bug 382542. support synthetic bold for fonts. r=vlad
authorpavlov@pavlov.net
Wed, 19 Mar 2008 22:35:05 -0700
changeset 13360 e1d64a00fd905b4ba32eeac5d7104c226802cb5f
parent 13359 58316a69961915e6a8ac8d04f3d69e8d8195c97c
child 13361 c7312b2c6d86079dbd1d607e79cc534a7f4ac45c
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs382542
milestone1.9b5pre
bug 382542. support synthetic bold for fonts. r=vlad
gfx/thebes/public/gfxFontUtils.h
gfx/thebes/public/gfxWindowsFonts.h
gfx/thebes/src/gfxWindowsFonts.cpp
gfx/thebes/src/gfxWindowsPlatform.cpp
--- a/gfx/thebes/public/gfxFontUtils.h
+++ b/gfx/thebes/public/gfxFontUtils.h
@@ -57,23 +57,34 @@
 
 // code from gfxWindowsFonts.h
 
 class gfxSparseBitSet {
 private:
     enum { BLOCK_SIZE = 32 };   // ==> 256 codepoints per block
     enum { BLOCK_SIZE_BITS = BLOCK_SIZE * 8 };
     enum { BLOCK_INDEX_SHIFT = 8 };
-    
+
     struct Block {
+        Block(const Block& aBlock) { memcpy(mBits, aBlock.mBits, sizeof(mBits)); }
         Block(unsigned char memsetValue = 0) { memset(mBits, memsetValue, BLOCK_SIZE); }
         PRUint8 mBits[BLOCK_SIZE];
     };
 
 public:
+    gfxSparseBitSet() { }
+    gfxSparseBitSet(const gfxSparseBitSet& aBitset) {
+        PRUint32 len = aBitset.mBlocks.Length();
+        mBlocks.AppendElements(len);
+        for (PRUint32 i = 0; i < len; ++i) {
+            Block *block = aBitset.mBlocks[i];
+            if (block)
+                mBlocks[i] = new Block(*block);
+        }
+    }
     PRBool test(PRUint32 aIndex) {
         PRUint32 blockIndex = aIndex/BLOCK_SIZE_BITS;
         if (blockIndex >= mBlocks.Length())
             return PR_FALSE;
         Block *block = mBlocks[blockIndex];
         if (!block)
             return PR_FALSE;
         return ((block->mBits[(aIndex>>3) & (BLOCK_SIZE - 1)]) & (1 << (aIndex & 0x7))) != 0;
--- a/gfx/thebes/public/gfxWindowsFonts.h
+++ b/gfx/thebes/public/gfxWindowsFonts.h
@@ -81,16 +81,33 @@ public:
 
     FontEntry(FontFamily *aFontFamily) : 
         mFamily(aFontFamily), mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE),
         mTrueType(PR_FALSE), mIsType1(PR_FALSE),
         mIsBadUnderlineFont(PR_FALSE), mCharset(0), mUnicodeRanges(0)
     {
     }
 
+    FontEntry(const FontEntry& aFontEntry) :
+        mFamily(aFontEntry.mFamily),
+        mWindowsFamily(aFontEntry.mWindowsFamily),
+        mWindowsPitch(aFontEntry.mWindowsPitch),
+        mUnicodeFont(aFontEntry.mUnicodeFont),
+        mSymbolFont(aFontEntry.mSymbolFont),
+        mTrueType(aFontEntry.mTrueType),
+        mIsType1(aFontEntry.mIsType1),
+        mIsBadUnderlineFont(aFontEntry.mIsBadUnderlineFont),
+        mItalic(aFontEntry.mItalic),
+        mWeight(aFontEntry.mWeight),
+        mCharset(aFontEntry.mCharset),
+        mUnicodeRanges(aFontEntry.mUnicodeRanges),
+        mCharacterMap(aFontEntry.mCharacterMap)
+    {
+    }
+
     const nsString& GetName() const {
         return mFamily->mName;
     }
 
     PRBool IsCrappyFont() const {
         /* return if it is a bitmap not a unicode font */
         return (!mUnicodeFont || mSymbolFont || mIsType1);
     }
--- a/gfx/thebes/src/gfxWindowsFonts.cpp
+++ b/gfx/thebes/src/gfxWindowsFonts.cpp
@@ -330,25 +330,17 @@ gfxWindowsFont::FillLogFont(gfxFloat aSi
     mLogFont.lfClipPrecision  = CLIP_TURNOFF_FONTASSOCIATION;
     mLogFont.lfQuality        = DEFAULT_QUALITY;
     mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
     // always force lfItalic if we want it.  Font selection code will
     // do its best to give us an italic font entry, but if no face exists
     // it may give us a regular one based on weight.  Windows should
     // do fake italic for us in that case.
     mLogFont.lfItalic         = (GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? TRUE : FALSE;
-    // for truetype fonts we want to use the entry's weight.
-    // for bitmap fonts we want to force our boldness.
-    if (mFontEntry->mTrueType) {
-        mLogFont.lfWeight     = mFontEntry->mWeight;
-    } else {
-        PRInt8 baseWeight, weightDistance;
-        GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
-        mLogFont.lfWeight     = (baseWeight * 100) + (weightDistance * 100);
-    }
+    mLogFont.lfWeight         = mFontEntry->mWeight;
 
     int len = PR_MIN(mName.Length(), LF_FACESIZE - 1);
     memcpy(mLogFont.lfFaceName, nsPromiseFlatString(mName).get(), len * 2);
     mLogFont.lfFaceName[len] = '\0';
 }
 
 
 nsString
--- a/gfx/thebes/src/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/src/gfxWindowsPlatform.cpp
@@ -263,16 +263,43 @@ gfxWindowsPlatform::FontGetStylesProc(ns
            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;