Back to index

lightning-sunbird  0.9+nobinonly
nsFontMetricsWin.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org Code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #ifndef nsFontMetricsWin_h__
00040 #define nsFontMetricsWin_h__
00041 
00042 #include <windows.h>
00043 
00044 #include "plhash.h"
00045 #include "nsIFontMetrics.h"
00046 #include "nsIFontEnumerator.h"
00047 #include "nsFont.h"
00048 #include "nsString.h"
00049 #include "nsUnitConversion.h"
00050 #include "nsIDeviceContext.h"
00051 #include "nsCRT.h"
00052 #include "nsDeviceContextWin.h"
00053 #include "nsCOMPtr.h"
00054 #include "nsVoidArray.h"
00055 #include "nsICharRepresentable.h"
00056 #include "nsCompressedCharMap.h"
00057 #include "nsUnicharUtils.h"
00058 
00059 #ifdef ADD_GLYPH
00060 #undef ADD_GLYPH
00061 #endif
00062 #define ADD_GLYPH(map, g) SET_REPRESENTABLE(map, g)
00063 
00064 enum eFontType {
00065  eFontType_UNKNOWN = -1,
00066  eFontType_Unicode,
00067  eFontType_NonUnicode
00068 };
00069 
00070 struct nsCharacterMap {
00071   PRUint8* mData;
00072   PRInt32  mLength;
00073 };
00074 
00075 struct nsGlobalFont
00076 {
00077   nsString      name;
00078   LOGFONT       logFont;
00079   PRUint16*     ccmap;
00080   FONTSIGNATURE signature;
00081   eFontType     fonttype;
00082   PRUint32      flags;
00083 };
00084 
00085 // Bits used for nsGlobalFont.flags
00086 // If this bit is set, then the font is to be ignored
00087 #define NS_GLOBALFONT_SKIP      0x80000000L
00088 // If this bit is set, then the font is a TrueType font
00089 #define NS_GLOBALFONT_TRUETYPE  0x40000000L
00090 // If this bit is set, then the font is a Symbol font (SYMBOL_CHARSET)
00091 #define NS_GLOBALFONT_SYMBOL    0x20000000L
00092 
00093 class nsFontWin
00094 {
00095 public:
00096   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
00097 
00098   nsFontWin(LOGFONT* aLogFont, HFONT aFont, PRUint16* aCCMap);
00099   virtual ~nsFontWin();
00100 
00101   virtual PRInt32 GetWidth(HDC aDC, const char* aString,
00102                            PRUint32 aLength);
00103 
00104   virtual PRInt32 GetWidth(HDC aDC, const PRUnichar* aString,
00105                            PRUint32 aLength) = 0;
00106 
00107   virtual void DrawString(HDC aDC, PRInt32 aX, PRInt32 aY,
00108                           const char* aString, PRUint32 aLength, INT* aDx0);
00109 
00110   virtual void DrawString(HDC aDC, PRInt32 aX, PRInt32 aY,
00111                           const PRUnichar* aString, PRUint32 aLength) = 0;
00112 
00113   virtual PRBool HasGlyph(PRUint32 ch) {return CCMAP_HAS_CHAR_EXT(mCCMap, ch);};
00114 #ifdef MOZ_MATHML
00115   virtual nsresult
00116   GetBoundingMetrics(HDC                aDC, 
00117                      const char*        aString,
00118                      PRUint32           aLength,
00119                      nsBoundingMetrics& aBoundingMetrics);
00120 
00121   virtual nsresult
00122   GetBoundingMetrics(HDC                aDC, 
00123                      const PRUnichar*   aString,
00124                      PRUint32           aLength,
00125                      nsBoundingMetrics& aBoundingMetrics) = 0;
00126 #ifdef NS_DEBUG
00127   virtual void DumpFontInfo() = 0;
00128 #endif // NS_DEBUG
00129 #endif
00130 
00131   char            mName[LF_FACESIZE];
00132   HFONT           mFont;
00133   PRUint16*       mCCMap;
00134 #ifdef MOZ_MATHML
00135   nsCharacterMap* mCMAP;
00136 #endif
00137 
00138   nscoord         mMaxAscent;
00139   nscoord         mMaxDescent;
00140 
00141   // Note: these are in device units (pixels) -- not twips like the others
00142   LONG            mOverhangCorrection;
00143   LONG            mMaxCharWidthMetric;
00144   LONG            mMaxHeightMetric;
00145   BYTE            mPitchAndFamily;
00146 
00147   PRBool FillClipRect(PRInt32 aX, PRInt32 aY, UINT aLength, UINT uOptions, RECT& clipRect);
00148 };
00149 
00150 // A "substitute font" to deal with missing glyphs -- see bug 6585
00151 // We now use transliteration+fallback to the REPLACEMENT CHAR + 
00152 // HEX representation to handle this issue.
00153 class nsFontWinSubstitute : public nsFontWin
00154 {
00155 public:
00156   nsFontWinSubstitute(LOGFONT* aLogFont, HFONT aFont, PRUint16* aCCMap, PRBool aDisplayUnicode);
00157   nsFontWinSubstitute(PRUint16* aCCMap);
00158   virtual ~nsFontWinSubstitute();
00159 
00160   virtual PRBool HasGlyph(PRUint32 ch) {
00161          return mIsForIgnorable ? CCMAP_HAS_CHAR_EXT(mCCMap, ch) :
00162                 IS_IN_BMP(ch) && IS_REPRESENTABLE(mRepresentableCharMap, ch);};
00163   virtual void SetRepresentable(PRUint32 ch) { if (IS_IN_BMP(ch)) SET_REPRESENTABLE(mRepresentableCharMap, ch); };
00164   virtual PRInt32 GetWidth(HDC aDC, const PRUnichar* aString, PRUint32 aLength);
00165   virtual void DrawString(HDC aDC, PRInt32 aX, PRInt32 aY,
00166                           const PRUnichar* aString, PRUint32 aLength);
00167 #ifdef MOZ_MATHML
00168   virtual nsresult
00169   GetBoundingMetrics(HDC                aDC,
00170                      const PRUnichar*   aString,
00171                      PRUint32           aLength,
00172                      nsBoundingMetrics& aBoundingMetrics);
00173 #ifdef NS_DEBUG
00174   virtual void DumpFontInfo();
00175 #endif // NS_DEBUG
00176 #endif
00177 private:
00178   PRBool mDisplayUnicode;
00179   PRBool mIsForIgnorable; 
00180 
00181   //We need to have a easily operatable charmap for substitute font
00182   PRUint32 mRepresentableCharMap[UCS2_MAP_LEN];
00183 };
00184 
00197 struct nsFontSwitch {
00198   // Simple wrapper on top of nsFontWin for the moment
00199   // Could hold other attributes of the font
00200   nsFontWin* mFontWin;
00201 };
00202 
00203 typedef PRBool (*PR_CALLBACK nsFontSwitchCallback)
00204                (const nsFontSwitch* aFontSwitch,
00205                 const PRUnichar*    aSubstring,
00206                 PRUint32            aSubstringLength,
00207                 void*               aData);
00208 
00209 class nsFontMetricsWin : public nsIFontMetrics
00210 {
00211 public:
00212   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
00213   NS_DECL_ISUPPORTS
00214 
00215   nsFontMetricsWin();
00216   virtual ~nsFontMetricsWin();
00217 
00218   NS_IMETHOD  Init(const nsFont& aFont, nsIAtom* aLangGroup,
00219                    nsIDeviceContext* aContext);
00220   NS_IMETHOD  Destroy();
00221 
00222   NS_IMETHOD  GetXHeight(nscoord& aResult);
00223   NS_IMETHOD  GetSuperscriptOffset(nscoord& aResult);
00224   NS_IMETHOD  GetSubscriptOffset(nscoord& aResult);
00225   NS_IMETHOD  GetStrikeout(nscoord& aOffset, nscoord& aSize);
00226   NS_IMETHOD  GetUnderline(nscoord& aOffset, nscoord& aSize);
00227   NS_IMETHOD  GetHeight(nscoord &aHeight);
00228 #ifdef FONT_LEADING_APIS_V2
00229   NS_IMETHOD  GetInternalLeading(nscoord &aLeading);
00230   NS_IMETHOD  GetExternalLeading(nscoord &aLeading);
00231 #else
00232   NS_IMETHOD  GetLeading(nscoord &aLeading);
00233   NS_IMETHOD  GetNormalLineHeight(nscoord &aHeight);
00234 #endif //FONT_LEADING_APIS_V2
00235   NS_IMETHOD  GetEmHeight(nscoord &aHeight);
00236   NS_IMETHOD  GetEmAscent(nscoord &aAscent);
00237   NS_IMETHOD  GetEmDescent(nscoord &aDescent);
00238   NS_IMETHOD  GetMaxHeight(nscoord &aHeight);
00239   NS_IMETHOD  GetMaxAscent(nscoord &aAscent);
00240   NS_IMETHOD  GetMaxDescent(nscoord &aDescent);
00241   NS_IMETHOD  GetMaxAdvance(nscoord &aAdvance);
00242   NS_IMETHOD  GetLangGroup(nsIAtom** aLangGroup);
00243   NS_IMETHOD  GetFontHandle(nsFontHandle &aHandle);
00244   NS_IMETHOD  GetAveCharWidth(nscoord &aAveCharWidth);
00245   NS_IMETHOD  GetSpaceWidth(nscoord &aSpaceWidth);
00246   virtual PRInt32 GetMaxStringLength();
00247 
00248   virtual nsresult
00249   ResolveForwards(HDC                  aDC,
00250                   const PRUnichar*     aString,
00251                   PRUint32             aLength,
00252                   nsFontSwitchCallback aFunc, 
00253                   void*                aData);
00254 
00255   virtual nsresult
00256   ResolveBackwards(HDC                  aDC,
00257                    const PRUnichar*     aString,
00258                    PRUint32             aLength,
00259                    nsFontSwitchCallback aFunc, 
00260                    void*                aData);
00261 
00262   nsFontWin*         FindFont(HDC aDC, PRUint32 aChar);
00263   virtual nsFontWin* FindUserDefinedFont(HDC aDC, PRUint32 aChar);
00264   virtual nsFontWin* FindLocalFont(HDC aDC, PRUint32 aChar);
00265   virtual nsFontWin* FindGenericFont(HDC aDC, PRUint32 aChar);
00266   virtual nsFontWin* FindPrefFont(HDC aDC, PRUint32 aChar);
00267   virtual nsFontWin* FindGlobalFont(HDC aDC, PRUint32 aChar);
00268   virtual nsFontWin* FindSubstituteFont(HDC aDC, PRUint32 aChar);
00269 
00270   virtual nsFontWin* LoadFont(HDC aDC, const nsString& aName, PRBool aNameQuirks=PR_FALSE);
00271   virtual nsFontWin* LoadGenericFont(HDC aDC, PRUint32 aChar, const nsString& aName);
00272   virtual nsFontWin* LoadGlobalFont(HDC aDC, nsGlobalFont* aGlobalFontItem);
00273   virtual nsFontWin* LoadSubstituteFont(HDC aDC, const nsString& aName);
00274 
00275   virtual nsFontWin* GetFontFor(HFONT aHFONT);
00276 
00277   nsCOMPtr<nsIAtom>   mLangGroup;
00278   nsStringArray       mFonts;
00279   PRInt32             mFontsIndex;
00280   nsVoidArray         mLoadedFonts;
00281   nsFontWin          *mSubstituteFont;
00282 
00283   PRInt32             mGenericIndex;
00284   nsString            mGeneric;
00285 
00286   nsString            mUserDefined;
00287 
00288   PRBool              mTriedAllGenerics;
00289   PRBool              mTriedAllPref;
00290   PRBool              mIsUserDefined;
00291 
00292   static PRUint16*    gEmptyCCMap;
00293   static PLHashTable* gFontMaps;
00294   static PLHashTable* gFamilyNames;
00295   static PLHashTable* gFontWeights;
00296   static nsVoidArray* gGlobalFonts;
00297 
00298   static nsVoidArray* InitializeGlobalFonts(HDC aDC);
00299 
00300   static void SetFontWeight(PRInt32 aWeight, PRUint16* aWeightTable);
00301   static PRBool IsFontWeightAvailable(PRInt32 aWeight, PRUint16 aWeightTable);
00302 
00303   static PRUint16* GetFontCCMAP(HDC aDC, const char* aShortName, 
00304     PRBool aNameQuirks, eFontType& aFontType, PRUint8& aCharset);
00305   static PRUint16* GetCCMAP(HDC aDC, const char* aShortName,
00306     PRBool* aNameQuirks, eFontType* aFontType, PRUint8* aCharset);
00307 
00308   static int SameAsPreviousMap(int aIndex);
00309 
00310   // These functions create possibly adjusted fonts
00311   HFONT CreateFontHandle(HDC aDC, const nsString& aName, LOGFONT* aLogFont);
00312   HFONT CreateFontHandle(HDC aDC, nsGlobalFont* aGlobalFont, LOGFONT* aLogFont);
00313   HFONT CreateFontAdjustHandle(HDC aDC, LOGFONT* aLogFont);
00314   void InitMetricsFor(HDC aDC, nsFontWin* aFontWin);
00315 
00316 protected:
00317   // @description Font Weights
00318   // Each available font weight is stored as as single bit inside a PRUint16.
00319   // e.g. The binary value 0000000000001000 indcates font weight 400 is available.
00320   // while the binary value 0000000000001001 indicates both font weight 100 and 400 are available
00321   // The font weights which will be represented include {100, 200, 300, 400, 500, 600, 700, 800, 900}
00322   // The font weight specified in the mFont->weight may include values which are not an even multiple of 100.
00323   // If so, the font weight mod 100 indicates the number steps to lighten are make bolder.
00324   // This corresponds to the CSS lighter and bolder property values. If bolder is applied twice to the font which has
00325   // a font weight of 400 then the mFont->weight will contain the value 402.
00326   // If lighter is applied twice to a font of weight 400 then the mFont->weight will contain the value 398.
00327   // Only nine steps of bolder or lighter are allowed by the CSS XPCODE.
00328   // The font weight table is used in conjuction with the mFont->weight to determine
00329   // what font weight to pass in the LOGFONT structure.
00330 
00331   // Utility methods for managing font weights.
00332   PRUint16 LookForFontWeightTable(HDC aDc, const nsString& aName);
00333   PRInt32  GetBolderWeight(PRInt32 aWeight, PRInt32 aDistance, PRUint16 aWeightTable);
00334   PRInt32  GetLighterWeight(PRInt32 aWeight, PRInt32 aDistance, PRUint16 aWeightTable);
00335   PRInt32  GetFontWeight(PRInt32 aWeight, PRUint16 aWeightTable);
00336   PRInt32  GetClosestWeight(PRInt32 aWeight, PRUint16 aWeightTable);
00337   PRUint16 GetFontWeightTable(HDC aDC, const nsString& aFontName);
00338   nsFontWin* LocateFont(HDC aDC, PRUint32 aChar, PRInt32 & aCount);
00339 
00340   nsresult RealizeFont();
00341   void FillLogFont(LOGFONT* aLogFont, PRInt32 aWeight,
00342                    PRBool aSizeOnly=PR_FALSE);
00343 
00344   nsDeviceContextWin *mDeviceContext;
00345 
00346   HFONT               mFontHandle;
00347 
00348   nscoord             mExternalLeading;
00349   nscoord             mInternalLeading;
00350   nscoord             mEmHeight;
00351   nscoord             mEmAscent;
00352   nscoord             mEmDescent;
00353   nscoord             mMaxHeight;
00354   nscoord             mMaxAscent;
00355   nscoord             mMaxDescent;
00356   nscoord             mMaxAdvance;
00357   nscoord             mAveCharWidth;
00358   nscoord             mXHeight;
00359   nscoord             mSuperscriptOffset;
00360   nscoord             mSubscriptOffset;
00361   nscoord             mStrikeoutSize;
00362   nscoord             mStrikeoutOffset;
00363   nscoord             mUnderlineSize;
00364   nscoord             mUnderlineOffset;
00365   nscoord             mSpaceWidth;
00366   PRInt32             mMaxStringLength;
00367 };
00368 
00369 
00370 class nsFontEnumeratorWin : public nsIFontEnumerator
00371 {
00372 public:
00373   nsFontEnumeratorWin();
00374   NS_DECL_ISUPPORTS
00375   NS_DECL_NSIFONTENUMERATOR
00376 };
00377 
00378 
00379 // The following is a workaround for a Japanse Windows 95 problem.
00380 
00381 class nsFontSubset;
00382 class nsFontMetricsWinA;
00383 
00384 class nsFontWinA : public nsFontWin
00385 {
00386 public:
00387   nsFontWinA(LOGFONT* aLogFont, HFONT aFont, PRUint16* aCCMap);
00388   virtual ~nsFontWinA();
00389 
00390   virtual PRInt32 GetWidth(HDC aDC, const PRUnichar* aString,
00391                            PRUint32 aLength);
00392   virtual void DrawString(HDC aDC, PRInt32 aX, PRInt32 aY,
00393                           const PRUnichar* aString, PRUint32 aLength);
00394   virtual nsFontSubset* FindSubset(HDC aDC, PRUnichar aChar, nsFontMetricsWinA* aFontMetrics);
00395 #ifdef MOZ_MATHML
00396   virtual nsresult
00397   GetBoundingMetrics(HDC                aDC, 
00398                      const PRUnichar*   aString,
00399                      PRUint32           aLength,
00400                      nsBoundingMetrics& aBoundingMetrics);
00401 #ifdef NS_DEBUG
00402   virtual void DumpFontInfo();
00403 #endif // NS_DEBUG
00404 #endif
00405 
00406   int GetSubsets(HDC aDC);
00407 
00408   LOGFONT        mLogFont;
00409   nsFontSubset** mSubsets;
00410   PRUint16       mSubsetsCount;
00411 };
00412 
00413 class nsFontWinSubstituteA : public nsFontWinA
00414 {
00415 public:
00416   nsFontWinSubstituteA(LOGFONT* aLogFont, HFONT aFont, PRUint16* aCCMap);
00417   nsFontWinSubstituteA(PRUint16* aCCMap);
00418   virtual ~nsFontWinSubstituteA();
00419 
00420   virtual PRBool HasGlyph(PRUint32 ch) {
00421     return mIsForIgnorable ? CCMAP_HAS_CHAR_EXT(mCCMap, ch) :
00422       IS_IN_BMP(ch) && IS_REPRESENTABLE(mRepresentableCharMap, ch);};
00423   virtual void SetRepresentable(PRUint32 ch) { if (IS_IN_BMP(ch)) SET_REPRESENTABLE(mRepresentableCharMap, ch); };
00424   virtual nsFontSubset* FindSubset(HDC aDC, PRUnichar aChar, nsFontMetricsWinA* aFontMetrics) {return mSubsets[0];};
00425 private:
00426   PRBool mIsForIgnorable;
00427 
00428   //We need to have a easily operatable charmap for substitute fonts
00429   PRUint32 mRepresentableCharMap[UCS2_MAP_LEN];
00430 };
00431 
00432 
00433 class nsFontMetricsWinA : public nsFontMetricsWin
00434 {
00435 public:
00436   virtual nsFontWin* FindLocalFont(HDC aDC, PRUint32 aChar);
00437   virtual nsFontWin* LoadGenericFont(HDC aDC, PRUint32 aChar, const nsString& aName);
00438   virtual nsFontWin* FindGlobalFont(HDC aDC, PRUint32 aChar);
00439   virtual nsFontWin* FindSubstituteFont(HDC aDC, PRUint32 aChar);
00440 
00441   virtual nsFontWin* LoadFont(HDC aDC, const nsString& aName, PRBool aNameQuirks=PR_FALSE);
00442   virtual nsFontWin* LoadGlobalFont(HDC aDC, nsGlobalFont* aGlobalFontItem);
00443   virtual nsFontWin* LoadSubstituteFont(HDC aDC, const nsString& aName);
00444 
00445   virtual nsFontWin* GetFontFor(HFONT aHFONT);
00446 
00447   virtual nsresult
00448   ResolveForwards(HDC                  aDC,
00449                   const PRUnichar*     aString,
00450                   PRUint32             aLength,
00451                   nsFontSwitchCallback aFunc, 
00452                   void*                aData);
00453 
00454   virtual nsresult
00455   ResolveBackwards(HDC                  aDC,
00456                    const PRUnichar*     aString,
00457                    PRUint32             aLength,
00458                    nsFontSwitchCallback aFunc, 
00459                    void*                aData);
00460 
00461 protected:
00462   nsFontSubset* LocateFontSubset(HDC aDC, PRUnichar aChar, PRInt32 & aCount, nsFontWinA*& aFont);
00463 };
00464 
00465 #endif /* nsFontMetricsWin_h__ */