Bug 549861 - reland font-variant subproperties with DOM-peer review. r=khuey

This commit is contained in:
John Daggett 2013-05-20 11:59:20 +09:00
parent 3d9c02c05e
commit 0eae803e8f
47 changed files with 2696 additions and 91 deletions

View File

@ -897,6 +897,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(LockedFile, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(CSSFontFeatureValuesRule, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
#ifdef MOZ_TIME_MANAGER
NS_DEFINE_CLASSINFO_DATA(MozTimeManager, nsDOMGenericSH,
@ -2266,6 +2268,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMLockedFile)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(CSSFontFeatureValuesRule, nsIDOMCSSFontFeatureValuesRule)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule)
DOM_CLASSINFO_MAP_END
#ifdef MOZ_TIME_MANAGER
DOM_CLASSINFO_MAP_BEGIN(MozTimeManager, nsIDOMMozTimeManager)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozTimeManager)

View File

@ -232,6 +232,8 @@ DOMCI_CLASS(AsyncScrollEventDetail)
DOMCI_CLASS(LockedFile)
DOMCI_CLASS(CSSFontFeatureValuesRule)
#ifdef MOZ_TIME_MANAGER
DOMCI_CLASS(MozTimeManager)
#endif

View File

@ -69,6 +69,7 @@ interface nsIDOMCSSPrimitiveValue;
interface nsIDOMCSSRule;
interface nsIDOMCSSRuleList;
interface nsIDOMMozCSSKeyframeRule;
interface nsIDOMCSSFontFeatureValuesRule;
interface nsIDOMCSSStyleSheet;
interface nsIDOMCSSStyleDeclaration;
interface nsIDOMCounter;

View File

