backing out previous patch.
authorpavlov@pavlov.net
Wed, 26 Mar 2008 13:24:37 -0700
changeset 13574 dfd5155de8eecb618d440042de6a9e562ad97f4f
parent 13573 4213d8cf6e664fbe537563cb5683f7ca93c421ce
child 13575 634491129642106501f43231e6fbf5583e74010f
push idunknown
push userunknown
push dateunknown
milestone1.9pre
backing out previous patch.
gfx/public/nsFont.h
gfx/src/thebes/nsThebesDeviceContext.cpp
gfx/thebes/public/gfxFontUtils.h
gfx/thebes/public/gfxWindowsFonts.h
gfx/thebes/public/gfxWindowsPlatform.h
gfx/thebes/src/gfxFontUtils.cpp
gfx/thebes/src/gfxQuartzFontCache.h
gfx/thebes/src/gfxQuartzFontCache.mm
gfx/thebes/src/gfxWindowsFonts.cpp
gfx/thebes/src/gfxWindowsPlatform.cpp
--- a/gfx/public/nsFont.h
+++ b/gfx/public/nsFont.h
@@ -92,16 +92,19 @@ struct NS_GFX nsFont {
   nscoord size;
 
   // The aspect-value (ie., the ratio actualsize:actualxheight) that any
   // actual physical font created from this font structure must have when
   // rendering or measuring a string. A value of 0 means no adjustment
   // needs to be done.
   float sizeAdjust;
 
+  // Stretch of the font 1-9
+  PRUint16 stretch;
+
   // Initialize the font struct with an ASCII name
   nsFont(const char* aName, PRUint8 aStyle, PRUint8 aVariant,
          PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize,
          float aSizeAdjust=0.0f);
 
   // Initialize the font struct with a (potentially) unicode name
   nsFont(const nsString& aName, PRUint8 aStyle, PRUint8 aVariant,
          PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize,
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -267,20 +267,17 @@ nsThebesDeviceContext::Init(nsNativeWidg
     if (getenv ("MOZ_X_SYNC")) {
         PR_LOG (gThebesGFXLog, PR_LOG_DEBUG, ("+++ Enabling XSynchronize\n"));
         XSynchronize (gdk_x11_get_default_xdisplay(), True);
         XSetErrorHandler(x11_error_handler);
     }
 
 #endif
 
-
-    mDepth = 24;
-
-    mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");   
+    mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThebesDeviceContext::CreateRenderingContext(nsIView *aView,
                                               nsIRenderingContext *&aContext)
 {
@@ -416,16 +413,22 @@ NS_IMETHODIMP
 nsThebesDeviceContext::CheckFontExistence(const nsString& aFaceName)
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThebesDeviceContext::GetDepth(PRUint32& aDepth)
 {
+    nsCOMPtr<nsIScreen> primaryScreen;
+    if (mDepth == 0) {
+        mScreenManager->GetPrimaryScreen(getter_AddRefs(primaryScreen));
+        primaryScreen->GetColorDepth(reinterpret_cast<PRInt32 *>(&mDepth));
+    }
+
     aDepth = mDepth;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThebesDeviceContext::GetPaletteInfo(nsPaletteInfo& aPaletteInfo)
 {
     aPaletteInfo.isPaletteDevice = PR_FALSE;
--- a/gfx/thebes/public/gfxFontUtils.h
+++ b/gfx/thebes/public/gfxFontUtils.h
@@ -302,24 +302,24 @@ public:
     
     static inline PRUint32
     ReadLongAt(const PRUint8 *aBuf, PRUint32 aIndex)
     {
         return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) | (aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
     }
     
     static nsresult
-    ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap);
+    ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges);
     
     static nsresult 
-    ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap);
+    ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges);
 
     static nsresult
-    ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
-             PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont);
+    ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges, PRPackedBool& aUnicodeFont, 
+        PRPackedBool& aSymbolFont);
 
     static inline bool IsJoiner(PRUint32 ch) {
         return (ch == 0x200C ||
                 ch == 0x200D ||
                 ch == 0x2060);
     }
 
     static inline bool IsInvalid(PRUint32 ch) {
--- a/gfx/thebes/public/gfxWindowsFonts.h
+++ b/gfx/thebes/public/gfxWindowsFonts.h
@@ -59,32 +59,22 @@
  */
 class FontEntry;
 class FontFamily
 {
 public:
     THEBES_INLINE_DECL_REFCOUNTING(FontFamily)
 
     FontFamily(const nsAString& aName) :
-        mName(aName), mHasStyles(PR_FALSE) { }
-
-    FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
+        mName(aName)
+    {
+    }
 
-private:
-    static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
-                                            const NEWTEXTMETRICEXW *nmetrics,
-                                            DWORD fontType, LPARAM data);
-    void FindStyleVariations();
-
-public:
     nsTArray<nsRefPtr<FontEntry> > mVariations;
     nsString mName;
-
-private:
-    PRBool mHasStyles;
 };
 
 class FontEntry
 {
 public:
     THEBES_INLINE_DECL_REFCOUNTING(FontEntry)
 
     FontEntry(const nsString& aFaceName) : 
--- a/gfx/thebes/public/gfxWindowsPlatform.h
+++ b/gfx/thebes/public/gfxWindowsPlatform.h
@@ -80,34 +80,32 @@ public:
      * this involves looking at the fonts on your machine and seeing which
      * code points they support as well as looking at things like the font
      * family, style, weight, etc.
      */
     FontEntry *FindFontForChar(PRUint32 aCh, gfxWindowsFont *aFont);
 
     /* Find a FontFamily/FontEntry object that represents a font on your system given a name */
     FontFamily *FindFontFamily(const nsAString& aName);
-    FontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle);
+    FontEntry *FindFontEntry(FontFamily *aFontFamily, const gfxFontStyle *aFontStyle);
+    FontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle *aFontStyle);
 
     PRBool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> > *array);
     void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<FontEntry> >& array);
 
     typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
 
 private:
     void Init();
 
     void InitBadUnderlineList();
 
     static int CALLBACK FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
                                      const NEWTEXTMETRICEXW *metrics,
                                      DWORD fontType, LPARAM data);
