From 172bb497815bfaaf7b1958c9b7d98a6317995835 Mon Sep 17 00:00:00 2001 From: "darin%netscape.com" Date: Tue, 4 Dec 2001 00:47:38 +0000 Subject: [PATCH] fixes bug 94327 "When there are multiple fonts with different foundry names but the same family name moz should pick the best fit based on width, weight and available size" patch=Roland.Mainz@informatik.med.uni-giessen.de r=katakai@japan.sun.com,(R.K.Aa)dark@c2i.net sr=kin@netscape.com,jst@netscape.com git-svn-id: svn://10.0.0.236/trunk@109586 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp | 326 ++++++++++++------- mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp | 360 +++++++++++++-------- 2 files changed, 441 insertions(+), 245 deletions(-) diff --git a/mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp b/mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp index 60a8c425dbe..fb3f47bbd62 100644 --- a/mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp +++ b/mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp @@ -232,7 +232,8 @@ static nsIUnicodeEncoder* gUserDefinedConverter = nsnull; static nsHashtable* gAliases = nsnull; static nsHashtable* gCharSetMaps = nsnull; static nsHashtable* gFamilies = nsnull; -static nsHashtable* gNodes = nsnull; +static nsHashtable* gFFRENodes = nsnull; +static nsHashtable* gAFRENodes = nsnull; // gCachedFFRESearches holds the "already looked up" // FFRE (Foundry Family Registry Encoding) font searches static nsHashtable* gCachedFFRESearches = nsnull; @@ -764,10 +765,15 @@ FreeGlobals(void) delete gCachedFFRESearches; gCachedFFRESearches = nsnull; } - if (gNodes) { - gNodes->Reset(FreeNode, nsnull); - delete gNodes; - gNodes = nsnull; + if (gFFRENodes) { + gFFRENodes->Reset(FreeNode, nsnull); + delete gFFRENodes; + gFFRENodes = nsnull; + } + if (gAFRENodes) { + gAFRENodes->Reset(FreeNode, nsnull); + delete gAFRENodes; + gAFRENodes = nsnull; } NS_IF_RELEASE(gPref); if (gSpecialCharSets) { @@ -920,8 +926,13 @@ InitGlobals(void) SIZE_FONT_PRINTF(("gBitmapUndersize = %g", gBitmapUndersize)); } - gNodes = new nsHashtable(); - if (!gNodes) { + gFFRENodes = new nsHashtable(); + if (!gFFRENodes) { + FreeGlobals(); + return NS_ERROR_OUT_OF_MEMORY; + } + gAFRENodes = new nsHashtable(); + if (!gAFRENodes) { FreeGlobals(); return NS_ERROR_OUT_OF_MEMORY; } @@ -2730,7 +2741,11 @@ nsFontMetricsGTK::PickASizeAndLoad(nsFontStretch* aStretch, // if we do not have the correct size // check if we can use a scaled font - if ((mPixelSize != bitmap_size) && (aStretch->mScalable)) { + // (when the size of a hand tuned font is close to the desired size + // favor it over outline scaled font) + if (( (bitmap_size < mPixelSize-(mPixelSize/10)) + || (bitmap_size > mPixelSize+(mPixelSize/10))) + && (aStretch->mScalable)) { // if we have an outline font then use that // if it is allowed to be closer than the bitmap if (aStretch->mOutlineScaled) { @@ -3281,8 +3296,133 @@ SetFontLangGroupInfo(nsFontCharSetMap* aCharSetMap) } } +static nsFontStyle* +NodeGetStyle(nsFontNode* aNode, int aStyleIndex) +{ + nsFontStyle* style = aNode->mStyles[aStyleIndex]; + if (!style) { + style = new nsFontStyle; + if (!style) { + return nsnull; + } + aNode->mStyles[aStyleIndex] = style; + } + return style; +} + +static nsFontWeight* +NodeGetWeight(nsFontStyle* aStyle, int aWeightIndex) +{ + nsFontWeight* weight = aStyle->mWeights[aWeightIndex]; + if (!weight) { + weight = new nsFontWeight; + if (!weight) { + return nsnull; + } + aStyle->mWeights[aWeightIndex] = weight; + } + return weight; +} + +static nsFontStretch* +NodeGetStretch(nsFontWeight* aWeight, int aStretchIndex) +{ + nsFontStretch* stretch = aWeight->mStretches[aStretchIndex]; + if (!stretch) { + stretch = new nsFontStretch; + if (!stretch) { + return nsnull; + } + aWeight->mStretches[aStretchIndex] = stretch; + } + return stretch; +} + +static PRBool +NodeAddScalable(nsFontStretch* aStretch, PRBool aOutlineScaled, + const char *aDashFoundry, const char *aFamily, + const char *aWeight, const char * aSlant, + const char *aWidth, const char *aStyle, + const char *aSpacing, const char *aCharSet) +{ + // if we have both an outline scaled font and a bitmap + // scaled font pick the outline scaled font + if ((aStretch->mScalable) && (!aStretch->mOutlineScaled) + && (aOutlineScaled)) { + PR_smprintf_free(aStretch->mScalable); + aStretch->mScalable = nsnull; + } + if (!aStretch->mScalable) { + aStretch->mOutlineScaled = aOutlineScaled; + if (aOutlineScaled) { + aStretch->mScalable = + PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-0-0-%s-*-%s", + aDashFoundry, aFamily, aWeight, aSlant, aWidth, aStyle, + aSpacing, aCharSet); + if (!aStretch->mScalable) + return PR_FALSE; + } + else { + aStretch->mScalable = + PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-*-*-%s-*-%s", + aDashFoundry, aFamily, aWeight, aSlant, aWidth, aStyle, + aSpacing, aCharSet); + if (!aStretch->mScalable) + return PR_FALSE; + } + } + return PR_TRUE; +} + +static PRBool +NodeAddSize(nsFontStretch* aStretch, int aSize, const char *aName, + nsFontCharSetInfo* aCharSetInfo) +{ + PRBool haveSize = PR_FALSE; + if (aStretch->mSizesCount) { + nsFontGTK** end = &aStretch->mSizes[aStretch->mSizesCount]; + nsFontGTK** s; + for (s = aStretch->mSizes; s < end; s++) { + if ((*s)->mSize == aSize) { + haveSize = PR_TRUE; + break; + } + } + } + if (!haveSize) { + if (aStretch->mSizesCount == aStretch->mSizesAlloc) { + int newSize = 2 * (aStretch->mSizesAlloc ? aStretch->mSizesAlloc : 1); + nsFontGTK** newSizes = new nsFontGTK*[newSize]; + if (!newSizes) + return PR_FALSE; + for (int j = aStretch->mSizesAlloc - 1; j >= 0; j--) { + newSizes[j] = aStretch->mSizes[j]; + } + aStretch->mSizesAlloc = newSize; + delete [] aStretch->mSizes; + aStretch->mSizes = newSizes; + } + char* copy = PR_smprintf("%s", aName); + if (!copy) { + return PR_FALSE; + } + nsFontGTK* size = new nsFontGTKNormal(); + if (!size) { + return PR_FALSE; + } + aStretch->mSizes[aStretch->mSizesCount++] = size; + size->mName = copy; + // size->mFont is initialized in the constructor + size->mSize = aSize; + size->mBaselineAdjust = 0; + size->mCCMap = nsnull; + size->mCharSetInfo = aCharSetInfo; + } + return PR_TRUE; +} + static void -GetFontNames(const char* aPattern, nsFontNodeArray* aNodes) +GetFontNames(const char* aPattern, PRBool aAnyFoundry, nsFontNodeArray* aNodes) { #ifdef NS_FONT_DEBUG_CALL_TRACE if (gDebug & NS_FONT_DEBUG_CALL_TRACE) { @@ -3291,6 +3431,14 @@ GetFontNames(const char* aPattern, nsFontNodeArray* aNodes) #endif nsCAutoString previousNodeName; + nsHashtable* node_hash; + if (aAnyFoundry) { + NS_ASSERTION(aPattern[1] == '*', "invalid 'anyFoundry' pattern"); + node_hash = gAFRENodes; + } + else { + node_hash = gFFRENodes; + } /* * We do not use XListFontsWithInfo here, because it is very expensive. @@ -3400,6 +3548,19 @@ GetFontNames(const char* aPattern, nsFontNodeArray* aNodes) FIND_FIELD(averageWidth); if (averageWidth[0] == '0') { scalable = 1; +/* Workaround for bug 103159 ("sorting fonts by foundry names cause font + * size of css ignored in some cases"). + * Hardcoded font ban until bug 104075 ("need X font banning") has been + * implemented. See http://bugzilla.mozilla.org/show_bug.cgi?id=94327#c34 + * for additional comments... + */ +#ifndef ENABLE_X_FONT_BANNING + // skip 'mysterious' and 'spurious' cases like + // -adobe-times-medium-r-normal--17-120-100-100-p-0-iso8859-9 + if ((pixelSize[0] != '0' || pointSize[0] != 0) && + (outline_scaled == PR_FALSE) ) + continue; +#endif /* ENABLE_X_FONT_BANNING */ } char* charSetName = p; // CHARSET_REGISTRY & CHARSET_ENCODING if (!*charSetName) { @@ -3431,22 +3592,27 @@ GetFontNames(const char* aPattern, nsFontNodeArray* aNodes) SetCharsetLangGroup(charSetInfo); SetFontLangGroupInfo(charSetMap); - nsCAutoString nodeName(foundry); + nsCAutoString nodeName; + if (aAnyFoundry) + nodeName.Assign('*'); + else + nodeName.Assign(foundry); nodeName.Append('-'); nodeName.Append(familyName); nodeName.Append('-'); nodeName.Append(charSetName); nsCStringKey key(nodeName); - nsFontNode* node = (nsFontNode*) gNodes->Get(&key); + nsFontNode* node = (nsFontNode*) node_hash->Get(&key); if (!node) { node = new nsFontNode; if (!node) { continue; } - gNodes->Put(&key, node); + node_hash->Put(&key, node); node->mName = nodeName; node->mCharSetInfo = charSetInfo; } + int found = 0; if (nodeName == previousNodeName) { found = 1; @@ -3473,14 +3639,9 @@ GetFontNames(const char* aPattern, nsFontNodeArray* aNodes) styleIndex = NS_FONT_STYLE_NORMAL; break; } - nsFontStyle* style = node->mStyles[styleIndex]; - if (!style) { - style = new nsFontStyle; - if (!style) { - continue; - } - node->mStyles[styleIndex] = style; - } + nsFontStyle* style = NodeGetStyle(node, styleIndex); + if (!style) + continue; nsCStringKey weightKey(weightName); int weightNumber = NS_PTR_TO_INT32(gWeights->Get(&weightKey)); @@ -3491,14 +3652,9 @@ GetFontNames(const char* aPattern, nsFontNodeArray* aNodes) weightNumber = NS_FONT_WEIGHT_NORMAL; } int weightIndex = WEIGHT_INDEX(weightNumber); - nsFontWeight* weight = style->mWeights[weightIndex]; - if (!weight) { - weight = new nsFontWeight; - if (!weight) { - continue; - } - style->mWeights[weightIndex] = weight; - } + nsFontWeight* weight = NodeGetWeight(style, weightIndex); + if (!weight) + continue; nsCStringKey setWidthKey(setWidth); int stretchIndex = NS_PTR_TO_INT32(gStretches->Get(&setWidthKey)); @@ -3509,68 +3665,16 @@ GetFontNames(const char* aPattern, nsFontNodeArray* aNodes) stretchIndex = 5; } stretchIndex--; - nsFontStretch* stretch = weight->mStretches[stretchIndex]; - if (!stretch) { - stretch = new nsFontStretch; - if (!stretch) { - continue; - } - weight->mStretches[stretchIndex] = stretch; - } - if (scalable) { - // if we have both an outline scaled font and a bitmap - // scaled font pick the outline scaled font - if ((stretch->mScalable) && (!stretch->mOutlineScaled) - && (outline_scaled)) { - PR_smprintf_free(stretch->mScalable); - stretch->mScalable = nsnull; - } - if (!stretch->mScalable) { - stretch->mOutlineScaled = outline_scaled; - if (outline_scaled) { - stretch->mScalable = - PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-0-0-%s-*-%s", - name, familyName, weightName, slant, setWidth, addStyle, - spacing, charSetName); - } - else { - stretch->mScalable = - PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-*-*-%s-*-%s", - name, familyName, weightName, slant, setWidth, addStyle, - spacing, charSetName); - } - } + nsFontStretch* stretch = NodeGetStretch(weight, stretchIndex); + if (!stretch) continue; + + if (scalable) { + if (!NodeAddScalable(stretch, outline_scaled, name, familyName, + weightName, slant, setWidth, addStyle, spacing, charSetName)) + continue; } - int pixels = atoi(pixelSize); - if (stretch->mSizesCount) { - nsFontGTK** end = &stretch->mSizes[stretch->mSizesCount]; - nsFontGTK** s; - for (s = stretch->mSizes; s < end; s++) { - if ((*s)->mSize == pixels) { - break; - } - } - if (s != end) { - continue; - } - } - if (stretch->mSizesCount == stretch->mSizesAlloc) { - int newSize = 2 * (stretch->mSizesAlloc ? stretch->mSizesAlloc : 1); - nsFontGTK** newPointer = new nsFontGTK*[newSize]; - if (newPointer) { - for (int j = stretch->mSizesAlloc - 1; j >= 0; j--) { - newPointer[j] = stretch->mSizes[j]; - } - stretch->mSizesAlloc = newSize; - delete [] stretch->mSizes; - stretch->mSizes = newPointer; - } - else { - continue; - } - } p = name; while (p < charSetName) { if (!*p) { @@ -3578,21 +3682,10 @@ GetFontNames(const char* aPattern, nsFontNodeArray* aNodes) } p++; } - char* copy = PR_smprintf("%s", name); - if (!copy) { + + int pixels = atoi(pixelSize); + if (!NodeAddSize(stretch, pixels, name, charSetInfo)) continue; - } - nsFontGTK* size = new nsFontGTKNormal(); - if (!size) { - continue; - } - stretch->mSizes[stretch->mSizesCount++] = size; - size->mName = copy; - // size->mFont is initialized in the constructor - size->mSize = pixels; - size->mBaselineAdjust = 0; - size->mCCMap = nsnull; - size->mCharSetInfo = charSetInfo; } XFreeFontNames(list); @@ -3611,7 +3704,9 @@ GetAllFontNames(void) if (!gGlobalList) { return NS_ERROR_OUT_OF_MEMORY; } - GetFontNames("-*", gGlobalList); + /* Using "-*" instead of the full-qualified "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" + * because it's faster and "smarter" - see bug 34242 for details. */ + GetFontNames("-*", PR_FALSE, gGlobalList); } return NS_OK; @@ -3628,7 +3723,7 @@ FindFamily(nsCString* aName) char pattern[256]; PR_snprintf(pattern, sizeof(pattern), "-*-%s-*-*-*-*-*-*-*-*-*-*-*-*", aName->get()); - GetFontNames(pattern, &family->mNodes); + GetFontNames(pattern, PR_TRUE, &family->mNodes); gFamilies->Put(&key, family); } } @@ -3707,7 +3802,9 @@ nsFontMetricsGTK::TryNodes(nsAWritableCString &aFFREName, PRUnichar aChar) { FIND_FONT_PRINTF((" TryNodes aFFREName = %s", PromiseFlatCString(aFFREName).get())); - nsCStringKey key(PromiseFlatCString(aFFREName).get()); + const char *FFREName = PromiseFlatCString(aFFREName).get(); + nsCStringKey key(FFREName); + PRBool anyFoundry = (FFREName[0] == '*'); nsFontNodeArray* nodes = (nsFontNodeArray*) gCachedFFRESearches->Get(&key); if (!nodes) { nsCAutoString pattern; @@ -3715,7 +3812,7 @@ nsFontMetricsGTK::TryNodes(nsAWritableCString &aFFREName, PRUnichar aChar) nodes = new nsFontNodeArray; if (!nodes) return nsnull; - GetFontNames(pattern.get(), nodes); + GetFontNames(pattern.get(), anyFoundry, nodes); gCachedFFRESearches->Put(&key, nodes); } int i, cnt = nodes->Count(); @@ -3739,17 +3836,16 @@ nsFontMetricsGTK::TryNode(nsCString* aName, PRUnichar aChar) nsFontGTK* font; nsCStringKey key(*aName); - nsFontNode* node = (nsFontNode*) gNodes->Get(&key); + nsFontNode* node = (nsFontNode*) gFFRENodes->Get(&key); if (!node) { nsCAutoString pattern; FFREToXLFDPattern(*aName, pattern); nsFontNodeArray nodes; - GetFontNames(pattern.get(), &nodes); - // no need to call gNodes->Put() since GetFontNames already did + GetFontNames(pattern.get(), PR_FALSE, &nodes); + // no need to call gFFRENodes->Put() since GetFontNames already did if (nodes.Count() > 0) { - // XXX This assertion may be spurious; you can have more than - // -*-courier-iso8859-1 font, for example, from different - // foundries. + // This assertion is not spurious; when searching for an FFRE + // like -*-courier-iso8859-1 TryNodes should be called not TryNode NS_ASSERTION((nodes.Count() == 1), "unexpected number of nodes"); node = nodes.GetElement(0); } @@ -3759,7 +3855,7 @@ nsFontMetricsGTK::TryNode(nsCString* aName, PRUnichar aChar) if (!node) { return nsnull; } - gNodes->Put(&key, node); + gFFRENodes->Put(&key, node); node->mDummy = 1; } } @@ -4288,10 +4384,10 @@ nsFontMetricsGTK::FindLangGroupFont(nsIAtom* aLangGroup, PRUnichar aChar, nsCStr } // look for a font with this charset (registry-encoding) & char // - nsCAutoString ffreName(""); + nsCAutoString ffreName; if(aName) { // if aName was specified so call TryNode() not TryNodes() - ffreName.Append(*aName); + ffreName.Assign(*aName); FFRESubstituteCharset(ffreName, charSetMap->mName); FIND_FONT_PRINTF((" %s ffre = %s", charSetMap->mName, ffreName.get())); if(aName->First() == '*') { @@ -4303,7 +4399,7 @@ nsFontMetricsGTK::FindLangGroupFont(nsIAtom* aLangGroup, PRUnichar aChar, nsCStr NS_ASSERTION(font ? font->SupportsChar(aChar) : 1, "font supposed to support this char"); } else { // no name was specified so call TryNodes() for this charset - ffreName.Append("*-*-*-*"); + ffreName.Assign("*-*-*-*"); FFRESubstituteCharset(ffreName, charSetMap->mName); FIND_FONT_PRINTF((" %s ffre = %s", charSetMap->mName, ffreName.get())); font = TryNodes(ffreName, aChar); diff --git a/mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp b/mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp index c3821dea4a2..b24bc842830 100644 --- a/mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp +++ b/mozilla/gfx/src/xlib/nsFontMetricsXlib.cpp @@ -60,6 +60,7 @@ #include "nsAWritableString.h" #include "nsXPIDLString.h" #include +#include #include #ifdef USE_XPRINT #include @@ -208,7 +209,8 @@ static nsIUnicodeEncoder* gUserDefinedConverter = nsnull; static nsHashtable* gAliases = nsnull; static nsHashtable* gCharSetMaps = nsnull; static nsHashtable* gFamilies = nsnull; -static nsHashtable* gNodes = nsnull; +static nsHashtable* gFFRENodes = nsnull; +static nsHashtable* gAFRENodes = nsnull; /* gCachedFFRESearches holds the "already looked up" FFRE (Foundry Family Registry Encoding) font searches */ static nsHashtable* gCachedFFRESearches = nsnull; @@ -725,10 +727,16 @@ nsFontMetricsXlib::FreeGlobals(void) gCachedFFRESearches = nsnull; } - if (gNodes) { - gNodes->Reset(FreeNode, nsnull); - delete gNodes; - gNodes = nsnull; + if (gFFRENodes) { + gFFRENodes->Reset(FreeNode, nsnull); + delete gFFRENodes; + gFFRENodes = nsnull; + } + + if (gAFRENodes) { + gAFRENodes->Reset(FreeNode, nsnull); + delete gAFRENodes; + gAFRENodes = nsnull; } NS_IF_RELEASE(gPref); @@ -833,8 +841,14 @@ nsFontMetricsXlib::InitGlobals(nsIDeviceContext *aDevice) if (percent) gBitmapUndersize = percent / 100.0; - gNodes = new nsHashtable(); - if (!gNodes) { + gFFRENodes = new nsHashtable(); + if (!gFFRENodes) { + FreeGlobals(); + return NS_ERROR_OUT_OF_MEMORY; + } + + gAFRENodes = new nsHashtable(); + if (!gAFRENodes) { FreeGlobals(); return NS_ERROR_OUT_OF_MEMORY; } @@ -2602,7 +2616,11 @@ nsFontMetricsXlib::PickASizeAndLoad(nsFontStretchXlib* aStretch, #endif /* !ABS */ // if we do not have the correct size // check if we can use a scaled font - if ((mPixelSize != bitmap_size) && (aStretch->mScalable)) { + // (when the size of a hand tuned font is close to the desired size + // favor it over outline scaled font) + if (( (bitmap_size < mPixelSize-(mPixelSize/10)) + || (bitmap_size > mPixelSize+(mPixelSize/10))) + && (aStretch->mScalable)) { // if we have an outline font then use that // if it is allowed to be closer than the bitmap if (aStretch->mOutlineScaled) { @@ -2627,7 +2645,7 @@ nsFontMetricsXlib::PickASizeAndLoad(nsFontStretchXlib* aStretch, NS_ASSERTION((bitmap_size < NOT_FOUND_FONT_SIZE) || use_scaled_font, "did not find font size"); - if (use_scaled_font) { + if (use_scaled_font && aStretch->mScalable) { PRInt32 i; PRInt32 n = aStretch->mScaledFonts.Count(); nsFontXlib *p = nsnull; @@ -3073,11 +3091,154 @@ SetFontLangGroupInfo(nsFontCharSetMapXlib* aCharSetMap) } } -static void -GetFontNames(const char* aPattern, nsFontNodeArrayXlib* aNodes) +static nsFontStyleXlib* +NodeGetStyle(nsFontNodeXlib* aNode, int aStyleIndex) +{ + nsFontStyleXlib* style = aNode->mStyles[aStyleIndex]; + if (!style) { + style = new nsFontStyleXlib; + if (!style) { + return nsnull; + } + aNode->mStyles[aStyleIndex] = style; + } + return style; +} + +static nsFontWeightXlib* +NodeGetWeight(nsFontStyleXlib* aStyle, int aWeightIndex) +{ + nsFontWeightXlib* weight = aStyle->mWeights[aWeightIndex]; + if (!weight) { + weight = new nsFontWeightXlib; + if (!weight) { + return nsnull; + } + aStyle->mWeights[aWeightIndex] = weight; + } + return weight; +} + +static nsFontStretchXlib* +NodeGetStretch(nsFontWeightXlib* aWeight, int aStretchIndex) +{ + nsFontStretchXlib* stretch = aWeight->mStretches[aStretchIndex]; + if (!stretch) { + stretch = new nsFontStretchXlib; + if (!stretch) { + return nsnull; + } + aWeight->mStretches[aStretchIndex] = stretch; + } + return stretch; +} + +static PRBool +NodeAddScalable(nsFontStretchXlib* aStretch, PRBool aOutlineScaled, + const char *aDashFoundry, const char *aFamily, + const char *aWeight, const char *aSlant, + const char *aWidth, const char *aStyle, + const char *aSpacing, const char *aCharSet) +{ +#ifdef USE_XPRINT + /* gisburn: disabled for Xprint - this kills printer buildin fonts + * Xprint printer-buildin fonts look like bitmap scaled fonts but are + * (scaleable) printer-buildin fonts in reality. + */ + if (nsFontMetricsXlib::mPrinterMode) + return PR_TRUE; +#endif /* USE_XPRINT */ + + // if we have both an outline scaled font and a bitmap + // scaled font pick the outline scaled font + if ((aStretch->mScalable) && (!aStretch->mOutlineScaled) + && (aOutlineScaled)) { + PR_smprintf_free(aStretch->mScalable); + aStretch->mScalable = nsnull; + } + if (!aStretch->mScalable) { + aStretch->mOutlineScaled = aOutlineScaled; + if (aOutlineScaled) { + aStretch->mScalable = + PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-0-0-%s-*-%s", + aDashFoundry, aFamily, aWeight, aSlant, aWidth, aStyle, + aSpacing, aCharSet); + if (!aStretch->mScalable) + return PR_FALSE; + } + else { + aStretch->mScalable = + PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-*-*-%s-*-%s", + aDashFoundry, aFamily, aWeight, aSlant, aWidth, aStyle, + aSpacing, aCharSet); + if (!aStretch->mScalable) + return PR_FALSE; + } + } + return PR_TRUE; +} + +static PRBool +NodeAddSize(nsFontStretchXlib* aStretch, int aSize, const char *aName, + nsFontCharSetXlibInfo* aCharSetInfo) +{ + PRBool haveSize = PR_FALSE; + if (aStretch->mSizesCount) { + nsFontXlib** end = &aStretch->mSizes[aStretch->mSizesCount]; + nsFontXlib** s; + for (s = aStretch->mSizes; s < end; s++) { + if ((*s)->mSize == aSize) { + haveSize = PR_TRUE; + break; + } + } + } + if (!haveSize) { + if (aStretch->mSizesCount == aStretch->mSizesAlloc) { + int newSize = 2 * (aStretch->mSizesAlloc ? aStretch->mSizesAlloc : 1); + nsFontXlib** newSizes = new nsFontXlib*[newSize]; + if (!newSizes) + return PR_FALSE; + for (int j = aStretch->mSizesAlloc - 1; j >= 0; j--) { + newSizes[j] = aStretch->mSizes[j]; + } + aStretch->mSizesAlloc = newSize; + delete [] aStretch->mSizes; + aStretch->mSizes = newSizes; + } + char* copy = PR_smprintf("%s", aName); + if (!copy) { + return PR_FALSE; + } + nsFontXlib* size = new nsFontXlibNormal(); + if (!size) { + return PR_FALSE; + } + aStretch->mSizes[aStretch->mSizesCount++] = size; + size->mName = copy; + // size->mFont is initialized in the constructor + size->mSize = aSize; + size->mBaselineAdjust = 0; + size->mCCMap = nsnull; + size->mCharSetInfo = aCharSetInfo; + } + return PR_TRUE; +} + +static void +GetFontNames(const char* aPattern, PRBool aAnyFoundry, nsFontNodeArrayXlib * aNodes) { - nsCAutoString previousNodeName; Display *dpy = xxlib_rgb_get_display(gXlibRgbHandle); + nsCAutoString previousNodeName; + nsHashtable *node_hash; + + if (aAnyFoundry) { + NS_ASSERTION(aPattern[1] == '*', "invalid 'anyFoundry' pattern"); + node_hash = gAFRENodes; + } + else { + node_hash = gFFRENodes; + } #ifdef USE_XPRINT #ifdef DEBUG @@ -3193,6 +3354,25 @@ GetFontNames(const char* aPattern, nsFontNodeArrayXlib* aNodes) FIND_FIELD(averageWidth); if (averageWidth[0] == '0') { scalable = 1; +/* Workaround for bug 103159 ("sorting fonts by foundry names cause font + * size of css ignored in some cases"). + * Hardcoded font ban until bug 104075 ("need X font banning") has been + * implemented. See http://bugzilla.mozilla.org/show_bug.cgi?id=94327#c34 + * for additional comments... + */ +#ifndef ENABLE_X_FONT_BANNING +#ifdef USE_XPRINT + /* The following check kills Xprint printer-buildin fonts... ;-( */ + if (!nsFontMetricsXlib::mPrinterMode) +#endif /* USE_XPRINT */ + { + // skip 'mysterious' and 'spurious' cases like + // -adobe-times-medium-r-normal--17-120-100-100-p-0-iso8859-9 + if ((pixelSize[0] != '0' || pointSize[0] != 0) && + (outline_scaled == PR_FALSE) ) + continue; + } +#endif /* ENABLE_X_FONT_BANNING */ } char* charSetName = p; // CHARSET_REGISTRY & CHARSET_ENCODING if (!*charSetName) { @@ -3225,20 +3405,24 @@ GetFontNames(const char* aPattern, nsFontNodeArrayXlib* aNodes) SetCharsetLangGroup(charSetInfo); SetFontLangGroupInfo(charSetMap); - nsCAutoString nodeName(foundry); + nsCAutoString nodeName; + if (aAnyFoundry) + nodeName.Assign('*'); + else + nodeName.Assign(foundry); nodeName.Append('-'); nodeName.Append(familyName); nodeName.Append('-'); nodeName.Append(charSetName); nsCStringKey key(nodeName); - nsFontNodeXlib* node = (nsFontNodeXlib*) gNodes->Get(&key); + nsFontNodeXlib* node = (nsFontNodeXlib*) node_hash->Get(&key); if (!node) { node = new nsFontNodeXlib; if (!node) continue; - gNodes->Put(&key, node); + node_hash->Put(&key, node); node->mName = nodeName; node->mCharSetInfo = charSetInfo; } @@ -3269,14 +3453,9 @@ GetFontNames(const char* aPattern, nsFontNodeArrayXlib* aNodes) styleIndex = NS_FONT_STYLE_NORMAL; break; } - nsFontStyleXlib* style = node->mStyles[styleIndex]; - if (!style) { - style = new nsFontStyleXlib; - if (!style) { - continue; - } - node->mStyles[styleIndex] = style; - } + nsFontStyleXlib* style = NodeGetStyle(node, styleIndex); + if (!style) + continue; nsCStringKey weightKey(weightName); int weightNumber = NS_PTR_TO_INT32(gWeights->Get(&weightKey)); @@ -3286,14 +3465,9 @@ GetFontNames(const char* aPattern, nsFontNodeArrayXlib* aNodes) weightNumber = NS_FONT_WEIGHT_NORMAL; } int weightIndex = WEIGHT_INDEX(weightNumber); - nsFontWeightXlib* weight = style->mWeights[weightIndex]; - if (!weight) { - weight = new nsFontWeightXlib; - if (!weight) { - continue; - } - style->mWeights[weightIndex] = weight; - } + nsFontWeightXlib *weight = NodeGetWeight(style, weightIndex); + if (!weight) + continue; nsCStringKey setWidthKey(setWidth); int stretchIndex = NS_PTR_TO_INT32(gStretches->Get(&setWidthKey)); @@ -3303,78 +3477,16 @@ GetFontNames(const char* aPattern, nsFontNodeArrayXlib* aNodes) stretchIndex = 5; } stretchIndex--; - nsFontStretchXlib* stretch = weight->mStretches[stretchIndex]; - if (!stretch) { - stretch = new nsFontStretchXlib; - if (!stretch) { - continue; - } - weight->mStretches[stretchIndex] = stretch; - } - if (scalable) { -/* gisburn: disabled for Xprint - this kills printer buildin fonts - * Xprint printer-buildin fonts look like bitmap scaled fonts but are - * (scaleable) printer-buildin fonts in reality. - */ -#ifdef USE_XPRINT - if(!nsFontMetricsXlib::mPrinterMode) -#endif /* USE_XPRINT */ - { - // if we have both an outline scaled font and a bitmap - // scaled font pick the outline scaled font - if ((stretch->mScalable) && (!stretch->mOutlineScaled) - && (outline_scaled)) { - PR_smprintf_free(stretch->mScalable); - stretch->mScalable = nsnull; - } - } - - if (!stretch->mScalable) { - stretch->mOutlineScaled = outline_scaled; - if (outline_scaled) { - stretch->mScalable = PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-0-0-%s-*-%s", - name, familyName, weightName, slant, setWidth, addStyle, spacing, charSetName); - } - else { - stretch->mScalable = - PR_smprintf("%s-%s-%s-%s-%s-%s-%%d-*-*-*-%s-*-%s", - name, familyName, weightName, slant, setWidth, addStyle, - spacing, charSetName); - } - } + nsFontStretchXlib* stretch = NodeGetStretch(weight, stretchIndex); + if (!stretch) continue; - } - int pixels = atoi(pixelSize); - NS_ASSERTION((pixels > 0), "unexpected pixel size"); - - if (stretch->mSizesCount) { - nsFontXlib** end = &stretch->mSizes[stretch->mSizesCount]; - nsFontXlib** s; - for (s = stretch->mSizes; s < end; s++) { - if ((*s)->mSize == pixels) { - break; - } - } - if (s != end) { + if (scalable) { + if (!NodeAddScalable(stretch, outline_scaled, name, familyName, + weightName, slant, setWidth, addStyle, spacing, charSetName)) continue; - } - } - if (stretch->mSizesCount == stretch->mSizesAlloc) { - int newSize = 2 * (stretch->mSizesAlloc ? stretch->mSizesAlloc : 1); - nsFontXlib** newPointer = new nsFontXlib*[newSize]; - if (newPointer) { - for (int j = stretch->mSizesAlloc - 1; j >= 0; j--) { - newPointer[j] = stretch->mSizes[j]; - } - stretch->mSizesAlloc = newSize; - delete [] stretch->mSizes; - stretch->mSizes = newPointer; - } - else { - continue; - } } + p = name; while (p < charSetName) { if (!*p) { @@ -3383,23 +3495,10 @@ GetFontNames(const char* aPattern, nsFontNodeArrayXlib* aNodes) p++; } - char* copy = PR_smprintf("%s", name); - - if (!copy) { - continue; - } - nsFontXlib* size = new nsFontXlibNormal(); - if (!size) - continue; - - stretch->mSizes[stretch->mSizesCount++] = size; - - size->mName = copy; - size->mFont = nsnull; - size->mSize = pixels; - size->mBaselineAdjust = 0; - size->mCCMap = nsnull; - size->mCharSetInfo = charSetInfo; + int pixels = atoi(pixelSize); + NS_ASSERTION(!((pixels == 0) && (errno == EINVAL)), "unexpected pixel size"); + if (!NodeAddSize(stretch, pixels, name, charSetInfo)) + continue; } XFreeFontNames(list); @@ -3420,7 +3519,7 @@ GetAllFontNames(void) } /* Using "-*" instead of the full-qualified "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" * because it's faster and "smarter" - see bug 34242 for details. */ - GetFontNames("-*", gGlobalList); + GetFontNames("-*", PR_FALSE, gGlobalList); } return NS_OK; @@ -3437,7 +3536,7 @@ FindFamily(nsCString* aName) char pattern[256]; PR_snprintf(pattern, sizeof(pattern), "-*-%s-*-*-*-*-*-*-*-*-*-*-*-*", aName->get()); - GetFontNames(pattern, &family->mNodes); + GetFontNames(pattern, PR_TRUE, &family->mNodes); gFamilies->Put(&key, family); } } @@ -3504,7 +3603,9 @@ FFRESubstituteEncoding(nsAWritableCString &aFFREName, const char *aReplacementEn nsFontXlib* nsFontMetricsXlib::TryNodes(nsAWritableCString &aFFREName, PRUnichar aChar) { - nsCStringKey key(PromiseFlatCString(aFFREName).get()); + const char *FFREName = PromiseFlatCString(aFFREName).get(); + nsCStringKey key(FFREName); + PRBool anyFoundry = (FFREName[0] == '*'); nsFontNodeArrayXlib* nodes = (nsFontNodeArrayXlib*) gCachedFFRESearches->Get(&key); if (!nodes) { nsCAutoString pattern; @@ -3512,7 +3613,7 @@ nsFontMetricsXlib::TryNodes(nsAWritableCString &aFFREName, PRUnichar aChar) nodes = new nsFontNodeArrayXlib; if (!nodes) return nsnull; - GetFontNames(pattern.get(), nodes); + GetFontNames(pattern.get(), anyFoundry, nodes); gCachedFFRESearches->Put(&key, nodes); } int i, cnt = nodes->Count(); @@ -3533,17 +3634,16 @@ nsFontMetricsXlib::TryNode(nsCString* aName, PRUnichar aChar) nsFontXlib* font; nsCStringKey key(*aName); - nsFontNodeXlib* node = (nsFontNodeXlib*) gNodes->Get(&key); + nsFontNodeXlib* node = (nsFontNodeXlib*) gFFRENodes->Get(&key); if (!node) { nsCAutoString pattern; FFREToXLFDPattern(*aName, pattern); nsFontNodeArrayXlib nodes; - GetFontNames(pattern.get(), &nodes); - // no need to call gNodes->Put() since GetFontNames already did + GetFontNames(pattern.get(), PR_FALSE, &nodes); + // no need to call gFFRENodes->Put() since GetFontNames already did if (nodes.Count() > 0) { - // XXX This assertion may be spurious; you can have more than - // -*-courier-iso8859-1 font, for example, from different - // foundries. + // This assertion is not spurious; when searching for an FFRE + // like -*-courier-iso8859-1 TryNodes should be called not TryNode NS_ASSERTION((nodes.Count() == 1), "unexpected number of nodes"); node = nodes.GetElement(0); } @@ -3553,7 +3653,7 @@ nsFontMetricsXlib::TryNode(nsCString* aName, PRUnichar aChar) if (!node) { return nsnull; } - gNodes->Put(&key, node); + gFFRENodes->Put(&key, node); node->mDummy = 1; } } @@ -4025,10 +4125,10 @@ nsFontMetricsXlib::FindLangGroupFont(nsIAtom* aLangGroup, PRUnichar aChar, nsCSt // look for a font with this charset (registry-encoding) & char // - nsCAutoString ffreName(""); + nsCAutoString ffreName; if (aName) { // if aName was specified so call TryNode() not TryNodes() - ffreName.Append(*aName); + ffreName.Assign(*aName); FFRESubstituteCharset(ffreName, charSetMap->mName); if(aName->First() == '*') { // called from TryFamily() @@ -4039,7 +4139,7 @@ nsFontMetricsXlib::FindLangGroupFont(nsIAtom* aLangGroup, PRUnichar aChar, nsCSt NS_ASSERTION(font ? font->SupportsChar(aChar) : 1, "font supposed to support this char"); } else { // no name was specified so call TryNodes() for this charset - ffreName.Append("*-*-*-*"); + ffreName.Assign("*-*-*-*"); FFRESubstituteCharset(ffreName, charSetMap->mName); font = TryNodes(ffreName, aChar); NS_ASSERTION(font ? font->SupportsChar(aChar) : 1, "font supposed to support this char");