Back to index

lightning-sunbird  0.9+nobinonly
nsFontMetricsXlib.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *   Peter Hartshorn <peter@igelaus.com.au>
00025  *   Quy Tonthat <quy@igelaus.com.au>
00026  *   Tony Tsui <tony@igelaus.com.au>
00027  *   Tim Copperfield <timecop@network.email.ne.jp>
00028  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
00029  *   Brian Stell <bstell@ix.netcom.com>
00030  *   Jungshik Shin <jshin@mailaps.org>
00031  *   IBM Corporation
00032  *
00033  * Alternatively, the contents of this file may be used under the terms of
00034  * either of the GNU General Public License Version 2 or later (the "GPL"),
00035  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00036  * in which case the provisions of the GPL or the LGPL are applicable instead
00037  * of those above. If you wish to allow use of your version of this file only
00038  * under the terms of either the GPL or the LGPL, and not to allow others to
00039  * use your version of this file under the terms of the MPL, indicate your
00040  * decision by deleting the provisions above and replace them with the notice
00041  * and other provisions required by the GPL or the LGPL. If you do not delete
00042  * the provisions above, a recipient may use your version of this file under
00043  * the terms of any one of the MPL, the GPL or the LGPL.
00044  *
00045  * ***** END LICENSE BLOCK ***** */
00046 
00047 #define ENABLE_X_FONT_BANNING 1
00048 
00049 #include <sys/types.h>
00050 #include "gfx-config.h"
00051 #include "nscore.h"
00052 #include "nsQuickSort.h"
00053 #include "nsFontMetricsXlib.h"
00054 #include "nsIServiceManager.h"
00055 #include "nsICharsetConverterManager.h"
00056 #include "nsILanguageAtomService.h"
00057 #include "nsISaveAsCharset.h"
00058 #include "nsIPref.h"
00059 #include "nsCOMPtr.h"
00060 #include "nsPrintfCString.h"
00061 #include "nspr.h"
00062 #include "nsHashtable.h"
00063 #include "nsReadableUtils.h"
00064 #include "nsAString.h"
00065 #include "nsXPIDLString.h"
00066 #ifdef MOZ_ENABLE_FREETYPE2
00067 #include "nsFT2FontCatalog.h"
00068 #include "nsFreeType.h"
00069 #endif /* MOZ_ENABLE_FREETYPE2 */
00070 #ifdef USE_X11SHARED_CODE
00071 #include "nsXFontNormal.h"
00072 #endif /* USE_X11SHARED_CODE */
00073 #ifdef USE_AASB
00074 #include "nsX11AlphaBlend.h"
00075 #include "nsXFontAAScaledBitmap.h"
00076 #endif /* USE_AASB */
00077 #ifdef USE_XPRINT
00078 #include "xprintutil.h"
00079 #endif /* USE_XPRINT */
00080 #include "xlibrgb.h"
00081 #include "nsUnicharUtils.h"
00082 #ifdef ENABLE_X_FONT_BANNING
00083 #include <regex.h>
00084 #endif /* ENABLE_X_FONT_BANNING */
00085 
00086 #include <X11/Xatom.h>
00087 
00088 #define UCS2_NOMAPPING 0XFFFD
00089 
00090 #ifdef PR_LOGGING 
00091 static PRLogModuleInfo *FontMetricsXlibLM = PR_NewLogModule("FontMetricsXlib");
00092 #endif /* PR_LOGGING */
00093 
00094 #ifdef ENABLE_X_FONT_BANNING
00095 /* Not all platforms may have REG_OK */
00096 #ifndef REG_OK
00097 #define REG_OK (0)
00098 #endif /* !REG_OK */
00099 #endif /* ENABLE_X_FONT_BANNING */
00100 
00101 #undef USER_DEFINED
00102 #define USER_DEFINED "x-user-def"
00103 
00104 // This is the scaling factor that we keep fonts limited to against
00105 // the display size.  If a pixel size is requested that is more than
00106 // this factor larger than the height of the display, it's clamped to
00107 // that value instead of the requested size.
00108 #define FONT_MAX_FONT_SCALE 2
00109 
00110 #undef NOISY_FONTS
00111 #undef REALLY_NOISY_FONTS
00112 
00113 /* Local prototypes */
00114 static PRBool                 FreeNode(nsHashKey* aKey, void* aData, void* aClosure);
00115 #ifdef MOZ_ENABLE_FREETYPE2
00116 static void                   CharSetNameToCodeRangeBits(const char*, PRUint32*, PRUint32*);
00117 #endif /* MOZ_ENABLE_FREETYPE2 */
00118 static const nsFontCharSetMapXlib *GetCharSetMap(nsFontMetricsXlibContext *aFmctx, const char *aCharSetName);
00119 
00120 // the font catalog is so expensive to generate
00121 // always tell the user what is happening
00122 static PRUint32 gFontDebug = 0 | NS_FONT_DEBUG_FONT_SCAN;
00123 
00124 struct nsFontCharSetMapXlib;
00125 struct nsFontFamilyNameXlib;
00126 struct nsFontPropertyNameXlib;
00127 struct nsFontStyleXlib;
00128 struct nsFontWeightXlib;
00129 struct nsFontLangGroupXlib;
00130 
00131 /* Container to hold per-device data (not per nsIDeviceContext data - one 
00132  * nsFontMetricsXlibContext instance may be used by multiple nsIDeviceContext
00133  * as long they map to the same physical device) for fontmetrics code
00134  */
00135 class nsFontMetricsXlibContext
00136 {
00137 public:
00138   nsFontMetricsXlibContext();
00139   nsresult Init(nsIDeviceContext *aDevice, PRBool printermode);
00140   ~nsFontMetricsXlibContext();
00141 
00142   XlibRgbHandle                        *mXlibRgbHandle;
00143 #ifdef USE_XPRINT
00144   /* Does this nsFont(Metrics)Xlib class operate on a Xprt (X11 print server) */
00145   PRPackedBool                          mPrinterMode;
00146 #endif /* USE_XPRINT */  
00147   PRPackedBool                          mAllowDoubleByteSpecialChars;
00148   PRPackedBool                          mForceOutlineScaledFonts;
00149 
00150   PRPackedBool                          mScaleBitmapFontsWithDevScale;
00151   float                                 mDevScale;
00152 
00153   nsCOMPtr<nsIPref>                     mPref;
00154 
00155   nsCOMPtr<nsICharsetConverterManager> mCharSetManager;
00156   nsCOMPtr<nsIUnicodeEncoder>           mUserDefinedConverter;
00157 
00158   nsHashtable                           mAliases;
00159   nsHashtable                           mCharSetMaps;
00160   nsHashtable                           mFamilies;
00161   nsHashtable                           mFFRENodes;
00162   nsHashtable                           mAFRENodes;
00163 
00164   // mCachedFFRESearches holds the "already looked up"
00165   // FFRE (Foundry Family Registry Encoding) font searches
00166   nsHashtable                           mCachedFFRESearches;
00167   nsHashtable                           mSpecialCharSets;
00168   nsHashtable                           mStretches;
00169   nsHashtable                           mWeights;
00170   nsCOMPtr<nsISaveAsCharset>            mFontSubConverter;
00171 
00172   PRBool                                mGlobalListInitalised;
00173   nsFontNodeArrayXlib                   mGlobalList;
00174 
00175   nsFontCharSetInfoXlib                *mUnknown,
00176                                        *mSpecial,
00177                                        *mISO106461;
00178   
00179   nsCOMPtr<nsIAtom>                     mUnicode;
00180   nsCOMPtr<nsIAtom>                     mUserDefined;
00181   nsCOMPtr<nsIAtom>                     mZHTW;
00182   nsCOMPtr<nsIAtom>                     mZHHK;
00183   nsCOMPtr<nsIAtom>                     mZHTWHK; // common to TW and HK
00184   nsCOMPtr<nsIAtom>                     mUsersLocale;
00185   nsCOMPtr<nsIAtom>                     mWesternLocale;
00186 
00187   const nsFontCharSetMapXlib           *mCharSetMap;
00188   const nsFontCharSetMapXlib           *mNoneCharSetMap;
00189   const nsFontCharSetMapXlib           *mSpecialCharSetMap;
00190 
00191   PRUint16                             *mUserDefinedCCMap;
00192   PRUint16                             *mEmptyCCMap;
00193   PRUint16                             *mDoubleByteSpecialCharsCCMap;
00194 
00195   // Controls for Outline Scaled Fonts (okay looking)
00196 
00197   PRInt32                               mOutlineScaleMinimum;
00198 #ifdef USE_AASB
00199 // Controls for Anti-Aliased Scaled Bitmaps (okay looking)
00200   PRBool                                mAABitmapScaleEnabled;
00201   PRBool                                mAABitmapScaleAlways;
00202   PRInt32                               mAABitmapScaleMinimum;
00203   double                                mAABitmapOversize;
00204   double                                mAABitmapUndersize;
00205 #endif /* USE_AASB */
00206 
00207 // Controls for (regular) Scaled Bitmaps (very ugly)
00208   PRInt32                               mBitmapScaleMinimum;
00209   double                                mBitmapOversize;
00210   double                                mBitmapUndersize;
00211 
00212 #ifdef USE_AASB
00213   PRInt32                               mAntiAliasMinimum;
00214 #endif /* USE_AASB */
00215   PRInt32                               mEmbeddedBitmapMaximumHeight;
00216 
00217 #ifdef MOZ_ENABLE_FREETYPE2
00218   PRBool                                mEnableFreeType2;
00219   PRBool                                mFreeType2Autohinted;
00220   PRBool                                mFreeType2Unhinted;
00221 #endif /* MOZ_ENABLE_FREETYPE2 */
00222 #ifdef USE_AASB
00223   PRUint8                               mAATTDarkTextMinValue;
00224   double                                mAATTDarkTextGain;
00225 #endif /* USE_AASB */
00226 
00227 #ifdef ENABLE_X_FONT_BANNING
00228   regex_t                              *mFontRejectRegEx,
00229                                        *mFontAcceptRegEx;
00230 #endif /* ENABLE_X_FONT_BANNING */
00231 };
00232 
00233 struct nsFontCharSetInfoXlib
00234 {
00235   const char*            mCharSet;
00236   nsFontCharSetConverterXlib Convert;
00237   PRUint8                mSpecialUnderline;
00238 #ifdef MOZ_ENABLE_FREETYPE2
00239   PRInt32                mCodeRange1Bits;
00240   PRInt32                mCodeRange2Bits;
00241 #endif
00242   PRUint16*              mCCMap;
00243   nsIUnicodeEncoder*     mConverter;
00244   nsIAtom*               mLangGroup;
00245   PRBool                 mInitedSizeInfo;
00246   PRInt32                mOutlineScaleMin;
00247   PRInt32                mBitmapScaleMin;
00248   double                 mBitmapOversize;
00249   double                 mBitmapUndersize;
00250 #ifdef USE_AASB  
00251   PRInt32                mAABitmapScaleMin;
00252   double                 mAABitmapOversize;
00253   double                 mAABitmapUndersize;
00254   PRBool                 mAABitmapScaleAlways;
00255 #endif /* USE_AASB */
00256 };
00257 
00258 struct nsFontFamilyXlib
00259 {
00260   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
00261 
00262   nsFontNodeArrayXlib mNodes;
00263 };
00264 
00265 struct nsFontFamilyNameXlib
00266 {
00267   const char* mName;
00268   const char* mXName;
00269 };
00270 
00271 struct nsFontPropertyNameXlib
00272 {
00273   const char* mName;
00274   int         mValue;
00275 };
00276 
00277 static void SetCharsetLangGroup(nsFontMetricsXlibContext *aFmctx, nsFontCharSetInfoXlib* aCharSetInfo);
00278 
00279 static int SingleByteConvert(nsFontCharSetInfoXlib* aSelf, XFontStruct* aFont,
00280   const PRUnichar* aSrcBuf, PRInt32 aSrcLen, char* aDestBuf, PRInt32 aDestLen);
00281 static int DoubleByteConvert(nsFontCharSetInfoXlib* aSelf, XFontStruct* aFont,
00282   const PRUnichar* aSrcBuf, PRInt32 aSrcLen, char* aDestBuf, PRInt32 aDestLen);
00283 static int ISO10646Convert(nsFontCharSetInfoXlib* aSelf, XFontStruct* aFont,
00284   const PRUnichar* aSrcBuf, PRInt32 aSrcLen, char* aDestBuf, PRInt32 aDestLen);
00285 
00286 static nsFontCharSetInfoXlib Unknown = { nsnull };
00287 static nsFontCharSetInfoXlib Special = { nsnull };
00288 
00289 #ifdef MOZ_ENABLE_FREETYPE2
00290 static nsFontCharSetInfoXlib USASCII =
00291   { "us-ascii", SingleByteConvert, 0,
00292     TT_OS2_CPR1_LATIN1 | TT_OS2_CPR1_MAC_ROMAN,
00293     TT_OS2_CPR2_CA_FRENCH |  TT_OS2_CPR2_PORTUGESE
00294     | TT_OS2_CPR2_WE_LATIN1 |  TT_OS2_CPR2_US };
00295 static nsFontCharSetInfoXlib ISO88591 =
00296   { "ISO-8859-1", SingleByteConvert, 0,
00297     TT_OS2_CPR1_LATIN1 | TT_OS2_CPR1_MAC_ROMAN,
00298     TT_OS2_CPR2_CA_FRENCH |  TT_OS2_CPR2_PORTUGESE
00299     | TT_OS2_CPR2_WE_LATIN1 |  TT_OS2_CPR2_US };
00300 static nsFontCharSetInfoXlib ISO88592 =
00301   { "ISO-8859-2", SingleByteConvert, 0,
00302     TT_OS2_CPR1_LATIN2, TT_OS2_CPR2_LATIN2 };
00303 static nsFontCharSetInfoXlib ISO88593 =
00304   { "ISO-8859-3", SingleByteConvert, 0,
00305     TT_OS2_CPR1_TURKISH, TT_OS2_CPR2_TURKISH };
00306 static nsFontCharSetInfoXlib ISO88594 =
00307   { "ISO-8859-4", SingleByteConvert, 0,
00308     TT_OS2_CPR1_BALTIC, TT_OS2_CPR2_BALTIC };
00309 static nsFontCharSetInfoXlib ISO88595 =
00310   { "ISO-8859-5", SingleByteConvert, 0,
00311     TT_OS2_CPR1_CYRILLIC, TT_OS2_CPR2_RUSSIAN | TT_OS2_CPR2_CYRILLIC };
00312 static nsFontCharSetInfoXlib ISO88596 =
00313   { "ISO-8859-6", SingleByteConvert, 0,
00314       TT_OS2_CPR1_ARABIC, TT_OS2_CPR2_ARABIC | TT_OS2_CPR2_ARABIC_708 };
00315 static nsFontCharSetInfoXlib ISO885968x =
00316   { "x-iso-8859-6-8-x", SingleByteConvert, 0,
00317       TT_OS2_CPR1_ARABIC, TT_OS2_CPR2_ARABIC | TT_OS2_CPR2_ARABIC_708 };
00318 static nsFontCharSetInfoXlib ISO8859616 =
00319   { "x-iso-8859-6-16", SingleByteConvert, 0,
00320       TT_OS2_CPR1_ARABIC, TT_OS2_CPR2_ARABIC | TT_OS2_CPR2_ARABIC_708 };
00321 static nsFontCharSetInfoXlib IBM1046 =
00322   { "x-IBM1046", SingleByteConvert, 0,
00323       TT_OS2_CPR1_ARABIC, TT_OS2_CPR2_ARABIC | TT_OS2_CPR2_ARABIC_708 };
00324 static nsFontCharSetInfoXlib ISO88597 =
00325   { "ISO-8859-7", SingleByteConvert, 0,
00326     TT_OS2_CPR1_GREEK, TT_OS2_CPR2_GREEK | TT_OS2_CPR2_GREEK_437G };
00327 static nsFontCharSetInfoXlib ISO88598 =
00328   { "ISO-8859-8", SingleByteConvert, 0,
00329     TT_OS2_CPR1_HEBREW, TT_OS2_CPR2_HEBREW };
00330 // change from  
00331 // { "ISO-8859-8", SingleByteConvertReverse, 0, 0, 0 };
00332 // untill we fix the layout and ensure we only call this with pure RTL text
00333 static nsFontCharSetInfoXlib ISO88599 =
00334   { "ISO-8859-9", SingleByteConvert, 0,
00335     TT_OS2_CPR1_TURKISH, TT_OS2_CPR2_TURKISH };
00336 // no support for iso-8859-10 (Nordic/Icelandic) currently
00337 // static nsFontCharSetInfoXlib ISO885910 =
00338 // { "ISO-8859-10", SingleByteConvert, 0,
00339 //   0, TT_OS2_CPR2_NORDIC | TT_OS2_CPR2_ICELANDIC };
00340 // no support for iso-8859-12 (Vietnamese) currently
00341 // static nsFontCharSetInfoXlib ISO885912 =
00342 // { "ISO-8859-12", SingleByteConvert, 0,
00343 //   TT_OS2_CPR1_VIETNAMESE, 0 };
00344 static nsFontCharSetInfoXlib ISO885913 =
00345   { "ISO-8859-13", SingleByteConvert, 0,
00346     TT_OS2_CPR1_BALTIC, TT_OS2_CPR2_BALTIC };
00347 static nsFontCharSetInfoXlib ISO885915 =
00348   { "ISO-8859-15", SingleByteConvert, 0,
00349     TT_OS2_CPR1_LATIN2, TT_OS2_CPR2_LATIN2 };
00350 static nsFontCharSetInfoXlib JISX0201 =
00351   { "jis_0201", SingleByteConvert, 1,
00352     TT_OS2_CPR1_JAPANESE, 0 };
00353 static nsFontCharSetInfoXlib KOI8R =
00354   { "KOI8-R", SingleByteConvert, 0,
00355     TT_OS2_CPR1_CYRILLIC, TT_OS2_CPR2_RUSSIAN | TT_OS2_CPR2_CYRILLIC };
00356 static nsFontCharSetInfoXlib KOI8U =
00357   { "KOI8-U", SingleByteConvert, 0,
00358     TT_OS2_CPR1_CYRILLIC, TT_OS2_CPR2_RUSSIAN | TT_OS2_CPR2_CYRILLIC };
00359 static nsFontCharSetInfoXlib TIS6202 =
00360 /* Added to support thai context sensitive shaping if
00361  * CTL extension is is in force */
00362 #ifdef SUNCTL
00363   { "tis620-2", SingleByteConvert, 0,
00364     TT_OS2_CPR1_THAI, 0 };
00365 #else
00366   { "windows-874", SingleByteConvert, 0,
00367     TT_OS2_CPR1_THAI, 0 };
00368 #endif /* SUNCTL */
00369 static nsFontCharSetInfoXlib TIS620 =
00370   { "TIS-620", SingleByteConvert, 0,
00371     TT_OS2_CPR1_THAI, 0 };
00372 static nsFontCharSetInfoXlib ISO885911 =
00373   { "ISO-8859-11", SingleByteConvert, 0,
00374     TT_OS2_CPR1_THAI, 0 };
00375 static nsFontCharSetInfoXlib Big5 =
00376   { "x-x-big5", DoubleByteConvert, 1,
00377     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00378 // a kludge to distinguish zh-TW only fonts in Big5 (such as hpbig5-)
00379 // from zh-TW/zh-HK common fonts in Big5 (such as big5-0, big5-1)
00380 static nsFontCharSetInfoXlib Big5TWHK =
00381   { "x-x-big5", DoubleByteConvert, 1,
00382     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00383 static nsFontCharSetInfoXlib CNS116431 =
00384   { "x-cns-11643-1", DoubleByteConvert, 1,
00385     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00386 static nsFontCharSetInfoXlib CNS116432 =
00387   { "x-cns-11643-2", DoubleByteConvert, 1,
00388     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00389 static nsFontCharSetInfoXlib CNS116433 =
00390   { "x-cns-11643-3", DoubleByteConvert, 1,
00391     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00392 static nsFontCharSetInfoXlib CNS116434 =
00393   { "x-cns-11643-4", DoubleByteConvert, 1,
00394     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00395 static nsFontCharSetInfoXlib CNS116435 =
00396   { "x-cns-11643-5", DoubleByteConvert, 1,
00397     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00398 static nsFontCharSetInfoXlib CNS116436 =
00399   { "x-cns-11643-6", DoubleByteConvert, 1,
00400     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00401 static nsFontCharSetInfoXlib CNS116437 =
00402   { "x-cns-11643-7", DoubleByteConvert, 1,
00403     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00404 static nsFontCharSetInfoXlib GB2312 =
00405   { "gb_2312-80", DoubleByteConvert, 1,
00406     TT_OS2_CPR1_CHINESE_SIMP, 0 };
00407 static nsFontCharSetInfoXlib GB18030_0 =
00408   { "gb18030.2000-0", DoubleByteConvert, 1,
00409     TT_OS2_CPR1_CHINESE_SIMP, 0 };
00410 static nsFontCharSetInfoXlib GB18030_1 =
00411   { "gb18030.2000-1", DoubleByteConvert, 1,
00412     TT_OS2_CPR1_CHINESE_SIMP, 0 };
00413 static nsFontCharSetInfoXlib GBK =
00414   { "x-gbk-noascii", DoubleByteConvert, 1,
00415     TT_OS2_CPR1_CHINESE_SIMP, 0 };
00416 static nsFontCharSetInfoXlib HKSCS =
00417   { "hkscs-1", DoubleByteConvert, 1,
00418     TT_OS2_CPR1_CHINESE_TRAD, 0 };
00419 static nsFontCharSetInfoXlib JISX0208 =
00420   { "jis_0208-1983", DoubleByteConvert, 1,
00421     TT_OS2_CPR1_JAPANESE, 0 };
00422 static nsFontCharSetInfoXlib JISX0212 =
00423   { "jis_0212-1990", DoubleByteConvert, 1,
00424     TT_OS2_CPR1_JAPANESE, 0 };
00425 static nsFontCharSetInfoXlib KSC5601 =
00426   { "ks_c_5601-1987", DoubleByteConvert, 1,
00427     TT_OS2_CPR1_KO_WANSUNG | TT_OS2_CPR1_KO_JOHAB, 0 };
00428 static nsFontCharSetInfoXlib X11Johab =
00429   { "x-x11johab", DoubleByteConvert, 1,
00430     TT_OS2_CPR1_KO_WANSUNG | TT_OS2_CPR1_KO_JOHAB, 0 };
00431 static nsFontCharSetInfoXlib JohabNoAscii =
00432   { "x-johab-noascii", DoubleByteConvert, 1,
00433     TT_OS2_CPR1_KO_WANSUNG | TT_OS2_CPR1_KO_JOHAB, 0 };
00434 static nsFontCharSetInfoXlib JamoTTF =
00435   { "x-koreanjamo-0", DoubleByteConvert, 1,
00436     TT_OS2_CPR1_KO_WANSUNG | TT_OS2_CPR1_KO_JOHAB, 0 };
00437 static nsFontCharSetInfoXlib TamilTTF =
00438   { "x-tamilttf-0", DoubleByteConvert, 1,
00439     0, 0 };
00440 static nsFontCharSetInfoXlib CP1250 =
00441   { "windows-1250", SingleByteConvert, 0,
00442     TT_OS2_CPR1_LATIN2, TT_OS2_CPR2_LATIN2 };
00443 static nsFontCharSetInfoXlib CP1251 =
00444   { "windows-1251", SingleByteConvert, 0,
00445     TT_OS2_CPR1_CYRILLIC, TT_OS2_CPR2_RUSSIAN };
00446 static nsFontCharSetInfoXlib CP1252 =
00447   { "windows-1252", SingleByteConvert, 0,
00448     TT_OS2_CPR1_LATIN1 | TT_OS2_CPR1_MAC_ROMAN,
00449     TT_OS2_CPR2_CA_FRENCH |  TT_OS2_CPR2_PORTUGESE
00450     | TT_OS2_CPR2_WE_LATIN1 |  TT_OS2_CPR2_US };
00451 static nsFontCharSetInfoXlib CP1253 =
00452   { "windows-1253", SingleByteConvert, 0,
00453     TT_OS2_CPR1_GREEK, TT_OS2_CPR2_GREEK | TT_OS2_CPR2_GREEK_437G };
00454 static nsFontCharSetInfoXlib CP1257 =
00455   { "windows-1257", SingleByteConvert, 0,
00456     TT_OS2_CPR1_BALTIC, TT_OS2_CPR2_BALTIC };
00457 
00458 #ifdef SUNCTL
00459 /* Hindi range currently unsupported in FT2 range. Change TT* once we 
00460    arrive at a way to identify hindi */
00461 static nsFontCharSetInfoXlib SunIndic =
00462   { "x-sun-unicode-india-0", DoubleByteConvert, 0,
00463     0, 0 };
00464 #endif /* SUNCTL */
00465 
00466 static nsFontCharSetInfoXlib ISO106461 =
00467   { nsnull, ISO10646Convert, 1, 0xFFFFFFFF, 0xFFFFFFFF };
00468 
00469 static nsFontCharSetInfoXlib AdobeSymbol =
00470    { "Adobe-Symbol-Encoding", SingleByteConvert, 0,
00471     TT_OS2_CPR1_SYMBOL, 0 };
00472 static nsFontCharSetInfoXlib AdobeEuro =
00473   { "x-adobe-euro", SingleByteConvert, 0,
00474     0, 0 };
00475 
00476 #ifdef MOZ_MATHML
00477 static nsFontCharSetInfoXlib CMCMEX =
00478    { "x-t1-cmex", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00479 static nsFontCharSetInfoXlib CMCMSY =
00480    { "x-t1-cmsy", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00481 static nsFontCharSetInfoXlib CMCMR =
00482    { "x-t1-cmr", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00483 static nsFontCharSetInfoXlib CMCMMI =
00484    { "x-t1-cmmi", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00485 static nsFontCharSetInfoXlib Mathematica1 =
00486    { "x-mathematica1", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00487 static nsFontCharSetInfoXlib Mathematica2 =
00488    { "x-mathematica2", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00489 static nsFontCharSetInfoXlib Mathematica3 =
00490    { "x-mathematica3", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00491 static nsFontCharSetInfoXlib Mathematica4 =
00492    { "x-mathematica4", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00493 static nsFontCharSetInfoXlib Mathematica5 =
00494    { "x-mathematica5", SingleByteConvert, 0, TT_OS2_CPR1_SYMBOL, 0};
00495 #endif /* MATHML */
00496 
00497 #else
00498 
00499 static nsFontCharSetInfoXlib USASCII =
00500   { "us-ascii", SingleByteConvert, 0 };
00501 static nsFontCharSetInfoXlib ISO88591 =
00502   { "ISO-8859-1", SingleByteConvert, 0 };
00503 static nsFontCharSetInfoXlib ISO88592 =
00504   { "ISO-8859-2", SingleByteConvert, 0 };
00505 static nsFontCharSetInfoXlib ISO88593 =
00506   { "ISO-8859-3", SingleByteConvert, 0 };
00507 static nsFontCharSetInfoXlib ISO88594 =
00508   { "ISO-8859-4", SingleByteConvert, 0 };
00509 static nsFontCharSetInfoXlib ISO88595 =
00510   { "ISO-8859-5", SingleByteConvert, 0 };
00511 static nsFontCharSetInfoXlib ISO88596 =
00512   { "ISO-8859-6", SingleByteConvert, 0 };
00513 static nsFontCharSetInfoXlib ISO885968x =
00514   { "x-iso-8859-6-8-x", SingleByteConvert, 0 };
00515 static nsFontCharSetInfoXlib ISO8859616 =
00516   { "x-iso-8859-6-16", SingleByteConvert, 0 };
00517 static nsFontCharSetInfoXlib IBM1046 =
00518   { "x-IBM1046", SingleByteConvert, 0 };
00519 static nsFontCharSetInfoXlib ISO88597 =
00520   { "ISO-8859-7", SingleByteConvert, 0 };
00521 static nsFontCharSetInfoXlib ISO88598 =
00522   { "ISO-8859-8", SingleByteConvert, 0 };
00523 // change from  
00524 // { "ISO-8859-8", SingleByteConvertReverse, 0, 0, 0 };
00525 // untill we fix the layout and ensure we only call this with pure RTL text
00526 static nsFontCharSetInfoXlib ISO88599 =
00527   { "ISO-8859-9", SingleByteConvert, 0 };
00528 // no support for iso-8859-10 (Nordic/Icelandic) currently
00529 // static nsFontCharSetInfoXlib ISO885910 =
00530 // { "ISO-8859-10", SingleByteConvert, 0,
00531 //   0, TT_OS2_CPR2_NORDIC | TT_OS2_CPR2_ICELANDIC };
00532 // no support for iso-8859-12 (Vietnamese) currently
00533 // static nsFontCharSetInfoXlib ISO885912 =
00534 // { "ISO-8859-12", SingleByteConvert, 0,
00535 //   TT_OS2_CPR1_VIETNAMESE, 0 };
00536 static nsFontCharSetInfoXlib ISO885913 =
00537   { "ISO-8859-13", SingleByteConvert, 0 };
00538 static nsFontCharSetInfoXlib ISO885915 =
00539   { "ISO-8859-15", SingleByteConvert, 0 };
00540 static nsFontCharSetInfoXlib JISX0201 =
00541   { "jis_0201", SingleByteConvert, 1 };
00542 static nsFontCharSetInfoXlib KOI8R =
00543   { "KOI8-R", SingleByteConvert, 0 };
00544 static nsFontCharSetInfoXlib KOI8U =
00545   { "KOI8-U", SingleByteConvert, 0 };
00546 static nsFontCharSetInfoXlib TIS6202 =
00547 /* Added to support thai context sensitive shaping if
00548  * CTL extension is is in force */
00549 #ifdef SUNCTL
00550   { "tis620-2", SingleByteConvert, 0 };
00551 #else
00552   { "windows-874", SingleByteConvert, 0 };
00553 #endif /* SUNCTL */
00554 static nsFontCharSetInfoXlib TIS620 =
00555   { "TIS-620", SingleByteConvert, 0 };
00556 static nsFontCharSetInfoXlib ISO885911 =
00557   { "ISO-8859-11", SingleByteConvert, 0 };
00558 static nsFontCharSetInfoXlib Big5 =
00559   { "x-x-big5", DoubleByteConvert, 1 };
00560 // a kludge to distinguish zh-TW only fonts in Big5 (such as hpbig5-)
00561 // from zh-TW/zh-HK common fonts in Big5 (such as big5-1)
00562 static nsFontCharSetInfoXlib Big5TWHK =
00563   { "x-x-big5", DoubleByteConvert, 1 };
00564 static nsFontCharSetInfoXlib CNS116431 =
00565   { "x-cns-11643-1", DoubleByteConvert, 1 };
00566 static nsFontCharSetInfoXlib CNS116432 =
00567   { "x-cns-11643-2", DoubleByteConvert, 1 };
00568 static nsFontCharSetInfoXlib CNS116433 =
00569   { "x-cns-11643-3", DoubleByteConvert, 1 };
00570 static nsFontCharSetInfoXlib CNS116434 =
00571   { "x-cns-11643-4", DoubleByteConvert, 1 };
00572 static nsFontCharSetInfoXlib CNS116435 =
00573   { "x-cns-11643-5", DoubleByteConvert, 1 };
00574 static nsFontCharSetInfoXlib CNS116436 =
00575   { "x-cns-11643-6", DoubleByteConvert, 1 };
00576 static nsFontCharSetInfoXlib CNS116437 =
00577   { "x-cns-11643-7", DoubleByteConvert, 1 };
00578 static nsFontCharSetInfoXlib GB2312 =
00579   { "gb_2312-80", DoubleByteConvert, 1 };
00580 static nsFontCharSetInfoXlib GB18030_0 =
00581   { "gb18030.2000-0", DoubleByteConvert, 1 };
00582 static nsFontCharSetInfoXlib GB18030_1 =
00583   { "gb18030.2000-1", DoubleByteConvert, 1 };
00584 static nsFontCharSetInfoXlib GBK =
00585   { "x-gbk-noascii", DoubleByteConvert, 1 };
00586 static nsFontCharSetInfoXlib HKSCS =
00587   { "hkscs-1", DoubleByteConvert, 1 };
00588 static nsFontCharSetInfoXlib JISX0208 =
00589   { "jis_0208-1983", DoubleByteConvert, 1 };
00590 static nsFontCharSetInfoXlib JISX0212 =
00591   { "jis_0212-1990", DoubleByteConvert, 1 };
00592 static nsFontCharSetInfoXlib KSC5601 =
00593   { "ks_c_5601-1987", DoubleByteConvert, 1 };
00594 static nsFontCharSetInfoXlib X11Johab =
00595   { "x-x11johab", DoubleByteConvert, 1 };
00596 static nsFontCharSetInfoXlib JohabNoAscii =
00597   { "x-johab-noascii", DoubleByteConvert, 1 };
00598 static nsFontCharSetInfoXlib JamoTTF =
00599   { "x-koreanjamo-0", DoubleByteConvert, 1 };
00600 static nsFontCharSetInfoXlib TamilTTF =
00601   { "x-tamilttf-0", DoubleByteConvert, 0 };
00602 static nsFontCharSetInfoXlib CP1250 =
00603   { "windows-1250", SingleByteConvert, 0 };
00604 static nsFontCharSetInfoXlib CP1251 =
00605   { "windows-1251", SingleByteConvert, 0 };
00606 static nsFontCharSetInfoXlib CP1252 =
00607   { "windows-1252", SingleByteConvert, 0 };
00608 static nsFontCharSetInfoXlib CP1253 =
00609   { "windows-1253", SingleByteConvert, 0 };
00610 static nsFontCharSetInfoXlib CP1257 =
00611   { "windows-1257", SingleByteConvert, 0 };
00612 
00613 #ifdef SUNCTL
00614 /* Hindi range currently unsupported in FT2 range. Change TT* once we 
00615    arrive at a way to identify hindi */
00616 static nsFontCharSetInfoXlib SunIndic =
00617   { "x-sun-unicode-india-0", DoubleByteConvert, 0 };
00618 #endif /* SUNCTL */
00619 
00620 static nsFontCharSetInfoXlib ISO106461 =
00621   { nsnull, ISO10646Convert, 1};
00622 
00623 static nsFontCharSetInfoXlib AdobeSymbol =
00624    { "Adobe-Symbol-Encoding", SingleByteConvert, 0 };
00625 static nsFontCharSetInfoXlib AdobeEuro =
00626   { "x-adobe-euro", SingleByteConvert, 0 };
00627          
00628 #ifdef MOZ_MATHML
00629 static nsFontCharSetInfoXlib CMCMEX =
00630    { "x-t1-cmex", SingleByteConvert, 0};
00631 static nsFontCharSetInfoXlib CMCMSY =
00632    { "x-t1-cmsy", SingleByteConvert, 0};
00633 static nsFontCharSetInfoXlib CMCMR =
00634    { "x-t1-cmr", SingleByteConvert, 0};
00635 static nsFontCharSetInfoXlib CMCMMI =
00636    { "x-t1-cmmi", SingleByteConvert, 0};
00637 static nsFontCharSetInfoXlib Mathematica1 =
00638    { "x-mathematica1", SingleByteConvert, 0};
00639 static nsFontCharSetInfoXlib Mathematica2 =
00640    { "x-mathematica2", SingleByteConvert, 0}; 
00641 static nsFontCharSetInfoXlib Mathematica3 =
00642    { "x-mathematica3", SingleByteConvert, 0};
00643 static nsFontCharSetInfoXlib Mathematica4 =
00644    { "x-mathematica4", SingleByteConvert, 0}; 
00645 static nsFontCharSetInfoXlib Mathematica5 =
00646    { "x-mathematica5", SingleByteConvert, 0};
00647 #endif /* MATHML */
00648 #endif /* FREETYPE2 */
00649 
00650 static nsFontLangGroupXlib FLG_WESTERN = { "x-western",     nsnull };
00651 static nsFontLangGroupXlib FLG_BALTIC  = { "x-baltic",      nsnull };
00652 static nsFontLangGroupXlib FLG_CE      = { "x-central-euro",nsnull };
00653 static nsFontLangGroupXlib FLG_RUSSIAN = { "x-cyrillic",    nsnull };
00654 static nsFontLangGroupXlib FLG_GREEK   = { "el",            nsnull };
00655 static nsFontLangGroupXlib FLG_TURKISH = { "tr",            nsnull };
00656 static nsFontLangGroupXlib FLG_HEBREW  = { "he",            nsnull };
00657 static nsFontLangGroupXlib FLG_ARABIC  = { "ar",            nsnull };
00658 static nsFontLangGroupXlib FLG_THAI    = { "th",            nsnull };
00659 static nsFontLangGroupXlib FLG_ZHCN    = { "zh-CN",         nsnull };
00660 static nsFontLangGroupXlib FLG_ZHTW    = { "zh-TW",         nsnull };
00661 static nsFontLangGroupXlib FLG_ZHHK    = { "zh-HK",         nsnull };
00662 static nsFontLangGroupXlib FLG_ZHTWHK  = { "x-zh-TWHK",     nsnull };
00663 static nsFontLangGroupXlib FLG_JA      = { "ja",            nsnull };
00664 static nsFontLangGroupXlib FLG_KO      = { "ko",            nsnull };
00665 #ifdef SUNCTL
00666 static nsFontLangGroupXlib FLG_INDIC   = { "x-devanagari",  nsnull };
00667 #endif
00668 static nsFontLangGroupXlib FLG_TAMIL   = { "x-tamil",       nsnull };
00669 static nsFontLangGroupXlib FLG_NONE    = { nsnull,          nsnull };
00670 
00671 /*
00672  * Normally, the charset of an X font can be determined simply by looking at
00673  * the last 2 fields of the long XLFD font name (CHARSET_REGISTRY and
00674  * CHARSET_ENCODING). However, there are a number of special cases:
00675  *
00676  * Sometimes, X server vendors use the same name to mean different things. For
00677  * example, IRIX uses "cns11643-1" to mean the 2nd plane of CNS 11643, while
00678  * Solaris uses that name for the 1st plane.
00679  *
00680  * Some X server vendors use certain names for something completely different.
00681  * For example, some Solaris fonts say "gb2312.1980-0" but are actually ASCII
00682  * fonts. These cases can be detected by looking at the POINT_SIZE and
00683  * AVERAGE_WIDTH fields. If the average width is half the point size, this is
00684  * an ASCII font, not GB 2312.
00685  *
00686  * Some fonts say "fontspecific" in the CHARSET_ENCODING field. Their charsets
00687  * depend on the FAMILY_NAME. For example, the following is a "Symbol" font:
00688  *
00689  *   -adobe-symbol-medium-r-normal--17-120-100-100-p-95-adobe-fontspecific
00690  *
00691  * Some vendors use one name to mean 2 different things, depending on the font.
00692  * For example, AIX has some "ksc5601.1987-0" fonts that require the 8th bit of
00693  * both bytes to be zero, while other fonts require them to be set to one.
00694  * These cases can be distinguished by looking at the FOUNDRY field, but a
00695  * better way is to look at XFontStruct.min_byte1.
00696  */
00697 static const nsFontCharSetMapXlib gConstCharSetMap[] =
00698 {
00699   { "-ascii",             &FLG_NONE,    &Unknown       },
00700   { "-ibm pc",            &FLG_NONE,    &Unknown       },
00701   { "adobe-fontspecific", &FLG_NONE,    &Special       },
00702   { "ansi-1251",          &FLG_RUSSIAN, &CP1251        },
00703   // On Solaris, big5-0 is used for ASCII-only fonts while in XFree86, 
00704   // it's for Big5 fonts without US-ASCII. When a non-Solaris binary
00705   // is displayed on a Solaris X server, this would break.
00706 #ifndef SOLARIS
00707   { "big5-0",             &FLG_ZHTWHK,  &Big5TWHK      }, // common to TW/HK
00708 #else 
00709   { "big5-0",             &FLG_ZHTW,    &USASCII       }, 
00710 #endif
00711   { "big5-1",             &FLG_ZHTWHK,  &Big5TWHK      }, // ditto
00712   { "big5.et-0",          &FLG_ZHTW,    &Big5          },
00713   { "big5.et.ext-0",      &FLG_ZHTW,    &Big5          },
00714   { "big5.etext-0",       &FLG_ZHTW,    &Big5          },
00715   { "big5.hku-0",         &FLG_ZHTW,    &Big5          },
00716   { "big5.hku-1",         &FLG_ZHTW,    &Big5          },
00717   { "big5.pc-0",          &FLG_ZHTW,    &Big5          },
00718   { "big5.shift-0",       &FLG_ZHTW,    &Big5          },
00719   { "big5hkscs-0",        &FLG_ZHHK,    &HKSCS         },
00720   { "cns11643.1986-1",    &FLG_ZHTW,    &CNS116431     },
00721   { "cns11643.1986-2",    &FLG_ZHTW,    &CNS116432     },
00722   { "cns11643.1992-1",    &FLG_ZHTW,    &CNS116431     },
00723   { "cns11643.1992.1-0",  &FLG_ZHTW,    &CNS116431     },
00724   { "cns11643.1992-12",   &FLG_NONE,    &Unknown       },
00725   { "cns11643.1992.2-0",  &FLG_ZHTW,    &CNS116432     },
00726   { "cns11643.1992-2",    &FLG_ZHTW,    &CNS116432     },
00727   { "cns11643.1992-3",    &FLG_ZHTW,    &CNS116433     },
00728   { "cns11643.1992.3-0",  &FLG_ZHTW,    &CNS116433     },
00729   { "cns11643.1992.4-0",  &FLG_ZHTW,    &CNS116434     },
00730   { "cns11643.1992-4",    &FLG_ZHTW,    &CNS116434     },
00731   { "cns11643.1992.5-0",  &FLG_ZHTW,    &CNS116435     },
00732   { "cns11643.1992-5",    &FLG_ZHTW,    &CNS116435     },
00733   { "cns11643.1992.6-0",  &FLG_ZHTW,    &CNS116436     },
00734   { "cns11643.1992-6",    &FLG_ZHTW,    &CNS116436     },
00735   { "cns11643.1992.7-0",  &FLG_ZHTW,    &CNS116437     },
00736   { "cns11643.1992-7",    &FLG_ZHTW,    &CNS116437     },
00737   { "cns11643-1",         &FLG_ZHTW,    &CNS116431     },
00738   { "cns11643-2",         &FLG_ZHTW,    &CNS116432     },
00739   { "cns11643-3",         &FLG_ZHTW,    &CNS116433     },
00740   { "cns11643-4",         &FLG_ZHTW,    &CNS116434     },
00741   { "cns11643-5",         &FLG_ZHTW,    &CNS116435     },
00742   { "cns11643-6",         &FLG_ZHTW,    &CNS116436     },
00743   { "cns11643-7",         &FLG_ZHTW,    &CNS116437     },
00744   { "cp1251-1",           &FLG_RUSSIAN, &CP1251        },
00745   { "dec-dectech",        &FLG_NONE,    &Unknown       },
00746   { "dtsymbol-1",         &FLG_NONE,    &Unknown       },
00747   { "fontspecific-0",     &FLG_NONE,    &Unknown       },
00748   { "gb2312.1980-0",      &FLG_ZHCN,    &GB2312        },
00749   { "gb2312.1980-1",      &FLG_ZHCN,    &GB2312        },
00750   { "gb13000.1993-1",     &FLG_ZHCN,    &GBK           },
00751   { "gb18030.2000-0",     &FLG_ZHCN,    &GB18030_0     },
00752   { "gb18030.2000-1",     &FLG_ZHCN,    &GB18030_1     },
00753   { "gbk-0",              &FLG_ZHCN,    &GBK           },
00754   { "gbk1988.1989-0",     &FLG_ZHCN,    &USASCII       },
00755   { "hkscs-1",            &FLG_ZHHK,    &HKSCS         },
00756   { "hp-japanese15",      &FLG_NONE,    &Unknown       },
00757   { "hp-japaneseeuc",     &FLG_NONE,    &Unknown       },
00758   { "hp-roman8",          &FLG_NONE,    &Unknown       },
00759   { "hp-schinese15",      &FLG_NONE,    &Unknown       },
00760   { "hp-tchinese15",      &FLG_NONE,    &Unknown       },
00761   { "hp-tchinesebig5",    &FLG_ZHTW,    &Big5          },
00762   { "hp-wa",              &FLG_NONE,    &Unknown       },
00763   { "hpbig5-",            &FLG_ZHTW,    &Big5          },
00764   { "hphkbig5-",          &FLG_ZHHK,    &HKSCS         },
00765   { "hproc16-",           &FLG_NONE,    &Unknown       },
00766   { "ibm-1046",           &FLG_ARABIC,  &IBM1046       },
00767   { "ibm-1252",           &FLG_NONE,    &Unknown       },
00768   { "ibm-850",            &FLG_NONE,    &Unknown       },
00769   { "ibm-fontspecific",   &FLG_NONE,    &Unknown       },
00770   { "ibm-sbdcn",          &FLG_NONE,    &Unknown       },
00771   { "ibm-sbdtw",          &FLG_NONE,    &Unknown       },
00772   { "ibm-special",        &FLG_NONE,    &Unknown       },
00773   { "ibm-udccn",          &FLG_NONE,    &Unknown       },
00774   { "ibm-udcjp",          &FLG_NONE,    &Unknown       },
00775   { "ibm-udctw",          &FLG_NONE,    &Unknown       },
00776   { "iso646.1991-irv",    &FLG_NONE,    &Unknown       },
00777   { "iso8859-1",          &FLG_WESTERN, &ISO88591      },
00778   { "iso8859-13",         &FLG_BALTIC,  &ISO885913     },
00779   { "iso8859-15",         &FLG_WESTERN, &ISO885915     },
00780   { "iso8859-1@cn",       &FLG_NONE,    &Unknown       },
00781   { "iso8859-1@kr",       &FLG_NONE,    &Unknown       },
00782   { "iso8859-1@tw",       &FLG_NONE,    &Unknown       },
00783   { "iso8859-1@zh",       &FLG_NONE,    &Unknown       },
00784   { "iso8859-2",          &FLG_CE,      &ISO88592      },
00785   { "iso8859-3",          &FLG_WESTERN, &ISO88593      },
00786   { "iso8859-4",          &FLG_BALTIC,  &ISO88594      },
00787   { "iso8859-5",          &FLG_RUSSIAN, &ISO88595      },
00788   { "iso8859-6",          &FLG_ARABIC,  &ISO88596      },
00789   { "iso8859-6.8x",       &FLG_ARABIC,  &ISO885968x    },
00790   { "iso8859-6.16",       &FLG_ARABIC,  &ISO8859616    },
00791   { "iso8859-7",          &FLG_GREEK,   &ISO88597      },
00792   { "iso8859-8",          &FLG_HEBREW,  &ISO88598      },
00793   { "iso8859-9",          &FLG_TURKISH, &ISO88599      },
00794   { "iso10646-1",         &FLG_NONE,    &ISO106461     },
00795   { "jisx0201.1976-0",    &FLG_JA,      &JISX0201      },
00796   { "jisx0201.1976-1",    &FLG_JA,      &JISX0201      },
00797   { "jisx0208.1983-0",    &FLG_JA,      &JISX0208      },
00798   { "jisx0208.1990-0",    &FLG_JA,      &JISX0208      },
00799   { "jisx0212.1990-0",    &FLG_JA,      &JISX0212      },
00800   { "koi8-r",             &FLG_RUSSIAN, &KOI8R         },
00801   { "koi8-u",             &FLG_RUSSIAN, &KOI8U         },
00802   { "johab-1",            &FLG_KO,      &X11Johab      },
00803   { "johabs-1",           &FLG_KO,      &X11Johab      },
00804   { "johabsh-1",          &FLG_KO,      &X11Johab      },
00805   { "ksc5601.1987-0",     &FLG_KO,      &KSC5601       },
00806   // We can handle GR fonts with GL encoders (KSC5601 and GB2312)
00807   // See |DoubleByteConvert|
00808   { "ksc5601.1987-1",     &FLG_KO,      &KSC5601       },
00809   { "ksc5601.1992-3",     &FLG_KO,      &JohabNoAscii  },
00810   { "koreanjamo-0",       &FLG_KO,      &JamoTTF       },
00811   { "microsoft-cp1250",   &FLG_CE,      &CP1250        },
00812   { "microsoft-cp1251",   &FLG_RUSSIAN, &CP1251        },
00813   { "microsoft-cp1252",   &FLG_WESTERN, &CP1252        },
00814   { "microsoft-cp1253",   &FLG_GREEK,   &CP1253        },
00815   { "microsoft-cp1257",   &FLG_BALTIC,  &CP1257        },
00816   { "misc-fontspecific",  &FLG_NONE,    &Unknown       },
00817   { "sgi-fontspecific",   &FLG_NONE,    &Unknown       },
00818   { "sun-fontspecific",   &FLG_NONE,    &Unknown       },
00819   { "sunolcursor-1",      &FLG_NONE,    &Unknown       },
00820   { "sunolglyph-1",       &FLG_NONE,    &Unknown       },
00821   { "symbol-fontspecific",&FLG_NONE,    &Special       },
00822   { "tis620.2529-1",      &FLG_THAI,    &TIS620        },
00823   { "tis620.2533-0",      &FLG_THAI,    &TIS620        },
00824   { "tis620.2533-1",      &FLG_THAI,    &TIS620        },
00825   { "tis620-0",           &FLG_THAI,    &TIS620        },
00826   { "tis620-2",           &FLG_THAI,    &TIS6202       },
00827   { "iso8859-11",         &FLG_THAI,    &ISO885911     },
00828   { "ucs2.cjk-0",         &FLG_NONE,    &ISO106461     },
00829   { "ucs2.cjk_china-0",   &FLG_ZHCN,    &ISO106461     },
00830   { "iso10646.2000-cn",   &FLG_ZHCN,    &ISO106461     },  // HP/UX
00831   { "ucs2.cjk_japan-0",   &FLG_JA,      &ISO106461     },
00832   { "ucs2.cjk_korea-0",   &FLG_KO,      &ISO106461     },
00833   { "korean.ucs2-0",      &FLG_KO,      &ISO106461     },  // HP/UX
00834   { "ucs2.cjk_taiwan-0",  &FLG_ZHTW,    &ISO106461     },
00835   { "ucs2.thai-0",        &FLG_THAI,    &ISO106461     },
00836   { "tamilttf-0",         &FLG_TAMIL,   &TamilTTF      },
00837 #ifdef SUNCTL
00838   { "sun.unicode.india-0",&FLG_INDIC,   &SunIndic      },
00839 #endif /* SUNCTL */
00840 
00841   { nsnull,               nsnull,       nsnull         }
00842 };
00843 
00844 static const nsFontFamilyNameXlib gFamilyNameTable[] =
00845 {
00846   { "arial",           "helvetica" },
00847   { "courier new",     "courier" },
00848   { "times new roman", "times" },
00849 
00850 #ifdef MOZ_MATHML
00851   { "cmex",             "cmex10" },
00852   { "cmsy",             "cmsy10" },
00853   { "-moz-math-text",   "times" },
00854   { "-moz-math-symbol", "symbol" },
00855 #endif /* MOZ_MATHML */
00856 
00857   { nsnull, nsnull }
00858 };
00859 
00860 static const nsFontCharSetMapXlib gConstNoneCharSetMap[] = { { nsnull }, };
00861 
00862 static const nsFontCharSetMapXlib gConstSpecialCharSetMap[] =
00863 {
00864   { "symbol-adobe-fontspecific", &FLG_NONE, &AdobeSymbol  },
00865   { "euromono-adobe-fontspecific",  &FLG_NONE, &AdobeEuro },
00866   { "eurosans-adobe-fontspecific",  &FLG_NONE, &AdobeEuro },
00867   { "euroserif-adobe-fontspecific", &FLG_NONE, &AdobeEuro },
00868 
00869 #ifdef MOZ_MATHML
00870   { "cmex10-adobe-fontspecific", &FLG_NONE, &CMCMEX  },
00871   { "cmsy10-adobe-fontspecific", &FLG_NONE, &CMCMSY  },
00872   { "cmr10-adobe-fontspecific",  &FLG_NONE, &CMCMR  },
00873   { "cmmi10-adobe-fontspecific", &FLG_NONE, &CMCMMI  },
00874 
00875   { "math1-adobe-fontspecific", &FLG_NONE, &Mathematica1 },
00876   { "math2-adobe-fontspecific", &FLG_NONE, &Mathematica2 },
00877   { "math3-adobe-fontspecific", &FLG_NONE, &Mathematica3 },
00878   { "math4-adobe-fontspecific", &FLG_NONE, &Mathematica4 },
00879   { "math5-adobe-fontspecific", &FLG_NONE, &Mathematica5 },
00880  
00881   { "math1mono-adobe-fontspecific", &FLG_NONE, &Mathematica1 },
00882   { "math2mono-adobe-fontspecific", &FLG_NONE, &Mathematica2 },
00883   { "math3mono-adobe-fontspecific", &FLG_NONE, &Mathematica3 },
00884   { "math4mono-adobe-fontspecific", &FLG_NONE, &Mathematica4 },
00885   { "math5mono-adobe-fontspecific", &FLG_NONE, &Mathematica5 },
00886 #endif /* MOZ_MATHML */
00887 
00888   { nsnull,                      nsnull        }
00889 };
00890 
00891 static const nsFontPropertyNameXlib gStretchNames[] =
00892 {
00893   { "block",         5 }, // XXX
00894   { "bold",          7 }, // XXX
00895   { "double wide",   9 },
00896   { "medium",        5 },
00897   { "narrow",        3 },
00898   { "normal",        5 },
00899   { "semicondensed", 4 },
00900   { "wide",          7 },
00901 
00902   { nsnull,          0 }
00903 };
00904 
00905 static const nsFontPropertyNameXlib gWeightNames[] =
00906 {
00907   { "black",    900 },
00908   { "bold",     700 },
00909   { "book",     400 },
00910   { "demi",     600 },
00911   { "demibold", 600 },
00912   { "light",    300 },
00913   { "medium",   400 },
00914   { "regular",  400 },
00915   
00916   { nsnull,     0 }
00917 };
00918 
00919 #ifdef DEBUG_copyfontcharsetmap
00920 void DumpFontCharSetMap(const nsFontCharSetMapXlib *fcsm)
00921 {
00922   printf("fcsm = %lx\n", fcsm);
00923   printf("{\n");
00924 
00925   for( ; fcsm->mName ; fcsm++ )
00926   {
00927 #define STRNULL(s) ((s)?(s):("nsnull"))
00928     printf("  { mName='%s', \tmFontLangGroup=%lx {mFontLangGroupName='%s'}, \tmInfo=%lx {mCharSet='%s'}}\n",
00929            STRNULL(fcsm->mName),
00930            fcsm->mFontLangGroup,
00931            STRNULL(fcsm->mFontLangGroup->mFontLangGroupName),
00932            fcsm->mInfo,
00933            STRNULL(fcsm->mInfo->mCharSet)); 
00934 #undef STRNULL
00935   }
00936   printf("}\n");
00937 }
00938 #endif /* DEBUG_copyfontcharsetmap */
00939 
00940 /* Copy nsFontCharSetMapXlib structures to the appropriate members of
00941  * |aFmctx|:
00942  * |gConstCharSetMap|        --> |aFmctx->mCharSetMap|
00943  * |gConstNoneCharSetMap|    --> |aFmctx->mNoneCharSetMap|
00944  * |gConstSpecialCharSetMap| --> |aFmctx->mSpecialCharSetMap|
00945  * When copying, we ensure that structures with identical content 
00946  * have identical pointers (since fontmetrics code uses such pointers
00947  * for |equal|, |not equal| comparisons etc.).
00948  */
00949 static
00950 PRBool CopyFontCharSetMapXlib(nsFontMetricsXlibContext *aFmctx)
00951 {
00952   long                        size1[3],
00953                               size2[3],
00954                               size3[3];
00955   int                         i,
00956                               j,
00957                               k,
00958                               l,
00959                               count[3];
00960   char                       *s;
00961   const nsFontCharSetMapXlib *fcsm[3];
00962   nsFontCharSetMapXlib       *copy[3];
00963   nsFontLangGroupXlib        *langgroup;
00964   nsFontCharSetInfoXlib      *charsetinfo;
00965 
00966   fcsm[0] = gConstCharSetMap;
00967   fcsm[1] = gConstNoneCharSetMap;
00968   fcsm[2] = gConstSpecialCharSetMap; 
00969   
00970   size1[0] = size2[0] = size3[0] = 0;
00971   size1[1] = size2[1] = size3[1] = 0;
00972   size1[2] = size2[2] = size3[2] = 0;
00973 
00974 /* Alignment macros to force memory alignment required by most RISC platforms
00975  * MAX_ALIGN_BYTES = sizeof(pointer) incl. the doubleword alignment required
00976  * by some platforms, ALIGN_PTR() aligns the given pointer to match
00977  * MAX_ALIGN_BYTES alignment
00978  * XXX: NSPR should define that...
00979  */
00980 #define MAX_ALIGN_BYTES (sizeof(void *) * 2)
00981 #define ALIGN_PTR(ptr) ((void *)(((PRUptrdiff)(ptr) & ~(MAX_ALIGN_BYTES-1L)) + MAX_ALIGN_BYTES))
00982 
00983   for( l = 0 ; l < 3 ; l++ )
00984   {  
00985     /* Count entries in fcsm */
00986     for( count[l]=0 ; fcsm[l][count[l]].mName ; count[l]++ ) ;
00987 
00988     count[l]++;
00989     size1[l] = sizeof(nsFontCharSetMapXlib)   * count[l] + MAX_ALIGN_BYTES;
00990     size2[l] = sizeof(nsFontLangGroupXlib)    * count[l] + MAX_ALIGN_BYTES;
00991     size3[l] = sizeof(nsFontCharSetInfoXlib)  * count[l] + MAX_ALIGN_BYTES;
00992     count[l]--;
00993   }
00994   
00995   s = (char *)calloc(1, size1[0]+size2[0]+size3[0]+
00996                         size1[1]+size2[1]+size3[1]+
00997                         size1[2]+size2[2]+size3[2]);
00998   if (!s)
00999     return PR_FALSE;
01000 
01001   /* Note that the pointer in |copy[0]| is stored in |mCharSetMap| later which
01002    * is finally passed to |free()| when the nsFontMetricsXlibContext destructor
01003    * is called. */
01004   copy[0]     = (nsFontCharSetMapXlib *)s;             s += size1[0];
01005   copy[1]     = (nsFontCharSetMapXlib *)ALIGN_PTR(s);  s += size1[1];
01006   copy[2]     = (nsFontCharSetMapXlib *)ALIGN_PTR(s);  s += size1[2];
01007   langgroup   = (nsFontLangGroupXlib  *)ALIGN_PTR(s);  s += size2[0] + size2[1] + size2[2];
01008   charsetinfo = (nsFontCharSetInfoXlib *)ALIGN_PTR(s);
01009 
01010   for( l = 0 ; l < 3 ; l++ )
01011   { 
01012     for( i = 0 ; i < count[l] ; i++ )
01013     {
01014       copy[l][i].mName = fcsm[l][i].mName;
01015 
01016       if (!copy[l][i].mFontLangGroup)
01017       {
01018         nsFontLangGroupXlib *slot = langgroup++;
01019         *slot = *fcsm[l][i].mFontLangGroup;
01020         copy[l][i].mFontLangGroup = slot;
01021 
01022         for( k = 0 ; k < 3 ; k++ )
01023         {
01024           for( j = 0 ; j < count[k] ; j++ )
01025           {
01026             if ((!copy[k][j].mFontLangGroup) && 
01027                 (fcsm[k][j].mFontLangGroup == fcsm[l][i].mFontLangGroup))
01028             {
01029               copy[k][j].mFontLangGroup = slot;
01030             }
01031           }
01032         }
01033       }
01034 
01035       if (!copy[l][i].mInfo)
01036       {
01037         nsFontCharSetInfoXlib *slot = charsetinfo++;
01038 
01039         if (fcsm[l][i].mInfo == &Unknown)
01040         {
01041           aFmctx->mUnknown = slot;
01042         }
01043         else if (fcsm[l][i].mInfo == &Special)
01044         {
01045           aFmctx->mSpecial = slot;
01046         }
01047         else if (fcsm[l][i].mInfo == &ISO106461)
01048         {
01049           aFmctx->mISO106461 = slot;
01050         }
01051 
01052         *slot = *fcsm[l][i].mInfo;
01053 
01054         copy[l][i].mInfo = slot;
01055 
01056         for( k = 0 ; k < 3 ; k++ )
01057         {
01058           for( j = 0 ; j < count[k] ; j++ )
01059           {
01060             if ((!copy[k][j].mInfo) && 
01061                 (fcsm[k][j].mInfo == fcsm[l][i].mInfo))
01062             {
01063               copy[k][j].mInfo = slot;
01064             }
01065           }
01066         }
01067       }
01068     }
01069   }
01070   
01071   aFmctx->mCharSetMap        = copy[0];
01072   aFmctx->mNoneCharSetMap    = copy[1];
01073   aFmctx->mSpecialCharSetMap = copy[2];
01074 
01075 #ifdef DEBUG_copyfontcharsetmap
01076   DumpFontCharSetMap(aFmctx->mCharSetMap);
01077   DumpFontCharSetMap(aFmctx->mNoneCharSetMap);
01078   DumpFontCharSetMap(aFmctx->mSpecialCharSetMap);
01079 #endif /* DEBUG_copyfontcharsetmap */
01080   
01081   return PR_TRUE; 
01082 }
01083 
01084 static char*
01085 atomToName(nsIAtom* aAtom)
01086 {
01087   const char *namePRU;
01088   aAtom->GetUTF8String(&namePRU);
01089   return ToNewCString(nsDependentCString(namePRU));
01090 }
01091 
01092 //
01093 // smart quotes (and other special chars) in Asian (double byte)
01094 // fonts are too large to use is western fonts.
01095 // To update the list, see one of files included below. (bug 180266)
01096 //
01097 #include "dbyte_special_chars.ccmap"
01098 DEFINE_CCMAP(gDoubleByteSpecialCharsCCMap, const);
01099          
01100 static PRBool
01101 FreeCharSetMap(nsHashKey* aKey, void* aData, void* aClosure)
01102 {
01103   nsFontCharSetMapXlib* charsetMap = (nsFontCharSetMapXlib*) aData;
01104   NS_IF_RELEASE(charsetMap->mInfo->mConverter);
01105   NS_IF_RELEASE(charsetMap->mInfo->mLangGroup);
01106   FreeCCMap(charsetMap->mInfo->mCCMap);
01107 
01108   return PR_TRUE;
01109 }
01110 
01111 static PRBool
01112 FreeFamily(nsHashKey* aKey, void* aData, void* aClosure)
01113 {
01114   delete (nsFontFamilyXlib*) aData;
01115 
01116   return PR_TRUE;
01117 }
01118 
01119 static void
01120 FreeStretch(nsFontStretchXlib* aStretch)
01121 {
01122   PR_smprintf_free(aStretch->mScalable);
01123 
01124   for (PRInt32 count = aStretch->mScaledFonts.Count()-1; count >= 0; --count) {
01125     nsFontXlib *font = (nsFontXlib*)aStretch->mScaledFonts.ElementAt(count);
01126     if (font) delete font;
01127   }
01128   // aStretch->mScaledFonts.Clear(); handled by delete of aStretch
01129 
01130   for (int i = 0; i < aStretch->mSizesCount; i++) {
01131     delete aStretch->mSizes[i];
01132   }
01133   delete [] aStretch->mSizes;
01134   delete aStretch;
01135 }
01136 
01137 static void
01138 FreeWeight(nsFontWeightXlib* aWeight)
01139 {
01140   for (int i = 0; i < 9; i++) {
01141     if (aWeight->mStretches[i]) {
01142       for (int j = i + 1; j < 9; j++) {
01143         if (aWeight->mStretches[j] == aWeight->mStretches[i]) {
01144           aWeight->mStretches[j] = nsnull;
01145         }
01146       }
01147       FreeStretch(aWeight->mStretches[i]);
01148     }
01149   }
01150   delete aWeight;
01151 }
01152 
01153 static void
01154 FreeStyle(nsFontStyleXlib* aStyle)
01155 {
01156   for (int i = 0; i < 9; i++) {
01157     if (aStyle->mWeights[i]) {
01158       for (int j = i + 1; j < 9; j++) {
01159         if (aStyle->mWeights[j] == aStyle->mWeights[i]) {
01160           aStyle->mWeights[j] = nsnull;
01161         }
01162       }
01163       FreeWeight(aStyle->mWeights[i]);
01164     }
01165   }
01166   delete aStyle;
01167 }
01168 
01169 static 
01170 PRBool
01171 FreeNode(nsHashKey* aKey, void* aData, void* aClosure)
01172 {
01173   nsFontNodeXlib* node = (nsFontNodeXlib*) aData;
01174   for (int i = 0; i < 3; i++) {
01175     if (node->mStyles[i]) {
01176       for (int j = i + 1; j < 3; j++) {
01177         if (node->mStyles[j] == node->mStyles[i]) {
01178           node->mStyles[j] = nsnull;
01179         }
01180       }
01181       FreeStyle(node->mStyles[i]);
01182     }
01183   }
01184   delete node;
01185 
01186   return PR_TRUE;
01187 }
01188 
01189 static 
01190 PRBool
01191 FreeNodeArray(nsHashKey* aKey, void* aData, void* aClosure)
01192 {
01193   nsFontNodeArrayXlib* nodes = (nsFontNodeArrayXlib*) aData;
01194   delete nodes;
01195 
01196   return PR_TRUE;
01197 }
01198 
01199 /* This is only required for the main display */
01200 static nsFontMetricsXlibContext *global_fmctx = nsnull;
01201 
01202 nsFontMetricsXlibContext::~nsFontMetricsXlibContext()
01203 {
01204   PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("# nsFontMetricsXlibContext destroy()\n"));
01205 
01206 #ifdef MOZ_ENABLE_FREETYPE2
01207   nsFreeTypeFreeGlobals();
01208 #endif /* MOZ_ENABLE_FREETYPE2 */
01209 
01210 #ifdef ENABLE_X_FONT_BANNING
01211   if (mFontRejectRegEx) {
01212     regfree(mFontRejectRegEx);
01213     delete mFontRejectRegEx;
01214   }
01215   
01216   if (mFontAcceptRegEx) {
01217     regfree(mFontAcceptRegEx);
01218     delete mFontAcceptRegEx;
01219   }  
01220 #endif /* ENABLE_X_FONT_BANNING */
01221 
01222 #ifdef USE_AASB
01223   nsXFontAAScaledBitmap::FreeGlobals();
01224   nsX11AlphaBlendFreeGlobals();
01225 #endif /* USE_AASB */
01226 
01227   mCharSetMaps.Reset(FreeCharSetMap, nsnull);
01228   mFamilies.Reset(FreeFamily, nsnull);
01229   mCachedFFRESearches.Reset(FreeNodeArray, nsnull); 
01230   mFFRENodes.Reset(FreeNode, nsnull);
01231   mAFRENodes.Reset(FreeNode, nsnull);
01232   mSpecialCharSets.Reset(FreeCharSetMap, nsnull);
01233 
01234   const nsFontCharSetMapXlib* charSetMap;
01235   for (charSetMap=mCharSetMap; charSetMap->mFontLangGroup; charSetMap++) {
01236     NS_IF_RELEASE(charSetMap->mFontLangGroup->mFontLangGroupAtom);
01237   }
01238   FreeCCMap(mUserDefinedCCMap);
01239   FreeCCMap(mEmptyCCMap);
01240   PR_Free(mDoubleByteSpecialCharsCCMap);
01241   
01242   /* Free memory allocated by |CopyFontCharSetMapXlib()| */
01243   if (mCharSetMap) {
01244     free((void *)mCharSetMap);
01245   }
01246 }
01247 
01248 /*
01249  * Initialize all the font lookup hash tables and other globals
01250  */
01251 
01252 nsresult CreateFontMetricsXlibContext(nsIDeviceContext *aDevice, PRBool aPrintermode, nsFontMetricsXlibContext **aFontMetricsXlibContext)
01253 {
01254   nsresult                  rv;
01255   nsFontMetricsXlibContext *fmctx;
01256   
01257   *aFontMetricsXlibContext = nsnull;
01258   
01259   fmctx = new nsFontMetricsXlibContext();
01260   if (!fmctx)
01261     return NS_ERROR_OUT_OF_MEMORY;
01262   
01263   rv = fmctx->Init(aDevice, aPrintermode);
01264   if ((NS_FAILED(rv))) {
01265     delete fmctx;
01266     return rv;
01267   }
01268   
01269   *aFontMetricsXlibContext = fmctx;
01270   
01271   return rv;
01272 }
01273 
01274 void DeleteFontMetricsXlibContext(nsFontMetricsXlibContext *aFontMetricsXlibContext)
01275 {
01276   if (aFontMetricsXlibContext) {
01277     delete aFontMetricsXlibContext;
01278   }
01279 }
01280 
01281 
01282 nsFontMetricsXlibContext::nsFontMetricsXlibContext()
01283 {
01284 }
01285 
01286 nsresult
01287 nsFontMetricsXlibContext::Init(nsIDeviceContext *aDevice, PRBool aPrintermode)
01288 {
01289   PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("# nsFontMetricsXlibContext new() for device=%p\n", aDevice));
01290 
01291   NS_ENSURE_TRUE(aDevice != nsnull, NS_ERROR_NULL_POINTER);
01292 
01293 #ifdef USE_XPRINT
01294   mPrinterMode = aPrintermode;
01295 #endif /* USE_XPRINT */
01296 
01297   mForceOutlineScaledFonts = PR_FALSE;
01298   mXlibRgbHandle = nsnull;
01299   mAllowDoubleByteSpecialChars = PR_TRUE;
01300 
01301   // XXX many of these statics need to be freed at shutdown time
01302 
01303   mDevScale = 0.0f; /* Scaler value from |GetCanonicalPixelScale()| */
01304   mScaleBitmapFontsWithDevScale = PR_FALSE;
01305 
01306   mGlobalListInitalised = PR_FALSE;
01307 
01308   mUserDefinedCCMap            = nsnull;
01309   mEmptyCCMap                  = nsnull;
01310   mDoubleByteSpecialCharsCCMap = nsnull;
01311 
01312   mCharSetMap        = nsnull;
01313   mNoneCharSetMap    = nsnull;
01314   mSpecialCharSetMap = nsnull;
01315   
01316   // Controls for Outline Scaled Fonts (okay looking)
01317 
01318   mOutlineScaleMinimum = 6;
01319 #ifdef USE_AASB
01320 // Controls for Anti-Aliased Scaled Bitmaps (okay looking)
01321   mAABitmapScaleEnabled = PR_TRUE;
01322   mAABitmapScaleAlways = PR_FALSE;
01323   mAABitmapScaleMinimum = 6;
01324   mAABitmapOversize = 1.1;
01325   mAABitmapUndersize = 0.9;
01326 #endif /* USE_AASB */
01327 
01328 // Controls for (regular) Scaled Bitmaps (very ugly)
01329   mBitmapScaleMinimum = 10;
01330   mBitmapOversize = 1.2;
01331   mBitmapUndersize = 0.8;
01332 
01333 #ifdef USE_AASB
01334   mAntiAliasMinimum = 8;
01335 #endif /* USE_AASB */
01336   mEmbeddedBitmapMaximumHeight = 1000000;
01337 
01338 #ifdef MOZ_ENABLE_FREETYPE2
01339   mEnableFreeType2 = PR_TRUE;
01340   mFreeType2Autohinted = PR_FALSE;
01341   mFreeType2Unhinted = PR_TRUE;
01342 #endif /* MOZ_ENABLE_FREETYPE2 */
01343 #ifdef USE_AASB
01344   mAATTDarkTextMinValue = 64;
01345   mAATTDarkTextGain = 0.8;
01346 #endif /* USE_AASB */
01347 
01348 #ifdef ENABLE_X_FONT_BANNING
01349   mFontRejectRegEx = nsnull;
01350   mFontAcceptRegEx = nsnull;
01351 #endif /* ENABLE_X_FONT_BANNING */
01352 
01353   PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("## CopyFontCharSetMapXlib start.\n"));
01354 
01355   if (!CopyFontCharSetMapXlib(this)) {
01356     PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("## CopyFontCharSetMapXlib FAILED.\n"));
01357     return NS_ERROR_OUT_OF_MEMORY;
01358   }
01359   PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("## CopyFontCharSetMapXlib done.\n"));
01360 
01361 #ifdef NS_FONT_DEBUG
01362   /* First check gfx/src/xlib/-specific env var "NS_FONT_DEBUG_XLIB" (or
01363   * "NS_FONT_DEBUG_XPRINT" if the device is a printer),
01364    * then the more general "NS_FONT_DEBUG" if 
01365    * "NS_FONT_DEBUG_XLIB"/"NS_FONT_DEBUG_XPRINT" is not present */
01366   const char *debug;
01367 #ifdef USE_XPRINT
01368   if (mPrinterMode) {
01369     debug = PR_GetEnv("NS_FONT_DEBUG_XPRINT");
01370   }
01371   else
01372 #endif /* USE_XPRINT */
01373   {
01374     debug = PR_GetEnv("NS_FONT_DEBUG_XLIB");
01375   }
01376 
01377   if (!debug) {
01378     debug = PR_GetEnv("NS_FONT_DEBUG");
01379   }
01380   
01381   if (debug) {
01382     PR_sscanf(debug, "%lX", &gFontDebug);
01383   }
01384 #endif /* NS_FONT_DEBUG */
01385 
01386   NS_STATIC_CAST(nsDeviceContextX *, aDevice)->GetXlibRgbHandle(mXlibRgbHandle);
01387 
01388   aDevice->GetCanonicalPixelScale(mDevScale);
01389 
01390   mCharSetManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID);
01391   if (!mCharSetManager) {
01392     return NS_ERROR_FAILURE;
01393   }
01394     
01395   mPref = do_GetService(NS_PREF_CONTRACTID);  
01396   if (!mPref) {
01397     return NS_ERROR_FAILURE;
01398   }
01399 
01400   nsCompressedCharMap empty_ccmapObj;
01401   mEmptyCCMap = empty_ccmapObj.NewCCMap();
01402   if (!mEmptyCCMap)
01403     return NS_ERROR_OUT_OF_MEMORY;
01404 
01405   // get the "disable double byte font special chars" setting
01406   PRBool val = PR_TRUE;
01407   nsresult rv = mPref->GetBoolPref("font.allow_double_byte_special_chars", &val);
01408   if (NS_SUCCEEDED(rv))
01409     mAllowDoubleByteSpecialChars = val;
01410 
01411   /* Make sure we allocate/copy enough (see bug 235913, comment 12)*/
01412   PRUint32 dbmapSize = sizeof(gDoubleByteSpecialCharsCCMapUnion);
01413   mDoubleByteSpecialCharsCCMap = (PRUint16*)PR_Malloc(dbmapSize);
01414   if (!mDoubleByteSpecialCharsCCMap)
01415     return NS_ERROR_OUT_OF_MEMORY;
01416   memcpy(mDoubleByteSpecialCharsCCMap, gDoubleByteSpecialCharsCCMap, dbmapSize);
01417 
01418   PRInt32 scale_minimum = 0;
01419   rv = mPref->GetIntPref("font.scale.outline.min", &scale_minimum);
01420   if (NS_SUCCEEDED(rv)) {
01421     mOutlineScaleMinimum = scale_minimum;
01422     SIZE_FONT_PRINTF(("mOutlineScaleMinimum = %d", mOutlineScaleMinimum));
01423   }
01424 
01425   PRInt32 int_val = 0;
01426   PRInt32 percent = 0;
01427 #ifdef USE_AASB
01428   val = PR_TRUE;
01429   rv = mPref->GetBoolPref("font.scale.aa_bitmap.enable", &val);
01430   if (NS_SUCCEEDED(rv)) {
01431     mAABitmapScaleEnabled = val;
01432     SIZE_FONT_PRINTF(("mAABitmapScaleEnabled = %d", mAABitmapScaleEnabled));
01433   }
01434 
01435   val = PR_FALSE;
01436   rv = mPref->GetBoolPref("font.scale.aa_bitmap.always", &val);
01437   if (NS_SUCCEEDED(rv)) {
01438     mAABitmapScaleAlways = val;
01439     SIZE_FONT_PRINTF(("mAABitmapScaleAlways = %d", mAABitmapScaleAlways));
01440   }
01441 
01442   rv = mPref->GetIntPref("font.scale.aa_bitmap.min", &scale_minimum);
01443   if (NS_SUCCEEDED(rv)) {
01444     mAABitmapScaleMinimum = scale_minimum;
01445     SIZE_FONT_PRINTF(("mAABitmapScaleMinimum = %d", mAABitmapScaleMinimum));
01446   }
01447 
01448   percent = 0;
01449   rv = mPref->GetIntPref("font.scale.aa_bitmap.undersize", &percent);
01450   if ((NS_SUCCEEDED(rv)) && (percent)) {
01451     mAABitmapUndersize = percent/100.0;
01452     SIZE_FONT_PRINTF(("mAABitmapUndersize = %g", mAABitmapUndersize));
01453   }
01454   percent = 0;
01455   rv = mPref->GetIntPref("font.scale.aa_bitmap.oversize", &percent);
01456   if ((NS_SUCCEEDED(rv)) && (percent)) {
01457     mAABitmapOversize = percent/100.0;
01458     SIZE_FONT_PRINTF(("mAABitmapOversize = %g", mAABitmapOversize));
01459   }
01460   int_val = 0;
01461   rv = mPref->GetIntPref("font.scale.aa_bitmap.dark_text.min", &int_val);
01462   if (NS_SUCCEEDED(rv)) {
01463     gAASBDarkTextMinValue = int_val;
01464     SIZE_FONT_PRINTF(("gAASBDarkTextMinValue = %d", gAASBDarkTextMinValue));
01465   }
01466   nsXPIDLCString str;
01467   rv = mPref->GetCharPref("font.scale.aa_bitmap.dark_text.gain",
01468                            getter_Copies(str));
01469   if (NS_SUCCEEDED(rv)) {
01470     gAASBDarkTextGain = atof(str.get());
01471     SIZE_FONT_PRINTF(("gAASBDarkTextGain = %g", gAASBDarkTextGain));
01472   }
01473   int_val = 0;
01474   rv = mPref->GetIntPref("font.scale.aa_bitmap.light_text.min", &int_val);
01475   if (NS_SUCCEEDED(rv)) {
01476     gAASBLightTextMinValue = int_val;
01477     SIZE_FONT_PRINTF(("gAASBLightTextMinValue = %d", gAASBLightTextMinValue));
01478   }
01479   rv = mPref->GetCharPref("font.scale.aa_bitmap.light_text.gain",
01480                            getter_Copies(str));
01481   if (NS_SUCCEEDED(rv)) {
01482     gAASBLightTextGain = atof(str.get());
01483     SIZE_FONT_PRINTF(("gAASBLightTextGain = %g", gAASBLightTextGain));
01484   }
01485 #endif /* USE_AASB */
01486 
01487   rv = mPref->GetIntPref("font.scale.bitmap.min", &scale_minimum);
01488   if (NS_SUCCEEDED(rv)) {
01489     mBitmapScaleMinimum = scale_minimum;
01490     SIZE_FONT_PRINTF(("mBitmapScaleMinimum = %d", mBitmapScaleMinimum));
01491   }
01492   percent = 0;
01493   mPref->GetIntPref("font.scale.bitmap.oversize", &percent);
01494   if (percent) {
01495     mBitmapOversize = percent/100.0;
01496     SIZE_FONT_PRINTF(("mBitmapOversize = %g", mBitmapOversize));
01497   }
01498   percent = 0;
01499   mPref->GetIntPref("font.scale.bitmap.undersize", &percent);
01500   if (percent) {
01501     mBitmapUndersize = percent/100.0;
01502     SIZE_FONT_PRINTF(("mBitmapUndersize = %g", mBitmapUndersize));
01503   }
01504 
01505 #ifdef USE_XPRINT
01506   if (mPrinterMode) {
01507     mForceOutlineScaledFonts = PR_TRUE;
01508   }
01509 #endif /* USE_XPRINT */
01510 
01511  PRBool force_outline_scaled_fonts = mForceOutlineScaledFonts;
01512 #ifdef USE_XPRINT
01513   if (mPrinterMode) {
01514     rv = mPref->GetBoolPref("print.xprint.font.force_outline_scaled_fonts", &force_outline_scaled_fonts);
01515   }  
01516   if (!mPrinterMode || NS_FAILED(rv)) {
01517 #endif /* USE_XPRINT */
01518     rv = mPref->GetBoolPref("font.x11.force_outline_scaled_fonts", &force_outline_scaled_fonts);
01519 #ifdef USE_XPRINT
01520   }
01521 #endif /* USE_XPRINT */
01522   if (NS_SUCCEEDED(rv)) {
01523     mForceOutlineScaledFonts = force_outline_scaled_fonts;
01524   }
01525 
01526 #ifdef MOZ_ENABLE_FREETYPE2
01527   PRBool enable_freetype2 = PR_TRUE;
01528   rv = mPref->GetBoolPref("font.FreeType2.enable", &enable_freetype2);
01529   if (NS_SUCCEEDED(rv)) {
01530     mEnableFreeType2 = enable_freetype2;
01531     FREETYPE_FONT_PRINTF(("mEnableFreeType2 = %d", mEnableFreeType2));
01532   }
01533 
01534   PRBool freetype2_autohinted = PR_FALSE;
01535   rv = mPref->GetBoolPref("font.FreeType2.autohinted", &freetype2_autohinted);
01536   if (NS_SUCCEEDED(rv)) {
01537     mFreeType2Autohinted = freetype2_autohinted;
01538     FREETYPE_FONT_PRINTF(("mFreeType2Autohinted = %d", mFreeType2Autohinted));
01539   }
01540 
01541   PRBool freetype2_unhinted = PR_TRUE;
01542   rv = mPref->GetBoolPref("font.FreeType2.unhinted", &freetype2_unhinted);
01543   if (NS_SUCCEEDED(rv)) {
01544     mFreeType2Unhinted = freetype2_unhinted;
01545     FREETYPE_FONT_PRINTF(("mFreeType2Unhinted = %d", mFreeType2Unhinted));
01546   }
01547 #endif /* MOZ_ENABLE_FREETYPE2 */
01548 
01549 #ifdef USE_AASB
01550   PRInt32 antialias_minimum = 8;
01551   rv = mPref->GetIntPref("font.antialias.min", &antialias_minimum);
01552   if (NS_SUCCEEDED(rv)) {
01553     mAntiAliasMinimum = antialias_minimum;
01554     FREETYPE_FONT_PRINTF(("mAntiAliasMinimum = %d", mAntiAliasMinimum));
01555   }
01556 #endif /* USE_AASB */
01557 
01558   PRInt32 embedded_bitmaps_maximum = 1000000;
01559   rv = mPref->GetIntPref("font.embedded_bitmaps.max",&embedded_bitmaps_maximum);
01560   if (NS_SUCCEEDED(rv)) {
01561     mEmbeddedBitmapMaximumHeight = embedded_bitmaps_maximum;
01562     FREETYPE_FONT_PRINTF(("mEmbeddedBitmapMaximumHeight = %d",
01563                           mEmbeddedBitmapMaximumHeight));
01564   }
01565   int_val = 0;
01566 #ifdef USE_AASB
01567   rv = mPref->GetIntPref("font.scale.tt_bitmap.dark_text.min", &int_val);
01568   if (NS_SUCCEEDED(rv)) {
01569     mAATTDarkTextMinValue = int_val;
01570     SIZE_FONT_PRINTF(("mAATTDarkTextMinValue = %d", mAATTDarkTextMinValue));
01571   }
01572   rv = mPref->GetCharPref("font.scale.tt_bitmap.dark_text.gain",
01573                            getter_Copies(str));
01574   if (NS_SUCCEEDED(rv)) {
01575     mAATTDarkTextGain = atof(str.get());
01576     SIZE_FONT_PRINTF(("mAATTDarkTextGain = %g", mAATTDarkTextGain));
01577   }
01578 #endif /* USE_AASB */
01579 
01580 #ifdef USE_XPRINT
01581   if (mPrinterMode) {
01582     mScaleBitmapFontsWithDevScale = PR_TRUE;
01583   }
01584 #endif /* USE_XPRINT */
01585 
01586  PRBool scale_bitmap_fonts_with_devscale = mScaleBitmapFontsWithDevScale;
01587 #ifdef USE_XPRINT
01588   if (mPrinterMode) {
01589     rv = mPref->GetBoolPref("print.xprint.font.scale_bitmap_fonts_with_devscale", &scale_bitmap_fonts_with_devscale);
01590   }  
01591   if (!mPrinterMode || NS_FAILED(rv)) {
01592 #endif /* USE_XPRINT */
01593     rv = mPref->GetBoolPref("font.x11.scale_bitmap_fonts_with_devscale", &scale_bitmap_fonts_with_devscale);
01594 #ifdef USE_XPRINT
01595   }
01596 #endif /* USE_XPRINT */
01597   if (NS_SUCCEEDED(rv)) {
01598     mScaleBitmapFontsWithDevScale = scale_bitmap_fonts_with_devscale;
01599   }
01600 
01601   const nsFontFamilyNameXlib* f = gFamilyNameTable;
01602   while (f->mName) {
01603     nsCStringKey key(f->mName);
01604     mAliases.Put(&key, (void *)f->mXName);
01605     f++;
01606   }
01607 
01608   const nsFontPropertyNameXlib* p = gWeightNames;
01609   while (p->mName) {
01610     nsCStringKey key(p->mName);
01611     mWeights.Put(&key, (void*) p->mValue);
01612     p++;
01613   }
01614 
01615   p = gStretchNames;
01616   while (p->mName) {
01617     nsCStringKey key(p->mName);
01618     mStretches.Put(&key, (void*) p->mValue);
01619     p++;
01620   }
01621 
01622   const nsFontCharSetMapXlib* charSetMap = mCharSetMap;
01623   while (charSetMap->mName) {
01624     nsCStringKey key(charSetMap->mName);
01625     mCharSetMaps.Put(&key, (void *)charSetMap);
01626     charSetMap++;
01627   }
01628 
01629   const nsFontCharSetMapXlib* specialCharSetMap = mSpecialCharSetMap;
01630   while (specialCharSetMap->mName) {
01631     nsCStringKey key(specialCharSetMap->mName);
01632     mSpecialCharSets.Put(&key, (void *)specialCharSetMap);
01633     specialCharSetMap++;
01634   }
01635 
01636   mUnicode = do_GetAtom("x-unicode");
01637   if (!mUnicode) {
01638     return NS_ERROR_OUT_OF_MEMORY;
01639   }
01640   mUserDefined = do_GetAtom(USER_DEFINED);
01641   if (!mUserDefined) {
01642     return NS_ERROR_OUT_OF_MEMORY;
01643   }
01644   mZHTW = do_GetAtom("zh-TW");
01645   if (!mZHTW) {
01646     return NS_ERROR_OUT_OF_MEMORY;
01647   }
01648   mZHHK = do_GetAtom("zh-HK");
01649   if (!mZHHK) {
01650     return NS_ERROR_OUT_OF_MEMORY;
01651   }
01652   mZHTWHK = do_GetAtom("x-zh-TWHK");
01653   if (!mZHTWHK) {
01654     return NS_ERROR_OUT_OF_MEMORY;
01655   }
01656 
01657   // the user's locale
01658   nsCOMPtr<nsILanguageAtomService> langService;
01659   langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
01660   if (langService) {
01661     mUsersLocale = langService->GetLocaleLanguageGroup();
01662   }
01663   if (!mUsersLocale) {
01664     mUsersLocale = do_GetAtom("x-western");
01665   }
01666   mWesternLocale = do_GetAtom("x-western");
01667   if (!mUsersLocale) {
01668     return NS_ERROR_OUT_OF_MEMORY;
01669   }
01670 
01671 #ifdef USE_AASB
01672   rv = nsX11AlphaBlendInitGlobals(xxlib_rgb_get_display(mXlibRgbHandle));
01673   if (NS_FAILED(rv) || (!nsX11AlphaBlend::CanAntiAlias())) {
01674     mAABitmapScaleEnabled = PR_FALSE;
01675   }
01676 
01677   if (mAABitmapScaleEnabled) {
01678       mAABitmapScaleEnabled = nsXFontAAScaledBitmap::InitGlobals(xxlib_rgb_get_display(mXlibRgbHandle),
01679                                                                  xxlib_rgb_get_screen(mXlibRgbHandle));
01680   }
01681 #endif /* USE_AASB */
01682   
01683 #ifdef ENABLE_X_FONT_BANNING
01684   /* get the font banning pattern */
01685   nsXPIDLCString fbpattern;
01686 #ifdef USE_XPRINT
01687   if (mPrinterMode) {
01688     rv = mPref->GetCharPref("print.xprint.font.rejectfontpattern", getter_Copies(fbpattern));
01689   }  
01690   if (!mPrinterMode || NS_FAILED(rv)) {
01691 #endif /* USE_XPRINT */
01692     rv = mPref->GetCharPref("font.x11.rejectfontpattern", getter_Copies(fbpattern));
01693 #ifdef USE_XPRINT
01694   }
01695 #endif /* USE_XPRINT */
01696   if (NS_SUCCEEDED(rv)) {
01697     mFontRejectRegEx = new regex_t;
01698     if (!mFontRejectRegEx) {
01699       return NS_ERROR_OUT_OF_MEMORY;
01700     }
01701     
01702     /* Compile the pattern - and return an error if we get an invalid pattern... */
01703     if (regcomp(mFontRejectRegEx, fbpattern.get(), REG_EXTENDED|REG_NOSUB) != REG_OK) {
01704       PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("Invalid rejectfontpattern '%s'\n", fbpattern.get()));
01705       BANNED_FONT_PRINTF(("Invalid font.x11.rejectfontpattern '%s'", fbpattern.get()));
01706       delete mFontRejectRegEx;
01707       mFontRejectRegEx = nsnull;
01708       
01709       return NS_ERROR_INVALID_ARG;
01710     }    
01711   }
01712 
01713 #ifdef USE_XPRINT
01714   if (mPrinterMode) {
01715     rv = mPref->GetCharPref("print.xprint.font.acceptfontpattern", getter_Copies(fbpattern));
01716   }  
01717   if (!mPrinterMode || NS_FAILED(rv)) {
01718 #endif /* USE_XPRINT */
01719     rv = mPref->GetCharPref("font.x11.acceptfontpattern", getter_Copies(fbpattern));
01720 #ifdef USE_XPRINT
01721   }
01722 #endif /* USE_XPRINT */
01723   if (NS_SUCCEEDED(rv)) {
01724     mFontAcceptRegEx = new regex_t;
01725     if (!mFontAcceptRegEx) {
01726       return NS_ERROR_OUT_OF_MEMORY;
01727     }
01728     
01729     /* Compile the pattern - and return an error if we get an invalid pattern... */
01730     if (regcomp(mFontAcceptRegEx, fbpattern.get(), REG_EXTENDED|REG_NOSUB) != REG_OK) {
01731       PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("Invalid acceptfontpattern '%s'\n", fbpattern.get()));
01732       BANNED_FONT_PRINTF(("Invalid font.x11.acceptfontpattern '%s'", fbpattern.get()));
01733       delete mFontAcceptRegEx;
01734       mFontAcceptRegEx = nsnull;
01735       
01736       return NS_ERROR_INVALID_ARG;
01737     }    
01738   }
01739 #endif /* ENABLE_X_FONT_BANNING */
01740 
01741 #ifdef MOZ_ENABLE_FREETYPE2
01742   rv = nsFreeTypeInitGlobals();
01743   if (NS_FAILED(rv)) {
01744     return NS_ERROR_OUT_OF_MEMORY;
01745   }
01746 #endif /* MOZ_ENABLE_FREETYPE2 */
01747 
01748   return NS_OK;
01749 }
01750 
01751 #ifdef USE_X11SHARED_CODE
01752 #error not implemented yet
01753 #else
01754 void
01755 nsXFontNormal::DrawText8(Drawable aDrawable, GC aGC,
01756                          PRInt32 aX, PRInt32 aY,
01757                          const char *aString, PRUint32 aLength)
01758 {
01759   XDrawString(mDisplay, aDrawable, aGC, aX, aY, aString, PR_MIN(aLength, 32767));
01760 }
01761 
01762 void
01763 nsXFontNormal::DrawText16(Drawable aDrawable, GC aGC,
01764                           PRInt32 aX, PRInt32 aY,
01765                           const XChar2b *aString, PRUint32 aLength)
01766 {
01767   XDrawString16(mDisplay, aDrawable, aGC, aX, aY, aString, PR_MIN(aLength, 32767));
01768 }
01769 
01770 PRBool
01771 nsXFontNormal::GetXFontProperty(Atom aAtom, unsigned long *aValue)
01772 {
01773   NS_ASSERTION(mXFont, "GetXFontProperty called before font loaded");
01774   if (mXFont==nsnull)
01775     return PR_FALSE;
01776 
01777   return ::XGetFontProperty(mXFont, aAtom, aValue);
01778 }
01779 
01780 XFontStruct *
01781 nsXFontNormal::GetXFontStruct()
01782 {
01783   NS_ASSERTION(mXFont, "GetXFontStruct called before font loaded");
01784   return mXFont;
01785 }
01786 
01787 PRBool
01788 nsXFontNormal::LoadFont()
01789 {
01790   if (!mXFont)
01791     return PR_FALSE;
01792   mIsSingleByte = (mXFont->min_byte1 == 0) && (mXFont->max_byte1 == 0);
01793   return PR_TRUE;
01794 }
01795 
01796 nsXFontNormal::nsXFontNormal(Display *aDisplay, XFontStruct *aXFont)
01797 {
01798   mDisplay = aDisplay;
01799   mXFont   = aXFont;
01800 }
01801 
01802 void
01803 nsXFontNormal::TextExtents8(const char *aString, PRUint32 aLength,
01804                             PRInt32* aLBearing, PRInt32* aRBearing,
01805                             PRInt32* aWidth, PRInt32* aAscent,
01806                             PRInt32* aDescent)
01807 {
01808   XCharStruct overall;
01809   int direction, font_ascent, font_descent;
01810   ::XTextExtents(mXFont, aString, aLength,
01811                  &direction, &font_ascent, &font_descent,
01812                  &overall);
01813 
01814   *aLBearing = overall.lbearing;
01815   *aRBearing = overall.rbearing;
01816   *aWidth    = overall.width;
01817   *aAscent   = overall.ascent;
01818   *aDescent  = overall.descent;
01819 }
01820 
01821 void
01822 nsXFontNormal::TextExtents16(const XChar2b *aString, PRUint32 aLength,
01823                             PRInt32* aLBearing, PRInt32* aRBearing,
01824                             PRInt32* aWidth, PRInt32* aAscent,
01825                             PRInt32* aDescent)
01826 {
01827   XCharStruct overall;
01828   int direction, font_ascent, font_descent;
01829   ::XTextExtents16(mXFont, aString, aLength,
01830                    &direction, &font_ascent, &font_descent,
01831                    &overall);
01832 
01833   *aLBearing = overall.lbearing;
01834   *aRBearing = overall.rbearing;
01835   *aWidth    = overall.width;
01836   *aAscent   = overall.ascent;
01837   *aDescent  = overall.descent;
01838 }
01839 
01840 PRInt32
01841 nsXFontNormal::TextWidth8(const char *aString, PRUint32 aLength)
01842 {
01843   NS_ASSERTION(mXFont, "TextWidth8 called before font loaded");
01844   if (mXFont==nsnull)
01845     return 0;
01846   PRInt32 width = ::XTextWidth(mXFont, aString, aLength);
01847   return width;
01848 }
01849 
01850 PRInt32
01851 nsXFontNormal::TextWidth16(const XChar2b *aString, PRUint32 aLength)
01852 {
01853   NS_ASSERTION(mXFont, "TextWidth16 called before font loaded");
01854   if (mXFont==nsnull)
01855     return 0;
01856   PRInt32 width = ::XTextWidth16(mXFont, aString, aLength);
01857   
01858   return width;
01859 }
01860 
01861 void
01862 nsXFontNormal::UnloadFont()
01863 {
01864   delete this;
01865 }
01866 
01867 nsXFontNormal::~nsXFontNormal()
01868 {
01869 }
01870 #endif /* USE_X11SHARED_CODE */
01871 
01872 nsFontMetricsXlib::nsFontMetricsXlib()
01873   : mFonts() // I'm not sure what the common size is here - I generally
01874   // see 2-5 entries.  For now, punt and let it be allocated later.  We can't
01875   // make it an nsAutoVoidArray since it's a cString array.
01876   // XXX mFontIsGeneric will generally need to be the same size; right now
01877   // it's an nsAutoVoidArray.  If the average is under 8, that's ok.
01878 {
01879 }
01880 
01881 nsFontMetricsXlib::~nsFontMetricsXlib()
01882 {
01883   // do not free mGeneric here
01884 
01885   if (mLoadedFonts) {
01886     PR_Free(mLoadedFonts);
01887     mLoadedFonts = nsnull;
01888   }
01889 
01890   if (mSubstituteFont) {
01891     delete mSubstituteFont;
01892     mSubstituteFont = nsnull;
01893   }
01894 
01895   mWesternFont = nsnull;
01896 
01897   if (mDeviceContext) {
01898     // Notify our device context that owns us so that it can update its font cache
01899     mDeviceContext->FontMetricsDeleted(this);
01900     mDeviceContext = nsnull;
01901   }
01902 }
01903 
01904 NS_IMPL_ISUPPORTS1(nsFontMetricsXlib, nsIFontMetrics)
01905 
01906 static PRBool
01907 IsASCIIFontName(const nsString& aName)
01908 {
01909   PRUint32 len = aName.Length();
01910   const PRUnichar* str = aName.get();
01911   for (PRUint32 i = 0; i < len; i++) {
01912     /*
01913      * X font names are printable ASCII, ignore others (for now)
01914      */
01915     if ((str[i] < 0x20) || (str[i] > 0x7E)) {
01916       return PR_FALSE;
01917     }
01918   }
01919 
01920   return PR_TRUE;
01921 }
01922 
01923 static PRBool
01924 FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
01925 {
01926 #ifdef REALLY_NOISY_FONTS
01927   printf("font = '");
01928   fputs(NS_LossyConvertUCS2toASCII(aFamily).get(), stdout);
01929   printf("'\n");
01930 #endif
01931 
01932   if (!IsASCIIFontName(aFamily)) {
01933     return PR_TRUE; // skip and continue
01934   }
01935 
01936   nsCAutoString name;
01937   name.AssignWithConversion(aFamily.get());
01938   ToLowerCase(name);
01939   nsFontMetricsXlib* metrics = (nsFontMetricsXlib*) aData;
01940   metrics->mFonts.AppendCString(name);
01941   metrics->mFontIsGeneric.AppendElement((void*) aGeneric);
01942   if (aGeneric) {
01943     metrics->mGeneric = metrics->mFonts.CStringAt(metrics->mFonts.Count() - 1);
01944     return PR_FALSE; // stop
01945   }
01946 
01947   return PR_TRUE; // continue
01948 }
01949 
01950 NS_IMETHODIMP nsFontMetricsXlib::Init(const nsFont& aFont, nsIAtom* aLangGroup,
01951   nsIDeviceContext* aContext)
01952 {
01953   NS_ASSERTION(!(nsnull == aContext), "attempt to init fontmetrics with null device context");
01954 
01955   nsresult res;
01956   mDocConverterType = nsnull;
01957   
01958   mDeviceContext = aContext;
01959  
01960   NS_STATIC_CAST(nsDeviceContextX *, mDeviceContext)->GetFontMetricsContext(mFontMetricsContext);
01961   
01962   mFont = aFont;
01963   mLangGroup = aLangGroup;
01964 
01965   float app2dev;
01966   app2dev = mDeviceContext->AppUnitsToDevUnits();
01967 
01968   mPixelSize = NSToIntRound(app2dev * mFont.size);
01969   // Make sure to clamp the pixel size to something reasonable so we
01970   // don't make the X server blow up.
01971   mPixelSize = PR_MIN(XHeightOfScreen(xxlib_rgb_get_screen(mFontMetricsContext->mXlibRgbHandle)) * FONT_MAX_FONT_SCALE, mPixelSize);
01972 
01973   mStretchIndex = 4; // Normal
01974   mStyleIndex = mFont.style;
01975 
01976   mFont.EnumerateFamilies(FontEnumCallback, this);
01977   nsXPIDLCString value;
01978   const char* langGroup = nsnull;
01979   mLangGroup->GetUTF8String(&langGroup);
01980   if (!mGeneric) {
01981     nsCAutoString name("font.default.");
01982     name.Append(langGroup);
01983     mFontMetricsContext->mPref->CopyCharPref(name.get(), getter_Copies(value));
01984     if (value.get()) {
01985       mDefaultFont = value.get();
01986     }
01987     else {
01988       mDefaultFont = "serif";
01989     }
01990     mGeneric = &mDefaultFont;
01991   }
01992 
01993   if (mLangGroup) {
01994     nsCAutoString name("font.min-size.");
01995     if (mGeneric->Equals("monospace")) {
01996       name.Append("fixed");
01997     }
01998     else {
01999       name.Append("variable");
02000     }
02001     name.Append(char('.'));
02002     name.Append(langGroup);
02003     PRInt32 minimum = 0;
02004     res = mFontMetricsContext->mPref->GetIntPref(name.get(), &minimum);
02005     if (NS_FAILED(res)) {
02006       mFontMetricsContext->mPref->GetDefaultIntPref(name.get(), &minimum);
02007     }
02008     if (minimum < 0) {
02009       minimum = 0;
02010     }
02011     if (mPixelSize < minimum) {
02012       mPixelSize = minimum;
02013     }
02014   }
02015 
02016   if (mLangGroup.get() == mFontMetricsContext->mUserDefined) {
02017     if (!mFontMetricsContext->mUserDefinedConverter) {
02018         nsIUnicodeEncoder *ud_conv;
02019         res = mFontMetricsContext->mCharSetManager->GetUnicodeEncoderRaw("x-user-defined", &ud_conv);
02020         if (NS_SUCCEEDED(res)) {
02021           mFontMetricsContext->mUserDefinedConverter = ud_conv;
02022           res = mFontMetricsContext->mUserDefinedConverter->SetOutputErrorBehavior(
02023             mFontMetricsContext->mUserDefinedConverter->kOnError_Replace, nsnull, '?');
02024           nsCOMPtr<nsICharRepresentable> mapper =
02025             do_QueryInterface(mFontMetricsContext->mUserDefinedConverter);
02026           if (mapper) {
02027             mFontMetricsContext->mUserDefinedCCMap = MapperToCCMap(mapper);
02028             if (!mFontMetricsContext->mUserDefinedCCMap)
02029               return NS_ERROR_OUT_OF_MEMORY;          
02030           }
02031         }
02032         else {
02033           return res;
02034         }
02035     }
02036 
02037     nsCAutoString name("font.name.");
02038     name.Append(*mGeneric);
02039     name.Append(char('.'));
02040     name.Append(USER_DEFINED);
02041     mFontMetricsContext->mPref->CopyCharPref(name.get(), getter_Copies(value));
02042     if (value.get()) {
02043       mUserDefined = value.get();
02044       mIsUserDefined = 1;
02045     }
02046   }
02047 
02048   mWesternFont = FindFont('a');
02049   if (!mWesternFont)
02050     return NS_ERROR_FAILURE;
02051 
02052   RealizeFont();
02053 
02054   return NS_OK;
02055 }
02056 
02057 NS_IMETHODIMP  nsFontMetricsXlib::Destroy()
02058 {
02059   mDeviceContext = nsnull;
02060   mFontMetricsContext = nsnull;
02061   return NS_OK;
02062 }
02063 
02064 void nsFontMetricsXlib::RealizeFont()
02065 {
02066   float f;
02067   f = mDeviceContext->DevUnitsToAppUnits();
02068 
02069 #ifdef MOZ_ENABLE_FREETYPE2
02070   if (mWesternFont->IsFreeTypeFont()) {
02071     nsFreeTypeFont *ft = (nsFreeTypeFont *)mWesternFont;
02072     if (!ft)
02073       return;
02074     // now that there are multiple font types (eg: core X fonts
02075     // and TrueType fonts) there should be a common set of methods 
02076     // to get the metrics info from the font object. These methods
02077     // probably should be virtual functions defined in nsFontXlib.
02078 #ifdef MOZ_ENABLE_FREETYPE2
02079     int lineSpacing = ft->ascent() + ft->descent();
02080     if (lineSpacing > mWesternFont->mSize) {
02081       mLeading = nscoord((lineSpacing - mWesternFont->mSize) * f);
02082     }
02083     else {
02084       mLeading = 0;
02085     }
02086     mEmHeight = PR_MAX(1, nscoord(mWesternFont->mSize * f));
02087     mEmAscent = nscoord(ft->ascent() * mWesternFont->mSize * f / lineSpacing);
02088     mEmDescent = mEmHeight - mEmAscent;
02089 
02090     mMaxHeight  = nscoord((ft->max_ascent() + ft->max_descent()) * f);
02091     mMaxAscent  = nscoord(ft->max_ascent() * f) ;
02092     mMaxDescent = nscoord(ft->max_descent() * f);
02093 
02094     mMaxAdvance = nscoord(ft->max_width() * f);
02095 
02096     // 56% of ascent, best guess for non-true type
02097     mXHeight = NSToCoordRound((float) ft->ascent()* f * 0.56f);
02098 
02099     PRUnichar space = (PRUnichar)' ';
02100     mSpaceWidth = NSToCoordRound(ft->GetWidth(&space, 1) * f);
02101 
02102     PRUnichar averageX = (PRUnichar)'x';
02103     mAveCharWidth = NSToCoordRound(ft->GetWidth(&averageX, 1) * f);
02104 
02105     unsigned long pr = 0;
02106     if (ft->getXHeight(pr)) {
02107       mXHeight = nscoord(pr * f);
02108     }
02109 
02110     float height;
02111     long val;
02112     if (ft->underlinePosition(val)) {
02113       /* this will only be provided from adobe .afm fonts and TrueType
02114        * fonts served by xfsft (not xfstt!) */
02115       mUnderlineOffset = -NSToIntRound(val * f);
02116     }
02117     else {
02118       height = ft->ascent() + ft->descent();
02119       mUnderlineOffset = -NSToIntRound(PR_MAX (1, floor (0.1 * height + 0.5)) * f);
02120     }
02121 
02122     if (ft->underline_thickness(pr)) {
02123       /* this will only be provided from adobe .afm fonts */
02124       mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(pr * f)));
02125     }
02126     else {
02127       height = ft->ascent() + ft->descent();
02128       mUnderlineSize = NSToIntRound(PR_MAX(1, floor (0.05 * height + 0.5)) * f);
02129     }
02130 
02131     if (ft->superscript_y(val)) {
02132       mSuperscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
02133     }
02134     else {
02135       mSuperscriptOffset = mXHeight;
02136     }
02137 
02138     if (ft->subscript_y(val)) {
02139       mSubscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
02140     }
02141     else {
02142      mSubscriptOffset = mXHeight;
02143     }
02144 
02145     /* need better way to calculate this */
02146     mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0);
02147     mStrikeoutSize = mUnderlineSize;
02148 
02149     return;
02150 #endif /* MOZ_ENABLE_FREETYPE2 */
02151   }
02152 #endif /* MOZ_ENABLE_FREETYPE2 */
02153   nsXFont *xFont = mWesternFont->GetXFont();
02154   XFontStruct *fontInfo = xFont->GetXFontStruct();
02155   f = mDeviceContext->DevUnitsToAppUnits();
02156 
02157   nscoord lineSpacing = nscoord((fontInfo->ascent + fontInfo->descent) * f);
02158   mEmHeight = PR_MAX(1, nscoord(mWesternFont->mSize * f));
02159   if (lineSpacing > mEmHeight) {
02160     mLeading = lineSpacing - mEmHeight;
02161   }
02162   else {
02163     mLeading = 0;
02164   }
02165   mMaxHeight = nscoord((fontInfo->ascent + fontInfo->descent) * f);
02166   mMaxAscent = nscoord(fontInfo->ascent * f);
02167   mMaxDescent = nscoord(fontInfo->descent * f);
02168 
02169   mEmAscent = nscoord(mMaxAscent * mEmHeight / lineSpacing);
02170   mEmDescent = mEmHeight - mEmAscent;
02171 
02172   mMaxAdvance = nscoord(fontInfo->max_bounds.width * f);
02173 
02174   int rawWidth, rawAverage;
02175   if ((fontInfo->min_byte1 == 0) && (fontInfo->max_byte1 == 0)) {
02176     rawWidth = xFont->TextWidth8(" ", 1);
02177     rawAverage = xFont->TextWidth8("x", 1);
02178   }
02179   else {
02180     XChar2b my16bit_space, my16bit_x;
02181     my16bit_space.byte1 = '\0';
02182     my16bit_space.byte2 = ' ';
02183     my16bit_x.byte1     = 0;
02184     my16bit_x.byte2     = 'x';
02185     rawWidth   = xFont->TextWidth16(&my16bit_space, 1);
02186     rawAverage = xFont->TextWidth16(&my16bit_x,     1);
02187   }
02188   mSpaceWidth = NSToCoordRound(rawWidth * f);
02189   mAveCharWidth = NSToCoordRound(rawAverage * f);
02190 
02191   unsigned long pr = 0;
02192   if (xFont->GetXFontProperty(XA_X_HEIGHT, &pr) && pr != 0 &&
02193       pr < 0x00ffffff)  // Bug 43214: arbitrary to exclude garbage values
02194   {
02195     mXHeight = nscoord(pr * f);
02196 #ifdef REALLY_NOISY_FONTS
02197     printf("xHeight=%d\n", mXHeight);
02198 #endif
02199   }
02200   else 
02201   {
02202     // 56% of ascent, best guess for non-true type
02203     mXHeight = NSToCoordRound((float) fontInfo->ascent* f * 0.56f);
02204   }
02205 
02206   if (xFont->GetXFontProperty(XA_UNDERLINE_POSITION, &pr))
02207   {
02208     /* this will only be provided from adobe .afm fonts and TrueType
02209      * fonts served by xfsft (not xfstt!) */
02210     mUnderlineOffset = -NSToIntRound(pr * f);
02211 #ifdef REALLY_NOISY_FONTS
02212     printf("underlineOffset=%d\n", mUnderlineOffset);
02213 #endif
02214   }
02215   else
02216   {
02217     /* this may need to be different than one for those weird asian fonts */
02218     float height;
02219     height = fontInfo->ascent + fontInfo->descent;
02220     mUnderlineOffset = -NSToIntRound(PR_MAX (1, floor (0.1 * height + 0.5)) * f);
02221   }
02222 
02223   if (xFont->GetXFontProperty(XA_UNDERLINE_THICKNESS, &pr))
02224   {
02225     /* this will only be provided from adobe .afm fonts */
02226     mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(pr * f)));
02227 #ifdef REALLY_NOISY_FONTS
02228     printf("underlineSize=%d\n", mUnderlineSize);
02229 #endif
02230   }
02231   else
02232   {
02233     float height;
02234     height = fontInfo->ascent + fontInfo->descent;
02235     mUnderlineSize = NSToIntRound(PR_MAX(1, floor (0.05 * height + 0.5)) * f);
02236   }
02237 
02238   if (xFont->GetXFontProperty(XA_SUPERSCRIPT_Y, &pr))
02239   {
02240     mSuperscriptOffset = nscoord(PR_MAX(f, NSToIntRound(pr * f)));
02241 #ifdef REALLY_NOISY_FONTS
02242     printf("superscriptOffset=%d\n", mSuperscriptOffset);
02243 #endif
02244   }
02245   else
02246   {
02247     mSuperscriptOffset = mXHeight;
02248   }
02249 
02250   if (xFont->GetXFontProperty(XA_SUBSCRIPT_Y, &pr))
02251   {
02252     mSubscriptOffset = nscoord(PR_MAX(f, NSToIntRound(pr * f)));
02253 #ifdef REALLY_NOISY_FONTS
02254     printf("subscriptOffset=%d\n", mSubscriptOffset);
02255 #endif
02256   }
02257   else
02258   {
02259     mSubscriptOffset = mXHeight;
02260   }
02261 
02262   /* need better way to calculate this */
02263   mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0);
02264   mStrikeoutSize = mUnderlineSize;
02265 }
02266 
02267 NS_IMETHODIMP  nsFontMetricsXlib::GetXHeight(nscoord& aResult)
02268 {
02269   aResult = mXHeight;
02270   return NS_OK;
02271 }
02272 
02273 NS_IMETHODIMP  nsFontMetricsXlib::GetSuperscriptOffset(nscoord& aResult)
02274 {
02275   aResult = mSuperscriptOffset;
02276   return NS_OK;
02277 }
02278 
02279 NS_IMETHODIMP  nsFontMetricsXlib::GetSubscriptOffset(nscoord& aResult)
02280 {
02281   aResult = mSubscriptOffset;
02282   return NS_OK;
02283 }
02284 
02285 NS_IMETHODIMP  nsFontMetricsXlib::GetStrikeout(nscoord& aOffset, nscoord& aSize)
02286 {
02287   aOffset = mStrikeoutOffset;
02288   aSize = mStrikeoutSize;
02289   return NS_OK;
02290 }
02291 
02292 NS_IMETHODIMP  nsFontMetricsXlib::GetUnderline(nscoord& aOffset, nscoord& aSize)
02293 {
02294   aOffset = mUnderlineOffset;
02295   aSize = mUnderlineSize;
02296   return NS_OK;
02297 }
02298 
02299 NS_IMETHODIMP  nsFontMetricsXlib::GetHeight(nscoord &aHeight)
02300 {
02301   aHeight = mMaxHeight;
02302   return NS_OK;
02303 }
02304 
02305 NS_IMETHODIMP  nsFontMetricsXlib::GetNormalLineHeight(nscoord &aHeight)
02306 {
02307   aHeight = mEmHeight + mLeading;
02308   return NS_OK;
02309 }
02310 
02311 NS_IMETHODIMP  nsFontMetricsXlib::GetLeading(nscoord &aLeading)
02312 {
02313   aLeading = mLeading;
02314   return NS_OK;
02315 }
02316 
02317 NS_IMETHODIMP  nsFontMetricsXlib::GetEmHeight(nscoord &aHeight)
02318 {
02319   aHeight = mEmHeight;
02320   return NS_OK;
02321 }
02322 
02323 NS_IMETHODIMP  nsFontMetricsXlib::GetEmAscent(nscoord &aAscent)
02324 {
02325   aAscent = mEmAscent;
02326   return NS_OK;
02327 }
02328 
02329 NS_IMETHODIMP  nsFontMetricsXlib::GetEmDescent(nscoord &aDescent)
02330 {
02331   aDescent = mEmDescent;
02332   return NS_OK;
02333 }
02334 
02335 NS_IMETHODIMP  nsFontMetricsXlib::GetMaxHeight(nscoord &aHeight)
02336 {
02337   aHeight = mMaxHeight;
02338   return NS_OK;
02339 }
02340 
02341 NS_IMETHODIMP  nsFontMetricsXlib::GetMaxAscent(nscoord &aAscent)
02342 {
02343   aAscent = mMaxAscent;
02344   return NS_OK;
02345 }
02346 
02347 NS_IMETHODIMP  nsFontMetricsXlib::GetMaxDescent(nscoord &aDescent)
02348 {
02349   aDescent = mMaxDescent;
02350   return NS_OK;
02351 }
02352 
02353 NS_IMETHODIMP  nsFontMetricsXlib::GetMaxAdvance(nscoord &aAdvance)
02354 {
02355   aAdvance = mMaxAdvance;
02356   return NS_OK;
02357 }
02358 
02359 NS_IMETHODIMP nsFontMetricsXlib::GetAveCharWidth(nscoord &aAveCharWidth)
02360 {
02361   aAveCharWidth = mAveCharWidth;
02362   return NS_OK;
02363 }
02364 
02365 NS_IMETHODIMP  nsFontMetricsXlib::GetLangGroup(nsIAtom** aLangGroup)
02366 {
02367   if (!aLangGroup) {
02368     return NS_ERROR_NULL_POINTER;
02369   }
02370 
02371   *aLangGroup = mLangGroup;
02372   NS_IF_ADDREF(*aLangGroup);
02373 
02374   return NS_OK;
02375 }
02376 
02377 NS_IMETHODIMP  nsFontMetricsXlib::GetFontHandle(nsFontHandle &aHandle)
02378 {
02379   aHandle = (nsFontHandle)mWesternFont;
02380   return NS_OK;
02381 }
02382 
02383 nsFontXlib*
02384 nsFontMetricsXlib::LocateFont(PRUint32 aChar, PRInt32 & aCount)
02385 {
02386   nsFontXlib *font;
02387   PRInt32 i;
02388 
02389   // see if one of our loaded fonts can represent the character
02390   for (i = 0; i < aCount; ++i) {
02391     font = (nsFontXlib *)mLoadedFonts[i];
02392     if (CCMAP_HAS_CHAR(font->mCCMap, aChar))
02393       return font;
02394   }
02395 
02396   font = FindFont(aChar);
02397   aCount = mLoadedFontsCount; // update since FindFont() can change it
02398 
02399   return font;
02400 }
02401 
02402 nsresult
02403 nsFontMetricsXlib::ResolveForwards(const PRUnichar*         aString,
02404                                    PRUint32                 aLength,
02405                                    nsFontSwitchCallbackXlib aFunc, 
02406                                    void*                    aData)
02407 {
02408   NS_ASSERTION(aString || !aLength, "invalid call");
02409   const PRUnichar* firstChar = aString;
02410   const PRUnichar* currChar = firstChar;
02411   const PRUnichar* lastChar  = aString + aLength;
02412   nsFontXlib* currFont;
02413   nsFontXlib* nextFont;
02414   PRInt32 count;
02415   nsFontSwitchXlib fontSwitch;
02416 
02417   if (firstChar == lastChar)
02418     return NS_OK;
02419 
02420   count = mLoadedFontsCount;
02421 
02422   if (IS_HIGH_SURROGATE(*currChar) && (currChar+1) < lastChar && IS_LOW_SURROGATE(*(currChar+1))) {
02423     currFont = LocateFont(SURROGATE_TO_UCS4(*currChar, *(currChar+1)), count);
02424     currChar += 2;
02425   }
02426   else {
02427     currFont = LocateFont(*currChar, count);
02428     ++currChar;
02429   }
02430 
02431   //This if block is meant to speedup the process in normal situation, when
02432   //most characters can be found in first font
02433   if (currFont == mLoadedFonts[0]) {
02434     while (currChar < lastChar && CCMAP_HAS_CHAR(currFont->mCCMap,*currChar))
02435       ++currChar;
02436     fontSwitch.mFontXlib = currFont;
02437     if (!(*aFunc)(&fontSwitch, firstChar, currChar - firstChar, aData))
02438       return NS_OK;
02439     if (currChar == lastChar)
02440       return NS_OK;
02441     // continue with the next substring, re-using the available loaded fonts
02442     firstChar = currChar;
02443     if (IS_HIGH_SURROGATE(*currChar) && (currChar+1) < lastChar && IS_LOW_SURROGATE(*(currChar+1))) {
02444       currFont = LocateFont(SURROGATE_TO_UCS4(*currChar, *(currChar+1)), count);
02445       currChar += 2;
02446     }
02447     else {
02448       currFont = LocateFont(*currChar, count);
02449       ++currChar;
02450     }
02451   }
02452 
02453   // see if we can keep the same font for adjacent characters
02454   PRInt32 lastCharLen;
02455   while (currChar < lastChar) {
02456     if (IS_HIGH_SURROGATE(*currChar) && (currChar+1) < lastChar && IS_LOW_SURROGATE(*(currChar+1))) {
02457       nextFont = LocateFont(SURROGATE_TO_UCS4(*currChar, *(currChar+1)), count);
02458       lastCharLen = 2;
02459     }
02460     else {
02461       nextFont = LocateFont(*currChar, count);
02462       lastCharLen = 1;
02463     }
02464     if (nextFont != currFont) {
02465       // We have a substring that can be represented with the same font, and
02466       // we are about to switch fonts, it is time to notify our caller.
02467       fontSwitch.mFontXlib = currFont;
02468       if (!(*aFunc)(&fontSwitch, firstChar, currChar - firstChar, aData))
02469         return NS_OK;
02470       // continue with the next substring, re-using the available loaded fonts
02471       firstChar = currChar;
02472 
02473       currFont = nextFont; // use the font found earlier for the char
02474     }
02475     currChar += lastCharLen;
02476   }
02477 
02478   //do it for last part of the string
02479   fontSwitch.mFontXlib = currFont;
02480   (*aFunc)(&fontSwitch, firstChar, currChar - firstChar, aData);
02481   return NS_OK;
02482 }
02483 
02484 NS_IMETHODIMP
02485 nsFontMetricsXlib::GetSpaceWidth(nscoord &aSpaceWidth)
02486 {
02487   aSpaceWidth = mSpaceWidth;
02488   return NS_OK;
02489 }
02490 
02491 /*
02492  * CSS2 "font properties":
02493  *   font-family
02494  *   font-style
02495  *   font-variant
02496  *   font-weight
02497  *   font-stretch
02498  *   font-size
02499  *   font-size-adjust
02500  *   font
02501  */
02502 
02503 /*
02504  * CSS2 "font descriptors":
02505  *   font-family
02506  *   font-style
02507  *   font-variant
02508  *   font-weight
02509  *   font-stretch
02510  *   font-size
02511  *   unicode-range
02512  *   units-per-em
02513  *   src
02514  *   panose-1
02515  *   stemv
02516  *   stemh
02517  *   slope
02518  *   cap-height
02519  *   x-height
02520  *   ascent
02521  *   descent
02522  *   widths
02523  *   bbox
02524  *   definition-src
02525  *   baseline
02526  *   centerline
02527  *   mathline
02528  *   topline
02529  */
02530 
02531 /*
02532  * XLFD 1.5 "FontName fields":
02533  *   FOUNDRY
02534  *   FAMILY_NAME
02535  *   WEIGHT_NAME
02536  *   SLANT
02537  *   SETWIDTH_NAME
02538  *   ADD_STYLE_NAME
02539  *   PIXEL_SIZE
02540  *   POINT_SIZE
02541  *   RESOLUTION_X
02542  *   RESOLUTION_Y
02543  *   SPACING
02544  *   AVERAGE_WIDTH
02545  *   CHARSET_REGISTRY
02546  *   CHARSET_ENCODING
02547  * XLFD example:
02548  *   -adobe-times-medium-r-normal--17-120-100-100-p-84-iso8859-1
02549  */
02550 
02551 /*
02552  * XLFD 1.5 "font properties":
02553  *   FOUNDRY
02554  *   FAMILY_NAME
02555  *   WEIGHT_NAME
02556  *   SLANT
02557  *   SETWIDTH_NAME
02558  *   ADD_STYLE_NAME
02559  *   PIXEL_SIZE
02560  *   POINT_SIZE
02561  *   RESOLUTION_X
02562  *   RESOLUTION_Y
02563  *   SPACING
02564  *   AVERAGE_WIDTH
02565  *   CHARSET_REGISTRY
02566  *   CHARSET_ENCODING
02567  *   MIN_SPACE
02568  *   NORM_SPACE
02569  *   MAX_SPACE
02570  *   END_SPACE
02571  *   AVG_CAPITAL_WIDTH
02572  *   AVG_LOWERCASE_WIDTH
02573  *   QUAD_WIDTH
02574  *   FIGURE_WIDTH
02575  *   SUPERSCRIPT_X
02576  *   SUPERSCRIPT_Y
02577  *   SUBSCRIPT_X
02578  *   SUBSCRIPT_Y
02579  *   SUPERSCRIPT_SIZE
02580  *   SUBSCRIPT_SIZE
02581  *   SMALL_CAP_SIZE
02582  *   UNDERLINE_POSITION
02583  *   UNDERLINE_THICKNESS
02584  *   STRIKEOUT_ASCENT
02585  *   STRIKEOUT_DESCENT
02586  *   ITALIC_ANGLE
02587  *   CAP_HEIGHT
02588  *   X_HEIGHT
02589  *   RELATIVE_SETWIDTH
02590  *   RELATIVE_WEIGHT
02591  *   WEIGHT
02592  *   RESOLUTION
02593  *   FONT
02594  *   FACE_NAME
02595  *   FULL_NAME
02596  *   COPYRIGHT
02597  *   NOTICE
02598  *   DESTINATION
02599  *   FONT_TYPE
02600  *   FONT_VERSION
02601  *   RASTERIZER_NAME
02602  *   RASTERIZER_VERSION
02603  *   RAW_ASCENT
02604  *   RAW_DESCENT
02605  *   RAW_*
02606  *   AXIS_NAMES
02607  *   AXIS_LIMITS
02608  *   AXIS_TYPES
02609  */
02610 
02611 /*
02612  * XLFD 1.5 BDF 2.1 properties:
02613  *   FONT_ASCENT
02614  *   FONT_DESCENT
02615  *   DEFAULT_CHAR
02616  */
02617 
02618 /*
02619  * CSS2 algorithm, in the following order:
02620  *   font-family:  FAMILY_NAME (and FOUNDRY? (XXX))
02621  *   font-style:   SLANT (XXX: XLFD's RI and RO)
02622  *   font-variant: implemented in mozilla/layout/html/base/src/nsTextFrame.cpp
02623  *   font-weight:  RELATIVE_WEIGHT (XXX), WEIGHT (XXX), WEIGHT_NAME
02624  *   font-size:    XFontStruct.max_bounds.ascent + descent
02625  *
02626  * The following property is not specified in the algorithm spec. It will be
02627  * inserted between the font-weight and font-size steps for now:
02628  *   font-stretch: RELATIVE_SETWIDTH (XXX), SETWIDTH_NAME
02629  */
02630 
02631 /*
02632  * XXX: Things to investigate in the future:
02633  *   ADD_STYLE_NAME font-family's serif and sans-serif
02634  *   SPACING        font-family's monospace; however, there are very few
02635  *                  proportional fonts in non-Latin-1 charsets, so beware in
02636  *                  font prefs dialog
02637  *   AVERAGE_WIDTH  none (see SETWIDTH_NAME)
02638  */
02639 
02640 static int
02641 SingleByteConvert(nsFontCharSetInfoXlib* aSelf, XFontStruct* aFont,
02642   const PRUnichar* aSrcBuf, PRInt32 aSrcLen, char* aDestBuf, PRInt32 aDestLen)
02643 {
02644   int count = 0;
02645   if (aSelf->mConverter) {
02646     aSelf->mConverter->Convert(aSrcBuf, &aSrcLen, aDestBuf, &aDestLen);
02647     count = aDestLen;
02648   }
02649 
02650   return count;
02651 }
02652 
02653 /*
02654 static void 
02655 ReverseBuffer(char* aBuf, int count)
02656 {
02657     char *head, *tail, *med;
02658     head = aBuf;
02659     tail = &aBuf[count-1];
02660     med = &aBuf[count/2];
02661 
02662     while(head < med)
02663     {
02664        char tmp = *head;
02665        *head++ = *tail;
02666        *tail-- = tmp;
02667     }
02668 }
02669 */
02670 
02671 // the following code assume all the PRUnichar is draw in the same
02672 // direction- left to right, without mixing with characters which should
02673 // draw from right to left. This mean it should not be used untill the 
02674 // upper level code resolve bi-di and ensure this assumption. otherwise
02675 // it may break non-bidi pages on a system which have hebrew/arabic fonts
02676 /*
02677 static int
02678 SingleByteConvertReverse(nsFontCharSetInfoXlib* aSelf, const PRUnichar* aSrcBuf,
02679   PRInt32 aSrcLen, char* aDestBuf, PRInt32 aDestLen)
02680 {
02681     int count = SingleByteConvert(aSelf, aSrcBuf,
02682                                   aSrcLen, aDestBuf,  aDestLen);
02683     ReverseBuffer(aDestBuf, count);
02684     return count;
02685 }
02686 */
02687 
02688 static int
02689 DoubleByteConvert(nsFontCharSetInfoXlib* aSelf, XFontStruct* aFont,
02690   const PRUnichar* aSrcBuf, PRInt32 aSrcLen, char* aDestBuf, PRInt32 aDestLen)
02691 {
02692   int count;
02693   if (aSelf->mConverter) {
02694     aSelf->mConverter->Convert(aSrcBuf, &aSrcLen, aDestBuf, &aDestLen);
02695     count = aDestLen;
02696     if (count > 0) {
02697       if ((aDestBuf[0] & 0x80) && (!(aFont->max_byte1 & 0x80))) {
02698         for (PRInt32 i = 0; i < aDestLen; i++)
02699           aDestBuf[i] &= 0x7F;
02700       }
02701       // We're using a GL encoder (KSC5601 or GB2312) for a GR font
02702       // (ksc5601.1987-1 or gb2312.1980-1)
02703       else if ((!(aDestBuf[0] & 0x80)) && (aFont->min_byte1 & 0x80)) {
02704         for (PRInt32 i = 0; i < aDestLen; i++)
02705           aDestBuf[i] |= 0x80;
02706       }
02707     }
02708   }
02709   else {
02710     count = 0;
02711   }
02712 
02713   return count;
02714 }
02715 
02716 static int
02717 ISO10646Convert(nsFontCharSetInfoXlib* aSelf, XFontStruct* aFont,
02718   const PRUnichar* aSrcBuf, PRInt32 aSrcLen, char* aDestBuf, PRInt32 aDestLen)
02719 {
02720   aDestLen /= 2;
02721   if (aSrcLen > aDestLen) {
02722     aSrcLen = aDestLen;
02723   }
02724   if (aSrcLen < 0) {
02725     aSrcLen = 0;
02726   }
02727   XChar2b* dest = (XChar2b*) aDestBuf;
02728   for (PRInt32 i = 0; i < aSrcLen; i++) {
02729     dest[i].byte1 = (aSrcBuf[i] >> 8);
02730     dest[i].byte2 = (aSrcBuf[i] & 0xFF);
02731   }
02732 
02733   return (int) aSrcLen * 2;
02734 }
02735 
02736 #ifdef DEBUG
02737 
02738 static void
02739 CheckMap(nsFontMetricsXlibContext *aFmctx, const nsFontCharSetMapXlib* aEntry)
02740 {
02741   while (aEntry->mName) {
02742     if (aEntry->mInfo->mCharSet) {
02743       
02744         nsresult res;
02745         // used to use NS_NewAtom??
02746         nsCOMPtr<nsIUnicodeEncoder> converter;
02747         res = aFmctx->mCharSetManager->GetUnicodeEncoderRaw(aEntry->mInfo->mCharSet,
02748           getter_AddRefs(converter));
02749         if (NS_FAILED(res)) {
02750           printf("=== %s failed (%s)\n", aEntry->mInfo->mCharSet, __FILE__);
02751         }
02752     }
02753     aEntry++;
02754   }
02755 }
02756 
02757 static void
02758 CheckSelf(nsFontMetricsXlibContext *aFmctx)
02759 {
02760   CheckMap(aFmctx, aFmctx->mCharSetMap);
02761 
02762 #ifdef MOZ_MATHML
02763   // For this to pass, the ucvmath module must be built as well
02764   CheckMap(aFmctx, aFmctx->mSpecialCharSetMap);
02765 #endif /* MOZ_MATHML */
02766 }
02767 
02768 #endif /* DEBUG */
02769 
02770 static PRBool
02771 SetUpFontCharSetInfo(nsFontMetricsXlibContext *aFmctx, nsFontCharSetInfoXlib* aSelf)
02772 {
02773 #ifdef DEBUG
02774   static PRBool checkedSelf = PR_FALSE;
02775   if (!checkedSelf) {
02776     CheckSelf(aFmctx);
02777     checkedSelf = PR_TRUE;
02778   }
02779 #endif /* DEBUG */
02780 
02781   nsresult res;
02782   
02783   nsIUnicodeEncoder* converter = nsnull;
02784   res = aFmctx->mCharSetManager->GetUnicodeEncoderRaw(aSelf->mCharSet, &converter);
02785   if (NS_SUCCEEDED(res)) {
02786     aSelf->mConverter = converter;
02787     res = converter->SetOutputErrorBehavior(converter->kOnError_Replace,
02788                                             nsnull, '?');
02789     nsCOMPtr<nsICharRepresentable> mapper = do_QueryInterface(converter);
02790     if (mapper) {
02791       aSelf->mCCMap = MapperToCCMap(mapper);
02792       if (aSelf->mCCMap) {
02793 #ifdef DEBUG
02794         NS_WARNING(nsPrintfCString(256, "SetUpFontCharSetInfo: charset = '%s'", aSelf->mCharSet).get());
02795 #endif /* DEBUG */
02796 
02797         /*
02798          * We used to disable special characters like smart quotes
02799          * in CJK fonts because if they are quite a bit larger than
02800          * western glyphs and we did not want glyph fill-in to use them
02801          * in single byte documents.
02802          *
02803          * Now, single byte documents find these special chars before
02804          * the CJK fonts are searched so this is no longer needed
02805          * but is useful when trying to determine which font(s) the
02806          * special chars are found in.
02807          */
02808         if ((aSelf->Convert == DoubleByteConvert) 
02809             && (!aFmctx->mAllowDoubleByteSpecialChars)) {
02810           PRUint16* ccmap = aSelf->mCCMap;
02811           PRUint32 page = CCMAP_BEGIN_AT_START_OF_MAP;
02812           const PRUint16* specialmap = aFmctx->mDoubleByteSpecialCharsCCMap;
02813           while (NextNonEmptyCCMapPage(specialmap, &page)) {
02814             PRUint32 pagechar = page;
02815             for (int i=0; i < CCMAP_BITS_PER_PAGE; i++) {
02816               if (CCMAP_HAS_CHAR(specialmap, pagechar)) 
02817                 CCMAP_UNSET_CHAR(ccmap, pagechar);
02818               pagechar++;
02819             }
02820           }
02821         }
02822         return PR_TRUE;
02823       }
02824     }
02825     else {
02826       NS_WARNING("cannot get nsICharRepresentable");
02827     }
02828   }
02829   else {
02830     NS_WARNING("cannot get Unicode converter");
02831   }
02832 
02833   //
02834   // always try to return a map even if it is empty
02835   //
02836   nsCompressedCharMap empty_ccmapObj;
02837   aSelf->mCCMap = empty_ccmapObj.NewCCMap();
02838 
02839   // return false if unable to alloc a map
02840   if (aSelf->mCCMap == nsnull)
02841     return PR_FALSE;
02842 
02843   return PR_TRUE;
02844 }
02845 
02846 #undef DEBUG_DUMP_TREE
02847 #ifdef DEBUG_DUMP_TREE
02848 
02849 static char* gDumpStyles[3] = { "normal", "italic", "oblique" };
02850 
02851 static PRIntn
02852 DumpCharSet(PLHashEntry* he, PRIntn i, void* arg)
02853 {
02854   printf("        %s\n", (char*) he->key);
02855   nsFontCharSetXlib* charSet = (nsFontCharSetXlib*) he->value;
02856   for (int sizeIndex = 0; sizeIndex < charSet->mSizesCount; sizeIndex++) {
02857     nsFontXlib* size = &charSet->mSizes[sizeIndex];
02858     printf("          %d %s\n", size->mSize, size->mName);
02859   }
02860   return HT_ENUMERATE_NEXT;
02861 }
02862 
02863 static void
02864 DumpFamily(nsFontFamilyXlib* aFamily)
02865 {
02866   for (int styleIndex = 0; styleIndex < 3; styleIndex++) {
02867     nsFontStyleXlib* style = aFamily->mStyles[styleIndex];
02868     if (style) {
02869       printf("  style: %s\n", gDumpStyles[styleIndex]);
02870       for (int weightIndex = 0; weightIndex < 8; weightIndex++) {
02871         nsFontWeightXlib* weight = style->mWeights[weightIndex];
02872         if (weight) {
02873           printf("    weight: %d\n", (weightIndex + 1) * 100);
02874           for (int stretchIndex = 0; stretchIndex < 9; stretchIndex++) {
02875             nsFontStretchXlib* stretch = weight->mStretches[stretchIndex];
02876             if (stretch) {
02877               printf("      stretch: %d\n", stretchIndex + 1);
02878               PL_HashTableEnumerateEntries(stretch->mCharSets, DumpCharSet,
02879                 nsnull);
02880             }
02881           }
02882         }
02883       }
02884     }
02885   }
02886 }
02887 
02888 // this existing debug code was broken and I have partly fixed it
02889 static PRBool
02890 DumpFamilyEnum(nsHashKey* hashKey, void *aData, void* closure)
02891 {
02892   printf("family: %s\n",
02893          NS_LossyConvertUCS2toASCII(*NS_STATIC_CAST(nsString*,he->key)));
02894   nsFontFamilyXlib* family = (nsFontFamilyXlib*) he->value;
02895   DumpFamily(family);
02896 
02897   return HT_ENUMERATE_NEXT;
02898 }
02899 
02900 static void
02901 DumpTree(void)
02902 {
02903   aFmctx->mFamilies.Enumerate(DumpFamilyEnum, nsnull);
02904 }
02905 #endif /* DEBUG_DUMP_TREE */
02906 
02907 struct nsFontSearch
02908 {
02909   nsFontMetricsXlib *mMetrics;
02910   PRUnichar          mChar;
02911   nsFontXlib        *mFont;
02912 };
02913 
02914 #if 0
02915 static void
02916 GetUnderlineInfo(nsXFont* aFont, unsigned long* aPositionX2,
02917   unsigned long* aThickness)
02918 {
02919   /*
02920    * XLFD 1.5 says underline position defaults descent/2.
02921    * Hence we return position*2 to avoid rounding error.
02922    */
02923   if (aFont->GetXFontProperty(XA_UNDERLINE_POSITION, aPositionX2)) {
02924     *aPositionX2 *= 2;
02925   }
02926   else {
02927     *aPositionX2 = aFont->max_bounds.descent;
02928   }
02929 
02930   /*
02931    * XLFD 1.5 says underline thickness defaults to cap stem width.
02932    * We don't know what that is, so we just take the thickness of "_".
02933    * This way, we get thicker underlines for bold fonts.
02934    */
02935   if (!xFont->GetXFontProperty(XA_UNDERLINE_THICKNESS, aThickness)) {
02936     int dir, ascent, descent;
02937     XCharStruct overall;
02938     XTextExtents(aFont, "_", 1, &dir, &ascent, &descent, &overall);
02939     *aThickness = (overall.ascent + overall.descent);
02940   }
02941 }
02942 #endif /* 0 */
02943 
02944 static PRUint16*
02945 GetMapFor10646Font(XFontStruct* aFont)
02946 {
02947   if (!aFont->per_char)
02948     return nsnull;
02949 
02950   nsCompressedCharMap ccmapObj;
02951   PRInt32 minByte1 = aFont->min_byte1;
02952   PRInt32 maxByte1 = aFont->max_byte1;
02953   PRInt32 minByte2 = aFont->min_char_or_byte2;
02954   PRInt32 maxByte2 = aFont->max_char_or_byte2;
02955   PRInt32 charsPerRow = maxByte2 - minByte2 + 1;
02956   for (PRInt32 row = minByte1; row <= maxByte1; row++) {
02957     PRInt32 offset = (((row - minByte1) * charsPerRow) - minByte2);
02958     for (PRInt32 cell = minByte2; cell <= maxByte2; cell++) {
02959       XCharStruct* bounds = &aFont->per_char[offset + cell];
02960       // From Section 8.5 Font Metrics in the Xlib programming manual:
02961       // A nonexistent character is represented with all members of its XCharStruct set to zero. 
02962       if (bounds->ascent ||
02963           bounds->descent ||
02964           bounds->lbearing ||
02965           bounds->rbearing ||
02966           bounds->width ||
02967           bounds->attributes) {
02968         ccmapObj.SetChar((row << 8) | cell);
02969       }
02970     }
02971   }
02972   PRUint16 *ccmap = ccmapObj.NewCCMap();
02973   return ccmap;
02974 }
02975 
02976 PRBool
02977 nsFontXlib::IsEmptyFont(XFontStruct* xFont)
02978 {
02979   if (!xFont)
02980     return PR_TRUE;
02981 
02982   //
02983   // scan and see if we can find at least one glyph
02984   //
02985   if (xFont->per_char) {
02986     PRInt32 minByte1 = xFont->min_byte1;
02987     PRInt32 maxByte1 = xFont->max_byte1;
02988     PRInt32 minByte2 = xFont->min_char_or_byte2;
02989     PRInt32 maxByte2 = xFont->max_char_or_byte2;
02990     PRInt32 charsPerRow = maxByte2 - minByte2 + 1;
02991     for (PRInt32 row = minByte1; row <= maxByte1; row++) {
02992       PRInt32 offset = (((row - minByte1) * charsPerRow) - minByte2);
02993       for (PRInt32 cell = minByte2; cell <= maxByte2; cell++) {
02994         XCharStruct* bounds = &xFont->per_char[offset + cell];
02995         if (bounds->ascent || bounds->descent) {
02996           return PR_FALSE;
02997         }
02998       }
02999     }
03000   }
03001 
03002   return PR_TRUE;
03003 }
03004 
03005 void
03006 nsFontXlib::LoadFont(void)
03007 {
03008   if (mAlreadyCalledLoadFont)
03009     return;
03010 
03011   Display *aDisplay = xxlib_rgb_get_display(mFontMetricsContext->mXlibRgbHandle);
03012 
03013 #ifdef USE_XPRINT
03014   if (mFontMetricsContext->mPrinterMode)
03015   {
03016     if (XpGetContext(aDisplay) == None)
03017     {
03018       /* applications must not make any assumptions about fonts _before_ XpSetContext() !!! */
03019       NS_ERROR("Obtaining font information without a valid print context (XLoadQueryFont()) _before_ XpSetContext()\n");
03020 #ifdef DEBUG
03021       abort();
03022 #else
03023       return;
03024 #endif /* DEBUG */      
03025     }
03026   }
03027 #endif /* USE_XPRINT */
03028 
03029   mAlreadyCalledLoadFont = PR_TRUE;
03030 
03031   XFontStruct *xlibFont = nsnull;
03032 
03033   NS_ASSERTION(!mFont, "mFont should not be loaded");
03034 #ifdef USE_AASB
03035   if (mAABaseSize==0)
03036 #endif /* USE_AASB */
03037   {
03038     NS_ASSERTION(!mFontHolder, "mFontHolder should not be loaded");
03039     xlibFont = ::XLoadQueryFont(aDisplay, mName);
03040     if(!xlibFont)
03041     {
03042 #ifdef DEBUG
03043       printf("nsFontXlib::LoadFont(): loading of font '%s' failed\n", mName);
03044 #endif /* DEBUG */
03045       return;
03046     }
03047 
03048     mXFont = new nsXFontNormal(aDisplay, xlibFont);
03049   }
03050 #ifdef USE_AASB
03051   else {
03052     NS_ASSERTION(mFontHolder, "mFontHolder should be loaded");
03053     xlibFont = mFontHolder;
03054     mXFont = new nsXFontAAScaledBitmap(xxlib_rgb_get_display(mFontMetricsContext->mXlibRgbHandle),
03055                                        xxlib_rgb_get_screen(mFontMetricsContext->mXlibRgbHandle),
03056                                        xlibFont, mSize, mAABaseSize);
03057   }
03058 #endif /* USE_AASB */
03059 
03060   NS_ASSERTION(mXFont,"failed to load mXFont");
03061   if (!mXFont)
03062     return;
03063   if (!mXFont->LoadFont()) {
03064     delete mXFont;
03065     mXFont = nsnull;
03066     return;
03067   }
03068 
03069   if (xlibFont) {
03070     XFontStruct* xFont = mXFont->GetXFontStruct();
03071     XFontStruct* xFont_with_per_char;
03072 #ifdef USE_AASB
03073     if (mAABaseSize==0)
03074 #endif /* USE_AASB */
03075       xFont_with_per_char = xFont;
03076 #ifdef USE_AASB
03077     else
03078       xFont_with_per_char = mFontHolder;
03079 #endif /* #ifdef USE_AASB */
03080 
03081     mMaxAscent = xFont->ascent;
03082     mMaxDescent = xFont->descent;
03083 
03084     if (mCharSetInfo == mFontMetricsContext->mISO106461) {
03085       mCCMap = GetMapFor10646Font(xFont_with_per_char);
03086       if (!mCCMap) {
03087         mXFont->UnloadFont();
03088         mXFont = nsnull;
03089         ::XFreeFont(aDisplay, xlibFont);
03090         mFontHolder = nsnull;
03091         return;
03092       }
03093     }
03094 
03095     // Redhat 6.2 Japanese has invalid jisx201 fonts
03096     // Solaris 2.6 has invalid cns11643 fonts for planes 4-7
03097     if ((mCharSetInfo == &JISX0201)
03098         || (mCharSetInfo == &CNS116434)
03099         || (mCharSetInfo == &CNS116435)
03100         || (mCharSetInfo == &CNS116436)
03101         || (mCharSetInfo == &CNS116437)
03102        ) {
03103       if (IsEmptyFont(xFont_with_per_char)) {
03104 #ifdef NS_FONT_DEBUG_LOAD_FONT
03105         if (gFontDebug & NS_FONT_DEBUG_LOAD_FONT) {
03106           printf("\n");
03107           printf("***************************************\n");
03108           printf("invalid font \"%s\", %s %d\n", mName, __FILE__, __LINE__);
03109           printf("***************************************\n");
03110           printf("\n");
03111         }
03112 #endif
03113         mXFont->UnloadFont();
03114         mXFont = nsnull;
03115         ::XFreeFont(aDisplay, xlibFont);
03116         mFontHolder = nsnull;
03117         return;
03118       }
03119     }
03120     mFont = xlibFont;
03121 
03122 #ifdef NS_FONT_DEBUG_LOAD_FONT
03123     if (gFontDebug & NS_FONT_DEBUG_LOAD_FONT) {
03124       printf("loaded %s\n", mName);
03125     }
03126 #endif
03127 
03128   }
03129 
03130 #ifdef NS_FONT_DEBUG_LOAD_FONT
03131   else if (gFontDebug & NS_FONT_DEBUG_LOAD_FONT) {
03132     printf("cannot load %s\n", mName);
03133   }
03134 #endif
03135 
03136 }
03137 
03138 XFontStruct *
03139 nsFontXlib::GetXFontStruct(void)
03140 {
03141   return mFont;
03142 }
03143 
03144 nsXFont*
03145 nsFontXlib::GetXFont(void)
03146 {
03147   return mXFont;
03148 }
03149 
03150 PRBool
03151 nsFontXlib::GetXFontIs10646(void)
03152 {
03153   return ((PRBool) (mCharSetInfo == mFontMetricsContext->mISO106461));
03154 }
03155 
03156 #ifdef MOZ_ENABLE_FREETYPE2
03157 PRBool
03158 nsFontXlib::IsFreeTypeFont(void)
03159 {
03160   return PR_FALSE;
03161 }
03162 #endif /* MOZ_ENABLE_FREETYPE2 */
03163 
03164 MOZ_DECL_CTOR_COUNTER(nsFontXlib)
03165 
03166 nsFontXlib::nsFontXlib()
03167 {
03168   MOZ_COUNT_CTOR(nsFontXlib);
03169 }
03170 
03171 nsFontXlib::~nsFontXlib()
03172 {
03173   MOZ_COUNT_DTOR(nsFontXlib);
03174   if (mXFont) {
03175     delete mXFont;
03176   }
03177   if (mFont 
03178 #ifdef USE_AASB
03179       && (mAABaseSize==0)
03180 #endif /* USE_AASB */
03181       ) {
03182     XFreeFont(xxlib_rgb_get_display(mFontMetricsContext->mXlibRgbHandle), mFont);
03183   }
03184   if (mCharSetInfo == mFontMetricsContext->mISO106461) {
03185     FreeCCMap(mCCMap);
03186   }
03187   if (mName) {
03188     PR_smprintf_free(mName);
03189   }
03190 }
03191 
03192 class nsFontXlibNormal : public nsFontXlib
03193 {
03194 public:
03195   nsFontXlibNormal(nsFontMetricsXlibContext *aFontMetricsContext);
03196   nsFontXlibNormal(nsFontXlib*);
03197   virtual ~nsFontXlibNormal();
03198 
03199   virtual int GetWidth(const PRUnichar* aString, PRUint32 aLength);
03200   virtual int DrawString(nsRenderingContextXlib* aContext,
03201                          nsIDrawingSurfaceXlib* aSurface, nscoord aX,
03202                          nscoord aY, const PRUnichar* aString,
03203                          PRUint32 aLength);
03204 #ifdef MOZ_MATHML
03205   virtual nsresult GetBoundingMetrics(const PRUnichar*   aString,
03206                                       PRUint32           aLength,
03207                                       nsBoundingMetrics& aBoundingMetrics);
03208 #endif /* MOZ_MATHML */
03209 };
03210 
03211 nsFontXlibNormal::nsFontXlibNormal(nsFontMetricsXlibContext *aFontMetricsContext)
03212 {
03213   mFontHolder = nsnull;
03214   mFontMetricsContext = aFontMetricsContext;
03215 }
03216 
03217 nsFontXlibNormal::nsFontXlibNormal(nsFontXlib *aFont)
03218 {
03219   mFontMetricsContext = aFont->mFontMetricsContext;
03220 
03221 #ifdef USE_AASB
03222   mAABaseSize = aFont->mSize;
03223 #endif /* USE_AASB */
03224   mFontHolder = aFont->GetXFontStruct();
03225   if (!mFontHolder) {
03226     aFont->LoadFont();
03227     mFontHolder = aFont->GetXFontStruct();
03228   }
03229   NS_ASSERTION(mFontHolder, "font to copy not loaded");
03230 }
03231 
03232 nsFontXlibNormal::~nsFontXlibNormal()
03233 {
03234 }
03235 
03236 int
03237 nsFontXlibNormal::GetWidth(const PRUnichar* aString, PRUint32 aLength)
03238 {
03239   if (!mFont) {
03240     LoadFont();
03241     if (!mFont) {
03242       return 0;
03243     }
03244   }
03245 
03246   XChar2b buf[512];
03247   char *p;
03248   PRInt32 bufLen;
03249   ENCODER_BUFFER_ALLOC_IF_NEEDED(p, mCharSetInfo->mConverter,
03250                          aString, aLength, buf, sizeof(buf), bufLen);
03251   int len = mCharSetInfo->Convert(mCharSetInfo, mXFont->GetXFontStruct(),
03252                                   aString, aLength, p, bufLen);
03253   int outWidth;
03254   if (mXFont->IsSingleByte())
03255     outWidth = mXFont->TextWidth8(p, len);
03256   else
03257     outWidth = mXFont->TextWidth16((const XChar2b*)p, len/2);
03258   ENCODER_BUFFER_FREE_IF_NEEDED(p, buf);
03259   return outWidth;
03260 }
03261 
03262 int
03263 nsFontXlibNormal::DrawString(nsRenderingContextXlib* aContext,
03264                              nsIDrawingSurfaceXlib* aSurface,
03265                              nscoord aX, nscoord aY,
03266                              const PRUnichar* aString, PRUint32 aLength)
03267 {
03268   if (!mFont) {
03269     LoadFont();
03270     if (!mFont) {
03271       return 0;
03272     }
03273   }
03274 
03275   XChar2b buf[512];
03276   char *p;
03277   PRInt32 bufLen;
03278   ENCODER_BUFFER_ALLOC_IF_NEEDED(p, mCharSetInfo->mConverter,
03279                          aString, aLength, buf, sizeof(buf), bufLen);
03280   int len = mCharSetInfo->Convert(mCharSetInfo, mXFont->GetXFontStruct(),
03281                                   aString, aLength, p, bufLen);
03282   xGC *gc = aContext->GetGC();
03283   int outWidth;
03284   if (mXFont->IsSingleByte()) {
03285     mXFont->DrawText8(aSurface->GetDrawable(), *gc, aX,
03286                                           aY + mBaselineAdjust, p, len);
03287     outWidth = mXFont->TextWidth8(p, len);
03288   }
03289   else {
03290     mXFont->DrawText16(aSurface->GetDrawable(), *gc, aX, aY + mBaselineAdjust,
03291                        (const XChar2b*)p, len/2);
03292     outWidth = mXFont->TextWidth16((const XChar2b*)p, len/2);
03293   }
03294   gc->Release();
03295   ENCODER_BUFFER_FREE_IF_NEEDED(p, buf);
03296   return outWidth;
03297 }
03298 
03299 #ifdef MOZ_MATHML
03300 // bounding metrics for a string 
03301 // remember returned values are not in app units
03302 nsresult
03303 nsFontXlibNormal::GetBoundingMetrics(const PRUnichar*   aString,
03304                                      PRUint32           aLength,
03305                                      nsBoundingMetrics& aBoundingMetrics)                                 
03306 {
03307   aBoundingMetrics.Clear();               
03308 
03309   if (!mFont) {
03310     LoadFont();
03311     if (!mFont) {
03312       return NS_ERROR_FAILURE;
03313     }
03314   }
03315 
03316   if (aString && 0 < aLength) {
03317     XFontStruct *fontInfo = mXFont->GetXFontStruct();
03318     XChar2b buf[512];
03319     char *p;
03320     PRInt32 bufLen;
03321     ENCODER_BUFFER_ALLOC_IF_NEEDED(p, mCharSetInfo->mConverter,
03322                          aString, aLength, buf, sizeof(buf), bufLen);
03323     int len = mCharSetInfo->Convert(mCharSetInfo, fontInfo, aString, aLength,
03324                                     p, bufLen);
03325     if (mXFont->IsSingleByte()) {
03326       mXFont->TextExtents8(p, len,
03327                            &aBoundingMetrics.leftBearing,
03328                            &aBoundingMetrics.rightBearing,
03329                            &aBoundingMetrics.width,
03330                            &aBoundingMetrics.ascent,
03331                            &aBoundingMetrics.descent);
03332     }
03333     else {
03334       mXFont->TextExtents16((const XChar2b*)p, len,
03335                            &aBoundingMetrics.leftBearing,
03336                            &aBoundingMetrics.rightBearing,
03337                            &aBoundingMetrics.width,
03338                            &aBoundingMetrics.ascent,
03339                            &aBoundingMetrics.descent);
03340     }
03341     ENCODER_BUFFER_FREE_IF_NEEDED(p, buf);
03342   }
03343 
03344   return NS_OK;
03345 }
03346 #endif /* MOZ_MATHML */
03347 
03348 class nsFontXlibSubstitute : public nsFontXlib
03349 {
03350 public:
03351   nsFontXlibSubstitute(nsFontXlib* aFont);
03352   virtual ~nsFontXlibSubstitute();
03353 
03354   virtual XFontStruct *GetXFontStruct(void);
03355   virtual nsXFont     *GetXFont(void);
03356   virtual PRBool       GetXFontIs10646(void);
03357   virtual int          GetWidth(const PRUnichar* aString, PRUint32 aLength);
03358   virtual int          DrawString(nsRenderingContextXlib* aContext,
03359                                   nsIDrawingSurfaceXlib* aSurface, nscoord aX,
03360                                   nscoord aY, const PRUnichar* aString,
03361                                   PRUint32 aLength);
03362 #ifdef MOZ_MATHML
03363   virtual nsresult GetBoundingMetrics(const PRUnichar*   aString,
03364                                       PRUint32           aLength,
03365                                       nsBoundingMetrics& aBoundingMetrics);
03366 #endif /* MOZ_MATHML */
03367   virtual PRUint32 Convert(const PRUnichar* aSrc, PRUint32 aSrcLen,
03368                            PRUnichar* aDest, PRUint32 aDestLen);
03369 
03370   nsFontXlib* mSubstituteFont;
03371 };
03372 
03373 nsFontXlibSubstitute::nsFontXlibSubstitute(nsFontXlib* aFont)
03374 {
03375   mSubstituteFont = aFont;
03376   mFontMetricsContext = aFont->mFontMetricsContext;
03377 }
03378 
03379 nsFontXlibSubstitute::~nsFontXlibSubstitute()
03380 {
03381   // Do not free mSubstituteFont here. It is owned by somebody else.
03382 }
03383 
03384 PRUint32
03385 nsFontXlibSubstitute::Convert(const PRUnichar* aSrc, PRUint32 aSrcLen,
03386   PRUnichar* aDest, PRUint32 aDestLen)
03387 {
03388   nsresult res;
03389   if (!mFontMetricsContext->mFontSubConverter) {
03390     mFontMetricsContext->mFontSubConverter = do_CreateInstance(NS_SAVEASCHARSET_CONTRACTID);
03391     if (mFontMetricsContext->mFontSubConverter) {
03392       res = mFontMetricsContext->mFontSubConverter->Init("ISO-8859-1",
03393                              nsISaveAsCharset::attr_FallbackQuestionMark +
03394                                nsISaveAsCharset::attr_EntityAfterCharsetConv +
03395                                nsISaveAsCharset::attr_IgnoreIgnorables,
03396                              nsIEntityConverter::transliterate);
03397       if (NS_FAILED(res))
03398         mFontMetricsContext->mFontSubConverter = nsnull; // destroy converter
03399     }
03400   }
03401 
03402   if (mFontMetricsContext->mFontSubConverter) {
03403     nsAutoString tmp(aSrc, aSrcLen);
03404     char* conv = nsnull;
03405 
03406     /* timecop revisit with nsXPIDLCString */
03407     res = mFontMetricsContext->mFontSubConverter->Convert(tmp.get(), &conv);
03408     if (NS_SUCCEEDED(res) && conv) {
03409       char *p = conv;
03410       PRUint32 i;
03411       for (i = 0; i < aDestLen; i++) {
03412         if (*p) {
03413           aDest[i] = *p;
03414         }
03415         else {
03416           break;
03417         }
03418         p++;
03419       }
03420       nsMemory::Free(conv);
03421       conv = nsnull;
03422       return i;
03423     }
03424   }
03425 
03426   if (aSrcLen > aDestLen) {
03427     aSrcLen = aDestLen;
03428   }
03429   for (PRUint32 i = 0; i < aSrcLen; i++)
03430     aDest[i] = '?';
03431 
03432   return aSrcLen;
03433 }
03434 
03435 int
03436 nsFontXlibSubstitute::GetWidth(const PRUnichar* aString, PRUint32 aLength)
03437 {
03438   PRUnichar buf[512];
03439   PRUnichar *p = buf;
03440   PRUint32 bufLen = sizeof(buf)/sizeof(PRUnichar);
03441   if ((aLength*2) > bufLen) {
03442     PRUnichar *tmp;
03443     tmp = (PRUnichar*)nsMemory::Alloc(sizeof(PRUnichar) * (aLength*2));
03444     if (tmp) {
03445       p = tmp;
03446       bufLen = (aLength*2);
03447     }
03448   }
03449   PRUint32 len = Convert(aString, aLength, p, bufLen);
03450   int outWidth = mSubstituteFont->GetWidth(p, len);
03451   if (p != buf)
03452     nsMemory::Free(p);
03453   return outWidth;
03454 
03455 }
03456 
03457 int
03458 nsFontXlibSubstitute::DrawString(nsRenderingContextXlib* aContext,
03459                                  nsIDrawingSurfaceXlib* aSurface,
03460                                  nscoord aX, nscoord aY,
03461                                  const PRUnichar* aString, PRUint32 aLength)
03462 {
03463   PRUnichar buf[512];
03464   PRUnichar *p = buf;
03465   PRUint32 bufLen = sizeof(buf)/sizeof(PRUnichar);
03466   if ((aLength*2) > bufLen) {
03467     PRUnichar *tmp;
03468     tmp = (PRUnichar*)nsMemory::Alloc(sizeof(PRUnichar) * (aLength*2));
03469     if (tmp) {
03470       p = tmp;
03471       bufLen = (aLength*2);
03472     }
03473   }
03474   PRUint32 len = Convert(aString, aLength, p, bufLen);
03475   int outWidth = mSubstituteFont->DrawString(aContext, aSurface, 
03476                                              aX, aY, p, len);
03477   if (p != buf)
03478     nsMemory::Free(p);
03479   return outWidth;
03480 }
03481 
03482 #ifdef MOZ_MATHML
03483 // bounding metrics for a string 
03484 // remember returned values are not in app units
03485 nsresult
03486 nsFontXlibSubstitute::GetBoundingMetrics(const PRUnichar*   aString,
03487                                          PRUint32           aLength,
03488                                          nsBoundingMetrics& aBoundingMetrics)                                 
03489 {
03490   PRUnichar buf[512];
03491   PRUnichar *p = buf;
03492   PRUint32 bufLen = sizeof(buf)/sizeof(PRUnichar);
03493   if ((aLength*2) > bufLen) {
03494     PRUnichar *tmp;
03495     tmp = (PRUnichar*)nsMemory::Alloc(sizeof(PRUnichar) * (aLength*2));
03496     if (tmp) {
03497       p = tmp;
03498       bufLen = (aLength*2);
03499     }
03500   }
03501   PRUint32 len = Convert(aString, aLength, p, bufLen);
03502   nsresult res = mSubstituteFont->GetBoundingMetrics(p, len, 
03503                                     aBoundingMetrics);
03504   if (p != buf)
03505     nsMemory::Free(p);
03506   return res;
03507 }
03508 #endif /*  MOZ_MATHML */
03509 
03510 XFontStruct * 
03511 nsFontXlibSubstitute::GetXFontStruct(void)
03512 {
03513   return mSubstituteFont->GetXFontStruct();
03514 }
03515 
03516 nsXFont*
03517 nsFontXlibSubstitute::GetXFont(void)
03518 {
03519   return mSubstituteFont->GetXFont();
03520 }
03521 
03522 PRBool
03523 nsFontXlibSubstitute::GetXFontIs10646(void)
03524 {
03525   return mSubstituteFont->GetXFontIs10646();
03526 }
03527 
03528 class nsFontXlibUserDefined : public nsFontXlib
03529 {
03530 public:
03531   nsFontXlibUserDefined(nsFontMetricsXlibContext *aFontMetricsContext);
03532   virtual ~nsFontXlibUserDefined();
03533 
03534   virtual PRBool Init(nsFontXlib* aFont);
03535   virtual int GetWidth(const PRUnichar* aString, PRUint32 aLength);
03536   virtual int DrawString(nsRenderingContextXlib* aContext,
03537                          nsIDrawingSurfaceXlib* aSurface, nscoord aX,
03538                          nscoord aY, const PRUnichar* aString,
03539                          PRUint32 aLength);
03540 #ifdef MOZ_MATHML
03541   virtual nsresult GetBoundingMetrics(const PRUnichar*   aString,
03542                                       PRUint32           aLength,
03543                                       nsBoundingMetrics& aBoundingMetrics);
03544 #endif /* MOZ_MATHML */
03545   virtual PRUint32 Convert(const PRUnichar* aSrc, PRInt32 aSrcLen,
03546                            char* aDest, PRInt32 aDestLen);
03547 };
03548 
03549 nsFontXlibUserDefined::nsFontXlibUserDefined(nsFontMetricsXlibContext *aFontMetricsContext)
03550 {
03551   mFontMetricsContext = aFontMetricsContext;
03552 }
03553 
03554 nsFontXlibUserDefined::~nsFontXlibUserDefined()
03555 {
03556   // Do not free mFont here. It is owned by somebody else.
03557 }
03558 
03559 PRBool
03560 nsFontXlibUserDefined::Init(nsFontXlib* aFont)
03561 {
03562   if (!aFont->GetXFont()) {
03563     aFont->LoadFont();
03564     if (!aFont->GetXFont()) {
03565       mCCMap = mFontMetricsContext->mEmptyCCMap;
03566       return PR_FALSE;
03567     }
03568   }
03569   mXFont = aFont->GetXFont();
03570   mCCMap = mFontMetricsContext->mUserDefinedCCMap;
03571   mName = aFont->mName;
03572 
03573   return PR_TRUE;
03574 }
03575 
03576 PRUint32
03577 nsFontXlibUserDefined::Convert(const PRUnichar* aSrc, PRInt32 aSrcLen,
03578   char* aDest, PRInt32 aDestLen)
03579 {
03580   if (aSrcLen > aDestLen) {
03581     aSrcLen = aDestLen;
03582   }
03583   mFontMetricsContext->mUserDefinedConverter->Convert(aSrc, &aSrcLen, aDest, &aDestLen);
03584 
03585   return aSrcLen;
03586 }
03587 
03588 int
03589 nsFontXlibUserDefined::GetWidth(const PRUnichar* aString, PRUint32 aLength)
03590 {
03591   char buf[1024];
03592   char *p;
03593   PRInt32 bufLen;
03594   ENCODER_BUFFER_ALLOC_IF_NEEDED(p, mFontMetricsContext->mUserDefinedConverter,
03595                          aString, aLength, buf, sizeof(buf), bufLen);
03596   PRUint32 len = Convert(aString, aLength, p, bufLen);
03597 
03598   int outWidth;
03599   if (mXFont->IsSingleByte())
03600     outWidth = mXFont->TextWidth8(p, len);
03601   else
03602     outWidth = mXFont->TextWidth16((const XChar2b*)p, len/2);
03603   ENCODER_BUFFER_FREE_IF_NEEDED(p, buf);
03604   return outWidth;
03605 }
03606 
03607 int
03608 nsFontXlibUserDefined::DrawString(nsRenderingContextXlib* aContext,
03609                                   nsIDrawingSurfaceXlib* aSurface,
03610                                   nscoord aX, nscoord aY,
03611                                   const PRUnichar* aString, PRUint32 aLength)
03612 {
03613   char  buf[1024];
03614   char *p;
03615   PRInt32 bufLen;
03616   ENCODER_BUFFER_ALLOC_IF_NEEDED(p, mFontMetricsContext->mUserDefinedConverter,
03617                          aString, aLength, buf, sizeof(buf), bufLen);
03618   PRUint32 len = Convert(aString, aLength, p, bufLen);
03619   xGC *gc = aContext->GetGC();
03620 
03621   int outWidth;
03622   if (mXFont->IsSingleByte()) {
03623     mXFont->DrawText8(aSurface->GetDrawable(), *gc, aX,
03624                                           aY + mBaselineAdjust, p, len);
03625     outWidth = mXFont->TextWidth8(p, len);
03626   }
03627   else {
03628     mXFont->DrawText16(aSurface->GetDrawable(), *gc, aX, aY + mBaselineAdjust,
03629                        (const XChar2b*)p, len);
03630     outWidth = mXFont->TextWidth16((const XChar2b*)p, len/2);
03631   }
03632   gc->Release();
03633   ENCODER_BUFFER_FREE_IF_NEEDED(p, buf);
03634   return outWidth;
03635 }
03636 
03637 #ifdef MOZ_MATHML
03638 // bounding metrics for a string 
03639 // remember returned values are not in app units
03640 nsresult
03641 nsFontXlibUserDefined::GetBoundingMetrics(const PRUnichar*   aString,
03642                                         PRUint32           aLength,
03643                                         nsBoundingMetrics& aBoundingMetrics)                                 
03644 {
03645   aBoundingMetrics.Clear();               
03646 
03647   if (aString && 0 < aLength) {
03648     char  buf[1024];
03649     char *p;
03650     PRInt32 bufLen;
03651     ENCODER_BUFFER_ALLOC_IF_NEEDED(p, mFontMetricsContext->mUserDefinedConverter,
03652                          aString, aLength, buf, sizeof(buf), bufLen);
03653     PRUint32 len = Convert(aString, aLength, p, bufLen);
03654     if (mXFont->IsSingleByte()) {
03655       mXFont->TextExtents8(p, len,
03656                            &aBoundingMetrics.leftBearing,
03657                            &aBoundingMetrics.rightBearing,
03658                            &aBoundingMetrics.width,
03659                            &aBoundingMetrics.ascent,
03660                            &aBoundingMetrics.descent);
03661     }
03662     else {
03663       mXFont->TextExtents16((const XChar2b*)p, len,
03664                             &aBoundingMetrics.leftBearing,
03665                             &aBoundingMetrics.rightBearing,
03666                             &aBoundingMetrics.width,
03667                             &aBoundingMetrics.ascent,
03668                             &aBoundingMetrics.descent);
03669     }
03670     ENCODER_BUFFER_FREE_IF_NEEDED(p, buf);
03671   }
03672 
03673   return NS_OK;
03674 }
03675 #endif /* MOZ_MATHML */
03676 
03677 nsFontXlib*
03678 nsFontMetricsXlib::AddToLoadedFontsList(nsFontXlib* aFont)
03679 {
03680   if (mLoadedFontsCount == mLoadedFontsAlloc) {
03681     int newSize;
03682     if (mLoadedFontsAlloc) {
03683       newSize = (2 * mLoadedFontsAlloc);
03684     }
03685     else {
03686       newSize = 1;
03687     }
03688     nsFontXlib** newPointer = (nsFontXlib**) 
03689       PR_Realloc(mLoadedFonts, newSize * sizeof(nsFontXlib*));
03690     if (newPointer) {
03691       mLoadedFonts = newPointer;
03692       mLoadedFontsAlloc = newSize;
03693     }
03694     else {
03695       return nsnull;
03696     }
03697   }
03698   mLoadedFonts[mLoadedFontsCount++] = aFont;
03699   return aFont;
03700 }
03701 
03702 // define a size such that a scaled font would always be closer
03703 // to the desired size than this
03704 #define NOT_FOUND_FONT_SIZE 1000*1000*1000
03705 
03706 nsFontXlib*
03707 nsFontMetricsXlib::FindNearestSize(nsFontStretchXlib* aStretch, PRUint16 aSize)
03708 {
03709   nsFontXlib* font = nsnull;
03710   if (aStretch->mSizes) {
03711     nsFontXlib** begin = aStretch->mSizes;
03712     nsFontXlib** end = &aStretch->mSizes[aStretch->mSizesCount];
03713     nsFontXlib** s;
03714     // scan the list of sizes
03715     for (s = begin; s < end; s++) {
03716       // stop when we hit or overshoot the size
03717       if ((*s)->mSize >= aSize) {
03718         break;
03719       }
03720     }
03721     // backup if we hit the end of the list
03722     if (s == end) {
03723       s--;
03724     }
03725     else if (s != begin) {
03726       // if we overshot pick the closest size
03727       if (((*s)->mSize - aSize) >= (aSize - (*(s - 1))->mSize)) {
03728         s--;
03729       }
03730     }
03731     // this is the nearest bitmap font
03732     font = *s;
03733   }
03734   return font;
03735 }
03736 
03737 static PRBool
03738 SetFontCharsetInfo(nsFontXlib *aFont, nsFontCharSetInfoXlib* aCharSet,
03739                    PRUnichar aChar)
03740 {
03741   if (aCharSet->mCharSet) {
03742     aFont->mCCMap = aCharSet->mCCMap;
03743     // check that the font is not empty
03744     if (CCMAP_HAS_CHAR(aFont->mCCMap, aChar)) {
03745       aFont->LoadFont();
03746       if (!aFont->GetXFont()) {
03747         return PR_FALSE;
03748       }
03749     }
03750   }
03751   else {
03752     if (aCharSet == aFont->mFontMetricsContext->mISO106461) {
03753       aFont->LoadFont();
03754       if (!aFont->GetXFont()) {
03755         return PR_FALSE;
03756       }
03757     }
03758   }
03759   return PR_TRUE;
03760 }
03761 
03762 static nsFontXlib*
03763 SetupUserDefinedFont(nsFontMetricsXlibContext *aFmctx, nsFontXlib *aFont)
03764 {
03765   if (!aFont->mUserDefinedFont) {
03766     aFont->mUserDefinedFont = new nsFontXlibUserDefined(aFmctx);
03767     if (!aFont->mUserDefinedFont) {
03768       return nsnull;
03769     }
03770     if (!aFont->mUserDefinedFont->Init(aFont)) {
03771       return nsnull;
03772     }
03773   }
03774   return aFont->mUserDefinedFont;
03775 }
03776 
03777 
03778 #ifdef USE_AASB
03779 nsFontXlib*
03780 nsFontMetricsXlib::GetAASBBaseFont(nsFontStretchXlib* aStretch, 
03781                                    nsFontCharSetInfoXlib* aCharSet)
03782 {
03783   nsFontXlib* base_aafont;
03784   PRInt32 scale_size;
03785   PRUint32 aa_target_size;
03786 
03787   scale_size = PR_MAX(mPixelSize, aCharSet->mAABitmapScaleMin);
03788   aa_target_size = PR_MAX((scale_size*2), 16);
03789   base_aafont = FindNearestSize(aStretch, aa_target_size);
03790   NS_ASSERTION(base_aafont,
03791              "failed to find a base font for Anti-Aliased bitmap Scaling");
03792   return base_aafont;
03793 }
03794 #endif /* USE_AASB */
03795 
03796 nsFontXlib*
03797 nsFontMetricsXlib::PickASizeAndLoad(nsFontStretchXlib* aStretch,
03798   nsFontCharSetInfoXlib* aCharSet, PRUnichar aChar, const char *aName)
03799 {
03800 #ifdef MOZ_ENABLE_FREETYPE2
03801   if (aStretch->mFreeTypeFaceID) {
03802     //FREETYPE_FONT_PRINTF(("mFreeTypeFaceID = 0x%p", aStretch->mFreeTypeFaceID));
03803     nsFreeTypeFont *ftfont = nsFreeTypeFont::NewFont(aStretch->mFreeTypeFaceID,
03804                                                      mPixelSize,
03805                                                      aName);
03806     if (!ftfont) {
03807       FREETYPE_FONT_PRINTF(("failed to create font"));
03808       return nsnull;
03809     }
03810     //FREETYPE_FONT_PRINTF(("created ftfont"));
03811     /*
03812      * XXX Instead of passing pixel size, we ought to take underline
03813      * into account. (Extra space for underline for Asian fonts.)
03814      */
03815     ftfont->mName = PR_smprintf("%s", aName);
03816     if (!ftfont->mName) {
03817       FREETYPE_FONT_PRINTF(("failed to create mName"));
03818       delete ftfont;
03819       return nsnull;
03820     }
03821     SetCharsetLangGroup(mFontMetricsContext, aCharSet);
03822     ftfont->mSize = mPixelSize;
03823     ftfont->LoadFont();
03824     ftfont->mCharSetInfo = mFontMetricsContext->mISO106461;
03825     //FREETYPE_FONT_PRINTF(("add the ftfont"));
03826     return AddToLoadedFontsList(ftfont);
03827   }
03828 #endif /* MOZ_ENABLE_FREETYPE2 */
03829 
03830   PRBool      use_scaled_font               = PR_FALSE;
03831   PRBool      have_nearly_rightsized_bitmap = PR_FALSE;
03832 #ifdef USE_AASB
03833   nsFontXlib *base_aafont                   = nsnull;
03834 #endif /* USE_AASB */
03835 
03836 #ifdef USE_XPRINT
03837 #define ALWAYS_USE_SCALED_FONTS_FOR_XPRINT 1
03838 #endif /* USE_XPRINT */
03839 
03840 #ifdef ALWAYS_USE_SCALED_FONTS_FOR_XPRINT
03841 /* gisburn: Small hack for Xprint:
03842  * Xprint usually operates at resolutions >= 300DPI. There are 
03843  * usually no "normal" bitmap fonts at those resolutions - only 
03844  * "scalable outline fonts" and "built-in printer fonts" (which 
03845  * usually look like scalable bitmap fonts) are available.
03846  * Therefore: force use of scalable fonts to get rid of 
03847  * manually scaled bitmap fonts...
03848  */
03849  if (mFontMetricsContext->mPrinterMode)
03850  {
03851    use_scaled_font = PR_TRUE;
03852  }
03853 #endif /* ALWAYS_USE_SCALED_FONTS_FOR_XPRINT */
03854 
03855   PRInt32 bitmap_size = NOT_FOUND_FONT_SIZE;
03856   PRInt32 scale_size = mPixelSize;
03857   nsFontXlib* font = FindNearestSize(aStretch, mPixelSize);
03858   if (font) {
03859     bitmap_size = font->mSize;
03860     if (   (bitmap_size >= mPixelSize-(mPixelSize/10))
03861         && (bitmap_size <= mPixelSize+(mPixelSize/10)))
03862       // When the size of a hand tuned font is close to the desired size
03863       // favor it over outline scaled font
03864       have_nearly_rightsized_bitmap = PR_TRUE;
03865   }
03866 
03867 #ifdef USE_AASB
03868   //
03869   // If the user says always try to aasb (anti alias scaled bitmap) scale
03870   //
03871   if (mFontMetricsContext->mAABitmapScaleEnabled && aCharSet->mAABitmapScaleAlways) {
03872     base_aafont = GetAASBBaseFont(aStretch, aCharSet);
03873     if (base_aafont) {
03874       use_scaled_font = PR_TRUE;
03875       SIZE_FONT_PRINTF(("anti-aliased bitmap scaled font: %s\n"
03876             "                    desired=%d, aa-scaled=%d, bitmap=%d, "
03877             "aa_bitmap=%d",
03878             aName, mPixelSize, scale_size, bitmap_size, base_aafont->mSize));
03879     }
03880   }
03881 #endif /* USE_AASB */
03882 
03883   //
03884   // if not already aasb scaling and
03885   // if we do not have a bitmap that is nearly the correct size 
03886   //
03887   if (!use_scaled_font && !have_nearly_rightsized_bitmap) {
03888     // check if we can use an outline scaled font
03889     if (aStretch->mOutlineScaled) {
03890       scale_size = PR_MAX(mPixelSize, aCharSet->mOutlineScaleMin);
03891 
03892       if (PR_ABS(mPixelSize-scale_size) < PR_ABS(mPixelSize-bitmap_size)) {
03893         use_scaled_font = PR_TRUE;
03894         SIZE_FONT_PRINTF(("outline font:______ %s\n"
03895                   "                    desired=%d, scaled=%d, bitmap=%d", 
03896                   aStretch->mScalable, mPixelSize, scale_size,
03897                   (bitmap_size=NOT_FOUND_FONT_SIZE?0:bitmap_size)));
03898       }
03899     }
03900 #ifdef USE_AASB
03901     // see if we can aasb (anti alias scaled bitmap)
03902     if (!use_scaled_font 
03903         && (bitmap_size<NOT_FOUND_FONT_SIZE) && mFontMetricsContext->mAABitmapScaleEnabled) {
03904       // if we do not have a near-the-right-size font or scalable font
03905       // see if we can anti-alias bitmap scale one
03906       scale_size = PR_MAX(mPixelSize, aCharSet->mAABitmapScaleMin);
03907       double ratio = (bitmap_size / ((double) mPixelSize));
03908       if (   (ratio < aCharSet->mAABitmapUndersize)
03909           || (ratio > aCharSet->mAABitmapOversize)) {
03910         //
03911         // Try to get a size font to scale that is 2x larger 
03912         // (but at least 16 pixel)
03913         //
03914         base_aafont = GetAASBBaseFont(aStretch, aCharSet);
03915         if (base_aafont) {
03916           use_scaled_font = PR_TRUE;
03917           SIZE_FONT_PRINTF(("anti-aliased bitmap scaled font: %s\n"
03918               "                    desired=%d, aa-scaled=%d, bitmap=%d, "
03919               "aa_bitmap=%d",
03920               aName, mPixelSize, scale_size, bitmap_size, base_aafont->mSize));
03921         }
03922       }
03923     }
03924 #endif /* USE_AASB */
03925 
03926     // last resort: consider a bitmap scaled font (ugly!)
03927     if (!use_scaled_font && aStretch->mScalable) {
03928       scale_size = PR_MAX(mPixelSize, aCharSet->mBitmapScaleMin);
03929       double ratio = (bitmap_size / ((double) mPixelSize));
03930       if ((ratio < aCharSet->mBitmapUndersize)
03931         || (ratio > aCharSet->mBitmapOversize)) {
03932         if ((PR_ABS(mPixelSize-scale_size) < PR_ABS(mPixelSize-bitmap_size))) {
03933           use_scaled_font = PR_TRUE;
03934           SIZE_FONT_PRINTF(("bitmap scaled font: %s\n"
03935                 "                    desired=%d, scaled=%d, bitmap=%d", 
03936                 aStretch->mScalable, mPixelSize, scale_size,
03937                 (bitmap_size=NOT_FOUND_FONT_SIZE?0:bitmap_size)));
03938         }
03939       }
03940     }
03941   }
03942 
03943   NS_ASSERTION((bitmap_size<NOT_FOUND_FONT_SIZE)||use_scaled_font,
03944                 "did not find font size");
03945   if (!use_scaled_font) {
03946     SIZE_FONT_PRINTF(("bitmap font:_______ %s\n" 
03947                       "                    desired=%d, scaled=%d, bitmap=%d", 
03948                       aName, mPixelSize, scale_size, bitmap_size));
03949   }
03950 
03951   if (use_scaled_font
03952 #ifdef ALWAYS_USE_SCALED_FONTS_FOR_XPRINT
03953    && aStretch->mScalable
03954 #endif /* ALWAYS_USE_SCALED_FONTS_FOR_XPRINT */
03955      ) {
03956    SIZE_FONT_PRINTF(("scaled font:_______ %s\n"
03957                      "                    desired=%d, scaled=%d, bitmap=%d",
03958                      aName, mPixelSize, scale_size, bitmap_size));
03959 
03960     PRInt32 i;
03961     PRInt32 n = aStretch->mScaledFonts.Count();
03962     nsFontXlib* p = nsnull;
03963     for (i = 0; i < n; i++) {
03964       p = (nsFontXlib*) aStretch->mScaledFonts.ElementAt(i);
03965       if (p->mSize == scale_size) {
03966         break;
03967       }
03968     }
03969     if (i == n) {
03970 #ifdef USE_AASB
03971       if (base_aafont) {
03972         // setup the base font
03973         if (!SetFontCharsetInfo(base_aafont, aCharSet, aChar))
03974           return nsnull;
03975         if (mIsUserDefined) {
03976           base_aafont = SetupUserDefinedFont(mFontMetricsContext, base_aafont);
03977           if (!base_aafont)
03978             return nsnull;
03979         }
03980         font = new nsFontXlibNormal(aFmctx, base_aafont);
03981       }
03982       else
03983 #endif /* USE_AASB */
03984       {
03985         font = new nsFontXlibNormal(mFontMetricsContext);
03986       }
03987 
03988       if (font) {
03989         /*
03990          * XXX Instead of passing pixel size, we ought to take underline
03991          * into account. (Extra space for underline for Asian fonts.)
03992          */
03993 #ifdef USE_AASB
03994         if (base_aafont) {
03995           font->mName = PR_smprintf("%s", base_aafont->mName);
03996           font->mAABaseSize = base_aafont->mSize;
03997         }
03998         else
03999 #endif /* USE_AASB */
04000         {
04001           font->mName = PR_smprintf(aStretch->mScalable, scale_size);
04002 #ifdef USE_AASB
04003           font->mAABaseSize = 0;
04004 #endif /* USE_AASB */
04005         }
04006         if (!font->mName) {
04007           delete font;
04008           return nsnull;
04009         }
04010         font->mSize = scale_size;
04011         font->mCharSetInfo = aCharSet;
04012         aStretch->mScaledFonts.AppendElement(font);
04013       }
04014       else {
04015         return nsnull;
04016       }
04017     }
04018     else {
04019       font = p;
04020     }
04021   }
04022 
04023   if (!SetFontCharsetInfo(font, aCharSet, aChar))
04024     return nsnull;
04025 
04026   if (mIsUserDefined) {
04027     font = SetupUserDefinedFont(mFontMetricsContext, font);
04028     if (!font)
04029       return nsnull;
04030   }
04031 
04032   return AddToLoadedFontsList(font);
04033 }
04034 
04035 PR_BEGIN_EXTERN_C
04036 static int
04037 CompareSizes(const void* aArg1, const void* aArg2, void *data)
04038 {
04039   return (*((nsFontXlib**) aArg1))->mSize - (*((nsFontXlib**) aArg2))->mSize;
04040 }
04041 PR_END_EXTERN_C
04042 
04043 void
04044 nsFontStretchXlib::SortSizes(void)
04045 {
04046   NS_QuickSort(mSizes, mSizesCount, sizeof(*mSizes), CompareSizes, NULL);
04047 }
04048 
04049 void
04050 nsFontWeightXlib::FillStretchHoles(void)
04051 {
04052   int i, j;
04053 
04054   for (i = 0; i < 9; i++) {
04055     if (mStretches[i]) {
04056       mStretches[i]->SortSizes();
04057     }
04058   }
04059 
04060   if (!mStretches[4]) {
04061     for (i = 5; i < 9; i++) {
04062       if (mStretches[i]) {
04063         mStretches[4] = mStretches[i];
04064         break;
04065       }
04066     }
04067     if (!mStretches[4]) {
04068       for (i = 3; i >= 0; i--) {
04069         if (mStretches[i]) {
04070           mStretches[4] = mStretches[i];
04071           break;
04072         }
04073       }
04074     }
04075   }
04076 
04077   for (i = 5; i < 9; i++) {
04078     if (!mStretches[i]) {
04079       for (j = i + 1; j < 9; j++) {
04080         if (mStretches[j]) {
04081           mStretches[i] = mStretches[j];
04082           break;
04083         }
04084       }
04085       if (!mStretches[i]) {
04086         for (j = i - 1; j >= 0; j--) {
04087           if (mStretches[j]) {
04088             mStretches[i] = mStretches[j];
04089             break;
04090           }
04091         }
04092       }
04093     }
04094   }
04095   for (i = 3; i >= 0; i--) {
04096     if (!mStretches[i]) {
04097       for (j = i - 1; j >= 0; j--) {
04098         if (mStretches[j]) {
04099           mStretches[i] = mStretches[j];
04100           break;
04101         }
04102       }
04103       if (!mStretches[i]) {
04104         for (j = i + 1; j < 9; j++) {
04105           if (mStretches[j]) {
04106             mStretches[i] = mStretches[j];
04107             break;
04108           }
04109         }
04110       }
04111     }
04112   }
04113 }
04114 
04115 void
04116 nsFontStyleXlib::FillWeightHoles(void)
04117 {
04118   int i, j;
04119 
04120   for (i = 0; i < 9; i++) {
04121     if (mWeights[i]) {
04122       mWeights[i]->FillStretchHoles();
04123     }
04124   }
04125 
04126   if (!mWeights[3]) {
04127     for (i = 4; i < 9; i++) {
04128       if (mWeights[i]) {
04129         mWeights[3] = mWeights[i];
04130         break;
04131       }
04132     }
04133     if (!mWeights[3]) {
04134       for (i = 2; i >= 0; i--) {
04135         if (mWeights[i]) {
04136           mWeights[3] = mWeights[i];
04137           break;
04138         }
04139       }
04140     }
04141   }
04142 
04143   // CSS2, section 15.5.1
04144   if (!mWeights[4]) {
04145     mWeights[4] = mWeights[3];
04146   }
04147   for (i = 5; i < 9; i++) {
04148     if (!mWeights[i]) {
04149       for (j = i + 1; j < 9; j++) {
04150         if (mWeights[j]) {
04151           mWeights[i] = mWeights[j];
04152           break;
04153         }
04154       }
04155       if (!mWeights[i]) {
04156         for (j = i - 1; j >= 0; j--) {
04157           if (mWeights[j]) {
04158             mWeights[i] = mWeights[j];
04159             break;
04160           }
04161         }
04162       }
04163     }
04164   }
04165   for (i = 2; i >= 0; i--) {
04166     if (!mWeights[i]) {
04167       for (j = i - 1; j >= 0; j--) {
04168         if (mWeights[j]) {
04169           mWeights[i] = mWeights[j];
04170           break;
04171         }
04172       }
04173       if (!mWeights[i]) {
04174         for (j = i + 1; j < 9; j++) {
04175           if (mWeights[j]) {
04176             mWeights[i] = mWeights[j];
04177             break;
04178           }
04179         }
04180       }
04181     }
04182   }
04183 }
04184 
04185 void
04186 nsFontNodeXlib::FillStyleHoles(void)
04187 {
04188   if (mHolesFilled) {
04189     return;
04190   }
04191   mHolesFilled = 1;
04192 
04193 #ifdef DEBUG_DUMP_TREE
04194   DumpFamily(this);
04195 #endif
04196 
04197   for (int i = 0; i < 3; i++) {
04198     if (mStyles[i]) {
04199       mStyles[i]->FillWeightHoles();
04200     }
04201   }
04202 
04203   // XXX If both italic and oblique exist, there is probably something
04204   // wrong. Try counting the fonts, and removing the one that has less.
04205   if (!mStyles[NS_FONT_STYLE_NORMAL]) {
04206     if (mStyles[NS_FONT_STYLE_ITALIC]) {
04207       mStyles[NS_FONT_STYLE_NORMAL] = mStyles[NS_FONT_STYLE_ITALIC];
04208     }
04209     else {
04210       mStyles[NS_FONT_STYLE_NORMAL] = mStyles[NS_FONT_STYLE_OBLIQUE];
04211     }
04212   }
04213   if (!mStyles[NS_FONT_STYLE_ITALIC]) {
04214     if (mStyles[NS_FONT_STYLE_OBLIQUE]) {
04215       mStyles[NS_FONT_STYLE_ITALIC] = mStyles[NS_FONT_STYLE_OBLIQUE];
04216     }
04217     else {
04218       mStyles[NS_FONT_STYLE_ITALIC] = mStyles[NS_FONT_STYLE_NORMAL];
04219     }
04220   }
04221   if (!mStyles[NS_FONT_STYLE_OBLIQUE]) {
04222     if (mStyles[NS_FONT_STYLE_ITALIC]) {
04223       mStyles[NS_FONT_STYLE_OBLIQUE] = mStyles[NS_FONT_STYLE_ITALIC];
04224     }
04225     else {
04226       mStyles[NS_FONT_STYLE_OBLIQUE] = mStyles[NS_FONT_STYLE_NORMAL];
04227     }
04228   }
04229 
04230 #ifdef DEBUG_DUMP_TREE
04231   DumpFamily(this);
04232 #endif
04233 }
04234 
04235 static void
04236 SetCharsetLangGroup(nsFontMetricsXlibContext *aFmctx, nsFontCharSetInfoXlib* aCharSetInfo)
04237 {
04238   if (!aCharSetInfo->mCharSet || aCharSetInfo->mLangGroup)
04239     return;
04240 
04241   nsresult res;
04242   
04243   res = aFmctx->mCharSetManager->GetCharsetLangGroupRaw(aCharSetInfo->mCharSet,
04244                                                         &aCharSetInfo->mLangGroup);
04245   if (NS_FAILED(res)) {
04246     aCharSetInfo->mLangGroup = NS_NewAtom("");
04247 #ifdef NOISY_FONTS
04248     printf("=== cannot get lang group for %s\n", aCharSetInfo->mCharSet);
04249 #endif
04250   }
04251 }
04252 
04253 #define GET_WEIGHT_INDEX(index, weight) \
04254   do {                                  \
04255     (index) = WEIGHT_INDEX(weight);     \
04256     if ((index) < 0) {                  \
04257       (index) = 0;                      \
04258     }                                   \
04259     else if ((index) > 8) {             \
04260       (index) = 8;                      \
04261     }                                   \
04262   } while (0)
04263 
04264 nsFontXlib*
04265 nsFontMetricsXlib::SearchNode(nsFontNodeXlib* aNode, PRUnichar aChar)
04266 {
04267   if (aNode->mDummy) {
04268     return nsnull;
04269   }
04270 
04271   nsFontCharSetInfoXlib* charSetInfo = aNode->mCharSetInfo;
04272 
04273   /*
04274    * mCharSet is set if we know which glyphs will be found in these fonts.
04275    * If mCCMap has already been created for this charset, we compare it with
04276    * the mCCMaps of the previously loaded fonts. If it is the same as any of
04277    * the previous ones, we return nsnull because there is no point in
04278    * loading a font with the same map.
04279    */
04280   if (charSetInfo->mCharSet) {
04281     PRUint16* ccmap = charSetInfo->mCCMap;
04282     if (ccmap) {
04283       for (int i = 0; i < mLoadedFontsCount; i++) {
04284         if (mLoadedFonts[i]->mCCMap == ccmap) {
04285           return nsnull;
04286         }
04287       }
04288     }
04289     else {
04290       if (!SetUpFontCharSetInfo(mFontMetricsContext, charSetInfo))
04291         return nsnull;
04292     }
04293   }
04294   else {
04295     if ((!mIsUserDefined) && (charSetInfo == mFontMetricsContext->mUnknown)) {
04296       return nsnull;
04297     }
04298   }
04299 
04300   aNode->FillStyleHoles();
04301   nsFontStyleXlib* style = aNode->mStyles[mStyleIndex];
04302 
04303   nsFontWeightXlib** weights = style->mWeights;
04304   int weight = mFont.weight;
04305   int steps = (weight % 100);
04306   int weightIndex;
04307   if (steps) {
04308     if (steps < 10) {
04309       int base = (weight - steps);
04310       GET_WEIGHT_INDEX(weightIndex, base);
04311       while (steps--) {
04312         nsFontWeightXlib* prev = weights[weightIndex];
04313         for (weightIndex++; weightIndex < 9; weightIndex++) {
04314           if (weights[weightIndex] != prev) {
04315             break;
04316           }
04317         }
04318         if (weightIndex >= 9) {
04319           weightIndex = 8;
04320         }
04321       }
04322     }
04323     else if (steps > 90) {
04324       steps = (100 - steps);
04325       int base = (weight + steps);
04326       GET_WEIGHT_INDEX(weightIndex, base);
04327       while (steps--) {
04328         nsFontWeightXlib* prev = weights[weightIndex];
04329         for (weightIndex--; weightIndex >= 0; weightIndex--) {
04330           if (weights[weightIndex] != prev) {
04331             break;
04332           }
04333         }
04334         if (weightIndex < 0) {
04335           weightIndex = 0;
04336         }
04337       }
04338     }
04339     else {
04340       GET_WEIGHT_INDEX(weightIndex, weight);
04341     }
04342   }
04343   else {
04344     GET_WEIGHT_INDEX(weightIndex, weight);
04345   }
04346 
04347   FIND_FONT_PRINTF(("        load font %s", aNode->mName.get()));
04348   return PickASizeAndLoad(weights[weightIndex]->mStretches[mStretchIndex],
04349     charSetInfo, aChar, aNode->mName.get());
04350 }
04351 
04352 static void 
04353 SetFontLangGroupInfo(nsFontMetricsXlibContext *aFmctx, const nsFontCharSetMapXlib* aCharSetMap)
04354 {
04355   nsFontLangGroupXlib *fontLangGroup = aCharSetMap->mFontLangGroup;
04356   if (!fontLangGroup)
04357     return;
04358 
04359   // get the atom for mFontLangGroup->mFontLangGroupName so we can
04360   // apply fontLangGroup operations to it
04361   // eg: search for related groups, check for scaling prefs
04362   const char *langGroup = fontLangGroup->mFontLangGroupName;
04363 
04364   // the font.scale prefs don't make sense without a langGroup
04365   // XXX FIX!!!  if langGroup is "", we need to bypass the font.scale stuff
04366   if (!langGroup)
04367     langGroup = "";
04368   if (!fontLangGroup->mFontLangGroupAtom) {
04369       fontLangGroup->mFontLangGroupAtom = NS_NewAtom(langGroup);
04370   }
04371 
04372   // hack : map 'x-zh-TWHK' to 'zh-TW'. See nsFontMetricsGTK.cpp for details.
04373   if (fontLangGroup->mFontLangGroupAtom == aFmctx->mZHTWHK) {
04374     langGroup = "zh-TW";
04375   }
04376 
04377   // get the font scaling controls
04378   nsFontCharSetInfoXlib *charSetInfo = aCharSetMap->mInfo;
04379   if (!charSetInfo->mInitedSizeInfo) {
04380     charSetInfo->mInitedSizeInfo = PR_TRUE;
04381 
04382     nsCAutoString name;
04383     nsresult rv;
04384     name.Assign("font.scale.outline.min.");
04385     name.Append(langGroup);
04386     rv = aFmctx->mPref->GetIntPref(name.get(), &charSetInfo->mOutlineScaleMin);
04387     if (NS_SUCCEEDED(rv))
04388       SIZE_FONT_PRINTF(("%s = %d", name.get(), charSetInfo->mOutlineScaleMin));
04389     else
04390       charSetInfo->mOutlineScaleMin = aFmctx->mOutlineScaleMinimum;
04391 
04392 #ifdef USE_AASB
04393     name.Assign("font.scale.aa_bitmap.min.");
04394     name.Append(langGroup);
04395     rv = aFmctx->mPref->GetIntPref(name.get(), &charSetInfo->mAABitmapScaleMin);
04396     if (NS_SUCCEEDED(rv))
04397       SIZE_FONT_PRINTF(("%s = %d", name.get(), charSetInfo->mAABitmapScaleMin));
04398     else
04399       charSetInfo->mAABitmapScaleMin = aFmctx->mAABitmapScaleMinimum;
04400 #endif /* USE_AASB */
04401 
04402     name.Assign("font.scale.bitmap.min.");
04403     name.Append(langGroup);
04404     rv = aFmctx->mPref->GetIntPref(name.get(), &charSetInfo->mBitmapScaleMin);
04405     if (NS_SUCCEEDED(rv))
04406       SIZE_FONT_PRINTF(("%s = %d", name.get(), charSetInfo->mBitmapScaleMin));
04407     else
04408       charSetInfo->mBitmapScaleMin = aFmctx->mBitmapScaleMinimum;
04409 
04410     PRInt32 percent = 0;
04411 #ifdef USE_AASB
04412     name.Assign("font.scale.aa_bitmap.oversize.");
04413     name.Append(langGroup);
04414     percent = 0;
04415     rv = mFontMetricsContext->mPref->GetIntPref(name.get(), &percent);
04416     if (NS_SUCCEEDED(rv)) {
04417       charSetInfo->mAABitmapOversize = percent/100.0;
04418       SIZE_FONT_PRINTF(("%s = %g", name.get(), charSetInfo->mAABitmapOversize));
04419     }
04420     else
04421       charSetInfo->mAABitmapOversize = aFmctx->mAABitmapOversize;
04422 
04423     percent = 0;
04424     name.Assign("font.scale.aa_bitmap.undersize.");
04425     name.Append(langGroup);
04426     rv = mFontMetricsContext->mPref->GetIntPref(name.get(), &percent);
04427     if (NS_SUCCEEDED(rv)) {
04428       charSetInfo->mAABitmapUndersize = percent/100.0;
04429       SIZE_FONT_PRINTF(("%s = %g", name.get(),charSetInfo->mAABitmapUndersize));
04430     }
04431     else
04432       charSetInfo->mAABitmapUndersize = aFmctx->mAABitmapUndersize;
04433 
04434     PRBool val = PR_TRUE;
04435     name.Assign("font.scale.aa_bitmap.always.");
04436     name.Append(langGroup);
04437     rv = mFontMetricsContext->mPref->GetBoolPref(name.get(), &val);
04438     if (NS_SUCCEEDED(rv)) {
04439       charSetInfo->mAABitmapScaleAlways = val;
04440       SIZE_FONT_PRINTF(("%s = %d", name.get(),charSetInfo->mAABitmapScaleAlways));
04441     }
04442     else
04443       charSetInfo->mAABitmapScaleAlways = aFmctx->mAABitmapScaleAlways;
04444 #endif /* USE_AASB */
04445 
04446     percent = 0;
04447     name.Assign("font.scale.bitmap.oversize.");
04448     name.Append(langGroup);
04449     rv = aFmctx->mPref->GetIntPref(name.get(), &percent);
04450     if (NS_SUCCEEDED(rv)) {
04451       charSetInfo->mBitmapOversize = percent/100.0;
04452       SIZE_FONT_PRINTF(("%s = %g", name.get(), charSetInfo->mBitmapOversize));
04453     }
04454     else
04455       charSetInfo->mBitmapOversize = aFmctx->mBitmapOversize;
04456 
04457     percent = 0;
04458     name.Assign("font.scale.bitmap.undersize.");
04459     name.Append(langGroup);
04460     rv = aFmctx->mPref->GetIntPref(name.get(), &percent);
04461     if (NS_SUCCEEDED(rv)) {
04462       charSetInfo->mBitmapUndersize = percent/100.0;
04463       SIZE_FONT_PRINTF(("%s = %g", name.get(), charSetInfo->mBitmapUndersize));
04464     }
04465     else
04466       charSetInfo->mBitmapUndersize = aFmctx->mBitmapUndersize;
04467   }
04468 }
04469 
04470 static nsFontStyleXlib*
04471 NodeGetStyle(nsFontNodeXlib* aNode, int aStyleIndex)
04472 {
04473   nsFontStyleXlib* style = aNode->mStyles[aStyleIndex];
04474   if (!style) {
04475     style = new nsFontStyleXlib;
04476     if (!style) {
04477       return nsnull;
04478     }
04479     aNode->mStyles[aStyleIndex] = style;
04480   }
04481   return style;
04482 }
04483 
04484 static nsFontWeightXlib*
04485 NodeGetWeight(nsFontStyleXlib* aStyle, int aWeightIndex)
04486 {
04487   nsFontWeightXlib* weight = aStyle->mWeights[aWeightIndex];
04488   if (!weight) {
04489     weight = new nsFontWeightXlib;
04490     if (!weight) {
04491       return nsnull;
04492     }
04493     aStyle->mWeights[aWeightIndex] = weight;
04494   }
04495   return weight;
04496 }
04497 
04498 static nsFontStretchXlib* 
04499 NodeGetStretch(nsFontWeightXlib* aWeight, int aStretchIndex)
04500 {
04501   nsFontStretchXlib* stretch = aWeight->mStretches[aStretchIndex];
04502   if (!stretch) {
04503     stretch = new nsFontStretchXlib;
04504     if (!stretch) {
04505       return nsnull;
04506     }
04507     aWeight->mStretches[aStretchIndex] = stretch;
04508   }
04509   return stretch;
04510 }
04511 
04512 static PRBool
04513 NodeAddScalable(nsFontStretchXlib* aStretch,
04514                 PRBool aOutlineScaled, 
04515 #ifdef USE_XPRINT
04516                 PRBool aPrinterBuiltinFont, int aResX, int aResY,
04517 #endif /* USE_XPRINT */                
04518                 const char *aDashFoundry, const char *aFamily, 
04519                 const char *aWeight,      const char * aSlant, 
04520                 const char *aWidth,       const char *aStyle, 
04521                 const char *aSpacing,     const char *aCharSet)
04522 {
04523   // if we have both an outline scaled font and a bitmap 
04524   // scaled font pick the outline scaled font
04525   if ((aStretch->mScalable) && (!aStretch->mOutlineScaled) 
04526       && (aOutlineScaled)) {
04527     PR_smprintf_free(aStretch->mScalable);
04528     aStretch->mScalable = nsnull;
04529   }
04530   if (!aStretch->mScalable) {
04531     aStretch->mOutlineScaled = aOutlineScaled;
04532 #ifdef USE_XPRINT
04533     /* Xprint built-in printer fonts are outline-scaled fonts (except
04534      * that we ask explicitly for X/Y resolution instead of using 0/0)
04535      */
04536     if (aPrinterBuiltinFont) {
04537       aStretch->mScalable = 
04538           PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-%d-%d-%s-*-%s", 
04539           aDashFoundry, aFamily, aWeight, aSlant, aWidth, aStyle, 
04540           aResX, aResY, aSpacing, aCharSet);      
04541       if (!aStretch->mScalable)
04542         return PR_FALSE;
04543     }
04544     else 
04545 #endif /* USE_XPRINT */                
04546     if (aOutlineScaled) {
04547       aStretch->mScalable = 
04548           PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-0-0-%s-*-%s", 
04549           aDashFoundry, aFamily, aWeight, aSlant, aWidth, aStyle, 
04550           aSpacing, aCharSet);
04551       if (!aStretch->mScalable)
04552         return PR_FALSE;
04553     }
04554     else {
04555       aStretch->mScalable = 
04556           PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-*-*-%s-*-%s", 
04557           aDashFoundry, aFamily, aWeight, aSlant, aWidth, aStyle, 
04558           aSpacing, aCharSet);
04559       if (!aStretch->mScalable)
04560         return PR_FALSE;
04561     }
04562   }
04563   return PR_TRUE;
04564 }
04565 
04566 static PRBool
04567 NodeAddSize(nsFontMetricsXlibContext *aFmctx,
04568             nsFontStretchXlib* aStretch, 
04569             int aPixelSize, int aPointSize,
04570             float scaler,
04571             int aResX,      int aResY,
04572             const char *aDashFoundry, const char *aFamily, 
04573             const char *aWeight,      const char * aSlant, 
04574             const char *aWidth,       const char *aStyle, 
04575             const char *aSpacing,     const char *aCharSet,
04576             nsFontCharSetInfoXlib* aCharSetInfo)
04577 {
04578   if (scaler!=1.0f)
04579   {
04580     aPixelSize = int(float(aPixelSize) * scaler);
04581     aPointSize = int(float(aPointSize) * scaler);
04582     aResX = 0;
04583     aResY = 0;
04584   }
04585 
04586   PRBool haveSize = PR_FALSE;
04587   if (aStretch->mSizesCount) {
04588     nsFontXlib** end = &aStretch->mSizes[aStretch->mSizesCount];
04589     nsFontXlib** s;
04590     for (s = aStretch->mSizes; s < end; s++) {
04591       if ((*s)->mSize == aPixelSize) {
04592         haveSize = PR_TRUE;
04593         break;
04594       }
04595     }
04596   }
04597   if (!haveSize) {
04598     if (aStretch->mSizesCount == aStretch->mSizesAlloc) {
04599       int newSize = 2 * (aStretch->mSizesAlloc ? aStretch->mSizesAlloc : 1);
04600       nsFontXlib** newSizes = new nsFontXlib*[newSize];
04601       if (!newSizes)
04602         return PR_FALSE;
04603       for (int j = aStretch->mSizesAlloc - 1; j >= 0; j--) {
04604         newSizes[j] = aStretch->mSizes[j];
04605       }
04606       aStretch->mSizesAlloc = newSize;
04607       delete [] aStretch->mSizes;
04608       aStretch->mSizes = newSizes;
04609     }
04610     char *name = PR_smprintf("%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-*-%s", 
04611                              aDashFoundry, aFamily, aWeight, aSlant, aWidth, aStyle, 
04612                              aPixelSize, aPointSize, aResX, aResY, aSpacing, aCharSet);  
04613 
04614     if (!name) {
04615       return PR_FALSE;
04616     }
04617     nsFontXlib* size = new nsFontXlibNormal(aFmctx);
04618     if (!size) {
04619       return PR_FALSE;
04620     }
04621     aStretch->mSizes[aStretch->mSizesCount++] = size;
04622     size->mName           = name;
04623     // size->mFont is initialized in the constructor
04624     size->mSize           = aPixelSize;
04625     size->mBaselineAdjust = 0;
04626     size->mCCMap          = nsnull;
04627     size->mCharSetInfo    = aCharSetInfo;
04628   }
04629   return PR_TRUE;
04630 }
04631 
04632 static void
04633 GetFontNames(nsFontMetricsXlibContext *aFmctx, const char* aPattern, PRBool aAnyFoundry, PRBool aOnlyOutlineScaledFonts, nsFontNodeArrayXlib* aNodes)
04634 {
04635   Display *dpy = xxlib_rgb_get_display(aFmctx->mXlibRgbHandle);
04636   Screen  *scr = xxlib_rgb_get_screen (aFmctx->mXlibRgbHandle);
04637 
04638 #ifdef NS_FONT_DEBUG_CALL_TRACE
04639   if (gFontDebug & NS_FONT_DEBUG_CALL_TRACE) {
04640     printf("GetFontNames %s\n", aPattern);
04641   }
04642 #endif
04643 
04644 #ifdef MOZ_ENABLE_FREETYPE2
04645   // get FreeType fonts
04646   nsFT2FontCatalog::GetFontNames(aFmctx, aPattern, aNodes);
04647 #endif /* MOZ_ENABLE_FREETYPE2 */
04648 
04649   nsCAutoString previousNodeName;
04650   nsHashtable* node_hash;
04651   if (aAnyFoundry) {
04652     NS_ASSERTION(aPattern[1] == '*', "invalid 'anyFoundry' pattern");
04653     node_hash = &aFmctx->mAFRENodes;
04654   }
04655   else {
04656     node_hash = &aFmctx->mFFRENodes;
04657   }
04658 
04659 #ifdef USE_XPRINT
04660 #ifdef DEBUG
04661   if (aFmctx->mPrinterMode)
04662   {
04663     if (!dpy)
04664     {
04665       NS_ERROR("Obtaining font information without having a |Display *|");
04666       abort(); /* DIE!! */
04667     }
04668   
04669     if (XpGetContext(dpy) == None)
04670     {
04671       /* applications must not make any assumptions about fonts _before_ XpSetContext() !!! */
04672       NS_ERROR("Obtaining font information without valid print context (XListFonts()) _before_ XpSetContext()");
04673       abort(); /* DIE!! */
04674     }    
04675   }               
04676 #endif /* DEBUG */
04677 #endif /* USE_XPRINT */
04678   
04679 #ifdef ENABLE_X_FONT_BANNING
04680   int  screen_xres,
04681        screen_yres;
04682   /* Get Xserver DPI. 
04683    * We cannot use Mozilla's API here because it may "override" the DPI
04684    * got from the Xserver via prefs. But we want to filter ("ban") fonts
04685    * we get from the Xserver which _it_(=Xserver) has "choosen" for us
04686    * using its DPI value ...
04687    */
04688 #ifdef USE_XPRINT
04689   if (aFmctx->mPrinterMode) {
04690     Bool success;
04691     long x_dpi = 0,
04692          y_dpi = 0;
04693     success = XpuGetResolution(dpy, XpGetContext(dpy), &x_dpi, &y_dpi);
04694     NS_ASSERTION(success, "XpuGetResolution(dpy, XpGetContext(dpy), &x_dpi, &y_dpi)!");
04695     screen_xres = x_dpi;
04696     screen_yres = y_dpi;
04697   }
04698   else
04699 #endif /* USE_XPRINT */
04700   {  
04701     screen_xres = int(((( double(::XWidthOfScreen(scr)))  * 25.4 / double(::XWidthMMOfScreen(scr)) ))  + 0.5);
04702     screen_yres = int(((( double(::XHeightOfScreen(scr))) * 25.4 / double(::XHeightMMOfScreen(scr)) )) + 0.5);
04703   }
04704 #endif /* ENABLE_X_FONT_BANNING */
04705       
04706   BANNED_FONT_PRINTF(("Loading font '%s'", aPattern));
04707   /*
04708    * We do not use XListFontsWithInfo here, because it is very expensive.
04709    * Instead, we get that info at the time when we actually load the font.
04710    */
04711   int    count;
04712   char **list = ::XListFonts(dpy, aPattern, INT_MAX, &count);
04713   if ((!list) || (count < 1)) {
04714     return;
04715   }
04716   for (int i = 0; i < count; i++) {
04717     char name[256]; /* X11 font names are never larger than 255 chars */
04718 
04719     /* Check if we can handle the font name ('*' and '?' are only valid in
04720      * input patterns passed as argument to |XListFont()|&co. but _not_ in
04721      * font names returned by these functions (see bug 136743 ("xlib complains
04722      * a lot about fonts with '*' in the XLFD string"))) */
04723     if ((!list[i]) || (list[i][0] != '-') || (PL_strpbrk(list[i], "*?") != nsnull)) {
04724       continue;
04725     }
04726 
04727     strcpy(name, list[i]);
04728     
04729     char *p = name + 1;
04730     PRBool scalable       = PR_FALSE,
04731            outline_scaled = PR_FALSE;
04732 #ifdef USE_XPRINT
04733     PRBool builtin_printer_font = PR_FALSE;
04734 #endif /* USE_XPRINT */
04735     int    resX = -1,
04736            resY = -1;
04737 
04738 #ifdef FIND_FIELD
04739 #undef FIND_FIELD
04740 #endif
04741 #define FIND_FIELD(var)           \
04742   char* var = p;                  \
04743   while ((*p) && ((*p) != '-')) { \
04744     p++;                          \
04745   }                               \
04746   if (*p) {                       \
04747     *p++ = 0;                     \
04748   }                               \
04749   else {                          \
04750     continue;                     \
04751   }
04752 
04753 #ifdef SKIP_FIELD
04754 #undef SKIP_FIELD
04755 #endif
04756 #define SKIP_FIELD(var)           \
04757   while ((*p) && ((*p) != '-')) { \
04758     p++;                          \
04759   }                               \
04760   if (*p) {                       \
04761     p++;                          \
04762   }                               \
04763   else {                          \
04764     continue;                     \
04765   }
04766 
04767     FIND_FIELD(foundry);
04768     // XXX What to do about the many Applix fonts that start with "ax"?
04769     FIND_FIELD(familyName);
04770     FIND_FIELD(weightName);
04771     FIND_FIELD(slant);
04772     FIND_FIELD(setWidth);
04773     FIND_FIELD(addStyle);
04774     FIND_FIELD(pixelSize);
04775     if (pixelSize[0] == '0') {
04776       scalable = PR_TRUE;
04777     }
04778     FIND_FIELD(pointSize);
04779     if (pointSize[0] == '0') {
04780       scalable = PR_TRUE;
04781     }
04782     FIND_FIELD(resolutionX);
04783     resX = atoi(resolutionX);
04784     NS_ASSERTION(!(resolutionX[0] != '0' && resX == 0), "atoi(resolutionX) failure.");
04785     if (resolutionX[0] == '0') {
04786       scalable = PR_TRUE;
04787     }
04788     FIND_FIELD(resolutionY);
04789     resY = atoi(resolutionY);
04790     NS_ASSERTION(!(resolutionY[0] != '0' && resY == 0), "atoi(resolutionY) failure.");
04791     if (resolutionY[0] == '0') {
04792       scalable = PR_TRUE;
04793     }
04794     /* check if bitmap non-scaled font */
04795     if ((pixelSize[0] != '0') || (pointSize[0] != '0')) {
04796       SCALED_FONT_PRINTF(("bitmap (non-scaled) font: %s", list[i]));
04797     }
04798     /* check if bitmap scaled font */
04799     else if ((pixelSize[0] == '0') && (pointSize[0] == '0')
04800           && (resolutionX[0] != '0') && (resolutionY[0] != '0')) {
04801       SCALED_FONT_PRINTF(("bitmap scaled font: %s", list[i]));
04802     }
04803     /* check if outline scaled font */
04804     else if ((pixelSize[0] == '0') && (pointSize[0] == '0')
04805           && (resolutionX[0] == '0') && (resolutionY[0] == '0')) {
04806       outline_scaled = PR_TRUE;
04807       SCALED_FONT_PRINTF(("outline scaled font: %s", list[i]));
04808     }
04809     else {
04810       SCALED_FONT_PRINTF(("unexpected font values: %s", list[i]));
04811       SCALED_FONT_PRINTF(("      pixelSize[0] = %c", pixelSize[0]));
04812       SCALED_FONT_PRINTF(("      pointSize[0] = %c", pointSize[0]));
04813       SCALED_FONT_PRINTF(("    resolutionX[0] = %c", resolutionX[0]));
04814       SCALED_FONT_PRINTF(("    resolutionY[0] = %c", resolutionY[0]));
04815       static PRBool already_complained = PR_FALSE;
04816       // only complaing once 
04817       if (!already_complained) {
04818         already_complained = PR_TRUE;
04819         NS_ASSERTION(pixelSize[0] == '0', "font scaler type test failed");
04820         NS_ASSERTION(pointSize[0] == '0', "font scaler type test failed");
04821         NS_ASSERTION(resolutionX[0] == '0', "font scaler type test failed");
04822         NS_ASSERTION(resolutionY[0] == '0', "font scaler type test failed");
04823       }
04824     }
04825     FIND_FIELD(spacing);
04826     FIND_FIELD(averageWidth);
04827 
04828 #ifdef USE_XPRINT
04829     /* I am not sure what Xprint built-in printer fonts exactly look like
04830      * (usually '-adobe-helvetica-medium-r-normal--0-0-1200-1200-p-0-iso8859-1'
04831      * for a 300DPI printer ("fonts.dir" entry in 
04832      * $XPCONFIGDIR/C/print/models/SPSPARC2/fonts/ for "Helvetica.pmf" 
04833      * (PMF=printer font metrics) looks like this: 
04834      * '-adobe-helvetica-medium-r-normal--199-120-1200-1200-p-1085-iso8859-1'))
04835      * but this test is good enough (except when someone installs 1200DPI
04836      * bitmap (!!) fonts on a system... =:-)
04837      */
04838     if (aFmctx->mPrinterMode &&
04839         averageWidth[0] == '0' && 
04840         resX > screen_xres && 
04841         resY > screen_yres) {
04842       builtin_printer_font = PR_TRUE;
04843       /* Treat built-in printer fonts like outline-scaled ones... */
04844       outline_scaled = PR_TRUE;
04845 
04846       PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("This may be a built-in printer font '%s'\n", list[i]));
04847     }
04848 #endif /* USE_XPRINT */
04849 
04850     if (averageWidth[0] == '0') {
04851       scalable = PR_TRUE;
04852 /* Workaround for bug 103159 ("sorting fonts by foundry names cause font
04853  * size of css ignored in some cases").
04854  * Hardcoded font ban until bug 104075 ("need X font banning") has been
04855  * implemented. See http://bugzilla.mozilla.org/show_bug.cgi?id=94327#c34
04856  * for additional comments...
04857  */      
04858 #ifndef DISABLE_WORKAROUND_FOR_BUG_103159
04859       /* Skip 'mysterious' and 'spurious' cases like
04860        * -adobe-times-medium-r-normal--17-120-100-100-p-0-iso8859-9
04861        * The only "legal" use for this type of XLFD are Xprint
04862        * build-in printer fonts.like
04863        * -adobe-times-medium-r-normal--50-120-300-300-p-0-iso8859-1
04864        * (300DPI printer)
04865        */
04866       if ((pixelSize[0] != '0' || pointSize[0] != 0) && 
04867           (outline_scaled == PR_FALSE)
04868 #ifdef USE_XPRINT
04869            && (builtin_printer_font == PR_FALSE)
04870 #endif /* USE_XPRINT */          
04871           ) {
04872         PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("rejecting font '%s' (via hardcoded workaround for bug 103159)\n", list[i]));
04873         BANNED_FONT_PRINTF(("rejecting font '%s' (via hardcoded workaround for bug 103159)", list[i]));          
04874         continue;
04875       }  
04876 #endif /* DISABLE_WORKAROUND_FOR_BUG_103159 */
04877     }
04878     char* charSetName = p; // CHARSET_REGISTRY & CHARSET_ENCODING
04879     if (!*charSetName) {
04880       continue;
04881     }
04882     
04883     if (aOnlyOutlineScaledFonts && (outline_scaled == PR_FALSE)) {
04884       continue;
04885     }
04886 
04887 #ifdef ENABLE_X_FONT_BANNING
04888 #define BOOL2STR(b) ((b)?("true"):("false"))    
04889     if (aFmctx->mFontRejectRegEx || aFmctx->mFontAcceptRegEx) {
04890       char fmatchbuf[512]; /* See sprintf() below. */
04891            
04892       sprintf(fmatchbuf, "fname=%s;scalable=%s;outline_scaled=%s;xdisplay=%s;xdpy=%d;ydpy=%d;xdevice=%s",
04893               list[i], /* full font name */
04894               BOOL2STR(scalable), 
04895               BOOL2STR(outline_scaled),
04896               XDisplayString(dpy),
04897               screen_xres,
04898               screen_yres,
04899 #ifdef USE_XPRINT
04900               aFmctx->mPrinterMode?("printer"):
04901 #endif /* USE_XPRINT */
04902               ("display")
04903               );
04904 #undef BOOL2STR
04905                   
04906       if (aFmctx->mFontRejectRegEx) {
04907         /* reject font if reject pattern matches it... */        
04908         if (regexec(aFmctx->mFontRejectRegEx, fmatchbuf, 0, nsnull, 0) == REG_OK) {
04909           PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("rejecting font '%s' (via reject pattern)\n", fmatchbuf));
04910           BANNED_FONT_PRINTF(("rejecting font '%s' (via reject pattern)", fmatchbuf));
04911           continue;
04912         }  
04913       }
04914 
04915       if (aFmctx->mFontAcceptRegEx) {
04916         if (regexec(aFmctx->mFontAcceptRegEx, fmatchbuf, 0, nsnull, 0) == REG_NOMATCH) {
04917           PR_LOG(FontMetricsXlibLM, PR_LOG_DEBUG, ("rejecting font '%s' (via accept pattern)\n", fmatchbuf));
04918           BANNED_FONT_PRINTF(("rejecting font '%s' (via accept pattern)", fmatchbuf));
04919           continue;
04920         }
04921       }       
04922     }    
04923 #endif /* ENABLE_X_FONT_BANNING */    
04924 
04925     const nsFontCharSetMapXlib *charSetMap = GetCharSetMap(aFmctx, charSetName);
04926     nsFontCharSetInfoXlib* charSetInfo = charSetMap->mInfo;
04927     // indirection for font specific charset encoding 
04928     if (charSetInfo == aFmctx->mSpecial) {
04929       nsCAutoString familyCharSetName(familyName);
04930       familyCharSetName.Append('-');
04931       familyCharSetName.Append(charSetName);
04932       nsCStringKey familyCharSetKey(familyCharSetName);
04933       charSetMap = NS_STATIC_CAST(nsFontCharSetMapXlib*, aFmctx->mSpecialCharSets.Get(&familyCharSetKey));
04934       if (!charSetMap)
04935         charSetMap = aFmctx->mNoneCharSetMap;
04936       charSetInfo = charSetMap->mInfo;
04937     }
04938     if (!charSetInfo) {
04939 #ifdef NOISY_FONTS
04940       printf("cannot find charset %s\n", charSetName);
04941 #endif
04942       charSetInfo = aFmctx->mUnknown;
04943     }
04944     SetCharsetLangGroup(aFmctx, charSetInfo);
04945     SetFontLangGroupInfo(aFmctx, charSetMap);
04946 
04947     nsCAutoString nodeName;
04948     if (aAnyFoundry)
04949       nodeName.Assign('*');
04950     else
04951       nodeName.Assign(foundry);
04952     nodeName.Append('-');
04953     nodeName.Append(familyName);
04954     nodeName.Append('-');
04955     nodeName.Append(charSetName);
04956     nsCStringKey key(nodeName);
04957     nsFontNodeXlib* node = (nsFontNodeXlib*) node_hash->Get(&key);
04958     if (!node) {
04959       node = new nsFontNodeXlib;
04960       if (!node) {
04961         continue;
04962       }
04963       node_hash->Put(&key, node);
04964       node->mName = nodeName;
04965       node->mCharSetInfo = charSetInfo;
04966     }
04967 
04968     int found = 0;
04969     if (nodeName == previousNodeName) {
04970       found = 1;
04971     }
04972     else {
04973       found = (aNodes->IndexOf(node) >= 0);
04974     }
04975     previousNodeName = nodeName;
04976     if (!found) {
04977       aNodes->AppendElement(node);
04978     }
04979 
04980     int styleIndex;
04981     // XXX This does not cover the full XLFD spec for SLANT.
04982     switch (slant[0]) {
04983     case 'i':
04984       styleIndex = NS_FONT_STYLE_ITALIC;
04985       break;
04986     case 'o':
04987       styleIndex = NS_FONT_STYLE_OBLIQUE;
04988       break;
04989     case 'r':
04990     default:
04991       styleIndex = NS_FONT_STYLE_NORMAL;
04992       break;
04993     }
04994     nsFontStyleXlib* style = NodeGetStyle(node, styleIndex);
04995     if (!style)
04996       continue;
04997 
04998     nsCStringKey weightKey(weightName);
04999     int weightNumber = NS_PTR_TO_INT32(aFmctx->mWeights.Get(&weightKey));
05000     if (!weightNumber) {
05001 #ifdef NOISY_FONTS
05002       printf("cannot find weight %s\n", weightName);
05003 #endif
05004       weightNumber = NS_FONT_WEIGHT_NORMAL;
05005     }
05006     int weightIndex = WEIGHT_INDEX(weightNumber);
05007     nsFontWeightXlib* weight = NodeGetWeight(style, weightIndex);
05008     if (!weight)
05009       continue;
05010   
05011     nsCStringKey setWidthKey(setWidth);
05012     int stretchIndex = NS_PTR_TO_INT32(aFmctx->mStretches.Get(&setWidthKey));
05013     if (!stretchIndex) {
05014 #ifdef NOISY_FONTS
05015       printf("cannot find stretch %s\n", setWidth);
05016 #endif
05017       stretchIndex = 5;
05018     }
05019     stretchIndex--;
05020     nsFontStretchXlib* stretch = NodeGetStretch(weight, stretchIndex);
05021     if (!stretch)
05022       continue;
05023 
05024     if (scalable) {
05025       if (!NodeAddScalable(stretch, outline_scaled,
05026 #ifdef USE_XPRINT
05027                            builtin_printer_font, resX, resY, 
05028 #endif /* USE_XPRINT */
05029                            name, familyName, weightName, slant, setWidth, addStyle, spacing, charSetName))
05030         continue;
05031     }
05032   
05033     // get pixel size before the string is changed
05034     int pixels,
05035         points;
05036 
05037     pixels = atoi(pixelSize);
05038     points = atoi(pointSize);
05039 
05040     if (pixels) {
05041       if (aFmctx->mScaleBitmapFontsWithDevScale && (aFmctx->mDevScale > 1.0f)) {
05042         /* Add a font size which is exactly scaled as the scaling factor ... */
05043         if (!NodeAddSize(aFmctx, stretch, pixels, points, aFmctx->mDevScale, resX, resY, name, familyName, weightName, 
05044                          slant, setWidth, addStyle, spacing, charSetName, charSetInfo))
05045           continue;
05046 
05047         /* ... and offer a range of scaled fonts with integer scaling factors
05048          * (we're taking half steps between integers, too - to avoid too big
05049          * steps between font sizes) */
05050         float minScaler = PR_MAX(aFmctx->mDevScale / 2.0f, 1.5f),
05051               maxScaler = aFmctx->mDevScale * 2.f,
05052               scaler;
05053         for( scaler = minScaler ; scaler <= maxScaler ; scaler += 0.5f )
05054         {
05055           if (!NodeAddSize(aFmctx, stretch, pixels, points, scaler, resX, resY, name, familyName, weightName, 
05056                            slant, setWidth, addStyle, spacing, charSetName, charSetInfo))
05057             break;
05058         }
05059         if (scaler <= maxScaler) {
05060           continue; /* |NodeAddSize| returned an error in the loop above... */
05061         }
05062       }
05063       else
05064       {
05065         if (!NodeAddSize(aFmctx, stretch, pixels, points, 1.0f, resX, resY, name, familyName, weightName, 
05066                          slant, setWidth, addStyle, spacing, charSetName, charSetInfo))
05067           continue;     
05068       }
05069     }
05070   }
05071   XFreeFontNames(list);
05072 
05073 #ifdef DEBUG_DUMP_TREE
05074   DumpTree();
05075 #endif
05076 }
05077 
05078 static nsresult
05079 GetAllFontNames(nsFontMetricsXlibContext *aFmctx)
05080 {
05081   if (!aFmctx->mGlobalListInitalised) {
05082     aFmctx->mGlobalListInitalised = PR_TRUE;
05083     // This may well expand further (families * sizes * styles?), but it's
05084     // only created once.
05085 
05086     /* Using "-*" instead of the full-qualified "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"
05087      * because it's faster and "smarter" - see bug 34242 for details. */
05088     GetFontNames(aFmctx, "-*", PR_FALSE, PR_FALSE, &aFmctx->mGlobalList);
05089   }
05090 
05091   return NS_OK;
05092 }
05093 
05094 static nsFontFamilyXlib*
05095 FindFamily(nsFontMetricsXlibContext *aFmctx, nsCString* aName)
05096 {
05097   nsCStringKey key(*aName);
05098   nsFontFamilyXlib* family = (nsFontFamilyXlib*) aFmctx->mFamilies.Get(&key);
05099   if (!family) {
05100     family = new nsFontFamilyXlib();
05101     if (family) {
05102       char pattern[256];
05103       PR_snprintf(pattern, sizeof(pattern), "-*-%s-*-*-*-*-*-*-*-*-*-*-*-*",
05104         aName->get());
05105       GetFontNames(aFmctx, pattern, PR_TRUE, aFmctx->mForceOutlineScaledFonts, &family->mNodes);
05106       aFmctx->mFamilies.Put(&key, family);
05107     }
05108   }
05109 
05110   return family;
05111 }
05112 
05113 nsresult
05114 nsFontMetricsXlib::FamilyExists(nsFontMetricsXlibContext *aFontMetricsContext, const nsString& aName)
05115 {
05116   if (!global_fmctx) {
05117     global_fmctx = aFontMetricsContext;
05118   }
05119 
05120   if (!IsASCIIFontName(aName)) {
05121     return NS_ERROR_FAILURE;
05122   }
05123 
05124   nsCAutoString name;
05125   name.AssignWithConversion(aName.get());
05126   ToLowerCase(name);
05127   nsFontFamilyXlib* family = FindFamily(aFontMetricsContext, &name);
05128   if (family && family->mNodes.Count()) {
05129     return NS_OK;
05130   }
05131 
05132   return NS_ERROR_FAILURE;
05133 }
05134 
05135 //
05136 // convert a FFRE (Foundry-Family-Registry-Encoding) To XLFD Pattern
05137 //
05138 static void
05139 FFREToXLFDPattern(nsACString &aFFREName, nsACString &oPattern)
05140 {
05141   PRInt32 charsetHyphen;
05142 
05143   oPattern.Append("-");
05144   oPattern.Append(aFFREName);
05145   /* Search for the 3rd appearance of '-' */
05146   charsetHyphen = oPattern.FindChar('-');
05147   charsetHyphen = oPattern.FindChar('-', charsetHyphen + 1);
05148   charsetHyphen = oPattern.FindChar('-', charsetHyphen + 1);
05149   oPattern.Insert("-*-*-*-*-*-*-*-*-*-*", charsetHyphen);
05150 }
05151 
05152 //
05153 // substitute the charset in a FFRE (Foundry-Family-Registry-Encoding)
05154 //
05155 static void
05156 FFRESubstituteCharset(nsACString &aFFREName,
05157                       const char *aReplacementCharset)
05158 {
05159   PRInt32 charsetHyphen = aFFREName.FindChar('-');
05160   charsetHyphen = aFFREName.FindChar('-', charsetHyphen + 1);
05161   aFFREName.Truncate(charsetHyphen+1);
05162   aFFREName.Append(aReplacementCharset);
05163 }
05164 
05165 //
05166 // substitute the encoding in a FFRE (Foundry-Family-Registry-Encoding)
05167 //
05168 static void
05169 FFRESubstituteEncoding(nsACString &aFFREName,
05170                        const char *aReplacementEncoding)
05171 {
05172   PRInt32 encodingHyphen;
05173   /* Search for the 3rd apperance of '-' */
05174   encodingHyphen = aFFREName.FindChar('-');
05175   encodingHyphen = aFFREName.FindChar('-', encodingHyphen + 1);
05176   encodingHyphen = aFFREName.FindChar('-', encodingHyphen + 1);
05177   aFFREName.Truncate(encodingHyphen+1);
05178   aFFREName.Append(aReplacementEncoding);
05179 }
05180 
05181 nsFontXlib*
05182 nsFontMetricsXlib::TryNodes(nsACString &aFFREName, PRUnichar aChar)
05183 {
05184   const nsPromiseFlatCString& FFREName = PromiseFlatCString(aFFREName);
05185 
05186   FIND_FONT_PRINTF(("        TryNodes aFFREName = %s", FFREName.get()));
05187   nsCStringKey key(FFREName);
05188   PRBool anyFoundry = (FFREName.First() == '*');
05189   nsFontNodeArrayXlib* nodes = (nsFontNodeArrayXlib*) mFontMetricsContext->mCachedFFRESearches.Get(&key);
05190   if (!nodes) {
05191     nsCAutoString pattern;
05192     FFREToXLFDPattern(aFFREName, pattern);
05193     nodes = new nsFontNodeArrayXlib;
05194     if (!nodes)
05195       return nsnull;
05196     GetFontNames(mFontMetricsContext, pattern.get(), anyFoundry, mFontMetricsContext->mForceOutlineScaledFonts, nodes);
05197     mFontMetricsContext->mCachedFFRESearches.Put(&key, nodes);
05198   }
05199   int i, cnt = nodes->Count();
05200   for (i=0; i<cnt; i++) {
05201     nsFontNodeXlib* node = nodes->GetElement(i);
05202     nsFontXlib * font;
05203     font = SearchNode(node, aChar);
05204     if (font && font->SupportsChar(aChar))
05205       return font;
05206   }
05207   return nsnull;
05208 }
05209 
05210 nsFontXlib*
05211 nsFontMetricsXlib::TryNode(nsCString* aName, PRUnichar aChar)
05212 {
05213   FIND_FONT_PRINTF(("        TryNode aName = %s", (*aName).get()));
05214   //
05215   // check the specified font (foundry-family-registry-encoding)
05216   //
05217   if (aName->IsEmpty()) {
05218     return nsnull;
05219   }
05220   nsFontXlib* font;
05221  
05222   nsCStringKey key(*aName);
05223   nsFontNodeXlib* node = (nsFontNodeXlib*) mFontMetricsContext->mFFRENodes.Get(&key);
05224   if (!node) {
05225     nsCAutoString pattern;
05226     FFREToXLFDPattern(*aName, pattern);
05227     nsFontNodeArrayXlib nodes;
05228     GetFontNames(mFontMetricsContext, pattern.get(), PR_FALSE, mFontMetricsContext->mForceOutlineScaledFonts, &nodes);
05229     // no need to call mFontMetricsContext->mFFRENodes.Put() since GetFontNames already did
05230     if (nodes.Count() > 0) {
05231       // This assertion is not spurious; when searching for an FFRE
05232       // like -*-courier-iso8859-1 TryNodes should be called not TryNode
05233       NS_ASSERTION((nodes.Count() == 1), "unexpected number of nodes");
05234       node = nodes.GetElement(0);
05235     }
05236     else {
05237       // add a dummy node to the hash table to avoid calling XListFonts again
05238       node = new nsFontNodeXlib();
05239       if (!node) {
05240         return nsnull;
05241       }
05242       mFontMetricsContext->mFFRENodes.Put(&key, node);
05243       node->mDummy = 1;
05244     }
05245   }
05246 
05247   if (node) {
05248     font = SearchNode(node, aChar);
05249     if (font && font->SupportsChar(aChar))
05250       return font;
05251   }
05252 
05253   //
05254   // do not check related sub-planes for UserDefined
05255   //
05256   if (mIsUserDefined) {
05257     return nsnull;
05258   }
05259   //
05260   // check related sub-planes (wild-card the encoding)
05261   //
05262   nsCAutoString ffreName(*aName);
05263   FFRESubstituteEncoding(ffreName, "*");
05264   FIND_FONT_PRINTF(("        TrySubplane: wild-card the encoding"));
05265   font = TryNodes(ffreName, aChar);
05266   if (font) {
05267     NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05268     return font;
05269   }
05270   return nsnull;
05271 }
05272 
05273 nsFontXlib* 
05274 nsFontMetricsXlib::TryLangGroup(nsIAtom* aLangGroup, nsCString* aName, PRUnichar aChar)
05275 {
05276   //
05277   // for this family check related registry-encoding (for the language)
05278   //
05279   FIND_FONT_PRINTF(("      TryLangGroup lang group = %s, aName = %s", 
05280                             atomToName(aLangGroup), (*aName).get()));
05281   if (aName->IsEmpty()) {
05282     return nsnull;
05283   }
05284   nsFontXlib* font = FindLangGroupFont(aLangGroup, aChar, aName);
05285   return font;
05286 }
05287 
05288 nsFontXlib*
05289 nsFontMetricsXlib::TryFamily(nsCString* aName, PRUnichar aChar)
05290 {
05291   //
05292   // check the patterh "*-familyname-registry-encoding" for language
05293   //
05294   nsFontFamilyXlib* family = FindFamily(mFontMetricsContext, aName);
05295   if (family) {
05296     // try family name of language group first
05297     nsCAutoString FFREName("*-");
05298     FFREName.Append(*aName);
05299     FFREName.Append("-*-*");
05300     FIND_FONT_PRINTF(("        TryFamily %s with lang group = %s", (*aName).get(),
05301                                                          atomToName(mLangGroup)));
05302     nsFontXlib* font = TryLangGroup(mLangGroup, &FFREName, aChar);
05303     if(font) {
05304       return font;
05305     }
05306 
05307     // then try family name regardless of language group
05308     nsFontNodeArrayXlib* nodes = &family->mNodes;
05309     PRInt32 n = nodes->Count();
05310     for (PRInt32 i = 0; i < n; i++) {
05311       FIND_FONT_PRINTF(("        TryFamily %s", nodes->GetElement(i)->mName.get()));
05312       nsFontXlib* font = SearchNode(nodes->GetElement(i), aChar);
05313       if (font && font->SupportsChar(aChar)) {
05314         return font;
05315       }
05316     }
05317   }
05318 
05319   return nsnull;
05320 }
05321 
05322 nsFontXlib*
05323 nsFontMetricsXlib::TryAliases(nsCString* aAlias, PRUnichar aChar)
05324 {
05325   nsCStringKey key(*aAlias);
05326   char* name = (char*) mFontMetricsContext->mAliases.Get(&key);
05327   if (name) {
05328     nsCAutoString str(name);
05329     return TryFamily(&str, aChar);
05330   }
05331 
05332   return nsnull;
05333 }
05334 
05335 nsFontXlib*
05336 nsFontMetricsXlib::FindUserDefinedFont(PRUnichar aChar)
05337 {
05338   if (mIsUserDefined) {
05339     FIND_FONT_PRINTF(("        FindUserDefinedFont"));
05340     nsFontXlib* font = TryNode(&mUserDefined, aChar);
05341     mIsUserDefined = PR_FALSE;
05342     if (font) {
05343       NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05344       return font;
05345     }
05346   }
05347 
05348   return nsnull;
05349 }
05350 
05351 nsFontXlib*
05352 nsFontMetricsXlib::FindStyleSheetSpecificFont(PRUnichar aChar)
05353 {
05354   FIND_FONT_PRINTF(("    FindStyleSheetSpecificFont"));
05355   while (mFontsIndex < mFonts.Count()) {
05356     if (mFontIsGeneric[mFontsIndex]) {
05357       return nsnull;
05358     }
05359     nsCString* familyName = mFonts.CStringAt(mFontsIndex);
05360 
05361     /*
05362      * count hyphens
05363      * XXX It might be good to try to pre-cache this information instead
05364      * XXX of recalculating it on every font access!
05365      */
05366     const char* str = familyName->get();
05367     FIND_FONT_PRINTF(("        familyName = %s", str));
05368     PRUint32 len = familyName->Length();
05369     int hyphens = 0;
05370     for (PRUint32 i = 0; i < len; i++) {
05371       if (str[i] == '-') {
05372         hyphens++;
05373       }
05374     }
05375 
05376     /*
05377      * if there are 3 hyphens, the name is in FFRE form
05378      * (foundry-family-registry-encoding)
05379      * ie: something like this:
05380      *
05381      *   adobe-times-iso8859-1
05382      *
05383      * otherwise it is something like
05384      *
05385      *   times new roman
05386      */
05387     nsFontXlib* font;
05388     if (hyphens == 3) {
05389       font = TryNode(familyName, aChar);
05390       if (font) {
05391         NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05392         return font;
05393       }
05394     }
05395     else {
05396       font = TryFamily(familyName, aChar);
05397       if (font) {
05398         NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05399         return font;
05400       }
05401       font = TryAliases(familyName, aChar);
05402       if (font) {
05403         NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05404         return font;
05405       }
05406     }
05407     // bug 42917: increment only after all of the above fails
05408     mFontsIndex++;
05409   }
05410 
05411   return nsnull;
05412 }
05413 
05414 static void
05415 PrefEnumCallback(const char* aName, void* aClosure)
05416 {
05417   nsFontSearch* s = (nsFontSearch*) aClosure;
05418   nsFontMetricsXlibContext *aFmctx = s->mMetrics->mFontMetricsContext;
05419 
05420   if (s->mFont) {
05421     NS_ASSERTION(s->mFont->SupportsChar(s->mChar), "font supposed to support this char");
05422     return;
05423   }
05424   nsXPIDLCString value;
05425   aFmctx->mPref->CopyCharPref(aName, getter_Copies(value));
05426   nsCAutoString name;
05427   if (value.get()) {
05428     name = value;
05429     FIND_FONT_PRINTF(("       PrefEnumCallback"));
05430     s->mFont = s->mMetrics->TryNode(&name, s->mChar);
05431     if (s->mFont) {
05432       NS_ASSERTION(s->mFont->SupportsChar(s->mChar), "font supposed to support this char");
05433       return;
05434     }
05435     s->mFont = s->mMetrics->TryLangGroup(s->mMetrics->mLangGroup, &name, s->mChar);
05436     if (s->mFont) {
05437       NS_ASSERTION(s->mFont->SupportsChar(s->mChar), "font supposed to support this char");
05438       return;
05439     }
05440   }
05441   aFmctx->mPref->CopyDefaultCharPref(aName, getter_Copies(value));
05442   if (value.get() && (!name.Equals(value))) {
05443     name = value;
05444     FIND_FONT_PRINTF(("       PrefEnumCallback:default"));
05445     s->mFont = s->mMetrics->TryNode(&name, s->mChar);
05446     if (s->mFont) {
05447       NS_ASSERTION(s->mFont->SupportsChar(s->mChar), "font supposed to support this char");
05448       return;
05449     }
05450     s->mFont = s->mMetrics->TryLangGroup(s->mMetrics->mLangGroup, &name, s->mChar);
05451     NS_ASSERTION(s->mFont ? s->mFont->SupportsChar(s->mChar) : 1, "font supposed to support this char");
05452   }
05453 }
05454 
05455 nsFontXlib*
05456 nsFontMetricsXlib::FindStyleSheetGenericFont(PRUnichar aChar)
05457 {
05458   FIND_FONT_PRINTF(("    FindStyleSheetGenericFont"));
05459   nsFontXlib* font;
05460 
05461   if (mTriedAllGenerics) {
05462     return nsnull;
05463   }
05464 
05465   //
05466   // find font based on document's lang group
05467   //
05468   font = FindLangGroupPrefFont(mLangGroup, aChar);
05469   if (font) {
05470     NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05471     return font;
05472   }
05473 
05474   //
05475   // Asian smart quote glyphs are much too large for western
05476   // documents so if this is a single byte document add a
05477   // special "font" to tranliterate those chars rather than
05478   // possibly find them in double byte fonts
05479   //
05480   // (risk management: since we are close to a ship point we have a 
05481   //  control (mAllowDoubleByteSpecialChars) to disable this new feature)
05482   //
05483 if (mFontMetricsContext->mAllowDoubleByteSpecialChars) {
05484   if (!mDocConverterType) {
05485     if (mLoadedFontsCount) {
05486       FIND_FONT_PRINTF(("just use the 1st converter type"));
05487       nsFontXlib* first_font = mLoadedFonts[0];
05488       if (first_font->mCharSetInfo) {
05489         mDocConverterType = first_font->mCharSetInfo->Convert;
05490         if (mDocConverterType == SingleByteConvert ) {
05491           FIND_FONT_PRINTF(("single byte converter for %s", atomToName(mLangGroup)));
05492         }
05493         else {
05494           FIND_FONT_PRINTF(("double byte converter for %s", atomToName(mLangGroup)));
05495         }
05496       }
05497     }
05498     if (!mDocConverterType) {
05499       mDocConverterType = SingleByteConvert;
05500     }
05501     if (mDocConverterType == SingleByteConvert) {
05502       // before we put in the transliterator to disable double byte special chars
05503       // add the x-western font before the early transliterator
05504       // to get the EURO sign (hack)
05505 
05506       nsFontXlib* western_font = nsnull;
05507       if (mLangGroup != mFontMetricsContext->mWesternLocale)
05508         western_font = FindLangGroupPrefFont(mFontMetricsContext->mWesternLocale, aChar);
05509 
05510       // add the symbol font before the early transliterator
05511       // to get the bullet (hack)
05512       nsCAutoString symbol_ffre("*-symbol-adobe-fontspecific");
05513       nsFontXlib* symbol_font = TryNodes(symbol_ffre, 0x0030);
05514 
05515       // Add the Adobe Euro fonts before the early transliterator
05516       nsCAutoString euro_ffre("*-euro*-adobe-fontspecific");
05517       nsFontXlib* euro_font = TryNodes(euro_ffre, 0x20AC);
05518 
05519       // add the early transliterator
05520       // to avoid getting Japanese "special chars" such as smart
05521       // since they are very oversized compared to western fonts
05522       nsFontXlib* sub_font = FindSubstituteFont(aChar);
05523       NS_ASSERTION(sub_font, "failed to get a special chars substitute font");
05524       if (sub_font) {
05525         sub_font->mCCMap = mFontMetricsContext->mDoubleByteSpecialCharsCCMap;
05526         AddToLoadedFontsList(sub_font);
05527       }
05528       if (western_font && CCMAP_HAS_CHAR(western_font->mCCMap, aChar)) {
05529         return western_font;
05530       }
05531       else if (symbol_font && CCMAP_HAS_CHAR(symbol_font->mCCMap, aChar)) {
05532         return symbol_font;
05533       }
05534       else if (euro_font && CCMAP_HAS_CHAR(euro_font->mCCMap, aChar)) {
05535         return euro_font;
05536       }
05537       else if (sub_font && CCMAP_HAS_CHAR(sub_font->mCCMap, aChar)) {
05538         FIND_FONT_PRINTF(("      transliterate special chars for single byte docs"));
05539         return sub_font;
05540       }
05541     }
05542   }
05543 }
05544 
05545   //
05546   // find font based on user's locale's lang group
05547   // if different from documents locale
05548   if (mFontMetricsContext->mUsersLocale != mLangGroup) {
05549     FIND_FONT_PRINTF(("      find font based on user's locale's lang group"));
05550     font = FindLangGroupPrefFont(mFontMetricsContext->mUsersLocale, aChar);
05551     if (font) {
05552       NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05553       return font;
05554     }
05555   }
05556 
05557   //
05558   // Search all font prefs for generic
05559   //
05560   nsCAutoString prefix("font.name.");
05561   prefix.Append(*mGeneric);
05562   nsFontSearch search = { this, aChar, nsnull };
05563   FIND_FONT_PRINTF(("      Search all font prefs for generic"));
05564   mFontMetricsContext->mPref->EnumerateChildren(prefix.get(), PrefEnumCallback, &search);
05565   if (search.mFont) {
05566     NS_ASSERTION(search.mFont->SupportsChar(aChar), "font supposed to support this char");
05567     return search.mFont;
05568   }
05569 
05570   //
05571   // Search all font prefs
05572   //
05573   // find based on all prefs (no generic part (eg: sans-serif))
05574   nsCAutoString allPrefs("font.name.");
05575   search.mFont = nsnull;
05576   FIND_FONT_PRINTF(("      Search all font prefs"));
05577   mFontMetricsContext->mPref->EnumerateChildren(allPrefs.get(), PrefEnumCallback, &search);
05578   if (search.mFont) {
05579     NS_ASSERTION(search.mFont->SupportsChar(aChar), "font supposed to support this char");
05580     return search.mFont;
05581   }
05582 
05583   mTriedAllGenerics = 1;
05584   return nsnull;
05585 }
05586 
05587 nsFontXlib*
05588 nsFontMetricsXlib::FindAnyFont(PRUnichar aChar)
05589 {
05590   FIND_FONT_PRINTF(("    FindAnyFont"));
05591 
05592   // XXX If we get to this point, that means that we have exhausted all the
05593   // families in the lists. Maybe we should try a list of fonts that are
05594   // specific to the vendor of the X server here. Because XListFonts for the
05595   // whole list is very expensive on some Unixes.
05596 
05597   /*
05598    * Try all the fonts on the system.
05599    */
05600   nsresult res = GetAllFontNames(mFontMetricsContext);
05601   if (NS_FAILED(res))
05602     return nsnull;
05603 
05604   PRInt32 n = mFontMetricsContext->mGlobalList.Count();
05605   for (PRInt32 i = 0; i < n; i++) {
05606     nsFontXlib* font = SearchNode(mFontMetricsContext->mGlobalList.GetElement(i), aChar);
05607     if (font && font->SupportsChar(aChar)) {
05608       // XXX We should probably write this family name out to disk, so that
05609       // we can use it next time. I.e. prefs file or something.
05610       return font;
05611     }
05612   }
05613 
05614   // future work:
05615   // to properly support the substitute font we
05616   // need to indicate here that all fonts have been tried
05617   return nsnull;
05618 }
05619 
05620 nsFontXlib*
05621 nsFontMetricsXlib::FindSubstituteFont(PRUnichar aChar)
05622 {
05623   if (!mSubstituteFont) {
05624     for (int i = 0; i < mLoadedFontsCount; i++) {
05625       if (CCMAP_HAS_CHAR(mLoadedFonts[i]->mCCMap, 'a')) {
05626         mSubstituteFont = new nsFontXlibSubstitute(mLoadedFonts[i]);
05627         break;
05628       }
05629     }
05630     // Currently the substitute font does not have a glyph map.
05631     // This means that even if we have already checked all fonts
05632     // for a particular character the mLoadedFonts will not know it.
05633     // Thus we reparse *all* font glyph maps every time we see
05634     // a character that ends up using a substitute font.
05635     // future work:
05636     // create an empty mCCMap and every time we determine a
05637     // character will get its "glyph" from the substitute font
05638     // mark that character in the mCCMap.
05639   }
05640   // mark the mCCMap to indicate that this character has a "glyph"
05641 
05642   // If we know that mLoadedFonts has every font's glyph map loaded
05643   // then we can now set all the bit in the substitute font's glyph map
05644   // and thus direct all umapped characters to the substitute
05645   // font (without the font search).
05646   // if tried all glyphs {
05647   //   create a substitute font with all bits set
05648   //   set all bits in mCCMap
05649   // }
05650 
05651   return mSubstituteFont;
05652 }
05653 
05654 //
05655 // find font based on lang group
05656 //
05657 
05658 nsFontXlib* 
05659 nsFontMetricsXlib::FindLangGroupPrefFont(nsIAtom* aLangGroup, PRUnichar aChar)
05660 { 
05661   nsFontXlib* font;
05662   //
05663   // get the font specified in prefs
05664   //
05665   nsCAutoString prefix("font.name."); 
05666   prefix.Append(*mGeneric); 
05667   if (aLangGroup) { 
05668     // check user set pref
05669     nsCAutoString pref = prefix;
05670     pref.Append(char('.'));
05671     const char* langGroup = nsnull;
05672     aLangGroup->GetUTF8String(&langGroup);
05673     pref.Append(langGroup);
05674     nsXPIDLCString value;
05675     mFontMetricsContext->mPref->CopyCharPref(pref.get(), getter_Copies(value));
05676     nsCAutoString str;
05677     nsCAutoString str_user;
05678     if (value.get()) {
05679       str = value.get();
05680       str_user = value.get();
05681       FIND_FONT_PRINTF(("      user pref %s = %s", pref.get(), str.get()));
05682       font = TryNode(&str, aChar);
05683       if (font) {
05684         NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05685         return font;
05686       }
05687       font = TryLangGroup(aLangGroup, &str, aChar);
05688       if (font) {
05689         NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05690         return font;
05691       }
05692     }
05693     // check factory set pref
05694     mFontMetricsContext->mPref->CopyDefaultCharPref(pref.get(), getter_Copies(value));
05695     if (value.get()) {
05696       str = value.get();
05697       // check if we already tried this name
05698       if (str != str_user) {
05699         FIND_FONT_PRINTF(("      default pref %s = %s", pref.get(), str.get()));
05700         font = TryNode(&str, aChar);
05701         if (font) {
05702           NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05703           return font;
05704         }
05705         font = TryLangGroup(aLangGroup, &str, aChar);
05706         if (font) {
05707           NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05708           return font;
05709         }
05710       }
05711     }
05712   }
05713 
05714   //
05715   // find any style font based on lang group
05716   //
05717   FIND_FONT_PRINTF(("      find font based on lang group"));
05718   font = FindLangGroupFont(aLangGroup, aChar, nsnull);
05719   if (font) {
05720     NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05721     return font;
05722   }
05723 
05724   return nsnull;
05725 }
05726 
05727 nsFontXlib*
05728 nsFontMetricsXlib::FindLangGroupFont(nsIAtom* aLangGroup, PRUnichar aChar, nsCString *aName)
05729 {
05730   nsFontXlib* font;
05731 
05732   FIND_FONT_PRINTF(("      lang group = %s", atomToName(aLangGroup)));
05733 
05734   //  scan mCharSetMap for encodings with matching lang groups
05735   const nsFontCharSetMapXlib* charSetMap;
05736   for (charSetMap=mFontMetricsContext->mCharSetMap; charSetMap->mName; charSetMap++) {
05737     nsFontLangGroupXlib* fontLangGroup = charSetMap->mFontLangGroup;
05738 
05739     if ((!fontLangGroup) || (!fontLangGroup->mFontLangGroupName)) {
05740       continue;
05741     }
05742 
05743     if (!charSetMap->mInfo->mLangGroup) {
05744       SetCharsetLangGroup(mFontMetricsContext, charSetMap->mInfo);
05745     }
05746 
05747     if (!fontLangGroup->mFontLangGroupAtom) {
05748       SetFontLangGroupInfo(mFontMetricsContext, charSetMap);
05749     }
05750 
05751     // if font's langGroup is different from requested langGroup, continue.
05752     // An exception is that font's langGroup ZHTWHK is regarded as matching
05753     // both ZHTW and ZHHK (Freetype2 and Solaris).
05754     if ((aLangGroup != fontLangGroup->mFontLangGroupAtom) &&
05755         (aLangGroup != charSetMap->mInfo->mLangGroup) &&
05756         (fontLangGroup->mFontLangGroupAtom != mFontMetricsContext->mZHTWHK || 
05757         (aLangGroup != mFontMetricsContext->mZHHK && aLangGroup != mFontMetricsContext->mZHTW))) {
05758       continue;
05759     }
05760     // look for a font with this charset (registry-encoding) & char
05761     //
05762     nsCAutoString ffreName;
05763     if(aName) {
05764       // if aName was specified so call TryNode() not TryNodes()
05765       ffreName.Assign(*aName);
05766       FFRESubstituteCharset(ffreName, charSetMap->mName); 
05767       FIND_FONT_PRINTF(("      %s ffre = %s", charSetMap->mName, ffreName.get()));
05768       if(aName->First() == '*') {
05769          // called from TryFamily()
05770          font = TryNodes(ffreName, aChar);
05771       } else {
05772          font = TryNode(&ffreName, aChar);
05773       }
05774       NS_ASSERTION(font ? font->SupportsChar(aChar) : 1, "font supposed to support this char");
05775     } else {
05776       // no name was specified so call TryNodes() for this charset
05777       ffreName.Assign("*-*-*-*");
05778       FFRESubstituteCharset(ffreName, charSetMap->mName); 
05779       FIND_FONT_PRINTF(("      %s ffre = %s", charSetMap->mName, ffreName.get()));
05780       font = TryNodes(ffreName, aChar);
05781       NS_ASSERTION(font ? font->SupportsChar(aChar) : 1, "font supposed to support this char");
05782     }
05783     if (font) {
05784       NS_ASSERTION(font->SupportsChar(aChar), "font supposed to support this char");
05785       return font;
05786     }
05787   }
05788 
05789   return nsnull;
05790 }
05791 
05792 /*
05793  * First we try to load the user-defined font, if the user-defined charset
05794  * has been selected in the menu.
05795  *
05796  * Next, we try the fonts listed in the font-family property (FindStyleSheetSpecificFont).
05797  *
05798  * Next, we try any CSS generic font encountered in the font-family list and
05799  * all of the fonts specified by the user for the generic (FindStyleSheetGenericFont).
05800  *
05801  * Next, we try all of the fonts on the system (FindAnyFont). This is
05802  * expensive on some Unixes.
05803  *
05804  * Finally, we try to create a substitute font that offers substitute glyphs
05805  * for the characters (FindSubstituteFont).
05806  */
05807 nsFontXlib*
05808 nsFontMetricsXlib::FindFont(PRUnichar aChar)
05809 {
05810   FIND_FONT_PRINTF(("\nFindFont(%c/0x%04x)", aChar, aChar));
05811 
05812   // If this is is the 'unknown' char (ie: converter could not 
05813   // convert it) there is no sense in searching any further for 
05814   // a font. Just returing mWesternFont
05815   if (aChar == UCS2_NOMAPPING) {
05816     FIND_FONT_PRINTF(("      ignore the 'UCS2_NOMAPPING' character, return mWesternFont"));
05817     return mWesternFont;
05818   }
05819 
05820   nsFontXlib* font = FindUserDefinedFont(aChar);
05821   if (!font) {
05822     font = FindStyleSheetSpecificFont(aChar);
05823     if (!font) {
05824       font = FindStyleSheetGenericFont(aChar);
05825       if (!font) {
05826         font = FindAnyFont(aChar);
05827         if (!font) {
05828           font = FindSubstituteFont(aChar);
05829         }
05830       }
05831     }
05832   }
05833 
05834 #ifdef NS_FONT_DEBUG_CALL_TRACE
05835   if (gFontDebug & NS_FONT_DEBUG_CALL_TRACE) {
05836     printf("FindFont(%04X)[", aChar);
05837     for (PRInt32 i = 0; i < mFonts.Count(); i++) {
05838       printf("%s, ", mFonts.CStringAt(i)->get());
05839     }
05840     printf("]\nreturns ");
05841     if (font) {
05842       printf("%s\n", font->mName ? font->mName : "(substitute)");
05843     }
05844     else {
05845       printf("NULL\n");
05846     }
05847   }
05848 #endif
05849 
05850   return font;
05851 }
05852 
05853 
05854 // The Font Enumerator
05855 
05856 nsFontEnumeratorXlib::nsFontEnumeratorXlib()
05857 {
05858 }
05859 
05860 NS_IMPL_ISUPPORTS1(nsFontEnumeratorXlib, nsIFontEnumerator)
05861 
05862 typedef struct EnumerateNodeInfo
05863 {
05864   PRUnichar** mArray;
05865   int         mIndex;
05866   nsIAtom*    mLangGroup;
05867   nsFontMetricsXlibContext *mFontMetricsContext;
05868 } EnumerateNodeInfo;
05869 
05870 static PRIntn
05871 EnumerateNode(void* aElement, void* aData)
05872 {
05873   nsFontNodeXlib* node = (nsFontNodeXlib*) aElement;
05874   EnumerateNodeInfo* info = (EnumerateNodeInfo*) aData;
05875   nsFontMetricsXlibContext *aFmctx = info->mFontMetricsContext;
05876   if (info->mLangGroup != aFmctx->mUserDefined) {
05877     if (node->mCharSetInfo == aFmctx->mUnknown) {
05878       return PR_TRUE; // continue
05879     }
05880     else if (info->mLangGroup != aFmctx->mUnicode) {
05881       // if font's langGroup is different from requested langGroup, continue.
05882       // An exception is that font's langGroup ZHTWHK(big5-1, big5-0) matches 
05883       // both ZHTW and ZHHK (Freetype2 and Solaris).
05884       if (node->mCharSetInfo->mLangGroup != info->mLangGroup &&
05885          (node->mCharSetInfo->mLangGroup != aFmctx->mZHTWHK ||
05886          (info->mLangGroup != aFmctx->mZHHK && 
05887           info->mLangGroup != aFmctx->mZHTW))) {
05888         return PR_TRUE; // continue
05889       }
05890     }
05891     // else {
05892     //   if (lang == add-style-field) {
05893     //     consider it part of the lang group
05894     //   }
05895     //   else if (a Unicode font reports its lang group) {
05896     //     consider it part of the lang group
05897     //   }
05898     //   else if (lang's ranges in list of ranges) {
05899     //     consider it part of the lang group
05900     //     // Note: at present we have no way to do this test but we 
05901     //     // could in the future and this would be the place to enable
05902     //     // to make the font show up in the preferences dialog
05903     //   }
05904     // }
05905 
05906   }
05907   PRUnichar** array = info->mArray;
05908   int j = info->mIndex;
05909   PRUnichar* str = ToNewUnicode(node->mName);
05910   if (!str) {
05911     for (j = j - 1; j >= 0; j--) {
05912       nsMemory::Free(array[j]);
05913     }
05914     info->mIndex = 0;
05915     return PR_FALSE; // stop
05916   }
05917   array[j] = str;
05918   info->mIndex++;
05919 
05920   return PR_TRUE; // continue
05921 }
05922 
05923 PR_BEGIN_EXTERN_C
05924 static int
05925 CompareFontNames(const void* aArg1, const void* aArg2, void* aClosure)
05926 {
05927   const PRUnichar* str1 = *((const PRUnichar**) aArg1);
05928   const PRUnichar* str2 = *((const PRUnichar**) aArg2);
05929 
05930   // XXX add nsICollation stuff
05931 
05932   return nsCRT::strcmp(str1, str2);
05933 }
05934 PR_END_EXTERN_C
05935 
05936 static nsresult
05937 EnumFonts(nsFontMetricsXlibContext *aFmctx, nsIAtom* aLangGroup, const char* aGeneric, PRUint32* aCount,
05938   PRUnichar*** aResult)
05939 {
05940   nsresult res = GetAllFontNames(aFmctx);
05941   if (NS_FAILED(res))
05942     return res;
05943 
05944   PRUnichar** array =
05945     (PRUnichar**) nsMemory::Alloc(aFmctx->mGlobalList.Count() * sizeof(PRUnichar*));
05946   if (!array)
05947     return NS_ERROR_OUT_OF_MEMORY;
05948 
05949   EnumerateNodeInfo info = { array, 0, aLangGroup, aFmctx };
05950   if (!aFmctx->mGlobalList.EnumerateForwards(EnumerateNode, &info)) {
05951     nsMemory::Free(array);
05952     return NS_ERROR_OUT_OF_MEMORY;
05953   }
05954 
05955   NS_QuickSort(array, info.mIndex, sizeof(PRUnichar*), CompareFontNames,
05956                nsnull);
05957 
05958   *aCount = info.mIndex;
05959   if (*aCount) {
05960     *aResult = array;
05961   }
05962   else {
05963     nsMemory::Free(array);
05964   }
05965 
05966   return NS_OK;
05967 }
05968 
05969 NS_IMETHODIMP
05970 nsFontEnumeratorXlib::EnumerateAllFonts(PRUint32* aCount, PRUnichar*** aResult)
05971 {
05972   NS_ENSURE_ARG_POINTER(aResult);
05973   *aResult = nsnull;
05974   NS_ENSURE_ARG_POINTER(aCount);
05975   *aCount = 0;
05976 
05977   return EnumFonts(global_fmctx, nsnull, nsnull, aCount, aResult);
05978 }
05979 
05980 NS_IMETHODIMP
05981 nsFontEnumeratorXlib::EnumerateFonts(const char* aLangGroup,
05982   const char* aGeneric, PRUint32* aCount, PRUnichar*** aResult)
05983 {
05984   NS_ENSURE_ARG_POINTER(aResult);
05985   *aResult = nsnull;
05986   NS_ENSURE_ARG_POINTER(aCount);
05987   *aCount = 0;
05988 
05989   // aLangGroup=null or ""  means any (i.e., don't care)
05990   // aGeneric=null or ""  means any (i.e, don't care)
05991   nsCOMPtr<nsIAtom> langGroup;
05992   if (aLangGroup && *aLangGroup)
05993     langGroup = do_GetAtom(aLangGroup);
05994   const char* generic = nsnull;
05995   if (aGeneric && *aGeneric)
05996     generic = aGeneric;
05997 
05998   // XXX still need to implement aLangGroup and aGeneric
05999   return EnumFonts(global_fmctx, langGroup, generic, aCount, aResult);
06000 }
06001 
06002 NS_IMETHODIMP
06003 nsFontEnumeratorXlib::HaveFontFor(const char* aLangGroup, PRBool* aResult)
06004 {
06005   NS_ENSURE_ARG_POINTER(aResult);
06006   *aResult = PR_FALSE;
06007   NS_ENSURE_ARG_POINTER(aLangGroup);
06008 
06009   *aResult = PR_TRUE; // always return true for now.
06010   // Finish me - ftang
06011   return NS_OK;
06012 }
06013 
06014 NS_IMETHODIMP
06015 nsFontEnumeratorXlib::GetDefaultFont(const char *aLangGroup, 
06016   const char *aGeneric, PRUnichar **aResult)
06017 {
06018   // aLangGroup=null or ""  means any (i.e., don't care)
06019   // aGeneric=null or ""  means any (i.e, don't care)
06020 
06021   NS_ENSURE_ARG_POINTER(aResult);
06022   *aResult = nsnull;
06023 
06024   return NS_OK;
06025 }
06026 
06027 NS_IMETHODIMP
06028 nsFontEnumeratorXlib::UpdateFontList(PRBool *updateFontList)
06029 {
06030   *updateFontList = PR_FALSE; // always return false for now
06031   return NS_OK;
06032 }
06033 
06034 static
06035 const nsFontCharSetMapXlib *GetCharSetMap(nsFontMetricsXlibContext *aFmctx, const char *aCharSetName)
06036 {
06037   nsCStringKey charSetKey(aCharSetName);
06038   const nsFontCharSetMapXlib* charSetMap = (const nsFontCharSetMapXlib *) aFmctx->mCharSetMaps.Get(&charSetKey);
06039   if (!charSetMap)
06040     charSetMap = aFmctx->mNoneCharSetMap;
06041   return charSetMap;
06042 }
06043 
06044 #ifdef MOZ_ENABLE_FREETYPE2
06045 static
06046 void CharSetNameToCodeRangeBits(const char *aCharset,
06047                                 PRUint32 *aCodeRange1, PRUint32 *aCodeRange2)
06048 {
06049   nsFontCharSetMapXlib  *charSetMap  = GetCharSetMap(aFmctx, aCharset);
06050   nsFontCharSetInfoXlib *charSetInfo = charSetMap->mInfo;
06051 
06052   *aCodeRange1 = charSetInfo->mCodeRange1Bits;
06053   *aCodeRange2 = charSetInfo->mCodeRange2Bits;
06054 }
06055 #endif /* MOZ_ENABLE_FREETYPE2 */