-    static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
-                                            const NEWTEXTMETRICEXW *nmetrics,
-                                            DWORD fontType, LPARAM data);
 
     static PLDHashOperator PR_CALLBACK FontGetStylesProc(nsStringHashKey::KeyType aKey,
                                                          nsRefPtr<FontFamily>& aFontFamily,
                                                          void* userArg);
 
     static PLDHashOperator PR_CALLBACK FontGetCMapDataProc(nsStringHashKey::KeyType aKey,
                                                            nsRefPtr<FontFamily>& aFontFamily,
                                                            void* userArg);
--- a/gfx/thebes/src/gfxFontUtils.cpp
+++ b/gfx/thebes/src/gfxFontUtils.cpp
@@ -215,17 +215,17 @@ static const struct UnicodeRangeTableEnt
     { 109, 0x1D300, 0x1D35F, "Tai Xuan Jing Symbols" },
     { 110, 0x12000, 0x123FF, "Cuneiform" },
     { 110, 0x12400, 0x1247F, "Cuneiform Numbers and Punctuation" },
     { 111, 0x1D360, 0x1D37F, "Counting Rod Numerals" }
 };
 
 
 nsresult
-gfxFontUtils::ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap) 
+gfxFontUtils::ReadCMAPTableFormat12(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges) 
 {
     enum {
         OffsetFormat = 0,
         OffsetReserved = 2,
         OffsetTableLength = 4,
         OffsetLanguage = 8,
         OffsetNumberGroups = 12,
         OffsetGroups = 16,
@@ -255,17 +255,17 @@ gfxFontUtils::ReadCMAPTableFormat12(PRUi
         const PRUint32 endCharCode = ReadLongAt(groups, GroupOffsetEndCode);
         aCharacterMap.SetRange(startCharCode, endCharCode);
     }
 
     return NS_OK;
 }
 
 nsresult 
-gfxFontUtils::ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap)
+gfxFontUtils::ReadCMAPTableFormat4(PRUint8 *aBuf, PRInt32 aLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges)
 {
     enum {
         OffsetFormat = 0,
         OffsetLength = 2,
         OffsetLanguage = 4,
         OffsetSegCountX2 = 6
     };
 
@@ -335,18 +335,18 @@ gfxFontUtils::ReadCMAPTableFormat4(PRUin
     #define isSymbol(p,e)               ((e) == EncodingIDSymbol)
 #endif
 
 #define acceptableUCS4Encoding(p, e) \
     ((platformID == PlatformIDMicrosoft && encodingID == EncodingIDUCS4ForMicrosoftPlatform) || \
      (platformID == PlatformIDUnicode   && encodingID == EncodingIDUCS4ForUnicodePlatform))
 
 nsresult
-gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap, 
-                       PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont)
+gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap, std::bitset<128>& aUnicodeRanges, 
+    PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont)
 {
     enum {
         OffsetVersion = 0,
         OffsetNumTables = 2,
         SizeOfHeader = 4,
 
         TableOffsetPlatformID = 0,
         TableOffsetEncodingID = 2,
@@ -390,35 +390,31 @@ gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PR
 
         if (isSymbol(platformID, encodingID)) {
             aUnicodeFont = PR_FALSE;
             aSymbolFont = PR_TRUE;
             keepFormat = format;
             keepOffset = offset;
             break;
         } else if (format == 4 && acceptableFormat4(platformID, encodingID, keepFormat)) {
-            aUnicodeFont = PR_TRUE;
-            aSymbolFont = PR_FALSE;
             keepFormat = format;
             keepOffset = offset;
         } else if (format == 12 && acceptableUCS4Encoding(platformID, encodingID)) {
-            aUnicodeFont = PR_TRUE;
-            aSymbolFont = PR_FALSE;
             keepFormat = format;
             keepOffset = offset;
             break; // we don't want to try anything else when this format is available.
         }
     }
 
     nsresult rv = NS_ERROR_FAILURE;
 
     if (keepFormat == 12)
-        rv = ReadCMAPTableFormat12(aBuf + keepOffset, aBufLength - keepOffset, aCharacterMap);
+        rv = ReadCMAPTableFormat12(aBuf + keepOffset, aBufLength - keepOffset, aCharacterMap, aUnicodeRanges);
     else if (keepFormat == 4)
-        rv = ReadCMAPTableFormat4(aBuf + keepOffset, aBufLength - keepOffset, aCharacterMap);
+        rv = ReadCMAPTableFormat4(aBuf + keepOffset, aBufLength - keepOffset, aCharacterMap, aUnicodeRanges);
 
     return rv;
 }
 
 PRUint8 gfxFontUtils::CharRangeBit(PRUint32 ch) {
     const PRUint32 n = sizeof(gUnicodeRanges) / sizeof(struct UnicodeRangeTableEntry);
 
     for (PRUint32 i = 0; i < n; ++i)
--- a/gfx/thebes/src/gfxQuartzFontCache.h
+++ b/gfx/thebes/src/gfxQuartzFontCache.h
@@ -97,16 +97,17 @@ public:
     MacOSFamilyEntry* FamilyEntry() { return mFamily; }
 protected:
     nsString mPostscriptName;
     PRInt32 mWeight; // CSS-type value: [1..9] which map to 100, 200, ..., 900
     PRUint32 mTraits;
     MacOSFamilyEntry *mFamily;
 
     ATSUFontID mATSUFontID;
+    std::bitset<128> mUnicodeRanges;
     gfxSparseBitSet mCharacterMap;
     
     PRPackedBool mCmapInitialized;
     PRPackedBool mATSUIDInitialized;
 };
 
 // helper class for adding other family names back into font cache
 class AddOtherFamilyNameFunctor;