@ -8,6 +8,7 @@ XPIDL_SOURCES += [
'nsIDOMCSSCharsetRule.idl',
'nsIDOMCSSConditionRule.idl',
'nsIDOMCSSFontFaceRule.idl',
'nsIDOMCSSFontFeatureValuesRule.idl',
'nsIDOMCSSGroupingRule.idl',
'nsIDOMCSSImportRule.idl',
'nsIDOMCSSMediaRule.idl',

View File

@ -32,6 +32,7 @@ interface nsIDOMCSSRule : nsISupports
const unsigned short MOZ_KEYFRAME_RULE = 8;
const unsigned short NAMESPACE_RULE = 10;
const unsigned short SUPPORTS_RULE = 12;
const unsigned short FONT_FEATURE_VALUES_RULE = 14;
readonly attribute unsigned short type;
attribute DOMString cssText;

View File

@ -115,6 +115,17 @@ PEMQExpectedFeatureValue=Found invalid value for media feature.
PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'.
PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'.
PEAnonBoxNotAlone=Did not expect anonymous box.
PEFFVUnexpectedEOF=Unexpected end of @font-feature-values rule.
PEFFVBlockStart=Expected opening { of @font-feature-values rule but found '%1$S'.
PEFFVValueSetStart=Expected opening { of feature value set but found '%1$S'.
PEFFVNoFamily=Expected font family list for @font-feature-values rule but found '%1$S'.
PEFFVUnexpectedBlockEnd=Expected '}' to end @font-feature-values rule but found '%1$S'.
PEFFVUnknownFontVariantPropValue=Unknown font-variant property value '%1$S'.
PEFFVExpectedIdent=Expected identifier but found '%1$S'.
PEFFVExpectedValue=Expected non-negative integer value but found '%1$S'.
PEFFVTooManyValues=Too many values for feature type '%1$S'.
PEFFVGenericInFamilyList=Family list cannot contain generic font family name.
PEFFVValueDefinitionTrailing=Expected end of value definition but found '%1$S'.
PEBadDirValue=Expected 'ltr' or 'rtl' in direction selector but found '%1$S'.
PESupportsConditionStartEOF2='not', '(', or function
PESupportsConditionInParensEOF=')'

View File

@ -492,6 +492,7 @@ var interfaceNamesInGlobalScope =
"CloseEvent",
"IDBCursorWithValue",
"CSSFontFaceRule",
"CSSFontFeatureValuesRule",
"XMLHttpRequestEventTarget",
"CompositionEvent",
"HTMLOutputElement",

View File

@ -11,8 +11,7 @@
nsFont::nsFont(const char* aName, uint8_t aStyle, uint8_t aVariant,
uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
nscoord aSize, float aSizeAdjust,
const nsString* aLanguageOverride)
nscoord aSize)
{
NS_ASSERTION(aName && IsASCII(nsDependentCString(aName)),
"Must only pass ASCII names here");
@ -24,16 +23,21 @@ nsFont::nsFont(const char* aName, uint8_t aStyle, uint8_t aVariant,
stretch = aStretch;
decorations = aDecoration;
size = aSize;
sizeAdjust = aSizeAdjust;
if (aLanguageOverride) {
languageOverride = *aLanguageOverride;
}
sizeAdjust = 0.0;
kerning = NS_FONT_KERNING_AUTO;
synthesis = NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE;
variantAlternates = 0;
variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
variantEastAsian = 0;
variantLigatures = 0;
variantNumeric = 0;
variantPosition = NS_FONT_VARIANT_POSITION_NORMAL;
}
nsFont::nsFont(const nsString& aName, uint8_t aStyle, uint8_t aVariant,
nsFont::nsFont(const nsSubstring& aName, uint8_t aStyle, uint8_t aVariant,
uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
nscoord aSize, float aSizeAdjust,
const nsString* aLanguageOverride)
nscoord aSize)
: name(aName)
{
style = aStyle;
@ -43,10 +47,16 @@ nsFont::nsFont(const nsString& aName, uint8_t aStyle, uint8_t aVariant,
stretch = aStretch;
decorations = aDecoration;
size = aSize;
sizeAdjust = aSizeAdjust;
if (aLanguageOverride) {
languageOverride = *aLanguageOverride;
}
sizeAdjust = 0.0;
kerning = NS_FONT_KERNING_AUTO;
synthesis = NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE;
variantAlternates = 0;
variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
variantEastAsian = 0;
variantLigatures = 0;
variantNumeric = 0;
variantPosition = NS_FONT_VARIANT_POSITION_NORMAL;
}
nsFont::nsFont(const nsFont& aOther)
@ -60,8 +70,18 @@ nsFont::nsFont(const nsFont& aOther)
decorations = aOther.decorations;
size = aOther.size;
sizeAdjust = aOther.sizeAdjust;
languageOverride = aOther.languageOverride;
kerning = aOther.kerning;
synthesis = aOther.synthesis;
fontFeatureSettings = aOther.fontFeatureSettings;
languageOverride = aOther.languageOverride;
variantAlternates = aOther.variantAlternates;
variantCaps = aOther.variantCaps;
variantEastAsian = aOther.variantEastAsian;
variantLigatures = aOther.variantLigatures;
variantNumeric = aOther.variantNumeric;
variantPosition = aOther.variantPosition;
alternateValues = aOther.alternateValues;
featureValueLookup = aOther.featureValueLookup;
}
nsFont::nsFont()
@ -81,8 +101,18 @@ bool nsFont::BaseEquals(const nsFont& aOther) const
(size == aOther.size) &&
(sizeAdjust == aOther.sizeAdjust) &&
name.Equals(aOther.name, nsCaseInsensitiveStringComparator()) &&
(kerning == aOther.kerning) &&
(synthesis == aOther.synthesis) &&
(fontFeatureSettings == aOther.fontFeatureSettings) &&
(languageOverride == aOther.languageOverride) &&
(fontFeatureSettings == aOther.fontFeatureSettings)) {
(variantAlternates == aOther.variantAlternates) &&
(variantCaps == aOther.variantCaps) &&
(variantEastAsian == aOther.variantEastAsian) &&
(variantLigatures == aOther.variantLigatures) &&
(variantNumeric == aOther.variantNumeric) &&
(variantPosition == aOther.variantPosition) &&
(alternateValues == aOther.alternateValues) &&
(featureValueLookup == aOther.featureValueLookup)) {
return true;
}
return false;
@ -109,16 +139,27 @@ nsFont& nsFont::operator=(const nsFont& aOther)
decorations = aOther.decorations;
size = aOther.size;
sizeAdjust = aOther.sizeAdjust;
languageOverride = aOther.languageOverride;
kerning = aOther.kerning;
synthesis = aOther.synthesis;
fontFeatureSettings = aOther.fontFeatureSettings;
languageOverride = aOther.languageOverride;
variantAlternates = aOther.variantAlternates;
variantCaps = aOther.variantCaps;
variantEastAsian = aOther.variantEastAsian;
variantLigatures = aOther.variantLigatures;
variantNumeric = aOther.variantNumeric;
variantPosition = aOther.variantPosition;
alternateValues = aOther.alternateValues;
featureValueLookup = aOther.featureValueLookup;
return *this;
}
void
nsFont::AddFontFeaturesToStyle(gfxFontStyle *aStyle) const
nsFont::CopyAlternates(const nsFont& aOther)
{
// simple copy for now, font-variant implementation will expand
aStyle->featureSettings.AppendElements(fontFeatureSettings);
variantAlternates = aOther.variantAlternates;
alternateValues = aOther.alternateValues;
featureValueLookup = aOther.featureValueLookup;
}
static bool IsGenericFontFamily(const nsString& aFamily)
@ -184,6 +225,199 @@ bool nsFont::EnumerateFamilies(nsFontFamilyEnumFunc aFunc, void* aData) const
return true;
}
// mapping from bitflag to font feature tag/value pair
//
// these need to be kept in sync with the constants listed
// in gfxFontConstants.h (e.g. NS_FONT_VARIANT_EAST_ASIAN_JIS78)
// NS_FONT_VARIANT_EAST_ASIAN_xxx values
const gfxFontFeature eastAsianDefaults[] = {
{ TRUETYPE_TAG('j','p','7','8'), 1 },
{ TRUETYPE_TAG('j','p','8','3'), 1 },
{ TRUETYPE_TAG('j','p','9','0'), 1 },
{ TRUETYPE_TAG('j','p','0','4'), 1 },
{ TRUETYPE_TAG('s','m','p','l'), 1 },
{ TRUETYPE_TAG('t','r','a','d'), 1 },
{ TRUETYPE_TAG('f','w','i','d'), 1 },
{ TRUETYPE_TAG('p','w','i','d'), 1 },
{ TRUETYPE_TAG('r','u','b','y'), 1 }
};
PR_STATIC_ASSERT(NS_ARRAY_LENGTH(eastAsianDefaults) ==
eFeatureEastAsian_numFeatures);
// NS_FONT_VARIANT_LIGATURES_xxx values
const gfxFontFeature ligDefaults[] = {
{ TRUETYPE_TAG('l','i','g','a'), 1 },
{ TRUETYPE_TAG('l','i','g','a'), 0 },
{ TRUETYPE_TAG('d','l','i','g'), 1 },
{ TRUETYPE_TAG('d','l','i','g'), 0 },
{ TRUETYPE_TAG('h','l','i','g'), 1 },
{ TRUETYPE_TAG('h','l','i','g'), 0 },
{ TRUETYPE_TAG('c','a','l','t'), 1 },
{ TRUETYPE_TAG('c','a','l','t'), 0 }
};
PR_STATIC_ASSERT(NS_ARRAY_LENGTH(ligDefaults) ==
eFeatureLigatures_numFeatures);
// NS_FONT_VARIANT_NUMERIC_xxx values
const gfxFontFeature numericDefaults[] = {
{ TRUETYPE_TAG('l','n','u','m'), 1 },
{ TRUETYPE_TAG('o','n','u','m'), 1 },
{ TRUETYPE_TAG('p','n','u','m'), 1 },
{ TRUETYPE_TAG('t','n','u','m'), 1 },
{ TRUETYPE_TAG('f','r','a','c'), 1 },
{ TRUETYPE_TAG('a','f','r','c'), 1 },
{ TRUETYPE_TAG('z','e','r','o'), 1 },
{ TRUETYPE_TAG('o','r','d','n'), 1 }
};
PR_STATIC_ASSERT(NS_ARRAY_LENGTH(numericDefaults) ==
eFeatureNumeric_numFeatures);
static void
AddFontFeaturesBitmask(uint32_t aValue, uint32_t aMin, uint32_t aMax,
const gfxFontFeature aFeatureDefaults[],
nsTArray<gfxFontFeature>& aFeaturesOut)
{
uint32_t i, m;
for (i = 0, m = aMin; m <= aMax; i++, m <<= 1) {
if (m & aValue) {
const gfxFontFeature& feature = aFeatureDefaults[i];
aFeaturesOut.AppendElement(feature);
}
}
}
void nsFont::AddFontFeaturesToStyle(gfxFontStyle *aStyle) const
{
// add in font-variant features
gfxFontFeature setting;
// -- kerning
setting.mTag = TRUETYPE_TAG('k','e','r','n');
switch (kerning) {
case NS_FONT_KERNING_NONE:
setting.mValue = 0;
aStyle->featureSettings.AppendElement(setting);
break;
case NS_FONT_KERNING_NORMAL:
setting.mValue = 1;
aStyle->featureSettings.AppendElement(setting);
break;
default:
// auto case implies use user agent default
break;
}
// -- alternates
if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_HISTORICAL) {
setting.mValue = 1;
setting.mTag = TRUETYPE_TAG('h','i','s','t');
aStyle->featureSettings.AppendElement(setting);
}
// -- copy font-specific alternate info into style
// (this will be resolved after font-matching occurs)
aStyle->alternateValues.AppendElements(alternateValues);
aStyle->featureValueLookup = featureValueLookup;
// -- caps
setting.mValue = 1;
switch (variantCaps) {
case NS_FONT_VARIANT_CAPS_ALLSMALL:
setting.mTag = TRUETYPE_TAG('c','2','s','c');
aStyle->featureSettings.AppendElement(setting);
// fall through to the small-caps case
case NS_FONT_VARIANT_CAPS_SMALLCAPS:
setting.mTag = TRUETYPE_TAG('s','m','c','p');
aStyle->featureSettings.AppendElement(setting);
break;
case NS_FONT_VARIANT_CAPS_ALLPETITE:
setting.mTag = TRUETYPE_TAG('c','2','p','c');
aStyle->featureSettings.AppendElement(setting);
// fall through to the petite-caps case
case NS_FONT_VARIANT_CAPS_PETITECAPS:
setting.mTag = TRUETYPE_TAG('p','c','a','p');
aStyle->featureSettings.AppendElement(setting);
break;
case NS_FONT_VARIANT_CAPS_TITLING:
setting.mTag = TRUETYPE_TAG('t','i','t','l');
aStyle->featureSettings.AppendElement(setting);
break;
case NS_FONT_VARIANT_CAPS_UNICASE:
setting.mTag = TRUETYPE_TAG('u','n','i','c');
aStyle->featureSettings.AppendElement(setting);
break;
default:
break;
}
// -- east-asian
if (variantEastAsian) {
AddFontFeaturesBitmask(variantEastAsian,
NS_FONT_VARIANT_EAST_ASIAN_JIS78,
NS_FONT_VARIANT_EAST_ASIAN_RUBY,
eastAsianDefaults, aStyle->featureSettings);
}
// -- ligatures
if (variantLigatures) {
AddFontFeaturesBitmask(variantLigatures,
NS_FONT_VARIANT_LIGATURES_COMMON,
NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL,
ligDefaults, aStyle->featureSettings);
// special case common ligs, which also enable/disable clig
if (variantLigatures & NS_FONT_VARIANT_LIGATURES_COMMON) {
setting.mTag = TRUETYPE_TAG('c','l','i','g');
setting.mValue = 1;
aStyle->featureSettings.AppendElement(setting);
} else if (variantLigatures & NS_FONT_VARIANT_LIGATURES_NO_COMMON) {
setting.mTag = TRUETYPE_TAG('c','l','i','g');
setting.mValue = 0;
aStyle->featureSettings.AppendElement(setting);
}
}
// -- numeric
if (variantNumeric) {
AddFontFeaturesBitmask(variantNumeric,
NS_FONT_VARIANT_NUMERIC_LINING,
NS_FONT_VARIANT_NUMERIC_ORDINAL,
numericDefaults, aStyle->featureSettings);
}
// -- position
setting.mTag = 0;
setting.mValue = 1;
switch (variantPosition) {
case NS_FONT_VARIANT_POSITION_SUPER:
setting.mTag = TRUETYPE_TAG('s','u','p','s');
aStyle->featureSettings.AppendElement(setting);
break;
case NS_FONT_VARIANT_POSITION_SUB:
setting.mTag = TRUETYPE_TAG('s','u','b','s');
aStyle->featureSettings.AppendElement(setting);
break;
default:
break;
}
// add in features from font-feature-settings
aStyle->featureSettings.AppendElements(fontFeatureSettings);
}
static bool FontEnumCallback(const nsString& aFamily, bool aGeneric, void *aData)
{
*((nsString*)aData) = aFamily;

View File

@ -12,6 +12,7 @@
#include "nsTArray.h"
#include "gfxFontConstants.h"
#include "gfxFontFeatures.h"
#include "nsAutoPtr.h"
// XXX we need a method to enumerate all of the possible fonts on the
// system across family, weight, style, size, etc. But not here!
@ -50,6 +51,22 @@ struct NS_GFX nsFont {
// The variant of the font (normal, small-caps)
uint8_t variant;
// Variant subproperties
// (currently -moz- versions, will replace variant above eventually)
uint8_t variantCaps;
uint8_t variantLigatures;
uint8_t variantNumeric;
uint8_t variantPosition;
uint16_t variantEastAsian;
// Some font-variant-alternates property values require
// font-specific settings defined via @font-feature-values rules.
// These are resolved *after* font matching occurs.
// -- bitmask for both enumerated and functional propvals
uint16_t variantAlternates;
// The decorations on the font (underline, overline,
// line-through). The decorations can be binary or'd together.
uint8_t decorations;
@ -70,6 +87,12 @@ struct NS_GFX nsFont {
// needs to be done.
float sizeAdjust;
// -- list of value tags for font-specific alternate features
nsTArray<gfxAlternateValue> alternateValues;
// -- object used to look these up once the font is matched
nsRefPtr<gfxFontFeatureValueSet> featureValueLookup;
// Font features from CSS font-feature-settings
nsTArray<gfxFontFeature> fontFeatureSettings;
@ -78,17 +101,21 @@ struct NS_GFX nsFont {
// (see http://www.microsoft.com/typography/otspec/languagetags.htm).
nsString languageOverride;
// Kerning
uint8_t kerning;
// Synthesis setting, controls use of fake bolding/italics
uint8_t synthesis;
// Initialize the font struct with an ASCII name
nsFont(const char* aName, uint8_t aStyle, uint8_t aVariant,
uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
nscoord aSize, float aSizeAdjust=0.0f,
const nsString* aLanguageOverride = nullptr);
nscoord aSize);
// Initialize the font struct with a (potentially) unicode name
nsFont(const nsString& aName, uint8_t aStyle, uint8_t aVariant,
nsFont(const nsSubstring& aName, uint8_t aStyle, uint8_t aVariant,
uint16_t aWeight, int16_t aStretch, uint8_t aDecoration,
nscoord aSize, float aSizeAdjust=0.0f,
const nsString* aLanguageOverride = nullptr);
nscoord aSize);
// Make a copy of the given font
nsFont(const nsFont& aFont);
@ -106,6 +133,8 @@ struct NS_GFX nsFont {
nsFont& operator=(const nsFont& aOther);
void CopyAlternates(const nsFont& aOther);
// Add featureSettings into style
void AddFontFeaturesToStyle(gfxFontStyle *aStyle) const;

View File

@ -80,7 +80,6 @@ SetupTests()
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
0.0,
false, false, false,
NS_LITERAL_STRING(""),
NS_LITERAL_STRING(""));
gfxFontStyle style_western_bold_16 (FONT_STYLE_NORMAL,
@ -90,7 +89,6 @@ SetupTests()
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
0.0,
false, false, false,
NS_LITERAL_STRING(""),
NS_LITERAL_STRING(""));
/* Test 0 */

View File

@ -66,7 +66,6 @@ RunTest (TestEntry *test, gfxContext *ctx) {
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
0.0,
false, false, false,
NS_LITERAL_STRING(""),
NS_LITERAL_STRING(""));
fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16, nullptr);

View File

@ -124,7 +124,6 @@ main (int argc, char **argv) {
NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
0.0,
false, false, false,
NS_LITERAL_STRING(""),
NS_LITERAL_STRING(""));
nsRefPtr<gfxFontGroup> fontGroup =

View File

@ -34,6 +34,7 @@ CPPSRCS = \
gfxDrawable.cpp \
gfxImageSurface.cpp \
gfxFont.cpp \
gfxFontFeatures.cpp \
gfxFontMissingGlyphs.cpp \
gfxFontTest.cpp \
gfxFontUtils.cpp \

View File

@ -1367,17 +1367,111 @@ gfxFontCache::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
SizeOfExcludingThis(aMallocSizeOf, aSizes);
}
#define MAX_SSXX_VALUE 99
#define MAX_CVXX_VALUE 99
static void
LookupAlternateValues(gfxFontFeatureValueSet *featureLookup,
const nsAString& aFamily,
const nsTArray<gfxAlternateValue>& altValue,
nsTArray<gfxFontFeature>& aFontFeatures)
{
uint32_t numAlternates = altValue.Length();
for (uint32_t i = 0; i < numAlternates; i++) {
const gfxAlternateValue& av = altValue.ElementAt(i);
nsAutoTArray<uint32_t,4> values;
// map <family, name, feature> ==> <values>
bool found =
featureLookup->GetFontFeatureValuesFor(aFamily, av.alternate,
av.value, values);
uint32_t numValues = values.Length();
// nothing defined, skip
if (!found || numValues == 0) {
continue;
}
gfxFontFeature feature;
if (av.alternate == NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT) {
NS_ASSERTION(numValues <= 2,
"too many values allowed for character-variant");
// character-variant(12 3) ==> 'cv12' = 3
uint32_t nn = values.ElementAt(0);
// ignore values greater than 99
if (nn == 0 || nn > MAX_CVXX_VALUE) {
continue;
}
feature.mValue = 1;
if (numValues > 1) {
feature.mValue = values.ElementAt(1);
}
feature.mTag = HB_TAG('c','v',('0' + nn / 10), ('0' + nn % 10));
aFontFeatures.AppendElement(feature);
} else if (av.alternate == NS_FONT_VARIANT_ALTERNATES_STYLESET) {
// styleset(1 2 7) ==> 'ss01' = 1, 'ss02' = 1, 'ss07' = 1
feature.mValue = 1;
for (uint32_t v = 0; v < numValues; v++) {
uint32_t nn = values.ElementAt(v);
if (nn == 0 || nn > MAX_SSXX_VALUE) {
continue;
}
feature.mTag = HB_TAG('s','s',('0' + nn / 10), ('0' + nn % 10));
aFontFeatures.AppendElement(feature);
}
} else {
NS_ASSERTION(numValues == 1,
"too many values for font-specific font-variant-alternates");
feature.mValue = values.ElementAt(0);
switch (av.alternate) {
case NS_FONT_VARIANT_ALTERNATES_STYLISTIC: // salt
feature.mTag = HB_TAG('s','a','l','t');
break;
case NS_FONT_VARIANT_ALTERNATES_SWASH: // swsh, cswh
feature.mTag = HB_TAG('s','w','s','h');
aFontFeatures.AppendElement(feature);
feature.mTag = HB_TAG('c','s','w','h');
break;
case NS_FONT_VARIANT_ALTERNATES_ORNAMENTS: // ornm
feature.mTag = HB_TAG('o','r','n','m');
break;
case NS_FONT_VARIANT_ALTERNATES_ANNOTATION: // nalt
feature.mTag = HB_TAG('n','a','l','t');
break;
default:
feature.mTag = 0;
break;
}
NS_ASSERTION(feature.mTag, "unsupported alternate type");
if (!feature.mTag) {
continue;
}
aFontFeatures.AppendElement(feature);
}
}
}
/* static */ bool
gfxFontShaper::MergeFontFeatures(
const nsTArray<gfxFontFeature>& aStyleRuleFeatures,
const gfxFontStyle *aStyle,
const nsTArray<gfxFontFeature>& aFontFeatures,
bool aDisableLigatures,
const nsAString& aFamilyName,
nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures)
{
uint32_t numAlts = aStyle->alternateValues.Length();
const nsTArray<gfxFontFeature>& styleRuleFeatures =
aStyle->featureSettings;
// bail immediately if nothing to do
if (aStyleRuleFeatures.IsEmpty() &&
if (styleRuleFeatures.IsEmpty() &&
aFontFeatures.IsEmpty() &&
!aDisableLigatures) {
!aDisableLigatures &&
numAlts == 0) {
return false;
}
@ -1399,10 +1493,25 @@ gfxFontShaper::MergeFontFeatures(
aMergedFeatures.Put(feature.mTag, feature.mValue);
}
// add font-specific feature values from style rules
if (aStyle->featureValueLookup && numAlts > 0) {
nsAutoTArray<gfxFontFeature,4> featureList;
// insert list of alternate feature settings
LookupAlternateValues(aStyle->featureValueLookup, aFamilyName,
aStyle->alternateValues, featureList);
count = featureList.Length();
for (i = 0; i < count; i++) {
const gfxFontFeature& feature = featureList.ElementAt(i);
aMergedFeatures.Put(feature.mTag, feature.mValue);
}
}
// add feature values from style rules
count = aStyleRuleFeatures.Length();
count = styleRuleFeatures.Length();
for (i = 0; i < count; i++) {
const gfxFontFeature& feature = aStyleRuleFeatures.ElementAt(i);
const gfxFontFeature& feature = styleRuleFeatures.ElementAt(i);
aMergedFeatures.Put(feature.mTag, feature.mValue);
}
@ -4791,6 +4900,7 @@ gfxFontStyle::gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
gfxFontStyle::gfxFontStyle(const gfxFontStyle& aStyle) :
language(aStyle.language),
featureValueLookup(aStyle.featureValueLookup),
size(aStyle.size), sizeAdjust(aStyle.sizeAdjust),
languageOverride(aStyle.languageOverride),
weight(aStyle.weight), stretch(aStyle.stretch),
@ -4798,6 +4908,7 @@ gfxFontStyle::gfxFontStyle(const gfxFontStyle& aStyle) :
style(aStyle.style)
{
featureSettings.AppendElements(aStyle.featureSettings);
alternateValues.AppendElements(aStyle.alternateValues);
}
int8_t

View File

@ -73,9 +73,23 @@ struct THEBES_API gfxFontStyle {
// or inferred from the charset
nsRefPtr<nsIAtom> language;
// Features are composed of (1) features from style rules (2) features
// from feature setttings rules and (3) family-specific features. (1) and
// (3) are guaranteed to be mutually exclusive
// custom opentype feature settings
nsTArray<gfxFontFeature> featureSettings;
// Some font-variant property values require font-specific settings
// defined via @font-feature-values rules. These are resolved after
// font matching occurs.
// -- list of value tags for specific alternate features
nsTArray<gfxAlternateValue> alternateValues;
// -- object used to look these up once the font is matched
nsRefPtr<gfxFontFeatureValueSet> featureValueLookup;
// The logical size of the font, in pixels
gfxFloat size;
@ -144,7 +158,9 @@ struct THEBES_API gfxFontStyle {
(*reinterpret_cast<const uint32_t*>(&sizeAdjust) ==
*reinterpret_cast<const uint32_t*>(&other.sizeAdjust)) &&
(featureSettings == other.featureSettings) &&
(languageOverride == other.languageOverride);
(languageOverride == other.languageOverride) &&
(alternateValues == other.alternateValues) &&
(featureValueLookup == other.featureValueLookup);
}
static void ParseFontFeatureSettings(const nsString& aFeatureString,
@ -1147,9 +1163,10 @@ public:
// returns true if features exist in output, false otherwise
static bool
MergeFontFeatures(const nsTArray<gfxFontFeature>& aStyleRuleFeatures,
MergeFontFeatures(const gfxFontStyle *aStyle,
const nsTArray<gfxFontFeature>& aFontFeatures,
bool aDisableLigatures,
const nsAString& aFamilyName,
nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures);
protected:
@ -1580,6 +1597,10 @@ public:
virtual mozilla::TemporaryRef<mozilla::gfx::ScaledFont> GetScaledFont(mozilla::gfx::DrawTarget *aTarget)
{ return gfxPlatform::GetPlatform()->GetScaledFontForFont(aTarget, this); }
bool KerningDisabled() {
return mKerningSet && !mKerningEnabled;
}
protected:
bool HasSubstitutionRulesWithSpaceLookups(int32_t aRunScript) {

View File

@ -30,4 +30,165 @@
#define NS_FONT_STRETCH_EXTRA_EXPANDED 3
#define NS_FONT_STRETCH_ULTRA_EXPANDED 4
#define NS_FONT_KERNING_AUTO 0
#define NS_FONT_KERNING_NONE 1
#define NS_FONT_KERNING_NORMAL 2
#define NS_FONT_SYNTHESIS_WEIGHT 0x1
#define NS_FONT_SYNTHESIS_STYLE 0x2
enum {
eFeatureAlternates_historical,
eFeatureAlternates_stylistic,
eFeatureAlternates_styleset,
eFeatureAlternates_character_variant,
eFeatureAlternates_swash,
eFeatureAlternates_ornaments,
eFeatureAlternates_annotation,
eFeatureAlternates_numFeatures
};
// alternates - simple enumerated values
#define NS_FONT_VARIANT_ALTERNATES_HISTORICAL (1 << eFeatureAlternates_historical)
// alternates - values that use functional syntax
#define NS_FONT_VARIANT_ALTERNATES_STYLISTIC (1 << eFeatureAlternates_stylistic)
#define NS_FONT_VARIANT_ALTERNATES_STYLESET (1 << eFeatureAlternates_styleset)
#define NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT (1 << eFeatureAlternates_character_variant)
#define NS_FONT_VARIANT_ALTERNATES_SWASH (1 << eFeatureAlternates_swash)
#define NS_FONT_VARIANT_ALTERNATES_ORNAMENTS (1 << eFeatureAlternates_ornaments)
#define NS_FONT_VARIANT_ALTERNATES_ANNOTATION (1 << eFeatureAlternates_annotation)
#define NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK \
NS_FONT_VARIANT_ALTERNATES_HISTORICAL
#define NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK ( \
NS_FONT_VARIANT_ALTERNATES_STYLISTIC | \
NS_FONT_VARIANT_ALTERNATES_STYLESET | \
NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT | \
NS_FONT_VARIANT_ALTERNATES_SWASH | \
NS_FONT_VARIANT_ALTERNATES_ORNAMENTS | \
NS_FONT_VARIANT_ALTERNATES_ANNOTATION )
#define NS_FONT_VARIANT_CAPS_NORMAL 0
#define NS_FONT_VARIANT_CAPS_SMALLCAPS 1
#define NS_FONT_VARIANT_CAPS_ALLSMALL 2
#define NS_FONT_VARIANT_CAPS_PETITECAPS 3
#define NS_FONT_VARIANT_CAPS_ALLPETITE 4
#define NS_FONT_VARIANT_CAPS_TITLING 5
#define NS_FONT_VARIANT_CAPS_UNICASE 6
enum {
eFeatureEastAsian_jis78,
eFeatureEastAsian_jis83,
eFeatureEastAsian_jis90,
eFeatureEastAsian_jis04,
eFeatureEastAsian_simplified,
eFeatureEastAsian_traditional,
eFeatureEastAsian_full_width,
eFeatureEastAsian_prop_width,
eFeatureEastAsian_ruby,
eFeatureEastAsian_numFeatures
};
#define NS_FONT_VARIANT_EAST_ASIAN_JIS78 (1 << eFeatureEastAsian_jis78)
#define NS_FONT_VARIANT_EAST_ASIAN_JIS83 (1 << eFeatureEastAsian_jis83)
#define NS_FONT_VARIANT_EAST_ASIAN_JIS90 (1 << eFeatureEastAsian_jis90)
#define NS_FONT_VARIANT_EAST_ASIAN_JIS04 (1 << eFeatureEastAsian_jis04)
#define NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED (1 << eFeatureEastAsian_simplified)
#define NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL (1 << eFeatureEastAsian_traditional)
#define NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH (1 << eFeatureEastAsian_full_width)
#define NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH (1 << eFeatureEastAsian_prop_width)
#define NS_FONT_VARIANT_EAST_ASIAN_RUBY (1 << eFeatureEastAsian_ruby)
#define NS_FONT_VARIANT_EAST_ASIAN_VARIANT_MASK ( \
NS_FONT_VARIANT_EAST_ASIAN_JIS78 | \
NS_FONT_VARIANT_EAST_ASIAN_JIS83 | \
NS_FONT_VARIANT_EAST_ASIAN_JIS90 | \
NS_FONT_VARIANT_EAST_ASIAN_JIS04 | \
NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED | \
NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL )
#define NS_FONT_VARIANT_EAST_ASIAN_WIDTH_MASK ( \
NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH | \
NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH )
enum {
eFeatureLigatures_common,
eFeatureLigatures_no_common,
eFeatureLigatures_discretionary,
eFeatureLigatures_no_discretionary,
eFeatureLigatures_historical,
eFeatureLigatures_no_historical,
eFeatureLigatures_contextual,
eFeatureLigatures_no_contextual,
eFeatureLigatures_numFeatures
};
#define NS_FONT_VARIANT_LIGATURES_COMMON (1 << eFeatureLigatures_common)
#define NS_FONT_VARIANT_LIGATURES_NO_COMMON (1 << eFeatureLigatures_no_common)
#define NS_FONT_VARIANT_LIGATURES_DISCRETIONARY (1 << eFeatureLigatures_discretionary)
#define NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY (1 << eFeatureLigatures_no_discretionary)
#define NS_FONT_VARIANT_LIGATURES_HISTORICAL (1 << eFeatureLigatures_historical)
#define NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL (1 << eFeatureLigatures_no_historical)
#define NS_FONT_VARIANT_LIGATURES_CONTEXTUAL (1 << eFeatureLigatures_contextual)
#define NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL (1 << eFeatureLigatures_no_contextual)
#define NS_FONT_VARIANT_LIGATURES_COMMON_MASK ( \
NS_FONT_VARIANT_LIGATURES_COMMON | \
NS_FONT_VARIANT_LIGATURES_NO_COMMON )
#define NS_FONT_VARIANT_LIGATURES_DISCRETIONARY_MASK ( \
NS_FONT_VARIANT_LIGATURES_DISCRETIONARY | \
NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY )
#define NS_FONT_VARIANT_LIGATURES_HISTORICAL_MASK ( \
NS_FONT_VARIANT_LIGATURES_HISTORICAL | \
NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL )
#define NS_FONT_VARIANT_LIGATURES_CONTEXTUAL_MASK \
NS_FONT_VARIANT_LIGATURES_CONTEXTUAL | \
NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL
enum {
eFeatureNumeric_lining,
eFeatureNumeric_oldstyle,
eFeatureNumeric_proportional,
eFeatureNumeric_tabular,
eFeatureNumeric_diagonal_fractions,
eFeatureNumeric_stacked_fractions,
eFeatureNumeric_slashedzero,
eFeatureNumeric_ordinal,
eFeatureNumeric_numFeatures
};
#define NS_FONT_VARIANT_NUMERIC_LINING (1 << eFeatureNumeric_lining)
#define NS_FONT_VARIANT_NUMERIC_OLDSTYLE (1 << eFeatureNumeric_oldstyle)
#define NS_FONT_VARIANT_NUMERIC_PROPORTIONAL (1 << eFeatureNumeric_proportional)
#define NS_FONT_VARIANT_NUMERIC_TABULAR (1 << eFeatureNumeric_tabular)
#define NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS (1 << eFeatureNumeric_diagonal_fractions)
#define NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS (1 << eFeatureNumeric_stacked_fractions)
#define NS_FONT_VARIANT_NUMERIC_SLASHZERO (1 << eFeatureNumeric_slashedzero)
#define NS_FONT_VARIANT_NUMERIC_ORDINAL (1 << eFeatureNumeric_ordinal)
#define NS_FONT_VARIANT_NUMERIC_FIGURE_MASK \
NS_FONT_VARIANT_NUMERIC_LINING | \
NS_FONT_VARIANT_NUMERIC_OLDSTYLE
#define NS_FONT_VARIANT_NUMERIC_SPACING_MASK \
NS_FONT_VARIANT_NUMERIC_PROPORTIONAL | \
NS_FONT_VARIANT_NUMERIC_TABULAR
#define NS_FONT_VARIANT_NUMERIC_FRACTION_MASK \
NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS | \
NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS
#define NS_FONT_VARIANT_POSITION_NORMAL 0
#define NS_FONT_VARIANT_POSITION_SUPER 1
#define NS_FONT_VARIANT_POSITION_SUB 2
#endif

View File

@ -7,6 +7,11 @@
#ifndef GFX_FONT_FEATURES_H
#define GFX_FONT_FEATURES_H
#include "gfxTypes.h"
#include "nsTHashtable.h"
#include "nsTArray.h"
#include "nsString.h"
// An OpenType feature tag and value pair
struct gfxFontFeature {
uint32_t mTag; // see http://www.microsoft.com/typography/otspec/featuretags.htm
@ -26,4 +31,95 @@ operator==(const gfxFontFeature& a, const gfxFontFeature& b)
return (a.mTag == b.mTag) && (a.mValue == b.mValue);
}
struct gfxAlternateValue {
uint32_t alternate; // constants in gfxFontConstants.h
nsString value; // string value to be looked up
};
inline bool
operator<(const gfxAlternateValue& a, const gfxAlternateValue& b)
{
return (a.alternate < b.alternate) ||
((a.alternate == b.alternate) && (a.value < b.value));
}
inline bool
operator==(const gfxAlternateValue& a, const gfxAlternateValue& b)
{
return (a.alternate == b.alternate) && (a.value == b.value);
}
class THEBES_API gfxFontFeatureValueSet {
public:
NS_INLINE_DECL_REFCOUNTING(gfxFontFeatureValueSet)
gfxFontFeatureValueSet();
virtual ~gfxFontFeatureValueSet() {}
struct ValueList {
ValueList(const nsAString& aName, const nsTArray<uint32_t>& aSelectors)
: name(aName), featureSelectors(aSelectors)
{}
nsString name;
nsTArray<uint32_t> featureSelectors;
};
struct FeatureValues {
uint32_t alternate;
nsTArray<ValueList> valuelist;
};
// returns true if found, false otherwise
bool
GetFontFeatureValuesFor(const nsAString& aFamily,
uint32_t aVariantProperty,
const nsAString& aName,
nsTArray<uint32_t>& aValues);
void
AddFontFeatureValues(const nsAString& aFamily,
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aValues);
protected:
struct FeatureValueHashKey {
nsString mFamily;
uint32_t mPropVal;
nsString mName;
FeatureValueHashKey()
: mPropVal(0)
{ }
FeatureValueHashKey(const nsAString& aFamily,
uint32_t aPropVal,
const nsAString& aName)
: mFamily(aFamily), mPropVal(aPropVal), mName(aName)
{ }
FeatureValueHashKey(const FeatureValueHashKey& aKey)
: mFamily(aKey.mFamily), mPropVal(aKey.mPropVal), mName(aKey.mName)
{ }
};
class FeatureValueHashEntry : public PLDHashEntryHdr {
public:
typedef const FeatureValueHashKey &KeyType;
typedef const FeatureValueHashKey *KeyTypePointer;
FeatureValueHashEntry(KeyTypePointer aKey) { }
FeatureValueHashEntry(const FeatureValueHashEntry& toCopy)
{
NS_ERROR("Should not be called");
}
~FeatureValueHashEntry() { }
bool KeyEquals(const KeyTypePointer aKey) const;
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
static PLDHashNumber HashKey(const KeyTypePointer aKey);
enum { ALLOW_MEMMOVE = true };
FeatureValueHashKey mKey;
nsTArray<uint32_t> mValues;
};
nsTHashtable<FeatureValueHashEntry> mFontFeatureValues;
};
#endif

View File

@ -192,8 +192,13 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
if (MergeFontFeatures(style->featureSettings, entry->mFeatureSettings,
aShapedText->DisableLigatures(), mergedFeatures)) {
// if style contains font-specific features
if (MergeFontFeatures(style,
mFont->GetFontEntry()->mFeatureSettings,
aShapedText->DisableLigatures(),
mFont->GetFontEntry()->FamilyName(),
mergedFeatures))
{
// enumerate result and insert into Graphite feature list
GrFontFeatures f = {mGrFace, grFeatures};
mergedFeatures.Enumerate(AddFeature, &f);

View File

@ -99,12 +99,14 @@ HBGetTable(hb_face_t *face, hb_tag_t aTag, void *aUserData)
*/
struct FontCallbackData {
FontCallbackData(gfxHarfBuzzShaper *aShaper, gfxContext *aContext)
: mShaper(aShaper), mContext(aContext)
FontCallbackData(gfxHarfBuzzShaper *aShaper, gfxContext *aContext,
bool aKerning)
: mShaper(aShaper), mContext(aContext), mKerning(aKerning)
{ }
gfxHarfBuzzShaper *mShaper;
gfxContext *mContext;
bool mKerning;
};
#define UNICODE_BMP_LIMIT 0x10000
@ -644,7 +646,13 @@ HBGetHKerning(hb_font_t *font, void *font_data,
{
const FontCallbackData *fcd =
static_cast<const FontCallbackData*>(font_data);
return fcd->mShaper->GetHKerning(first_glyph, second_glyph);
// return 0 if kerning is explicitly disabled
if (fcd->mKerning) {
return fcd->mShaper->GetHKerning(first_glyph, second_glyph);
} else {
return 0.0;
}
}
/*
@ -956,7 +964,9 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
return false;
}
FontCallbackData fcd(this, aContext);
const gfxFontStyle *style = mFont->GetStyle();
// kerning is enabled *except* when explicitly disabled (font-kerning: none)
FontCallbackData fcd(this, aContext, !mFont->KerningDisabled());
hb_font_t *font = hb_font_create(mHBFace);
hb_font_set_funcs(font, sHBFontFuncs, &fcd, nullptr);
hb_font_set_ppem(font, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
@ -966,13 +976,15 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
nsAutoTArray<hb_feature_t,20> features;
gfxFontEntry *entry = mFont->GetFontEntry();
const gfxFontStyle *style = mFont->GetStyle();
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
if (MergeFontFeatures(style->featureSettings,
mFont->GetFontEntry()->mFeatureSettings,
aShapedText->DisableLigatures(), mergedFeatures)) {
if (MergeFontFeatures(style,
mFont->GetFontEntry()->mFeatureSettings,
aShapedText->DisableLigatures(),
mFont->GetFontEntry()->FamilyName(),
mergedFeatures))
{
// enumerate result and insert into hb_feature array
mergedFeatures.Enumerate(AddFeature, &features);
}

View File

@ -51,6 +51,38 @@ skip-if(B2G) HTTP(..) == font-features-turkish-override-5.html font-features-tur
HTTP(..) == font-features-order-1.html font-features-ref.html
HTTP(..) == font-features-order-2.html font-features-noliga.html
# check priority of feature settings vs. font-variant subproperty
HTTP(..) == font-features-order-3.html font-features-noliga.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-features-order-4.html font-features-noliga.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-features-order-5.html font-features-hlig.html
# check priority involving feature settings and font-variant-alternates
pref(layout.css.font-features.enabled,true) HTTP(..) == alternates-order.html alternates-order-ref.html
# check that font-specific values line up with @font-face feature settings
pref(layout.css.font-features.enabled,true) HTTP(..) == annotations.html annotations-ref.html
# font-variant subproperties
# test for specific features being on and others off, based on prop values
# (debug problems with font-variant-debug.html which displays all props)
pref(layout.css.font-features.enabled,true) HTTP(..) == font-variant-alternates.html font-variant-alternates-ref.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-variant-caps.html font-variant-caps-ref.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-variant-east-asian.html font-variant-east-asian-ref.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-variant-ligatures.html font-variant-ligatures-ref.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-variant-numeric.html font-variant-numeric-ref.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-variant-position.html font-variant-position-ref.html
# font-kerning
pref(layout.css.font-features.enabled,true) HTTP(..) != font-kerning-normal.html font-kerning-none.html
pref(layout.css.font-features.enabled,true) HTTP(..) != font-kerning-auto.html font-kerning-none.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-kerning-auto.html font-kerning-normal.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-kerning-normal.html font-kerning-kern.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-kerning-none.html font-kerning-nokern.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-kerning-1.html font-kerning-none.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-kerning-2.html font-kerning-normal.html
pref(layout.css.font-features.enabled,true) HTTP(..) == font-kerning-3.html font-kerning-none.html
pref(layout.css.font-features.enabled,true) HTTP(..) != font-kerning-table-none.html font-kerning-table-normal.html
# sanity check for kerning - with no spaces, kerning should occur
HTTP(..) == kerning-sanity-check-kern.html kerning-sanity-check-default.html
HTTP(..) != kerning-sanity-check-nokern.html kerning-sanity-check-default.html

View File

@ -537,6 +537,22 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
*data->ValueFor(eCSSProperty_font_feature_settings);
const nsCSSValue &languageOverride =
*data->ValueFor(eCSSProperty_font_language_override);
const nsCSSValue &fontKerning =
*data->ValueFor(eCSSProperty_font_kerning);
const nsCSSValue &fontSynthesis =
*data->ValueFor(eCSSProperty_font_synthesis);
const nsCSSValue &fontVariantAlternates =
*data->ValueFor(eCSSProperty_font_variant_alternates);
const nsCSSValue &fontVariantCaps =
*data->ValueFor(eCSSProperty_font_variant_caps);
const nsCSSValue &fontVariantEastAsian =
*data->ValueFor(eCSSProperty_font_variant_east_asian);
const nsCSSValue &fontVariantLigatures =
*data->ValueFor(eCSSProperty_font_variant_ligatures);
const nsCSSValue &fontVariantNumeric =
*data->ValueFor(eCSSProperty_font_variant_numeric);
const nsCSSValue &fontVariantPosition =
*data->ValueFor(eCSSProperty_font_variant_position);
if (systemFont &&
systemFont->GetUnit() != eCSSUnit_None &&
@ -550,21 +566,39 @@ Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
stretch.GetUnit() != eCSSUnit_System_Font ||
sizeAdjust.GetUnit() != eCSSUnit_System_Font ||
featureSettings.GetUnit() != eCSSUnit_System_Font ||
languageOverride.GetUnit() != eCSSUnit_System_Font) {
languageOverride.GetUnit() != eCSSUnit_System_Font ||
fontKerning.GetUnit() != eCSSUnit_System_Font ||
fontSynthesis.GetUnit() != eCSSUnit_System_Font ||
fontVariantAlternates.GetUnit() != eCSSUnit_System_Font ||
fontVariantCaps.GetUnit() != eCSSUnit_System_Font ||
fontVariantEastAsian.GetUnit() != eCSSUnit_System_Font ||
fontVariantLigatures.GetUnit() != eCSSUnit_System_Font ||
fontVariantNumeric.GetUnit() != eCSSUnit_System_Font ||
fontVariantPosition.GetUnit() != eCSSUnit_System_Font) {
// This can't be represented as a shorthand.
return;
}
systemFont->AppendToString(eCSSProperty__x_system_font, aValue);
} else {
// The font-stretch, font-size-adjust,
// -moz-font-feature-settings, and -moz-font-language-override
// properties are reset by this shorthand property to their
// -moz-font-feature-settings, -moz-font-language-override
// along with kerning, synthesis and other font-variant
// subproperties are reset by this shorthand property to their
// initial values, but can't be represented in its syntax.
if (stretch.GetUnit() != eCSSUnit_Enumerated ||
stretch.GetIntValue() != NS_STYLE_FONT_STRETCH_NORMAL ||
sizeAdjust.GetUnit() != eCSSUnit_None ||
featureSettings.GetUnit() != eCSSUnit_Normal ||
languageOverride.GetUnit() != eCSSUnit_Normal) {
languageOverride.GetUnit() != eCSSUnit_Normal ||
fontKerning.GetIntValue() != NS_FONT_KERNING_AUTO ||
fontSynthesis.GetIntValue() !=
(NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE) ||
fontVariantAlternates.GetUnit() != eCSSUnit_Normal ||
fontVariantCaps.GetUnit() != eCSSUnit_Normal ||
fontVariantEastAsian.GetUnit() != eCSSUnit_Normal ||
fontVariantLigatures.GetUnit() != eCSSUnit_Normal ||
fontVariantNumeric.GetUnit() != eCSSUnit_Normal ||
fontVariantPosition.GetUnit() != eCSSUnit_Normal) {
return;
}

View File

@ -65,7 +65,8 @@ public:
KEYFRAME_RULE,
KEYFRAMES_RULE,
DOCUMENT_RULE,
SUPPORTS_RULE
SUPPORTS_RULE,
FONT_FEATURE_VALUES_RULE
};
virtual int32_t GetType() const = 0;

View File

@ -9,5 +9,8 @@ CSS_FONT_DESC(font-weight, Weight)
CSS_FONT_DESC(font-stretch, Stretch)
CSS_FONT_DESC(src, Src)
CSS_FONT_DESC(unicode-range, UnicodeRange)
/* Note: the parsing code explicitly also accepts font-feature-settings
and font-language-override. */
CSS_FONT_DESC(-moz-font-feature-settings, FontFeatureSettings)
CSS_FONT_DESC(-moz-font-language-override, FontLanguageOverride)

View File

@ -163,11 +163,14 @@ CSS_KEY(activeborder, activeborder)
CSS_KEY(activecaption, activecaption)
CSS_KEY(alias, alias)
CSS_KEY(all, all)
CSS_KEY(all-petite-caps, all_petite_caps)
CSS_KEY(all-scroll, all_scroll)
CSS_KEY(all-small-caps, all_small_caps)
CSS_KEY(alpha, alpha)
CSS_KEY(alternate, alternate)
CSS_KEY(alternate-reverse, alternate_reverse)
CSS_KEY(always, always)
CSS_KEY(annotation, annotation)
CSS_KEY(appworkspace, appworkspace)
CSS_KEY(armenian, armenian)
CSS_KEY(auto, auto)
@ -200,6 +203,7 @@ CSS_KEY(captiontext, captiontext)
CSS_KEY(cell, cell)
CSS_KEY(center, center)
CSS_KEY(ch, ch)
CSS_KEY(character-variant, character_variant)
CSS_KEY(circle, circle)
CSS_KEY(cjk-ideographic, cjk_ideographic)
CSS_KEY(clip, clip)
@ -209,6 +213,7 @@ CSS_KEY(closest-side, closest_side)
CSS_KEY(cm, cm)
CSS_KEY(col-resize, col_resize)
CSS_KEY(collapse, collapse)
CSS_KEY(common-ligatures, common_ligatures)
CSS_KEY(column, column)
CSS_KEY(column-reverse, column_reverse)
CSS_KEY(condensed, condensed)
@ -217,6 +222,7 @@ CSS_KEY(content-box, content_box)
CSS_KEY(context-menu, context_menu)
CSS_KEY(continuous, continuous)
CSS_KEY(copy, copy)
CSS_KEY(contextual, contextual)
CSS_KEY(cover, cover)
CSS_KEY(crop, crop)
CSS_KEY(cross, cross)
@ -227,9 +233,11 @@ CSS_KEY(decimal, decimal)
CSS_KEY(decimal-leading-zero, decimal_leading_zero)
CSS_KEY(default, default)
CSS_KEY(deg, deg)
CSS_KEY(diagonal-fractions, diagonal_fractions)
CSS_KEY(dialog, dialog)
CSS_KEY(disabled, disabled)
CSS_KEY(disc, disc)
CSS_KEY(discretionary-ligatures, discretionary_ligatures)
CSS_KEY(dotted, dotted)
CSS_KEY(double, double)
CSS_KEY(e-resize, e_resize)
@ -273,6 +281,8 @@ CSS_KEY(highlight, highlight)
CSS_KEY(highlighttext, highlighttext)
CSS_KEY(hiragana, hiragana)
CSS_KEY(hiragana-iroha, hiragana_iroha)
CSS_KEY(historical-forms, historical_forms)
CSS_KEY(historical-ligatures, historical_ligatures)
CSS_KEY(horizontal, horizontal)
CSS_KEY(hz, hz)
CSS_KEY(icon, icon)
@ -297,6 +307,10 @@ CSS_KEY(inset, inset)
CSS_KEY(inside, inside)
CSS_KEY(interpolatematrix, interpolatematrix)
CSS_KEY(italic, italic)
CSS_KEY(jis78, jis78)
CSS_KEY(jis83, jis83)
CSS_KEY(jis90, jis90)
CSS_KEY(jis04, jis04)
CSS_KEY(justify, justify)
CSS_KEY(katakana, katakana)
CSS_KEY(katakana-iroha, katakana_iroha)
@ -309,6 +323,7 @@ CSS_KEY(left, left)
CSS_KEY(lighter, lighter)
CSS_KEY(line-through, line_through)
CSS_KEY(linear, linear)
CSS_KEY(lining-nums, lining_nums)
CSS_KEY(list-item, list_item)
CSS_KEY(logical, logical)
CSS_KEY(lower-alpha, lower_alpha)
@ -337,7 +352,11 @@ CSS_KEY(narrower, narrower)
CSS_KEY(ne-resize, ne_resize)
CSS_KEY(nesw-resize, nesw_resize)
CSS_KEY(no-close-quote, no_close_quote)
CSS_KEY(no-common-ligatures, no_common_ligatures)
CSS_KEY(no-contextual, no_contextual)
CSS_KEY(no-discretionary-ligatures, no_discretionary_ligatures)
CSS_KEY(no-drop, no_drop)
CSS_KEY(no-historical-ligatures, no_historical_ligatures)
CSS_KEY(no-open-quote, no_open_quote)
CSS_KEY(no-repeat, no_repeat)
CSS_KEY(none, none)
@ -348,7 +367,10 @@ CSS_KEY(ns-resize, ns_resize)
CSS_KEY(nw-resize, nw_resize)
CSS_KEY(nwse-resize, nwse_resize)
CSS_KEY(oblique, oblique)
CSS_KEY(oldstyle-nums, oldstyle_nums)
CSS_KEY(open-quote, open_quote)
CSS_KEY(ordinal, ordinal)
CSS_KEY(ornaments, ornaments)
CSS_KEY(outset, outset)
CSS_KEY(outside, outside)
CSS_KEY(overline, overline)
@ -357,6 +379,7 @@ CSS_KEY(painted, painted)
CSS_KEY(paused, paused)
CSS_KEY(pc, pc)
CSS_KEY(perspective, perspective)
CSS_KEY(petite-caps, petite_caps)
CSS_KEY(physical, physical)
CSS_KEY(pointer, pointer)
CSS_KEY(portrait, portrait)
@ -366,6 +389,8 @@ CSS_KEY(pre-line, pre_line)
CSS_KEY(preserve-3d, preserve_3d)
CSS_KEY(progress, progress)
CSS_KEY(progressive, progressive)
CSS_KEY(proportional-nums, proportional_nums)
CSS_KEY(proportional-width, proportional_width)
CSS_KEY(pt, pt)
CSS_KEY(px, px)
CSS_KEY(rad, rad)
@ -388,6 +413,7 @@ CSS_KEY(row, row)
CSS_KEY(row-resize, row_resize)
CSS_KEY(row-reverse, row_reverse)
CSS_KEY(rtl, rtl)
CSS_KEY(ruby, ruby)
CSS_KEY(running, running)
CSS_KEY(s, s)
CSS_KEY(s-resize, s_resize)
@ -409,9 +435,11 @@ CSS_KEY(semi-condensed, semi_condensed)
CSS_KEY(semi-expanded, semi_expanded)
CSS_KEY(separate, separate)
CSS_KEY(show, show)
CSS_KEY(simplified, simplified)
CSS_KEY(skew, skew)
CSS_KEY(skewx, skewx)
CSS_KEY(skewy, skewy)
CSS_KEY(slashed-zero, slashed_zero)
CSS_KEY(small, small)
CSS_KEY(small-caps, small_caps)
CSS_KEY(small-caption, small_caption)
@ -421,6 +449,7 @@ CSS_KEY(solid, solid)
CSS_KEY(space-around, space_around)
CSS_KEY(space-between, space_between)
CSS_KEY(square, square)
CSS_KEY(stacked-fractions, stacked_fractions)
CSS_KEY(start, start)
CSS_KEY(static, static)
CSS_KEY(status-bar, status_bar)
@ -429,9 +458,13 @@ CSS_KEY(step-start, step_start)
CSS_KEY(stretch, stretch)
CSS_KEY(stretch-to-fit, stretch_to_fit)
CSS_KEY(stroke, stroke)
CSS_KEY(style, style)
CSS_KEY(styleset, styleset)
CSS_KEY(stylistic, stylistic)
CSS_KEY(sub, sub)
CSS_KEY(super, super)
CSS_KEY(sw-resize, sw_resize)
CSS_KEY(swash, swash)
CSS_KEY(table, table)
CSS_KEY(table-caption, table_caption)
CSS_KEY(table-cell, table_cell)
@ -441,6 +474,7 @@ CSS_KEY(table-footer-group, table_footer_group)
CSS_KEY(table-header-group, table_header_group)
CSS_KEY(table-row, table_row)
CSS_KEY(table-row-group, table_row_group)
CSS_KEY(tabular-nums, tabular_nums)
CSS_KEY(text, text)
CSS_KEY(text-bottom, text_bottom)
CSS_KEY(text-top, text_top)
@ -451,9 +485,11 @@ CSS_KEY(threedface, threedface)
CSS_KEY(threedhighlight, threedhighlight)
CSS_KEY(threedlightshadow, threedlightshadow)
CSS_KEY(threedshadow, threedshadow)
CSS_KEY(titling-caps, titling_caps)
CSS_KEY(toggle, toggle)
CSS_KEY(top, top)
CSS_KEY(top-outside, top_outside)
CSS_KEY(traditional, traditional)
CSS_KEY(translate, translate)
CSS_KEY(translate3d, translate3d)
CSS_KEY(translatex, translatex)
@ -464,6 +500,7 @@ CSS_KEY(tri-state, tri_state)
CSS_KEY(ultra-condensed, ultra_condensed)
CSS_KEY(ultra-expanded, ultra_expanded)
CSS_KEY(underline, underline)
CSS_KEY(unicase, unicase)
CSS_KEY(upper-alpha, upper_alpha)
CSS_KEY(upper-latin, upper_latin)
CSS_KEY(upper-roman, upper_roman)
@ -477,6 +514,7 @@ CSS_KEY(visiblestroke, visiblestroke)
CSS_KEY(w-resize, w_resize)
CSS_KEY(wait, wait)
CSS_KEY(wavy, wavy)
CSS_KEY(weight, weight)
CSS_KEY(wider, wider)
CSS_KEY(window, window)
CSS_KEY(windowframe, windowframe)

View File

@ -375,6 +375,9 @@ protected:
void* aProcessData);
bool ParseFontFaceRule(RuleAppendFunc aAppendFunc, void* aProcessData);
bool ParseFontFeatureValuesRule(RuleAppendFunc aAppendFunc,
void* aProcessData);
bool ParseFontFeatureValueSet(nsCSSFontFeatureValuesRule *aRule);
bool ParseFontDescriptor(nsCSSFontFaceRule* aRule);
bool ParseFontDescriptorValue(nsCSSFontDesc aDescID,
nsCSSValue& aValue);
@ -562,6 +565,14 @@ protected:
bool ParseCounterData(nsCSSProperty aPropID);
bool ParseCursor();
bool ParseFont();
bool ParseFontSynthesis(nsCSSValue& aValue);
bool ParseSingleAlternate(int32_t& aWhichFeature, nsCSSValue& aValue);
bool ParseFontVariantAlternates(nsCSSValue& aValue);
bool ParseBitmaskValues(nsCSSValue& aValue, const int32_t aKeywordTable[],
const int32_t aMasks[]);
bool ParseFontVariantEastAsian(nsCSSValue& aValue);
bool ParseFontVariantLigatures(nsCSSValue& aValue);
bool ParseFontVariantNumeric(nsCSSValue& aValue);
bool ParseFontWeight(nsCSSValue& aValue);
bool ParseOneFamily(nsAString& aFamily, bool& aOneKeyword);
bool ParseFamily(nsCSSValue& aValue);
@ -665,12 +676,13 @@ protected:
/* Functions for transform Parsing */
bool ParseSingleTransform(bool aIsPrefixed, nsCSSValue& aValue, bool& aIs3D);
bool ParseFunction(const nsString &aFunction, const int32_t aAllowedTypes[],
uint16_t aMinElems, uint16_t aMaxElems,
nsCSSValue &aValue);
int32_t aVariantMaskAll, uint16_t aMinElems,
uint16_t aMaxElems, nsCSSValue &aValue);
bool ParseFunctionInternals(const int32_t aVariantMask[],
uint16_t aMinElems,
uint16_t aMaxElems,
InfallibleTArray<nsCSSValue>& aOutput);
int32_t aVariantMaskAll,
uint16_t aMinElems,
uint16_t aMaxElems,
InfallibleTArray<nsCSSValue>& aOutput);
/* Functions for transform-origin/perspective-origin Parsing */
bool ParseTransformOrigin(bool aPerspective);
@ -1626,6 +1638,11 @@ CSSParserImpl::ParseAtRule(RuleAppendFunc aAppendFunc,
parseFunc = &CSSParserImpl::ParseFontFaceRule;
newSection = eCSSSection_General;
} else if (mToken.mIdent.LowerCaseEqualsLiteral("font-feature-values") &&
nsCSSFontFeatureValuesRule::PrefEnabled()) {
parseFunc = &CSSParserImpl::ParseFontFeatureValuesRule;
newSection = eCSSSection_General;
} else if (mToken.mIdent.LowerCaseEqualsLiteral("page")) {
parseFunc = &CSSParserImpl::ParsePageRule;
newSection = eCSSSection_General;
@ -2351,6 +2368,233 @@ CSSParserImpl::ParseFontDescriptor(nsCSSFontFaceRule* aRule)
return true;
}
// @font-feature-values <font-family># {
// @<feature-type> {
// <feature-ident> : <feature-index>+;
// <feature-ident> : <feature-index>+;
// ...
// }
// ...
// }
bool
CSSParserImpl::ParseFontFeatureValuesRule(RuleAppendFunc aAppendFunc,
void* aData)
{
nsRefPtr<nsCSSFontFeatureValuesRule>
valuesRule(new nsCSSFontFeatureValuesRule());
// parse family list
nsCSSValue familyValue;
if (!ParseFamily(familyValue) ||
familyValue.GetUnit() != eCSSUnit_Families)
{
REPORT_UNEXPECTED_TOKEN(PEFFVNoFamily);
return false;
}
// add family to rule
nsAutoString familyList;
bool hasGeneric;
familyValue.GetStringValue(familyList);
valuesRule->SetFamilyList(familyList, hasGeneric);
// family list has generic ==> parse error
if (hasGeneric) {
REPORT_UNEXPECTED_TOKEN(PEFFVGenericInFamilyList);
return false;
}
// open brace
if (!ExpectSymbol('{', true)) {
REPORT_UNEXPECTED_TOKEN(PEFFVBlockStart);
return false;
}
// list of sets of feature values, each set bound to a specific
// feature-type (e.g. swash, annotation)
for (;;) {
if (!GetToken(true)) {
REPORT_UNEXPECTED_EOF(PEFFVUnexpectedEOF);
break;
}
if (mToken.IsSymbol('}')) { // done!
UngetToken();
break;
}
if (!ParseFontFeatureValueSet(valuesRule)) {
if (!SkipAtRule(false)) {
break;
}
}
}
if (!ExpectSymbol('}', true)) {
REPORT_UNEXPECTED_TOKEN(PEFFVUnexpectedBlockEnd);
SkipUntil('}');
return false;
}
(*aAppendFunc)(valuesRule, aData);
return true;
}
#define NUMVALUES_NO_LIMIT 0xFFFF
// parse a single value set containing name-value pairs for a single feature type
// @<feature-type> { [ <feature-ident> : <feature-index>+ ; ]* }
// Ex: @swash { flowing: 1; delicate: 2; }
bool
CSSParserImpl::ParseFontFeatureValueSet(nsCSSFontFeatureValuesRule
*aFeatureValuesRule)
{
// -- @keyword (e.g. swash, styleset)
if (eCSSToken_AtKeyword != mToken.mType) {
REPORT_UNEXPECTED_TOKEN(PEFontFeatureValuesNoAt);
OUTPUT_ERROR();
UngetToken();
return false;
}
// which font-specific variant of font-variant-alternates
int32_t whichVariant;
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
if (keyword == eCSSKeyword_UNKNOWN ||
!nsCSSProps::FindKeyword(keyword,
nsCSSProps::kFontVariantAlternatesFuncsKTable,
whichVariant))
{
if (!NonMozillaVendorIdentifier(mToken.mIdent)) {
REPORT_UNEXPECTED_TOKEN(PEFFVUnknownFontVariantPropValue);
OUTPUT_ERROR();
}
UngetToken();
return false;
}
nsAutoString featureType(mToken.mIdent);
// open brace
if (!ExpectSymbol('{', true)) {
REPORT_UNEXPECTED_TOKEN(PEFFVValueSetStart);
return false;
}
// styleset and character-variant can be multi-valued, otherwise single value
int32_t limitNumValues;
switch (keyword) {
case eCSSKeyword_styleset:
limitNumValues = NUMVALUES_NO_LIMIT;
break;
case eCSSKeyword_character_variant:
limitNumValues = 2;
break;
default:
limitNumValues = 1;
break;
}
// -- ident integer+ [, ident integer+]
nsAutoTArray<gfxFontFeatureValueSet::ValueList, 5> values;
// list of font-feature-values-declaration's
for (;;) {
nsAutoString valueId;
if (!GetToken(true)) {
REPORT_UNEXPECTED_EOF(PEFFVUnexpectedEOF);
break;
}
// ignore extra semicolons
if (mToken.IsSymbol(';')) {
continue;
}
// close brace ==> done
if (mToken.IsSymbol('}')) {
break;
}
// ident
if (eCSSToken_Ident != mToken.mType) {
REPORT_UNEXPECTED_TOKEN(PEFFVExpectedIdent);
if (!SkipDeclaration(true)) {
break;
}
continue;
}
valueId.Assign(mToken.mIdent);
// colon
if (!ExpectSymbol(':', true)) {
REPORT_UNEXPECTED_TOKEN(PEParseDeclarationNoColon);
OUTPUT_ERROR();
if (!SkipDeclaration(true)) {
break;
}
continue;
}
// value list
nsAutoTArray<uint32_t,4> featureSelectors;
nsCSSValue intValue;
while (ParseNonNegativeVariant(intValue, VARIANT_INTEGER, nullptr)) {
featureSelectors.AppendElement(uint32_t(intValue.GetIntValue()));
}
int32_t numValues = featureSelectors.Length();
if (numValues == 0) {
REPORT_UNEXPECTED_TOKEN(PEFFVExpectedValue);
OUTPUT_ERROR();
if (!SkipDeclaration(true)) {
break;
}
continue;
}
if (numValues > limitNumValues) {
REPORT_UNEXPECTED_P(PEFFVTooManyValues, featureType);
OUTPUT_ERROR();
if (!SkipDeclaration(true)) {
break;
}
continue;
}
if (!GetToken(true)) {
REPORT_UNEXPECTED_EOF(PEFFVUnexpectedEOF);
gfxFontFeatureValueSet::ValueList v(valueId, featureSelectors);
values.AppendElement(v);
break;
}
// ';' or '}' to end definition
if (!mToken.IsSymbol(';') && !mToken.IsSymbol('}')) {
REPORT_UNEXPECTED_TOKEN(PEFFVValueDefinitionTrailing);
OUTPUT_ERROR();
if (!SkipDeclaration(true)) {
break;
}
continue;
}
gfxFontFeatureValueSet::ValueList v(valueId, featureSelectors);
values.AppendElement(v);
if (mToken.IsSymbol('}')) {
break;
}
}
aFeatureValuesRule->AddValueList(whichVariant, values);
return true;
}
bool
CSSParserImpl::ParseKeyframesRule(RuleAppendFunc aAppendFunc, void* aData)
@ -6370,6 +6614,16 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
switch (aPropID) {
case eCSSProperty_font_family:
return ParseFamily(aValue);
case eCSSProperty_font_synthesis:
return ParseFontSynthesis(aValue);
case eCSSProperty_font_variant_alternates:
return ParseFontVariantAlternates(aValue);
case eCSSProperty_font_variant_east_asian:
return ParseFontVariantEastAsian(aValue);
case eCSSProperty_font_variant_ligatures:
return ParseFontVariantLigatures(aValue);
case eCSSProperty_font_variant_numeric:
return ParseFontVariantNumeric(aValue);
case eCSSProperty_font_feature_settings:
return ParseFontFeatureSettings(aValue);
case eCSSProperty_font_weight:
@ -7993,7 +8247,7 @@ CSSParserImpl::ParseCalcTerm(nsCSSValue& aValue, int32_t& aVariantMask)
// ... or just a value
UngetToken();
// Always pass VARIANT_NUMBER to ParseVariant so that unitless zero
// always gets picked up
// always gets picked up
if (!ParseVariant(aValue, aVariantMask | VARIANT_NUMBER, nullptr)) {
return false;
}
@ -8303,6 +8557,14 @@ CSSParserImpl::ParseFont()
AppendValue(eCSSProperty_font_size_adjust, family);
AppendValue(eCSSProperty_font_feature_settings, family);
AppendValue(eCSSProperty_font_language_override, family);
AppendValue(eCSSProperty_font_kerning, family);
AppendValue(eCSSProperty_font_synthesis, family);
AppendValue(eCSSProperty_font_variant_alternates, family);
AppendValue(eCSSProperty_font_variant_caps, family);
AppendValue(eCSSProperty_font_variant_east_asian, family);
AppendValue(eCSSProperty_font_variant_ligatures, family);
AppendValue(eCSSProperty_font_variant_numeric, family);
AppendValue(eCSSProperty_font_variant_position, family);
}
else {
AppendValue(eCSSProperty__x_system_font, family);
@ -8317,6 +8579,14 @@ CSSParserImpl::ParseFont()
AppendValue(eCSSProperty_font_size_adjust, systemFont);
AppendValue(eCSSProperty_font_feature_settings, systemFont);
AppendValue(eCSSProperty_font_language_override, systemFont);
AppendValue(eCSSProperty_font_kerning, systemFont);
AppendValue(eCSSProperty_font_synthesis, systemFont);
AppendValue(eCSSProperty_font_variant_alternates, systemFont);
AppendValue(eCSSProperty_font_variant_caps, systemFont);
AppendValue(eCSSProperty_font_variant_east_asian, systemFont);
AppendValue(eCSSProperty_font_variant_ligatures, systemFont);
AppendValue(eCSSProperty_font_variant_numeric, systemFont);
AppendValue(eCSSProperty_font_variant_position, systemFont);
}
return true;
}
@ -8380,12 +8650,287 @@ CSSParserImpl::ParseFont()
AppendValue(eCSSProperty_font_size_adjust, nsCSSValue(eCSSUnit_None));
AppendValue(eCSSProperty_font_feature_settings, nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_language_override, nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_kerning,
nsCSSValue(NS_FONT_KERNING_AUTO, eCSSUnit_Enumerated));
AppendValue(eCSSProperty_font_synthesis,
nsCSSValue(NS_FONT_SYNTHESIS_WEIGHT | NS_FONT_SYNTHESIS_STYLE,
eCSSUnit_Enumerated));
AppendValue(eCSSProperty_font_variant_alternates,
nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_variant_caps, nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_variant_east_asian,
nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_variant_ligatures,
nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_variant_numeric,
nsCSSValue(eCSSUnit_Normal));
AppendValue(eCSSProperty_font_variant_position,
nsCSSValue(eCSSUnit_Normal));
return true;
}
}
return false;
}
bool
CSSParserImpl::ParseFontSynthesis(nsCSSValue& aValue)
{
if (!ParseVariant(aValue, VARIANT_HK | VARIANT_NONE,
nsCSSProps::kFontSynthesisKTable)) {
return false;
}
// first value 'none' ==> done
if (eCSSUnit_None == aValue.GetUnit() ||
eCSSUnit_Initial == aValue.GetUnit() ||
eCSSUnit_Inherit == aValue.GetUnit())
{
return true;
}
// look for a second value
int32_t intValue = aValue.GetIntValue();
nsCSSValue nextValue;
if (ParseEnum(nextValue, nsCSSProps::kFontSynthesisKTable)) {
int32_t nextIntValue = nextValue.GetIntValue();
if (nextIntValue & intValue) {
return false;
}
aValue.SetIntValue(nextIntValue | intValue, eCSSUnit_Enumerated);
}
return true;
}
// font-variant-alternates allows for a combination of multiple
// simple enumerated values and functional values. Functional values have
// parameter lists with one or more idents which are later resolved
// based on values defined in @font-feature-value rules.
//
// font-variant-alternates: swash(flowing), historical-forms, styleset(alt-g, alt-m);
//
// So for this the nsCSSValue is set to a pair value, with one
// value for a bitmask of both simple and functional property values
// and another value containing a ValuePairList with lists of idents
// for each functional property value.
//
// pairValue
// o intValue
// NS_FONT_VARIANT_ALTERNATES_SWASH |
// NS_FONT_VARIANT_ALTERNATES_STYLESET
// o valuePairList, each element with
// - intValue - indicates which alternate
// - string or valueList of strings
//
// Note: when only 'historical-forms' is specified, there are no
// functional values to store, in which case the valuePairList is a
// single element dummy list. In all other cases, the length of the
// list will match the number of functional values.
#define MAX_ALLOWED_FEATURES 512
bool
CSSParserImpl::ParseSingleAlternate(int32_t& aWhichFeature,
nsCSSValue& aValue)
{
if (!GetToken(true)) {
return false;
}
bool isIdent = (mToken.mType == eCSSToken_Ident);
if (mToken.mType != eCSSToken_Function && !isIdent) {
UngetToken();
return false;
}
// ident ==> simple enumerated prop val (e.g. historical-forms)
// function ==> e.g. swash(flowing) styleset(alt-g, alt-m)
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(mToken.mIdent);
if (!(eCSSKeyword_UNKNOWN < keyword &&
nsCSSProps::FindKeyword(keyword,
(isIdent ?
nsCSSProps::kFontVariantAlternatesKTable :
nsCSSProps::kFontVariantAlternatesFuncsKTable),
aWhichFeature)))
{
// failed, pop token
UngetToken();
return false;
}
if (isIdent) {
aValue.SetIntValue(aWhichFeature, eCSSUnit_Enumerated);
return true;
}
uint16_t maxElems = 1;
if (keyword == eCSSKeyword_styleset ||
keyword == eCSSKeyword_character_variant) {
maxElems = MAX_ALLOWED_FEATURES;
}
return ParseFunction(mToken.mIdent, nullptr, VARIANT_IDENTIFIER,
1, maxElems, aValue);
}
bool
CSSParserImpl::ParseFontVariantAlternates(nsCSSValue& aValue)
{
if (ParseVariant(aValue, VARIANT_INHERIT | VARIANT_NORMAL, nullptr)) {
return true;
}
// iterate through parameters
nsCSSValue listValue;
int32_t feature, featureFlags = 0;
// if no functional values, this may be a list with a single, unused element
listValue.SetListValue();
nsCSSValueList* list = nullptr;
nsCSSValue value;
while (ParseSingleAlternate(feature, value)) {
// check to make sure value not already set
if (feature == 0 ||
feature & featureFlags) {
return false;
}
featureFlags |= feature;
// if function, need to add to the list of functions
if (value.GetUnit() == eCSSUnit_Function) {
if (!list) {
list = listValue.GetListValue();
} else {
list->mNext = new nsCSSValueList;
list = list->mNext;
}
list->mValue = value;
}
}
nsCSSValue featureValue;
featureValue.SetIntValue(featureFlags, eCSSUnit_Enumerated);
aValue.SetPairValue(featureValue, listValue);
return true;
}
#define MASK_END_VALUE -1
// aMasks - array of masks for mutually-exclusive property values,
// e.g. proportial-nums, tabular-nums
bool
CSSParserImpl::ParseBitmaskValues(nsCSSValue& aValue,
const int32_t aKeywordTable[],
const int32_t aMasks[])
{
if (!ParseVariant(aValue, VARIANT_HMK, aKeywordTable)) {
return false;
}
// first value 'normal', 'inherit', 'initial' ==> done
if (eCSSUnit_Normal == aValue.GetUnit() ||
eCSSUnit_Initial == aValue.GetUnit() ||
eCSSUnit_Inherit == aValue.GetUnit())
{
return true;
}
// look for more values
nsCSSValue nextValue;
int32_t mergedValue = aValue.GetIntValue();
while (ParseEnum(nextValue, aKeywordTable))
{
int32_t nextIntValue = nextValue.GetIntValue();
// check to make sure value not already set
if (nextIntValue & mergedValue) {
return false;
}
const int32_t *m = aMasks;
int32_t c = 0;
while (*m != MASK_END_VALUE) {
if (*m & nextIntValue) {
c = mergedValue & *m;
break;
}
m++;
}
if (c) {
return false;
}
mergedValue |= nextIntValue;
}
aValue.SetIntValue(mergedValue, eCSSUnit_Enumerated);
return true;
}
static const int32_t maskEastAsian[] = {
NS_FONT_VARIANT_EAST_ASIAN_VARIANT_MASK,
NS_FONT_VARIANT_EAST_ASIAN_WIDTH_MASK,
MASK_END_VALUE
};
bool
CSSParserImpl::ParseFontVariantEastAsian(nsCSSValue& aValue)
{
NS_ASSERTION(maskEastAsian[NS_ARRAY_LENGTH(maskEastAsian) - 1] ==
MASK_END_VALUE,
"incorrectly terminated array");
return ParseBitmaskValues(aValue, nsCSSProps::kFontVariantEastAsianKTable,
maskEastAsian);
}
static const int32_t maskLigatures[] = {
NS_FONT_VARIANT_LIGATURES_COMMON_MASK,
NS_FONT_VARIANT_LIGATURES_DISCRETIONARY_MASK,
NS_FONT_VARIANT_LIGATURES_HISTORICAL_MASK,
NS_FONT_VARIANT_LIGATURES_CONTEXTUAL_MASK,
MASK_END_VALUE
};
bool
CSSParserImpl::ParseFontVariantLigatures(nsCSSValue& aValue)
{
NS_ASSERTION(maskLigatures[NS_ARRAY_LENGTH(maskLigatures) - 1] ==
MASK_END_VALUE,
"incorrectly terminated array");
return ParseBitmaskValues(aValue, nsCSSProps::kFontVariantLigaturesKTable,
maskLigatures);
}
static const int32_t maskNumeric[] = {
NS_FONT_VARIANT_NUMERIC_FIGURE_MASK,
NS_FONT_VARIANT_NUMERIC_SPACING_MASK,
NS_FONT_VARIANT_NUMERIC_FRACTION_MASK,
MASK_END_VALUE
};
bool
CSSParserImpl::ParseFontVariantNumeric(nsCSSValue& aValue)
{
NS_ASSERTION(maskNumeric[NS_ARRAY_LENGTH(maskNumeric) - 1] ==
MASK_END_VALUE,
"incorrectly terminated array");
return ParseBitmaskValues(aValue, nsCSSProps::kFontVariantNumericKTable,
maskNumeric);
}
bool
CSSParserImpl::ParseFontWeight(nsCSSValue& aValue)
{
@ -9157,14 +9702,21 @@ CSSParserImpl::ParseTextOverflow(nsCSSValue& aValue)
*/
bool
CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[],
int32_t aVariantMaskAll,
uint16_t aMinElems,
uint16_t aMaxElems,
InfallibleTArray<nsCSSValue> &aOutput)
{
NS_ASSERTION((aVariantMask && !aVariantMaskAll) ||
(!aVariantMask && aVariantMaskAll),
"only one of the two variant mask parameters can be set");
for (uint16_t index = 0; index < aMaxElems; ++index) {
nsCSSValue newValue;
if (!ParseVariant(newValue, aVariantMask[index], nullptr))
int32_t m = aVariantMaskAll ? aVariantMaskAll : aVariantMask[index];
if (!ParseVariant(newValue, m, nullptr)) {
return false;
}
aOutput.AppendElement(newValue);
@ -9192,7 +9744,8 @@ CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[],
* types for each element in the function. The zeroth element in the
* array corresponds to the first function parameter, etc. The length
* of this array _must_ be greater than or equal to aMaxElems or the
* behavior is undefined.
* behavior is undefined. If not null, aAllowTypesAll must be 0.
* @param aAllowedTypesAll If set, every element tested for these types
* @param aMinElems Minimum number of elements to read. Reading fewer than
* this many elements will result in the function failing.
* @param aMaxElems Maximum number of elements to read. Reading more than
@ -9202,9 +9755,13 @@ CSSParserImpl::ParseFunctionInternals(const int32_t aVariantMask[],
bool
CSSParserImpl::ParseFunction(const nsString &aFunction,
const int32_t aAllowedTypes[],
int32_t aAllowedTypesAll,
uint16_t aMinElems, uint16_t aMaxElems,
nsCSSValue &aValue)
{
NS_ASSERTION((aAllowedTypes && !aAllowedTypesAll) ||
(!aAllowedTypes && aAllowedTypesAll),
"only one of the two allowed type parameter can be set");
typedef InfallibleTArray<nsCSSValue>::size_type arrlen_t;
/* 2^16 - 2, so that if we have 2^16 - 2 transforms, we have 2^16 - 1
@ -9222,9 +9779,10 @@ CSSParserImpl::ParseFunction(const nsString &aFunction,
* it's out of bounds.
*/
InfallibleTArray<nsCSSValue> foundValues;
if (!ParseFunctionInternals(aAllowedTypes, aMinElems, aMaxElems,
foundValues))
if (!ParseFunctionInternals(aAllowedTypes, aAllowedTypesAll, aMinElems,
aMaxElems, foundValues)) {
return false;
}
/* Now, convert this array into an nsCSSValue::Array object.
* We'll need N + 1 spots, one for the function name and the rest for the
@ -9499,7 +10057,8 @@ CSSParserImpl::ParseSingleTransform(bool aIsPrefixed,
break;
}
return ParseFunction(mToken.mIdent, variantMask, minElems, maxElems, aValue);
return ParseFunction(mToken.mIdent, variantMask, 0, minElems,
maxElems, aValue);
}
/* Parses a transform property list by continuously reading in properties

View File

@ -55,3 +55,5 @@ CSS_PROP_ALIAS(-moz-animation-iteration-count, animation_iteration_count, MozAni
CSS_PROP_ALIAS(-moz-animation-name, animation_name, MozAnimationName, "layout.css.prefixes.animations")
CSS_PROP_ALIAS(-moz-animation-play-state, animation_play_state, MozAnimationPlayState, "layout.css.prefixes.animations")
CSS_PROP_ALIAS(-moz-animation-timing-function, animation_timing_function, MozAnimationTimingFunction, "layout.css.prefixes.animations")
CSS_PROP_ALIAS(font-feature-settings, font_feature_settings, FontFeatureSettings, "layout.css.font-features.enabled")
CSS_PROP_ALIAS(font-language-override, font_language_override, FontLanguageOverride, "layout.css.font-features.enabled")

View File

@ -1709,6 +1709,18 @@ CSS_PROP_FONT(
nullptr,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-kerning,
font_kerning,
FontKerning,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
VARIANT_HK,
kFontKerningKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
-moz-font-language-override,
font_language_override,
@ -1774,6 +1786,19 @@ CSS_PROP_FONT(
kFontStyleKTable,
offsetof(nsStyleFont, mFont.style),
eStyleAnimType_EnumU8)
CSS_PROP_FONT(
font-synthesis,
font_synthesis,
FontSynthesis,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
0,
kFontSynthesisKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-variant,
font_variant,
@ -1786,6 +1811,82 @@ CSS_PROP_FONT(
kFontVariantKTable,
offsetof(nsStyleFont, mFont.variant),
eStyleAnimType_EnumU8)
CSS_PROP_FONT(
font-variant-alternates,
font_variant_alternates,
FontVariantAlternates,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
VARIANT_HK,
kFontVariantAlternatesKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-variant-caps,
font_variant_caps,
FontVariantCaps,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
VARIANT_HMK,
kFontVariantCapsKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-variant-east-asian,
font_variant_east_asian,
FontVariantEastAsian,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
0,
kFontVariantEastAsianKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-variant-ligatures,
font_variant_ligatures,
FontVariantLigatures,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
0,
kFontVariantLigaturesKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-variant-numeric,
font_variant_numeric,
FontVariantNumeric,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_VALUE_PARSER_FUNCTION |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
0,
kFontVariantNumericKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-variant-position,
font_variant_position,
FontVariantPosition,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER,
"layout.css.font-features.enabled",
VARIANT_HMK,
kFontVariantPositionKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_FONT(
font-weight,
font_weight,

View File

@ -410,7 +410,17 @@ nsCSSFontDesc
nsCSSProps::LookupFontDesc(const nsAString& aFontDesc)
{
NS_ABORT_IF_FALSE(gFontDescTable, "no lookup table, needs addref");
return nsCSSFontDesc(gFontDescTable->Lookup(aFontDesc));
nsCSSFontDesc which = nsCSSFontDesc(gFontDescTable->Lookup(aFontDesc));
// check for unprefixed font-feature-settings/font-language-override
if (which == eCSSFontDesc_UNKNOWN &&
mozilla::Preferences::GetBool("layout.css.font-features.enabled")) {
nsAutoString prefixedProp;
prefixedProp.AppendLiteral("-moz-");
prefixedProp.Append(aFontDesc);
which = nsCSSFontDesc(gFontDescTable->Lookup(prefixedProp));
}
return which;
}
const nsAFlatCString&
@ -1013,6 +1023,13 @@ const int32_t nsCSSProps::kFontKTable[] = {
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontKerningKTable[] = {
eCSSKeyword_auto, NS_FONT_KERNING_AUTO,
eCSSKeyword_none, NS_FONT_KERNING_NONE,
eCSSKeyword_normal, NS_FONT_KERNING_NORMAL,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontSizeKTable[] = {
eCSSKeyword_xx_small, NS_STYLE_FONT_SIZE_XXSMALL,
eCSSKeyword_x_small, NS_STYLE_FONT_SIZE_XSMALL,
@ -1046,12 +1063,87 @@ const int32_t nsCSSProps::kFontStyleKTable[] = {
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontSynthesisKTable[] = {
eCSSKeyword_weight, NS_FONT_SYNTHESIS_WEIGHT,
eCSSKeyword_style, NS_FONT_SYNTHESIS_STYLE,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantKTable[] = {
eCSSKeyword_normal, NS_STYLE_FONT_VARIANT_NORMAL,
eCSSKeyword_small_caps, NS_STYLE_FONT_VARIANT_SMALL_CAPS,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantAlternatesKTable[] = {
eCSSKeyword_historical_forms, NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantAlternatesFuncsKTable[] = {
eCSSKeyword_stylistic, NS_FONT_VARIANT_ALTERNATES_STYLISTIC,
eCSSKeyword_styleset, NS_FONT_VARIANT_ALTERNATES_STYLESET,
eCSSKeyword_character_variant, NS_FONT_VARIANT_ALTERNATES_CHARACTER_VARIANT,
eCSSKeyword_swash, NS_FONT_VARIANT_ALTERNATES_SWASH,
eCSSKeyword_ornaments, NS_FONT_VARIANT_ALTERNATES_ORNAMENTS,
eCSSKeyword_annotation, NS_FONT_VARIANT_ALTERNATES_ANNOTATION,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantCapsKTable[] = {
eCSSKeyword_small_caps, NS_FONT_VARIANT_CAPS_SMALLCAPS,
eCSSKeyword_all_small_caps, NS_FONT_VARIANT_CAPS_ALLSMALL,
eCSSKeyword_petite_caps, NS_FONT_VARIANT_CAPS_PETITECAPS,
eCSSKeyword_all_petite_caps, NS_FONT_VARIANT_CAPS_ALLPETITE,
eCSSKeyword_titling_caps, NS_FONT_VARIANT_CAPS_TITLING,
eCSSKeyword_unicase, NS_FONT_VARIANT_CAPS_UNICASE,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantEastAsianKTable[] = {
eCSSKeyword_jis78, NS_FONT_VARIANT_EAST_ASIAN_JIS78,
eCSSKeyword_jis83, NS_FONT_VARIANT_EAST_ASIAN_JIS83,
eCSSKeyword_jis90, NS_FONT_VARIANT_EAST_ASIAN_JIS90,
eCSSKeyword_jis04, NS_FONT_VARIANT_EAST_ASIAN_JIS04,
eCSSKeyword_simplified, NS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED,
eCSSKeyword_traditional, NS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL,
eCSSKeyword_full_width, NS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH,
eCSSKeyword_proportional_width, NS_FONT_VARIANT_EAST_ASIAN_PROP_WIDTH,
eCSSKeyword_ruby, NS_FONT_VARIANT_EAST_ASIAN_RUBY,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantLigaturesKTable[] = {
eCSSKeyword_common_ligatures, NS_FONT_VARIANT_LIGATURES_COMMON,
eCSSKeyword_no_common_ligatures, NS_FONT_VARIANT_LIGATURES_NO_COMMON,
eCSSKeyword_discretionary_ligatures, NS_FONT_VARIANT_LIGATURES_DISCRETIONARY,
eCSSKeyword_no_discretionary_ligatures, NS_FONT_VARIANT_LIGATURES_NO_DISCRETIONARY,
eCSSKeyword_historical_ligatures, NS_FONT_VARIANT_LIGATURES_HISTORICAL,
eCSSKeyword_no_historical_ligatures, NS_FONT_VARIANT_LIGATURES_NO_HISTORICAL,
eCSSKeyword_contextual, NS_FONT_VARIANT_LIGATURES_CONTEXTUAL,
eCSSKeyword_no_contextual, NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantNumericKTable[] = {
eCSSKeyword_lining_nums, NS_FONT_VARIANT_NUMERIC_LINING,
eCSSKeyword_oldstyle_nums, NS_FONT_VARIANT_NUMERIC_OLDSTYLE,
eCSSKeyword_proportional_nums, NS_FONT_VARIANT_NUMERIC_PROPORTIONAL,
eCSSKeyword_tabular_nums, NS_FONT_VARIANT_NUMERIC_TABULAR,
eCSSKeyword_diagonal_fractions, NS_FONT_VARIANT_NUMERIC_DIAGONAL_FRACTIONS,
eCSSKeyword_stacked_fractions, NS_FONT_VARIANT_NUMERIC_STACKED_FRACTIONS,
eCSSKeyword_slashed_zero, NS_FONT_VARIANT_NUMERIC_SLASHZERO,
eCSSKeyword_ordinal, NS_FONT_VARIANT_NUMERIC_ORDINAL,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontVariantPositionKTable[] = {
eCSSKeyword_super, NS_FONT_VARIANT_POSITION_SUPER,
eCSSKeyword_sub, NS_FONT_VARIANT_POSITION_SUB,
eCSSKeyword_UNKNOWN,-1
};
const int32_t nsCSSProps::kFontWeightKTable[] = {
eCSSKeyword_normal, NS_STYLE_FONT_WEIGHT_NORMAL,
eCSSKeyword_bold, NS_STYLE_FONT_WEIGHT_BOLD,
@ -2072,11 +2164,19 @@ static const nsCSSProperty gFontSubpropTable[] = {
eCSSProperty_font_weight,
eCSSProperty_font_size,
eCSSProperty_line_height,
eCSSProperty_font_size_adjust, // XXX Added LDB.
eCSSProperty_font_stretch, // XXX Added LDB.
eCSSProperty_font_size_adjust,
eCSSProperty_font_stretch,
eCSSProperty__x_system_font,
eCSSProperty_font_feature_settings,
eCSSProperty_font_language_override,
eCSSProperty_font_kerning,
eCSSProperty_font_synthesis,
eCSSProperty_font_variant_alternates,
eCSSProperty_font_variant_caps,
eCSSProperty_font_variant_east_asian,
eCSSProperty_font_variant_ligatures,
eCSSProperty_font_variant_numeric,
eCSSProperty_font_variant_position,
eCSSProperty_UNKNOWN
};

View File

@ -192,7 +192,7 @@ public:
static nsCSSProperty OtherNameFor(nsCSSProperty aProperty);
// Given a CSS Property and a Property Enum Value
// Return back a const nsString& representation of the
// Return back a const nsString& representation of the
// value. Return back nullstr if no value is found
static const nsAFlatCString& LookupPropertyValue(nsCSSProperty aProperty, int32_t aValue);
@ -402,10 +402,19 @@ public:
static const int32_t kFloatKTable[];
static const int32_t kFloatEdgeKTable[];
static const int32_t kFontKTable[];
static const int32_t kFontKerningKTable[];
static const int32_t kFontSizeKTable[];
static const int32_t kFontStretchKTable[];
static const int32_t kFontStyleKTable[];
static const int32_t kFontSynthesisKTable[];
static const int32_t kFontVariantKTable[];
static const int32_t kFontVariantAlternatesKTable[];
static const int32_t kFontVariantAlternatesFuncsKTable[];
static const int32_t kFontVariantCapsKTable[];
static const int32_t kFontVariantEastAsianKTable[];
static const int32_t kFontVariantLigaturesKTable[];
static const int32_t kFontVariantNumericKTable[];
static const int32_t kFontVariantPositionKTable[];
static const int32_t kFontWeightKTable[];
static const int32_t kIMEModeKTable[];
static const int32_t kLineHeightKTable[];

View File

@ -649,7 +649,7 @@ void RuleHash::AppendRule(const RuleSelectorPair& aRuleInfo)
}
AppendRuleToTagTable(&mTagTable, selector->mLowercaseTag, ruleValue);
RULE_HASH_STAT_INCREMENT(mTagSelectors);
if (selector->mCasedTag &&
if (selector->mCasedTag &&
selector->mCasedTag != selector->mLowercaseTag) {
AppendRuleToTagTable(&mTagTable, selector->mCasedTag, ruleValue);
RULE_HASH_STAT_INCREMENT(mTagSelectors);
@ -978,6 +978,7 @@ struct RuleCascadeData {
nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
nsTArray<nsCSSKeyframesRule*> mKeyframesRules;
nsTArray<nsCSSFontFeatureValuesRule*> mFontFeatureValuesRules;
nsTArray<nsCSSPageRule*> mPageRules;
// Looks up or creates the appropriate list in |mAttributeSelectors|.
@ -1029,6 +1030,7 @@ RuleCascadeData::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
n += mFontFaceRules.SizeOfExcludingThis(aMallocSizeOf);
n += mKeyframesRules.SizeOfExcludingThis(aMallocSizeOf);
n += mFontFeatureValuesRules.SizeOfExcludingThis(aMallocSizeOf);
n += mPageRules.SizeOfExcludingThis(aMallocSizeOf);
return n;
@ -1437,11 +1439,11 @@ static bool AttrMatchesValue(const nsAttrSelector* aAttrSelector,
: static_cast<const nsStringComparator&>(ciComparator);
switch (aAttrSelector->mFunction) {
case NS_ATTR_FUNC_EQUALS:
case NS_ATTR_FUNC_EQUALS:
return aValue.Equals(aAttrSelector->mValue, comparator);
case NS_ATTR_FUNC_INCLUDES:
case NS_ATTR_FUNC_INCLUDES:
return ValueIncludes(aValue, aAttrSelector->mValue, comparator);
case NS_ATTR_FUNC_DASHMATCH:
case NS_ATTR_FUNC_DASHMATCH:
return nsStyleUtil::DashMatchCompare(aValue, aAttrSelector->mValue, comparator);
case NS_ATTR_FUNC_ENDSMATCH:
return StringEndsWith(aValue, aAttrSelector->mValue, comparator);
@ -2749,6 +2751,21 @@ nsCSSRuleProcessor::AppendPageRules(
return true;
}
bool
nsCSSRuleProcessor::AppendFontFeatureValuesRules(
nsPresContext *aPresContext,
nsTArray<nsCSSFontFeatureValuesRule*>& aArray)
{
RuleCascadeData* cascade = GetRuleCascade(aPresContext);
if (cascade) {
if (!aArray.AppendElements(cascade->mFontFeatureValuesRules))
return false;
}
return true;
}
nsresult
nsCSSRuleProcessor::ClearRuleCascades()
{
@ -3047,12 +3064,14 @@ struct CascadeEnumData {
CascadeEnumData(nsPresContext* aPresContext,
nsTArray<nsFontFaceRuleContainer>& aFontFaceRules,
nsTArray<nsCSSKeyframesRule*>& aKeyframesRules,
nsTArray<nsCSSFontFeatureValuesRule*>& aFontFeatureValuesRules,
nsTArray<nsCSSPageRule*>& aPageRules,
nsMediaQueryResultCacheKey& aKey,
uint8_t aSheetType)
: mPresContext(aPresContext),
mFontFaceRules(aFontFaceRules),
mKeyframesRules(aKeyframesRules),
mFontFeatureValuesRules(aFontFeatureValuesRules),
mPageRules(aPageRules),
mCacheKey(aKey),
mSheetType(aSheetType)
@ -3076,6 +3095,7 @@ struct CascadeEnumData {
nsPresContext* mPresContext;
nsTArray<nsFontFaceRuleContainer>& mFontFaceRules;
nsTArray<nsCSSKeyframesRule*>& mKeyframesRules;
nsTArray<nsCSSFontFeatureValuesRule*>& mFontFeatureValuesRules;
nsTArray<nsCSSPageRule*>& mPageRules;
nsMediaQueryResultCacheKey& mCacheKey;
PLArenaPool mArena;
@ -3093,7 +3113,9 @@ struct CascadeEnumData {
* but kept in order per-weight, and
* (2) add any @font-face rules, in order, into data->mFontFaceRules.
* (3) add any @keyframes rules, in order, into data->mKeyframesRules.
* (4) add any @page rules, in order, into data->mPageRules.
* (4) add any @font-feature-value rules, in order,
* into data->mFontFeatureValuesRules.
* (5) add any @page rules, in order, into data->mPageRules.
*/
static bool
CascadeRuleEnumFunc(css::Rule* aRule, void* aData)
@ -3146,6 +3168,13 @@ CascadeRuleEnumFunc(css::Rule* aRule, void* aData)
return false;
}
}
else if (css::Rule::FONT_FEATURE_VALUES_RULE == type) {
nsCSSFontFeatureValuesRule *fontFeatureValuesRule =
static_cast<nsCSSFontFeatureValuesRule*>(aRule);
if (!data->mFontFeatureValuesRules.AppendElement(fontFeatureValuesRule)) {
return false;
}
}
else if (css::Rule::PAGE_RULE == type) {
nsCSSPageRule* pageRule = static_cast<nsCSSPageRule*>(aRule);
if (!data->mPageRules.AppendElement(pageRule)) {
@ -3252,6 +3281,7 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
if (newCascade) {
CascadeEnumData data(aPresContext, newCascade->mFontFaceRules,
newCascade->mKeyframesRules,
newCascade->mFontFeatureValuesRules,
newCascade->mPageRules,
newCascade->mCacheKey,
mSheetType);

View File

@ -128,6 +128,9 @@ public:
bool AppendPageRules(nsPresContext* aPresContext,
nsTArray<nsCSSPageRule*>& aArray);
bool AppendFontFeatureValuesRules(nsPresContext* aPresContext,
nsTArray<nsCSSFontFeatureValuesRule*>& aArray);
/**
* Returns the scope element for the scoped style sheets this rule
* processor is for. If this is not a rule processor for scoped style

View File

@ -34,6 +34,7 @@
#include "nsDOMClassInfoID.h"
#include "mozilla/dom/CSSStyleDeclarationBinding.h"
#include "StyleRule.h"
#include "nsFont.h"
using namespace mozilla;
@ -718,7 +719,7 @@ GroupRule::AppendRulesToCssText(nsAString& aCssText)
}
aCssText.AppendLiteral("}");
return NS_OK;
}
@ -1910,6 +1911,255 @@ nsCSSFontFaceRule::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
}
// -----------------------------------
// nsCSSFontFeatureValuesRule
//
/* virtual */ already_AddRefed<css::Rule>
nsCSSFontFeatureValuesRule::Clone() const
{
nsRefPtr<css::Rule> clone = new nsCSSFontFeatureValuesRule(*this);
return clone.forget();
}
NS_IMPL_ADDREF(nsCSSFontFeatureValuesRule)
NS_IMPL_RELEASE(nsCSSFontFeatureValuesRule)
DOMCI_DATA(CSSFontFeatureValuesRule, nsCSSFontFeatureValuesRule)
// QueryInterface implementation for nsCSSFontFeatureValuesRule
NS_INTERFACE_MAP_BEGIN(nsCSSFontFeatureValuesRule)
NS_INTERFACE_MAP_ENTRY(nsIStyleRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRule)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStyleRule)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(CSSFontFeatureValuesRule)
NS_INTERFACE_MAP_END
IMPL_STYLE_RULE_INHERIT(nsCSSFontFeatureValuesRule, Rule)
static void
FamilyListToString(const nsTArray<nsString>& aFamilyList, nsAString& aOutStr)
{
uint32_t i, n = aFamilyList.Length();
for (i = 0; i < n; i++) {
nsStyleUtil::AppendEscapedCSSString(aFamilyList[i], aOutStr);
if (i != n - 1) {
aOutStr.AppendLiteral(", ");
}
}
}
static void
FeatureValuesToString(
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
nsAString& aOutStr)
{
uint32_t i, n;
// append values
n = aFeatureValues.Length();
for (i = 0; i < n; i++) {
const gfxFontFeatureValueSet::FeatureValues& fv = aFeatureValues[i];
// @alternate
aOutStr.AppendLiteral(" @");
nsAutoString functAlt;
nsStyleUtil::GetFunctionalAlternatesName(fv.alternate, functAlt);
aOutStr.Append(functAlt);
aOutStr.AppendLiteral(" {");
// for each ident-values tuple
uint32_t j, numValues = fv.valuelist.Length();
for (j = 0; j < numValues; j++) {
aOutStr.AppendLiteral(" ");
const gfxFontFeatureValueSet::ValueList& vlist = fv.valuelist[j];
nsStyleUtil::AppendEscapedCSSIdent(vlist.name, aOutStr);
aOutStr.AppendLiteral(":");
uint32_t k, numSelectors = vlist.featureSelectors.Length();
for (k = 0; k < numSelectors; k++) {
aOutStr.AppendLiteral(" ");
aOutStr.AppendInt(vlist.featureSelectors[k]);
}
aOutStr.AppendLiteral(";");
}
aOutStr.AppendLiteral(" }\n");
}
}
static void
FontFeatureValuesRuleToString(
const nsTArray<nsString>& aFamilyList,
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& aFeatureValues,
nsAString& aOutStr)
{
aOutStr.AssignLiteral("@font-feature-values ");
nsAutoString familyListStr, valueTextStr;
FamilyListToString(aFamilyList, familyListStr);
aOutStr.Append(familyListStr);
aOutStr.AppendLiteral(" {\n");
FeatureValuesToString(aFeatureValues, valueTextStr);
aOutStr.Append(valueTextStr);
aOutStr.AppendLiteral("}");
}
#ifdef DEBUG
void
nsCSSFontFeatureValuesRule::List(FILE* out, int32_t aIndent) const
{
nsAutoString text;
FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, text);
NS_ConvertUTF16toUTF8 utf8(text);
// replace newlines with newlines plus indent spaces
char* indent = new char[(aIndent + 1) * 2];
int32_t i;
for (i = 1; i < (aIndent + 1) * 2 - 1; i++) {
indent[i] = 0x20;
}
indent[0] = 0xa;
indent[aIndent * 2 + 1] = 0;
utf8.ReplaceSubstring("\n", indent);
delete [] indent;
for (i = aIndent; --i >= 0; ) fputs(" ", out);
fprintf(out, "%s\n", utf8.get());
}
#endif
/* virtual */ int32_t
nsCSSFontFeatureValuesRule::GetType() const
{
return Rule::FONT_FEATURE_VALUES_RULE;
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::GetType(uint16_t* aType)
{
*aType = nsIDOMCSSRule::FONT_FEATURE_VALUES_RULE;
return NS_OK;
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::GetCssText(nsAString& aCssText)
{
FontFeatureValuesRuleToString(mFamilyList, mFeatureValues, aCssText);
return NS_OK;
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::SetCssText(const nsAString& aCssText)
{
// FIXME: implement???
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet)
{
return Rule::GetParentStyleSheet(aSheet);
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::GetParentRule(nsIDOMCSSRule** aParentRule)
{
return Rule::GetParentRule(aParentRule);
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::GetFontFamily(nsAString& aFontFamily)
{
FamilyListToString(mFamilyList, aFontFamily);
return NS_OK;
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::SetFontFamily(const nsAString& aFontFamily)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::GetValueText(nsAString& aValueText)
{
FeatureValuesToString(mFeatureValues, aValueText);
return NS_OK;
}
NS_IMETHODIMP
nsCSSFontFeatureValuesRule::SetValueText(const nsAString& aValueText)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
struct MakeFamilyArray {
MakeFamilyArray(nsTArray<nsString>& aFamilyArray)
: familyArray(aFamilyArray), hasGeneric(false)
{}
static bool
AddFamily(const nsString& aFamily, bool aGeneric, void* aData)
{
MakeFamilyArray *familyArr = reinterpret_cast<MakeFamilyArray*> (aData);
if (!aGeneric && !aFamily.IsEmpty()) {
familyArr->familyArray.AppendElement(aFamily);
}
if (aGeneric) {
familyArr->hasGeneric = true;
}
return true;
}
nsTArray<nsString>& familyArray;
bool hasGeneric;
};
void
nsCSSFontFeatureValuesRule::SetFamilyList(const nsAString& aFamilyList,
bool& aContainsGeneric)
{
nsFont font(aFamilyList, 0, 0, 0, 0, 0, 0);
MakeFamilyArray families(mFamilyList);
font.EnumerateFamilies(MakeFamilyArray::AddFamily, (void*) &families);
aContainsGeneric = families.hasGeneric;
}
void
nsCSSFontFeatureValuesRule::AddValueList(int32_t aVariantAlternate,
nsTArray<gfxFontFeatureValueSet::ValueList>& aValueList)
{
uint32_t i, len = mFeatureValues.Length();
bool foundAlternate = false;
// add to an existing list for a given property value
for (i = 0; i < len; i++) {
gfxFontFeatureValueSet::FeatureValues& f = mFeatureValues.ElementAt(i);
if (f.alternate == uint32_t(aVariantAlternate)) {
f.valuelist.AppendElements(aValueList);
foundAlternate = true;
break;
}
}
// create a new list for a given property value
if (!foundAlternate) {
gfxFontFeatureValueSet::FeatureValues &f = *mFeatureValues.AppendElement();
f.alternate = aVariantAlternate;
f.valuelist.AppendElements(aValueList);
}
}
size_t
nsCSSFontFeatureValuesRule::SizeOfIncludingThis(
nsMallocSizeOfFun aMallocSizeOf) const
{
return aMallocSizeOf(this);
}
// -------------------------------------------
// nsCSSKeyframeStyleDeclaration
//

View File

@ -15,6 +15,7 @@
#include "mozilla/Preferences.h"
#include "nsIDOMCSSConditionRule.h"
#include "nsIDOMCSSFontFaceRule.h"
#include "nsIDOMCSSFontFeatureValuesRule.h"
#include "nsIDOMCSSGroupingRule.h"
#include "nsIDOMCSSMediaRule.h"
#include "nsIDOMCSSMozDocumentRule.h"
@ -31,6 +32,7 @@
#include "Declaration.h"
#include "nsIDOMCSSPageRule.h"
#include "StyleRule.h"
#include "gfxFontFeatures.h"
class nsMediaList;
@ -212,7 +214,7 @@ protected:
#include "nsCSSFontDescList.h"
#undef CSS_FONT_DESC
static nsCSSValue nsCSSFontFaceStyleDecl::* const Fields[];
static nsCSSValue nsCSSFontFaceStyleDecl::* const Fields[];
inline nsCSSFontFaceRule* ContainingRule();
inline const nsCSSFontFaceRule* ContainingRule() const;
@ -264,7 +266,7 @@ protected:
nsCSSFontFaceStyleDecl mDecl;
};
// nsFontFaceRuleContainer - used for associating sheet type with
// nsFontFaceRuleContainer - used for associating sheet type with
// specific @font-face rules
struct nsFontFaceRuleContainer {
nsRefPtr<nsCSSFontFaceRule> mRule;
@ -285,6 +287,61 @@ nsCSSFontFaceStyleDecl::ContainingRule() const
(reinterpret_cast<const char*>(this) - offsetof(nsCSSFontFaceRule, mDecl));
}
class nsCSSFontFeatureValuesRule MOZ_FINAL :
public mozilla::css::Rule,
public nsIDOMCSSFontFeatureValuesRule
{
public:
nsCSSFontFeatureValuesRule() {}
nsCSSFontFeatureValuesRule(const nsCSSFontFeatureValuesRule& aCopy)
// copy everything except our reference count
: mozilla::css::Rule(aCopy),
mFamilyList(aCopy.mFamilyList),
mFeatureValues(aCopy.mFeatureValues) {}
NS_DECL_ISUPPORTS
// nsIStyleRule methods
#ifdef DEBUG
virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE;
#endif
// Rule methods
DECL_STYLE_RULE_INHERIT
virtual int32_t GetType() const MOZ_OVERRIDE;
virtual already_AddRefed<mozilla::css::Rule> Clone() const MOZ_OVERRIDE;
// nsIDOMCSSRule interface
NS_DECL_NSIDOMCSSRULE
// nsIDOMCSSFontFaceRule interface
NS_DECL_NSIDOMCSSFONTFEATUREVALUESRULE
const nsTArray<nsString>& GetFamilyList() { return mFamilyList; }
void SetFamilyList(const nsAString& aFamilyList, bool& aContainsGeneric);
void AddValueList(int32_t aVariantAlternate,
nsTArray<gfxFontFeatureValueSet::ValueList>& aValueList);
const nsTArray<gfxFontFeatureValueSet::FeatureValues>& GetFeatureValues()
{
return mFeatureValues;
}
virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
static bool PrefEnabled()
{
return mozilla::Preferences::GetBool("layout.css.font-features.enabled");
}
protected:
nsTArray<nsString> mFamilyList;
nsTArray<gfxFontFeatureValueSet::FeatureValues> mFeatureValues;
};
namespace mozilla {
namespace css {

View File

@ -806,8 +806,10 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
aResult.AppendInt(GetIntValue(), 10);
}
else if (eCSSUnit_Enumerated == unit) {
if (eCSSProperty_text_decoration_line == aProperty) {
int32_t intValue = GetIntValue();
int32_t intValue = GetIntValue();
switch(aProperty) {
case eCSSProperty_text_decoration_line:
if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
aResult);
@ -821,9 +823,9 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS,
aResult);
}
}
else if (eCSSProperty_marks == aProperty) {
int32_t intValue = GetIntValue();
break;
case eCSSProperty_marks:
if (intValue == NS_STYLE_PAGE_MARKS_NONE) {
AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
aResult);
@ -833,17 +835,48 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
NS_STYLE_PAGE_MARKS_REGISTER,
aResult);
}
}
else if (eCSSProperty_paint_order == aProperty) {
break;
case eCSSProperty_paint_order:
MOZ_STATIC_ASSERT
(NS_STYLE_PAINT_ORDER_BITWIDTH * NS_STYLE_PAINT_ORDER_LAST_VALUE <= 8,
"SVGStyleStruct::mPaintOrder and the following cast not big enough");
nsStyleUtil::AppendPaintOrderValue(static_cast<uint8_t>(GetIntValue()),
aResult);
}
else {
const nsAFlatCString& name = nsCSSProps::LookupPropertyValue(aProperty, GetIntValue());
break;
case eCSSProperty_font_synthesis:
nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
NS_FONT_SYNTHESIS_WEIGHT,
NS_FONT_SYNTHESIS_STYLE,
aResult);
break;
case eCSSProperty_font_variant_east_asian:
nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
NS_FONT_VARIANT_EAST_ASIAN_JIS78,
NS_FONT_VARIANT_EAST_ASIAN_RUBY,
aResult);
break;
case eCSSProperty_font_variant_ligatures:
nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
NS_FONT_VARIANT_LIGATURES_COMMON,
NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL,
aResult);
break;
case eCSSProperty_font_variant_numeric:
nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
NS_FONT_VARIANT_NUMERIC_LINING,
NS_FONT_VARIANT_NUMERIC_ORDINAL,
aResult);
break;
default:
const nsAFlatCString& name = nsCSSProps::LookupPropertyValue(aProperty, intValue);
AppendASCIItoUTF16(name, aResult);
break;
}
}
else if (eCSSUnit_EnumColor == unit) {
@ -1057,7 +1090,27 @@ nsCSSValue::AppendToString(nsCSSProperty aProperty, nsAString& aResult) const
aResult.AppendLiteral(")");
} else if (eCSSUnit_Pair == unit) {
GetPairValue().AppendToString(aProperty, aResult);
if (eCSSProperty_font_variant_alternates == aProperty) {
int32_t intValue = GetPairValue().mXValue.GetIntValue();
nsAutoString out;
// simple, enumerated values
nsStyleUtil::AppendBitmaskCSSValue(aProperty,
intValue & NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK,
NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
out);
// functional values
const nsCSSValueList *list = GetPairValue().mYValue.GetListValue();
nsAutoTArray<gfxAlternateValue,8> altValues;
nsStyleUtil::ComputeFunctionalAlternates(list, altValues);
nsStyleUtil::SerializeFunctionalAlternates(altValues, out);
aResult.Append(out);
} else {
GetPairValue().AppendToString(aProperty, aResult);
}
} else if (eCSSUnit_Triplet == unit) {
GetTripletValue().AppendToString(aProperty, aResult);
} else if (eCSSUnit_Rect == unit) {

View File

@ -1332,6 +1332,16 @@ nsComputedDOMStyle::DoGetFontFeatureSettings()
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontKerning()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.kerning,
nsCSSProps::kFontKerningKTable));
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontLanguageOverride()
{
@ -1348,6 +1358,157 @@ nsComputedDOMStyle::DoGetFontLanguageOverride()
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontSynthesis()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
int32_t intValue = StyleFont()->mFont.synthesis;
if (0 == intValue) {
val->SetIdent(eCSSKeyword_none);
} else {
nsAutoString valueStr;
nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_synthesis,
intValue, NS_FONT_SYNTHESIS_WEIGHT,
NS_FONT_SYNTHESIS_STYLE, valueStr);
val->SetString(valueStr);
}
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontVariantAlternates()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
int32_t intValue = StyleFont()->mFont.variantAlternates;
if (0 == intValue) {
val->SetIdent(eCSSKeyword_normal);
return val;
}
// first, include enumerated values
nsAutoString valueStr;
nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_alternates,
intValue & NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK,
NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
NS_FONT_VARIANT_ALTERNATES_HISTORICAL, valueStr);
// next, include functional values if present
if (intValue & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) {
nsStyleUtil::SerializeFunctionalAlternates(StyleFont()->mFont.alternateValues,
valueStr);
}
val->SetString(valueStr);
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontVariantCaps()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
int32_t intValue = StyleFont()->mFont.variantCaps;
if (0 == intValue) {
val->SetIdent(eCSSKeyword_normal);
} else {
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(intValue,
nsCSSProps::kFontVariantCapsKTable));
}
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontVariantEastAsian()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
int32_t intValue = StyleFont()->mFont.variantEastAsian;
if (0 == intValue) {
val->SetIdent(eCSSKeyword_normal);
} else {
nsAutoString valueStr;
nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_east_asian,
intValue, NS_FONT_VARIANT_EAST_ASIAN_JIS78,
NS_FONT_VARIANT_EAST_ASIAN_RUBY, valueStr);
val->SetString(valueStr);
}
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontVariantLigatures()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
int32_t intValue = StyleFont()->mFont.variantLigatures;
if (0 == intValue) {
val->SetIdent(eCSSKeyword_normal);
} else {
nsAutoString valueStr;
nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_ligatures,
intValue, NS_FONT_VARIANT_LIGATURES_COMMON,
NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL, valueStr);
val->SetString(valueStr);
}
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontVariantNumeric()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
int32_t intValue = StyleFont()->mFont.variantNumeric;
if (0 == intValue) {
val->SetIdent(eCSSKeyword_normal);
} else {
nsAutoString valueStr;
nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_numeric,
intValue, NS_FONT_VARIANT_NUMERIC_LINING,
NS_FONT_VARIANT_NUMERIC_ORDINAL, valueStr);
val->SetString(valueStr);
}
return val;
}
CSSValue*
nsComputedDOMStyle::DoGetFontVariantPosition()
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
int32_t intValue = StyleFont()->mFont.variantPosition;
if (0 == intValue) {
val->SetIdent(eCSSKeyword_normal);
} else {
val->SetIdent(
nsCSSProps::ValueToKeywordEnum(intValue,
nsCSSProps::kFontVariantPositionKTable));
}
return val;
}
CSSValue*
nsComputedDOMStyle::GetBackgroundList(uint8_t nsStyleBackground::Layer::* aMember,
uint32_t nsStyleBackground::* aCount,
@ -4761,11 +4922,19 @@ nsComputedDOMStyle::GetQueryablePropertyMap(uint32_t* aLength)
COMPUTED_STYLE_MAP_ENTRY(float, Float),
//// COMPUTED_STYLE_MAP_ENTRY(font, Font),
COMPUTED_STYLE_MAP_ENTRY(font_family, FontFamily),
COMPUTED_STYLE_MAP_ENTRY(font_kerning, FontKerning),
COMPUTED_STYLE_MAP_ENTRY(font_size, FontSize),
COMPUTED_STYLE_MAP_ENTRY(font_size_adjust, FontSizeAdjust),
COMPUTED_STYLE_MAP_ENTRY(font_stretch, FontStretch),
COMPUTED_STYLE_MAP_ENTRY(font_style, FontStyle),
COMPUTED_STYLE_MAP_ENTRY(font_synthesis, FontSynthesis),
COMPUTED_STYLE_MAP_ENTRY(font_variant, FontVariant),
COMPUTED_STYLE_MAP_ENTRY(font_variant_alternates, FontVariantAlternates),
COMPUTED_STYLE_MAP_ENTRY(font_variant_caps, FontVariantCaps),
COMPUTED_STYLE_MAP_ENTRY(font_variant_east_asian, FontVariantEastAsian),
COMPUTED_STYLE_MAP_ENTRY(font_variant_ligatures, FontVariantLigatures),
COMPUTED_STYLE_MAP_ENTRY(font_variant_numeric, FontVariantNumeric),
COMPUTED_STYLE_MAP_ENTRY(font_variant_position, FontVariantPosition),
COMPUTED_STYLE_MAP_ENTRY(font_weight, FontWeight),
COMPUTED_STYLE_MAP_ENTRY_LAYOUT(height, Height),
COMPUTED_STYLE_MAP_ENTRY(ime_mode, IMEMode),

View File

@ -188,13 +188,21 @@ private:
mozilla::dom::CSSValue* DoGetColor();
mozilla::dom::CSSValue* DoGetFontFamily();
mozilla::dom::CSSValue* DoGetFontFeatureSettings();
mozilla::dom::CSSValue* DoGetFontKerning();
mozilla::dom::CSSValue* DoGetFontLanguageOverride();
mozilla::dom::CSSValue* DoGetFontSize();
mozilla::dom::CSSValue* DoGetFontSizeAdjust();
mozilla::dom::CSSValue* DoGetFontStretch();
mozilla::dom::CSSValue* DoGetFontStyle();
mozilla::dom::CSSValue* DoGetFontWeight();
mozilla::dom::CSSValue* DoGetFontSynthesis();
mozilla::dom::CSSValue* DoGetFontVariant();
mozilla::dom::CSSValue* DoGetFontVariantAlternates();
mozilla::dom::CSSValue* DoGetFontVariantCaps();
mozilla::dom::CSSValue* DoGetFontVariantEastAsian();
mozilla::dom::CSSValue* DoGetFontVariantLigatures();
mozilla::dom::CSSValue* DoGetFontVariantNumeric();
mozilla::dom::CSSValue* DoGetFontVariantPosition();
mozilla::dom::CSSValue* DoGetFontWeight();
/* Background properties */
mozilla::dom::CSSValue* DoGetBackgroundAttachment();

View File

@ -39,6 +39,7 @@
#include "CSSCalc.h"
#include "nsPrintfCString.h"
#include "nsRenderingContext.h"
#include "nsStyleUtil.h"
#include "mozilla/LookAndFeel.h"
@ -3273,6 +3274,109 @@ nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
aFont->mScriptLevel = 0;
}
// font-kerning: none, enum, inherit, initial, -moz-system-font
SetDiscrete(*aRuleData->ValueForFontKerning(),
aFont->mFont.kerning, aCanStoreInRuleTree,
SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
aParentFont->mFont.kerning,
defaultVariableFont->kerning,
0, 0, 0, systemFont.kerning);
// font-synthesis: none, enum (bit field), inherit, initial, -moz-system-font
SetDiscrete(*aRuleData->ValueForFontSynthesis(),
aFont->mFont.synthesis, aCanStoreInRuleTree,
SETDSC_NONE | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
aParentFont->mFont.synthesis,
defaultVariableFont->synthesis,
0, 0, 0, systemFont.synthesis);
// font-variant-alternates: normal, enum (bit field) + functions, inherit,
// initial, -moz-system-font
const nsCSSValue* variantAlternatesValue =
aRuleData->ValueForFontVariantAlternates();
int32_t variantAlternates = 0;
switch (variantAlternatesValue->GetUnit()) {
case eCSSUnit_Inherit:
aFont->mFont.CopyAlternates(aParentFont->mFont);
aCanStoreInRuleTree = false;
break;
case eCSSUnit_Initial:
case eCSSUnit_Normal:
aFont->mFont.variantAlternates = 0;
aFont->mFont.alternateValues.Clear();
aFont->mFont.featureValueLookup = nullptr;
break;
case eCSSUnit_Pair:
NS_ASSERTION(variantAlternatesValue->GetPairValue().mXValue.GetUnit() ==
eCSSUnit_Enumerated, "strange unit for variantAlternates");
variantAlternates =
variantAlternatesValue->GetPairValue().mXValue.GetIntValue();
aFont->mFont.variantAlternates = variantAlternates;
if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) {
// fetch the feature lookup object from the styleset
aFont->mFont.featureValueLookup =
aPresContext->StyleSet()->GetFontFeatureValuesLookup();
NS_ASSERTION(variantAlternatesValue->GetPairValue().mYValue.GetUnit() ==
eCSSUnit_List, "function list not a list value");
nsStyleUtil::ComputeFunctionalAlternates(
variantAlternatesValue->GetPairValue().mYValue.GetListValue(),
aFont->mFont.alternateValues);
}
break;
default:
break;
}
// font-variant-caps: normal, enum, inherit, initial, -moz-system-font
SetDiscrete(*aRuleData->ValueForFontVariantCaps(),
aFont->mFont.variantCaps, aCanStoreInRuleTree,
SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
aParentFont->mFont.variantCaps,
defaultVariableFont->variantCaps,
0, 0, 0, systemFont.variantCaps);
// font-variant-east-asian: normal, enum (bit field), inherit, initial,
// -moz-system-font
SetDiscrete(*aRuleData->ValueForFontVariantEastAsian(),
aFont->mFont.variantEastAsian, aCanStoreInRuleTree,
SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
aParentFont->mFont.variantEastAsian,
defaultVariableFont->variantEastAsian,
0, 0, 0, systemFont.variantEastAsian);
// font-variant-ligatures: normal, enum (bit field), inherit, initial,
// -moz-system-font
SetDiscrete(*aRuleData->ValueForFontVariantLigatures(),
aFont->mFont.variantLigatures, aCanStoreInRuleTree,
SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
aParentFont->mFont.variantLigatures,
defaultVariableFont->variantLigatures,
0, 0, 0, systemFont.variantLigatures);
// font-variant-numeric: normal, enum (bit field), inherit, initial,
// -moz-system-font
SetDiscrete(*aRuleData->ValueForFontVariantNumeric(),
aFont->mFont.variantNumeric, aCanStoreInRuleTree,
SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
aParentFont->mFont.variantNumeric,
defaultVariableFont->variantNumeric,
0, 0, 0, systemFont.variantNumeric);
// font-variant-position: normal, enum, inherit, initial,
// -moz-system-font
SetDiscrete(*aRuleData->ValueForFontVariantPosition(),
aFont->mFont.variantPosition, aCanStoreInRuleTree,
SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
aParentFont->mFont.variantPosition,
defaultVariableFont->variantPosition,
0, 0, 0, systemFont.variantPosition);
// font-feature-settings
const nsCSSValue* featureSettingsValue =
aRuleData->ValueForFontFeatureSettings();

