diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 703bac83fa11..97ca8a8c6162 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -63,6 +63,7 @@ namespace mozilla { namespace gfx { +class ScaledFont; class SourceSurface; class DataSourceSurface; class DrawTarget; @@ -711,6 +712,25 @@ public: static uint32_t DeletionCounter() { return sDeletionCounter; } + typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex, + void *aBaton); + typedef void (*FontInstanceDataOutput)(const uint8_t* aData, uint32_t aLength, void* aBaton); + typedef void (*FontDescriptorOutput)(const uint8_t* aData, uint32_t aLength, void* aBaton); + + virtual bool GetFontFileData(FontFileDataOutput, void *) { return false; } + + virtual bool GetFontInstanceData(FontInstanceDataOutput, void *) { return false; } + + virtual bool GetFontDescriptor(FontDescriptorOutput, void *) { return false; } + + virtual already_AddRefed + CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) + { + return nullptr; + } + protected: UnscaledFont() {} @@ -728,17 +748,6 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont) virtual ~ScaledFont() {} - typedef struct { - uint32_t mTag; - Float mValue; - } VariationSetting; - - typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, - uint32_t aVariationCount, const VariationSetting* aVariations, - void *aBaton); - typedef void (*FontInstanceDataOutput)(const uint8_t* aData, uint32_t aLength, void* aBaton); - typedef void (*FontDescriptorOutput)(const uint8_t* aData, uint32_t aLength, Float aFontSize, void* aBaton); - virtual FontType GetType() const = 0; virtual Float GetSize() const = 0; virtual AntialiasMode GetDefaultAAMode(); @@ -761,12 +770,15 @@ public: */ virtual void GetGlyphDesignMetrics(const uint16_t* aGlyphIndices, uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics) = 0; - virtual bool GetFontFileData(FontFileDataOutput, void *) { return false; } + struct VariationSetting { + uint32_t mTag; + float mValue; + }; + + typedef void (*FontInstanceDataOutput)(const uint8_t* aData, uint32_t aLength, void* aBaton); virtual bool GetFontInstanceData(FontInstanceDataOutput, void *) { return false; } - virtual bool GetFontDescriptor(FontDescriptorOutput, void *) { return false; } - virtual bool CanSerialize() { return false; } void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) { @@ -797,20 +809,19 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResource) /** - * Creates a ScaledFont using the font corresponding to the index and - * the given glyph size. + * Creates a UnscaledFont using the font corresponding to the index. * * @param aIndex index for the font within the resource. - * @param aGlyphSize the size of ScaledFont required. * @param aInstanceData pointer to read-only buffer of any available instance data. * @param aInstanceDataLength the size of the instance data. - * @return an already_addrefed ScaledFont, containing nullptr if failed. + * @return an already_addrefed UnscaledFont, containing nullptr if failed. */ - virtual already_AddRefed - CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) = 0; + virtual already_AddRefed + CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) = 0; - virtual ~NativeFontResource() {}; + virtual ~NativeFontResource() {} }; /** This class is designed to allow passing additional glyph rendering @@ -1469,23 +1480,18 @@ public: * * @param aData Pointer to the data * @param aSize Size of the TrueType data - * @param aVariationCount Number of VariationSetting records provided. - * @param aVariations Pointer to VariationSetting records. * @param aType Type of NativeFontResource that should be created. * @return a NativeFontResource of nullptr if failed. */ static already_AddRefed - CreateNativeFontResource(uint8_t *aData, uint32_t aSize, - uint32_t aVariationCount, - const ScaledFont::VariationSetting* aVariations, - FontType aType); + CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType); /** - * This creates a scaled font of the given type based on font descriptor + * This creates an unscaled font of the given type based on font descriptor * data retrieved from ScaledFont::GetFontDescriptor. */ - static already_AddRefed - CreateScaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, Float aSize); + static already_AddRefed + CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength); /** * This creates a scaled font with an associated cairo_scaled_font_t, and diff --git a/gfx/2d/DrawTargetRecording.cpp b/gfx/2d/DrawTargetRecording.cpp index b8eda90feac1..9f687b482ed3 100644 --- a/gfx/2d/DrawTargetRecording.cpp +++ b/gfx/2d/DrawTargetRecording.cpp @@ -388,32 +388,39 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont, { EnsurePatternDependenciesStored(aPattern); - if (!aFont->GetUserData(reinterpret_cast(mRecorder.get()))) { - RecordedFontData fontData(aFont); - RecordedFontDetails fontDetails; - if (fontData.GetFontDetails(fontDetails)) { - // Try to serialise the whole font, just in case this is a web font that - // is not present on the system. - if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) { - mRecorder->RecordEvent(fontData); - mRecorder->AddStoredFontData(fontDetails.fontDataKey); - } - mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, fontDetails)); - } else { - // If that fails, record just the font description and try to load it from - // the system on the other side. - RecordedFontDescriptor fontDesc(aFont); - if (fontDesc.IsValid()) { - mRecorder->RecordEvent(fontDesc); + UserDataKey* userDataKey = reinterpret_cast(mRecorder.get()); + if (!aFont->GetUserData(userDataKey)) { + UnscaledFont* unscaledFont = aFont->GetUnscaledFont(); + if (!mRecorder->HasStoredObject(unscaledFont)) { + RecordedFontData fontData(unscaledFont); + RecordedFontDetails fontDetails; + if (fontData.GetFontDetails(fontDetails)) { + // Try to serialise the whole font, just in case this is a web font that + // is not present on the system. + if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) { + mRecorder->RecordEvent(fontData); + mRecorder->AddStoredFontData(fontDetails.fontDataKey); + } + mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails)); } else { - gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise ScaledFont"; + // If that fails, record just the font description and try to load it from + // the system on the other side. + RecordedFontDescriptor fontDesc(unscaledFont); + if (fontDesc.IsValid()) { + mRecorder->RecordEvent(fontDesc); + } else { + gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont"; + } } + mRecorder->AddStoredObject(unscaledFont); } + + mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont)); + RecordingFontUserData *userData = new RecordingFontUserData; userData->refPtr = aFont; userData->recorder = mRecorder; - aFont->AddUserData(reinterpret_cast(mRecorder.get()), userData, - &RecordingFontUserDataDestroyFunc); + aFont->AddUserData(userDataKey, userData, &RecordingFontUserDataDestroyFunc); } mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs)); diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index f64aa7647f98..9aa9fc23c11f 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -24,6 +24,7 @@ #if defined(WIN32) #include "ScaledFontWin.h" #include "NativeFontResourceGDI.h" +#include "UnscaledFontGDI.h" #endif #ifdef XP_DARWIN @@ -34,6 +35,7 @@ #ifdef MOZ_WIDGET_GTK #include "ScaledFontFontconfig.h" #include "NativeFontResourceFontconfig.h" +#include "UnscaledFontFreeType.h" #endif #ifdef WIN32 @@ -505,10 +507,7 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, } already_AddRefed -Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, - uint32_t aVariationCount, - const ScaledFont::VariationSetting* aVariations, - FontType aType) +Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType) { switch (aType) { #ifdef WIN32 @@ -528,12 +527,10 @@ Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, return NativeFontResourceDWrite::Create(aData, aSize, /* aNeedsCairo = */ true); } else { - return NativeFontResourceGDI::Create(aData, aSize, - /* aNeedsCairo = */ true); + return NativeFontResourceGDI::Create(aData, aSize); } #elif defined(XP_DARWIN) - return NativeFontResourceMac::Create(aData, aSize, - aVariationCount, aVariations); + return NativeFontResourceMac::Create(aData, aSize); #elif defined(MOZ_WIDGET_GTK) return NativeFontResourceFontconfig::Create(aData, aSize); #else @@ -547,20 +544,20 @@ Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, } } -already_AddRefed -Factory::CreateScaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, Float aSize) +already_AddRefed +Factory::CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength) { switch (aType) { #ifdef WIN32 case FontType::GDI: - return ScaledFontWin::CreateFromFontDescriptor(aData, aDataLength, aSize); + return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength); #endif #ifdef MOZ_WIDGET_GTK case FontType::FONTCONFIG: - return ScaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength, aSize); + return UnscaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength); #endif default: - gfxWarning() << "Invalid type specified for ScaledFont font descriptor"; + gfxWarning() << "Invalid type specified for UnscaledFont font descriptor"; return nullptr; } } diff --git a/gfx/2d/Logging.h b/gfx/2d/Logging.h index 394c403cc0c0..afec48164df0 100644 --- a/gfx/2d/Logging.h +++ b/gfx/2d/Logging.h @@ -131,6 +131,7 @@ enum class LogReason : int { ProcessingError, InvalidDrawTarget, NativeFontResourceNotFound, + UnscaledFontNotFound, // End MustBeLessThanThis = 101, }; diff --git a/gfx/2d/NativeFontResourceDWrite.cpp b/gfx/2d/NativeFontResourceDWrite.cpp index afa14f8c3a77..02395601b599 100644 --- a/gfx/2d/NativeFontResourceDWrite.cpp +++ b/gfx/2d/NativeFontResourceDWrite.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "NativeFontResourceDWrite.h" +#include "UnscaledFontDWrite.h" #include @@ -258,9 +259,10 @@ NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength, return fontResource.forget(); } -already_AddRefed -NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) +already_AddRefed +NativeFontResourceDWrite::CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) { if (aIndex >= mNumberOfFaces) { gfxWarning() << "Font face index is too high for font resource."; @@ -275,13 +277,12 @@ NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, return nullptr; } - RefPtr scaledFont = new ScaledFontDWrite(fontFace, nullptr, aGlyphSize); - if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) { - gfxWarning() << "Unable to create cairo scaled font DWrite font."; - return nullptr; - } + RefPtr unscaledFont = + new UnscaledFontDWrite(fontFace, + DWRITE_FONT_SIMULATIONS_NONE, + mNeedsCairo); - return scaledFont.forget(); + return unscaledFont.forget(); } } // gfx diff --git a/gfx/2d/NativeFontResourceDWrite.h b/gfx/2d/NativeFontResourceDWrite.h index fc11c7b0dfd2..ab06fba66a2e 100644 --- a/gfx/2d/NativeFontResourceDWrite.h +++ b/gfx/2d/NativeFontResourceDWrite.h @@ -31,9 +31,10 @@ public: static already_AddRefed Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo); - already_AddRefed - CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; + already_AddRefed + CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) final; private: NativeFontResourceDWrite(IDWriteFactory *aFactory, diff --git a/gfx/2d/NativeFontResourceFontconfig.cpp b/gfx/2d/NativeFontResourceFontconfig.cpp index a205f98fae08..3c4a30e0677a 100644 --- a/gfx/2d/NativeFontResourceFontconfig.cpp +++ b/gfx/2d/NativeFontResourceFontconfig.cpp @@ -6,6 +6,7 @@ #include "NativeFontResourceFontconfig.h" #include "ScaledFontFontconfig.h" +#include "UnscaledFontFreeType.h" #include "Logging.h" namespace mozilla { @@ -48,17 +49,12 @@ NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength) return resource.forget(); } -already_AddRefed -NativeFontResourceFontconfig::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) +already_AddRefed +NativeFontResourceFontconfig::CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) { - if (aInstanceDataLength < sizeof(ScaledFontFontconfig::InstanceData)) { - gfxWarning() << "Fontconfig scaled font instance data is truncated."; - return nullptr; - } - return ScaledFontFontconfig::CreateFromInstanceData( - *reinterpret_cast(aInstanceData), - mFace, nullptr, 0, aGlyphSize); + RefPtr unscaledFont = new UnscaledFontFontconfig(mFace); + return unscaledFont.forget(); } } // gfx diff --git a/gfx/2d/NativeFontResourceFontconfig.h b/gfx/2d/NativeFontResourceFontconfig.h index 4e95192dfd9f..12afa0ac781f 100644 --- a/gfx/2d/NativeFontResourceFontconfig.h +++ b/gfx/2d/NativeFontResourceFontconfig.h @@ -23,9 +23,9 @@ public: static already_AddRefed Create(uint8_t *aFontData, uint32_t aDataLength); - already_AddRefed - CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; + already_AddRefed + CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; ~NativeFontResourceFontconfig(); diff --git a/gfx/2d/NativeFontResourceGDI.cpp b/gfx/2d/NativeFontResourceGDI.cpp index 4de37943d6c9..df9849636ded 100644 --- a/gfx/2d/NativeFontResourceGDI.cpp +++ b/gfx/2d/NativeFontResourceGDI.cpp @@ -9,14 +9,14 @@ #include "Logging.h" #include "mozilla/RefPtr.h" #include "ScaledFontWin.h" +#include "UnscaledFontGDI.h" namespace mozilla { namespace gfx { /* static */ already_AddRefed -NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength, - bool aNeedsCairo) +NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength) { DWORD numberOfFontsAdded; HANDLE fontResourceHandle = ::AddFontMemResourceEx(aFontData, aDataLength, @@ -27,7 +27,7 @@ NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength, } RefPtr fontResouce = - new NativeFontResourceGDI(fontResourceHandle, aNeedsCairo); + new NativeFontResourceGDI(fontResourceHandle); return fontResouce.forget(); } @@ -37,26 +37,19 @@ NativeFontResourceGDI::~NativeFontResourceGDI() ::RemoveFontMemResourceEx(mFontResourceHandle); } -already_AddRefed -NativeFontResourceGDI::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) +already_AddRefed +NativeFontResourceGDI::CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) { if (aInstanceDataLength < sizeof(LOGFONT)) { - gfxWarning() << "GDI scaled font instance data is truncated."; + gfxWarning() << "GDI unscaled font instance data is truncated."; return nullptr; } const LOGFONT* logFont = reinterpret_cast(aInstanceData); - - // Constructor for ScaledFontWin dereferences and copies the LOGFONT, so we - // are safe to pass this reference. - RefPtr scaledFont = new ScaledFontWin(logFont, nullptr, aGlyphSize); - if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) { - gfxWarning() << "Unable to create cairo scaled font GDI font."; - return nullptr; - } - - return scaledFont.forget(); + RefPtr unscaledFont = new UnscaledFontGDI(*logFont); + return unscaledFont.forget(); } } // gfx diff --git a/gfx/2d/NativeFontResourceGDI.h b/gfx/2d/NativeFontResourceGDI.h index 8a68b13e5d51..8104896f6bf5 100644 --- a/gfx/2d/NativeFontResourceGDI.h +++ b/gfx/2d/NativeFontResourceGDI.h @@ -26,27 +26,24 @@ public: * * @param aFontData the SFNT data. * @param aDataLength length of data. - * @param aNeedsCairo whether the ScaledFont created need a cairo scaled font * @return Referenced NativeFontResourceGDI or nullptr if invalid. */ static already_AddRefed - Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo); + Create(uint8_t *aFontData, uint32_t aDataLength); ~NativeFontResourceGDI(); - already_AddRefed - CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; + already_AddRefed + CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) final; private: - NativeFontResourceGDI(HANDLE aFontResourceHandle, - bool aNeedsCairo) + explicit NativeFontResourceGDI(HANDLE aFontResourceHandle) : mFontResourceHandle(aFontResourceHandle) - , mNeedsCairo(aNeedsCairo) {} HANDLE mFontResourceHandle; - bool mNeedsCairo; }; } // gfx diff --git a/gfx/2d/NativeFontResourceMac.cpp b/gfx/2d/NativeFontResourceMac.cpp index 53782b06d6c5..360fa1c4f52d 100644 --- a/gfx/2d/NativeFontResourceMac.cpp +++ b/gfx/2d/NativeFontResourceMac.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "NativeFontResourceMac.h" +#include "UnscaledFontMac.h" #include "Types.h" #include "mozilla/RefPtr.h" @@ -15,152 +16,12 @@ #include "nsCocoaFeatures.h" -// Simple helper class to automatically release a CFObject when it goes out -// of scope. -template -class AutoRelease -{ -public: - explicit AutoRelease(T aObject) - : mObject(aObject) - { - } - - ~AutoRelease() - { - if (mObject) { - CFRelease(mObject); - } - } - - operator T() - { - return mObject; - } - - T forget() - { - T obj = mObject; - mObject = nullptr; - return obj; - } - -private: - T mObject; -}; - -// This is essentially identical to the similarly-named helper function -// in gfx/thebes/gfxMacFont.cpp. Maybe we should put it somewhere that -// can be shared by both Moz2d and Thebes callers? -static CFDictionaryRef -CreateVariationDictionaryOrNull(CGFontRef aCGFont, uint32_t aVariationCount, - const mozilla::gfx::ScaledFont::VariationSetting* aVariations) -{ - // Avoid calling potentially buggy variation APIs on pre-Sierra macOS - // versions (see bug 1331683) - if (!nsCocoaFeatures::OnSierraOrLater()) { - return nullptr; - } - - AutoRelease - ctFont(CTFontCreateWithGraphicsFont(aCGFont, 0, nullptr, nullptr)); - AutoRelease axes(CTFontCopyVariationAxes(ctFont)); - if (!axes) { - return nullptr; - } - - CFIndex axisCount = CFArrayGetCount(axes); - AutoRelease - dict(CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - - // Number of variation settings passed in the aVariations parameter. - // This will typically be a very low value, so we just linear-search them. - bool allDefaultValues = true; - - for (CFIndex i = 0; i < axisCount; ++i) { - // We sanity-check the axis info found in the CTFont, and bail out - // (returning null) if it doesn't have the expected types. - CFTypeRef axisInfo = CFArrayGetValueAtIndex(axes, i); - if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { - return nullptr; - } - CFDictionaryRef axis = static_cast(axisInfo); - - CFTypeRef axisTag = - CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey); - if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) { - return nullptr; - } - int64_t tagLong; - if (!CFNumberGetValue(static_cast(axisTag), - kCFNumberSInt64Type, &tagLong)) { - return nullptr; - } - - CFTypeRef axisName = - CFDictionaryGetValue(axis, kCTFontVariationAxisNameKey); - if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) { - return nullptr; - } - - // Clamp axis values to the supported range. - CFTypeRef min = CFDictionaryGetValue(axis, kCTFontVariationAxisMinimumValueKey); - CFTypeRef max = CFDictionaryGetValue(axis, kCTFontVariationAxisMaximumValueKey); - CFTypeRef def = CFDictionaryGetValue(axis, kCTFontVariationAxisDefaultValueKey); - if (!min || CFGetTypeID(min) != CFNumberGetTypeID() || - !max || CFGetTypeID(max) != CFNumberGetTypeID() || - !def || CFGetTypeID(def) != CFNumberGetTypeID()) { - return nullptr; - } - double minDouble; - double maxDouble; - double defDouble; - if (!CFNumberGetValue(static_cast(min), kCFNumberDoubleType, - &minDouble) || - !CFNumberGetValue(static_cast(max), kCFNumberDoubleType, - &maxDouble) || - !CFNumberGetValue(static_cast(def), kCFNumberDoubleType, - &defDouble)) { - return nullptr; - } - - double value = defDouble; - for (uint32_t j = 0; j < aVariationCount; ++j) { - if (aVariations[j].mTag == tagLong) { - value = std::min(std::max(aVariations[j].mValue, - minDouble), - maxDouble); - if (value != defDouble) { - allDefaultValues = false; - } - break; - } - } - AutoRelease valueNumber(CFNumberCreate(kCFAllocatorDefault, - kCFNumberDoubleType, - &value)); - CFDictionaryAddValue(dict, axisName, valueNumber); - } - - if (allDefaultValues) { - // We didn't actually set any non-default values, so throw away the - // variations dictionary and just use the default rendering. - return nullptr; - } - - return dict.forget(); -} - namespace mozilla { namespace gfx { /* static */ already_AddRefed -NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength, - uint32_t aVariationCount, - const ScaledFont::VariationSetting* aVariations) +NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength) { // copy font data CFDataRef data = CFDataCreate(kCFAllocatorDefault, aFontData, aDataLength); @@ -184,20 +45,6 @@ NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength, return nullptr; } - if (aVariationCount > 0) { - MOZ_ASSERT(aVariations); - AutoRelease - varDict(CreateVariationDictionaryOrNull(fontRef, aVariationCount, - aVariations)); - if (varDict) { - CGFontRef varFont = CGFontCreateCopyWithVariations(fontRef, varDict); - if (varFont) { - CFRelease(fontRef); - fontRef = varFont; - } - } - } - // passes ownership of fontRef to the NativeFontResourceMac instance RefPtr fontResource = new NativeFontResourceMac(fontRef); @@ -205,18 +52,14 @@ NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength, return fontResource.forget(); } -already_AddRefed -NativeFontResourceMac::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) +already_AddRefed +NativeFontResourceMac::CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) { - RefPtr scaledFont = new ScaledFontMac(mFontRef, nullptr, aGlyphSize); + RefPtr unscaledFont = new UnscaledFontMac(mFontRef); - if (!scaledFont->PopulateCairoScaledFont()) { - gfxWarning() << "Unable to create cairo scaled Mac font."; - return nullptr; - } - - return scaledFont.forget(); + return unscaledFont.forget(); } } // gfx diff --git a/gfx/2d/NativeFontResourceMac.h b/gfx/2d/NativeFontResourceMac.h index 73cd693a6a5a..cdd5f88b755d 100644 --- a/gfx/2d/NativeFontResourceMac.h +++ b/gfx/2d/NativeFontResourceMac.h @@ -20,13 +20,12 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceMac) static already_AddRefed - Create(uint8_t *aFontData, uint32_t aDataLength, - uint32_t aVariationCount, - const ScaledFont::VariationSetting* aVariations); + Create(uint8_t *aFontData, uint32_t aDataLength); - already_AddRefed - CreateScaledFont(uint32_t aIndex, Float aGlyphSize, - const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; + already_AddRefed + CreateUnscaledFont(uint32_t aIndex, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) final; ~NativeFontResourceMac() { diff --git a/gfx/2d/RecordedEvent.cpp b/gfx/2d/RecordedEvent.cpp index 370ac98d1ffe..eb85589efb41 100644 --- a/gfx/2d/RecordedEvent.cpp +++ b/gfx/2d/RecordedEvent.cpp @@ -84,6 +84,8 @@ RecordedEvent::LoadEventFromStream(std::istream &aStream, EventType aType) LOAD_EVENT_TYPE(FONTDESC, RecordedFontDescriptor); LOAD_EVENT_TYPE(PUSHLAYER, RecordedPushLayer); LOAD_EVENT_TYPE(POPLAYER, RecordedPopLayer); + LOAD_EVENT_TYPE(UNSCALEDFONTCREATION, RecordedUnscaledFontCreation); + LOAD_EVENT_TYPE(UNSCALEDFONTDESTRUCTION, RecordedUnscaledFontDestruction); default: return nullptr; } @@ -167,6 +169,10 @@ RecordedEvent::GetEventName(EventType aType) return "PushLayer"; case POPLAYER: return "PopLayer"; + case UNSCALEDFONTCREATION: + return "UnscaledFontCreation"; + case UNSCALEDFONTDESTRUCTION: + return "UnscaledFontDestruction"; default: return "Unknown"; } @@ -1522,7 +1528,6 @@ RecordedSnapshot::OutputSimpleEventInfo(stringstream &aStringStream) const RecordedFontData::~RecordedFontData() { delete[] mData; - delete[] mVariations; } bool @@ -1530,7 +1535,6 @@ RecordedFontData::PlayEvent(Translator *aTranslator) const { RefPtr fontResource = Factory::CreateNativeFontResource(mData, mFontDetails.size, - mFontDetails.variationCount, mVariations, aTranslator->GetDesiredFontType()); if (!fontResource) { return false; @@ -1548,8 +1552,6 @@ RecordedFontData::RecordToStream(std::ostream &aStream) const WriteElement(aStream, mFontDetails.fontDataKey); WriteElement(aStream, mFontDetails.size); aStream.write((const char*)mData, mFontDetails.size); - WriteElement(aStream, mFontDetails.variationCount); - aStream.write((const char*)mVariations, mFontDetails.variationCount * sizeof(ScaledFont::VariationSetting)); } void @@ -1559,23 +1561,14 @@ RecordedFontData::OutputSimpleEventInfo(stringstream &aStringStream) const } void -RecordedFontData::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, - Float aGlyphSize, uint32_t aVariationCount, - const ScaledFont::VariationSetting* aVariations) +RecordedFontData::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex) { mData = new uint8_t[aSize]; memcpy(mData, aData, aSize); - uint32_t varDataSize = aVariationCount * sizeof(ScaledFont::VariationSetting); mFontDetails.fontDataKey = - SFNTData::GetUniqueKey(aData, aSize, varDataSize, aVariations); + SFNTData::GetUniqueKey(aData, aSize, 0, nullptr); mFontDetails.size = aSize; mFontDetails.index = aIndex; - mFontDetails.glyphSize = aGlyphSize; - mFontDetails.variationCount = aVariationCount; - if (aVariationCount > 0) { - mVariations = new ScaledFont::VariationSetting[aVariationCount]; - memcpy(mVariations, aVariations, varDataSize); - } } bool @@ -1587,28 +1580,18 @@ RecordedFontData::GetFontDetails(RecordedFontDetails& fontDetails) fontDetails.fontDataKey = mFontDetails.fontDataKey; fontDetails.size = mFontDetails.size; - fontDetails.glyphSize = mFontDetails.glyphSize; fontDetails.index = mFontDetails.index; - fontDetails.variationCount = mFontDetails.variationCount; return true; } RecordedFontData::RecordedFontData(istream &aStream) : RecordedEvent(FONTDATA) , mData(nullptr) - , mVariations(nullptr) { ReadElement(aStream, mFontDetails.fontDataKey); ReadElement(aStream, mFontDetails.size); mData = new uint8_t[mFontDetails.size]; aStream.read((char*)mData, mFontDetails.size); - ReadElement(aStream, mFontDetails.variationCount); - if (mFontDetails.variationCount > 0) { - mVariations = new ScaledFont::VariationSetting[mFontDetails.variationCount]; - aStream.read((char*)mVariations, mFontDetails.variationCount * sizeof(ScaledFont::VariationSetting)); - } else { - mVariations = nullptr; - } } RecordedFontDescriptor::~RecordedFontDescriptor() @@ -1618,15 +1601,15 @@ RecordedFontDescriptor::~RecordedFontDescriptor() bool RecordedFontDescriptor::PlayEvent(Translator *aTranslator) const { - RefPtr font = - Factory::CreateScaledFontFromFontDescriptor(mType, mData.data(), mData.size(), mFontSize); + RefPtr font = + Factory::CreateUnscaledFontFromFontDescriptor(mType, mData.data(), mData.size()); if (!font) { gfxDevCrash(LogReason::InvalidFont) << - "Failed creating ScaledFont of type " << int(mType) << " from font descriptor"; + "Failed creating UnscaledFont of type " << int(mType) << " from font descriptor"; return false; } - aTranslator->AddScaledFont(mRefPtr, font); + aTranslator->AddUnscaledFont(mRefPtr, font); return true; } @@ -1635,7 +1618,6 @@ RecordedFontDescriptor::RecordToStream(std::ostream &aStream) const { MOZ_ASSERT(mHasDesc); WriteElement(aStream, mType); - WriteElement(aStream, mFontSize); WriteElement(aStream, mRefPtr); WriteElement(aStream, (size_t)mData.size()); aStream.write((char*)mData.data(), mData.size()); @@ -1648,17 +1630,15 @@ RecordedFontDescriptor::OutputSimpleEventInfo(stringstream &aStringStream) const } void -RecordedFontDescriptor::SetFontDescriptor(const uint8_t* aData, uint32_t aSize, Float aFontSize) +RecordedFontDescriptor::SetFontDescriptor(const uint8_t* aData, uint32_t aSize) { mData.assign(aData, aData + aSize); - mFontSize = aFontSize; } RecordedFontDescriptor::RecordedFontDescriptor(istream &aStream) - : RecordedEvent(FONTDATA) + : RecordedEvent(FONTDESC) { ReadElement(aStream, mType); - ReadElement(aStream, mFontSize); ReadElement(aStream, mRefPtr); size_t size; @@ -1668,7 +1648,7 @@ RecordedFontDescriptor::RecordedFontDescriptor(istream &aStream) } bool -RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const +RecordedUnscaledFontCreation::PlayEvent(Translator *aTranslator) const { NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey); if (!fontResource) { @@ -1677,8 +1657,84 @@ RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const return false; } + RefPtr unscaledFont = + fontResource->CreateUnscaledFont(mIndex, mInstanceData.data(), mInstanceData.size()); + aTranslator->AddUnscaledFont(mRefPtr, unscaledFont); + return true; +} + +void +RecordedUnscaledFontCreation::RecordToStream(std::ostream &aStream) const +{ + WriteElement(aStream, mRefPtr); + WriteElement(aStream, mFontDataKey); + WriteElement(aStream, mIndex); + WriteElement(aStream, (size_t)mInstanceData.size()); + aStream.write((char*)mInstanceData.data(), mInstanceData.size()); +} + +void +RecordedUnscaledFontCreation::OutputSimpleEventInfo(stringstream &aStringStream) const +{ + aStringStream << "[" << mRefPtr << "] UnscaledFont Created"; +} + +void +RecordedUnscaledFontCreation::SetFontInstanceData(const uint8_t *aData, uint32_t aSize) +{ + mInstanceData.assign(aData, aData + aSize); +} + +RecordedUnscaledFontCreation::RecordedUnscaledFontCreation(istream &aStream) + : RecordedEvent(UNSCALEDFONTCREATION) +{ + ReadElement(aStream, mRefPtr); + ReadElement(aStream, mFontDataKey); + ReadElement(aStream, mIndex); + + size_t size; + ReadElement(aStream, size); + mInstanceData.resize(size); + aStream.read((char*)mInstanceData.data(), size); +} + +bool +RecordedUnscaledFontDestruction::PlayEvent(Translator *aTranslator) const +{ + aTranslator->RemoveUnscaledFont(mRefPtr); + return true; +} + +void +RecordedUnscaledFontDestruction::RecordToStream(ostream &aStream) const +{ + WriteElement(aStream, mRefPtr); +} + +RecordedUnscaledFontDestruction::RecordedUnscaledFontDestruction(istream &aStream) + : RecordedEvent(UNSCALEDFONTDESTRUCTION) +{ + ReadElement(aStream, mRefPtr); +} + +void +RecordedUnscaledFontDestruction::OutputSimpleEventInfo(stringstream &aStringStream) const +{ + aStringStream << "[" << mRefPtr << "] UnscaledFont Destroyed"; +} + +bool +RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const +{ + UnscaledFont* unscaledFont = aTranslator->LookupUnscaledFont(mUnscaledFont); + if (!unscaledFont) { + gfxDevCrash(LogReason::UnscaledFontNotFound) << + "UnscaledFont lookup failed for key |" << hexa(mUnscaledFont) << "|."; + return false; + } + RefPtr scaledFont = - fontResource->CreateScaledFont(mIndex, mGlyphSize, mInstanceData.data(), mInstanceData.size()); + unscaledFont->CreateScaledFont(mGlyphSize, mInstanceData.data(), mInstanceData.size()); aTranslator->AddScaledFont(mRefPtr, scaledFont); return true; } @@ -1687,8 +1743,7 @@ void RecordedScaledFontCreation::RecordToStream(std::ostream &aStream) const { WriteElement(aStream, mRefPtr); - WriteElement(aStream, mFontDataKey); - WriteElement(aStream, mIndex); + WriteElement(aStream, mUnscaledFont); WriteElement(aStream, mGlyphSize); WriteElement(aStream, (size_t)mInstanceData.size()); aStream.write((char*)mInstanceData.data(), mInstanceData.size()); @@ -1710,8 +1765,7 @@ RecordedScaledFontCreation::RecordedScaledFontCreation(istream &aStream) : RecordedEvent(SCALEDFONTCREATION) { ReadElement(aStream, mRefPtr); - ReadElement(aStream, mFontDataKey); - ReadElement(aStream, mIndex); + ReadElement(aStream, mUnscaledFont); ReadElement(aStream, mGlyphSize); size_t size; diff --git a/gfx/2d/RecordedEvent.h b/gfx/2d/RecordedEvent.h index 0eb949e8c951..5312b4e0e867 100644 --- a/gfx/2d/RecordedEvent.h +++ b/gfx/2d/RecordedEvent.h @@ -24,7 +24,7 @@ const uint32_t kMagicInt = 0xc001feed; // loss of backwards compatibility. Old streams will not work in a player // using a newer major revision. And new streams will not work in a player // using an older major revision. -const uint16_t kMajorRevision = 8; +const uint16_t kMajorRevision = 9; // A change in minor revision means additions of new events. New streams will // not play in older players. const uint16_t kMinorRevision = 0; @@ -67,8 +67,6 @@ struct RecordedFontDetails uint64_t fontDataKey; uint32_t size; uint32_t index; - uint32_t variationCount; - Float glyphSize; }; // Used by the Azure drawing debugger (player2d) @@ -90,6 +88,7 @@ public: virtual FilterNode *LookupFilterNode(ReferencePtr aRefPtr) = 0; virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0; virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0; + virtual UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) = 0; virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0; virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0; virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0; @@ -103,6 +102,8 @@ public: virtual void RemoveGradientStops(ReferencePtr aRefPtr) = 0; virtual void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) = 0; virtual void RemoveScaledFont(ReferencePtr aRefPtr) = 0; + virtual void AddUnscaledFont(ReferencePtr aRefPtr, UnscaledFont* aUnscaledFont) = 0; + virtual void RemoveUnscaledFont(ReferencePtr aRefPtr) = 0; virtual void AddNativeFontResource(uint64_t aKey, NativeFontResource *aNativeFontResource) = 0; @@ -197,6 +198,8 @@ public: FONTDESC, PUSHLAYER, POPLAYER, + UNSCALEDFONTCREATION, + UNSCALEDFONTDESTRUCTION, }; static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1; @@ -1015,24 +1018,22 @@ class RecordedFontData : public RecordedEvent { public: static void FontDataProc(const uint8_t *aData, uint32_t aSize, - uint32_t aIndex, Float aGlyphSize, - uint32_t aVariationCount, - const ScaledFont::VariationSetting* aVariations, - void* aBaton) + uint32_t aIndex, void* aBaton) { auto recordedFontData = static_cast(aBaton); - recordedFontData->SetFontData(aData, aSize, aIndex, aGlyphSize, - aVariationCount, aVariations); + recordedFontData->SetFontData(aData, aSize, aIndex); } - explicit RecordedFontData(ScaledFont *aScaledFont) - : RecordedEvent(FONTDATA), mData(nullptr), mVariations(nullptr) + explicit RecordedFontData(UnscaledFont *aUnscaledFont) + : RecordedEvent(FONTDATA), mData(nullptr) { - mGetFontFileDataSucceeded = aScaledFont->GetFontFileData(&FontDataProc, this); + mGetFontFileDataSucceeded = aUnscaledFont->GetFontFileData(&FontDataProc, this); } ~RecordedFontData(); + bool IsValid() const { return mGetFontFileDataSucceeded; } + virtual bool PlayEvent(Translator *aTranslator) const; virtual void RecordToStream(std::ostream &aStream) const; @@ -1041,9 +1042,7 @@ public: virtual std::string GetName() const { return "Font Data"; } virtual ReferencePtr GetObjectRef() const { return nullptr; }; - void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, - Float aGlyphSize, uint32_t aVariationCount, - const ScaledFont::VariationSetting* aVariations); + void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex); bool GetFontDetails(RecordedFontDetails& fontDetails); @@ -1051,7 +1050,6 @@ private: friend class RecordedEvent; uint8_t* mData; - ScaledFont::VariationSetting* mVariations; RecordedFontDetails mFontDetails; bool mGetFontFileDataSucceeded; @@ -1063,18 +1061,18 @@ class RecordedFontDescriptor : public RecordedEvent { public: static void FontDescCb(const uint8_t* aData, uint32_t aSize, - Float aFontSize, void* aBaton) + void* aBaton) { auto recordedFontDesc = static_cast(aBaton); - recordedFontDesc->SetFontDescriptor(aData, aSize, aFontSize); + recordedFontDesc->SetFontDescriptor(aData, aSize); } - explicit RecordedFontDescriptor(ScaledFont* aScaledFont) + explicit RecordedFontDescriptor(UnscaledFont* aUnscaledFont) : RecordedEvent(FONTDESC) - , mType(aScaledFont->GetType()) - , mRefPtr(aScaledFont) + , mType(aUnscaledFont->GetType()) + , mRefPtr(aUnscaledFont) { - mHasDesc = aScaledFont->GetFontDescriptor(FontDescCb, this); + mHasDesc = aUnscaledFont->GetFontDescriptor(FontDescCb, this); } ~RecordedFontDescriptor(); @@ -1092,18 +1090,77 @@ public: private: friend class RecordedEvent; - void SetFontDescriptor(const uint8_t* aData, uint32_t aSize, Float aFontSize); + void SetFontDescriptor(const uint8_t* aData, uint32_t aSize); bool mHasDesc; FontType mType; - Float mFontSize; std::vector mData; ReferencePtr mRefPtr; MOZ_IMPLICIT RecordedFontDescriptor(std::istream &aStream); }; +class RecordedUnscaledFontCreation : public RecordedEvent { +public: + static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize, void* aBaton) + { + auto recordedUnscaledFontCreation = static_cast(aBaton); + recordedUnscaledFontCreation->SetFontInstanceData(aData, aSize); + } + + RecordedUnscaledFontCreation(UnscaledFont* aUnscaledFont, + RecordedFontDetails aFontDetails) + : RecordedEvent(UNSCALEDFONTCREATION) + , mRefPtr(aUnscaledFont) + , mFontDataKey(aFontDetails.fontDataKey) + , mIndex(aFontDetails.index) + { + aUnscaledFont->GetFontInstanceData(FontInstanceDataProc, this); + } + + virtual bool PlayEvent(Translator *aTranslator) const; + + virtual void RecordToStream(std::ostream &aStream) const; + virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const; + + virtual std::string GetName() const { return "UnscaledFont Creation"; } + virtual ReferencePtr GetObjectRef() const { return mRefPtr; } + + void SetFontInstanceData(const uint8_t *aData, uint32_t aSize); + +private: + friend class RecordedEvent; + + ReferencePtr mRefPtr; + uint64_t mFontDataKey; + uint32_t mIndex; + std::vector mInstanceData; + + MOZ_IMPLICIT RecordedUnscaledFontCreation(std::istream &aStream); +}; + +class RecordedUnscaledFontDestruction : public RecordedEvent { +public: + MOZ_IMPLICIT RecordedUnscaledFontDestruction(ReferencePtr aRefPtr) + : RecordedEvent(UNSCALEDFONTDESTRUCTION), mRefPtr(aRefPtr) + {} + + virtual bool PlayEvent(Translator *aTranslator) const; + + virtual void RecordToStream(std::ostream &aStream) const; + virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const; + + virtual std::string GetName() const { return "UnscaledFont Destruction"; } + virtual ReferencePtr GetObjectRef() const { return mRefPtr; } +private: + friend class RecordedEvent; + + ReferencePtr mRefPtr; + + MOZ_IMPLICIT RecordedUnscaledFontDestruction(std::istream &aStream); +}; + class RecordedScaledFontCreation : public RecordedEvent { public: @@ -1114,12 +1171,11 @@ public: } RecordedScaledFontCreation(ScaledFont* aScaledFont, - RecordedFontDetails aFontDetails) + UnscaledFont* aUnscaledFont) : RecordedEvent(SCALEDFONTCREATION) , mRefPtr(aScaledFont) - , mFontDataKey(aFontDetails.fontDataKey) - , mGlyphSize(aFontDetails.glyphSize) - , mIndex(aFontDetails.index) + , mUnscaledFont(aUnscaledFont) + , mGlyphSize(aScaledFont->GetSize()) { aScaledFont->GetFontInstanceData(FontInstanceDataProc, this); } @@ -1138,9 +1194,8 @@ private: friend class RecordedEvent; ReferencePtr mRefPtr; - uint64_t mFontDataKey; + ReferencePtr mUnscaledFont; Float mGlyphSize; - uint32_t mIndex; std::vector mInstanceData; MOZ_IMPLICIT RecordedScaledFontCreation(std::istream &aStream); diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp index 70f991cd8c88..05278bd909ff 100644 --- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -5,6 +5,7 @@ #include "DrawTargetD2D1.h" #include "ScaledFontDWrite.h" +#include "UnscaledFontDWrite.h" #include "PathD2D.h" #include "gfxFont.h" @@ -221,7 +222,7 @@ ScaledFontDWrite::CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink } bool -ScaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) +UnscaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) { UINT32 fileCount = 0; mFontFace->GetFiles(&fileCount, nullptr); @@ -242,13 +243,13 @@ ScaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton UINT32 refKeySize; // XXX - This can currently crash for webfonts, as when we get the reference // key out of the file, that can be an invalid reference key for the loader - // we use it with. The fix to this is not obvious but it will probably + // we use it with. The fix to this is not obvious but it will probably // have to happen inside thebes. file->GetReferenceKey(&referenceKey, &refKeySize); RefPtr loader; file->GetLoader(getter_AddRefs(loader)); - + RefPtr stream; loader->CreateStreamFromKey(referenceKey, refKeySize, getter_AddRefs(stream)); @@ -258,20 +259,33 @@ ScaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton MOZ_ASSERT(false); return false; } - + uint32_t fileSize = static_cast(fileSize64); const void *fragmentStart; void *context; stream->ReadFileFragment(&fragmentStart, 0, fileSize, &context); - aDataCallback((uint8_t*)fragmentStart, fileSize, mFontFace->GetIndex(), mSize, - 0, nullptr, aBaton); + aDataCallback((uint8_t*)fragmentStart, fileSize, mFontFace->GetIndex(), aBaton); stream->ReleaseFileFragment(context); return true; } +already_AddRefed +UnscaledFontDWrite::CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) +{ + RefPtr scaledFont = new ScaledFontDWrite(mFontFace, this, aGlyphSize); + if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) { + gfxWarning() << "Unable to create cairo scaled font DWrite font."; + return nullptr; + } + + return scaledFont.forget(); +} + AntialiasMode ScaledFontDWrite::GetDefaultAAMode() { diff --git a/gfx/2d/ScaledFontDWrite.h b/gfx/2d/ScaledFontDWrite.h index c3c97e2c72e7..bce40f5ce77a 100644 --- a/gfx/2d/ScaledFontDWrite.h +++ b/gfx/2d/ScaledFontDWrite.h @@ -18,7 +18,7 @@ namespace gfx { class ScaledFontDWrite final : public ScaledFontBase { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDwrite) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDWrite, override) ScaledFontDWrite(IDWriteFontFace *aFont, const RefPtr& aUnscaledFont, Float aSize) @@ -35,26 +35,24 @@ public: bool aForceGDIMode, const gfxFontStyle* aStyle); - virtual FontType GetType() const { return FontType::DWRITE; } + FontType GetType() const override { return FontType::DWRITE; } - virtual already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); - virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, const Matrix *aTransformHint); + already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) override; + void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, const Matrix *aTransformHint) override; void CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink *aSink); - virtual void GetGlyphDesignMetrics(const uint16_t* aGlyphIndices, uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics); + void GetGlyphDesignMetrics(const uint16_t* aGlyphIndices, uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics) override; - virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton); + bool CanSerialize() override { return true; } - virtual bool CanSerialize() override { return true; } - - virtual AntialiasMode GetDefaultAAMode() override; + AntialiasMode GetDefaultAAMode() override; bool UseEmbeddedBitmaps() { return mUseEmbeddedBitmap; } bool ForceGDIMode() { return mForceGDIMode; } #ifdef USE_SKIA - virtual SkTypeface* GetSkTypeface(); + SkTypeface* GetSkTypeface() override; SkFontStyle mStyle; #endif @@ -71,13 +69,13 @@ protected: class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsDWrite) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsDWrite, override) explicit GlyphRenderingOptionsDWrite(IDWriteRenderingParams *aParams) : mParams(aParams) { } - virtual FontType GetType() const { return FontType::DWRITE; } + FontType GetType() const override { return FontType::DWRITE; } private: friend class DrawTargetD2D; diff --git a/gfx/2d/ScaledFontFontconfig.cpp b/gfx/2d/ScaledFontFontconfig.cpp index 25fd44fc4d8b..76ff30100964 100644 --- a/gfx/2d/ScaledFontFontconfig.cpp +++ b/gfx/2d/ScaledFontFontconfig.cpp @@ -4,14 +4,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ScaledFontFontconfig.h" +#include "UnscaledFontFreeType.h" #include "Logging.h" #ifdef USE_SKIA #include "skia/include/ports/SkTypeface_cairo.h" #endif -#include FT_TRUETYPE_TABLES_H - #include namespace mozilla { @@ -48,27 +47,6 @@ SkTypeface* ScaledFontFontconfig::GetSkTypeface() } #endif -bool -ScaledFontFontconfig::GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) -{ - bool success = false; - // Lock the Cairo scaled font to force it to resolve the Fontconfig pattern to an FT_Face. - if (FT_Face face = cairo_ft_scaled_font_lock_face(GetCairoScaledFont())) { - FT_ULong length = 0; - // Request the SFNT file. This may not always succeed for all font types. - if (FT_Load_Sfnt_Table(face, 0, 0, nullptr, &length) == FT_Err_Ok) { - uint8_t* fontData = new uint8_t[length]; - if (FT_Load_Sfnt_Table(face, 0, 0, fontData, &length) == FT_Err_Ok) { - aDataCallback(fontData, length, 0, mSize, 0, nullptr, aBaton); - success = true; - } - delete[] fontData; - } - cairo_ft_scaled_font_unlock_face(GetCairoScaledFont()); - } - return success; -} - ScaledFontFontconfig::InstanceData::InstanceData(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern) : mFlags(0) , mHintStyle(FC_HINT_NONE) @@ -253,52 +231,35 @@ ScaledFontFontconfig::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBat return true; } -bool -ScaledFontFontconfig::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) +already_AddRefed +UnscaledFontFontconfig::CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) { - // Check if the Fontconfig pattern uses a font file and index to specify which - // font to load. If so, record these as a font descriptor along with any instance - // data required to rebuild a scaled font from it. - FcChar8* pathname = nullptr; - if (FcPatternGetString(mPattern, FC_FILE, 0, &pathname) != FcResultMatch) { - return false; + if (aInstanceDataLength < sizeof(ScaledFontFontconfig::InstanceData)) { + gfxWarning() << "Fontconfig scaled font instance data is truncated."; + return nullptr; } - int index = 0; - FcPatternGetInteger(mPattern, FC_INDEX, 0, &index); - if (index < 0) { - return false; - } - - size_t pathLength = strlen(reinterpret_cast(pathname)) + 1; - size_t dataLength = sizeof(FontDescriptor) + pathLength; - uint8_t* data = new uint8_t[dataLength]; - FontDescriptor* desc = reinterpret_cast(data); - desc->mPathLength = pathLength; - desc->mIndex = index; - desc->mInstanceData = InstanceData(GetCairoScaledFont(), mPattern); - memcpy(data + sizeof(FontDescriptor), pathname, pathLength); - - aCb(data, dataLength, mSize, aBaton); - delete[] data; - return true; + const ScaledFontFontconfig::InstanceData *instanceData = + reinterpret_cast(aInstanceData); + return ScaledFontFontconfig::CreateFromInstanceData(*instanceData, this, aGlyphSize); } already_AddRefed ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData, - FT_Face aFace, const char* aPathname, uint32_t aIndex, + UnscaledFontFontconfig* aUnscaledFont, Float aSize) - { FcPattern* pattern = FcPatternCreate(); if (!pattern) { gfxWarning() << "Failing initializing Fontconfig pattern for scaled font"; return nullptr; } - if (aFace) { - FcPatternAddFTFace(pattern, FC_FT_FACE, aFace); + if (aUnscaledFont->GetFace()) { + FcPatternAddFTFace(pattern, FC_FT_FACE, aUnscaledFont->GetFace()); } else { - FcPatternAddString(pattern, FC_FILE, reinterpret_cast(aPathname)); - FcPatternAddInteger(pattern, FC_INDEX, aIndex); + FcPatternAddString(pattern, FC_FILE, reinterpret_cast(aUnscaledFont->GetFile())); + FcPatternAddInteger(pattern, FC_INDEX, aUnscaledFont->GetIndex()); } FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize); aInstanceData.SetupPattern(pattern); @@ -332,15 +293,15 @@ ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData, } RefPtr scaledFont = - new ScaledFontFontconfig(cairoScaledFont, pattern, nullptr, aSize); + new ScaledFontFontconfig(cairoScaledFont, pattern, aUnscaledFont, aSize); FcPatternDestroy(pattern); return scaledFont.forget(); } -already_AddRefed -ScaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize) +already_AddRefed +UnscaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength) { if (aDataLength < sizeof(FontDescriptor)) { gfxWarning() << "Fontconfig font descriptor is truncated."; @@ -352,12 +313,14 @@ ScaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aD gfxWarning() << "Pathname in Fontconfig font descriptor has invalid size."; return nullptr; } - const char* pathname = reinterpret_cast(aData + sizeof(FontDescriptor)); - if (pathname[desc->mPathLength - 1] != '\0') { + const char* path = reinterpret_cast(aData + sizeof(FontDescriptor)); + if (path[desc->mPathLength - 1] != '\0') { gfxWarning() << "Pathname in Fontconfig font descriptor is not terminated."; return nullptr; } - return CreateFromInstanceData(desc->mInstanceData, nullptr, pathname, desc->mIndex, aSize); + + RefPtr unscaledFont = new UnscaledFontFontconfig(path, desc->mIndex); + return unscaledFont.forget(); } } // namespace gfx diff --git a/gfx/2d/ScaledFontFontconfig.h b/gfx/2d/ScaledFontFontconfig.h index a446dd2e018e..d69aa32183c3 100644 --- a/gfx/2d/ScaledFontFontconfig.h +++ b/gfx/2d/ScaledFontFontconfig.h @@ -14,6 +14,7 @@ namespace mozilla { namespace gfx { class NativeFontResourceFontconfig; +class UnscaledFontFontconfig; class ScaledFontFontconfig : public ScaledFontBase { @@ -31,17 +32,11 @@ public: bool CanSerialize() override { return true; } - bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override; - bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override; - bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override; - - static already_AddRefed - CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize); - private: friend class NativeFontResourceFontconfig; + friend class UnscaledFontFontconfig; struct InstanceData { @@ -68,16 +63,9 @@ private: Float mSkew; }; - struct FontDescriptor - { - uint32_t mPathLength; - uint32_t mIndex; - InstanceData mInstanceData; - }; - static already_AddRefed CreateFromInstanceData(const InstanceData& aInstanceData, - FT_Face aFace, const char* aPathname, uint32_t aIndex, + UnscaledFontFontconfig* aUnscaledFont, Float aSize); FcPattern* mPattern; diff --git a/gfx/2d/ScaledFontMac.cpp b/gfx/2d/ScaledFontMac.cpp index f5ef2f0da56e..dc1d88a64964 100644 --- a/gfx/2d/ScaledFontMac.cpp +++ b/gfx/2d/ScaledFontMac.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ScaledFontMac.h" +#include "UnscaledFontMac.h" #ifdef USE_SKIA #include "PathSkia.h" #include "skia/include/core/SkPaint.h" @@ -31,6 +32,40 @@ CGPathRef CGFontGetGlyphPath(CGFontRef fontRef, CGAffineTransform *textTransform namespace mozilla { namespace gfx { +// Simple helper class to automatically release a CFObject when it goes out +// of scope. +template +class AutoRelease +{ +public: + explicit AutoRelease(T aObject) + : mObject(aObject) + { + } + + ~AutoRelease() + { + if (mObject) { + CFRelease(mObject); + } + } + + operator T() + { + return mObject; + } + + T forget() + { + T obj = mObject; + mObject = nullptr; + return obj; + } + +private: + T mObject; +}; + ScaledFontMac::CTFontDrawGlyphsFuncT* ScaledFontMac::CTFontDrawGlyphsPtr = nullptr; bool ScaledFontMac::sSymbolLookupDone = false; @@ -69,7 +104,8 @@ CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize) ScaledFontMac::ScaledFontMac(CGFontRef aFont, const RefPtr& aUnscaledFont, - Float aSize) + Float aSize, + bool aOwnsFont) : ScaledFontBase(aUnscaledFont, aSize) { if (!sSymbolLookupDone) { @@ -78,8 +114,11 @@ ScaledFontMac::ScaledFontMac(CGFontRef aFont, sSymbolLookupDone = true; } - // XXX: should we be taking a reference - mFont = CGFontRetain(aFont); + if (!aOwnsFont) { + // XXX: should we be taking a reference + mFont = CGFontRetain(aFont); + } + if (CTFontDrawGlyphsPtr != nullptr) { // only create mCTFont if we're going to be using the CTFontDrawGlyphs API mCTFont = CreateCTFontFromCGFontWithVariations(aFont, aSize); @@ -214,7 +253,7 @@ static void CollectVariationSetting(const void *key, const void *value, void *co } bool -ScaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) +UnscaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) { // We'll reconstruct a TTF font from the tables we can get from the CGFont CFArrayRef tags = CGFontCopyTableTags(mFont); @@ -281,6 +320,15 @@ ScaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) // set checkSumAdjust to the computed checksum memcpy(&buf.data[checkSumAdjustmentOffset], &fontChecksum, sizeof(fontChecksum)); + // we always use an index of 0 + aDataCallback(buf.data, buf.offset, 0, aBaton); + + return true; +} + +bool +ScaledFontMac::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) +{ // Collect any variation settings that were incorporated into the CTFont. uint32_t variationCount = 0; VariationSetting* variations = nullptr; @@ -302,12 +350,158 @@ ScaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) } } - // we always use an index of 0 - aDataCallback(buf.data, buf.offset, 0, mSize, variationCount, variations, aBaton); + aCb(reinterpret_cast(variations), variationCount * sizeof(VariationSetting), aBaton); delete[] variations; return true; +} +static CFDictionaryRef +CreateVariationDictionaryOrNull(CGFontRef aCGFont, uint32_t aVariationCount, + const ScaledFont::VariationSetting* aVariations) +{ + // Avoid calling potentially buggy variation APIs on pre-Sierra macOS + // versions (see bug 1331683) + if (!nsCocoaFeatures::OnSierraOrLater()) { + return nullptr; + } + + AutoRelease + ctFont(CTFontCreateWithGraphicsFont(aCGFont, 0, nullptr, nullptr)); + AutoRelease axes(CTFontCopyVariationAxes(ctFont)); + if (!axes) { + return nullptr; + } + + CFIndex axisCount = CFArrayGetCount(axes); + AutoRelease + dict(CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + + // Number of variation settings passed in the aVariations parameter. + // This will typically be a very low value, so we just linear-search them. + bool allDefaultValues = true; + + for (CFIndex i = 0; i < axisCount; ++i) { + // We sanity-check the axis info found in the CTFont, and bail out + // (returning null) if it doesn't have the expected types. + CFTypeRef axisInfo = CFArrayGetValueAtIndex(axes, i); + if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { + return nullptr; + } + CFDictionaryRef axis = static_cast(axisInfo); + + CFTypeRef axisTag = + CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey); + if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) { + return nullptr; + } + int64_t tagLong; + if (!CFNumberGetValue(static_cast(axisTag), + kCFNumberSInt64Type, &tagLong)) { + return nullptr; + } + + CFTypeRef axisName = + CFDictionaryGetValue(axis, kCTFontVariationAxisNameKey); + if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) { + return nullptr; + } + + // Clamp axis values to the supported range. + CFTypeRef min = CFDictionaryGetValue(axis, kCTFontVariationAxisMinimumValueKey); + CFTypeRef max = CFDictionaryGetValue(axis, kCTFontVariationAxisMaximumValueKey); + CFTypeRef def = CFDictionaryGetValue(axis, kCTFontVariationAxisDefaultValueKey); + if (!min || CFGetTypeID(min) != CFNumberGetTypeID() || + !max || CFGetTypeID(max) != CFNumberGetTypeID() || + !def || CFGetTypeID(def) != CFNumberGetTypeID()) { + return nullptr; + } + double minDouble; + double maxDouble; + double defDouble; + if (!CFNumberGetValue(static_cast(min), kCFNumberDoubleType, + &minDouble) || + !CFNumberGetValue(static_cast(max), kCFNumberDoubleType, + &maxDouble) || + !CFNumberGetValue(static_cast(def), kCFNumberDoubleType, + &defDouble)) { + return nullptr; + } + + double value = defDouble; + for (uint32_t j = 0; j < aVariationCount; ++j) { + if (aVariations[j].mTag == tagLong) { + value = std::min(std::max(aVariations[j].mValue, + minDouble), + maxDouble); + if (value != defDouble) { + allDefaultValues = false; + } + break; + } + } + AutoRelease valueNumber(CFNumberCreate(kCFAllocatorDefault, + kCFNumberDoubleType, + &value)); + CFDictionaryAddValue(dict, axisName, valueNumber); + } + + if (allDefaultValues) { + // We didn't actually set any non-default values, so throw away the + // variations dictionary and just use the default rendering. + return nullptr; + } + + return dict.forget(); +} + +CGFontRef +UnscaledFontMac::CreateCGFontWithVariations(CGFontRef aFont, + uint32_t aVariationCount, + const ScaledFont::VariationSetting* aVariations) +{ + MOZ_ASSERT(aVariationCount > 0); + MOZ_ASSERT(aVariations); + + AutoRelease + varDict(CreateVariationDictionaryOrNull(aFont, aVariationCount, aVariations)); + if (!varDict) { + return nullptr; + } + + return CGFontCreateCopyWithVariations(aFont, varDict); +} + +already_AddRefed +UnscaledFontMac::CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) +{ + uint32_t variationCount = + aInstanceDataLength / sizeof(ScaledFont::VariationSetting); + const ScaledFont::VariationSetting* variations = + reinterpret_cast(aInstanceData); + + CGFontRef fontRef = mFont; + if (variationCount > 0) { + CGFontRef varFont = + CreateCGFontWithVariations(mFont, variationCount, variations); + if (varFont) { + fontRef = varFont; + } + } + + RefPtr scaledFont = + new ScaledFontMac(fontRef, this, aGlyphSize, fontRef != mFont); + + if (!scaledFont->PopulateCairoScaledFont()) { + gfxWarning() << "Unable to create cairo scaled Mac font."; + return nullptr; + } + + return scaledFont.forget(); } #ifdef USE_CAIRO_SCALED_FONT diff --git a/gfx/2d/ScaledFontMac.h b/gfx/2d/ScaledFontMac.h index 69ff35c6be7e..8b1cbb401967 100644 --- a/gfx/2d/ScaledFontMac.h +++ b/gfx/2d/ScaledFontMac.h @@ -40,20 +40,22 @@ private: class ScaledFontMac : public ScaledFontBase { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontMac) - ScaledFontMac(CGFontRef aFont, const RefPtr& aUnscaledFont, Float aSize); - virtual ~ScaledFontMac(); + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontMac, override) + ScaledFontMac(CGFontRef aFont, const RefPtr& aUnscaledFont, Float aSize, bool aOwnsFont = false); + ~ScaledFontMac(); - virtual FontType GetType() const { return FontType::MAC; } + FontType GetType() const override { return FontType::MAC; } #ifdef USE_SKIA - virtual SkTypeface* GetSkTypeface(); + SkTypeface* GetSkTypeface() override; #endif - virtual already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); - virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton); - virtual bool CanSerialize() { return true; } + already_AddRefed GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) override; + + bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override; + + bool CanSerialize() override { return true; } #ifdef USE_CAIRO_SCALED_FONT - cairo_font_face_t* GetCairoFontFace(); + cairo_font_face_t* GetCairoFontFace() override; #endif private: diff --git a/gfx/2d/ScaledFontWin.cpp b/gfx/2d/ScaledFontWin.cpp index 58275ed3dc51..2ae91d935313 100644 --- a/gfx/2d/ScaledFontWin.cpp +++ b/gfx/2d/ScaledFontWin.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ScaledFontWin.h" +#include "UnscaledFontGDI.h" #include "AutoHelpersWin.h" #include "Logging.h" @@ -31,7 +32,7 @@ ScaledFontWin::ScaledFontWin(const LOGFONT* aFont, } bool -ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) +UnscaledFontGDI::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) { AutoDC dc; AutoSelectFont font(dc.GetDC(), &mLogFont); @@ -56,7 +57,7 @@ ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) return false; } - aDataCallback(fontData.get(), tableSize, 0, mSize, 0, nullptr, aBaton); + aDataCallback(fontData.get(), tableSize, 0, aBaton); return true; } @@ -68,21 +69,41 @@ ScaledFontWin::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) } bool -ScaledFontWin::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) +UnscaledFontGDI::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) { - aCb(reinterpret_cast(&mLogFont), sizeof(mLogFont), mSize, aBaton); + aCb(reinterpret_cast(&mLogFont), sizeof(mLogFont), aBaton); return true; } -already_AddRefed -ScaledFontWin::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize) +already_AddRefed +UnscaledFontGDI::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength) { + if (aDataLength < sizeof(LOGFONT)) { + gfxWarning() << "GDI font descriptor is truncated."; + return nullptr; + } + + const LOGFONT* logFont = reinterpret_cast(aData); + RefPtr unscaledFont = new UnscaledFontGDI(*logFont); + return unscaledFont.forget(); +} + +already_AddRefed +UnscaledFontGDI::CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) +{ + if (aInstanceDataLength < sizeof(LOGFONT)) { + gfxWarning() << "GDI unscaled font instance data is truncated."; + return nullptr; + } + NativeFont nativeFont; nativeFont.mType = NativeFontType::GDI_FONT_FACE; - nativeFont.mFont = (void*)aData; + nativeFont.mFont = (void*)aInstanceData; RefPtr font = - Factory::CreateScaledFontForNativeFont(nativeFont, nullptr, aSize); + Factory::CreateScaledFontForNativeFont(nativeFont, this, aGlyphSize); #ifdef USE_CAIRO_SCALED_FONT static_cast(font.get())->PopulateCairoScaledFont(); diff --git a/gfx/2d/ScaledFontWin.h b/gfx/2d/ScaledFontWin.h index 3b935ded8e79..ccf00c7b145e 100644 --- a/gfx/2d/ScaledFontWin.h +++ b/gfx/2d/ScaledFontWin.h @@ -15,26 +15,19 @@ namespace gfx { class ScaledFontWin : public ScaledFontBase { public: - MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin, override) ScaledFontWin(const LOGFONT* aFont, const RefPtr& aUnscaledFont, Float aSize); - virtual FontType GetType() const { return FontType::GDI; } - - bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override; + FontType GetType() const override { return FontType::GDI; } bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override; - virtual bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override; - - static already_AddRefed - CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize); - - virtual AntialiasMode GetDefaultAAMode() override; + AntialiasMode GetDefaultAAMode() override; #ifdef USE_SKIA - virtual SkTypeface* GetSkTypeface(); + SkTypeface* GetSkTypeface() override; #endif protected: diff --git a/gfx/2d/UnscaledFontDWrite.h b/gfx/2d/UnscaledFontDWrite.h index 121a7aead48d..8bfc20164e69 100644 --- a/gfx/2d/UnscaledFontDWrite.h +++ b/gfx/2d/UnscaledFontDWrite.h @@ -19,9 +19,11 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontDWrite, override) explicit UnscaledFontDWrite(const RefPtr& aFontFace, DWRITE_FONT_SIMULATIONS aSimulations = - DWRITE_FONT_SIMULATIONS_NONE) - : mFontFace(aFontFace), - mSimulations(aSimulations) + DWRITE_FONT_SIMULATIONS_NONE, + bool aNeedsCairo = false) + : mFontFace(aFontFace) + , mSimulations(aSimulations) + , mNeedsCairo(aNeedsCairo) {} FontType GetType() const override { return FontType::DWRITE; } @@ -29,9 +31,17 @@ public: const RefPtr GetFontFace() const { return mFontFace; } DWRITE_FONT_SIMULATIONS GetSimulations() const { return mSimulations; } + bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override; + + already_AddRefed + CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) override; + private: RefPtr mFontFace; DWRITE_FONT_SIMULATIONS mSimulations; + bool mNeedsCairo; }; } // namespace gfx diff --git a/gfx/2d/UnscaledFontFreeType.cpp b/gfx/2d/UnscaledFontFreeType.cpp new file mode 100644 index 000000000000..b342fb493112 --- /dev/null +++ b/gfx/2d/UnscaledFontFreeType.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +#include "UnscaledFontFreeType.h" + +#include FT_TRUETYPE_TABLES_H + +namespace mozilla { +namespace gfx { + +bool +UnscaledFontFreeType::GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) +{ + bool success = false; + FT_ULong length = 0; + // Request the SFNT file. This may not always succeed for all font types. + if (FT_Load_Sfnt_Table(mFace, 0, 0, nullptr, &length) == FT_Err_Ok) { + uint8_t* fontData = new uint8_t[length]; + if (FT_Load_Sfnt_Table(mFace, 0, 0, fontData, &length) == FT_Err_Ok) { + aDataCallback(fontData, length, 0, aBaton); + success = true; + } + delete[] fontData; + } + return success; +} + +bool +UnscaledFontFreeType::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) +{ + if (mFile.empty()) { + return false; + } + + const char* path = mFile.c_str(); + size_t pathLength = strlen(path) + 1; + size_t dataLength = sizeof(FontDescriptor) + pathLength; + uint8_t* data = new uint8_t[dataLength]; + FontDescriptor* desc = reinterpret_cast(data); + desc->mPathLength = pathLength; + desc->mIndex = mIndex; + memcpy(data + sizeof(FontDescriptor), path, pathLength); + + aCb(data, dataLength, aBaton); + delete[] data; + return true; +} + +} // namespace gfx +} // namespace mozilla + diff --git a/gfx/2d/UnscaledFontFreeType.h b/gfx/2d/UnscaledFontFreeType.h index 2e57feb1e749..4b6e42fa8a7e 100644 --- a/gfx/2d/UnscaledFontFreeType.h +++ b/gfx/2d/UnscaledFontFreeType.h @@ -17,16 +17,25 @@ class UnscaledFontFreeType : public UnscaledFont { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontFreeType, override) - explicit UnscaledFontFreeType(FT_Face aFace) + explicit UnscaledFontFreeType(FT_Face aFace, + bool aOwnsFace = false) : mFace(aFace) + , mOwnsFace(aOwnsFace) , mIndex(0) {} explicit UnscaledFontFreeType(const char* aFile, uint32_t aIndex = 0) : mFace(nullptr) + , mOwnsFace(false) , mFile(aFile) , mIndex(aIndex) {} + ~UnscaledFontFreeType() + { + if (mOwnsFace) { + FT_Done_Face(mFace); + } + } FontType GetType() const override { return FontType::FREETYPE; } @@ -34,8 +43,19 @@ public: const char* GetFile() const { return mFile.c_str(); } uint32_t GetIndex() const { return mIndex; } + struct FontDescriptor + { + uint32_t mPathLength; + uint32_t mIndex; + }; + + bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override; + + bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override; + private: FT_Face mFace; + bool mOwnsFace; std::string mFile; uint32_t mIndex; }; @@ -45,8 +65,9 @@ class UnscaledFontFontconfig : public UnscaledFontFreeType { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontFontconfig, override) - explicit UnscaledFontFontconfig(FT_Face aFace) - : UnscaledFontFreeType(aFace) + explicit UnscaledFontFontconfig(FT_Face aFace, + bool aOwnsFace = false) + : UnscaledFontFreeType(aFace, aOwnsFace) {} explicit UnscaledFontFontconfig(const char* aFile, uint32_t aIndex = 0) @@ -54,6 +75,14 @@ public: {} FontType GetType() const override { return FontType::FONTCONFIG; } + + static already_AddRefed + CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength); + + already_AddRefed + CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) override; }; #endif diff --git a/gfx/2d/UnscaledFontGDI.h b/gfx/2d/UnscaledFontGDI.h index eaaa92e927bf..c6344ef90113 100644 --- a/gfx/2d/UnscaledFontGDI.h +++ b/gfx/2d/UnscaledFontGDI.h @@ -24,6 +24,18 @@ public: const LOGFONT& GetLogFont() const { return mLogFont; } + bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override; + + bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override; + + static already_AddRefed + CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength); + + already_AddRefed + CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) override; + private: LOGFONT mLogFont; }; diff --git a/gfx/2d/UnscaledFontMac.h b/gfx/2d/UnscaledFontMac.h index 27da8185a8ec..bfd7862c6c48 100644 --- a/gfx/2d/UnscaledFontMac.h +++ b/gfx/2d/UnscaledFontMac.h @@ -36,6 +36,18 @@ public: CGFontRef GetFont() const { return mFont; } + bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override; + + already_AddRefed + CreateScaledFont(Float aGlyphSize, + const uint8_t* aInstanceData, + uint32_t aInstanceDataLength) override; + + static CGFontRef + CreateCGFontWithVariations(CGFontRef aFont, + uint32_t aVariationCount, + const ScaledFont::VariationSetting* aVariations); + private: CGFontRef mFont; }; diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index 372ba7e012fa..014554559376 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -98,6 +98,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3'): EXPORTS.mozilla.gfx += [ 'UnscaledFontFreeType.h', ] + SOURCES += [ + 'UnscaledFontFreeType.cpp', + ] if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): SOURCES += [ diff --git a/gfx/layers/wr/WebRenderBridgeChild.cpp b/gfx/layers/wr/WebRenderBridgeChild.cpp index e990155744b1..0d96f1b8b7b6 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.cpp +++ b/gfx/layers/wr/WebRenderBridgeChild.cpp @@ -156,13 +156,11 @@ struct FontFileData { wr::ByteBuffer mFontBuffer; uint32_t mFontIndex; - float mGlyphSize; }; static void WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex, - float aGlyphSize, uint32_t aVariationCount, - const ScaledFont::VariationSetting* aVariations, void* aBaton) + void* aBaton) { FontFileData* data = static_cast(aBaton); @@ -172,7 +170,6 @@ WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex, memcpy(data->mFontBuffer.mData, aData, aLength); data->mFontIndex = aIndex; - data->mGlyphSize = aGlyphSize; } void @@ -228,7 +225,7 @@ WebRenderBridgeChild::GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont) } FontFileData data; - if (!aScaledFont->GetFontFileData(WriteFontFileData, &data) || + if (!unscaled->GetFontFileData(WriteFontFileData, &data) || !data.mFontBuffer.mData) { return key; } diff --git a/gfx/thebes/gfxMacFont.cpp b/gfx/thebes/gfxMacFont.cpp index 67e761d58153..10b08c582b1b 100644 --- a/gfx/thebes/gfxMacFont.cpp +++ b/gfx/thebes/gfxMacFont.cpp @@ -23,142 +23,6 @@ using namespace mozilla; using namespace mozilla::gfx; -// Simple helper class to automatically release a CFObject when it goes out -// of scope. -template -class AutoRelease -{ -public: - explicit AutoRelease(T aObject) - : mObject(aObject) - { - } - - ~AutoRelease() - { - if (mObject) { - CFRelease(mObject); - } - } - - operator T() - { - return mObject; - } - - T forget() - { - T obj = mObject; - mObject = nullptr; - return obj; - } - -private: - T mObject; -}; - -static CFDictionaryRef -CreateVariationDictionaryOrNull(CGFontRef aCGFont, - const nsTArray& aVariations) -{ - // Avoid calling potentially buggy variation APIs on pre-Sierra macOS - // versions (see bug 1331683) - if (!nsCocoaFeatures::OnSierraOrLater()) { - return nullptr; - } - - AutoRelease - ctFont(CTFontCreateWithGraphicsFont(aCGFont, 0, nullptr, nullptr)); - AutoRelease axes(CTFontCopyVariationAxes(ctFont)); - if (!axes) { - return nullptr; - } - - CFIndex axisCount = CFArrayGetCount(axes); - AutoRelease - dict(CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)); - - // Number of variation settings passed in the aVariations parameter. - // This will typically be a very low value, so we just linear-search them. - uint32_t numVars = aVariations.Length(); - bool allDefaultValues = true; - - for (CFIndex i = 0; i < axisCount; ++i) { - // We sanity-check the axis info found in the CTFont, and bail out - // (returning null) if it doesn't have the expected types. - CFTypeRef axisInfo = CFArrayGetValueAtIndex(axes, i); - if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { - return nullptr; - } - CFDictionaryRef axis = static_cast(axisInfo); - - CFTypeRef axisTag = - CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey); - if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) { - return nullptr; - } - int64_t tagLong; - if (!CFNumberGetValue(static_cast(axisTag), - kCFNumberSInt64Type, &tagLong)) { - return nullptr; - } - - CFTypeRef axisName = - CFDictionaryGetValue(axis, kCTFontVariationAxisNameKey); - if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) { - return nullptr; - } - - // Clamp axis values to the supported range. - CFTypeRef min = CFDictionaryGetValue(axis, kCTFontVariationAxisMinimumValueKey); - CFTypeRef max = CFDictionaryGetValue(axis, kCTFontVariationAxisMaximumValueKey); - CFTypeRef def = CFDictionaryGetValue(axis, kCTFontVariationAxisDefaultValueKey); - if (!min || CFGetTypeID(min) != CFNumberGetTypeID() || - !max || CFGetTypeID(max) != CFNumberGetTypeID() || - !def || CFGetTypeID(def) != CFNumberGetTypeID()) { - return nullptr; - } - double minDouble; - double maxDouble; - double defDouble; - if (!CFNumberGetValue(static_cast(min), kCFNumberDoubleType, - &minDouble) || - !CFNumberGetValue(static_cast(max), kCFNumberDoubleType, - &maxDouble) || - !CFNumberGetValue(static_cast(def), kCFNumberDoubleType, - &defDouble)) { - return nullptr; - } - - double value = defDouble; - for (uint32_t j = 0; j < numVars; ++j) { - if (aVariations[j].mTag == tagLong) { - value = std::min(std::max(aVariations[j].mValue, - minDouble), - maxDouble); - if (value != defDouble) { - allDefaultValues = false; - } - break; - } - } - AutoRelease valueNumber(CFNumberCreate(kCFAllocatorDefault, - kCFNumberDoubleType, - &value)); - CFDictionaryAddValue(dict, axisName, valueNumber); - } - - if (allDefaultValues) { - // We didn't actually set any non-default values, so throw away the - // variations dictionary and just use the default rendering. - return nullptr; - } - - return dict.forget(); -} - gfxMacFont::gfxMacFont(const RefPtr& aUnscaledFont, MacOSFontEntry *aFontEntry, const gfxFontStyle *aFontStyle, @@ -177,14 +41,16 @@ gfxMacFont::gfxMacFont(const RefPtr& aUnscaledFont, mIsValid = false; return; } - CFDictionaryRef variations = - CreateVariationDictionaryOrNull(baseFont, aFontStyle->variationSettings); - if (variations) { - mCGFont = ::CGFontCreateCopyWithVariations(baseFont, variations); - ::CFRelease(variations); - } else { - ::CFRetain(baseFont); - mCGFont = baseFont; + MOZ_ASSERT(sizeof(ScaledFont::VariationSetting) == sizeof(gfxFontVariation)); + mCGFont = + UnscaledFontMac::CreateCGFontWithVariations( + baseFont, + aFontStyle->variationSettings.Length(), + reinterpret_cast( + aFontStyle->variationSettings.Elements())); + if (!mCGFont) { + ::CFRetain(baseFont); + mCGFont = baseFont; } } else { mCGFont = aUnscaledFont->GetFont(); diff --git a/layout/printing/PrintTranslator.h b/layout/printing/PrintTranslator.h index 92d8bbed2bcb..96f68b78098e 100644 --- a/layout/printing/PrintTranslator.h +++ b/layout/printing/PrintTranslator.h @@ -27,6 +27,7 @@ using gfx::SourceSurface; using gfx::FilterNode; using gfx::GradientStops; using gfx::ScaledFont; +using gfx::UnscaledFont; using gfx::NativeFontResource; class PrintTranslator final : public Translator @@ -78,6 +79,13 @@ public: return result; } + UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) final + { + UnscaledFont* result = mUnscaledFonts.GetWeak(aRefPtr); + MOZ_ASSERT(result); + return result; + } + NativeFontResource* LookupNativeFontResource(uint64_t aKey) final { NativeFontResource* result = mNativeFontResources.GetWeak(aKey); @@ -115,6 +123,11 @@ public: mScaledFonts.Put(aRefPtr, aScaledFont); } + void AddUnscaledFont(ReferencePtr aRefPtr, UnscaledFont* aUnscaledFont) final + { + mUnscaledFonts.Put(aRefPtr, aUnscaledFont); + } + void AddNativeFontResource(uint64_t aKey, NativeFontResource *aScaledFontResouce) final { @@ -151,6 +164,11 @@ public: mScaledFonts.Remove(aRefPtr); } + void RemoveUnscaledFont(ReferencePtr aRefPtr) final + { + mUnscaledFonts.Remove(aRefPtr); + } + already_AddRefed CreateDrawTarget(ReferencePtr aRefPtr, const gfx::IntSize &aSize, gfx::SurfaceFormat aFormat) final; @@ -169,6 +187,7 @@ private: nsRefPtrHashtable, FilterNode> mFilterNodes; nsRefPtrHashtable, GradientStops> mGradientStops; nsRefPtrHashtable, ScaledFont> mScaledFonts; + nsRefPtrHashtable, UnscaledFont> mUnscaledFonts; nsRefPtrHashtable mNativeFontResources; };