--- a/gfx/thebes/src/gfxQuartzFontCache.mm
+++ b/gfx/thebes/src/gfxQuartzFontCache.mm
@@ -185,17 +185,17 @@ MacOSFontEntry::ReadCMAP()
         return NS_ERROR_OUT_OF_MEMORY;
     PRUint8 *cmap = buffer.Elements();
 
     status = ATSFontGetTable(fontID, 'cmap', 0, size, cmap, &size);
     NS_ENSURE_TRUE(status == noErr, NS_ERROR_FAILURE);
 
     nsresult rv = NS_ERROR_FAILURE;
     PRPackedBool  unicodeFont, symbolFont; // currently ignored
-    rv = gfxFontUtils::ReadCMAP(cmap, size, mCharacterMap, unicodeFont, symbolFont);
+    rv = gfxFontUtils::ReadCMAP(cmap, size, mCharacterMap, mUnicodeRanges, unicodeFont, symbolFont);
 
     // for complex scripts, check for the presence of mort/morx
     PRBool checkedForMorphTable = PR_FALSE, hasMorphTable = PR_FALSE;
     
     PRUint32 s, numScripts = sizeof(gScriptsThatRequireShaping) / sizeof(ScriptRange);
     
     for (s = 0; s < numScripts; s++) {
         eComplexScript  whichScript = gScriptsThatRequireShaping[s].script;
--- a/gfx/thebes/src/gfxWindowsFonts.cpp
+++ b/gfx/thebes/src/gfxWindowsFonts.cpp
@@ -104,270 +104,16 @@ struct DCFromContext {
     operator HDC () {
         return dc;
     }
 
     HDC dc;
     PRBool needsRelease;
 };
 
-
-/**********************************************************************
- *
- * class FontFamily
- *
- **********************************************************************/
-static nsresult
-ReadCMAP(HDC hdc, FontEntry *aFontEntry)
-{
-    const PRUint32 kCMAP = (('c') | ('m' << 8) | ('a' << 16) | ('p' << 24));
-
-    DWORD len = GetFontData(hdc, kCMAP, 0, nsnull, 0);
-    if (len == GDI_ERROR || len == 0) // not a truetype font --
-        return NS_ERROR_FAILURE;      // we'll treat it as a symbol font
-
-    nsAutoTArray<PRUint8,16384> buffer;
-    if (!buffer.AppendElements(len))
-        return NS_ERROR_OUT_OF_MEMORY;
-    PRUint8 *buf = buffer.Elements();
-
-    DWORD newLen = GetFontData(hdc, kCMAP, 0, buf, len);
-    NS_ENSURE_TRUE(newLen == len, NS_ERROR_FAILURE);
-    
-    return gfxFontUtils::ReadCMAP(buf, len, aFontEntry->mCharacterMap,
-                                  aFontEntry->mUnicodeFont, aFontEntry->mSymbolFont);
-}
-
-struct FamilyAddStyleProcData {
-    HDC dc;
-    FontFamily *ff;
-};
-
-int CALLBACK 
-FontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
-                                const NEWTEXTMETRICEXW *nmetrics,
-                                DWORD fontType, LPARAM data)
-{
-    const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
-    LOGFONTW logFont = lpelfe->elfLogFont;
-
-    FamilyAddStyleProcData *faspd = reinterpret_cast<FamilyAddStyleProcData*>(data);
-    FontFamily *ff = faspd->ff;
-    HDC hdc = faspd->dc;
-
-    // Some fonts claim to support things > 900, but we don't so clamp the sizes
-    logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
-
-    FontEntry *fe = nsnull;
-    for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
-        fe = ff->mVariations[i];
-
-        // check if we already know about this face
-        if (fe->mWeight == logFont.lfWeight &&
-            fe->mItalic == (logFont.lfItalic == 0xFF)) {
-            // update the charset bit here since this could be different
-            fe->mCharset[metrics.tmCharSet] = 1;
-            return 1; 
-        }
-    }
-
-    fe = new FontEntry(ff->mName);
-    ff->mVariations.AppendElement(fe);
-
-    fe->mItalic = (logFont.lfItalic == 0xFF);
-    fe->mWeight = logFont.lfWeight;
-
-    if (metrics.ntmFlags & NTM_TYPE1)
-        fe->mIsType1 = fe->mForceGDI = PR_TRUE;
-
-    // fontType == TRUETYPE_FONTTYPE when (metrics.ntmFlags & NTM_TT_OPENTYPE)
-    if (fontType == TRUETYPE_FONTTYPE || metrics.ntmFlags & (NTM_PS_OPENTYPE))
-        fe->mTrueType = PR_TRUE;
-
-    // mark the charset bit
-    fe->mCharset[metrics.tmCharSet] = 1;
-
-    fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
-    fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
-
-    if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 &&
-        nmetrics->ntmFontSig.fsUsb[1] != 0x00000000 &&
-        nmetrics->ntmFontSig.fsUsb[2] != 0x00000000 &&
-        nmetrics->ntmFontSig.fsUsb[3] != 0x00000000) {
-
-        // set the unicode ranges
-        PRUint32 x = 0;
-        for (PRUint32 i = 0; i < 4; ++i) {
-            DWORD range = nmetrics->ntmFontSig.fsUsb[i];
-            for (PRUint32 k = 0; k < 32; ++k) {
-                fe->mUnicodeRanges[x++] = (range & (1 << k)) != 0;
-            }
-        }
-    }
-
-    // read in the character map
-    logFont.lfCharSet = DEFAULT_CHARSET;
-    HFONT font = CreateFontIndirectW(&logFont);
-
-    NS_ASSERTION(font, "This font creation should never ever ever fail");
-    if (font) {
-        HFONT oldFont = (HFONT)SelectObject(hdc, font);
-
-        // ReadCMAP may change the values of mUnicodeFont and mSymbolFont
-        if (NS_FAILED(ReadCMAP(hdc, fe))) {
-            // Type1 fonts aren't necessarily Unicode but
-            // this is the best guess we can make here
-            if (fe->mIsType1)
-                fe->mUnicodeFont = PR_TRUE;
-            else
-                fe->mUnicodeFont = PR_FALSE;
-
-            // For fonts where we failed to read the character map,
-            // we should use GDI to slowly determine their cmap lazily
-            fe->mForceGDI = PR_TRUE;
-
-            //printf("%d, %s failed to get cmap\n", aFontEntry->mIsType1, NS_ConvertUTF16toUTF8(aFontEntry->mName).get());
-        }
-
-        SelectObject(hdc, oldFont);
-        DeleteObject(font);
-    }
-
-    return 1;
-}
-
-// general cmap reading routines moved to gfxFontUtils.cpp
-void
-FontFamily::FindStyleVariations()
-{
-    mHasStyles = PR_TRUE;
-
-    HDC hdc = GetDC(nsnull);
-
-    LOGFONTW logFont;
-    memset(&logFont, 0, sizeof(LOGFONTW));
-    logFont.lfCharSet = DEFAULT_CHARSET;
-    logFont.lfPitchAndFamily = 0;
-    PRUint32 l = PR_MIN(mName.Length(), LF_FACESIZE - 1);
-    memcpy(logFont.lfFaceName,
-           nsPromiseFlatString(mName).get(),
-           l * sizeof(PRUnichar));
-    logFont.lfFaceName[l] = 0;
-
-    FamilyAddStyleProcData faspd;
-    faspd.dc = hdc;
-    faspd.ff = this;
-
-    EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)FontFamily::FamilyAddStylesProc, (LPARAM)&faspd, 0);
-
-    ReleaseDC(nsnull, hdc);
-
-    // Look for font families without bold variations and add a FontEntry
-    // with synthetic bold (weight 600) for them.
-    FontEntry *darkestItalic = nsnull;
-    FontEntry *darkestNonItalic = nsnull;
-    PRUint8 highestItalic = 0, highestNonItalic = 0;
-    for (PRUint32 i = 0; i < mVariations.Length(); i++) {
-        FontEntry *fe = mVariations[i];
-        if (fe->mItalic) {
-            if (!darkestItalic || fe->mWeight > darkestItalic->mWeight)
-                darkestItalic = fe;
-        } else {
-            if (!darkestNonItalic || fe->mWeight > darkestNonItalic->mWeight)
-                darkestNonItalic = fe;
-        }
-    }
-
-    if (darkestItalic && darkestItalic->mWeight < 600) {
-        FontEntry *newEntry = new FontEntry(*darkestItalic);
-        newEntry->mWeight = 600;
-        mVariations.AppendElement(newEntry);
-    }
-    if (darkestNonItalic && darkestNonItalic->mWeight < 600) {
-        FontEntry *newEntry = new FontEntry(*darkestNonItalic);
-        newEntry->mWeight = 600;
-        mVariations.AppendElement(newEntry);
-    }
-}
-
-
-FontEntry *
-FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle)
-{
-    if (!mHasStyles)
-        FindStyleVariations();
-
-    PRUint8 bestMatch = 0;
-    PRBool italic = (aFontStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
-
-    FontEntry *weightList[10] = { 0 };
-    for (PRUint32 j = 0; j < 2; j++) {
-        PRBool matchesSomething = PR_FALSE;
-        // build up an array of weights that match the italicness we're looking for
-        for (PRUint32 i = 0; i < mVariations.Length(); i++) {
-            FontEntry *fe = mVariations[i];
-            const PRUint8 weight = (fe->mWeight / 100);
-            if (fe->mItalic == italic) {
-                weightList[weight] = fe;
-                matchesSomething = PR_TRUE;
-            }
-        }
-        if (matchesSomething)
-            break;
-        italic = !italic;
-    }
-
-    PRInt8 baseWeight, weightDistance;
-    aFontStyle.ComputeWeightAndOffset(&baseWeight, &weightDistance);
-
-    // 500 isn't quite bold so we want to treat it as 400 if we don't
-    // have a 500 weight
-    if (baseWeight == 5 && weightDistance == 0) {
-        // If we have a 500 weight then use it
-        if (weightList[5])
-            return weightList[5];
-
-        // Otherwise treat as 400
-        baseWeight = 4;
-    }
-
-    PRInt8 matchBaseWeight = 0;
-    PRInt8 direction = (baseWeight > 5) ? 1 : -1;
-    for (PRInt8 i = baseWeight; ; i += direction) {
-        if (weightList[i]) {
-            matchBaseWeight = i;
-            break;
-        }
-
-        // if we've reached one side without finding a font,
-        // go the other direction until we find a match
-        if (i == 1 || i == 9)
-            direction = -direction;
-    }
-
-    FontEntry *matchFE;
-    const PRInt8 absDistance = abs(weightDistance);
-    direction = (weightDistance >= 0) ? 1 : -1;
-    for (PRInt8 i = matchBaseWeight, k = 0; i < 10 && i > 0; i += direction) {
-        if (weightList[i]) {
-            matchFE = weightList[i];
-            k++;
-        }
-        if (k > absDistance)
-            break;
-    }
-
-    if (!matchFE)
-        matchFE = weightList[matchBaseWeight];
-
-    NS_ASSERTION(matchFE, "we should always be able to return something here");
-    return matchFE;
-}
-
-
 /**********************************************************************
  *
  * class gfxWindowsFont
  *
  **********************************************************************/
 
 gfxWindowsFont::gfxWindowsFont(const nsAString& aName, const gfxFontStyle *aFontStyle, FontEntry *aFontEntry)
     : gfxFont(aName, aFontStyle),
@@ -691,33 +437,33 @@ AddFontNameToArray(const nsAString& aNam
 void
 gfxWindowsFontGroup::GroupFamilyListToArrayList(nsTArray<nsRefPtr<FontEntry> > *list)
 {
     nsAutoTArray<nsAutoString, 15> fonts;
     ForEachFont(AddFontNameToArray, &fonts);
 
     PRUint32 len = fonts.Length();
     for (PRUint32 i = 0; i < len; ++i) {
-        nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], mStyle);
+        nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(fonts[i], &mStyle);
         list->AppendElement(fe);
     }
 }
 
 void
 gfxWindowsFontGroup::FamilyListToArrayList(const nsString& aFamilies,
                                            const nsCString& aLangGroup,
                                            nsTArray<nsRefPtr<FontEntry> > *list)
 {
     nsAutoTArray<nsAutoString, 15> fonts;
     ForEachFont(aFamilies, aLangGroup, AddFontNameToArray, &fonts);
 
     PRUint32 len = fonts.Length();
     for (PRUint32 i = 0; i < len; ++i) {
         const nsAutoString& str = fonts[i];
-        nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(str, mStyle);
+        nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(str, &mStyle);
         list->AppendElement(fe);
     }
 }
 
 gfxWindowsFontGroup::gfxWindowsFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle)
     : gfxFontGroup(aFamilies, aStyle)
 {
     GroupFamilyListToArrayList(&mFontEntries);
@@ -726,17 +472,17 @@ gfxWindowsFontGroup::gfxWindowsFontGroup
         // Should append default GUI font if there are no available fonts.
         HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
         LOGFONTW logFont;
         if (!hGDI ||
             !::GetObjectW(hGDI, sizeof(logFont), &logFont)) {
             NS_ERROR("Failed to create font group");
             return;
         }
-        nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(nsDependentString(logFont.lfFaceName), *aStyle);
+        nsRefPtr<FontEntry> fe = gfxWindowsPlatform::GetPlatform()->FindFontEntry(nsDependentString(logFont.lfFaceName), aStyle);
         mFontEntries.AppendElement(fe);
     }
 
     mFonts.AppendElements(mFontEntries.Length());
 
     for (PRUint32 i = 0; i < mFontEntries.Length(); ++i) {
         if (mFontEntries[i]->IsBadUnderlineFont()) {
             gfxFloat first = GetFontAt(0)->GetMetrics().underlineOffset;
@@ -986,17 +732,17 @@ gfxWindowsFontGroup::InitTextRunGDI(gfxC
 struct ScriptPropertyEntry {
     const char *value;
     const char *langCode;
 };
 
 static const struct ScriptPropertyEntry gScriptToText[] =
 {
     { nsnull, nsnull },
-    { "LANG_ARABIC",     "ar" }, // ara
+    { "LANG_ARABIC",     "ara" },
     { "LANG_BULGARIAN",  "bul" },
     { "LANG_CATALAN",    "cat" },
     { "LANG_CHINESE",    "zh-CN" }, //XXX right lang code?
     { "LANG_CZECH",      "cze" }, // cze/ces
     { "LANG_DANISH",     "dan" },
     { "LANG_GERMAN",     "ger" }, // ger/deu
     { "LANG_GREEK",      "el" }, // gre/ell
     { "LANG_ENGLISH",    "x-western" },
@@ -1553,23 +1299,16 @@ public:
         // check the list of fonts
         selectedFont = WhichFontSupportsChar(mGroup->GetFontList(), ch);
 
         // don't look in other fonts if the character is in a Private Use Area
         if ((ch >= 0xE000  && ch <= 0xF8FF) || 
             (ch >= 0xF0000 && ch <= 0x10FFFD))
             return selectedFont;
 
-        // check out the style's language group
-        if (!selectedFont) {
-            nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
-            this->GetPrefFonts(mGroup->GetStyle()->langGroup.get(), fonts);
-            selectedFont = WhichFontSupportsChar(fonts, ch);
-        }
-
         // otherwise search prefs
         if (!selectedFont) {
             /* first check with the script properties to see what they think */
             const SCRIPT_PROPERTIES *sp = ScriptProperties();
             if (!sp->fAmbiguousCharSet) {
                 WORD primaryId = PRIMARYLANGID(sp->langid);
                 const char *langGroup = gScriptToText[primaryId].langCode;
                 if (langGroup) {
--- a/gfx/thebes/src/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/src/gfxWindowsPlatform.cpp
@@ -53,23 +53,17 @@
 #include "gfxWindowsFonts.h"
 
 #include <string>
 
 #include "lcms.h"
 
 //#define DEBUG_CMAP_SIZE 1
 
-static __inline void
-BuildKeyNameFromFontName(nsAString &aName)
-{
-    if (aName.Length() >= LF_FACESIZE)
-        aName.Truncate(LF_FACESIZE - 1);
-    ToLowerCase(aName);
-}
+static nsresult ReadCMAP(HDC hdc, FontEntry *aFontEntry);
 
 int PR_CALLBACK
 gfxWindowsPlatform::PrefChangedCallback(const char *aPrefName, void *closure)
 {
     // XXX this could be made to only clear out the cache for the prefs that were changed
     // but it probably isn't that big a deal.
     gfxWindowsPlatform *plat = static_cast<gfxWindowsPlatform *>(closure);
     plat->mPrefFonts.Clear();
@@ -108,36 +102,209 @@ gfxWindowsPlatform::CreateOffscreenSurfa
 int CALLBACK 
 gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
                                  const NEWTEXTMETRICEXW *nmetrics,
                                  DWORD fontType, LPARAM data)
 {
     FontTable *ht = reinterpret_cast<FontTable*>(data);
 
     const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
-    const LOGFONTW& logFont = lpelfe->elfLogFont;
+    LOGFONTW logFont = lpelfe->elfLogFont;
 
     // Ignore vertical fonts
-    if (logFont.lfFaceName[0] == L'@')
+    if (logFont.lfFaceName[0] == L'@') {
         return 1;
+    }
+
+    // Some fonts claim to support things > 900, but we don't so clamp the sizes
+    logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
 
-    nsAutoString name(logFont.lfFaceName);
-    BuildKeyNameFromFontName(name);
+#ifdef DEBUG_pavlov
+    printf("%s %d %d %d\n", NS_ConvertUTF16toUTF8(nsDependentString(logFont.lfFaceName)).get(),
+           logFont.lfCharSet, logFont.lfItalic, logFont.lfWeight);
+#endif
+
+    nsString name(logFont.lfFaceName);
+    ToLowerCase(name);
 
     nsRefPtr<FontFamily> ff;
     if (!ht->Get(name, &ff)) {
         ff = new FontFamily(nsDependentString(logFont.lfFaceName));
         ht->Put(name, ff);
     }
 
+    nsRefPtr<FontEntry> fe;
+    for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
+        fe = ff->mVariations[i];
+        if (fe->mWeight == logFont.lfWeight &&
+            fe->mItalic == (logFont.lfItalic == 0xFF)) {
+            return 1; /* we already know about this font */
+        }
+    }
+
+    fe = new FontEntry(ff->mName);
+    /* don't append it until the end in case of error */
+
+    fe->mItalic = (logFont.lfItalic == 0xFF);
+    fe->mWeight = logFont.lfWeight;
+
+    if (metrics.ntmFlags & NTM_TYPE1)
+        fe->mIsType1 = fe->mForceGDI = PR_TRUE;
+    if (metrics.ntmFlags & (NTM_PS_OPENTYPE | NTM_TT_OPENTYPE))
+        fe->mTrueType = PR_TRUE;
+
+    // mark the charset bit
+    fe->mCharset[metrics.tmCharSet] = 1;
+
+    fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
+    fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
+
+    if (nmetrics->ntmFontSig.fsUsb[0] == 0x00000000 &&
+        nmetrics->ntmFontSig.fsUsb[1] == 0x00000000 &&
+        nmetrics->ntmFontSig.fsUsb[2] == 0x00000000 &&
+        nmetrics->ntmFontSig.fsUsb[3] == 0x00000000) {
+        // no unicode ranges
+        fe->mUnicodeFont = PR_FALSE;
+    } else {
+        fe->mUnicodeFont = PR_TRUE;
+
+        // set the unicode ranges
+        PRUint32 x = 0;
+        for (PRUint32 i = 0; i < 4; ++i) {
+            DWORD range = nmetrics->ntmFontSig.fsUsb[i];
+            for (PRUint32 k = 0; k < 32; ++k) {
+                fe->mUnicodeRanges[x++] = (range & (1 << k)) != 0;
+            }
+        }
+    }
+
+    /* read in the character map */
+    HDC hdc = GetDC(nsnull);
+    logFont.lfCharSet = DEFAULT_CHARSET;
+    HFONT font = CreateFontIndirectW(&logFont);
+
+    NS_ASSERTION(font, "This font creation should never ever ever fail");
+    if (font) {
+        HFONT oldFont = (HFONT)SelectObject(hdc, font);
+
+        TEXTMETRIC metrics;
+        GetTextMetrics(hdc, &metrics);
+        if (metrics.tmPitchAndFamily & TMPF_TRUETYPE)
+            fe->mTrueType = PR_TRUE;
+
+        if (NS_FAILED(ReadCMAP(hdc, fe))) {
+            // Type1 fonts aren't necessarily Unicode but
+            // this is the best guess we can make here
+            if (fe->mIsType1)
+                fe->mUnicodeFont = PR_TRUE;
+            else
+                fe->mUnicodeFont = PR_FALSE;
+
+            //printf("%d, %s failed to get cmap\n", aFontEntry->mIsType1, NS_ConvertUTF16toUTF8(aFontEntry->mName).get());
+        }
+
+        SelectObject(hdc, oldFont);
+        DeleteObject(font);
+    }
+
+    ReleaseDC(nsnull, hdc);
+
+    if (!fe->mUnicodeFont) {
+        /* non-unicode fonts.. boy lets just set all code points
+           between 0x20 and 0xFF.  All the ones on my system do...
+           If we really wanted to test which characters in this
+           range were supported we could just generate a string with
+           each codepoint and do GetGlyphIndicies or similar to determine
+           what is there.
+        */
+        fe->mCharacterMap.SetRange(0x20, 0xFF);
+    }
+
+    /* append the variation to the font family */
+    ff->mVariations.AppendElement(fe);
+
     return 1;
 }
 
+// general cmap reading routines moved to gfxFontUtils.cpp
 
-// general cmap reading routines moved to gfxFontUtils.cpp
+static nsresult
+ReadCMAP(HDC hdc, FontEntry *aFontEntry)
+{
+    const PRUint32 kCMAP = (('c') | ('m' << 8) | ('a' << 16) | ('p' << 24));
+
+    DWORD len = GetFontData(hdc, kCMAP, 0, nsnull, 0);
+    if (len == GDI_ERROR || len == 0) // not a truetype font --
+        return NS_ERROR_FAILURE;      // we'll treat it as a symbol font
+
+    nsAutoTArray<PRUint8,16384> buffer;
+    if (!buffer.AppendElements(len))
+        return NS_ERROR_OUT_OF_MEMORY;
+    PRUint8 *buf = buffer.Elements();
+
+    DWORD newLen = GetFontData(hdc, kCMAP, 0, buf, len);
+    NS_ENSURE_TRUE(newLen == len, NS_ERROR_FAILURE);
+    
+    return gfxFontUtils::ReadCMAP(buf, len, aFontEntry->mCharacterMap, aFontEntry->mUnicodeRanges,
+                                  aFontEntry->mUnicodeFont, aFontEntry->mSymbolFont);
+}
+
+PLDHashOperator PR_CALLBACK
+gfxWindowsPlatform::FontGetStylesProc(nsStringHashKey::KeyType aKey,
+                                      nsRefPtr<FontFamily>& aFontFamily,
+                                      void* userArg)
+{
+    NS_ASSERTION(aFontFamily->mVariations.Length() == 1, "We should only have 1 variation here");
+    nsRefPtr<FontEntry> aFontEntry = aFontFamily->mVariations[0];
+
+    HDC hdc = GetDC(nsnull);
+
+    LOGFONTW logFont;
+    memset(&logFont, 0, sizeof(LOGFONTW));
+    logFont.lfCharSet = DEFAULT_CHARSET;
+    logFont.lfPitchAndFamily = 0;
+    PRUint32 l = PR_MIN(aFontEntry->GetName().Length(), LF_FACESIZE - 1);
+    memcpy(logFont.lfFaceName,
+           nsPromiseFlatString(aFontEntry->GetName()).get(),
+           l * sizeof(PRUnichar));
+    logFont.lfFaceName[l] = 0;
+
+    EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)userArg, 0);
+
+    ReleaseDC(nsnull, hdc);
+
+    // Look for font families without bold variations and add a FontEntry
+    // with synthetic bold (weight 600) for them.
+    nsRefPtr<FontEntry> darkestItalic;
+    nsRefPtr<FontEntry> darkestNonItalic;
+    PRUint8 highestItalic = 0, highestNonItalic = 0;
+    for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); i++) {
+        nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
+        if (fe->mItalic) {
+            if (!darkestItalic || fe->mWeight > darkestItalic->mWeight)
+                darkestItalic = fe;
+        } else {
+            if (!darkestNonItalic || fe->mWeight > darkestNonItalic->mWeight)
+                darkestNonItalic = fe;
+        }
+    }
+
+    if (darkestItalic && darkestItalic->mWeight < 600) {
+        nsRefPtr<FontEntry> newEntry = new FontEntry(*darkestItalic.get());
+        newEntry->mWeight = 600;
+        aFontFamily->mVariations.AppendElement(newEntry);
+    }
+    if (darkestNonItalic && darkestNonItalic->mWeight < 600) {
+        nsRefPtr<FontEntry> newEntry = new FontEntry(*darkestNonItalic.get());
+        newEntry->mWeight = 600;
+        aFontFamily->mVariations.AppendElement(newEntry);
+    }
+
+    return PL_DHASH_NEXT;
+}
 
 struct FontListData {
     FontListData(const nsACString& aLangGroup, const nsACString& aGenericFamily, nsStringArray& aListOfFonts) :
         mLangGroup(aLangGroup), mGenericFamily(aGenericFamily), mStringArray(aListOfFonts) {}
     const nsACString& mLangGroup;
     const nsACString& mGenericFamily;
     nsStringArray& mStringArray;
 };
@@ -183,16 +350,24 @@ gfxWindowsPlatform::GetFontList(const ns
 static void
 RemoveCharsetFromFontSubstitute(nsAString &aName)
 {
     PRInt32 comma = aName.FindChar(PRUnichar(','));
     if (comma >= 0)
         aName.Truncate(comma);
 }
 
+static void
+BuildKeyNameFromFontName(nsAString &aName)
+{
+    if (aName.Length() >= LF_FACESIZE)
+        aName.Truncate(LF_FACESIZE - 1);
+    ToLowerCase(aName);
+}
+
 nsresult
 gfxWindowsPlatform::UpdateFontList()
 {
     gfxFontCache *fc = gfxFontCache::GetCache();
     if (fc)
         fc->AgeAllGenerations();
     mFonts.Clear();
     mFontAliases.Clear();
@@ -206,16 +381,19 @@ gfxWindowsPlatform::UpdateFontList()
     logFont.lfFaceName[0] = 0;
     logFont.lfPitchAndFamily = 0;
 
     // Use the screen DC here.. should we use something else for printing?
     HDC dc = ::GetDC(nsnull);
     EnumFontFamiliesExW(dc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)&mFonts, 0);
     ::ReleaseDC(nsnull, dc);
 
+    // Look for additional styles
+    mFonts.Enumerate(gfxWindowsPlatform::FontGetStylesProc, &mFonts);
+
     // Create the list of FontSubstitutes
     nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
     if (!regKey)
         return NS_ERROR_FAILURE;
      NS_NAMED_LITERAL_STRING(kFontSubstitutesKey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
 
     nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
                                kFontSubstitutesKey, nsIWindowsRegKey::ACCESS_READ);
@@ -258,17 +436,17 @@ gfxWindowsPlatform::UpdateFontList()
 
     InitBadUnderlineList();
 
     return NS_OK;
 }
 
 static PRBool SimpleResolverCallback(const nsAString& aName, void* aClosure)
 {
-    nsString *result = static_cast<nsString*>(aClosure);
+    nsString* result = static_cast<nsString*>(aClosure);
     result->Assign(aName);
     return PR_FALSE;
 }
 
 void
 gfxWindowsPlatform::InitBadUnderlineList()
 {
     nsAutoTArray<nsAutoString, 10> blacklist;
@@ -408,17 +586,17 @@ PLDHashOperator PR_CALLBACK
 gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
                                         nsRefPtr<FontFamily>& aFontFamily,
                                         void* userArg)
 {
     FontSearch *data = (FontSearch*)userArg;
 
     const PRUint32 ch = data->ch;
 
-    nsRefPtr<FontEntry> fe = aFontFamily->FindFontEntry(*data->fontToMatch->GetStyle());
+    nsRefPtr<FontEntry> fe = GetPlatform()->FindFontEntry(aFontFamily, data->fontToMatch->GetStyle());
 
     // skip over non-unicode and bitmap fonts and fonts that don't have
     // the code point we're looking for
     if (fe->IsCrappyFont() || !fe->mCharacterMap.test(ch))
         return PL_DHASH_NEXT;
 
     PRInt32 rank = 0;
     // fonts that claim to support the range are more
@@ -430,17 +608,17 @@ gfxWindowsPlatform::FindFontForCharProc(
         rank += 2;
 
     if (fe->mWindowsFamily == data->fontToMatch->GetFontEntry()->mWindowsFamily)
         rank += 3;
     if (fe->mWindowsPitch == data->fontToMatch->GetFontEntry()->mWindowsFamily)
         rank += 3;
 
     /* italic */
-    const PRBool italic = (data->fontToMatch->GetStyle()->style != FONT_STYLE_NORMAL);
+    const PRBool italic = (data->fontToMatch->GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? PR_TRUE : PR_FALSE;
     if (fe->mItalic != italic)
         rank += 3;
 
     /* weight */
     PRInt8 baseWeight, weightDistance;
     data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
     if (fe->mWeight == (baseWeight * 100) + (weightDistance * 100))
         rank += 2;
@@ -469,50 +647,130 @@ gfxWindowsPlatform::FindFontForChar(PRUi
 
     // find fonts that support the character
     mFonts.Enumerate(gfxWindowsPlatform::FindFontForCharProc, &data);
 
     // no match? add to set of non-matching codepoints
     if (!data.bestMatch) {
         mCodepointsWithNoFonts.set(aCh);
     }
-
+    
     return data.bestMatch;
 }
 
 gfxFontGroup *
 gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
                                     const gfxFontStyle *aStyle)
 {
     return new gfxWindowsFontGroup(aFamilies, aStyle);
 }
 
 FontFamily *
 gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
 {
-    nsAutoString name(aName);
-    BuildKeyNameFromFontName(name);
+    nsString name(aName);
+    ToLowerCase(name);
 
     nsRefPtr<FontFamily> ff;
     if (!mFonts.Get(name, &ff) &&
         !mFontSubstitutes.Get(name, &ff) &&
         !mFontAliases.Get(name, &ff)) {
         return nsnull;
     }
     return ff.get();
 }
 
 FontEntry *
-gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle)
+gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle *aFontStyle)
 {
     nsRefPtr<FontFamily> ff = FindFontFamily(aName);
     if (!ff)
         return nsnull;
 
-    return ff->FindFontEntry(aFontStyle);
+    return FindFontEntry(ff, aFontStyle);
+}
+
+FontEntry *
+gfxWindowsPlatform::FindFontEntry(FontFamily *aFontFamily, const gfxFontStyle *aFontStyle)
+{
+    PRUint8 bestMatch = 0;
+    PRBool italic = (aFontStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
+
+    nsAutoTArray<nsRefPtr<FontEntry>, 10> weightList;
+    weightList.AppendElements(10);
+    for (PRUint32 j = 0; j < 2; j++) {
+        PRBool matchesSomething = PR_FALSE;
+        // build up an array of weights that match the italicness we're looking for
+        for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); i++) {
+            nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
+            const PRUint8 weight = (fe->mWeight / 100);
+            if (fe->mItalic == italic) {
+                weightList[weight] = fe;
+                matchesSomething = PR_TRUE;
+            }
+        }
+        if (matchesSomething)
+            break;
+        italic = !italic;
+    }
+
+    PRInt8 baseWeight, weightDistance;
+    aFontStyle->ComputeWeightAndOffset(&baseWeight, &weightDistance);
+
+    // 500 isn't quite bold so we want to treat it as 400 if we don't
+    // have a 500 weight
+    if (baseWeight == 5 && weightDistance == 0) {
+        // If we have a 500 weight then use it
+        if (weightList[5])
+            return weightList[5];
+
+        // Otherwise treat as 400
+        baseWeight = 4;
+    }
+
+
+    PRInt8 matchBaseWeight = 0;
+    PRInt8 direction = (baseWeight > 5) ? 1 : -1;
+    for (PRInt8 i = baseWeight; ; i += direction) {
+        if (weightList[i]) {
+            matchBaseWeight = i;
+            break;
+        }
+
+        // if we've reached one side without finding a font,
+        // go the other direction until we find a match
+        if (i == 1 || i == 9)
+            direction = -direction;
+    }
+
+    nsRefPtr<FontEntry> matchFE;
+    const PRInt8 absDistance = abs(weightDistance);
+    direction = (weightDistance >= 0) ? 1 : -1;
+    for (PRInt8 i = matchBaseWeight, k = 0; i < 10 && i > 0; i += direction) {
+        if (weightList[i]) {
+            matchFE = weightList[i];
+            k++;
+        }
+        if (k > absDistance)
+            break;
+    }
+
+    if (!matchFE) {
+        /* if we still don't have a match, grab the closest thing in the other direction */
+        direction = -direction;
+        for (PRInt8 i = matchBaseWeight; i < 10 && i > 0; i += direction) {
+            if (weightList[i]) {
+                matchFE = weightList[i];
+            }
+        }
+    }
+
+
+    NS_ASSERTION(matchFE, "we should always be able to return something here");
+    return matchFE;
 }
 
 cmsHPROFILE
 gfxWindowsPlatform::GetPlatformCMSOutputProfile()
 {
     WCHAR str[1024+1];
     DWORD size = 1024;