View File

@ -110,6 +110,7 @@ nsStyleSet::nsStyleSet()
mInShutdown(false),
mAuthorStyleDisabled(false),
mInReconstruct(false),
mInitFontFeatureValuesLookup(true),
mDirty(0),
mUnusedRuleNodeCount(0)
{
@ -1104,7 +1105,7 @@ nsStyleSet::WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc,
if (mRuleProcessors[ePresHintSheet])
(*aFunc)(mRuleProcessors[ePresHintSheet], aData);
bool cutOffInheritance = false;
if (mBindingManager) {
// We can supply additional document-level sheets that should be walked.
@ -1540,6 +1541,59 @@ nsStyleSet::AppendKeyframesRules(nsPresContext* aPresContext,
return true;
}
bool
nsStyleSet::AppendFontFeatureValuesRules(nsPresContext* aPresContext,
nsTArray<nsCSSFontFeatureValuesRule*>& aArray)
{
NS_ENSURE_FALSE(mInShutdown, false);
for (uint32_t i = 0; i < NS_ARRAY_LENGTH(gCSSSheetTypes); ++i) {
nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*>
(mRuleProcessors[gCSSSheetTypes[i]].get());
if (ruleProc &&
!ruleProc->AppendFontFeatureValuesRules(aPresContext, aArray))
{
return false;
}
}
return true;
}
already_AddRefed<gfxFontFeatureValueSet>
nsStyleSet::GetFontFeatureValuesLookup()
{
if (mInitFontFeatureValuesLookup) {
mInitFontFeatureValuesLookup = false;
nsTArray<nsCSSFontFeatureValuesRule*> rules;
AppendFontFeatureValuesRules(PresContext(), rules);
mFontFeatureValuesLookup = new gfxFontFeatureValueSet();
uint32_t i, numRules = rules.Length();
for (i = 0; i < numRules; i++) {
nsCSSFontFeatureValuesRule *rule = rules[i];
const nsTArray<nsString>& familyList = rule->GetFamilyList();
const nsTArray<gfxFontFeatureValueSet::FeatureValues>&
featureValues = rule->GetFeatureValues();
// for each family
uint32_t f, numFam;
numFam = familyList.Length();
for (f = 0; f < numFam; f++) {
const nsString& family = familyList.ElementAt(f);
nsAutoString silly(family);
mFontFeatureValuesLookup->AddFontFeatureValues(silly, featureValues);
}
}
}
nsRefPtr<gfxFontFeatureValueSet> lookup = mFontFeatureValuesLookup;
return lookup.forget();
}
bool
nsStyleSet::AppendPageRules(nsPresContext* aPresContext,
nsTArray<nsCSSPageRule*>& aArray)
@ -1812,7 +1866,7 @@ struct MOZ_STACK_CLASS AttributeData : public AttributeRuleProcessorData {
mHint(nsRestyleHint(0))
{}
nsRestyleHint mHint;
};
};
static bool
SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData)

