bug 3512 - implement font-stretch property for Linux (fontconfig) backend. r=karlt

This commit is contained in:
Jonathan Kew 2011-09-05 08:33:43 +01:00
parent fb390fb055
commit 5baab87ad2
3 changed files with 80 additions and 3 deletions

View File

@ -177,6 +177,66 @@ gfxFontconfigUtils::FcWeightForBaseWeight(PRInt8 aBaseWeight)
return aBaseWeight < 2 ? FC_WEIGHT_THIN : FC_WEIGHT_EXTRABLACK;
}
/* static */ PRInt16
gfxFontconfigUtils::GetThebesStretch(FcPattern *aPattern)
{
int width;
if (FcPatternGetInteger(aPattern, FC_WIDTH, 0, &width) != FcResultMatch) {
return NS_FONT_STRETCH_NORMAL;
}
if (width <= (FC_WIDTH_ULTRACONDENSED + FC_WIDTH_EXTRACONDENSED) / 2) {
return NS_FONT_STRETCH_ULTRA_CONDENSED;
}
if (width <= (FC_WIDTH_EXTRACONDENSED + FC_WIDTH_CONDENSED) / 2) {
return NS_FONT_STRETCH_EXTRA_CONDENSED;
}
if (width <= (FC_WIDTH_CONDENSED + FC_WIDTH_SEMICONDENSED) / 2) {
return NS_FONT_STRETCH_CONDENSED;
}
if (width <= (FC_WIDTH_SEMICONDENSED + FC_WIDTH_NORMAL) / 2) {
return NS_FONT_STRETCH_SEMI_CONDENSED;
}
if (width <= (FC_WIDTH_NORMAL + FC_WIDTH_SEMIEXPANDED) / 2) {
return NS_FONT_STRETCH_NORMAL;
}
if (width <= (FC_WIDTH_SEMIEXPANDED + FC_WIDTH_EXPANDED) / 2) {
return NS_FONT_STRETCH_SEMI_EXPANDED;
}
if (width <= (FC_WIDTH_EXPANDED + FC_WIDTH_EXTRAEXPANDED) / 2) {
return NS_FONT_STRETCH_EXPANDED;
}
if (width <= (FC_WIDTH_EXTRAEXPANDED + FC_WIDTH_ULTRAEXPANDED) / 2) {
return NS_FONT_STRETCH_EXTRA_EXPANDED;
}
return NS_FONT_STRETCH_ULTRA_EXPANDED;
}
/* static */ int
gfxFontconfigUtils::FcWidthForThebesStretch(PRInt16 aStretch)
{
switch (aStretch) {
default: // this will catch "normal" (0) as well as out-of-range values
return FC_WIDTH_NORMAL;
case NS_FONT_STRETCH_ULTRA_CONDENSED:
return FC_WIDTH_ULTRACONDENSED;
case NS_FONT_STRETCH_EXTRA_CONDENSED:
return FC_WIDTH_EXTRACONDENSED;
case NS_FONT_STRETCH_CONDENSED:
return FC_WIDTH_CONDENSED;
case NS_FONT_STRETCH_SEMI_CONDENSED:
return FC_WIDTH_SEMICONDENSED;
case NS_FONT_STRETCH_SEMI_EXPANDED:
return FC_WIDTH_SEMIEXPANDED;
case NS_FONT_STRETCH_EXPANDED:
return FC_WIDTH_EXPANDED;
case NS_FONT_STRETCH_EXTRA_EXPANDED:
return FC_WIDTH_EXTRAEXPANDED;
case NS_FONT_STRETCH_ULTRA_EXPANDED:
return FC_WIDTH_ULTRAEXPANDED;
}
}
// This makes a guess at an FC_WEIGHT corresponding to a base weight and
// offset (without any knowledge of which weights are available).
@ -244,6 +304,7 @@ gfxFontconfigUtils::NewPattern(const nsTArray<nsString>& aFamilies,
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aFontStyle.size);
FcPatternAddInteger(pattern, FC_SLANT, GetFcSlant(aFontStyle));
FcPatternAddInteger(pattern, FC_WEIGHT, GuessFcWeight(aFontStyle));
FcPatternAddInteger(pattern, FC_WIDTH, FcWidthForThebesStretch(aFontStyle.stretch));
if (aLang) {
AddString(pattern, FC_LANG, aLang);

View File

@ -149,12 +149,15 @@ public:
static PRUint8 FcSlantToThebesStyle(int aFcSlant);
static PRUint8 GetThebesStyle(FcPattern *aPattern); // slant
static PRUint16 GetThebesWeight(FcPattern *aPattern);
static PRInt16 GetThebesStretch(FcPattern *aPattern);
static int GetFcSlant(const gfxFontStyle& aFontStyle);
// Returns a precise FC_WEIGHT from |aBaseWeight|,
// which is a CSS absolute weight / 100.
static int FcWeightForBaseWeight(PRInt8 aBaseWeight);
static int FcWidthForThebesStretch(PRInt16 aStretch);
static PRBool GetFullnameFromFamilyAndStyle(FcPattern *aFont,
nsACString *aFullname);

View File

@ -449,6 +449,14 @@ gfxUserFcFontEntry::AdjustPatternToCSS(FcPattern *aPattern)
IsItalic() ? FC_SLANT_OBLIQUE : FC_SLANT_ROMAN);
}
int fontWidth = -1;
FcPatternGetInteger(aPattern, FC_WIDTH, 0, &fontWidth);
int cssWidth = gfxFontconfigUtils::FcWidthForThebesStretch(mStretch);
if (cssWidth != fontWidth) {
FcPatternDel(aPattern, FC_WIDTH);
FcPatternAddInteger(aPattern, FC_WIDTH, cssWidth);
}
// Ensure that there is a fullname property (if there is a family
// property) so that fontconfig rules can identify the real name of the
// font, because the family property will be replaced.
@ -1250,8 +1258,9 @@ private:
// and style |aStyle| properties.
static const nsTArray< nsCountedRef<FcPattern> >*
FindFontPatterns(gfxUserFontSet *mUserFontSet,
const nsACString &aFamily, PRUint8 aStyle, PRUint16 aWeight,
PRBool& aFoundFamily, PRBool& aWaitForUserFont)
const nsACString &aFamily, PRUint8 aStyle,
PRUint16 aWeight, PRInt16 aStretch,
PRBool& aFoundFamily, PRBool& aWaitForUserFont)
{
// Convert to UTF16
NS_ConvertUTF8toUTF16 utf16Family(aFamily);
@ -1264,6 +1273,7 @@ FindFontPatterns(gfxUserFontSet *mUserFontSet,
gfxFontStyle style;
style.style = aStyle;
style.weight = aWeight;
style.stretch = aStretch;
gfxUserFcFontEntry *fontEntry = static_cast<gfxUserFcFontEntry*>
(mUserFontSet->FindFontEntry(utf16Family, style, aFoundFamily,
@ -1431,10 +1441,13 @@ gfxFcFontSet::SortPreferredFonts(PRBool &aWaitForUserFont)
gfxFontconfigUtils::FcSlantToThebesStyle(requestedSlant);
PRUint16 thebesWeight =
gfxFontconfigUtils::GetThebesWeight(mSortPattern);
PRInt16 thebesStretch =
gfxFontconfigUtils::GetThebesStretch(mSortPattern);
PRBool foundFamily, waitForUserFont;
familyFonts = FindFontPatterns(mUserFontSet, cssFamily,
thebesStyle, thebesWeight,
thebesStyle,
thebesWeight, thebesStretch,
foundFamily, waitForUserFont);
if (waitForUserFont) {
aWaitForUserFont = PR_TRUE;