author | Jonathan Kew <jkew@mozilla.com> |
Wed, 25 Apr 2018 10:18:07 +0100 | |
changeset 415623 | aa4185068f2e3ffb1377afa0e0d95b3c5ac0a04c |
parent 415622 | ff274dd24756e046c25bf37451fa77286c7ce737 |
child 415624 | 6696fd50114a8c105771f1e87e0b76cbf5761c26 |
push id | 33901 |
push user | apavel@mozilla.com |
push date | Thu, 26 Apr 2018 06:05:37 +0000 |
treeherder | mozilla-central@b62ad926cf2a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1454598 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/accessible/base/TextAttrs.cpp +++ b/accessible/base/TextAttrs.cpp @@ -651,20 +651,19 @@ TextAttrsMgr::FontWeightTextAttr:: return FontWeight::Bold(); } // On Windows, font->GetStyle()->weight will give the same weight as // fontEntry->Weight(), the weight of the first font in the font group, // which may not be the weight of the font face used to render the // characters. On Mac, font->GetStyle()->weight will just give the same // number as getComputedStyle(). fontEntry->Weight() will give the weight - // range supported by the font face used, so we clamp the weight that was - // requested by style to what is actually supported by the font. + // of the font face used. gfxFontEntry *fontEntry = font->GetFontEntry(); - return fontEntry->Weight().Clamp(font->GetStyle()->weight); + return fontEntry->Weight(); } //////////////////////////////////////////////////////////////////////////////// // AutoGeneratedTextAttr //////////////////////////////////////////////////////////////////////////////// TextAttrsMgr::AutoGeneratedTextAttr:: AutoGeneratedTextAttr(HyperTextAccessible* aHyperTextAcc, Accessible* aAccessible) :
--- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -112,19 +112,19 @@ namespace mozilla { namespace dom { // Used on Android/B2G to pass the list of fonts on the device // to the child process struct FontListEntry { nsString familyName; nsString faceName; nsCString filepath; - uint32_t weightRange; - uint32_t stretchRange; - uint32_t styleRange; + float weight; + int16_t stretch; + uint8_t italic; uint8_t index; }; // Used on Mac OS X to pass the list of font families (not faces) // from chrome to content processes. // The entryType field distinguishes several types of font family // record; see gfxMacPlatformFontList.h for values and meaning. struct FontFamilyListEntry {
--- a/gfx/src/FontPropertyTypes.h +++ b/gfx/src/FontPropertyTypes.h @@ -3,27 +3,20 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* font specific types shared by both thebes and layout */ #ifndef GFX_FONT_PROPERTY_TYPES_H #define GFX_FONT_PROPERTY_TYPES_H -#include <algorithm> #include <cstdint> #include <cmath> -#include <utility> - -#include <ctype.h> -#include <stdlib.h> -#include <string.h> - #include "mozilla/Assertions.h" -#include "nsString.h" +#include "nsStringFwd.h" /* * This file is separate from gfxFont.h so that layout can include it * without bringing in gfxFont.h and everything it includes. */ namespace mozilla { @@ -37,17 +30,17 @@ namespace mozilla { * ambiguity between constructors from /int/ and /T/, which mean * different things. * FractionBits - number of bits to use for the fractional part * Min, Max - [inclusive] limits to the range of values that may be stored * Values are constructed from and exposed as floating-point, but stored * internally as fixed point, so there will be a quantization effect on * fractional values, depending on the number of fractional bits used. * Using (16-bit) fixed-point types rather than floats for these style - * attributes reduces the memory footprint of gfxFontEntry and gfxFontStyle; + * attributes reduces the memory footprint of gfxFontEntry and gfxFontSlantStyle; * it will also tend to reduce the number of distinct font instances that * get created, particularly when styles are animated or set to arbitrary * values (e.g. by sliders in the UI), which should reduce pressure on * graphics resources and improve cache hit rates. */ template<class InternalType, unsigned FractionBits, int Min, int Max> class FontPropertyValue { @@ -57,17 +50,17 @@ public: // constructors to be "trivial" (i.e. the compiler implemented defaults that // do no initialization). // Annoyingly we can't make the default implementations constexpr (at least // in clang). That would be nice to do in order to allow the methods of // subclasses that always return the same value (e.g., FontWeight::Thin()) // to also be constexpr. :/ FontPropertyValue() = default; explicit FontPropertyValue(const FontPropertyValue& aOther) = default; - FontPropertyValue& operator=(const FontPropertyValue& aOther) = default; + FontPropertyValue& operator= (const FontPropertyValue& aOther) = default; bool operator==(const FontPropertyValue& aOther) const { return mValue == aOther.mValue; } bool operator!=(const FontPropertyValue& aOther) const { return mValue != aOther.mValue; @@ -92,20 +85,19 @@ public: // The difference between two values, returned as a raw floating-point number // (which might not be a valid property value in its own right). float operator-(const FontPropertyValue& aOther) const { return (mValue - aOther.mValue) * kInverseScale; } /// Return the raw internal representation, for purposes of hashing. - /// (Do not try to interpret the numeric value of this.) - uint16_t ForHash() const + InternalType ForHash() const { - return uint16_t(mValue); + return mValue; } static constexpr const float kMin = float(Min); static constexpr const float kMax = float(Max); protected: // Construct from a floating-point or integer value, checking that it is // within the allowed range and converting to fixed-point representation. @@ -189,21 +181,19 @@ public: } bool IsNormal() const { return mValue == kNormal; } bool IsBold() const { return mValue >= kBoldThreshold; } float ToFloat() const { return FontPropertyValue::ToFloat(); } int ToIntRounded() const { return FontPropertyValue::ToIntRounded(); } +private: typedef uint16_t InternalType; -private: - friend class WeightRange; - explicit FontWeight(InternalType aValue) : FontPropertyValue(aValue) { } static const InternalType kNormal = 400u << kFractionBits; static const InternalType kBold = 700u << kFractionBits; static const InternalType kBoldThreshold = 600u << kFractionBits; @@ -272,21 +262,19 @@ public: static FontStretch UltraExpanded() { return FontStretch(kUltraExpanded); } bool IsNormal() const { return mValue == kNormal; } float Percentage() const { return ToFloat(); } +private: typedef uint16_t InternalType; -private: - friend class StretchRange; - explicit FontStretch(InternalType aValue) : FontPropertyValue(aValue) { } static const InternalType kUltraCondensed = 50u << kFractionBits; static const InternalType kExtraCondensed = (62u << kFractionBits) + kPointFive; static const InternalType kCondensed = 75u << kFractionBits; @@ -305,16 +293,17 @@ private: * (representable range -128.0 - 127.99609375) * - Define min value (-128.0) as meaning 'normal' * - Define max value (127.99609375) as 'italic' * - Other values represent 'oblique <angle>' * - Note that 'oblique 0deg' is distinct from 'normal' (should it be?) */ class FontSlantStyle final : public FontPropertyValue<int16_t,8,-90,90> { + typedef int16_t InternalType; public: const static constexpr float kDefaultAngle = 14.0; // See comment in FontPropertyValue regarding requirement for a trivial // default constructor. FontSlantStyle() = default; static FontSlantStyle Normal() @@ -327,270 +316,39 @@ public: return FontSlantStyle(kItalic); } static FontSlantStyle Oblique(float aAngle = kDefaultAngle) { return FontSlantStyle(aAngle); } - // Create from a string as generated by ToString. This is for internal use - // when serializing/deserializing entries for the startupcache, and is not - // intended to parse arbitrary (untrusted) strings. - static FontSlantStyle FromString(const char* aString) - { - if (strcmp(aString, "normal") == 0) { - return Normal(); - } else if (strcmp(aString, "italic") == 0) { - return Italic(); - } else { - if (isdigit(aString[0]) && strstr(aString, "deg")) { - float angle = strtof(aString, nullptr); - return Oblique(angle); - } - // Not recognized as an oblique angle; maybe it's from a startup-cache - // created by an older version. Just treat it as 'normal'. - return Normal(); - } - } - bool IsNormal() const { return mValue == kNormal; } bool IsItalic() const { return mValue == kItalic; } bool IsOblique() const { return mValue != kItalic && mValue != kNormal; } float ObliqueAngle() const { // It's not meaningful to get the oblique angle from a style that is // actually 'normal' or 'italic'. MOZ_ASSERT(IsOblique()); return ToFloat(); } - /** - * Write a string representation of the value to aOutString. - * - * NOTE that this APPENDS to the output string, it does not replace - * any existing contents. - */ - void ToString(nsACString& aOutString) const - { - if (IsNormal()) { - aOutString.Append("normal"); - } else if (IsItalic()) { - aOutString.Append("italic"); - } else { - aOutString.AppendPrintf("%gdeg", ObliqueAngle()); - } - } - - typedef int16_t InternalType; - private: - friend class SlantStyleRange; - explicit FontSlantStyle(InternalType aConstant) : FontPropertyValue(aConstant) { } explicit FontSlantStyle(float aAngle) : FontPropertyValue(aAngle) { } static const InternalType kNormal = INT16_MIN; static const InternalType kItalic = INT16_MAX; }; - -/** - * Convenience type to hold a <min, max> pair representing a range of values. - * - * The min and max are both inclusive, so when min == max the range represents - * a single value (not an empty range). - */ -template<class T> -class FontPropertyRange -{ - // This implementation assumes the underlying property type is a 16-bit value - // (see FromScalar and AsScalar below). - static_assert(sizeof(T) == 2, "FontPropertyValue should be a 16-bit type!"); - -public: - /** - * Construct a range from given minimum and maximum values (inclusive). - */ - FontPropertyRange(T aMin, T aMax) - : mValues(aMin, aMax) - { - MOZ_ASSERT(aMin <= aMax); - } - - /** - * Construct a range representing a single value (min==max). - */ - explicit FontPropertyRange(T aValue) - : mValues(aValue, aValue) - { - } - - explicit FontPropertyRange(const FontPropertyRange& aOther) = default; - FontPropertyRange& operator=(const FontPropertyRange& aOther) = default; - - T Min() const { return mValues.first; } - T Max() const { return mValues.second; } - - /** - * Clamp the given value to this range. - * - * (We can't use mozilla::Clamp here because it only accepts integral types.) - */ - T Clamp(T aValue) const - { - return aValue <= Min() ? Min() : (aValue >= Max() ? Max() : aValue); - } - - /** - * Return whether the range consists of a single unique value. - */ - bool IsSingle() const - { - return Min() == Max(); - } - - bool operator==(const FontPropertyRange& aOther) const - { - return mValues == aOther.mValues; - } - bool operator!=(const FontPropertyRange& aOther) const - { - return mValues != aOther.mValues; - } - - /** - * Conversion of the property range to/from a single 32-bit scalar value, - * suitable for IPC serialization, hashing, caching. - * - * No assumptions should be made about the numeric value of the scalar. - * - * This depends on the underlying property type being a 16-bit value! - */ - typedef uint32_t ScalarType; - - ScalarType AsScalar() const - { - return (mValues.first.ForHash() << 16) | mValues.second.ForHash(); - } - - /* - * FIXME: - * FromScalar is defined in each individual subclass, because I can't - * persuade the compiler to accept a definition here in the template. :\ - * - static FontPropertyRange FromScalar(ScalarType aScalar) - { - return FontPropertyRange(T(typename T::InternalType(aScalar >> 16)), - T(typename T::InternalType(aScalar & 0xffff))); - } - */ - -protected: - std::pair<T,T> mValues; -}; - -class WeightRange : public FontPropertyRange<FontWeight> -{ -public: - WeightRange(FontWeight aMin, FontWeight aMax) - : FontPropertyRange(aMin, aMax) - { - } - - explicit WeightRange(FontWeight aWeight) - : FontPropertyRange(aWeight) - { - } - - WeightRange(const WeightRange& aOther) = default; - - void ToString(nsACString& aOutString, const char* aDelim = "..") const - { - aOutString.AppendFloat(Min().ToFloat()); - if (!IsSingle()) { - aOutString.Append(aDelim); - aOutString.AppendFloat(Max().ToFloat()); - } - } - - static WeightRange FromScalar(ScalarType aScalar) - { - return WeightRange(FontWeight(FontWeight::InternalType(aScalar >> 16)), - FontWeight(FontWeight::InternalType(aScalar & 0xffff))); - } -}; - -class StretchRange : public FontPropertyRange<FontStretch> -{ -public: - StretchRange(FontStretch aMin, FontStretch aMax) - : FontPropertyRange(aMin, aMax) - { - } - - explicit StretchRange(FontStretch aStretch) - : FontPropertyRange(aStretch) - { - } - - StretchRange(const StretchRange& aOther) = default; - - void ToString(nsACString& aOutString, const char* aDelim = "..") const - { - aOutString.AppendFloat(Min().Percentage()); - if (!IsSingle()) { - aOutString.Append(aDelim); - aOutString.AppendFloat(Max().Percentage()); - } - } - - static StretchRange FromScalar(ScalarType aScalar) - { - return StretchRange( - FontStretch(FontStretch::InternalType(aScalar >> 16)), - FontStretch(FontStretch::InternalType(aScalar & 0xffff))); - } -}; - -class SlantStyleRange : public FontPropertyRange<FontSlantStyle> -{ -public: - SlantStyleRange(FontSlantStyle aMin, FontSlantStyle aMax) - : FontPropertyRange(aMin, aMax) - { - } - - explicit SlantStyleRange(FontSlantStyle aStyle) - : FontPropertyRange(aStyle) - { - } - - SlantStyleRange(const SlantStyleRange& aOther) = default; - - void ToString(nsACString& aOutString, const char* aDelim = "..") const - { - Min().ToString(aOutString); - if (!IsSingle()) { - aOutString.Append(aDelim); - Max().ToString(aOutString); - } - } - - static SlantStyleRange FromScalar(ScalarType aScalar) - { - return SlantStyleRange( - FontSlantStyle(FontSlantStyle::InternalType(aScalar >> 16)), - FontSlantStyle(FontSlantStyle::InternalType(aScalar & 0xffff))); - } -}; - } // namespace mozilla #endif // GFX_FONT_PROPERTY_TYPES_H +
--- a/gfx/src/nsFont.cpp +++ b/gfx/src/nsFont.cpp @@ -287,16 +287,19 @@ void nsFont::AddFontFeaturesToStyle(gfxF aStyle->useGrayscaleAntialiasing = true; } aStyle->fontSmoothingBackgroundColor = fontSmoothingBackgroundColor; } void nsFont::AddFontVariationsToStyle(gfxFontStyle *aStyle) const { + // TODO: add variation settings from specific CSS properties + // such as weight, width, stretch + // If auto optical sizing is enabled, and if there's no 'opsz' axis in // fontVariationSettings, then set the automatic value on the style. class VariationTagComparator { public: bool Equals(const gfxFontVariation& aVariation, uint32_t aTag) const { return aVariation.mTag == aTag; } };
--- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -185,19 +185,16 @@ gfxDWriteFontFamily::FindStyleVariations // <em> and <i> should be rendered as italic in the default style. if (fullID.EqualsLiteral("Meiryo Italic") || fullID.EqualsLiteral("Meiryo Bold Italic")) { continue; } gfxDWriteFontEntry *fe = new gfxDWriteFontEntry(fullID, font, mIsSystemFontFamily); fe->SetForceGDIClassic(mForceGDIClassic); - - fe->SetupVariationRanges(); - AddFontEntry(fe); // postscript/fullname if needed nsAutoString psname, fullname; if (fontInfoShouldHaveFaceNames) { aFontInfoData->GetFaceNames(fe->Name(), fullname, psname); if (!fullname.IsEmpty()) { fp->AddFullname(fe, fullname); @@ -217,26 +214,23 @@ gfxDWriteFontFamily::FindStyleVariations if (FAILED(hr)) { skipFaceNames = true; } else if (fullname.Length() > 0) { fp->AddFullname(fe, fullname); } } if (LOG_FONTLIST_ENABLED()) { - nsAutoCString weightString; - fe->Weight().ToString(weightString); LOG_FONTLIST(("(fontlist) added (%s) to family (%s)" - " with style: %s weight: %s stretch: %d psname: %s fullname: %s", + " with style: %s weight: %g stretch: %d psname: %s fullname: %s", NS_ConvertUTF16toUTF8(fe->Name()).get(), NS_ConvertUTF16toUTF8(Name()).get(), (fe->IsItalic()) ? "italic" : (fe->IsOblique() ? "oblique" : "normal"), - weightString.get(), - fe->Stretch(), + fe->Weight().ToFloat(), fe->Stretch(), NS_ConvertUTF16toUTF8(psname).get(), NS_ConvertUTF16toUTF8(fullname).get())); } } // assume that if no error, all postscript/fullnames were initialized if (!skipFaceNames) { mFaceNamesInitialized = true; @@ -371,21 +365,17 @@ gfxDWriteFontFamily::AddSizeOfIncludingT //////////////////////////////////////////////////////////////////////////////// // gfxDWriteFontEntry gfxFontEntry* gfxDWriteFontEntry::Clone() const { MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!"); - gfxDWriteFontEntry* fe = new gfxDWriteFontEntry(Name(), mFont); - fe->mWeightRange = mWeightRange; - fe->mStretchRange = mStretchRange; - fe->mStyleRange = mStyleRange; - return fe; + return new gfxDWriteFontEntry(Name(), mFont); } gfxDWriteFontEntry::~gfxDWriteFontEntry() { } static bool UsingArabicOrHebrewScriptSystemLocale() @@ -674,46 +664,46 @@ gfxDWriteFontEntry::CreateFontInstance(c DWRITE_FONT_SIMULATIONS sims = aNeedsBold ? DWRITE_FONT_SIMULATIONS_BOLD : DWRITE_FONT_SIMULATIONS_NONE; if (HasVariations() && !aFontStyle->variationSettings.IsEmpty()) { // If we need to apply variations, we can't use the cached mUnscaledFont // or mUnscaledFontBold here. // XXX todo: consider caching a small number of variation instances? RefPtr<IDWriteFontFace> fontFace; nsresult rv = CreateFontFace(getter_AddRefs(fontFace), - aFontStyle, + &aFontStyle->variationSettings, sims); if (NS_FAILED(rv)) { return nullptr; } RefPtr<UnscaledFontDWrite> unscaledFont = new UnscaledFontDWrite(fontFace, mIsSystemFont ? mFont : nullptr, sims); return new gfxDWriteFont(unscaledFont, this, aFontStyle, aNeedsBold); } ThreadSafeWeakPtr<UnscaledFontDWrite>& unscaledFontPtr = aNeedsBold ? mUnscaledFontBold : mUnscaledFont; RefPtr<UnscaledFontDWrite> unscaledFont(unscaledFontPtr); if (!unscaledFont) { RefPtr<IDWriteFontFace> fontFace; - nsresult rv = CreateFontFace(getter_AddRefs(fontFace), aFontStyle, sims); + nsresult rv = CreateFontFace(getter_AddRefs(fontFace), nullptr, sims); if (NS_FAILED(rv)) { return nullptr; } unscaledFont = new UnscaledFontDWrite(fontFace, mIsSystemFont ? mFont : nullptr, sims); unscaledFontPtr = unscaledFont; } return new gfxDWriteFont(unscaledFont, this, aFontStyle, aNeedsBold); } nsresult gfxDWriteFontEntry::CreateFontFace(IDWriteFontFace **aFontFace, - const gfxFontStyle* aFontStyle, + const nsTArray<gfxFontVariation>* aVariations, DWRITE_FONT_SIMULATIONS aSimulations) { // Convert an OpenType font tag from our uint32_t representation // (as constructed by TRUETYPE_TAG(...)) to the order DWrite wants. auto makeDWriteAxisTag = [](uint32_t aTag) { return DWRITE_MAKE_FONT_AXIS_TAG((aTag >> 24) & 0xff, (aTag >> 16) & 0xff, (aTag >> 8) & 0xff, @@ -771,38 +761,46 @@ gfxDWriteFontEntry::CreateFontFace(IDWri // Do we need to modify DWrite simulations from what mFontFace has? bool needSimulations = (aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) && !(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD); // If the IDWriteFontFace5 interface is available, we can go via // IDWriteFontResource to create a new modified face. - if (mFontFace5 && (HasVariations() || needSimulations)) { + if (mFontFace5 && (aVariations && !aVariations->IsEmpty() || + needSimulations)) { RefPtr<IDWriteFontResource> resource; HRESULT hr = mFontFace5->GetFontResource(getter_AddRefs(resource)); MOZ_ASSERT(SUCCEEDED(hr)); AutoTArray<DWRITE_FONT_AXIS_VALUE, 4> fontAxisValues; - - // Get the variation settings needed to instantiate the fontEntry - // for a particular fontStyle. - AutoTArray<gfxFontVariation,4> vars; - GetVariationsForStyle(vars, *aFontStyle); - - // Copy variation settings to DWrite's type. - if (!vars.IsEmpty()) { - for (const auto& v : vars) { + if (aVariations) { + // Merge mVariationSettings and *aVariations if both present + const nsTArray<gfxFontVariation>* vars; + AutoTArray<gfxFontVariation,4> mergedSettings; + if (!aVariations) { + vars = &mVariationSettings; + } else { + if (mVariationSettings.IsEmpty()) { + vars = aVariations; + } else { + gfxFontUtils::MergeVariations(mVariationSettings, + *aVariations, + &mergedSettings); + vars = &mergedSettings; + } + } + for (const auto& v : *vars) { DWRITE_FONT_AXIS_VALUE axisValue = { makeDWriteAxisTag(v.mTag), v.mValue }; fontAxisValues.AppendElement(axisValue); } } - IDWriteFontFace5* ff5; resource->CreateFontFace(aSimulations, fontAxisValues.Elements(), fontAxisValues.Length(), &ff5); if (ff5) { *aFontFace = ff5; } @@ -954,43 +952,43 @@ gfxDWriteFontList::GetDefaultFontForPlat } } return nullptr; } gfxFontEntry * gfxDWriteFontList::LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) { gfxFontEntry *lookup; lookup = LookupInFaceNameLists(aFontName); if (!lookup) { return nullptr; } gfxDWriteFontEntry* dwriteLookup = static_cast<gfxDWriteFontEntry*>(lookup); gfxDWriteFontEntry *fe = new gfxDWriteFontEntry(lookup->Name(), dwriteLookup->mFont, - aWeightForEntry, - aStretchForEntry, - aStyleForEntry); + aWeight, + aStretch, + aStyle); fe->SetForceGDIClassic(dwriteLookup->GetForceGDIClassic()); return fe; } gfxFontEntry * gfxDWriteFontList::MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) { RefPtr<IDWriteFontFileStream> fontFileStream; RefPtr<IDWriteFontFile> fontFile; HRESULT hr = gfxDWriteFontFileLoader::CreateCustomFontFile(aFontData, aLength, getter_AddRefs(fontFile), @@ -1010,19 +1008,19 @@ gfxDWriteFontList::MakePlatformFont(cons BOOL isSupported; DWRITE_FONT_FILE_TYPE fileType; UINT32 numFaces; gfxDWriteFontEntry *entry = new gfxDWriteFontEntry(uniqueName, fontFile, fontFileStream, - aWeightForEntry, - aStretchForEntry, - aStyleForEntry); + aWeight, + aStretch, + aStyle); fontFile->Analyze(&isSupported, &fileType, &entry->mFaceType, &numFaces); if (!isSupported || numFaces > 1) { // We don't know how to deal with 0 faces either. delete entry; return nullptr; } @@ -1148,26 +1146,23 @@ gfxDWriteFontList::InitFontListForPlatfo // add faces to Gill Sans MT for (i = 0; i < faces.Length(); i++) { // change the entry's family name to match its adoptive family faces[i]->mFamilyName = gillSansMTFamily->Name(); gillSansMTFamily->AddFontEntry(faces[i]); if (LOG_FONTLIST_ENABLED()) { gfxFontEntry *fe = faces[i]; - nsAutoCString weightString; - fe->Weight().ToString(weightString); LOG_FONTLIST(("(fontlist) moved (%s) to family (%s)" - " with style: %s weight: %s stretch: %d", + " with style: %s weight: %g stretch: %d", NS_ConvertUTF16toUTF8(fe->Name()).get(), NS_ConvertUTF16toUTF8(gillSansMTFamily->Name()).get(), (fe->IsItalic()) ? "italic" : (fe->IsOblique() ? "oblique" : "normal"), - weightString.get(), - fe->Stretch())); + fe->Weight().ToFloat(), fe->Stretch())); } } // remove Gills Sans mFontFamilies.Remove(nameGillSans); } }
--- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -110,30 +110,25 @@ public: gfxDWriteFontEntry(const nsAString& aFaceName, IDWriteFont *aFont, bool aIsSystemFont = false) : gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr), mIsSystemFont(aIsSystemFont), mForceGDIClassic(false), mHasVariations(false), mHasVariationsInitialized(false) { DWRITE_FONT_STYLE dwriteStyle = aFont->GetStyle(); - FontSlantStyle style = - (dwriteStyle == DWRITE_FONT_STYLE_ITALIC - ? FontSlantStyle::Italic() - : (dwriteStyle == DWRITE_FONT_STYLE_OBLIQUE - ? FontSlantStyle::Oblique() - : FontSlantStyle::Normal())); - mStyleRange = SlantStyleRange(style); + mStyle = (dwriteStyle == DWRITE_FONT_STYLE_ITALIC ? + FontSlantStyle::Italic() : + (dwriteStyle == DWRITE_FONT_STYLE_OBLIQUE ? + FontSlantStyle::Oblique() : FontSlantStyle::Normal())); + mStretch = FontStretchFromDWriteStretch(aFont->GetStretch()); + int weight = NS_ROUNDUP(aFont->GetWeight() - 50, 100); - mStretchRange = - StretchRange(FontStretchFromDWriteStretch(aFont->GetStretch())); - - int weight = NS_ROUNDUP(aFont->GetWeight() - 50, 100); weight = mozilla::Clamp(weight, 100, 900); - mWeightRange = WeightRange(FontWeight(weight)); + mWeight = FontWeight(weight); mIsCJK = UNINITIALIZED_VALUE; } /** * Constructs a font entry using a font. But with custom font values. * This is used for creating correct font entries for @font-face with local * font source. @@ -141,26 +136,26 @@ public: * \param aFaceName The name of the corresponding font face. * \param aFont DirectWrite font object * \param aWeight Weight of the font * \param aStretch Stretch of the font * \param aStyle italic or oblique of font */ gfxDWriteFontEntry(const nsAString& aFaceName, IDWriteFont *aFont, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) : gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr), mIsSystemFont(false), mForceGDIClassic(false), mHasVariations(false), mHasVariationsInitialized(false) { - mWeightRange = aWeight; - mStretchRange = aStretch; - mStyleRange = aStyle; + mWeight = aWeight; + mStretch = aStretch; + mStyle = aStyle; mIsLocalUserFont = true; mIsCJK = UNINITIALIZED_VALUE; } /** * Constructs a font entry using a font file. * * \param aFaceName The name of the corresponding font face. @@ -168,27 +163,27 @@ public: * \param aFontFileStream DirectWrite fontfile stream object * \param aWeight Weight of the font * \param aStretch Stretch of the font * \param aStyle italic or oblique of font */ gfxDWriteFontEntry(const nsAString& aFaceName, IDWriteFontFile *aFontFile, IDWriteFontFileStream *aFontFileStream, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) : gfxFontEntry(aFaceName), mFont(nullptr), mFontFile(aFontFile), mFontFileStream(aFontFileStream), mIsSystemFont(false), mForceGDIClassic(false), mHasVariations(false), mHasVariationsInitialized(false) { - mWeightRange = aWeight; - mStretchRange = aStretch; - mStyleRange = aStyle; + mWeight = aWeight; + mStretch = aStretch; + mStyle = aStyle; mIsDataUserFont = true; mIsCJK = UNINITIALIZED_VALUE; } gfxFontEntry* Clone() const override; virtual ~gfxDWriteFontEntry(); @@ -217,17 +212,17 @@ protected: virtual nsresult CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>& aBuffer) override; virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold); nsresult CreateFontFace( IDWriteFontFace **aFontFace, - const gfxFontStyle* aFontStyle = nullptr, + const nsTArray<gfxFontVariation>* aVariations = nullptr, DWRITE_FONT_SIMULATIONS aSimulations = DWRITE_FONT_SIMULATIONS_NONE); static bool InitLogFont(IDWriteFont *aFont, LOGFONTW *aLogFont); /** * A fontentry only needs to have either of these. If it has both only * the IDWriteFont will be used. */ @@ -405,24 +400,24 @@ public: } // initialize font lists virtual nsresult InitFontListForPlatform() override; gfxFontFamily* CreateFontFamily(const nsAString& aName) const override; virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry); + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle); virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength); bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName); IDWriteGdiInterop *GetGDIInterop() { return mGDIInterop; } bool UseGDIFontTableAccess() { return mGDIFontTableAccess; }
--- a/gfx/thebes/gfxDWriteFonts.cpp +++ b/gfx/thebes/gfxDWriteFonts.cpp @@ -152,18 +152,17 @@ gfxDWriteFont::GetFakeMetricsForArialBla return true; } void gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption) { DWRITE_FONT_METRICS fontMetrics; - if (!(mFontEntry->Weight().Min() == FontWeight(900) && - mFontEntry->Weight().Max() == FontWeight(900) && + if (!(mFontEntry->Weight() == FontWeight(900) && !mFontEntry->IsUserFont() && mFontEntry->Name().EqualsLiteral("Arial Black") && GetFakeMetricsForArialBlack(&fontMetrics))) { mFontFace->GetMetrics(&fontMetrics); } if (mStyle.sizeAdjust >= 0.0) {
--- a/gfx/thebes/gfxFT2FontBase.cpp +++ b/gfx/thebes/gfxFT2FontBase.cpp @@ -224,21 +224,33 @@ gfxFT2FontBase::InitMetrics() mMetrics.underlineOffset = -underlineSize; mMetrics.strikeoutOffset = 0.25 * emHeight; mMetrics.strikeoutSize = underlineSize; SanitizeMetrics(&mMetrics, false); return; } - if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) { + if ((!mFontEntry->mVariationSettings.IsEmpty() || + !mStyle.variationSettings.IsEmpty()) && + (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) { // Resolve variations from entry (descriptor) and style (property) - AutoTArray<gfxFontVariation,8> settings; - mFontEntry->GetVariationsForStyle(settings, mStyle); - SetupVarCoords(face, settings, &mCoords); + const nsTArray<gfxFontVariation>* settings; + AutoTArray<gfxFontVariation,8> mergedSettings; + if (mFontEntry->mVariationSettings.IsEmpty()) { + settings = &mStyle.variationSettings; + } else if (mStyle.variationSettings.IsEmpty()) { + settings = &mFontEntry->mVariationSettings; + } else { + gfxFontUtils::MergeVariations(mFontEntry->mVariationSettings, + mStyle.variationSettings, + &mergedSettings); + settings = &mergedSettings; + } + SetupVarCoords(face, *settings, &mCoords); if (!mCoords.IsEmpty()) { #if MOZ_TREE_FREETYPE FT_Set_Var_Design_Coordinates(face, mCoords.Length(), mCoords.Elements()); #else typedef FT_Error (*SetCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*); static SetCoordsFunc setCoords; static bool firstTime = true; if (firstTime) {
--- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -219,19 +219,19 @@ FT2FontEntry::~FT2FontEntry() gfxFontEntry* FT2FontEntry::Clone() const { MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!"); FT2FontEntry* fe = new FT2FontEntry(Name()); fe->mFilename = mFilename; fe->mFTFontIndex = mFTFontIndex; - fe->mWeightRange = mWeightRange; - fe->mStretchRange = mStretchRange; - fe->mStyleRange = mStyleRange; + fe->mWeight = mWeight; + fe->mStretch = mStretch; + fe->mStyle = mStyle; return fe; } gfxFont* FT2FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) { cairo_scaled_font_t *scaledFont = CreateScaledFont(aFontStyle); if (!scaledFont) { @@ -252,19 +252,19 @@ FT2FontEntry::CreateFontInstance(const g aFontStyle, aNeedsBold); cairo_scaled_font_destroy(scaledFont); return font; } /* static */ FT2FontEntry* FT2FontEntry::CreateFontEntry(const nsAString& aFontName, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) { // Ownership of aFontData is passed in here; the fontEntry must // retain it as long as the FT_Face needs it, and ensure it is // eventually deleted. FT_Face face = Factory::NewFTFaceFromData(nullptr, aFontData, aLength, 0); if (!face) { @@ -277,19 +277,19 @@ FT2FontEntry::CreateFontEntry(const nsAS return nullptr; } // Create our FT2FontEntry, which inherits the name of the userfont entry // as it's not guaranteed that the face has valid names (bug 737315) FT2FontEntry* fe = FT2FontEntry::CreateFontEntry(face, nullptr, 0, aFontName, aFontData, aLength); if (fe) { - fe->mStyleRange = aStyle; - fe->mWeightRange = aWeight; - fe->mStretchRange = aStretch; + fe->mStyle = aStyle; + fe->mWeight = aWeight; + fe->mStretch = aStretch; fe->mIsDataUserFont = true; } return fe; } class FTUserFontData { public: FTUserFontData(FT_Face aFace, const uint8_t* aData, uint32_t aLength) @@ -323,19 +323,22 @@ FTFontDestroyFunc(void *data) /* static */ FT2FontEntry* FT2FontEntry::CreateFontEntry(const FontListEntry& aFLE) { FT2FontEntry *fe = new FT2FontEntry(aFLE.faceName()); fe->mFilename = aFLE.filepath(); fe->mFTFontIndex = aFLE.index(); - fe->mWeightRange = WeightRange::FromScalar(aFLE.weightRange()); - fe->mStretchRange = StretchRange::FromScalar(aFLE.stretchRange()); - fe->mStyleRange = SlantStyleRange::FromScalar(aFLE.styleRange()); + // The weight transported across IPC is a float, so we need to explicitly + // convert it back to a FontWeight. + fe->mWeight = FontWeight(aFLE.weight()); + fe->mStretch = FontStretch(float(aFLE.stretch())); + fe->mStyle = aFLE.italic() + ? FontSlantStyle::Italic() : FontSlantStyle::Normal(); return fe; } // Helpers to extract font entry properties from an FT_Face static bool FTFaceIsItalic(FT_Face aFace) { return !!(aFace->style_flags & FT_STYLE_FLAG_ITALIC); @@ -383,20 +386,19 @@ FTFaceGetWeight(FT_Face aFace) FT2FontEntry* FT2FontEntry::CreateFontEntry(FT_Face aFace, const char* aFilename, uint8_t aIndex, const nsAString& aName, const uint8_t* aFontData, uint32_t aLength) { FT2FontEntry *fe = new FT2FontEntry(aName); - fe->mStyleRange = SlantStyleRange(FTFaceIsItalic(aFace) - ? FontSlantStyle::Italic() - : FontSlantStyle::Normal()); - fe->mWeightRange = WeightRange(FTFaceGetWeight(aFace)); + fe->mStyle = (FTFaceIsItalic(aFace) ? + FontSlantStyle::Italic() : FontSlantStyle::Normal()); + fe->mWeight = FTFaceGetWeight(aFace); fe->mFilename = aFilename; fe->mFTFontIndex = aIndex; if (aFontData) { fe->mFTFace = aFace; int flags = gfxPlatform::GetPlatform()->FontHintingEnabled() ? FT_LOAD_DEFAULT : (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING); @@ -459,20 +461,32 @@ FT2FontEntry::CairoFontFace(const gfxFon // have custom variation coordinates applied. if ((!mVariationSettings.IsEmpty() || (aStyle && !aStyle->variationSettings.IsEmpty())) && (mFTFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) { int flags = gfxPlatform::GetPlatform()->FontHintingEnabled() ? FT_LOAD_DEFAULT : (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING); // Resolve variations from entry (descriptor) and style (property) - AutoTArray<gfxFontVariation,8> settings; - GetVariationsForStyle(settings, aStyle ? *aStyle : gfxFontStyle()); + const nsTArray<gfxFontVariation>* settings; + AutoTArray<gfxFontVariation,8> mergedSettings; + if (aStyle) { + if (mVariationSettings.IsEmpty()) { + settings = &aStyle->variationSettings; + } else { + gfxFontUtils::MergeVariations(mVariationSettings, + aStyle->variationSettings, + &mergedSettings); + settings = &mergedSettings; + } + } else { + settings = &mVariationSettings; + } AutoTArray<FT_Fixed,8> coords; - gfxFT2FontBase::SetupVarCoords(mFTFace, settings, &coords); + gfxFT2FontBase::SetupVarCoords(mFTFace, *settings, &coords); // Create a separate FT_Face because we need to apply custom // variation settings to it. FT_Face ftFace; if (!mFilename.IsEmpty()) { ftFace = Factory::NewFTFace(nullptr, mFilename.get(), mFTFontIndex); } else { auto ufd = reinterpret_cast<FTUserFontData*>( cairo_font_face_get_user_data(mFontFace, &sFTUserFontDataKey)); @@ -646,22 +660,26 @@ FT2FontFamily::AddFacesToFontList(Infall { for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) { const FT2FontEntry *fe = static_cast<const FT2FontEntry*>(mAvailableFonts[i].get()); if (!fe) { continue; } + // We convert the weight to a float purely for transport across IPC. + // Ideally we'd avoid doing that. aFontList->AppendElement(FontListEntry(Name(), fe->Name(), fe->mFilename, - fe->Weight().AsScalar(), - fe->Stretch().AsScalar(), - fe->SlantStyle().AsScalar(), + fe->Weight().ToFloat(), + fe->Stretch().Percentage(), + fe->mStyle.IsItalic() + ? NS_FONT_STYLE_ITALIC + : NS_FONT_STYLE_NORMAL, fe->mFTFontIndex)); } } /* * Startup cache support for the font list: * We store the list of families and faces, with their style attributes and the * corresponding font files, in the startup cache. @@ -925,75 +943,44 @@ gfxFT2FontList::AppendFacesFromCachedFac const nsCString& aFaceList, StandardFile aStdFile) { const char *beginning = aFaceList.get(); const char *end = strchr(beginning, ','); while (end) { NS_ConvertUTF8toUTF16 familyName(beginning, end - beginning); ToLowerCase(familyName); - beginning = end + 1; if (!(end = strchr(beginning, ','))) { break; } NS_ConvertUTF8toUTF16 faceName(beginning, end - beginning); - beginning = end + 1; if (!(end = strchr(beginning, ','))) { break; } uint32_t index = strtoul(beginning, nullptr, 10); - beginning = end + 1; if (!(end = strchr(beginning, ','))) { break; } - nsAutoCString minStyle(beginning, end - beginning); - nsAutoCString maxStyle(minStyle); - int32_t colon = minStyle.FindChar(':'); - if (colon > 0) { - maxStyle.Assign(minStyle.BeginReading() + colon + 1); - minStyle.Truncate(colon - 1); - } - + bool italic = (*beginning != '0'); beginning = end + 1; if (!(end = strchr(beginning, ','))) { break; } - char* limit; - float minWeight = strtof(beginning, &limit); - float maxWeight; - if (*limit == ':' && limit + 1 < end) { - maxWeight = strtof(limit + 1, nullptr); - } else { - maxWeight = minWeight; - } - + uint32_t weight = strtoul(beginning, nullptr, 10); beginning = end + 1; if (!(end = strchr(beginning, ','))) { break; } - float minStretch = strtof(beginning, &limit); - float maxStretch; - if (*limit == ':' && limit + 1 < end) { - maxStretch = strtof(limit + 1, nullptr); - } else { - maxStretch = minStretch; - } + uint32_t stretch = strtoul(beginning, nullptr, 10); - FontListEntry fle( - familyName, faceName, aFileName, - WeightRange(FontWeight(minWeight), - FontWeight(maxWeight)).AsScalar(), - StretchRange(FontStretch(minStretch), - FontStretch(maxStretch)).AsScalar(), - SlantStyleRange(FontSlantStyle::FromString(minStyle.get()), - FontSlantStyle::FromString(maxStyle.get())).AsScalar(), - index); + FontListEntry fle(familyName, faceName, aFileName, + weight, stretch, italic, index); AppendFaceFromFontListEntry(fle, aStdFile); beginning = end + 1; end = strchr(beginning, ','); } } static void @@ -1003,23 +990,20 @@ AppendToFaceList(nsCString& aFaceList, aFaceList.Append(NS_ConvertUTF16toUTF8(aFamilyName)); aFaceList.Append(','); aFaceList.Append(NS_ConvertUTF16toUTF8(aFontEntry->Name())); aFaceList.Append(','); aFaceList.AppendInt(aFontEntry->mFTFontIndex); aFaceList.Append(','); aFaceList.Append(aFontEntry->IsItalic() ? '1' : '0'); aFaceList.Append(','); - aFaceList.AppendFloat(aFontEntry->Weight().Min().ToFloat()); - aFaceList.Append(':'); - aFaceList.AppendFloat(aFontEntry->Weight().Max().ToFloat()); + aFaceList.AppendFloat(aFontEntry->Weight().ToFloat()); aFaceList.Append(','); - aFaceList.AppendFloat(aFontEntry->Stretch().Min().Percentage()); - aFaceList.Append(':'); - aFaceList.AppendFloat(aFontEntry->Stretch().Max().Percentage()); + // FIXME(emilio): Probably the stretch should be converted to float. + aFaceList.AppendInt(int32_t(aFontEntry->Stretch().Percentage())); aFaceList.Append(','); } void FT2FontEntry::CheckForBrokenFont(gfxFontFamily *aFamily) { // note if the family is in the "bad underline" blacklist if (aFamily->IsBadUnderlineFamily()) { @@ -1165,27 +1149,22 @@ gfxFT2FontList::AddFaceToList(const nsCS } fe->mStandardFace = (aStdFile == kStandard); family->AddFontEntry(fe); fe->CheckForBrokenFont(family); AppendToFaceList(aFaceList, name, fe); if (LOG_ENABLED()) { - nsAutoCString weightString; - fe->Weight().ToString(weightString); - nsAutoCString stretchString; - fe->Stretch().ToString(stretchString); LOG(("(fontinit) added (%s) to family (%s)" - " with style: %s weight: %s stretch: %s", + " with style: %s weight: %g stretch: %g%%", NS_ConvertUTF16toUTF8(fe->Name()).get(), NS_ConvertUTF16toUTF8(family->Name()).get(), fe->IsItalic() ? "italic" : "normal", - weightString.get(), - stretchString.get())); + fe->Weight().ToFloat(), fe->Stretch().Percentage())); } } } void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive, const nsCString& aEntryName, FontNameCache *aCache, @@ -1485,19 +1464,19 @@ gfxFT2FontList::InitFontListForPlatform( return NS_OK; } // called for each family name, based on the assumption that the // first part of the full name is the family name gfxFontEntry* gfxFT2FontList::LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) { // walk over list of names FT2FontEntry* fontEntry = nullptr; nsString fullName(aFontName); for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) { // Check family name, based on the assumption that the // first part of the full name is the family name @@ -1542,19 +1521,19 @@ searchDone: } FT2FontEntry* fe = FT2FontEntry::CreateFontEntry(fontEntry->mFTFace, fontEntry->mFilename.get(), fontEntry->mFTFontIndex, fontEntry->Name(), nullptr); if (fe) { - fe->mStyleRange = aStyleForEntry; - fe->mWeightRange = aWeightForEntry; - fe->mStretchRange = aStretchForEntry; + fe->mStyle = aStyle; + fe->mWeight = aWeight; + fe->mStretch = aStretch; fe->mIsLocalUserFont = true; } return fe; } gfxFontFamily* gfxFT2FontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle) @@ -1567,30 +1546,27 @@ gfxFT2FontList::GetDefaultFontForPlatfor } #endif /* TODO: what about Qt or other platforms that may use this? */ return ff; } gfxFontEntry* gfxFT2FontList::MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) { // The FT2 font needs the font data to persist, so we do NOT free it here // but instead pass ownership to the font entry. // Deallocation will happen later, when the font face is destroyed. - return FT2FontEntry::CreateFontEntry(aFontName, - aWeightForEntry, - aStretchForEntry, - aStyleForEntry, - aFontData, aLength); + return FT2FontEntry::CreateFontEntry(aFontName, aWeight, aStretch, + aStyle, aFontData, aLength); } void gfxFT2FontList::GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray) { for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) { RefPtr<gfxFontFamily>& family = iter.Data(); aFamilyArray.AppendElement(family);
--- a/gfx/thebes/gfxFT2FontList.h +++ b/gfx/thebes/gfxFT2FontList.h @@ -38,19 +38,19 @@ public: const nsString& GetName() const { return Name(); } // create a font entry for a downloaded font static FT2FontEntry* CreateFontEntry(const nsAString& aFontName, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength); // create a font entry representing an installed font, identified by // a FontListEntry; the freetype and cairo faces will not be instantiated // until actually needed static FT2FontEntry* CreateFontEntry(const FontListEntry& aFLE); @@ -117,24 +117,24 @@ public: class gfxFT2FontList : public gfxPlatformFontList { public: gfxFT2FontList(); virtual ~gfxFT2FontList(); virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) override; + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) override; virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) override; void GetSystemFontList(InfallibleTArray<FontListEntry>* retValue); static gfxFT2FontList* PlatformFontList() { return static_cast<gfxFT2FontList*>(gfxPlatformFontList::PlatformFontList()); }
--- a/gfx/thebes/gfxFcPlatformFontList.cpp +++ b/gfx/thebes/gfxFcPlatformFontList.cpp @@ -53,19 +53,16 @@ using namespace mozilla::gfx; using namespace mozilla::unicode; using mozilla::dom::SystemFontListEntry; using mozilla::dom::FontPatternListEntry; #ifndef FC_POSTSCRIPT_NAME #define FC_POSTSCRIPT_NAME "postscriptname" /* String */ #endif -#ifndef FC_VARIABLE -#define FC_VARIABLE "variable" /* Bool */ -#endif #define PRINTING_FC_PROPERTY "gfx.printing" #define LOG_FONTLIST(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \ LogLevel::Debug, args) #define LOG_FONTLIST_ENABLED() MOZ_LOG_TEST( \ gfxPlatform::GetLog(eGfxLog_fontlist), \ LogLevel::Debug) @@ -231,43 +228,42 @@ MapFcWidth(int aFcWidth) } gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName, FcPattern* aFontPattern, bool aIgnoreFcCharmap) : gfxFontEntry(aFaceName), mFontPattern(aFontPattern), mFTFace(nullptr), mFTFaceInitialized(false), mIgnoreFcCharmap(aIgnoreFcCharmap), - mHasVariationsInitialized(false), mAspect(0.0), mFontData(nullptr), mLength(0) { // italic int slant; if (FcPatternGetInteger(aFontPattern, FC_SLANT, 0, &slant) != FcResultMatch) { slant = FC_SLANT_ROMAN; } if (slant == FC_SLANT_OBLIQUE) { - mStyleRange = SlantStyleRange(FontSlantStyle::Oblique()); + mStyle = FontSlantStyle::Oblique(); } else if (slant > 0) { - mStyleRange = SlantStyleRange(FontSlantStyle::Italic()); + mStyle = FontSlantStyle::Italic(); } // weight int weight; if (FcPatternGetInteger(aFontPattern, FC_WEIGHT, 0, &weight) != FcResultMatch) { weight = FC_WEIGHT_REGULAR; } - mWeightRange = WeightRange(MapFcWeight(weight)); + mWeight = MapFcWeight(weight); // width int width; if (FcPatternGetInteger(aFontPattern, FC_WIDTH, 0, &width) != FcResultMatch) { width = FC_WIDTH_NORMAL; } - mStretchRange = StretchRange(MapFcWidth(width)); + mStretch = MapFcWidth(width); } gfxFontEntry* gfxFontconfigFontEntry::Clone() const { MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!"); return new gfxFontconfigFontEntry(Name(), mFontPattern, mIgnoreFcCharmap); } @@ -311,51 +307,49 @@ CreateFaceForPattern(FcPattern* aPattern int index; if (FcPatternGetInteger(aPattern, FC_INDEX, 0, &index) != FcResultMatch) { index = 0; // default to 0 if not found in pattern } return Factory::NewFTFace(nullptr, ToCharPtr(filename), index); } gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t *aData, uint32_t aLength, FT_Face aFace) : gfxFontEntry(aFaceName), mFTFace(aFace), mFTFaceInitialized(true), mIgnoreFcCharmap(true), - mHasVariationsInitialized(false), mAspect(0.0), mFontData(aData), mLength(aLength) { - mWeightRange = aWeight; - mStyleRange = aStyle; - mStretchRange = aStretch; + mWeight = aWeight; + mStyle = aStyle; + mStretch = aStretch; mIsDataUserFont = true; mFontPattern = CreatePatternForFace(mFTFace); mUserFontData = new FTUserFontData(mFTFace, mFontData); } gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsAString& aFaceName, FcPattern* aFontPattern, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) : gfxFontEntry(aFaceName), mFontPattern(aFontPattern), mFTFace(nullptr), mFTFaceInitialized(false), - mHasVariationsInitialized(false), mAspect(0.0), mFontData(nullptr), mLength(0) { - mWeightRange = aWeight; - mStyleRange = aStyle; - mStretchRange = aStretch; + mWeight = aWeight; + mStyle = aStyle; + mStretch = aStretch; mIsLocalUserFont = true; // The proper setting of mIgnoreFcCharmap is tricky for fonts loaded // via src:local()... // If the local font happens to come from the application fontset, // we want to set it to true so that color/svg fonts will work even // if the default glyphs are blank; but if the local font is a non- // sfnt face (e.g. legacy type 1) then we need to set it to false @@ -766,22 +760,32 @@ gfxFontconfigFontEntry::CreateScaledFont if (needsOblique) { // disable embedded bitmaps (mimics behavior in 90-synthetic.conf) FcPatternDel(aRenderPattern, FC_EMBEDDED_BITMAP); FcPatternAddBool(aRenderPattern, FC_EMBEDDED_BITMAP, FcFalse); } AutoTArray<FT_Fixed,8> coords; - if (HasVariations()) { + if (!aStyle->variationSettings.IsEmpty() || !mVariationSettings.IsEmpty()) { FT_Face ftFace = GetFTFace(); if (ftFace) { - AutoTArray<gfxFontVariation,8> settings; - GetVariationsForStyle(settings, *aStyle); - gfxFT2FontBase::SetupVarCoords(ftFace, settings, &coords); + const nsTArray<gfxFontVariation>* settings; + AutoTArray<gfxFontVariation,8> mergedSettings; + if (mVariationSettings.IsEmpty()) { + settings = &aStyle->variationSettings; + } else if (aStyle->variationSettings.IsEmpty()) { + settings = &mVariationSettings; + } else { + gfxFontUtils::MergeVariations(mVariationSettings, + aStyle->variationSettings, + &mergedSettings); + settings = &mergedSettings; + } + gfxFT2FontBase::SetupVarCoords(ftFace, *settings, &coords); } } cairo_font_face_t *face = cairo_ft_font_face_create_for_pattern(aRenderPattern, coords.Elements(), coords.Length()); @@ -1055,38 +1059,21 @@ gfxFontconfigFontEntry::GetFTFace() mFTFace = CreateFaceForPattern(mFontPattern); } return mFTFace; } bool gfxFontconfigFontEntry::HasVariations() { - if (mHasVariationsInitialized) { - return mHasVariations; + FT_Face face = GetFTFace(); + if (face) { + return face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS; } - mHasVariationsInitialized = true; - mHasVariations = false; - - // For installed fonts, query the fontconfig pattern rather than paying - // the cost of loading a FT_Face that we otherwise might never need. - if (!IsUserFont() || IsLocalUserFont()) { - FcBool variable; - if ((FcPatternGetBool(mFontPattern, FC_VARIABLE, 0, - &variable) == FcResultMatch) && variable) { - mHasVariations = true; - } - } else { - FT_Face face = GetFTFace(); - if (face) { - mHasVariations = face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS; - } - } - - return mHasVariations; + return false; } FT_MM_Var* gfxFontconfigFontEntry::GetMMVar() { if (mMMVarInitialized) { return mMMVar; } @@ -1203,39 +1190,32 @@ gfxFontconfigFontFamily::FindStyleVariat // figure out the psname/fullname and choose which to use as the facename nsAutoString psname, fullname; GetFaceNames(face, mName, psname, fullname); const nsAutoString& faceName = !psname.IsEmpty() ? psname : fullname; gfxFontconfigFontEntry *fontEntry = new gfxFontconfigFontEntry(faceName, face, mContainsAppFonts); - fontEntry->SetupVariationRanges(); - AddFontEntry(fontEntry); if (fontEntry->IsNormalStyle()) { numRegularFaces++; } if (LOG_FONTLIST_ENABLED()) { - nsAutoCString weightString; - fontEntry->Weight().ToString(weightString); - nsAutoCString stretchString; - fontEntry->Stretch().ToString(stretchString); - nsAutoCString styleString; - fontEntry->SlantStyle().ToString(styleString); LOG_FONTLIST(("(fontlist) added (%s) to family (%s)" - " with style: %s weight: %s stretch: %s" + " with style: %s weight: %g stretch: %g%%" " psname: %s fullname: %s", NS_ConvertUTF16toUTF8(fontEntry->Name()).get(), NS_ConvertUTF16toUTF8(Name()).get(), - styleString.get(), - weightString.get(), - stretchString.get(), + (fontEntry->IsItalic()) ? + "italic" : (fontEntry->IsOblique() ? "oblique" : "normal"), + fontEntry->Weight().ToFloat(), + fontEntry->Stretch().Percentage(), NS_ConvertUTF16toUTF8(psname).get(), NS_ConvertUTF16toUTF8(fullname).get())); } } // somewhat arbitrary, but define a family with two or more regular // faces as a family for which intra-family fallback should be used if (numRegularFaces > 1) { @@ -1331,17 +1311,17 @@ gfxFontconfigFontFamily::FindAllFontsFor double dist = SizeDistance(entry, aFontStyle, mForceScalable || aIgnoreSizeTolerance); // If the entry is scalable or has a style that does not match // the group of unscalable fonts, then start a new group. if (dist < 0.0 || !bestEntry || bestEntry->Stretch() != entry->Stretch() || bestEntry->Weight() != entry->Weight() || - bestEntry->SlantStyle() != entry->SlantStyle()) { + bestEntry->mStyle != entry->mStyle) { // If the best entry in this group is still outside the tolerance, // then skip the entire group. if (bestDist >= kRejectDistance) { skipped++; } // Remove any compacted entries from the previous group. if (skipped) { i -= skipped; @@ -1874,59 +1854,54 @@ gfxFcPlatformFontList::GetDefaultFontFor if (prefFonts && !prefFonts->IsEmpty()) { return (*prefFonts)[0]; } return nullptr; } gfxFontEntry* gfxFcPlatformFontList::LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) { nsAutoString keyName(aFontName); ToLowerCase(keyName); // if name is not in the global list, done FcPattern* fontPattern = mLocalNames.Get(keyName); if (!fontPattern) { return nullptr; } return new gfxFontconfigFontEntry(aFontName, fontPattern, - aWeightForEntry, - aStretchForEntry, - aStyleForEntry); + aWeight, aStretch, aStyle); } gfxFontEntry* gfxFcPlatformFontList::MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) { FT_Face face = Factory::NewFTFaceFromData(nullptr, aFontData, aLength, 0); if (!face) { free((void*)aFontData); return nullptr; } if (FT_Err_Ok != FT_Select_Charmap(face, FT_ENCODING_UNICODE)) { Factory::ReleaseFTFace(face); free((void*)aFontData); return nullptr; } - return new gfxFontconfigFontEntry(aFontName, - aWeightForEntry, - aStretchForEntry, - aStyleForEntry, - aFontData, aLength, face); + return new gfxFontconfigFontEntry(aFontName, aWeight, aStretch, + aStyle, aFontData, aLength, face); } bool gfxFcPlatformFontList::FindAndAddFamilies(const nsAString& aFamily, nsTArray<gfxFontFamily*>* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle, gfxFloat aDevToCssSize) @@ -2200,36 +2175,37 @@ gfxFcPlatformFontList::GetFTLibrary() // has been called on each FT_Face, at least until this bug is fixed: // https://bugs.freedesktop.org/show_bug.cgi?id=18857 // // Cairo keeps it's own FT_Library object for creating FT_Face // instances, so use that. There's no simple API for accessing this // so use the hacky method below of making a font and extracting // the library pointer from that. - FcPattern* pat = - FcPatternBuild(0, FC_FAMILY, FcTypeString, "serif", (char*)0); - cairo_font_face_t* face = - cairo_ft_font_face_create_for_pattern(pat, nullptr, 0); - FcPatternDestroy(pat); + bool needsBold; + gfxFontStyle style; + gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); + gfxFontFamily* family = pfl->GetDefaultFont(&style); + NS_ASSERTION(family, "couldn't find a default font family"); + gfxFontEntry* fe = family->FindFontForStyle(style, needsBold, true); + if (!fe) { + return nullptr; + } + RefPtr<gfxFont> font = fe->FindOrMakeFont(&style, false); + if (!font) { + return nullptr; + } - cairo_matrix_t identity; - cairo_matrix_init_identity(&identity); - cairo_font_options_t* options = cairo_font_options_create(); - cairo_scaled_font_t* sf = - cairo_scaled_font_create(face, &identity, &identity, options); - cairo_font_options_destroy(options); - cairo_font_face_destroy(face); + gfxFT2FontBase* ft2Font = reinterpret_cast<gfxFT2FontBase*>(font.get()); + gfxFT2LockedFace face(ft2Font); + if (!face.get()) { + return nullptr; + } - FT_Face ft = cairo_ft_scaled_font_lock_face(sf); - - sCairoFTLibrary = ft->glyph->library; - - cairo_ft_scaled_font_unlock_face(sf); - cairo_scaled_font_destroy(sf); + sCairoFTLibrary = face.get()->glyph->library; } return sCairoFTLibrary; } gfxPlatformFontList::PrefFontList* gfxFcPlatformFontList::FindGenericFamilies(const nsAString& aGeneric, nsAtom* aLanguage)
--- a/gfx/thebes/gfxFcPlatformFontList.h +++ b/gfx/thebes/gfxFcPlatformFontList.h @@ -89,29 +89,29 @@ public: // used for system fonts with explicit patterns explicit gfxFontconfigFontEntry(const nsAString& aFaceName, FcPattern* aFontPattern, bool aIgnoreFcCharmap); // used for data fonts where the fontentry takes ownership // of the font data and the FT_Face explicit gfxFontconfigFontEntry(const nsAString& aFaceName, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t *aData, uint32_t aLength, FT_Face aFace); // used for @font-face local system fonts with explicit patterns explicit gfxFontconfigFontEntry(const nsAString& aFaceName, FcPattern* aFontPattern, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle); + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle); gfxFontEntry* Clone() const override; FcPattern* GetPattern() { return mFontPattern; } nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override; bool TestCharacterMap(uint32_t aCh) override; @@ -163,23 +163,16 @@ protected: // Whether TestCharacterMap should check the actual cmap rather than asking // fontconfig about character coverage. // We do this for app-bundled (rather than system) fonts, as they may // include color glyphs that fontconfig would overlook, and for fonts // loaded via @font-face. bool mIgnoreFcCharmap; - // Whether the face supports variations. For system-installed fonts, we - // query fontconfig for this (so they will only work if fontconfig is - // recent enough to include support); for downloaded user-fonts we query - // the FreeType face. - bool mHasVariations; - bool mHasVariationsInitialized; - double mAspect; // data font const uint8_t* mFontData; uint32_t mLength; class UnscaledFontCache { @@ -291,25 +284,25 @@ public: const nsACString& aGenericFamily, nsTArray<nsString>& aListOfFonts) override; void ReadSystemFontList( InfallibleTArray<mozilla::dom::SystemFontListEntry>* retValue); gfxFontEntry* LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) override; + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) override; gfxFontEntry* MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) override; bool FindAndAddFamilies(const nsAString& aFamily, nsTArray<gfxFontFamily*>* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, gfxFloat aDevToCssSize = 1.0) override;
--- a/gfx/thebes/gfxFontEntry.cpp +++ b/gfx/thebes/gfxFontEntry.cpp @@ -75,19 +75,19 @@ gfxFontEntry::gfxFontEntry() : mGraphiteSpaceContextualsInitialized(false), mHasGraphiteSpaceContextuals(false), mSpaceGlyphIsInvisible(false), mSpaceGlyphIsInvisibleInitialized(false), mCheckedForGraphiteTables(false), mHasCmapTable(false), mGrFaceInitialized(false), mCheckedForColorGlyph(false), - mWeightRange(FontWeight(500)), - mStretchRange(FontStretch::Normal()), - mStyleRange(FontSlantStyle::Normal()), + mWeight(500), + mStretch(FontStretch::Normal()), + mStyle(FontSlantStyle::Normal()), mUVSOffset(0), mUVSData(nullptr), mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE), mCOLR(nullptr), mCPAL(nullptr), mUnitsPerEm(0), mHBFace(nullptr), mGrFace(nullptr), mGrFaceRefCnt(0), @@ -114,19 +114,19 @@ gfxFontEntry::gfxFontEntry(const nsAStri mGraphiteSpaceContextualsInitialized(false), mHasGraphiteSpaceContextuals(false), mSpaceGlyphIsInvisible(false), mSpaceGlyphIsInvisibleInitialized(false), mCheckedForGraphiteTables(false), mHasCmapTable(false), mGrFaceInitialized(false), mCheckedForColorGlyph(false), - mWeightRange(FontWeight(500)), - mStretchRange(FontStretch::Normal()), - mStyleRange(FontSlantStyle::Normal()), + mWeight(500), + mStretch(FontStretch::Normal()), + mStyle(FontSlantStyle::Normal()), mUVSOffset(0), mUVSData(nullptr), mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE), mCOLR(nullptr), mCPAL(nullptr), mUnitsPerEm(0), mHBFace(nullptr), mGrFace(nullptr), mGrFaceRefCnt(0), @@ -1027,133 +1027,16 @@ gfxFontEntry::GetColorLayersInfo(uint32_ return gfxFontUtils::GetColorGlyphLayers(mCOLR, mCPAL, aGlyphId, aDefaultColor, aLayerGlyphs, aLayerColors); } -void -gfxFontEntry::SetupVariationRanges() -{ - if (!HasVariations() || IsUserFont()) { - return; - } - AutoTArray<gfxFontVariationAxis,4> axes; - GetVariationAxes(axes); - for (const auto& axis : axes) { - switch (axis.mTag) { - case HB_TAG('w','g','h','t'): - // If the axis range looks like it doesn't fit the CSS font-weight - // scale, we don't hook up the high-level property. Setting 'wght' - // with font-variation-settings will still work. - // Strictly speaking, the min value should be checked against 1.0, - // not 0.0, but we'll allow font makers that amount of leeway, as - // in practice a number of fonts seem to use 0..1000. - if (axis.mMinValue >= 0.0f && axis.mMaxValue <= 1000.0f && - // If axis.mMaxValue is less than the default weight we already - // set up, assume the axis has a non-standard range (like Skia) - // and don't try to map it. - Weight().Min() <= FontWeight(axis.mMaxValue)) { - if (FontWeight(axis.mDefaultValue) != Weight().Min()) { - mStandardFace = false; - } - mWeightRange = - WeightRange(FontWeight(std::max(1.0f, axis.mMinValue)), - FontWeight(axis.mMaxValue)); - } - break; - - case HB_TAG('w','d','t','h'): - if (axis.mMinValue >= 0.0f && axis.mMaxValue <= 1000.0f && - Stretch().Min() <= FontStretch(axis.mMaxValue)) { - if (FontStretch(axis.mDefaultValue) != Stretch().Min()) { - mStandardFace = false; - } - mStretchRange = - StretchRange(FontStretch(axis.mMinValue), - FontStretch(axis.mMaxValue)); - } - break; - - case HB_TAG('s','l','n','t'): - if (axis.mMinValue >= -90.0f && axis.mMaxValue <= 90.0f) { - if (FontSlantStyle::Oblique(axis.mDefaultValue) != SlantStyle().Min()) { - mStandardFace = false; - } - mStyleRange = - SlantStyleRange(FontSlantStyle::Oblique(axis.mMinValue), - FontSlantStyle::Oblique(axis.mMaxValue)); - } - break; - - // case HB_TAG('i','t','a','l'): // XXX how to handle? - default: - continue; - } - } -} - -void -gfxFontEntry::GetVariationsForStyle(nsTArray<gfxFontVariation>& aResult, - const gfxFontStyle& aStyle) -{ - // Resolve high-level CSS properties from the requested style - // (font-{style,weight,stretch}) to the appropriate variations. - float clampedWeight = Weight().Clamp(aStyle.weight).ToFloat(); - aResult.AppendElement(gfxFontVariation{HB_TAG('w','g','h','t'), - clampedWeight}); - - float clampedStretch = Stretch().Clamp(aStyle.stretch).Percentage(); - aResult.AppendElement(gfxFontVariation{HB_TAG('w','d','t','h'), - clampedStretch}); - - if (SlantStyle().Min().IsOblique()) { - float clampedSlant = - aStyle.style.IsOblique() - ? SlantStyle().Clamp(aStyle.style).ObliqueAngle() - : aStyle.style.IsItalic() - ? SlantStyle().Clamp(FontSlantStyle::Oblique()).ObliqueAngle() - : SlantStyle().Clamp(FontSlantStyle::Oblique(0.0f)).ObliqueAngle(); - aResult.AppendElement(gfxFontVariation{HB_TAG('s','l','n','t'), - clampedSlant}); - } - - // Although there is a registered tag 'ital', it is normally considered - // a binary toggle rather than a variable axis, - - auto replaceOrAppend = [&aResult](const gfxFontVariation& aSetting) { - struct TagEquals { - bool Equals(const gfxFontVariation& aIter, uint32_t aTag) const { - return aIter.mTag == aTag; - } - }; - auto index = aResult.IndexOf(aSetting.mTag, 0, TagEquals()); - if (index == aResult.NoIndex) { - aResult.AppendElement(aSetting); - } else { - aResult[index].mValue = aSetting.mValue; - } - }; - - // The low-level font-variation-settings descriptor from @font-face, - // if present, takes precedence over automatic variation settings - // from high-level properties. - for (const auto& v : mVariationSettings) { - replaceOrAppend(v); - } - - // And the low-level font-variation-settings property takes precedence - // over the descriptor. - for (const auto& v : aStyle.variationSettings) { - replaceOrAppend(v); - } -} - size_t gfxFontEntry::FontTableHashEntry::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { size_t n = 0; if (mBlob) { n += aMallocSizeOf(mBlob); } if (mSharedBlobData) { @@ -1290,179 +1173,135 @@ gfxFontFamily::FindFontForStyle(const gf FindAllFontsForStyle(aFontStyle, matched, aNeedsSyntheticBold, aIgnoreSizeTolerance); if (!matched.IsEmpty()) { return matched[0]; } return nullptr; } -// style distance ==> [0,500] -static inline double -StyleDistance(const gfxFontEntry* aFontEntry, FontSlantStyle aTargetStyle) -{ - FontSlantStyle minStyle = aFontEntry->SlantStyle().Min(); - if (aTargetStyle == minStyle) { - return 0.0; // styles match exactly ==> 0 - } - - // Compare oblique angles to see how closely they match. - // The range of angles is [-90.0 .. 90.0], although in practice values - // are unlikely to get anywhere near the extremes. - // The style 'italic' is treated as having the same angle as the default - // for 'oblique', but with a constant added to the distance to reflect - // distinction. - - double extraDistance = 0.0; - const double kReverseDistance = 100.0; - - double target; - if (aTargetStyle.IsNormal()) { - target = 0.0; - extraDistance = 300.0; - } else if (aTargetStyle.IsOblique()) { - target = aTargetStyle.ObliqueAngle(); - } else { - target = FontSlantStyle::Oblique().ObliqueAngle(); - extraDistance = 200.0; - } +#define STYLE_SHIFT 2 // number of bits to contain style distance - FontSlantStyle maxStyle = aFontEntry->SlantStyle().Max(); - - double minAngle, maxAngle; - // There can only be a range of styles if it's oblique - if (minStyle.IsNormal()) { - minAngle = maxAngle = 0.0; - extraDistance = 300.0; - } else if (minStyle.IsOblique()) { - MOZ_ASSERT(maxStyle.IsOblique()); - minAngle = minStyle.ObliqueAngle(); - maxAngle = maxStyle.ObliqueAngle(); - } else { - minAngle = maxAngle = FontSlantStyle::Oblique().ObliqueAngle(); - extraDistance = 200.0; +// style distance ==> [0,2] +static inline uint32_t +StyleDistance(FontSlantStyle aFontStyle, FontSlantStyle aTargetStyle) +{ + if (aFontStyle == aTargetStyle) { + return 0; // styles match exactly ==> 0 } - - double distance = 0.0; - if (target < minAngle || target > maxAngle) { - if (target > 0.0) { - distance = minAngle - target; - } else { - distance = target - maxAngle; - } + if (aFontStyle == FontSlantStyle::Normal() || + aTargetStyle == FontSlantStyle::Normal()) { + return 2; // one is normal (but not the other) ==> 2 } - if (distance < 0.0) { - distance = kReverseDistance - distance; - } - - return distance + extraDistance; + return 1; // neither is normal; must be italic vs oblique ==> 1 } -// stretch distance ==> [0,2000] -static inline double -StretchDistance(const gfxFontEntry* aFontEntry, FontStretch aTargetStretch) +#define REVERSE_STRETCH_DISTANCE 200.0f + +// stretch distance ==> [0,350] +static inline uint32_t +StretchDistance(FontStretch aFontStretch, FontStretch aTargetStretch) { - const double kReverseDistance = 1000.0; - double distance = 0.0; - - FontStretch minStretch = aFontEntry->Stretch().Min(); - FontStretch maxStretch = aFontEntry->Stretch().Max(); - - if (aTargetStretch < minStretch || aTargetStretch > maxStretch) { - // stretch values are in the range 0 .. 1000 + float distance = 0.0f; + if (aTargetStretch != aFontStretch) { + // stretch values are in the range 50 .. 200 // if aTargetStretch is >100, we prefer larger values; // if <=100, prefer smaller if (aTargetStretch > FontStretch::Normal()) { - distance = (minStretch - aTargetStretch); + distance = (aFontStretch - aTargetStretch); } else { - distance = (aTargetStretch - maxStretch); + distance = (aTargetStretch - aFontStretch); } // if the computed "distance" here is negative, it means that // aFontEntry lies in the "non-preferred" direction from aTargetStretch, // so we treat that as larger than any preferred-direction distance - // (max possible is 1000) by adding an extra 1000 to the absolute value + // (max possible is 150) by adding an extra 200 to the absolute value if (distance < 0.0f) { - distance = kReverseDistance - distance; + distance = -distance + REVERSE_STRETCH_DISTANCE; } } - return distance; + return uint32_t(distance); } +// CSS currently limits font weights to multiples of 100 but the weight +// matching code below does not assume this. +// // Calculate weight distance with values in the range (0..1000). In general, // heavier weights match towards even heavier weights while lighter weights // match towards even lighter weights. Target weight values in the range // [400..500] are special, since they will first match up to 500, then down // towards 0, then up again towards 999. // // Example: with target 600 and font weight 800, distance will be 200. With // target 300 and font weight 600, distance will be 900, since heavier // weights are farther away than lighter weights. If the target is 5 and the // font weight 995, the distance would be 1590 for the same reason. -// weight distance ==> [0,1600] -static inline double -WeightDistance(const gfxFontEntry* aFontEntry, FontWeight aTargetWeight) -{ - const double kReverseDistance = 600.0; +#define REVERSE_WEIGHT_DISTANCE 600 +#define WEIGHT_SHIFT 11 // number of bits to contain weight distance - double distance = 0.0, addedDistance = 0.0; - FontWeight minWeight = aFontEntry->Weight().Min(); - FontWeight maxWeight = aFontEntry->Weight().Max(); - if (aTargetWeight < minWeight || aTargetWeight > maxWeight) { +// weight distance ==> [0,1598] +static inline uint32_t +WeightDistance(FontWeight aFontWeight, FontWeight aTargetWeight) +{ + // Compute a measure of the "distance" between the requested + // weight and the given fontEntry + + float distance = 0.0f, addedDistance = 0.0f; + if (aTargetWeight != aFontWeight) { if (aTargetWeight > FontWeight(500)) { - distance = minWeight - aTargetWeight; + distance = aFontWeight - aTargetWeight; } else if (aTargetWeight < FontWeight(400)) { - distance = aTargetWeight - maxWeight; + distance = aTargetWeight - aFontWeight; } else { // special case - target is between 400 and 500 // font weights between 400 and 500 are close - if (maxWeight >= FontWeight(400) && - minWeight <= FontWeight(500)) { - if (maxWeight < aTargetWeight) { - distance = FontWeight(500) - maxWeight; + if (aFontWeight >= FontWeight(400) && + aFontWeight <= FontWeight(500)) { + if (aFontWeight < aTargetWeight) { + distance = FontWeight(500) - aFontWeight; } else { - distance = minWeight - aTargetWeight; + distance = aFontWeight - aTargetWeight; } } else { // font weights outside use rule for target weights < 400 with // added distance to separate from font weights in // the [400..500] range - distance = aTargetWeight - maxWeight; - addedDistance = 100.0; + distance = aTargetWeight - aFontWeight; + addedDistance = 100; } } - if (distance < 0.0) { - distance = kReverseDistance - distance; + if (distance < 0.0f) { + distance = -distance + REVERSE_WEIGHT_DISTANCE; } distance += addedDistance; } - return distance; + return uint32_t(distance); } -#define MAX_DISTANCE 1.0e20 // >> than any WeightStyleStretchDistance result +#define MAX_DISTANCE 0xffffffff -static inline double +static inline uint32_t WeightStyleStretchDistance(gfxFontEntry* aFontEntry, const gfxFontStyle& aTargetStyle) { - double stretchDist = StretchDistance(aFontEntry, aTargetStyle.stretch); - double styleDist = StyleDistance(aFontEntry, aTargetStyle.style); - double weightDist = WeightDistance(aFontEntry, aTargetStyle.weight); + // weight/style/stretch priority: stretch >> style >> weight + uint32_t stretchDist = + StretchDistance(aFontEntry->mStretch, aTargetStyle.stretch); + uint32_t styleDist = StyleDistance(aFontEntry->mStyle, aTargetStyle.style); + uint32_t weightDist = + WeightDistance(aFontEntry->Weight(), aTargetStyle.weight); - // Sanity-check that the distances are within the expected range - // (update if implementation of the distance functions is changed). - MOZ_ASSERT(stretchDist >= 0.0 && stretchDist <= 2000.0); - MOZ_ASSERT(styleDist >= 0.0 && styleDist <= 500.0); - MOZ_ASSERT(weightDist >= 0.0 && weightDist <= 1600.0); + NS_ASSERTION(weightDist < (1 << WEIGHT_SHIFT), "weight value out of bounds"); + NS_ASSERTION(styleDist < (1 << STYLE_SHIFT), "slope value out of bounds"); - // weight/style/stretch priority: stretch >> style >> weight - // so we multiply the stretch and style values to make them dominate - // the result - return stretchDist * 1.0e8 + styleDist * 1.0e4 + weightDist; + return (stretchDist << (STYLE_SHIFT + WEIGHT_SHIFT)) | + (styleDist << WEIGHT_SHIFT) | + weightDist; } void gfxFontFamily::FindAllFontsForStyle(const gfxFontStyle& aFontStyle, nsTArray<gfxFontEntry*>& aFontEntryList, bool& aNeedsSyntheticBold, bool aIgnoreSizeTolerance) { @@ -1543,24 +1382,24 @@ gfxFontFamily::FindAllFontsForStyle(cons // given but the 99% use case is only a single font entry per // weight/style/stretch distance value. To optimize this, only add entries // to the matched font array when another entry already has the same // weight/style/stretch distance and add the last matched font entry. For // normal platform fonts with a single font entry for each // weight/style/stretch combination, only the last matched font entry will // be added. - double minDistance = MAX_DISTANCE; + uint32_t minDistance = MAX_DISTANCE; gfxFontEntry* matched = nullptr; // iterate in forward order so that faces like 'Bold' are matched before // matching style distance faces such as 'Bold Outline' (see bug 1185812) for (uint32_t i = 0; i < count; i++) { fe = mAvailableFonts[i]; // weight/style/stretch priority: stretch >> style >> weight - double distance = WeightStyleStretchDistance(fe, aFontStyle); + uint32_t distance = WeightStyleStretchDistance(fe, aFontStyle); if (distance < minDistance) { matched = fe; if (!aFontEntryList.IsEmpty()) { aFontEntryList.Clear(); } minDistance = distance; } else if (distance == minDistance) { if (matched) { @@ -1595,33 +1434,27 @@ gfxFontFamily::CheckForSimpleFamily() // if none then the family is unusable anyway } if (count == 1) { mIsSimpleFamily = true; return; } - StretchRange firstStretch = mAvailableFonts[0]->Stretch(); - if (!firstStretch.IsSingle()) { - return; // family with variation fonts is not considered "simple" - } + FontStretch firstStretch = mAvailableFonts[0]->Stretch(); gfxFontEntry *faces[4] = { 0 }; for (uint8_t i = 0; i < count; ++i) { gfxFontEntry *fe = mAvailableFonts[i]; if (fe->Stretch() != firstStretch || fe->IsOblique()) { // simple families don't have varying font-stretch or oblique return; } - if (!fe->Weight().IsSingle() || !fe->SlantStyle().IsSingle()) { - return; // family with variation fonts is not considered "simple" - } uint8_t faceIndex = (fe->IsItalic() ? kItalicMask : 0) | - (fe->IsBold() ? kBoldMask : 0); + (fe->Weight() >= FontWeight(600) ? kBoldMask : 0); if (faces[faceIndex]) { return; // two faces resolve to the same slot; family isn't "simple" } faces[faceIndex] = fe; } // we have successfully slotted the available faces into the standard // 4-face framework @@ -1658,51 +1491,43 @@ gfxFontFamily::ContainsFace(gfxFontEntry void gfxFontFamily::LocalizedName(nsAString& aLocalizedName) { // just return the primary name; subclasses should override aLocalizedName = mName; } // metric for how close a given font matches a style -static float +static int32_t CalcStyleMatch(gfxFontEntry *aFontEntry, const gfxFontStyle *aStyle) { - float rank = 0; + int32_t rank = 0; if (aStyle) { - // TODO: stretch - - // italics - bool wantUpright = aStyle->style.IsNormal(); - if (aFontEntry->IsUpright() == wantUpright) { - rank += 5000.0f; - } + // italics + bool wantUpright = aStyle->style.IsNormal(); + if (aFontEntry->IsUpright() == wantUpright) { + rank += 10; + } // measure of closeness of weight to the desired value - if (aFontEntry->Weight().Min() > aStyle->weight) { - rank += aFontEntry->Weight().Min() - aStyle->weight; - } else if (aFontEntry->Weight().Max() < aStyle->weight) { - rank += aStyle->weight - aFontEntry->Weight().Max(); - } else { - rank += 2000.0f; // the font supports the exact weight wanted - } + rank += 9 - Abs((aFontEntry->Weight() - aStyle->weight) / 100.0f); } else { // if no font to match, prefer non-bold, non-italic fonts if (aFontEntry->IsUpright()) { - rank += 2000.0f; + rank += 3; } if (!aFontEntry->IsBold()) { - rank += 1000.0f; + rank += 2; } } return rank; } -#define RANK_MATCHED_CMAP 10000.0f +#define RANK_MATCHED_CMAP 20 void gfxFontFamily::FindFontForChar(GlobalFontMatch *aMatchData) { if (mFamilyCharacterMapInitialized && !TestCharacterMap(aMatchData->mCh)) { // none of the faces in the family support the required char, // so bail out immediately return; @@ -1710,17 +1535,17 @@ gfxFontFamily::FindFontForChar(GlobalFon bool needsBold; gfxFontEntry *fe = FindFontForStyle(aMatchData->mStyle ? *aMatchData->mStyle : gfxFontStyle(), needsBold, true); if (fe && !fe->SkipDuringSystemFallback()) { - float rank = 0; + int32_t rank = 0; if (fe->HasCharacter(aMatchData->mCh)) { rank += RANK_MATCHED_CMAP; aMatchData->mCount++; LogModule* log = gfxPlatform::GetLog(eGfxLog_textrun); if (MOZ_UNLIKELY(MOZ_LOG_TEST(log, LogLevel::Debug))) { @@ -1770,17 +1595,17 @@ gfxFontFamily::FindFontForChar(GlobalFon void gfxFontFamily::SearchAllFontsForChar(GlobalFontMatch *aMatchData) { uint32_t i, numFonts = mAvailableFonts.Length(); for (i = 0; i < numFonts; i++) { gfxFontEntry *fe = mAvailableFonts[i]; if (fe && fe->HasCharacter(aMatchData->mCh)) { - float rank = RANK_MATCHED_CMAP; + int32_t rank = RANK_MATCHED_CMAP; rank += CalcStyleMatch(fe, aMatchData->mStyle); if (rank > aMatchData->mMatchRank || (rank == aMatchData->mMatchRank && Compare(fe->Name(), aMatchData->mBestMatch->Name()) > 0)) { aMatchData->mBestMatch = fe; aMatchData->mMatchedFamily = this; aMatchData->mMatchRank = rank;
--- a/gfx/thebes/gfxFontEntry.h +++ b/gfx/thebes/gfxFontEntry.h @@ -110,19 +110,16 @@ struct gfxFontFeatureInfo { class gfxFontEntry { public: typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::unicode::Script Script; typedef mozilla::FontWeight FontWeight; typedef mozilla::FontSlantStyle FontSlantStyle; typedef mozilla::FontStretch FontStretch; - typedef mozilla::WeightRange WeightRange; - typedef mozilla::SlantStyleRange SlantStyleRange; - typedef mozilla::StretchRange StretchRange; // Used by stylo NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontEntry) explicit gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false); // Create a new entry that refers to the same font as this, but without // additional state that may have been set up (such as family name). @@ -141,43 +138,40 @@ public: // will (usually, except on Linux) load and parse the 'name' table; // they are intended only for the font-inspection API, not for // perf-critical layout/drawing work. // The "real" name of the face, if available from the font resource; // returns Name() if nothing better is available. virtual nsString RealFaceName(); - WeightRange Weight() const { return mWeightRange; } - StretchRange Stretch() const { return mStretchRange; } - SlantStyleRange SlantStyle() const { return mStyleRange; } + FontWeight Weight() const { return mWeight; } + FontStretch Stretch() const { return mStretch; } bool IsUserFont() const { return mIsDataUserFont || mIsLocalUserFont; } bool IsLocalUserFont() const { return mIsLocalUserFont; } bool IsFixedPitch() const { return mFixedPitch; } - bool IsItalic() const { return SlantStyle().Min().IsItalic(); } - bool IsOblique() const { return SlantStyle().Min().IsOblique(); } - bool IsUpright() const { return SlantStyle().Min().IsNormal(); } - bool IsBold() const { return Weight().Max().IsBold(); } // bold == weights 600 and above + bool IsItalic() const { return mStyle.IsItalic(); } + bool IsOblique() const { return mStyle.IsOblique(); } + bool IsUpright() const { return mStyle.IsNormal(); } + bool IsBold() const { return mWeight.IsBold(); } // bold == weights 600 and above bool IgnoreGDEF() const { return mIgnoreGDEF; } bool IgnoreGSUB() const { return mIgnoreGSUB; } // Return whether the face corresponds to "normal" CSS style properties: // font-style: normal; // font-weight: normal; // font-stretch: normal; // If this is false, we might want to fall back to a different face and // possibly apply synthetic styling. bool IsNormalStyle() const { return IsUpright() && - Weight().Min() <= FontWeight::Normal() && - Weight().Max() >= FontWeight::Normal() && - Stretch().Min() <= FontStretch::Normal() && - Stretch().Max() >= FontStretch::Normal(); + Weight() == FontWeight::Normal() && + Stretch().IsNormal(); } // 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) virtual bool SupportsOpenTypeFeature(Script aScript, uint32_t aFeatureTag); bool SupportsGraphiteFeature(uint32_t aFeatureTag); // returns a set containing all input glyph ids for a given feature @@ -371,26 +365,16 @@ public: } virtual void GetVariationAxes(nsTArray<gfxFontVariationAxis>& aVariationAxes) { } virtual void GetVariationInstances(nsTArray<gfxFontVariationInstance>& aInstances) { } - // Set up the entry's weight/stretch/style ranges according to axes found - // by GetVariationAxes (for installed fonts; do NOT call this for user - // fonts, where the ranges are provided by @font-face descriptors). - void SetupVariationRanges(); - - // Get variation axis settings that should be used to implement a particular - // font style using this resource. - void GetVariationsForStyle(nsTArray<gfxFontVariation>& aResult, - const gfxFontStyle& aStyle); - // Get the font's list of features (if any) for DevTools support. void GetFeatureInfo(nsTArray<gfxFontFeatureInfo>& aFeatureInfo); nsString mName; nsString mFamilyName; bool mFixedPitch : 1; bool mIsBadUnderlineFont : 1; @@ -416,19 +400,19 @@ public: bool mGrFaceInitialized : 1; bool mCheckedForColorGlyph : 1; // bitvector of substitution space features per script, one each // for default and non-default features uint32_t mDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32]; uint32_t mNonDefaultSubSpaceFeatures[(int(Script::NUM_SCRIPT_CODES) + 31) / 32]; - WeightRange mWeightRange; - StretchRange mStretchRange; - SlantStyleRange mStyleRange; + FontWeight mWeight; + FontStretch mStretch; + FontSlantStyle mStyle; RefPtr<gfxCharacterMap> mCharacterMap; uint32_t mUVSOffset; mozilla::UniquePtr<uint8_t[]> mUVSData; mozilla::UniquePtr<gfxUserFontData> mUserFontData; mozilla::UniquePtr<gfxSVGGlyphs> mSVGGlyphs; // list of gfxFonts that are using SVG glyphs nsTArray<gfxFont*> mFontsUsingSVGGlyphs; @@ -623,24 +607,24 @@ private: }; // used when iterating over all fonts looking for a match for a given character struct GlobalFontMatch { GlobalFontMatch(const uint32_t aCharacter, const gfxFontStyle *aStyle) : mCh(aCharacter), mStyle(aStyle), - mMatchRank(0.0f), mCount(0), mCmapsTested(0) + mMatchRank(0), mCount(0), mCmapsTested(0) { } const uint32_t mCh; // codepoint to be matched const gfxFontStyle* mStyle; // style to match - float mMatchRank; // metric indicating closest match + int32_t mMatchRank; // metric indicating closest match RefPtr<gfxFontEntry> mBestMatch; // current best match RefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to uint32_t mCount; // number of fonts matched uint32_t mCmapsTested; // number of cmaps tested }; class gfxFontFamily { public:
--- a/gfx/thebes/gfxFontUtils.cpp +++ b/gfx/thebes/gfxFontUtils.cpp @@ -1939,16 +1939,34 @@ gfxFontUtils::GetVariationInstances(gfxF value.mAxis = axes[j].axisTag; value.mValue = int32_t(coords[j]) / 65536.0; instance.mValues.AppendElement(value); } aInstances.AppendElement(instance); } } +void +gfxFontUtils::MergeVariations(const nsTArray<gfxFontVariation>& aEntrySettings, + const nsTArray<gfxFontVariation>& aStyleSettings, + nsTArray<gfxFontVariation>* aMerged) +{ + MOZ_ASSERT(!aEntrySettings.IsEmpty() && + !aStyleSettings.IsEmpty() && + aMerged->IsEmpty()); + // Settings from the CSS style will take precedence over those from the + // font entry (i.e. from the @font-face descriptor). + aMerged->AppendElements(aStyleSettings); + for (auto& setting : aEntrySettings) { + if (!aMerged->Contains(setting.mTag, VariationTagComparator())) { + aMerged->AppendElement(setting); + } + } +} + #ifdef XP_WIN /* static */ bool gfxFontUtils::IsCffFont(const uint8_t* aFontData) { // this is only called after aFontData has passed basic validation, // so we know there is enough data present to allow us to read the version!
--- a/gfx/thebes/gfxFontUtils.h +++ b/gfx/thebes/gfxFontUtils.h @@ -1005,16 +1005,32 @@ public: // platforms where the native font APIs don't provide the info we want // in a convenient form. // (Not used on platforms -- currently, freetype -- where the font APIs // expose variation instance details directly.) static void GetVariationInstances(gfxFontEntry* aFontEntry, nsTArray<gfxFontVariationInstance>& aInstances); + // Merge a list of font-variation-settings from a font entry and a list + // from a gfxFontStyle, to get a combined collection of settings that can + // be used to instantiate a font. + static void + MergeVariations(const nsTArray<gfxFontVariation>& aEntrySettings, + const nsTArray<gfxFontVariation>& aStyleSettings, + nsTArray<gfxFontVariation>* aMerged); + + // Helper used by MergeVariations, and other code that wants to check + // whether an array of variation settings includes a particular tag. + struct VariationTagComparator { + bool Equals(const gfxFontVariation& aVariation, uint32_t aTag) const { + return aVariation.mTag == aTag; + } + }; + protected: friend struct MacCharsetMappingComparator; static nsresult ReadNames(const char *aNameData, uint32_t aDataLen, uint32_t aNameID, int32_t aLangID, int32_t aPlatformID, nsTArray<nsString>& aNames); // convert opentype name-table platform/encoding/language values to an
--- a/gfx/thebes/gfxGDIFont.cpp +++ b/gfx/thebes/gfxGDIFont.cpp @@ -455,20 +455,17 @@ gfxGDIFont::FillLogFont(LOGFONTW& aLogFo // choice of actual face used (bug 724231) weight = 0; } else { // avoid GDI synthetic bold which occurs when weight // specified is >= font data weight + 200 weight = mNeedsBold ? 700 : 200; } } else { - // GDI doesn't support variation fonts, so for system fonts we know - // that the entry has only a single weight, not a range. - MOZ_ASSERT(fe->Weight().IsSingle()); - weight = mNeedsBold ? 700 : fe->Weight().Min().ToIntRounded(); + weight = mNeedsBold ? 700 : fe->Weight().ToIntRounded(); } fe->FillLogFont(&aLogFont, weight, aSize); } uint32_t gfxGDIFont::GetGlyph(uint32_t aUnicode, uint32_t aVarSelector) {
--- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -110,42 +110,42 @@ FontTypeToOutPrecision(uint8_t fontType) /*************************************************************** * * GDIFontEntry * */ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType, - SlantStyleRange aStyle, - WeightRange aWeight, - StretchRange aStretch, + FontSlantStyle aStyle, + FontWeight aWeight, + FontStretch aStretch, gfxUserFontData *aUserFontData) : gfxFontEntry(aFaceName), mFontType(aFontType), mForceGDI(false), mUnicodeRanges() { mUserFontData.reset(aUserFontData); - mStyleRange = aStyle; - mWeightRange = aWeight; - mStretchRange = aStretch; + mStyle = aStyle; + mWeight = aWeight; + mStretch = aStretch; if (IsType1()) mForceGDI = true; mIsDataUserFont = aUserFontData != nullptr; InitLogFont(aFaceName, aFontType); } gfxFontEntry* GDIFontEntry::Clone() const { MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!"); - return new GDIFontEntry(Name(), mFontType, SlantStyle(), Weight(), - Stretch(), nullptr); + return new GDIFontEntry(Name(), mFontType, mStyle, mWeight, mStretch, + nullptr); } nsresult GDIFontEntry::ReadCMAP(FontInfoData *aFontInfoData) { AUTO_PROFILER_LABEL("GDIFontEntry::ReadCMAP", OTHER); // attempt this once, if errors occur leave a blank cmap @@ -300,17 +300,17 @@ GDIFontEntry::TestCharacterMap(uint32_t if (aCh > 0xFFFF) return false; // previous code was using the group style gfxFontStyle fakeStyle; if (!IsUpright()) { fakeStyle.style = FontSlantStyle::Italic(); } - fakeStyle.weight = Weight().Min(); + fakeStyle.weight = mWeight; RefPtr<gfxFont> tempFont = FindOrMakeFont(&fakeStyle, false); if (!tempFont || !tempFont->Valid()) return false; gfxGDIFont *font = static_cast<gfxGDIFont*>(tempFont.get()); HDC dc = GetDC((HWND)nullptr); SetGraphicsMode(dc, GM_ADVANCED); @@ -379,29 +379,29 @@ GDIFontEntry::InitLogFont(const nsAStrin mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION; mLogFont.lfQuality = DEFAULT_QUALITY; mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; // always force lfItalic if we want it. Font selection code will // do its best to give us an italic font entry, but if no face exists // it may give us a regular one based on weight. Windows should // do fake italic for us in that case. mLogFont.lfItalic = !IsUpright(); - mLogFont.lfWeight = Weight().Min().ToIntRounded(); + mLogFont.lfWeight = int(mWeight.ToFloat()); int len = std::min<int>(aName.Length(), LF_FACESIZE - 1); memcpy(&mLogFont.lfFaceName, aName.BeginReading(), len * sizeof(char16_t)); mLogFont.lfFaceName[len] = '\0'; } GDIFontEntry* GDIFontEntry::CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, - SlantStyleRange aStyle, - WeightRange aWeight, - StretchRange aStretch, + FontSlantStyle aStyle, + FontWeight aWeight, + FontStretch aStretch, gfxUserFontData* aUserFontData) { // jtdfix - need to set charset, unicode ranges, pitch/family GDIFontEntry *fe = new GDIFontEntry(aName, aFontType, aStyle, aWeight, aStretch, aUserFontData); return fe; @@ -462,35 +462,35 @@ GDIFontFamily::FamilyAddStylesProc(const // otherwise if the new type is worse, skip it return 1; } } for (uint32_t i = 0; i < ff->mAvailableFonts.Length(); ++i) { fe = static_cast<GDIFontEntry*>(ff->mAvailableFonts[i].get()); // check if we already know about this face - if (fe->Weight().Min() == FontWeight(int32_t(logFont.lfWeight)) && + if (fe->mWeight == FontWeight(int32_t(logFont.lfWeight)) && fe->IsItalic() == (logFont.lfItalic == 0xFF)) { // update the charset bit here since this could be different // XXX Can we still do this now that we store mCharset // on the font family rather than the font entry? ff->mCharset.set(metrics.tmCharSet); return 1; } } // We can't set the hasItalicFace flag correctly here, // because we might not have seen the family's italic face(s) yet. // So we'll set that flag for all members after loading all the faces. auto italicStyle = (logFont.lfItalic == 0xFF ? FontSlantStyle::Italic() : FontSlantStyle::Normal()); fe = GDIFontEntry::CreateFontEntry(nsDependentString(lpelfe->elfFullName), - feType, SlantStyleRange(italicStyle), - WeightRange(FontWeight(int32_t(logFont.lfWeight))), - StretchRange(FontStretch::Normal()), + feType, italicStyle, + FontWeight(int32_t(logFont.lfWeight)), + FontStretch::Normal(), nullptr); if (!fe) return 1; ff->AddFontEntry(fe); if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 && nmetrics->ntmFontSig.fsUsb[1] != 0x00000000 && @@ -503,22 +503,25 @@ GDIFontFamily::FamilyAddStylesProc(const DWORD range = nmetrics->ntmFontSig.fsUsb[i]; for (uint32_t k = 0; k < 32; ++k) { fe->mUnicodeRanges.set(x++, (range & (1 << k)) != 0); } } } if (LOG_FONTLIST_ENABLED()) { + nsAutoCString stretchString; LOG_FONTLIST(("(fontlist) added (%s) to family (%s)" - " with style: %s weight: %d stretch: normal", + " with style: %s weight: %d stretch: %g%%", NS_ConvertUTF16toUTF8(fe->Name()).get(), NS_ConvertUTF16toUTF8(ff->Name()).get(), (logFont.lfItalic == 0xff) ? "italic" : "normal", - logFont.lfWeight)); + logFont.lfWeight, + fe->Stretch().Percentage(), + stretchString.get())); } return 1; } void GDIFontFamily::FindStyleVariations(FontInfoData *aFontInfoData) { if (mHasStyles) @@ -706,46 +709,45 @@ gfxGDIFontList::EnumFontFamExProc(ENUMLO family->mCharset.set(metrics.tmCharSet); } return 1; } gfxFontEntry* gfxGDIFontList::LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) { gfxFontEntry *lookup; lookup = LookupInFaceNameLists(aFontName); if (!lookup) { return nullptr; } bool isCFF = false; // jtdfix -- need to determine this // use the face name from the lookup font entry, which will be the localized // face name which GDI mapping tables use (e.g. with the system locale set to // Dutch, a fullname of 'Arial Bold' will find a font entry with the face name // 'Arial Vet' which can be used as a key in GDI font lookups). GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(lookup->Name(), gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/, - lookup->SlantStyle(), lookup->Weight(), aStretchForEntry, nullptr); + lookup->mStyle, lookup->mWeight, aStretch, nullptr); if (!fe) return nullptr; fe->mIsLocalUserFont = true; // make the new font entry match the userfont entry style characteristics - fe->mWeightRange = aWeightForEntry; - fe->mStyleRange = aStyleForEntry; - fe->mStretchRange = aStretchForEntry; + fe->mWeight = aWeight; + fe->mStyle = aStyle; return fe; } // If aFontData contains only a MS/Symbol cmap subtable, not MS/Unicode, // we modify the subtable header to mark it as Unicode instead, because // otherwise GDI will refuse to load the font. // NOTE that this function does not bounds-check every access to the font data. @@ -799,19 +801,19 @@ FixupSymbolEncodedFont(uint8_t* aFontDat return true; } } return false; } gfxFontEntry* gfxGDIFontList::MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) { // MakePlatformFont is responsible for deleting the font data with free // so we set up a stack object to ensure it is freed even if we take an // early exit struct FontDataDeleter { explicit FontDataDeleter(const uint8_t* aFontData) @@ -866,17 +868,17 @@ gfxGDIFontList::MakePlatformFont(const n RemoveFontMemResourceEx(fontRef); return nullptr; } // make a new font entry using the unique name WinUserFontData *winUserFontData = new WinUserFontData(fontRef); GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(uniqueName, gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/, - aStyleForEntry, aWeightForEntry, aStretchForEntry, winUserFontData); + aStyle, aWeight, aStretch, winUserFontData); if (fe) { fe->mIsDataUserFont = true; } return fe; }
--- a/gfx/thebes/gfxGDIFontList.h +++ b/gfx/thebes/gfxGDIFontList.h @@ -103,16 +103,20 @@ enum gfxWindowsFontType { }; // A single member of a font family (i.e. a single face, such as Times Italic) // represented as a LOGFONT that will resolve to the correct face. // This replaces FontEntry from gfxWindowsFonts.h/cpp. class GDIFontEntry : public gfxFontEntry { public: + typedef mozilla::FontStretch FontStretch; + typedef mozilla::FontSlantStyle FontSlantStyle; + typedef mozilla::FontWeight FontWeight; + LPLOGFONTW GetLogFont() { return &mLogFont; } nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr) override; void FillLogFont(LOGFONTW *aLogFont, LONG aWeight, gfxFloat aSize); @@ -161,31 +165,37 @@ public: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; gfxFontEntry* Clone() const override; // create a font entry for a font with a given name static GDIFontEntry* CreateFontEntry(const nsAString& aName, gfxWindowsFontType aFontType, - SlantStyleRange aStyle, - WeightRange aWeight, - StretchRange aStretch, + FontSlantStyle aStyle, + FontWeight aWeight, + FontStretch aStretch, gfxUserFontData* aUserFontData); + // create a font entry for a font referenced by its fullname + static GDIFontEntry* LoadLocalFont(const nsAString& aFontName, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle); + gfxWindowsFontType mFontType; bool mForceGDI; gfxSparseBitSet mUnicodeRanges; protected: friend class gfxGDIFont; GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType, - SlantStyleRange aStyle, WeightRange aWeight, StretchRange aStretch, + FontSlantStyle aStyle, FontWeight aWeight, FontStretch aStretch, gfxUserFontData *aUserFontData); void InitLogFont(const nsAString& aName, gfxWindowsFontType aFontType); virtual gfxFont* CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) override; virtual nsresult CopyFontTable(uint32_t aTableTag, @@ -307,40 +317,44 @@ protected: private: static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe, const NEWTEXTMETRICEXW *nmetrics, DWORD fontType, LPARAM data); }; class gfxGDIFontList : public gfxPlatformFontList { public: + typedef mozilla::FontStretch FontStretch; + typedef mozilla::FontSlantStyle FontSlantStyle; + typedef mozilla::FontWeight FontWeight; + static gfxGDIFontList* PlatformFontList() { return static_cast<gfxGDIFontList*>(sPlatformFontList); } // initialize font lists virtual nsresult InitFontListForPlatform() override; gfxFontFamily* CreateFontFamily(const nsAString& aName) const override; bool FindAndAddFamilies(const nsAString& aFamily, nsTArray<gfxFontFamily*>* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, gfxFloat aDevToCssSize = 1.0) override; virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry); + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle); virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength); virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const; virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, FontListSizes* aSizes) const;
--- a/gfx/thebes/gfxMacFont.cpp +++ b/gfx/thebes/gfxMacFont.cpp @@ -31,32 +31,44 @@ gfxMacFont::gfxMacFont(const RefPtr<Unsc mCGFont(nullptr), mCTFont(nullptr), mFontFace(nullptr), mFontSmoothingBackgroundColor(aFontStyle->fontSmoothingBackgroundColor), mVariationFont(aFontEntry->HasVariations()) { mApplySyntheticBold = aNeedsBold; - if (mVariationFont) { + if (mVariationFont && (!aFontStyle->variationSettings.IsEmpty() || + !aFontEntry->mVariationSettings.IsEmpty())) { CGFontRef baseFont = aUnscaledFont->GetFont(); if (!baseFont) { mIsValid = false; return; } - // Get the variation settings needed to instantiate the fontEntry - // for a particular fontStyle. - AutoTArray<gfxFontVariation,4> vars; - aFontEntry->GetVariationsForStyle(vars, *aFontStyle); + // Probably one of the lists of variations, either from the @font-face + // descriptor or from the property, will be empty. So skip merging them + // unless really necessary. + const nsTArray<gfxFontVariation>* vars; + AutoTArray<gfxFontVariation,4> mergedSettings; + if (aFontStyle->variationSettings.IsEmpty()) { + vars = &aFontEntry->mVariationSettings; + } else if (aFontEntry->mVariationSettings.IsEmpty()) { + vars = &aFontStyle->variationSettings; + } else { + gfxFontUtils::MergeVariations(aFontEntry->mVariationSettings, + aFontStyle->variationSettings, + &mergedSettings); + vars = &mergedSettings; + } mCGFont = UnscaledFontMac::CreateCGFontWithVariations(baseFont, - vars.Length(), - vars.Elements()); + vars->Length(), + vars->Elements()); if (!mCGFont) { ::CFRetain(baseFont); mCGFont = baseFont; } } else { mCGFont = aUnscaledFont->GetFont(); if (!mCGFont) { mIsValid = false;
--- a/gfx/thebes/gfxMacPlatformFontList.h +++ b/gfx/thebes/gfxMacPlatformFontList.h @@ -26,23 +26,23 @@ class gfxMacPlatformFontList; // a single member of a font family (i.e. a single face, such as Times Italic) class MacOSFontEntry : public gfxFontEntry { public: friend class gfxMacPlatformFontList; - MacOSFontEntry(const nsAString& aPostscriptName, WeightRange aWeight, + MacOSFontEntry(const nsAString& aPostscriptName, FontWeight aWeight, bool aIsStandardFace = false, double aSizeHint = 0.0); // for use with data fonts MacOSFontEntry(const nsAString& aPostscriptName, CGFontRef aFontRef, - WeightRange aWeight, StretchRange aStretch, SlantStyleRange aStyle, + FontWeight aWeight, FontStretch aStretch, FontSlantStyle aStyle, bool aIsDataUserFont, bool aIsLocal); virtual ~MacOSFontEntry() { if (mTrakTable) { hb_blob_destroy(mTrakTable); } ::CGFontRelease(mFontRef); } @@ -126,24 +126,24 @@ public: gfxFontFamily* CreateFontFamily(const nsAString& aName) const override; static int32_t AppleWeightToCSSWeight(int32_t aAppleWeight); bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) override; gfxFontEntry* LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) override; + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) override; gfxFontEntry* MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) override; bool FindAndAddFamilies(const nsAString& aFamily, nsTArray<gfxFontFamily*>* aOutput, FindFamiliesFlags aFlags, gfxFontStyle* aStyle = nullptr, gfxFloat aDevToCssSize = 1.0) override;
--- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -359,17 +359,17 @@ MacOSFontEntry::IsCFF() mIsCFFInitialized = true; mIsCFF = HasFontTable(TRUETYPE_TAG('C','F','F',' ')); } return mIsCFF; } MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, - WeightRange aWeight, + FontWeight aWeight, bool aIsStandardFace, double aSizeHint) : gfxFontEntry(aPostscriptName, aIsStandardFace), mFontRef(NULL), mSizeHint(aSizeHint), mFontRefInitialized(false), mRequiresAAT(false), mIsCFF(false), @@ -378,24 +378,24 @@ MacOSFontEntry::MacOSFontEntry(const nsA mHasVariationsInitialized(false), mHasAATSmallCaps(false), mHasAATSmallCapsInitialized(false), mCheckedForTracking(false), mTrakTable(nullptr), mTrakValues(nullptr), mTrakSizeTable(nullptr) { - mWeightRange = aWeight; + mWeight = aWeight; } MacOSFontEntry::MacOSFontEntry(const nsAString& aPostscriptName, CGFontRef aFontRef, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, bool aIsDataUserFont, bool aIsLocalUserFont) : gfxFontEntry(aPostscriptName, false), mFontRef(NULL), mSizeHint(0.0), mFontRefInitialized(false), mRequiresAAT(false), mIsCFF(false), @@ -408,35 +408,35 @@ MacOSFontEntry::MacOSFontEntry(const nsA mTrakTable(nullptr), mTrakValues(nullptr), mTrakSizeTable(nullptr) { mFontRef = aFontRef; mFontRefInitialized = true; ::CFRetain(mFontRef); - mWeightRange = aWeight; - mStretchRange = aStretch; + mWeight = aWeight; + mStretch = aStretch; mFixedPitch = false; // xxx - do we need this for downloaded fonts? - mStyleRange = aStyle; + mStyle = aStyle; NS_ASSERTION(!(aIsDataUserFont && aIsLocalUserFont), "userfont is either a data font or a local font"); mIsDataUserFont = aIsDataUserFont; mIsLocalUserFont = aIsLocalUserFont; } gfxFontEntry* MacOSFontEntry::Clone() const { MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!"); MacOSFontEntry* fe = - new MacOSFontEntry(Name(), Weight(), mStandardFace, mSizeHint); - fe->mStyleRange = mStyleRange; - fe->mStretchRange = mStretchRange; + new MacOSFontEntry(Name(), mWeight, mStandardFace, mSizeHint); + fe->mStyle = mStyle; + fe->mStretch = mStretch; fe->mFixedPitch = mFixedPitch; return fe; } CGFontRef MacOSFontEntry::GetFontRef() { if (!mFontRefInitialized) { @@ -899,56 +899,48 @@ gfxMacFontFamily::FindStyleVariations(Fo [facename isEqualToString:@"Bold Italic"] || [facename isEqualToString:@"Bold Oblique"]) { isStandardFace = true; } // create a font entry MacOSFontEntry *fontEntry = - new MacOSFontEntry(postscriptFontName, - WeightRange(FontWeight(cssWeight)), + new MacOSFontEntry(postscriptFontName, FontWeight(cssWeight), isStandardFace, mSizeHint); if (!fontEntry) { break; } // set additional properties based on the traits reported by Cocoa if (macTraits & (NSCondensedFontMask | NSNarrowFontMask | NSCompressedFontMask)) { - fontEntry->mStretchRange = StretchRange(FontStretch::Condensed()); + fontEntry->mStretch = FontStretch::Condensed(); } else if (macTraits & NSExpandedFontMask) { - fontEntry->mStretchRange = StretchRange(FontStretch::Expanded()); + fontEntry->mStretch = FontStretch::Expanded(); } // Cocoa fails to set the Italic traits bit for HelveticaLightItalic, // at least (see bug 611855), so check for style name endings as well if ((macTraits & NSItalicFontMask) || [facename hasSuffix:@"Italic"] || [facename hasSuffix:@"Oblique"]) { - fontEntry->mStyleRange = SlantStyleRange(FontSlantStyle::Italic()); + fontEntry->mStyle = FontSlantStyle::Italic(); } if (macTraits & NSFixedPitchFontMask) { fontEntry->mFixedPitch = true; } - fontEntry->SetupVariationRanges(); - if (LOG_FONTLIST_ENABLED()) { - nsAutoCString weightString; - fontEntry->Weight().ToString(weightString); - nsAutoCString stretchString; - fontEntry->Stretch().ToString(stretchString); LOG_FONTLIST(("(fontlist) added (%s) to family (%s)" - " with style: %s weight: %s stretch: %s" + " with style: %s weight: %d stretch: %g%%" " (apple-weight: %d macTraits: %8.8x)", NS_ConvertUTF16toUTF8(fontEntry->Name()).get(), NS_ConvertUTF16toUTF8(Name()).get(), fontEntry->IsItalic() ? "italic" : "normal", - weightString.get(), - stretchString.get(), + cssWeight, fontEntry->Stretch().Percentage(), appKitWeight, macTraits)); } // insert into font entry array of family AddFontEntry(fontEntry); } SortAvailableFonts(); @@ -1285,17 +1277,17 @@ gfxMacPlatformFontList::InitSingleFaceLi // add only if doesn't exist already if (!mFontFamilies.GetWeak(key)) { RefPtr<gfxFontFamily> familyEntry = new gfxSingleFaceMacFontFamily(familyName); // We need a separate font entry, because its family name will // differ from the one we found in the main list. MacOSFontEntry* fontEntry = - new MacOSFontEntry(fe->Name(), fe->Weight(), true, + new MacOSFontEntry(fe->Name(), fe->mWeight, true, static_cast<const MacOSFontEntry*>(fe)-> mSizeHint); familyEntry->AddFontEntry(fontEntry); familyEntry->SetHasStyles(true); mFontFamilies.Put(key, familyEntry); LOG_FONTLIST(("(fontlist-singleface) added new family: %s, key: %s\n", NS_ConvertUTF16toUTF8(familyName).get(), NS_ConvertUTF16toUTF8(key).get())); @@ -1536,55 +1528,60 @@ gfxMacPlatformFontList::AppleWeightToCSS aAppleWeight = 1; else if (aAppleWeight > kAppleMaxWeight) aAppleWeight = kAppleMaxWeight; return gAppleWeightToCSSWeight[aAppleWeight]; } gfxFontEntry* gfxMacPlatformFontList::LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) { nsAutoreleasePool localPool; NSString *faceName = GetNSStringForString(aFontName); MacOSFontEntry *newFontEntry; // lookup face based on postscript or full name CGFontRef fontRef = ::CGFontCreateWithFontName(CFStringRef(faceName)); if (!fontRef) { return nullptr; } + MOZ_ASSERT(aWeight >= FontWeight(100) && aWeight <= FontWeight(900), + "bogus font weight value!"); + newFontEntry = - new MacOSFontEntry(aFontName, fontRef, aWeightForEntry, - aStretchForEntry, aStyleForEntry, + new MacOSFontEntry(aFontName, fontRef, aWeight, aStretch, aStyle, false, true); ::CFRelease(fontRef); return newFontEntry; } static void ReleaseData(void *info, const void *data, size_t size) { free((void*)data); } gfxFontEntry* gfxMacPlatformFontList::MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) { NS_ASSERTION(aFontData, "MakePlatformFont called with null data"); + MOZ_ASSERT(aWeight >= FontWeight(100) && aWeight <= FontWeight(900), + "bogus font weight value!"); + // create the font entry nsAutoString uniqueName; nsresult rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName); if (NS_FAILED(rv)) { return nullptr; } @@ -1594,19 +1591,18 @@ gfxMacPlatformFontList::MakePlatformFont CGFontRef fontRef = ::CGFontCreateWithDataProvider(provider); ::CGDataProviderRelease(provider); if (!fontRef) { return nullptr; } auto newFontEntry = - MakeUnique<MacOSFontEntry>(uniqueName, fontRef, aWeightForEntry, - aStretchForEntry, aStyleForEntry, - true, false); + MakeUnique<MacOSFontEntry>(uniqueName, fontRef, aWeight, aStretch, + aStyle, true, false); ::CFRelease(fontRef); // if succeeded and font cmap is good, return the new font if (NS_SUCCEEDED(newFontEntry->ReadCMAP())) { return newFontEntry.release(); } // if something is funky about this font, delete immediately
--- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -769,20 +769,16 @@ gfxPlatform::Init() # endif #endif InitLayersIPC(); gPlatform->PopulateScreenInfo(); gPlatform->ComputeTileSize(); -#ifdef MOZ_ENABLE_FREETYPE - Factory::SetFTLibrary(gPlatform->GetFTLibrary()); -#endif - nsresult rv; rv = gfxPlatformFontList::Init(); if (NS_FAILED(rv)) { MOZ_CRASH("Could not initialize gfxPlatformFontList"); } gPlatform->mScreenReferenceSurface = gPlatform->CreateOffscreenSurface(IntSize(1, 1), @@ -804,16 +800,20 @@ gfxPlatform::Init() } } rv = gfxFontCache::Init(); if (NS_FAILED(rv)) { MOZ_CRASH("Could not initialize gfxFontCache"); } +#ifdef MOZ_ENABLE_FREETYPE + Factory::SetFTLibrary(gPlatform->GetFTLibrary()); +#endif + /* Create and register our CMS Override observer. */ gPlatform->mSRGBOverrideObserver = new SRGBOverrideObserver(); Preferences::AddWeakObserver(gPlatform->mSRGBOverrideObserver, GFX_PREF_CMS_FORCE_SRGB); gPlatform->mFontPrefsObserver = new FontPrefsObserver(); Preferences::AddStrongObservers(gPlatform->mFontPrefsObserver, kObservedPrefs); GLContext::PlatformStartup(); @@ -1740,36 +1740,40 @@ gfxPlatform::IsFontFormatSupported(uint3 } // no format hint set, need to look at data return true; } gfxFontEntry* gfxPlatform::LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) { - return gfxPlatformFontList::PlatformFontList()-> - LookupLocalFont(aFontName, aWeightForEntry, aStretchForEntry, - aStyleForEntry); + return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aFontName, + aWeight, + aStretch, + aStyle); } gfxFontEntry* gfxPlatform::MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) { - return gfxPlatformFontList::PlatformFontList()-> - MakePlatformFont(aFontName, aWeightForEntry, aStretchForEntry, - aStyleForEntry, aFontData, aLength); + return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aFontName, + aWeight, + aStretch, + aStyle, + aFontData, + aLength); } mozilla::layers::DiagnosticTypes gfxPlatform::GetLayerDiagnosticTypes() { mozilla::layers::DiagnosticTypes type = DiagnosticTypes::NO_DIAGNOSTIC; if (gfxPrefs::DrawLayerBorders()) { type |= mozilla::layers::DiagnosticTypes::LAYER_BORDERS;
--- a/gfx/thebes/gfxPlatform.h +++ b/gfx/thebes/gfxPlatform.h @@ -154,19 +154,19 @@ struct BackendPrefsData uint32_t mContentBitmask = 0; mozilla::gfx::BackendType mContentDefault = mozilla::gfx::BackendType::NONE; }; class gfxPlatform { friend class SRGBOverrideObserver; public: - typedef mozilla::StretchRange StretchRange; - typedef mozilla::SlantStyleRange SlantStyleRange; - typedef mozilla::WeightRange WeightRange; + typedef mozilla::FontStretch FontStretch; + typedef mozilla::FontSlantStyle FontSlantStyle; + typedef mozilla::FontWeight FontWeight; typedef mozilla::gfx::Color Color; typedef mozilla::gfx::DataSourceSurface DataSourceSurface; typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::IntSize IntSize; typedef mozilla::gfx::SourceSurface SourceSurface; typedef mozilla::unicode::Script Script; /** @@ -389,35 +389,35 @@ public: gfxFloat aDevToCssSize) = 0; /** * Look up a local platform font using the full font face name. * (Needed to support @font-face src local().) * Ownership of the returned gfxFontEntry is passed to the caller, * who must either AddRef() or delete. */ - gfxFontEntry* LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry); + virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle); /** * Activate a platform font. (Needed to support @font-face src url().) * aFontData is a NS_Malloc'ed block that must be freed by this function * (or responsibility passed on) when it is no longer needed; the caller * will NOT free it. * Ownership of the returned gfxFontEntry is passed to the caller, * who must either AddRef() or delete. */ - gfxFontEntry* MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, - const uint8_t* aFontData, - uint32_t aLength); + virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, + const uint8_t* aFontData, + uint32_t aLength); /** * Whether to allow downloadable fonts via @font-face rules */ bool DownloadableFontsEnabled(); /** * True when hinting should be enabled. This setting shouldn't
--- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -93,19 +93,19 @@ struct FontListSizes { class gfxUserFontSet; class gfxPlatformFontList : public gfxFontInfoLoader { friend class InitOtherFamilyNamesRunnable; public: - typedef mozilla::StretchRange StretchRange; - typedef mozilla::SlantStyleRange SlantStyleRange; - typedef mozilla::WeightRange WeightRange; + typedef mozilla::FontStretch FontStretch; + typedef mozilla::FontSlantStyle FontSlantStyle; + typedef mozilla::FontWeight FontWeight; typedef mozilla::unicode::Script Script; static gfxPlatformFontList* PlatformFontList() { return sPlatformFontList; } static nsresult Init() { NS_ASSERTION(!sPlatformFontList, "What's this doing here?"); @@ -183,43 +183,28 @@ public: bool NeedFullnamePostscriptNames() { return mExtraNames != nullptr; } // pure virtual functions, to be provided by concrete subclasses // get the system default font family gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle); - /** - * Look up a font by name on the host platform. - * - * Note that the style attributes (weight, stretch, style) are NOT used in - * selecting the platform font, which is looked up by name only; these are - * values to be recorded in the new font entry. - */ + // look up a font by name on the host platform virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry) = 0; + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) = 0; - /** - * Create a new platform font from downloaded data (@font-face). - * - * Note that the style attributes (weight, stretch, style) are NOT related - * (necessarily) to any values within the font resource itself; these are - * values to be recorded in the new font entry and used for face selection, - * in place of whatever inherent style attributes the resource may have. - * - * This method takes ownership of the data block passed in as aFontData, - * and must ensure it is free()'d when no longer required. - */ + // create a new platform font from downloaded data (@font-face) + // this method is responsible to ensure aFontData is free()'d virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, - WeightRange aWeightForEntry, - StretchRange aStretchForEntry, - SlantStyleRange aStyleForEntry, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const uint8_t* aFontData, uint32_t aLength) = 0; // get the standard family name on the platform for a given font name // (platforms may override, eg Mac) virtual bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName); // get the default font name which is available on the system from
--- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -268,16 +268,40 @@ gfxPlatformGtk::CreateFontGroup(const Fo gfxTextPerfMetrics* aTextPerf, gfxUserFontSet* aUserFontSet, gfxFloat aDevToCssSize) { return new gfxFontGroup(aFontFamilyList, aStyle, aTextPerf, aUserFontSet, aDevToCssSize); } +gfxFontEntry* +gfxPlatformGtk::LookupLocalFont(const nsAString& aFontName, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) +{ + gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); + return pfl->LookupLocalFont(aFontName, aWeight, aStretch, + aStyle); +} + +gfxFontEntry* +gfxPlatformGtk::MakePlatformFont(const nsAString& aFontName, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, + const uint8_t* aFontData, + uint32_t aLength) +{ + gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); + return pfl->MakePlatformFont(aFontName, aWeight, aStretch, + aStyle, aFontData, aLength); +} + FT_Library gfxPlatformGtk::GetFTLibrary() { return gfxFcPlatformFontList::GetFTLibrary(); } static int32_t sDPI = 0;
--- a/gfx/thebes/gfxPlatformGtk.h +++ b/gfx/thebes/gfxPlatformGtk.h @@ -57,16 +57,36 @@ public: gfxFontGroup* CreateFontGroup(const mozilla::FontFamilyList& aFontFamilyList, const gfxFontStyle *aStyle, gfxTextPerfMetrics* aTextPerf, gfxUserFontSet *aUserFontSet, gfxFloat aDevToCssSize) override; /** + * Look up a local platform font using the full font face name (needed to + * support @font-face src local() ) + */ + virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle) override; + + /** + * Activate a platform font (needed to support @font-face src url() ) + * + */ + virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, + const uint8_t* aFontData, + uint32_t aLength) override; + + /** * Calls XFlush if xrender is enabled. */ virtual void FlushContentDrawing() override; FT_Library GetFTLibrary() override; static int32_t GetFontScaleDPI(); static double GetFontScaleFactor();
--- a/gfx/thebes/gfxUserFontSet.cpp +++ b/gfx/thebes/gfxUserFontSet.cpp @@ -100,66 +100,68 @@ private: void* mPtr; size_t mLength; const size_t mLimit; off_t mOff; }; gfxUserFontEntry::gfxUserFontEntry(gfxUserFontSet* aFontSet, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) : gfxFontEntry(NS_LITERAL_STRING("userfont")), mUserFontLoadState(STATUS_NOT_LOADED), mFontDataLoadingState(NOT_LOADING), mUnsupportedFormat(false), mFontDisplay(aFontDisplay), mLoader(nullptr), mFontSet(aFontSet) { + MOZ_ASSERT(aWeight.ToFloat() != 0.0f, + "aWeight must not be 0; use FontWeight::Normal() instead"); mIsUserFontContainer = true; mSrcList = aFontFaceSrcList; mSrcIndex = 0; - mWeightRange = aWeight; - mStretchRange = aStretch; - mStyleRange = aStyle; + mWeight = aWeight; + mStretch = aStretch; + mStyle = aStyle; mFeatureSettings.AppendElements(aFeatureSettings); mVariationSettings.AppendElements(aVariationSettings); mLanguageOverride = aLanguageOverride; mCharacterMap = aUnicodeRanges; } gfxUserFontEntry::~gfxUserFontEntry() { // Assert that we don't drop any gfxUserFontEntry objects during a Servo // traversal, since PostTraversalTask objects can hold raw pointers to // gfxUserFontEntry objects. MOZ_ASSERT(!ServoStyleSet::IsInServoTraversal()); } bool gfxUserFontEntry::Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) { - return Weight() == aWeight && - Stretch() == aStretch && - SlantStyle() == aStyle && + return mWeight == aWeight && + mStretch == aStretch && + mStyle == aStyle && mFeatureSettings == aFeatureSettings && mVariationSettings == aVariationSettings && mLanguageOverride == aLanguageOverride && mSrcList == aFontFaceSrcList && mFontDisplay == aFontDisplay && ((!aUnicodeRanges && !mCharacterMap) || (aUnicodeRanges && mCharacterMap && mCharacterMap->Equals(aUnicodeRanges))); } @@ -509,19 +511,19 @@ gfxUserFontEntry::DoLoadNextSrc(bool aFo // src local ==> lookup and load immediately if (currSrc.mSourceType == gfxFontFaceSrc::eSourceType_Local) { // Don't look up local fonts if the font whitelist is being used. gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); gfxFontEntry* fe = pfl && pfl->IsFontFamilyWhitelistActive() ? nullptr : gfxPlatform::GetPlatform()->LookupLocalFont(currSrc.mLocalName, - Weight(), - Stretch(), - SlantStyle()); + mWeight, + mStretch, + mStyle); nsTArray<gfxUserFontSet*> fontSets; GetUserFontSets(fontSets); for (gfxUserFontSet* fontSet : fontSets) { // We need to note on each gfxUserFontSet that contains the user // font entry that we used a local() rule. fontSet->SetLocalRulesUsed(); } if (fe) { @@ -764,19 +766,19 @@ gfxUserFontEntry::LoadPlatformFont(const // don't allow us to retrieve or measure it directly. // The *OnAlloc function will also tell DMD about this block, as the // OS font code may hold on to it for an extended period. computedSize = UserFontMallocSizeOfOnAlloc(saneData); // Here ownership of saneData is passed to the platform, // which will delete it when no longer required fe = gfxPlatform::GetPlatform()->MakePlatformFont(mName, - Weight(), - Stretch(), - SlantStyle(), + mWeight, + mStretch, + mStyle, saneData, saneLen); if (!fe) { mFontSet->LogMessage(this, "not usable by platform"); } } if (fe) { @@ -929,19 +931,19 @@ gfxUserFontSet::~gfxUserFontSet() fp->RemoveUserFontSet(this); } } already_AddRefed<gfxUserFontEntry> gfxUserFontSet::FindOrCreateUserFontEntry( const nsAString& aFamilyName, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) { RefPtr<gfxUserFontEntry> entry; @@ -969,19 +971,19 @@ gfxUserFontSet::FindOrCreateUserFontEntr } return entry.forget(); } already_AddRefed<gfxUserFontEntry> gfxUserFontSet::CreateUserFontEntry( const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) { RefPtr<gfxUserFontEntry> userFontEntry = @@ -990,25 +992,28 @@ gfxUserFontSet::CreateUserFontEntry( aLanguageOverride, aUnicodeRanges, aFontDisplay); return userFontEntry.forget(); } gfxUserFontEntry* gfxUserFontSet::FindExistingUserFontEntry( gfxUserFontFamily* aFamily, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) { + MOZ_ASSERT(aWeight.ToFloat() != 0.0f, + "aWeight must not be 0; use FontWeight::Normal() instead"); + nsTArray<RefPtr<gfxFontEntry>>& fontList = aFamily->GetFontList(); for (size_t i = 0, count = fontList.Length(); i < count; i++) { if (!fontList[i]->mIsUserFontContainer) { continue; } gfxUserFontEntry* existingUserFontEntry = @@ -1030,27 +1035,23 @@ gfxUserFontSet::FindExistingUserFontEntr void gfxUserFontSet::AddUserFontEntry(const nsAString& aFamilyName, gfxUserFontEntry* aUserFontEntry) { gfxUserFontFamily* family = GetFamily(aFamilyName); family->AddFontEntry(aUserFontEntry); if (LOG_ENABLED()) { - nsAutoCString weightString; - aUserFontEntry->Weight().ToString(weightString); - nsAutoCString stretchString; - aUserFontEntry->Stretch().ToString(stretchString); - LOG(("userfonts (%p) added to \"%s\" (%p) style: %s weight: %s " - "stretch: %s display: %d", + LOG(("userfonts (%p) added to \"%s\" (%p) style: %s weight: %g " + "stretch: %g%% display: %d", this, NS_ConvertUTF16toUTF8(aFamilyName).get(), aUserFontEntry, (aUserFontEntry->IsItalic() ? "italic" : (aUserFontEntry->IsOblique() ? "oblique" : "normal")), - weightString.get(), - stretchString.get(), + aUserFontEntry->Weight().ToFloat(), + aUserFontEntry->Stretch().Percentage(), aUserFontEntry->GetFontDisplay())); } } void gfxUserFontSet::IncrementGeneration(bool aIsRebuild) { // add one, increment again if zero @@ -1176,19 +1177,19 @@ gfxUserFontSet::UserFontCache::Entry::Ke return false; } } if (mPrivate != aKey->mPrivate) { return false; } - if (mFontEntry->SlantStyle() != fe->SlantStyle() || - mFontEntry->Weight() != fe->Weight() || - mFontEntry->Stretch() != fe->Stretch() || + if (mFontEntry->mStyle != fe->mStyle || + mFontEntry->mWeight != fe->mWeight || + mFontEntry->mStretch != fe->mStretch || mFontEntry->mFeatureSettings != fe->mFeatureSettings || mFontEntry->mVariationSettings != fe->mVariationSettings || mFontEntry->mLanguageOverride != fe->mLanguageOverride || mFontEntry->mFamilyName != fe->mFamilyName) { return false; } return true;
--- a/gfx/thebes/gfxUserFontSet.h +++ b/gfx/thebes/gfxUserFontSet.h @@ -181,21 +181,18 @@ class gfxUserFontEntry; class gfxOTSContext; class gfxUserFontSet { friend class gfxUserFontEntry; friend class gfxOTSContext; public: typedef mozilla::FontStretch FontStretch; - typedef mozilla::StretchRange StretchRange; typedef mozilla::FontSlantStyle FontSlantStyle; - typedef mozilla::SlantStyleRange SlantStyleRange; typedef mozilla::FontWeight FontWeight; - typedef mozilla::WeightRange WeightRange; NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxUserFontSet) gfxUserFontSet(); enum { // no flags ==> no hint set // unknown ==> unknown format hint set @@ -231,33 +228,33 @@ public: // creates a font face without adding it to a particular family // weight - [100, 900] (multiples of 100) // stretch = [FontStretch::UltraCondensed(), FontStretch::UltraExpanded()] // italic style = constants in gfxFontConstants.h, e.g. NS_FONT_STYLE_NORMAL // language override = result of calling nsRuleNode::ParseFontLanguageOverride // TODO: support for unicode ranges not yet implemented virtual already_AddRefed<gfxUserFontEntry> CreateUserFontEntry( const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) = 0; // creates a font face for the specified family, or returns an existing // matching entry on the family if there is one already_AddRefed<gfxUserFontEntry> FindOrCreateUserFontEntry( const nsAString& aFamilyName, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay); // add in a font face for which we have the gfxUserFontEntry already void AddUserFontEntry(const nsAString& aFamilyName, @@ -406,19 +403,20 @@ public: static PLDHashNumber HashKey(const KeyTypePointer aKey) { PLDHashNumber principalHash = aKey->mPrincipal ? aKey->mPrincipal->Hash() : 0; return mozilla::HashGeneric(principalHash + int(aKey->mPrivate), aKey->mURI->Hash(), HashFeatures(aKey->mFontEntry->mFeatureSettings), HashVariations(aKey->mFontEntry->mVariationSettings), mozilla::HashString(aKey->mFontEntry->mFamilyName), - aKey->mFontEntry->Weight().AsScalar(), - aKey->mFontEntry->SlantStyle().AsScalar(), - aKey->mFontEntry->Stretch().AsScalar(), + aKey->mFontEntry->mWeight.ForHash(), + // XXX Is this right? + aKey->mFontEntry->mStyle.ForHash(), + aKey->mFontEntry->mStretch.ForHash(), aKey->mFontEntry->mLanguageOverride); } enum { ALLOW_MEMMOVE = false }; gfxFontSrcURI* GetURI() const { return mURI; } gfxFontSrcPrincipal* GetPrincipal() const { return mPrincipal; } gfxFontEntry* GetFontEntry() const { return mFontEntry; } @@ -499,19 +497,19 @@ protected: // helper method for performing the actual userfont set rebuild virtual void DoRebuildUserFontSet() = 0; // helper method for FindOrCreateUserFontEntry gfxUserFontEntry* FindExistingUserFontEntry( gfxUserFontFamily* aFamily, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay); // creates a new gfxUserFontFamily in mFontFamilies, or returns an existing // family if there is one @@ -539,42 +537,46 @@ protected: class gfxUserFontEntry : public gfxFontEntry { friend class mozilla::PostTraversalTask; friend class gfxUserFontSet; friend class nsUserFontSet; friend class nsFontFaceLoader; friend class gfxOTSContext; public: + typedef mozilla::FontStretch FontStretch; + typedef mozilla::FontSlantStyle FontSlantStyle; + typedef mozilla::FontWeight FontWeight; + enum UserFontLoadState { STATUS_NOT_LOADED = 0, STATUS_LOAD_PENDING, STATUS_LOADING, STATUS_LOADED, STATUS_FAILED }; gfxUserFontEntry(gfxUserFontSet* aFontSet, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay); virtual ~gfxUserFontEntry(); // Return whether the entry matches the given list of attributes bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay); gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold) override;
--- a/layout/style/FontFace.h +++ b/layout/style/FontFace.h @@ -43,19 +43,19 @@ class FontFace final : public nsISupport public: class Entry final : public gfxUserFontEntry { friend class FontFace; public: Entry(gfxUserFontSet* aFontSet, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) : gfxUserFontEntry(aFontSet, aFontFaceSrcList, aWeight, aStretch, aStyle, aFeatureSettings, aVariationSettings, aLanguageOverride,
--- a/layout/style/FontFaceSet.cpp +++ b/layout/style/FontFaceSet.cpp @@ -984,108 +984,87 @@ GetWeightForDescriptor(const nsCSSValue& switch (aVal.GetUnit()) { case eCSSUnit_FontWeight: return aVal.GetFontWeight(); case eCSSUnit_Enumerated: return FontWeight(aVal.GetIntValue()); case eCSSUnit_Normal: case eCSSUnit_Null: return FontWeight::Normal(); + case eCSSUnit_Pair: + // TODO(jfkthame): Handle optional second value of the font descriptor. + return GetWeightForDescriptor(aVal.GetPairValue().mXValue); default: MOZ_ASSERT_UNREACHABLE("Unknown font-weight descriptor value"); return FontWeight::Normal(); } } -static WeightRange -GetWeightRangeForDescriptor(const nsCSSValue& aVal) -{ - if (aVal.GetUnit() == eCSSUnit_Pair) { - return WeightRange(GetWeightForDescriptor(aVal.GetPairValue().mXValue), - GetWeightForDescriptor(aVal.GetPairValue().mYValue)); - } - return WeightRange(GetWeightForDescriptor(aVal)); -} - static FontSlantStyle GetStyleForDescriptor(const nsCSSValue& aVal) { switch (aVal.GetUnit()) { case eCSSUnit_Normal: case eCSSUnit_Null: return FontSlantStyle::Normal(); case eCSSUnit_Enumerated: MOZ_ASSERT(aVal.GetIntValue() == NS_FONT_STYLE_ITALIC); return FontSlantStyle::Italic(); case eCSSUnit_FontSlantStyle: return aVal.GetFontSlantStyle(); + case eCSSUnit_Pair: + // TODO(jfkthame): Handle optional second value of the font descriptor. + return GetStyleForDescriptor(aVal.GetPairValue().mXValue); default: MOZ_ASSERT_UNREACHABLE("Unknown font-style descriptor value"); return FontSlantStyle::Normal(); } } -static SlantStyleRange -GetStyleRangeForDescriptor(const nsCSSValue& aVal) -{ - if (aVal.GetUnit() == eCSSUnit_Pair) { - return SlantStyleRange(GetStyleForDescriptor(aVal.GetPairValue().mXValue), - GetStyleForDescriptor(aVal.GetPairValue().mYValue)); - } - return SlantStyleRange(GetStyleForDescriptor(aVal)); -} - static FontStretch GetStretchForDescriptor(const nsCSSValue& aVal) { switch (aVal.GetUnit()) { case eCSSUnit_Null: return FontStretch::Normal(); case eCSSUnit_FontStretch: return aVal.GetFontStretch(); + case eCSSUnit_Pair: + // TODO(jfkthame): Handle optional second value of the font descriptor. + return GetStretchForDescriptor(aVal.GetPairValue().mXValue); default: MOZ_ASSERT_UNREACHABLE("Unknown font-style descriptor value"); return FontStretch::Normal(); } } -static StretchRange -GetStretchRangeForDescriptor(const nsCSSValue& aVal) -{ - if (aVal.GetUnit() == eCSSUnit_Pair) { - return StretchRange(GetStretchForDescriptor(aVal.GetPairValue().mXValue), - GetStretchForDescriptor(aVal.GetPairValue().mYValue)); - } - return StretchRange(GetStretchForDescriptor(aVal)); -} - /* static */ already_AddRefed<gfxUserFontEntry> FontFaceSet::FindOrCreateUserFontEntryFromFontFace(const nsAString& aFamilyName, FontFace* aFontFace, SheetType aSheetType) { FontFaceSet* set = aFontFace->GetPrimaryFontFaceSet(); nsCSSValue val; nsCSSUnit unit; uint32_t languageOverride = NO_FONT_LANGUAGE_OVERRIDE; uint8_t fontDisplay = NS_FONT_DISPLAY_AUTO; // set up weight aFontFace->GetDesc(eCSSFontDesc_Weight, val); - WeightRange weight = GetWeightRangeForDescriptor(val); + FontWeight weight = GetWeightForDescriptor(val); // set up stretch aFontFace->GetDesc(eCSSFontDesc_Stretch, val); - StretchRange stretch = GetStretchRangeForDescriptor(val); + FontStretch stretch = GetStretchForDescriptor(val); // set up font style aFontFace->GetDesc(eCSSFontDesc_Style, val); - SlantStyleRange italicStyle = GetStyleRangeForDescriptor(val); + FontSlantStyle italicStyle = GetStyleForDescriptor(val); // set up font display aFontFace->GetDesc(eCSSFontDesc_Display, val); unit = val.GetUnit(); if (unit == eCSSUnit_Enumerated) { fontDisplay = val.GetIntValue(); } else { NS_ASSERTION(unit == eCSSUnit_Null, @@ -1303,28 +1282,24 @@ FontFaceSet::LogMessage(gfxUserFontEntry if (!console) { return NS_ERROR_NOT_AVAILABLE; } nsAutoCString familyName; nsAutoCString fontURI; aUserFontEntry->GetFamilyNameAndURIForLogging(familyName, fontURI); - nsAutoCString weightString; - aUserFontEntry->Weight().ToString(weightString); - nsAutoCString stretchString; - aUserFontEntry->Stretch().ToString(stretchString); nsPrintfCString message ("downloadable font: %s " - "(font-family: \"%s\" style:%s weight:%s stretch:%s src index:%d)", + "(font-family: \"%s\" style:%s weight:%g stretch:%g%% src index:%d)", aMessage, familyName.get(), - aUserFontEntry->IsItalic() ? "italic" : "normal", // XXX todo: oblique? - weightString.get(), - stretchString.get(), + aUserFontEntry->IsItalic() ? "italic" : "normal", + aUserFontEntry->Weight().ToFloat(), + aUserFontEntry->Stretch().Percentage(), aUserFontEntry->GetSrcIndex()); if (NS_FAILED(aStatus)) { message.AppendLiteral(": "); switch (aStatus) { case NS_ERROR_DOM_BAD_URI: message.AppendLiteral("bad URI or cross-site access not allowed"); break; @@ -1985,19 +1960,19 @@ FontFaceSet::UserFontSet::DoRebuildUserF return; } mFontFaceSet->MarkUserFontSetDirty(); } /* virtual */ already_AddRefed<gfxUserFontEntry> FontFaceSet::UserFontSet::CreateUserFontEntry( const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) { RefPtr<gfxUserFontEntry> entry = new FontFace::Entry(this, aFontFaceSrcList, aWeight, aStretch, aStyle,
--- a/layout/style/FontFaceSet.h +++ b/layout/style/FontFaceSet.h @@ -93,19 +93,19 @@ public: uint32_t& aBufferLength) override; virtual nsresult LogMessage(gfxUserFontEntry* aUserFontEntry, const char* aMessage, uint32_t aFlags = nsIScriptError::errorFlag, nsresult aStatus = NS_OK) override; virtual void DoRebuildUserFontSet() override; already_AddRefed<gfxUserFontEntry> CreateUserFontEntry( const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, - WeightRange aWeight, - StretchRange aStretch, - SlantStyleRange aStyle, + FontWeight aWeight, + FontStretch aStretch, + FontSlantStyle aStyle, const nsTArray<gfxFontFeature>& aFeatureSettings, const nsTArray<gfxFontVariation>& aVariationSettings, uint32_t aLanguageOverride, gfxCharacterMap* aUnicodeRanges, uint8_t aFontDisplay) override; private: RefPtr<FontFaceSet> mFontFaceSet;