View File

@ -23,11 +23,12 @@
#include "nsAutoPtr.h"
#include "nsIStyleRule.h"
#include "nsCSSPseudoElements.h"
#include "mozilla/Attributes.h"
#include "gfxFontFeatures.h"
class nsIURI;
class nsCSSFontFaceRule;
class nsCSSKeyframesRule;
class nsCSSFontFeatureValuesRule;
class nsCSSPageRule;
class nsRuleWalker;
struct ElementDependentRuleProcessorData;
@ -137,7 +138,7 @@ class nsStyleSet
nsCSSPseudoElements::Type aType,
nsStyleContext* aParentContext,
TreeMatchContext& aTreeMatchContext);
// Get a style context for an anonymous box. aPseudoTag is the
// pseudo-tag to use and must be non-null.
already_AddRefed<nsStyleContext>
@ -164,6 +165,14 @@ class nsStyleSet
bool AppendKeyframesRules(nsPresContext* aPresContext,
nsTArray<nsCSSKeyframesRule*>& aArray);
// Fetch object for looking up font feature values
already_AddRefed<gfxFontFeatureValueSet> GetFontFeatureValuesLookup();
// Append all the currently-active font feature values rules to aArray.
// Return true for success and false for failure.
bool AppendFontFeatureValuesRules(nsPresContext* aPresContext,
nsTArray<nsCSSFontFeatureValuesRule*>& aArray);
// Append all the currently-active page rules to aArray. Return
// true for success and false for failure.
bool AppendPageRules(nsPresContext* aPresContext,
@ -406,6 +415,7 @@ class nsStyleSet
unsigned mInShutdown : 1;
unsigned mAuthorStyleDisabled: 1;
unsigned mInReconstruct : 1;
unsigned mInitFontFeatureValuesLookup : 1;
unsigned mDirty : 9; // one dirty bit is used per sheet type
uint32_t mUnusedRuleNodeCount; // used to batch rule node GC
@ -423,6 +433,9 @@ class nsStyleSet
// BeginReconstruct and EndReconstruct, but in case of bugs that cause
// style contexts to exist too long, may last longer.
nsTArray<nsRuleNode*> mOldRuleTrees;
// whether font feature values lookup object needs initialization
nsRefPtr<gfxFontFeatureValueSet> mFontFeatureValuesLookup;
};
#ifdef _IMPL_NS_LAYOUT

