зеркало из https://github.com/mozilla/gecko-dev.git
Bug 961558 - add fallback support for font-variant-caps values. r=jfkthame
This commit is contained in:
Родитель
516d813bbb
Коммит
b69e91abce
|
@ -275,38 +275,13 @@ void nsFont::AddFontFeaturesToStyle(gfxFontStyle *aStyle) const
|
|||
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;
|
||||
// passed into gfxFontStyle to deal with appropriate fallback.
|
||||
// for now, font-variant setting overrides font-variant-caps
|
||||
// when font-variant becomes a shorthand, this will be removed
|
||||
if (variant == NS_FONT_VARIANT_SMALL_CAPS) {
|
||||
aStyle->variantCaps = NS_FONT_VARIANT_CAPS_SMALLCAPS;
|
||||
} else {
|
||||
aStyle->variantCaps = variantCaps;
|
||||
}
|
||||
|
||||
// -- east-asian
|
||||
|
|
|
@ -125,7 +125,6 @@ gfxFontEntry::gfxFontEntry() :
|
|||
mHasSpaceFeaturesNonKerning(false),
|
||||
mSkipDefaultFeatureSpaceCheck(false),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mCheckedForGraphiteSmallCaps(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
mCheckedForColorGlyph(false),
|
||||
|
@ -159,7 +158,6 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) :
|
|||
mHasSpaceFeaturesNonKerning(false),
|
||||
mSkipDefaultFeatureSpaceCheck(false),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mCheckedForGraphiteSmallCaps(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
mCheckedForColorGlyph(false),
|
||||
|
@ -883,15 +881,36 @@ gfxFontEntry::CheckForGraphiteTables()
|
|||
mHasGraphiteTables = HasFontTable(TRUETYPE_TAG('S','i','l','f'));
|
||||
}
|
||||
|
||||
|
||||
#define FEATURE_SCRIPT_MASK 0x000000ff // script index replaces low byte of tag
|
||||
|
||||
// check for too many script codes
|
||||
PR_STATIC_ASSERT(MOZ_NUM_SCRIPT_CODES <= FEATURE_SCRIPT_MASK);
|
||||
|
||||
// high-order three bytes of tag with script in low-order byte
|
||||
#define SCRIPT_FEATURE(s,tag) (((~FEATURE_SCRIPT_MASK) & (tag)) | \
|
||||
((FEATURE_SCRIPT_MASK) & (s)))
|
||||
|
||||
bool
|
||||
gfxFontEntry::SupportsOpenTypeSmallCaps(int32_t aScript)
|
||||
gfxFontEntry::SupportsOpenTypeFeature(int32_t aScript, uint32_t aFeatureTag)
|
||||
{
|
||||
if (!mSmallCapsSupport) {
|
||||
mSmallCapsSupport = new nsDataHashtable<nsUint32HashKey,bool>();
|
||||
if (!mSupportedFeatures) {
|
||||
mSupportedFeatures = new nsDataHashtable<nsUint32HashKey,bool>();
|
||||
}
|
||||
|
||||
NS_ASSERTION(aFeatureTag == HB_TAG('s','m','c','p') ||
|
||||
aFeatureTag == HB_TAG('c','2','s','c') ||
|
||||
aFeatureTag == HB_TAG('p','c','a','p') ||
|
||||
aFeatureTag == HB_TAG('c','2','p','c'),
|
||||
"use of unknown feature tag");
|
||||
|
||||
// note: graphite feature support uses the last script index
|
||||
NS_ASSERTION(aScript < FEATURE_SCRIPT_MASK - 1,
|
||||
"need to bump the size of the feature shift");
|
||||
|
||||
uint32_t scriptFeature = SCRIPT_FEATURE(aScript, aFeatureTag);
|
||||
bool result;
|
||||
if (mSmallCapsSupport->Get(uint32_t(aScript), &result)) {
|
||||
if (mSupportedFeatures->Get(scriptFeature, &result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -928,7 +947,6 @@ gfxFontEntry::SupportsOpenTypeSmallCaps(int32_t aScript)
|
|||
|
||||
// Now check for 'smcp' under the first of those scripts that is present
|
||||
const hb_tag_t kGSUB = HB_TAG('G','S','U','B');
|
||||
const hb_tag_t kSMCP = HB_TAG('s','m','c','p');
|
||||
scriptTag = &scriptTags[0];
|
||||
while (*scriptTag != HB_TAG_NONE) {
|
||||
unsigned int scriptIndex;
|
||||
|
@ -937,7 +955,7 @@ gfxFontEntry::SupportsOpenTypeSmallCaps(int32_t aScript)
|
|||
if (hb_ot_layout_language_find_feature(face, kGSUB,
|
||||
scriptIndex,
|
||||
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
|
||||
kSMCP, nullptr)) {
|
||||
aFeatureTag, nullptr)) {
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
|
@ -948,22 +966,38 @@ gfxFontEntry::SupportsOpenTypeSmallCaps(int32_t aScript)
|
|||
|
||||
hb_face_destroy(face);
|
||||
|
||||
mSmallCapsSupport->Put(uint32_t(aScript), result);
|
||||
mSupportedFeatures->Put(scriptFeature, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFontEntry::SupportsGraphiteSmallCaps()
|
||||
gfxFontEntry::SupportsGraphiteFeature(uint32_t aFeatureTag)
|
||||
{
|
||||
if (!mCheckedForGraphiteSmallCaps) {
|
||||
gr_face* face = GetGrFace();
|
||||
mHasGraphiteSmallCaps =
|
||||
gr_face_find_fref(face, TRUETYPE_TAG('s','m','c','p')) != nullptr;
|
||||
ReleaseGrFace(face);
|
||||
mCheckedForGraphiteSmallCaps = true;
|
||||
if (!mSupportedFeatures) {
|
||||
mSupportedFeatures = new nsDataHashtable<nsUint32HashKey,bool>();
|
||||
}
|
||||
return mHasGraphiteSmallCaps;
|
||||
|
||||
NS_ASSERTION(aFeatureTag == HB_TAG('s','m','c','p') ||
|
||||
aFeatureTag == HB_TAG('c','2','s','c') ||
|
||||
aFeatureTag == HB_TAG('p','c','a','p') ||
|
||||
aFeatureTag == HB_TAG('c','2','p','c'),
|
||||
"use of unknown feature tag");
|
||||
|
||||
// graphite feature check uses the last script slot
|
||||
uint32_t scriptFeature = SCRIPT_FEATURE(FEATURE_SCRIPT_MASK, aFeatureTag);
|
||||
bool result;
|
||||
if (mSupportedFeatures->Get(scriptFeature, &result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
gr_face* face = GetGrFace();
|
||||
result = gr_face_find_fref(face, aFeatureTag) != nullptr;
|
||||
ReleaseGrFace(face);
|
||||
|
||||
mSupportedFeatures->Put(scriptFeature, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2091,6 +2125,7 @@ gfxFontShaper::MergeFontFeatures(
|
|||
const nsTArray<gfxFontFeature>& aFontFeatures,
|
||||
bool aDisableLigatures,
|
||||
const nsAString& aFamilyName,
|
||||
bool aAddSmallCaps,
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures)
|
||||
{
|
||||
uint32_t numAlts = aStyle->alternateValues.Length();
|
||||
|
@ -2102,6 +2137,7 @@ gfxFontShaper::MergeFontFeatures(
|
|||
aFontFeatures.IsEmpty() &&
|
||||
!aDisableLigatures &&
|
||||
!aStyle->smallCaps &&
|
||||
aStyle->variantCaps == NS_FONT_VARIANT_CAPS_NORMAL &&
|
||||
numAlts == 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2113,10 +2149,6 @@ gfxFontShaper::MergeFontFeatures(
|
|||
aMergedFeatures.Put(HB_TAG('c','l','i','g'), 0);
|
||||
}
|
||||
|
||||
if (aStyle->smallCaps) {
|
||||
aMergedFeatures.Put(HB_TAG('s','m','c','p'), 1);
|
||||
}
|
||||
|
||||
// add feature values from font
|
||||
uint32_t i, count;
|
||||
|
||||
|
@ -2126,6 +2158,38 @@ gfxFontShaper::MergeFontFeatures(
|
|||
aMergedFeatures.Put(feature.mTag, feature.mValue);
|
||||
}
|
||||
|
||||
// font-variant-caps - handled here due to the need for fallback handling
|
||||
// petite caps cases can fallback to appropriate smallcaps
|
||||
uint32_t variantCaps = aStyle->variantCaps;
|
||||
switch (variantCaps) {
|
||||
case NS_FONT_VARIANT_CAPS_ALLSMALL:
|
||||
aMergedFeatures.Put(HB_TAG('c','2','s','c'), 1);
|
||||
// fall through to the small-caps case
|
||||
case NS_FONT_VARIANT_CAPS_SMALLCAPS:
|
||||
aMergedFeatures.Put(HB_TAG('s','m','c','p'), 1);
|
||||
break;
|
||||
|
||||
case NS_FONT_VARIANT_CAPS_ALLPETITE:
|
||||
aMergedFeatures.Put(aAddSmallCaps ? HB_TAG('c','2','s','c') :
|
||||
HB_TAG('c','2','p','c'), 1);
|
||||
// fall through to the petite-caps case
|
||||
case NS_FONT_VARIANT_CAPS_PETITECAPS:
|
||||
aMergedFeatures.Put(aAddSmallCaps ? HB_TAG('s','m','c','p') :
|
||||
HB_TAG('p','c','a','p'), 1);
|
||||
break;
|
||||
|
||||
case NS_FONT_VARIANT_CAPS_TITLING:
|
||||
aMergedFeatures.Put(HB_TAG('t','i','t','l'), 1);
|
||||
break;
|
||||
|
||||
case NS_FONT_VARIANT_CAPS_UNICASE:
|
||||
aMergedFeatures.Put(HB_TAG('u','n','i','c'), 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// add font-specific feature values from style rules
|
||||
if (aStyle->featureValueLookup && numAlts > 0) {
|
||||
nsAutoTArray<gfxFontFeature,4> featureList;
|
||||
|
@ -2704,13 +2768,75 @@ gfxFont::SpaceMayParticipateInShaping(int32_t aRunScript)
|
|||
}
|
||||
|
||||
bool
|
||||
gfxFont::SupportsSmallCaps(int32_t aScript)
|
||||
gfxFont::SupportsFeature(int32_t aScript, uint32_t aFeatureTag)
|
||||
{
|
||||
if (mGraphiteShaper && gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
|
||||
return GetFontEntry()->SupportsGraphiteSmallCaps();
|
||||
return GetFontEntry()->SupportsGraphiteFeature(aFeatureTag);
|
||||
}
|
||||
return GetFontEntry()->SupportsOpenTypeFeature(aScript, aFeatureTag);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFont::SupportsVariantCaps(int32_t aScript,
|
||||
uint32_t aVariantCaps,
|
||||
bool& aFallbackToSmallCaps,
|
||||
bool& aSyntheticLowerToSmallCaps,
|
||||
bool& aSyntheticUpperToSmallCaps)
|
||||
{
|
||||
bool ok = true; // cases without fallback are fine
|
||||
aFallbackToSmallCaps = false;
|
||||
aSyntheticLowerToSmallCaps = false;
|
||||
aSyntheticUpperToSmallCaps = false;
|
||||
switch (aVariantCaps) {
|
||||
case NS_FONT_VARIANT_CAPS_SMALLCAPS:
|
||||
ok = SupportsFeature(aScript, HB_TAG('s','m','c','p'));
|
||||
if (!ok) {
|
||||
aSyntheticLowerToSmallCaps = true;
|
||||
}
|
||||
break;
|
||||
case NS_FONT_VARIANT_CAPS_ALLSMALL:
|
||||
ok = SupportsFeature(aScript, HB_TAG('s','m','c','p')) &&
|
||||
SupportsFeature(aScript, HB_TAG('c','2','s','c'));
|
||||
if (!ok) {
|
||||
aSyntheticLowerToSmallCaps = true;
|
||||
aSyntheticUpperToSmallCaps = true;
|
||||
}
|
||||
break;
|
||||
case NS_FONT_VARIANT_CAPS_PETITECAPS:
|
||||
ok = SupportsFeature(aScript, HB_TAG('p','c','a','p'));
|
||||
if (!ok) {
|
||||
ok = SupportsFeature(aScript, HB_TAG('s','m','c','p'));
|
||||
aFallbackToSmallCaps = ok;
|
||||
}
|
||||
if (!ok) {
|
||||
aSyntheticLowerToSmallCaps = true;
|
||||
}
|
||||
break;
|
||||
case NS_FONT_VARIANT_CAPS_ALLPETITE:
|
||||
ok = SupportsFeature(aScript, HB_TAG('p','c','a','p')) &&
|
||||
SupportsFeature(aScript, HB_TAG('c','2','p','c'));
|
||||
if (!ok) {
|
||||
ok = SupportsFeature(aScript, HB_TAG('s','m','c','p')) &&
|
||||
SupportsFeature(aScript, HB_TAG('c','2','s','c'));
|
||||
aFallbackToSmallCaps = ok;
|
||||
}
|
||||
if (!ok) {
|
||||
aSyntheticLowerToSmallCaps = true;
|
||||
aSyntheticUpperToSmallCaps = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GetFontEntry()->SupportsOpenTypeSmallCaps(aScript);
|
||||
NS_ASSERTION(!(ok && (aSyntheticLowerToSmallCaps ||
|
||||
aSyntheticUpperToSmallCaps)),
|
||||
"shouldn't use synthetic features if we found real ones");
|
||||
|
||||
NS_ASSERTION(!(!ok && aFallbackToSmallCaps),
|
||||
"if we found a usable fallback, that counts as ok");
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -5490,14 +5616,28 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
|
|||
|
||||
// create the glyph run for this range
|
||||
if (matchedFont) {
|
||||
if (mStyle.smallCaps &&
|
||||
!matchedFont->SupportsSmallCaps(aRunScript)) {
|
||||
bool needsFakeSmallCaps = false;
|
||||
bool petiteToSmallCaps = false;
|
||||
bool syntheticLower = false;
|
||||
bool syntheticUpper = false;
|
||||
|
||||
if (mStyle.smallCaps ||
|
||||
mStyle.variantCaps != NS_FONT_VARIANT_CAPS_NORMAL) {
|
||||
needsFakeSmallCaps =
|
||||
!matchedFont->SupportsVariantCaps(aRunScript,
|
||||
(mStyle.smallCaps ? NS_FONT_VARIANT_CAPS_SMALLCAPS :
|
||||
mStyle.variantCaps),
|
||||
petiteToSmallCaps, syntheticLower, syntheticUpper);
|
||||
}
|
||||
if (needsFakeSmallCaps) {
|
||||
if (!matchedFont->InitFakeSmallCapsRun(aContext, aTextRun,
|
||||
aString + runStart,
|
||||
aOffset + runStart,
|
||||
matchedLength,
|
||||
range.matchType,
|
||||
aRunScript)) {
|
||||
aRunScript,
|
||||
syntheticLower,
|
||||
syntheticUpper)) {
|
||||
matchedFont = nullptr;
|
||||
}
|
||||
} else {
|
||||
|
@ -5602,12 +5742,15 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
|
|||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
uint8_t aMatchType,
|
||||
int32_t aScript)
|
||||
int32_t aScript,
|
||||
bool aSyntheticLower,
|
||||
bool aSyntheticUpper)
|
||||
{
|
||||
NS_ConvertASCIItoUTF16 unicodeString(reinterpret_cast<const char*>(aText),
|
||||
aLength);
|
||||
return InitFakeSmallCapsRun(aContext, aTextRun, unicodeString.get(),
|
||||
aOffset, aLength, aMatchType, aScript);
|
||||
aOffset, aLength, aMatchType, aScript,
|
||||
aSyntheticLower, aSyntheticUpper);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -5617,22 +5760,25 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
|
|||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
uint8_t aMatchType,
|
||||
int32_t aScript)
|
||||
int32_t aScript,
|
||||
bool aSyntheticLower,
|
||||
bool aSyntheticUpper)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
nsRefPtr<gfxFont> smallCapsFont = GetSmallCapsFont();
|
||||
|
||||
enum RunCaseState {
|
||||
kUpperOrCaseless, // will be untouched by font-variant:small-caps
|
||||
kLowercase, // will be uppercased and reduced
|
||||
kSpecialUpper // specials: don't shrink, but apply uppercase mapping
|
||||
enum RunCaseAction {
|
||||
kNoChange,
|
||||
kUppercaseReduce,
|
||||
kUppercase
|
||||
};
|
||||
RunCaseState runCase = kUpperOrCaseless;
|
||||
|
||||
RunCaseAction runAction = kNoChange;
|
||||
uint32_t runStart = 0;
|
||||
|
||||
for (uint32_t i = 0; i <= aLength; ++i) {
|
||||
RunCaseState chCase = kUpperOrCaseless;
|
||||
RunCaseAction chAction = kNoChange;
|
||||
// Unless we're at the end, figure out what treatment the current
|
||||
// character will need.
|
||||
if (i < aLength) {
|
||||
|
@ -5644,22 +5790,25 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
|
|||
// Characters that aren't the start of a cluster are ignored here.
|
||||
// They get added to whatever lowercase/non-lowercase run we're in.
|
||||
if (IsClusterExtender(ch)) {
|
||||
chCase = runCase;
|
||||
chAction = runAction;
|
||||
} else {
|
||||
uint32_t ch2 = ToUpperCase(ch);
|
||||
if (ch != ch2 || mozilla::unicode::SpecialUpper(ch)) {
|
||||
chCase = kLowercase;
|
||||
}
|
||||
else if (mStyle.language == nsGkAtoms::el) {
|
||||
if (ch != ToUpperCase(ch) || mozilla::unicode::SpecialUpper(ch)) {
|
||||
// ch is lower case
|
||||
chAction = (aSyntheticLower ? kUppercaseReduce : kNoChange);
|
||||
} else if (ch != ToLowerCase(ch)) {
|
||||
// ch is upper case
|
||||
chAction = (aSyntheticUpper ? kUppercaseReduce : kNoChange);
|
||||
if (mStyle.language == nsGkAtoms::el) {
|
||||
// In Greek, check for characters that will be modified by
|
||||
// the GreekUpperCase mapping - this catches accented
|
||||
// capitals where the accent is to be removed (bug 307039).
|
||||
// These are handled by using the full-size font with the
|
||||
// uppercasing transform.
|
||||
mozilla::GreekCasing::State state;
|
||||
ch2 = mozilla::GreekCasing::UpperCase(ch, state);
|
||||
if (ch != ch2) {
|
||||
chCase = kSpecialUpper;
|
||||
uint32_t ch2 = mozilla::GreekCasing::UpperCase(ch, state);
|
||||
if (ch != ch2 && !aSyntheticUpper) {
|
||||
chAction = kUppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5670,11 +5819,11 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
|
|||
// and prepare to accumulate a new run.
|
||||
// Note that we do not look at any source data for offset [i] here,
|
||||
// as that would be invalid in the case where i==length.
|
||||
if ((i == aLength || runCase != chCase) && runStart < i) {
|
||||
if ((i == aLength || runAction != chAction) && runStart < i) {
|
||||
uint32_t runLength = i - runStart;
|
||||
gfxFont* f = this;
|
||||
switch (runCase) {
|
||||
case kUpperOrCaseless:
|
||||
switch (runAction) {
|
||||
case kNoChange:
|
||||
// just use the current font and the existing string
|
||||
aTextRun->AddGlyphRun(f, aMatchType, aOffset + runStart, true);
|
||||
if (!f->SplitAndInitTextRun(aContext, aTextRun,
|
||||
|
@ -5685,11 +5834,11 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
|
|||
}
|
||||
break;
|
||||
|
||||
case kLowercase:
|
||||
// use reduced-size font, fall through to uppercase the text
|
||||
case kUppercaseReduce:
|
||||
// use reduced-size font, then fall through to uppercase the text
|
||||
f = smallCapsFont;
|
||||
|
||||
case kSpecialUpper:
|
||||
case kUppercase:
|
||||
// apply uppercase transform to the string
|
||||
nsDependentSubstring origString(aText + runStart, runLength);
|
||||
nsAutoString convertedString;
|
||||
|
@ -5751,7 +5900,7 @@ gfxFont::InitFakeSmallCapsRun(gfxContext *aContext,
|
|||
}
|
||||
|
||||
if (i < aLength) {
|
||||
runCase = chCase;
|
||||
runAction = chAction;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5764,6 +5913,7 @@ gfxFont::GetSmallCapsFont()
|
|||
gfxFontStyle style(*GetStyle());
|
||||
style.size *= SMALL_CAPS_SCALE_FACTOR;
|
||||
style.smallCaps = false;
|
||||
style.variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
|
||||
gfxFontEntry* fe = GetFontEntry();
|
||||
bool needsBold = style.weight >= 600 && !fe->IsBold();
|
||||
return fe->FindOrMakeFont(&style, needsBold);
|
||||
|
@ -6212,8 +6362,10 @@ gfxFontStyle::gfxFontStyle() :
|
|||
languageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||
weight(NS_FONT_WEIGHT_NORMAL), stretch(NS_FONT_STRETCH_NORMAL),
|
||||
systemFont(true), printerFont(false), useGrayscaleAntialiasing(false),
|
||||
smallCaps(false), allowSyntheticWeight(true), allowSyntheticStyle(true),
|
||||
style(NS_FONT_STYLE_NORMAL)
|
||||
style(NS_FONT_STYLE_NORMAL),
|
||||
allowSyntheticWeight(true), allowSyntheticStyle(true),
|
||||
smallCaps(false),
|
||||
variantCaps(NS_FONT_VARIANT_CAPS_NORMAL)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -6230,10 +6382,11 @@ gfxFontStyle::gfxFontStyle(uint8_t aStyle, uint16_t aWeight, int16_t aStretch,
|
|||
weight(aWeight), stretch(aStretch),
|
||||
systemFont(aSystemFont), printerFont(aPrinterFont),
|
||||
useGrayscaleAntialiasing(false),
|
||||
smallCaps(aSmallCaps),
|
||||
style(aStyle),
|
||||
allowSyntheticWeight(aAllowWeightSynthesis),
|
||||
allowSyntheticStyle(aAllowStyleSynthesis),
|
||||
style(aStyle)
|
||||
smallCaps(aSmallCaps),
|
||||
variantCaps(NS_FONT_VARIANT_CAPS_NORMAL)
|
||||
{
|
||||
MOZ_ASSERT(!mozilla::IsNaN(size));
|
||||
MOZ_ASSERT(!mozilla::IsNaN(sizeAdjust));
|
||||
|
@ -6265,10 +6418,11 @@ gfxFontStyle::gfxFontStyle(const gfxFontStyle& aStyle) :
|
|||
weight(aStyle.weight), stretch(aStyle.stretch),
|
||||
systemFont(aStyle.systemFont), printerFont(aStyle.printerFont),
|
||||
useGrayscaleAntialiasing(aStyle.useGrayscaleAntialiasing),
|
||||
smallCaps(aStyle.smallCaps),
|
||||
style(aStyle.style),
|
||||
allowSyntheticWeight(aStyle.allowSyntheticWeight),
|
||||
allowSyntheticStyle(aStyle.allowSyntheticStyle),
|
||||
style(aStyle.style)
|
||||
smallCaps(aStyle.smallCaps),
|
||||
variantCaps(aStyle.variantCaps)
|
||||
{
|
||||
featureSettings.AppendElements(aStyle.featureSettings);
|
||||
alternateValues.AppendElements(aStyle.alternateValues);
|
||||
|
|
|
@ -143,16 +143,20 @@ struct gfxFontStyle {
|
|||
// Used to imitate -webkit-font-smoothing: antialiased
|
||||
bool useGrayscaleAntialiasing : 1;
|
||||
|
||||
// Font should render as small-caps, using OT feature if available,
|
||||
// otherwise using a synthetic small-caps implementation
|
||||
bool smallCaps : 1;
|
||||
// The style of font (normal, italic, oblique)
|
||||
uint8_t style : 2;
|
||||
|
||||
// Whether synthetic styles are allowed
|
||||
bool allowSyntheticWeight : 1;
|
||||
bool allowSyntheticStyle : 1;
|
||||
|
||||
// The style of font (normal, italic, oblique)
|
||||
uint8_t style : 2;
|
||||
// font-variant small-caps? render with font feature or use synthetic
|
||||
// xxx - this will be trimmed out once font-variant becomes a shorthand
|
||||
bool smallCaps : 1;
|
||||
|
||||
// caps variant (small-caps, petite-caps, etc.)
|
||||
// (note: once font features are enabled this will subsume the bool above)
|
||||
uint8_t variantCaps;
|
||||
|
||||
// Return the final adjusted font size for the given aspect ratio.
|
||||
// Not meant to be called when sizeAdjust = 0.
|
||||
|
@ -176,6 +180,7 @@ struct gfxFontStyle {
|
|||
*reinterpret_cast<const uint64_t*>(&other.size)) &&
|
||||
(style == other.style) &&
|
||||
(smallCaps == other.smallCaps) &&
|
||||
(variantCaps == other.variantCaps) &&
|
||||
(allowSyntheticWeight == other.allowSyntheticWeight) &&
|
||||
(allowSyntheticStyle == other.allowSyntheticStyle) &&
|
||||
(systemFont == other.systemFont) &&
|
||||
|
@ -281,8 +286,10 @@ public:
|
|||
bool IgnoreGDEF() const { return mIgnoreGDEF; }
|
||||
bool IgnoreGSUB() const { return mIgnoreGSUB; }
|
||||
|
||||
bool SupportsOpenTypeSmallCaps(int32_t aScript);
|
||||
bool SupportsGraphiteSmallCaps();
|
||||
// whether a feature is supported by the font (limited to a small set
|
||||
// of features for which some form of fallback needs to be implemented)
|
||||
bool SupportsOpenTypeFeature(int32_t aScript, uint32_t aFeatureTag);
|
||||
bool SupportsGraphiteFeature(uint32_t aFeatureTag);
|
||||
|
||||
virtual bool IsSymbolFont();
|
||||
|
||||
|
@ -552,8 +559,6 @@ public:
|
|||
bool mSkipDefaultFeatureSpaceCheck : 1;
|
||||
bool mHasGraphiteTables : 1;
|
||||
bool mCheckedForGraphiteTables : 1;
|
||||
bool mHasGraphiteSmallCaps : 1;
|
||||
bool mCheckedForGraphiteSmallCaps : 1;
|
||||
bool mHasCmapTable : 1;
|
||||
bool mGrFaceInitialized : 1;
|
||||
bool mCheckedForColorGlyph : 1;
|
||||
|
@ -575,7 +580,7 @@ public:
|
|||
nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
|
||||
nsAutoPtr<gfxMathTable> mMathTable;
|
||||
nsTArray<gfxFontFeature> mFeatureSettings;
|
||||
nsAutoPtr<nsDataHashtable<nsUint32HashKey,bool>> mSmallCapsSupport;
|
||||
nsAutoPtr<nsDataHashtable<nsUint32HashKey,bool>> mSupportedFeatures;
|
||||
uint32_t mLanguageOverride;
|
||||
|
||||
// Color Layer font support
|
||||
|
@ -1493,6 +1498,7 @@ public:
|
|||
const nsTArray<gfxFontFeature>& aFontFeatures,
|
||||
bool aDisableLigatures,
|
||||
const nsAString& aFamilyName,
|
||||
bool aAddSmallCaps,
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t>& aMergedFeatures);
|
||||
|
||||
protected:
|
||||
|
@ -1622,8 +1628,16 @@ public:
|
|||
return mFontEntry->HasGraphiteTables();
|
||||
}
|
||||
|
||||
// whether the font supports "real" small caps or should fake them
|
||||
bool SupportsSmallCaps(int32_t aScript);
|
||||
// whether a feature is supported by the font (limited to a small set
|
||||
// of features for which some form of fallback needs to be implemented)
|
||||
bool SupportsFeature(int32_t aScript, uint32_t aFeatureTag);
|
||||
|
||||
// whether the font supports "real" small caps, petite caps etc.
|
||||
// aFallbackToSmallCaps true when petite caps should fallback to small caps
|
||||
bool SupportsVariantCaps(int32_t aScript, uint32_t aVariantCaps,
|
||||
bool& aFallbackToSmallCaps,
|
||||
bool& aSyntheticLowerToSmallCaps,
|
||||
bool& aSyntheticUpperToSmallCaps);
|
||||
|
||||
// Subclasses may choose to look up glyph ids for characters.
|
||||
// If they do not override this, gfxHarfBuzzShaper will fetch the cmap
|
||||
|
@ -1831,7 +1845,9 @@ public:
|
|||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
uint8_t aMatchType,
|
||||
int32_t aScript);
|
||||
int32_t aScript,
|
||||
bool aSyntheticLower,
|
||||
bool aSyntheticUpper);
|
||||
|
||||
bool InitFakeSmallCapsRun(gfxContext *aContext,
|
||||
gfxTextRun *aTextRun,
|
||||
|
@ -1839,7 +1855,9 @@ public:
|
|||
uint32_t aOffset,
|
||||
uint32_t aLength,
|
||||
uint8_t aMatchType,
|
||||
int32_t aScript);
|
||||
int32_t aScript,
|
||||
bool aSyntheticLower,
|
||||
bool aSyntheticUpper);
|
||||
|
||||
// call the (virtual) InitTextRun method to do glyph generation/shaping,
|
||||
// limiting the length of text passed by processing the run in multiple
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "gfxGraphiteShaper.h"
|
||||
#include "nsString.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxFontConstants.h"
|
||||
|
||||
#include "graphite2/Font.h"
|
||||
#include "graphite2/Segment.h"
|
||||
|
@ -29,7 +30,7 @@ using namespace mozilla; // for AutoSwap_* types
|
|||
gfxGraphiteShaper::gfxGraphiteShaper(gfxFont *aFont)
|
||||
: gfxFontShaper(aFont),
|
||||
mGrFace(mFont->GetFontEntry()->GetGrFace()),
|
||||
mGrFont(nullptr)
|
||||
mGrFont(nullptr), mFallbackToSmallCaps(false)
|
||||
{
|
||||
mCallbackData.mFont = aFont;
|
||||
mCallbackData.mShaper = this;
|
||||
|
@ -96,6 +97,8 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
|
|||
|
||||
mCallbackData.mContext = aContext;
|
||||
|
||||
const gfxFontStyle *style = mFont->GetStyle();
|
||||
|
||||
if (!mGrFont) {
|
||||
if (!mGrFace) {
|
||||
return false;
|
||||
|
@ -116,10 +119,24 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
|
|||
if (!mGrFont) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// determine whether petite-caps falls back to small-caps
|
||||
if (style->variantCaps != NS_FONT_VARIANT_CAPS_NORMAL) {
|
||||
switch (style->variantCaps) {
|
||||
case NS_FONT_VARIANT_CAPS_ALLPETITE:
|
||||
case NS_FONT_VARIANT_CAPS_PETITECAPS:
|
||||
bool synLower, synUpper;
|
||||
mFont->SupportsVariantCaps(aScript, style->variantCaps,
|
||||
mFallbackToSmallCaps, synLower,
|
||||
synUpper);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfxFontEntry *entry = mFont->GetFontEntry();
|
||||
const gfxFontStyle *style = mFont->GetStyle();
|
||||
uint32_t grLang = 0;
|
||||
if (style->languageOverride) {
|
||||
grLang = MakeGraphiteLangTag(style->languageOverride);
|
||||
|
@ -132,13 +149,14 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
|
|||
}
|
||||
gr_feature_val *grFeatures = gr_face_featureval_for_lang(mGrFace, grLang);
|
||||
|
||||
// if style contains font-specific features
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
|
||||
|
||||
// if style contains font-specific features
|
||||
if (MergeFontFeatures(style,
|
||||
mFont->GetFontEntry()->mFeatureSettings,
|
||||
aShapedText->DisableLigatures(),
|
||||
mFont->GetFontEntry()->FamilyName(),
|
||||
mFallbackToSmallCaps,
|
||||
mergedFeatures))
|
||||
{
|
||||
// enumerate result and insert into Graphite feature list
|
||||
|
|
|
@ -47,6 +47,7 @@ protected:
|
|||
};
|
||||
|
||||
CallbackData mCallbackData;
|
||||
bool mFallbackToSmallCaps; // special fallback for the petite-caps case
|
||||
|
||||
// Convert HTML 'lang' (BCP47) to Graphite language code
|
||||
static uint32_t GetGraphiteTagForLang(const nsCString& aLang);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "nsString.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxFontConstants.h"
|
||||
#include "gfxHarfBuzzShaper.h"
|
||||
#include "gfxFontUtils.h"
|
||||
#include "nsUnicodeProperties.h"
|
||||
|
@ -967,11 +968,27 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
|||
nsAutoTArray<hb_feature_t,20> features;
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
|
||||
|
||||
// determine whether petite-caps falls back to small-caps
|
||||
bool addSmallCaps = false;
|
||||
if (style->variantCaps != NS_FONT_VARIANT_CAPS_NORMAL) {
|
||||
switch (style->variantCaps) {
|
||||
case NS_FONT_VARIANT_CAPS_ALLPETITE:
|
||||
case NS_FONT_VARIANT_CAPS_PETITECAPS:
|
||||
bool synLower, synUpper;
|
||||
mFont->SupportsVariantCaps(aScript, style->variantCaps,
|
||||
addSmallCaps, synLower, synUpper);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gfxFontEntry *entry = mFont->GetFontEntry();
|
||||
if (MergeFontFeatures(style,
|
||||
entry->mFeatureSettings,
|
||||
aShapedText->DisableLigatures(),
|
||||
entry->FamilyName(),
|
||||
addSmallCaps,
|
||||
mergedFeatures))
|
||||
{
|
||||
// enumerate result and insert into hb_feature array
|
||||
|
|
Загрузка…
Ссылка в новой задаче