View File

@ -192,6 +192,16 @@ nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont&
(aFont1.weight == aFont2.weight) &&
(aFont1.stretch == aFont2.stretch) &&
(aFont1.name == aFont2.name) &&
(aFont1.kerning == aFont2.kerning) &&
(aFont1.synthesis == aFont2.synthesis) &&
(aFont1.variantAlternates == aFont2.variantAlternates) &&
(aFont1.alternateValues == aFont2.alternateValues) &&
(aFont1.featureValueLookup == aFont2.featureValueLookup) &&
(aFont1.variantCaps == aFont2.variantCaps) &&
(aFont1.variantEastAsian == aFont2.variantEastAsian) &&
(aFont1.variantLigatures == aFont2.variantLigatures) &&
(aFont1.variantNumeric == aFont2.variantNumeric) &&
(aFont1.variantPosition == aFont2.variantPosition) &&
(aFont1.fontFeatureSettings == aFont2.fontFeatureSettings) &&
(aFont1.languageOverride == aFont2.languageOverride)) {
if ((aFont1.decorations == aFont2.decorations)) {

View File

@ -270,6 +270,118 @@ nsStyleUtil::AppendFontFeatureSettings(const nsCSSValue& aSrc,
AppendFontFeatureSettings(featureSettings, aResult);
}
/* static */ void
nsStyleUtil::GetFunctionalAlternatesName(int32_t aFeature,
nsAString& aFeatureName)
{
aFeatureName.Truncate();
nsCSSKeyword key =
nsCSSProps::ValueToKeywordEnum(aFeature,
nsCSSProps::kFontVariantAlternatesFuncsKTable);
NS_ASSERTION(key != eCSSKeyword_UNKNOWN, "bad alternate feature type");
AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(key), aFeatureName);
}
/* static */ void
nsStyleUtil::SerializeFunctionalAlternates(
const nsTArray<gfxAlternateValue>& aAlternates,
nsAString& aResult)
{
nsAutoString funcName, funcParams;
uint32_t numValues = aAlternates.Length();
uint32_t feature = 0;
for (uint32_t i = 0; i < numValues; i++) {
const gfxAlternateValue& v = aAlternates.ElementAt(i);
if (feature != v.alternate) {
feature = v.alternate;
if (!funcName.IsEmpty() && !funcParams.IsEmpty()) {
if (!aResult.IsEmpty()) {
aResult.Append(PRUnichar(' '));
}
// append the previous functional value
aResult.Append(funcName);
aResult.Append(PRUnichar('('));
aResult.Append(funcParams);
aResult.Append(PRUnichar(')'));
}
// function name
GetFunctionalAlternatesName(v.alternate, funcName);
NS_ASSERTION(!funcName.IsEmpty(), "unknown property value name");
// function params
AppendEscapedCSSIdent(v.value, funcParams);
} else {
if (!funcParams.IsEmpty()) {
funcParams.Append(NS_LITERAL_STRING(", "));
}
AppendEscapedCSSIdent(v.value, funcParams);
}
}
// append the previous functional value
if (!funcName.IsEmpty() && !funcParams.IsEmpty()) {
if (!aResult.IsEmpty()) {
aResult.Append(PRUnichar(' '));
}
aResult.Append(funcName);
aResult.Append(PRUnichar('('));
aResult.Append(funcParams);
aResult.Append(PRUnichar(')'));
}
}
/* static */ void
nsStyleUtil::ComputeFunctionalAlternates(const nsCSSValueList* aList,
nsTArray<gfxAlternateValue>& aAlternateValues)
{
gfxAlternateValue v;
aAlternateValues.Clear();
for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) {
// list contains function units
if (curr->mValue.GetUnit() != eCSSUnit_Function) {
continue;
}
// element 0 is the propval in ident form
const nsCSSValue::Array *func = curr->mValue.GetArrayValue();
// lookup propval
nsAutoString keywordStr;
func->Item(0).GetStringValue(keywordStr);
nsCSSKeyword key = nsCSSKeywords::LookupKeyword(keywordStr);
NS_ASSERTION(key != eCSSKeyword_UNKNOWN, "unknown alternate property value");
int32_t alternate;
if (key == eCSSKeyword_UNKNOWN ||
!nsCSSProps::FindKeyword(key,
nsCSSProps::kFontVariantAlternatesFuncsKTable,
alternate)) {
NS_NOTREACHED("keyword not a font-variant-alternates value");
}
v.alternate = alternate;
// other elements are the idents associated with the propval
// append one alternate value for each one
uint32_t numElems = func->Count();
for (uint32_t i = 1; i < numElems; i++) {
const nsCSSValue& value = func->Item(i);
NS_ASSERTION(value.GetUnit() == eCSSUnit_Ident,
"weird unit found in variant alternate");
if (value.GetUnit() != eCSSUnit_Ident) {
continue;
}
value.GetStringValue(v.value);
aAlternateValues.AppendElement(v);
}
}
}
/* static */ float
nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha)
{

View File

@ -7,6 +7,7 @@
#include "nsCoord.h"
#include "nsCSSProperty.h"
#include "gfxFontFeatures.h"
#include "nsIPrincipal.h"
#include "nsSubstring.h"
@ -14,6 +15,7 @@ class nsCSSValue;
class nsStringComparator;
class nsIContent;
struct gfxFontFeature;
class nsCSSValueList;
template <class E> class nsTArray;
// Style utility functions
@ -51,6 +53,20 @@ public:
static void AppendFontFeatureSettings(const nsCSSValue& src,
nsAString& aResult);
// convert bitmask value to keyword name for a functional alternate
static void GetFunctionalAlternatesName(int32_t aFeature,
nsAString& aFeatureName);
// Append functional font-variant-alternates values to string
static void
SerializeFunctionalAlternates(const nsTArray<gfxAlternateValue>& aAlternates,
nsAString& aResult);
// List of functional font-variant-alternates values to feature/value pairs
static void
ComputeFunctionalAlternates(const nsCSSValueList* aList,
nsTArray<gfxAlternateValue>& aAlternateValues);
/*
* Convert an author-provided floating point number to an integer (0
* ... 255) appropriate for use in the alpha component of a color.

View File

@ -101,6 +101,7 @@ MOCHITEST_FILES = test_acid3_test46.html \
test_dont_use_document_colors.html \
test_font_face_parser.html \
test_font_family_parsing.html \
test_font_feature_values_parsing.html \
test_garbage_at_end_of_declarations.html \
test_group_insertRule.html \
test_html_attribute_computed_values.html \

View File

@ -2491,7 +2491,7 @@ var gCSSProperties = {
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [ "small-caps" ],
invalid_values: []
invalid_values: [ "small-caps normal" ]
},
"font-weight": {
domProp: "fontWeight",
@ -4257,6 +4257,129 @@ if (SpecialPowers.getBoolPref("layout.css.flexbox.enabled")) {
gCSSProperties["display"].other_values.push("inline-flex");
}
if (SpecialPowers.getBoolPref("layout.css.font-features.enabled")) {
var fontFeatureProperties = {
"font-kerning": {
domProp: "fontKerning",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "auto" ],
other_values: [ "normal", "none" ],
invalid_values: [ "on" ]
},
"font-variant-alternates": {
domProp: "fontVariantAlternates",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [ "historical-forms",
"styleset(alt-a, alt-b)", "character-variant(a, b, c)", "annotation(circled)",
"swash(squishy)", "styleset(complex\\ blob, a)", "annotation(\\62 lah)" ],
invalid_values: [ "historical-forms normal", "historical-forms historical-forms",
"swash", "swash(3)", "annotation(a, b)", "ornaments(a,b)",
"styleset(1234blah)", "annotation(a), annotation(b)", "annotation(a) normal" ]
},
"font-variant-caps": {
domProp: "fontVariantCaps",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [ "small-caps", "all-small-caps", "petite-caps", "all-petite-caps", "titling-caps", "unicase" ],
invalid_values: [ "normal small-caps", "petite-caps normal", "unicase unicase" ]
},
"font-variant-east-asian": {
domProp: "fontVariantEastAsian",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [ "jis78", "jis83", "jis90", "jis04", "simplified", "traditional", "full-width", "proportional-width", "ruby",
"jis78 full-width", "jis78 full-width ruby", "simplified proportional-width", "ruby simplified" ],
invalid_values: [ "jis78 normal", "jis90 jis04", "simplified traditional", "full-width proportional-width",
"ruby simplified ruby", "jis78 ruby simplified" ]
},
"font-variant-ligatures": {
domProp: "fontVariantLigatures",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [ "common-ligatures", "no-common-ligatures", "discretionary-ligatures", "no-discretionary-ligatures",
"historical-ligatures", "no-historical-ligatures", "contextual", "no-contextual",
"common-ligatures no-discretionary-ligatures", "contextual no-discretionary-ligatures",
"historical-ligatures no-common-ligatures", "no-historical-ligatures discretionary-ligatures",
"common-ligatures no-discretionary-ligatures historical-ligatures no-contextual" ],
invalid_values: [ "common-ligatures normal", "common-ligatures no-common-ligatures", "common-ligatures common-ligatures",
"no-historical-ligatures historical-ligatures", "no-discretionary-ligatures discretionary-ligatures",
"no-contextual contextual", "common-ligatures no-discretionary-ligatures no-common-ligatures" ]
},
"font-variant-numeric": {
domProp: "fontVariantNumeric",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [ "lining-nums", "oldstyle-nums", "proportional-nums", "tabular-nums", "diagonal-fractions",
"stacked-fractions", "slashed-zero", "ordinal", "lining-nums diagonal-fractions",
"tabular-nums stacked-fractions", "tabular-nums slashed-zero stacked-fractions",
"proportional-nums slashed-zero diagonal-fractions oldstyle-nums ordinal" ],
invalid_values: [ "lining-nums normal", "lining-nums oldstyle-nums", "lining-nums normal slashed-zero ordinal",
"proportional-nums tabular-nums", "diagonal-fractions stacked-fractions", "slashed-zero diagonal-fractions slashed-zero",
"lining-nums slashed-zero diagonal-fractions oldstyle-nums", "diagonal-fractions diagonal-fractions" ]
},
"font-variant-position": {
domProp: "fontVariantPosition",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal" ],
other_values: [ "super", "sub" ],
invalid_values: [ "normal sub", "super sub" ]
},
"font-synthesis": {
domProp: "fontSynthesis",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "weight style" ],
other_values: [ "none", "weight", "style" ],
invalid_values: [ "weight none", "style none", "none style", "weight 10px", "weight weight", "style style" ]
},
// aliases for prefixed properties
"font-feature-settings": {
domProp: "fontFeatureSettings",
inherited: true,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "-moz-font-feature-settings",
subproperties: [ "-moz-font-feature-settings" ],
initial_values: [ "normal" ],
other_values: [
"'liga' on", "'liga'", "\"liga\" 1", "'liga', 'clig' 1",
"\"liga\" off", "\"liga\" 0", '"cv01" 3, "cv02" 4',
'"cswh", "smcp" off, "salt" 4', '"cswh" 1, "smcp" off, "salt" 4',
'"cswh" 0, \'blah\', "liga", "smcp" off, "salt" 4',
'"liga" ,"smcp" 0 , "blah"'
],
invalid_values: [
'liga', 'liga 1', 'liga normal', '"liga" normal', 'normal liga',
'normal "liga"', 'normal, "liga"', '"liga=1"', "'foobar' on",
'"blahblah" 0', '"liga" 3.14', '"liga" 1 3.14', '"liga" 1 normal',
'"liga" 1 off', '"liga" on off', '"liga" , 0 "smcp"', '"liga" "smcp"'
]
},
"font-language-override": {
domProp: "fontLanguageOverride",
inherited: true,
type: CSS_TYPE_SHORTHAND_AND_LONGHAND,
alias_for: "-moz-font-language-override",
subproperties: [ "-moz-font-language-override" ],
initial_values: [ "normal" ],
other_values: [ "'ENG'", "'TRK'", "\"TRK\"", "'N\\'Ko'" ],
invalid_values: [ "TRK", "ja" ]
}
};
for (var prop in fontFeatureProperties) {
gCSSProperties[prop] = fontFeatureProperties[prop];
}
var fontAdditions = [ "font-kerning", "font-synthesis", "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", "font-variant-position" ];
gCSSProperties["font"].subproperties = gCSSProperties["font"].subproperties.concat(fontAdditions);
}
if (SpecialPowers.getBoolPref("layout.css.masking.enabled")) {
gCSSProperties["mask-type"] = {
domProp: "maskType",

View File

@ -61,6 +61,21 @@ var all_but_one = {
"-moz-font-feature-settings": "normal", // has to be default value
"-moz-font-language-override": "normal" // has to be default value
};
if (SpecialPowers.getBoolPref("layout.css.font-features.enabled")) {
var featureDefs = {
"font-kerning": "auto", // has to be default value
"font-synthesis": "weight style", // has to be default value
"font-variant-alternates": "normal", // has to be default value
"font-variant-caps": "normal", // has to be default value
"font-variant-east-asian": "normal", // has to be default value
"font-variant-ligatures": "normal", // has to be default value
"font-variant-numeric": "normal", // has to be default value
"font-variant-position": "normal" // has to be default value
};
for (var prop in featureDefs) {
all_but_one[prop] = featureDefs[prop];
}
}
for (var prop in all_but_one) {
s.setProperty(prop, all_but_one[prop], "");
}

View File

@ -47,7 +47,13 @@ is(e.style.cssText, "font: menu; font-weight: -moz-use-system-font ! important;"
is(e.style.font, "", "font getter returns nothing");
e.setAttribute("style", "font: inherit; font-family: Helvetica;");
is(e.style.cssText, "font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: inherit; line-height: inherit; font-size-adjust: inherit; font-stretch: inherit; -moz-font-feature-settings: inherit; -moz-font-language-override: inherit; font-family: Helvetica;", "don't serialize system font for font:inherit");
var cssTextStr = "font-style: inherit; font-variant: inherit; font-weight: inherit; font-size: inherit; line-height: inherit; font-size-adjust: inherit; font-stretch: inherit; -moz-font-feature-settings: inherit; -moz-font-language-override: inherit;";
if (SpecialPowers.getBoolPref("layout.css.font-features.enabled")) {
cssTextStr += " font-kerning: inherit; font-synthesis: inherit; font-variant-alternates: inherit; font-variant-caps: inherit; font-variant-east-asian: inherit; font-variant-ligatures: inherit; font-variant-numeric: inherit; font-variant-position: inherit;"
}
is(e.style.cssText, cssTextStr + " font-family: Helvetica;", "don't serialize system font for font:inherit");
is(e.style.font, "", "font getter returns nothing");
</script>

View File

@ -1739,6 +1739,19 @@ pref("layout.css.supports-rule.enabled", true);
// Is support for CSS Flexbox enabled?
pref("layout.css.flexbox.enabled", true);
// Is support for CSS3 Fonts features enabled?
// (includes font-variant-*, font-kerning, font-synthesis
// and the @font-feature-values rule)
// Note: with this enabled, font-feature-settings is aliased
// to -moz-font-feature-settings. When unprefixing, this should
// be reversed, -moz-font-feature-settings should alias to
// font-feature-settings.
#ifdef RELEASE_BUILD
pref("layout.css.font-features.enabled", false);
#else
pref("layout.css.font-features.enabled", true);
#endif
// Are sets of prefixed properties supported?
pref("layout.css.prefixes.border-image", true);
pref("layout.css.prefixes.transforms", true);