Bug 1355931 - move font serialization from ScaledFont to UnscaledFont. r=jrmuizel

MozReview-Commit-ID: 3d1XMoe2BKj
This commit is contained in:
Lee Salzman 2017-04-14 14:11:00 -04:00
parent a363fb8c8b
commit 28471864af
31 changed files with 763 additions and 639 deletions

View File

@ -63,6 +63,7 @@ namespace mozilla {
namespace gfx { namespace gfx {
class ScaledFont;
class SourceSurface; class SourceSurface;
class DataSourceSurface; class DataSourceSurface;
class DrawTarget; class DrawTarget;
@ -711,6 +712,25 @@ public:
static uint32_t DeletionCounter() { return sDeletionCounter; } 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<ScaledFont>
CreateScaledFont(Float aGlyphSize,
const uint8_t* aInstanceData,
uint32_t aInstanceDataLength)
{
return nullptr;
}
protected: protected:
UnscaledFont() {} UnscaledFont() {}
@ -728,17 +748,6 @@ public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont)
virtual ~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 FontType GetType() const = 0;
virtual Float GetSize() const = 0; virtual Float GetSize() const = 0;
virtual AntialiasMode GetDefaultAAMode(); virtual AntialiasMode GetDefaultAAMode();
@ -761,12 +770,15 @@ public:
*/ */
virtual void GetGlyphDesignMetrics(const uint16_t* aGlyphIndices, uint32_t aNumGlyphs, GlyphMetrics* aGlyphMetrics) = 0; 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 GetFontInstanceData(FontInstanceDataOutput, void *) { return false; }
virtual bool GetFontDescriptor(FontDescriptorOutput, void *) { return false; }
virtual bool CanSerialize() { return false; } virtual bool CanSerialize() { return false; }
void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) { void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
@ -797,20 +809,19 @@ public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResource) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResource)
/** /**
* Creates a ScaledFont using the font corresponding to the index and * Creates a UnscaledFont using the font corresponding to the index.
* the given glyph size.
* *
* @param aIndex index for the font within the resource. * @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 aInstanceData pointer to read-only buffer of any available instance data.
* @param aInstanceDataLength the size of the 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<ScaledFont> virtual already_AddRefed<UnscaledFont>
CreateScaledFont(uint32_t aIndex, Float aGlyphSize, CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) = 0; const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) = 0;
virtual ~NativeFontResource() {}; virtual ~NativeFontResource() {}
}; };
/** This class is designed to allow passing additional glyph rendering /** This class is designed to allow passing additional glyph rendering
@ -1469,23 +1480,18 @@ public:
* *
* @param aData Pointer to the data * @param aData Pointer to the data
* @param aSize Size of the TrueType 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. * @param aType Type of NativeFontResource that should be created.
* @return a NativeFontResource of nullptr if failed. * @return a NativeFontResource of nullptr if failed.
*/ */
static already_AddRefed<NativeFontResource> static already_AddRefed<NativeFontResource>
CreateNativeFontResource(uint8_t *aData, uint32_t aSize, CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType);
uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations,
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. * data retrieved from ScaledFont::GetFontDescriptor.
*/ */
static already_AddRefed<ScaledFont> static already_AddRefed<UnscaledFont>
CreateScaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, Float aSize); CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength);
/** /**
* This creates a scaled font with an associated cairo_scaled_font_t, and * This creates a scaled font with an associated cairo_scaled_font_t, and

View File

@ -388,8 +388,11 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
{ {
EnsurePatternDependenciesStored(aPattern); EnsurePatternDependenciesStored(aPattern);
if (!aFont->GetUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()))) { UserDataKey* userDataKey = reinterpret_cast<UserDataKey*>(mRecorder.get());
RecordedFontData fontData(aFont); if (!aFont->GetUserData(userDataKey)) {
UnscaledFont* unscaledFont = aFont->GetUnscaledFont();
if (!mRecorder->HasStoredObject(unscaledFont)) {
RecordedFontData fontData(unscaledFont);
RecordedFontDetails fontDetails; RecordedFontDetails fontDetails;
if (fontData.GetFontDetails(fontDetails)) { if (fontData.GetFontDetails(fontDetails)) {
// Try to serialise the whole font, just in case this is a web font that // Try to serialise the whole font, just in case this is a web font that
@ -398,22 +401,26 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
mRecorder->RecordEvent(fontData); mRecorder->RecordEvent(fontData);
mRecorder->AddStoredFontData(fontDetails.fontDataKey); mRecorder->AddStoredFontData(fontDetails.fontDataKey);
} }
mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, fontDetails)); mRecorder->RecordEvent(RecordedUnscaledFontCreation(unscaledFont, fontDetails));
} else { } else {
// If that fails, record just the font description and try to load it from // If that fails, record just the font description and try to load it from
// the system on the other side. // the system on the other side.
RecordedFontDescriptor fontDesc(aFont); RecordedFontDescriptor fontDesc(unscaledFont);
if (fontDesc.IsValid()) { if (fontDesc.IsValid()) {
mRecorder->RecordEvent(fontDesc); mRecorder->RecordEvent(fontDesc);
} else { } else {
gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise ScaledFont"; gfxWarning() << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont";
} }
} }
mRecorder->AddStoredObject(unscaledFont);
}
mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, unscaledFont));
RecordingFontUserData *userData = new RecordingFontUserData; RecordingFontUserData *userData = new RecordingFontUserData;
userData->refPtr = aFont; userData->refPtr = aFont;
userData->recorder = mRecorder; userData->recorder = mRecorder;
aFont->AddUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()), userData, aFont->AddUserData(userDataKey, userData, &RecordingFontUserDataDestroyFunc);
&RecordingFontUserDataDestroyFunc);
} }
mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs)); mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));

View File

@ -24,6 +24,7 @@
#if defined(WIN32) #if defined(WIN32)
#include "ScaledFontWin.h" #include "ScaledFontWin.h"
#include "NativeFontResourceGDI.h" #include "NativeFontResourceGDI.h"
#include "UnscaledFontGDI.h"
#endif #endif
#ifdef XP_DARWIN #ifdef XP_DARWIN
@ -34,6 +35,7 @@
#ifdef MOZ_WIDGET_GTK #ifdef MOZ_WIDGET_GTK
#include "ScaledFontFontconfig.h" #include "ScaledFontFontconfig.h"
#include "NativeFontResourceFontconfig.h" #include "NativeFontResourceFontconfig.h"
#include "UnscaledFontFreeType.h"
#endif #endif
#ifdef WIN32 #ifdef WIN32
@ -505,10 +507,7 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont,
} }
already_AddRefed<NativeFontResource> already_AddRefed<NativeFontResource>
Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType)
uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations,
FontType aType)
{ {
switch (aType) { switch (aType) {
#ifdef WIN32 #ifdef WIN32
@ -528,12 +527,10 @@ Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize,
return NativeFontResourceDWrite::Create(aData, aSize, return NativeFontResourceDWrite::Create(aData, aSize,
/* aNeedsCairo = */ true); /* aNeedsCairo = */ true);
} else { } else {
return NativeFontResourceGDI::Create(aData, aSize, return NativeFontResourceGDI::Create(aData, aSize);
/* aNeedsCairo = */ true);
} }
#elif defined(XP_DARWIN) #elif defined(XP_DARWIN)
return NativeFontResourceMac::Create(aData, aSize, return NativeFontResourceMac::Create(aData, aSize);
aVariationCount, aVariations);
#elif defined(MOZ_WIDGET_GTK) #elif defined(MOZ_WIDGET_GTK)
return NativeFontResourceFontconfig::Create(aData, aSize); return NativeFontResourceFontconfig::Create(aData, aSize);
#else #else
@ -547,20 +544,20 @@ Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize,
} }
} }
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
Factory::CreateScaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, Float aSize) Factory::CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength)
{ {
switch (aType) { switch (aType) {
#ifdef WIN32 #ifdef WIN32
case FontType::GDI: case FontType::GDI:
return ScaledFontWin::CreateFromFontDescriptor(aData, aDataLength, aSize); return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength);
#endif #endif
#ifdef MOZ_WIDGET_GTK #ifdef MOZ_WIDGET_GTK
case FontType::FONTCONFIG: case FontType::FONTCONFIG:
return ScaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength, aSize); return UnscaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength);
#endif #endif
default: default:
gfxWarning() << "Invalid type specified for ScaledFont font descriptor"; gfxWarning() << "Invalid type specified for UnscaledFont font descriptor";
return nullptr; return nullptr;
} }
} }

View File

@ -131,6 +131,7 @@ enum class LogReason : int {
ProcessingError, ProcessingError,
InvalidDrawTarget, InvalidDrawTarget,
NativeFontResourceNotFound, NativeFontResourceNotFound,
UnscaledFontNotFound,
// End // End
MustBeLessThanThis = 101, MustBeLessThanThis = 101,
}; };

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "NativeFontResourceDWrite.h" #include "NativeFontResourceDWrite.h"
#include "UnscaledFontDWrite.h"
#include <unordered_map> #include <unordered_map>
@ -258,9 +259,10 @@ NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength,
return fontResource.forget(); return fontResource.forget();
} }
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, NativeFontResourceDWrite::CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) const uint8_t* aInstanceData,
uint32_t aInstanceDataLength)
{ {
if (aIndex >= mNumberOfFaces) { if (aIndex >= mNumberOfFaces) {
gfxWarning() << "Font face index is too high for font resource."; gfxWarning() << "Font face index is too high for font resource.";
@ -275,13 +277,12 @@ NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, Float aGlyphSize,
return nullptr; return nullptr;
} }
RefPtr<ScaledFontBase> scaledFont = new ScaledFontDWrite(fontFace, nullptr, aGlyphSize); RefPtr<UnscaledFont> unscaledFont =
if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) { new UnscaledFontDWrite(fontFace,
gfxWarning() << "Unable to create cairo scaled font DWrite font."; DWRITE_FONT_SIMULATIONS_NONE,
return nullptr; mNeedsCairo);
}
return scaledFont.forget(); return unscaledFont.forget();
} }
} // gfx } // gfx

View File

@ -31,9 +31,10 @@ public:
static already_AddRefed<NativeFontResourceDWrite> static already_AddRefed<NativeFontResourceDWrite>
Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo); Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo);
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
CreateScaledFont(uint32_t aIndex, Float aGlyphSize, CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) final;
private: private:
NativeFontResourceDWrite(IDWriteFactory *aFactory, NativeFontResourceDWrite(IDWriteFactory *aFactory,

View File

@ -6,6 +6,7 @@
#include "NativeFontResourceFontconfig.h" #include "NativeFontResourceFontconfig.h"
#include "ScaledFontFontconfig.h" #include "ScaledFontFontconfig.h"
#include "UnscaledFontFreeType.h"
#include "Logging.h" #include "Logging.h"
namespace mozilla { namespace mozilla {
@ -48,17 +49,12 @@ NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength)
return resource.forget(); return resource.forget();
} }
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
NativeFontResourceFontconfig::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, NativeFontResourceFontconfig::CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) const uint8_t* aInstanceData, uint32_t aInstanceDataLength)
{ {
if (aInstanceDataLength < sizeof(ScaledFontFontconfig::InstanceData)) { RefPtr<UnscaledFont> unscaledFont = new UnscaledFontFontconfig(mFace);
gfxWarning() << "Fontconfig scaled font instance data is truncated."; return unscaledFont.forget();
return nullptr;
}
return ScaledFontFontconfig::CreateFromInstanceData(
*reinterpret_cast<const ScaledFontFontconfig::InstanceData*>(aInstanceData),
mFace, nullptr, 0, aGlyphSize);
} }
} // gfx } // gfx

View File

@ -23,8 +23,8 @@ public:
static already_AddRefed<NativeFontResourceFontconfig> static already_AddRefed<NativeFontResourceFontconfig>
Create(uint8_t *aFontData, uint32_t aDataLength); Create(uint8_t *aFontData, uint32_t aDataLength);
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
CreateScaledFont(uint32_t aIndex, Float aGlyphSize, CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final;
~NativeFontResourceFontconfig(); ~NativeFontResourceFontconfig();

View File

@ -9,14 +9,14 @@
#include "Logging.h" #include "Logging.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "ScaledFontWin.h" #include "ScaledFontWin.h"
#include "UnscaledFontGDI.h"
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
/* static */ /* static */
already_AddRefed<NativeFontResourceGDI> already_AddRefed<NativeFontResourceGDI>
NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength, NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength)
bool aNeedsCairo)
{ {
DWORD numberOfFontsAdded; DWORD numberOfFontsAdded;
HANDLE fontResourceHandle = ::AddFontMemResourceEx(aFontData, aDataLength, HANDLE fontResourceHandle = ::AddFontMemResourceEx(aFontData, aDataLength,
@ -27,7 +27,7 @@ NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength,
} }
RefPtr<NativeFontResourceGDI> fontResouce = RefPtr<NativeFontResourceGDI> fontResouce =
new NativeFontResourceGDI(fontResourceHandle, aNeedsCairo); new NativeFontResourceGDI(fontResourceHandle);
return fontResouce.forget(); return fontResouce.forget();
} }
@ -37,26 +37,19 @@ NativeFontResourceGDI::~NativeFontResourceGDI()
::RemoveFontMemResourceEx(mFontResourceHandle); ::RemoveFontMemResourceEx(mFontResourceHandle);
} }
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
NativeFontResourceGDI::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, NativeFontResourceGDI::CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) const uint8_t* aInstanceData,
uint32_t aInstanceDataLength)
{ {
if (aInstanceDataLength < sizeof(LOGFONT)) { if (aInstanceDataLength < sizeof(LOGFONT)) {
gfxWarning() << "GDI scaled font instance data is truncated."; gfxWarning() << "GDI unscaled font instance data is truncated.";
return nullptr; return nullptr;
} }
const LOGFONT* logFont = reinterpret_cast<const LOGFONT*>(aInstanceData); const LOGFONT* logFont = reinterpret_cast<const LOGFONT*>(aInstanceData);
RefPtr<UnscaledFont> unscaledFont = new UnscaledFontGDI(*logFont);
// Constructor for ScaledFontWin dereferences and copies the LOGFONT, so we return unscaledFont.forget();
// are safe to pass this reference.
RefPtr<ScaledFontBase> scaledFont = new ScaledFontWin(logFont, nullptr, aGlyphSize);
if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) {
gfxWarning() << "Unable to create cairo scaled font GDI font.";
return nullptr;
}
return scaledFont.forget();
} }
} // gfx } // gfx

View File

@ -26,27 +26,24 @@ public:
* *
* @param aFontData the SFNT data. * @param aFontData the SFNT data.
* @param aDataLength length of data. * @param aDataLength length of data.
* @param aNeedsCairo whether the ScaledFont created need a cairo scaled font
* @return Referenced NativeFontResourceGDI or nullptr if invalid. * @return Referenced NativeFontResourceGDI or nullptr if invalid.
*/ */
static already_AddRefed<NativeFontResourceGDI> static already_AddRefed<NativeFontResourceGDI>
Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo); Create(uint8_t *aFontData, uint32_t aDataLength);
~NativeFontResourceGDI(); ~NativeFontResourceGDI();
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
CreateScaledFont(uint32_t aIndex, Float aGlyphSize, CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) final;
private: private:
NativeFontResourceGDI(HANDLE aFontResourceHandle, explicit NativeFontResourceGDI(HANDLE aFontResourceHandle)
bool aNeedsCairo)
: mFontResourceHandle(aFontResourceHandle) : mFontResourceHandle(aFontResourceHandle)
, mNeedsCairo(aNeedsCairo)
{} {}
HANDLE mFontResourceHandle; HANDLE mFontResourceHandle;
bool mNeedsCairo;
}; };
} // gfx } // gfx

View File

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "NativeFontResourceMac.h" #include "NativeFontResourceMac.h"
#include "UnscaledFontMac.h"
#include "Types.h" #include "Types.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
@ -15,152 +16,12 @@
#include "nsCocoaFeatures.h" #include "nsCocoaFeatures.h"
// Simple helper class to automatically release a CFObject when it goes out
// of scope.
template<class T>
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<CTFontRef>
ctFont(CTFontCreateWithGraphicsFont(aCGFont, 0, nullptr, nullptr));
AutoRelease<CFArrayRef> axes(CTFontCopyVariationAxes(ctFont));
if (!axes) {
return nullptr;
}
CFIndex axisCount = CFArrayGetCount(axes);
AutoRelease<CFMutableDictionaryRef>
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<CFDictionaryRef>(axisInfo);
CFTypeRef axisTag =
CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey);
if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
return nullptr;
}
int64_t tagLong;
if (!CFNumberGetValue(static_cast<CFNumberRef>(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<CFNumberRef>(min), kCFNumberDoubleType,
&minDouble) ||
!CFNumberGetValue(static_cast<CFNumberRef>(max), kCFNumberDoubleType,
&maxDouble) ||
!CFNumberGetValue(static_cast<CFNumberRef>(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<double>(aVariations[j].mValue,
minDouble),
maxDouble);
if (value != defDouble) {
allDefaultValues = false;
}
break;
}
}
AutoRelease<CFNumberRef> 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 mozilla {
namespace gfx { namespace gfx {
/* static */ /* static */
already_AddRefed<NativeFontResourceMac> already_AddRefed<NativeFontResourceMac>
NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength, NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength)
uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations)
{ {
// copy font data // copy font data
CFDataRef data = CFDataCreate(kCFAllocatorDefault, aFontData, aDataLength); CFDataRef data = CFDataCreate(kCFAllocatorDefault, aFontData, aDataLength);
@ -184,20 +45,6 @@ NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength,
return nullptr; return nullptr;
} }
if (aVariationCount > 0) {
MOZ_ASSERT(aVariations);
AutoRelease<CFDictionaryRef>
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 // passes ownership of fontRef to the NativeFontResourceMac instance
RefPtr<NativeFontResourceMac> fontResource = RefPtr<NativeFontResourceMac> fontResource =
new NativeFontResourceMac(fontRef); new NativeFontResourceMac(fontRef);
@ -205,18 +52,14 @@ NativeFontResourceMac::Create(uint8_t *aFontData, uint32_t aDataLength,
return fontResource.forget(); return fontResource.forget();
} }
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
NativeFontResourceMac::CreateScaledFont(uint32_t aIndex, Float aGlyphSize, NativeFontResourceMac::CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) const uint8_t* aInstanceData,
uint32_t aInstanceDataLength)
{ {
RefPtr<ScaledFontBase> scaledFont = new ScaledFontMac(mFontRef, nullptr, aGlyphSize); RefPtr<UnscaledFont> unscaledFont = new UnscaledFontMac(mFontRef);
if (!scaledFont->PopulateCairoScaledFont()) { return unscaledFont.forget();
gfxWarning() << "Unable to create cairo scaled Mac font.";
return nullptr;
}
return scaledFont.forget();
} }
} // gfx } // gfx

View File

@ -20,13 +20,12 @@ public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceMac) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceMac)
static already_AddRefed<NativeFontResourceMac> static already_AddRefed<NativeFontResourceMac>
Create(uint8_t *aFontData, uint32_t aDataLength, Create(uint8_t *aFontData, uint32_t aDataLength);
uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations);
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
CreateScaledFont(uint32_t aIndex, Float aGlyphSize, CreateUnscaledFont(uint32_t aIndex,
const uint8_t* aInstanceData, uint32_t aInstanceDataLength) final; const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) final;
~NativeFontResourceMac() ~NativeFontResourceMac()
{ {

View File

@ -84,6 +84,8 @@ RecordedEvent::LoadEventFromStream(std::istream &aStream, EventType aType)
LOAD_EVENT_TYPE(FONTDESC, RecordedFontDescriptor); LOAD_EVENT_TYPE(FONTDESC, RecordedFontDescriptor);
LOAD_EVENT_TYPE(PUSHLAYER, RecordedPushLayer); LOAD_EVENT_TYPE(PUSHLAYER, RecordedPushLayer);
LOAD_EVENT_TYPE(POPLAYER, RecordedPopLayer); LOAD_EVENT_TYPE(POPLAYER, RecordedPopLayer);
LOAD_EVENT_TYPE(UNSCALEDFONTCREATION, RecordedUnscaledFontCreation);
LOAD_EVENT_TYPE(UNSCALEDFONTDESTRUCTION, RecordedUnscaledFontDestruction);
default: default:
return nullptr; return nullptr;
} }
@ -167,6 +169,10 @@ RecordedEvent::GetEventName(EventType aType)
return "PushLayer"; return "PushLayer";
case POPLAYER: case POPLAYER:
return "PopLayer"; return "PopLayer";
case UNSCALEDFONTCREATION:
return "UnscaledFontCreation";
case UNSCALEDFONTDESTRUCTION:
return "UnscaledFontDestruction";
default: default:
return "Unknown"; return "Unknown";
} }
@ -1522,7 +1528,6 @@ RecordedSnapshot::OutputSimpleEventInfo(stringstream &aStringStream) const
RecordedFontData::~RecordedFontData() RecordedFontData::~RecordedFontData()
{ {
delete[] mData; delete[] mData;
delete[] mVariations;
} }
bool bool
@ -1530,7 +1535,6 @@ RecordedFontData::PlayEvent(Translator *aTranslator) const
{ {
RefPtr<NativeFontResource> fontResource = RefPtr<NativeFontResource> fontResource =
Factory::CreateNativeFontResource(mData, mFontDetails.size, Factory::CreateNativeFontResource(mData, mFontDetails.size,
mFontDetails.variationCount, mVariations,
aTranslator->GetDesiredFontType()); aTranslator->GetDesiredFontType());
if (!fontResource) { if (!fontResource) {
return false; return false;
@ -1548,8 +1552,6 @@ RecordedFontData::RecordToStream(std::ostream &aStream) const
WriteElement(aStream, mFontDetails.fontDataKey); WriteElement(aStream, mFontDetails.fontDataKey);
WriteElement(aStream, mFontDetails.size); WriteElement(aStream, mFontDetails.size);
aStream.write((const char*)mData, mFontDetails.size); aStream.write((const char*)mData, mFontDetails.size);
WriteElement(aStream, mFontDetails.variationCount);
aStream.write((const char*)mVariations, mFontDetails.variationCount * sizeof(ScaledFont::VariationSetting));
} }
void void
@ -1559,23 +1561,14 @@ RecordedFontData::OutputSimpleEventInfo(stringstream &aStringStream) const
} }
void void
RecordedFontData::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, RecordedFontData::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex)
Float aGlyphSize, uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations)
{ {
mData = new uint8_t[aSize]; mData = new uint8_t[aSize];
memcpy(mData, aData, aSize); memcpy(mData, aData, aSize);
uint32_t varDataSize = aVariationCount * sizeof(ScaledFont::VariationSetting);
mFontDetails.fontDataKey = mFontDetails.fontDataKey =
SFNTData::GetUniqueKey(aData, aSize, varDataSize, aVariations); SFNTData::GetUniqueKey(aData, aSize, 0, nullptr);
mFontDetails.size = aSize; mFontDetails.size = aSize;
mFontDetails.index = aIndex; mFontDetails.index = aIndex;
mFontDetails.glyphSize = aGlyphSize;
mFontDetails.variationCount = aVariationCount;
if (aVariationCount > 0) {
mVariations = new ScaledFont::VariationSetting[aVariationCount];
memcpy(mVariations, aVariations, varDataSize);
}
} }
bool bool
@ -1587,28 +1580,18 @@ RecordedFontData::GetFontDetails(RecordedFontDetails& fontDetails)
fontDetails.fontDataKey = mFontDetails.fontDataKey; fontDetails.fontDataKey = mFontDetails.fontDataKey;
fontDetails.size = mFontDetails.size; fontDetails.size = mFontDetails.size;
fontDetails.glyphSize = mFontDetails.glyphSize;
fontDetails.index = mFontDetails.index; fontDetails.index = mFontDetails.index;
fontDetails.variationCount = mFontDetails.variationCount;
return true; return true;
} }
RecordedFontData::RecordedFontData(istream &aStream) RecordedFontData::RecordedFontData(istream &aStream)
: RecordedEvent(FONTDATA) : RecordedEvent(FONTDATA)
, mData(nullptr) , mData(nullptr)
, mVariations(nullptr)
{ {
ReadElement(aStream, mFontDetails.fontDataKey); ReadElement(aStream, mFontDetails.fontDataKey);
ReadElement(aStream, mFontDetails.size); ReadElement(aStream, mFontDetails.size);
mData = new uint8_t[mFontDetails.size]; mData = new uint8_t[mFontDetails.size];
aStream.read((char*)mData, 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() RecordedFontDescriptor::~RecordedFontDescriptor()
@ -1618,15 +1601,15 @@ RecordedFontDescriptor::~RecordedFontDescriptor()
bool bool
RecordedFontDescriptor::PlayEvent(Translator *aTranslator) const RecordedFontDescriptor::PlayEvent(Translator *aTranslator) const
{ {
RefPtr<ScaledFont> font = RefPtr<UnscaledFont> font =
Factory::CreateScaledFontFromFontDescriptor(mType, mData.data(), mData.size(), mFontSize); Factory::CreateUnscaledFontFromFontDescriptor(mType, mData.data(), mData.size());
if (!font) { if (!font) {
gfxDevCrash(LogReason::InvalidFont) << 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; return false;
} }
aTranslator->AddScaledFont(mRefPtr, font); aTranslator->AddUnscaledFont(mRefPtr, font);
return true; return true;
} }
@ -1635,7 +1618,6 @@ RecordedFontDescriptor::RecordToStream(std::ostream &aStream) const
{ {
MOZ_ASSERT(mHasDesc); MOZ_ASSERT(mHasDesc);
WriteElement(aStream, mType); WriteElement(aStream, mType);
WriteElement(aStream, mFontSize);
WriteElement(aStream, mRefPtr); WriteElement(aStream, mRefPtr);
WriteElement(aStream, (size_t)mData.size()); WriteElement(aStream, (size_t)mData.size());
aStream.write((char*)mData.data(), mData.size()); aStream.write((char*)mData.data(), mData.size());
@ -1648,17 +1630,15 @@ RecordedFontDescriptor::OutputSimpleEventInfo(stringstream &aStringStream) const
} }
void 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); mData.assign(aData, aData + aSize);
mFontSize = aFontSize;
} }
RecordedFontDescriptor::RecordedFontDescriptor(istream &aStream) RecordedFontDescriptor::RecordedFontDescriptor(istream &aStream)
: RecordedEvent(FONTDATA) : RecordedEvent(FONTDESC)
{ {
ReadElement(aStream, mType); ReadElement(aStream, mType);
ReadElement(aStream, mFontSize);
ReadElement(aStream, mRefPtr); ReadElement(aStream, mRefPtr);
size_t size; size_t size;
@ -1668,7 +1648,7 @@ RecordedFontDescriptor::RecordedFontDescriptor(istream &aStream)
} }
bool bool
RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const RecordedUnscaledFontCreation::PlayEvent(Translator *aTranslator) const
{ {
NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey); NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey);
if (!fontResource) { if (!fontResource) {
@ -1677,8 +1657,84 @@ RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const
return false; return false;
} }
RefPtr<UnscaledFont> 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> scaledFont = RefPtr<ScaledFont> scaledFont =
fontResource->CreateScaledFont(mIndex, mGlyphSize, mInstanceData.data(), mInstanceData.size()); unscaledFont->CreateScaledFont(mGlyphSize, mInstanceData.data(), mInstanceData.size());
aTranslator->AddScaledFont(mRefPtr, scaledFont); aTranslator->AddScaledFont(mRefPtr, scaledFont);
return true; return true;
} }
@ -1687,8 +1743,7 @@ void
RecordedScaledFontCreation::RecordToStream(std::ostream &aStream) const RecordedScaledFontCreation::RecordToStream(std::ostream &aStream) const
{ {
WriteElement(aStream, mRefPtr); WriteElement(aStream, mRefPtr);
WriteElement(aStream, mFontDataKey); WriteElement(aStream, mUnscaledFont);
WriteElement(aStream, mIndex);
WriteElement(aStream, mGlyphSize); WriteElement(aStream, mGlyphSize);
WriteElement(aStream, (size_t)mInstanceData.size()); WriteElement(aStream, (size_t)mInstanceData.size());
aStream.write((char*)mInstanceData.data(), mInstanceData.size()); aStream.write((char*)mInstanceData.data(), mInstanceData.size());
@ -1710,8 +1765,7 @@ RecordedScaledFontCreation::RecordedScaledFontCreation(istream &aStream)
: RecordedEvent(SCALEDFONTCREATION) : RecordedEvent(SCALEDFONTCREATION)
{ {
ReadElement(aStream, mRefPtr); ReadElement(aStream, mRefPtr);
ReadElement(aStream, mFontDataKey); ReadElement(aStream, mUnscaledFont);
ReadElement(aStream, mIndex);
ReadElement(aStream, mGlyphSize); ReadElement(aStream, mGlyphSize);
size_t size; size_t size;

View File

@ -24,7 +24,7 @@ const uint32_t kMagicInt = 0xc001feed;
// loss of backwards compatibility. Old streams will not work in a player // 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 a newer major revision. And new streams will not work in a player
// using an older major revision. // 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 // A change in minor revision means additions of new events. New streams will
// not play in older players. // not play in older players.
const uint16_t kMinorRevision = 0; const uint16_t kMinorRevision = 0;
@ -67,8 +67,6 @@ struct RecordedFontDetails
uint64_t fontDataKey; uint64_t fontDataKey;
uint32_t size; uint32_t size;
uint32_t index; uint32_t index;
uint32_t variationCount;
Float glyphSize;
}; };
// Used by the Azure drawing debugger (player2d) // Used by the Azure drawing debugger (player2d)
@ -90,6 +88,7 @@ public:
virtual FilterNode *LookupFilterNode(ReferencePtr aRefPtr) = 0; virtual FilterNode *LookupFilterNode(ReferencePtr aRefPtr) = 0;
virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0; virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0;
virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0; virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0;
virtual UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) = 0;
virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0; virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0;
virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0; virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0;
virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0; virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0;
@ -103,6 +102,8 @@ public:
virtual void RemoveGradientStops(ReferencePtr aRefPtr) = 0; virtual void RemoveGradientStops(ReferencePtr aRefPtr) = 0;
virtual void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) = 0; virtual void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) = 0;
virtual void RemoveScaledFont(ReferencePtr aRefPtr) = 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, virtual void AddNativeFontResource(uint64_t aKey,
NativeFontResource *aNativeFontResource) = 0; NativeFontResource *aNativeFontResource) = 0;
@ -197,6 +198,8 @@ public:
FONTDESC, FONTDESC,
PUSHLAYER, PUSHLAYER,
POPLAYER, POPLAYER,
UNSCALEDFONTCREATION,
UNSCALEDFONTDESTRUCTION,
}; };
static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1; static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1;
@ -1015,24 +1018,22 @@ class RecordedFontData : public RecordedEvent {
public: public:
static void FontDataProc(const uint8_t *aData, uint32_t aSize, static void FontDataProc(const uint8_t *aData, uint32_t aSize,
uint32_t aIndex, Float aGlyphSize, uint32_t aIndex, void* aBaton)
uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations,
void* aBaton)
{ {
auto recordedFontData = static_cast<RecordedFontData*>(aBaton); auto recordedFontData = static_cast<RecordedFontData*>(aBaton);
recordedFontData->SetFontData(aData, aSize, aIndex, aGlyphSize, recordedFontData->SetFontData(aData, aSize, aIndex);
aVariationCount, aVariations);
} }
explicit RecordedFontData(ScaledFont *aScaledFont) explicit RecordedFontData(UnscaledFont *aUnscaledFont)
: RecordedEvent(FONTDATA), mData(nullptr), mVariations(nullptr) : RecordedEvent(FONTDATA), mData(nullptr)
{ {
mGetFontFileDataSucceeded = aScaledFont->GetFontFileData(&FontDataProc, this); mGetFontFileDataSucceeded = aUnscaledFont->GetFontFileData(&FontDataProc, this);
} }
~RecordedFontData(); ~RecordedFontData();
bool IsValid() const { return mGetFontFileDataSucceeded; }
virtual bool PlayEvent(Translator *aTranslator) const; virtual bool PlayEvent(Translator *aTranslator) const;
virtual void RecordToStream(std::ostream &aStream) const; virtual void RecordToStream(std::ostream &aStream) const;
@ -1041,9 +1042,7 @@ public:
virtual std::string GetName() const { return "Font Data"; } virtual std::string GetName() const { return "Font Data"; }
virtual ReferencePtr GetObjectRef() const { return nullptr; }; virtual ReferencePtr GetObjectRef() const { return nullptr; };
void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex);
Float aGlyphSize, uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations);
bool GetFontDetails(RecordedFontDetails& fontDetails); bool GetFontDetails(RecordedFontDetails& fontDetails);
@ -1051,7 +1050,6 @@ private:
friend class RecordedEvent; friend class RecordedEvent;
uint8_t* mData; uint8_t* mData;
ScaledFont::VariationSetting* mVariations;
RecordedFontDetails mFontDetails; RecordedFontDetails mFontDetails;
bool mGetFontFileDataSucceeded; bool mGetFontFileDataSucceeded;
@ -1063,18 +1061,18 @@ class RecordedFontDescriptor : public RecordedEvent {
public: public:
static void FontDescCb(const uint8_t* aData, uint32_t aSize, static void FontDescCb(const uint8_t* aData, uint32_t aSize,
Float aFontSize, void* aBaton) void* aBaton)
{ {
auto recordedFontDesc = static_cast<RecordedFontDescriptor*>(aBaton); auto recordedFontDesc = static_cast<RecordedFontDescriptor*>(aBaton);
recordedFontDesc->SetFontDescriptor(aData, aSize, aFontSize); recordedFontDesc->SetFontDescriptor(aData, aSize);
} }
explicit RecordedFontDescriptor(ScaledFont* aScaledFont) explicit RecordedFontDescriptor(UnscaledFont* aUnscaledFont)
: RecordedEvent(FONTDESC) : RecordedEvent(FONTDESC)
, mType(aScaledFont->GetType()) , mType(aUnscaledFont->GetType())
, mRefPtr(aScaledFont) , mRefPtr(aUnscaledFont)
{ {
mHasDesc = aScaledFont->GetFontDescriptor(FontDescCb, this); mHasDesc = aUnscaledFont->GetFontDescriptor(FontDescCb, this);
} }
~RecordedFontDescriptor(); ~RecordedFontDescriptor();
@ -1092,18 +1090,77 @@ public:
private: private:
friend class RecordedEvent; 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; bool mHasDesc;
FontType mType; FontType mType;
Float mFontSize;
std::vector<uint8_t> mData; std::vector<uint8_t> mData;
ReferencePtr mRefPtr; ReferencePtr mRefPtr;
MOZ_IMPLICIT RecordedFontDescriptor(std::istream &aStream); 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<RecordedUnscaledFontCreation*>(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<uint8_t> 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 { class RecordedScaledFontCreation : public RecordedEvent {
public: public:
@ -1114,12 +1171,11 @@ public:
} }
RecordedScaledFontCreation(ScaledFont* aScaledFont, RecordedScaledFontCreation(ScaledFont* aScaledFont,
RecordedFontDetails aFontDetails) UnscaledFont* aUnscaledFont)
: RecordedEvent(SCALEDFONTCREATION) : RecordedEvent(SCALEDFONTCREATION)
, mRefPtr(aScaledFont) , mRefPtr(aScaledFont)
, mFontDataKey(aFontDetails.fontDataKey) , mUnscaledFont(aUnscaledFont)
, mGlyphSize(aFontDetails.glyphSize) , mGlyphSize(aScaledFont->GetSize())
, mIndex(aFontDetails.index)
{ {
aScaledFont->GetFontInstanceData(FontInstanceDataProc, this); aScaledFont->GetFontInstanceData(FontInstanceDataProc, this);
} }
@ -1138,9 +1194,8 @@ private:
friend class RecordedEvent; friend class RecordedEvent;
ReferencePtr mRefPtr; ReferencePtr mRefPtr;
uint64_t mFontDataKey; ReferencePtr mUnscaledFont;
Float mGlyphSize; Float mGlyphSize;
uint32_t mIndex;
std::vector<uint8_t> mInstanceData; std::vector<uint8_t> mInstanceData;
MOZ_IMPLICIT RecordedScaledFontCreation(std::istream &aStream); MOZ_IMPLICIT RecordedScaledFontCreation(std::istream &aStream);

View File

@ -5,6 +5,7 @@
#include "DrawTargetD2D1.h" #include "DrawTargetD2D1.h"
#include "ScaledFontDWrite.h" #include "ScaledFontDWrite.h"
#include "UnscaledFontDWrite.h"
#include "PathD2D.h" #include "PathD2D.h"
#include "gfxFont.h" #include "gfxFont.h"
@ -221,7 +222,7 @@ ScaledFontDWrite::CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink
} }
bool bool
ScaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) UnscaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
{ {
UINT32 fileCount = 0; UINT32 fileCount = 0;
mFontFace->GetFiles(&fileCount, nullptr); mFontFace->GetFiles(&fileCount, nullptr);
@ -264,14 +265,27 @@ ScaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton
void *context; void *context;
stream->ReadFileFragment(&fragmentStart, 0, fileSize, &context); stream->ReadFileFragment(&fragmentStart, 0, fileSize, &context);
aDataCallback((uint8_t*)fragmentStart, fileSize, mFontFace->GetIndex(), mSize, aDataCallback((uint8_t*)fragmentStart, fileSize, mFontFace->GetIndex(), aBaton);
0, nullptr, aBaton);
stream->ReleaseFileFragment(context); stream->ReleaseFileFragment(context);
return true; return true;
} }
already_AddRefed<ScaledFont>
UnscaledFontDWrite::CreateScaledFont(Float aGlyphSize,
const uint8_t* aInstanceData,
uint32_t aInstanceDataLength)
{
RefPtr<ScaledFontBase> 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 AntialiasMode
ScaledFontDWrite::GetDefaultAAMode() ScaledFontDWrite::GetDefaultAAMode()
{ {

View File

@ -18,7 +18,7 @@ namespace gfx {
class ScaledFontDWrite final : public ScaledFontBase class ScaledFontDWrite final : public ScaledFontBase
{ {
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDwrite) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDWrite, override)
ScaledFontDWrite(IDWriteFontFace *aFont, ScaledFontDWrite(IDWriteFontFace *aFont,
const RefPtr<UnscaledFont>& aUnscaledFont, const RefPtr<UnscaledFont>& aUnscaledFont,
Float aSize) Float aSize)
@ -35,26 +35,24 @@ public:
bool aForceGDIMode, bool aForceGDIMode,
const gfxFontStyle* aStyle); const gfxFontStyle* aStyle);
virtual FontType GetType() const { return FontType::DWRITE; } FontType GetType() const override { return FontType::DWRITE; }
virtual already_AddRefed<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); already_AddRefed<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) override;
virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, const Matrix *aTransformHint); void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder, const Matrix *aTransformHint) override;
void CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink *aSink); 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; } AntialiasMode GetDefaultAAMode() override;
virtual AntialiasMode GetDefaultAAMode() override;
bool UseEmbeddedBitmaps() { return mUseEmbeddedBitmap; } bool UseEmbeddedBitmaps() { return mUseEmbeddedBitmap; }
bool ForceGDIMode() { return mForceGDIMode; } bool ForceGDIMode() { return mForceGDIMode; }
#ifdef USE_SKIA #ifdef USE_SKIA
virtual SkTypeface* GetSkTypeface(); SkTypeface* GetSkTypeface() override;
SkFontStyle mStyle; SkFontStyle mStyle;
#endif #endif
@ -71,13 +69,13 @@ protected:
class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions
{ {
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsDWrite) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsDWrite, override)
explicit GlyphRenderingOptionsDWrite(IDWriteRenderingParams *aParams) explicit GlyphRenderingOptionsDWrite(IDWriteRenderingParams *aParams)
: mParams(aParams) : mParams(aParams)
{ {
} }
virtual FontType GetType() const { return FontType::DWRITE; } FontType GetType() const override { return FontType::DWRITE; }
private: private:
friend class DrawTargetD2D; friend class DrawTargetD2D;

View File

@ -4,14 +4,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScaledFontFontconfig.h" #include "ScaledFontFontconfig.h"
#include "UnscaledFontFreeType.h"
#include "Logging.h" #include "Logging.h"
#ifdef USE_SKIA #ifdef USE_SKIA
#include "skia/include/ports/SkTypeface_cairo.h" #include "skia/include/ports/SkTypeface_cairo.h"
#endif #endif
#include FT_TRUETYPE_TABLES_H
#include <fontconfig/fcfreetype.h> #include <fontconfig/fcfreetype.h>
namespace mozilla { namespace mozilla {
@ -48,27 +47,6 @@ SkTypeface* ScaledFontFontconfig::GetSkTypeface()
} }
#endif #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) ScaledFontFontconfig::InstanceData::InstanceData(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern)
: mFlags(0) : mFlags(0)
, mHintStyle(FC_HINT_NONE) , mHintStyle(FC_HINT_NONE)
@ -253,52 +231,35 @@ ScaledFontFontconfig::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBat
return true; return true;
} }
bool already_AddRefed<ScaledFont>
ScaledFontFontconfig::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) 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 if (aInstanceDataLength < sizeof(ScaledFontFontconfig::InstanceData)) {
// font to load. If so, record these as a font descriptor along with any instance gfxWarning() << "Fontconfig scaled font instance data is truncated.";
// data required to rebuild a scaled font from it. return nullptr;
FcChar8* pathname = nullptr;
if (FcPatternGetString(mPattern, FC_FILE, 0, &pathname) != FcResultMatch) {
return false;
} }
int index = 0; const ScaledFontFontconfig::InstanceData *instanceData =
FcPatternGetInteger(mPattern, FC_INDEX, 0, &index); reinterpret_cast<const ScaledFontFontconfig::InstanceData*>(aInstanceData);
if (index < 0) { return ScaledFontFontconfig::CreateFromInstanceData(*instanceData, this, aGlyphSize);
return false;
}
size_t pathLength = strlen(reinterpret_cast<char*>(pathname)) + 1;
size_t dataLength = sizeof(FontDescriptor) + pathLength;
uint8_t* data = new uint8_t[dataLength];
FontDescriptor* desc = reinterpret_cast<FontDescriptor*>(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;
} }
already_AddRefed<ScaledFont> already_AddRefed<ScaledFont>
ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData, ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData,
FT_Face aFace, const char* aPathname, uint32_t aIndex, UnscaledFontFontconfig* aUnscaledFont,
Float aSize) Float aSize)
{ {
FcPattern* pattern = FcPatternCreate(); FcPattern* pattern = FcPatternCreate();
if (!pattern) { if (!pattern) {
gfxWarning() << "Failing initializing Fontconfig pattern for scaled font"; gfxWarning() << "Failing initializing Fontconfig pattern for scaled font";
return nullptr; return nullptr;
} }
if (aFace) { if (aUnscaledFont->GetFace()) {
FcPatternAddFTFace(pattern, FC_FT_FACE, aFace); FcPatternAddFTFace(pattern, FC_FT_FACE, aUnscaledFont->GetFace());
} else { } else {
FcPatternAddString(pattern, FC_FILE, reinterpret_cast<const FcChar8*>(aPathname)); FcPatternAddString(pattern, FC_FILE, reinterpret_cast<const FcChar8*>(aUnscaledFont->GetFile()));
FcPatternAddInteger(pattern, FC_INDEX, aIndex); FcPatternAddInteger(pattern, FC_INDEX, aUnscaledFont->GetIndex());
} }
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize); FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize);
aInstanceData.SetupPattern(pattern); aInstanceData.SetupPattern(pattern);
@ -332,15 +293,15 @@ ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData,
} }
RefPtr<ScaledFontFontconfig> scaledFont = RefPtr<ScaledFontFontconfig> scaledFont =
new ScaledFontFontconfig(cairoScaledFont, pattern, nullptr, aSize); new ScaledFontFontconfig(cairoScaledFont, pattern, aUnscaledFont, aSize);
FcPatternDestroy(pattern); FcPatternDestroy(pattern);
return scaledFont.forget(); return scaledFont.forget();
} }
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
ScaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize) UnscaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength)
{ {
if (aDataLength < sizeof(FontDescriptor)) { if (aDataLength < sizeof(FontDescriptor)) {
gfxWarning() << "Fontconfig font descriptor is truncated."; 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."; gfxWarning() << "Pathname in Fontconfig font descriptor has invalid size.";
return nullptr; return nullptr;
} }
const char* pathname = reinterpret_cast<const char*>(aData + sizeof(FontDescriptor)); const char* path = reinterpret_cast<const char*>(aData + sizeof(FontDescriptor));
if (pathname[desc->mPathLength - 1] != '\0') { if (path[desc->mPathLength - 1] != '\0') {
gfxWarning() << "Pathname in Fontconfig font descriptor is not terminated."; gfxWarning() << "Pathname in Fontconfig font descriptor is not terminated.";
return nullptr; return nullptr;
} }
return CreateFromInstanceData(desc->mInstanceData, nullptr, pathname, desc->mIndex, aSize);
RefPtr<UnscaledFont> unscaledFont = new UnscaledFontFontconfig(path, desc->mIndex);
return unscaledFont.forget();
} }
} // namespace gfx } // namespace gfx

View File

@ -14,6 +14,7 @@ namespace mozilla {
namespace gfx { namespace gfx {
class NativeFontResourceFontconfig; class NativeFontResourceFontconfig;
class UnscaledFontFontconfig;
class ScaledFontFontconfig : public ScaledFontBase class ScaledFontFontconfig : public ScaledFontBase
{ {
@ -31,17 +32,11 @@ public:
bool CanSerialize() override { return true; } bool CanSerialize() override { return true; }
bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override;
bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override; bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override;
bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
static already_AddRefed<ScaledFont>
CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize);
private: private:
friend class NativeFontResourceFontconfig; friend class NativeFontResourceFontconfig;
friend class UnscaledFontFontconfig;
struct InstanceData struct InstanceData
{ {
@ -68,16 +63,9 @@ private:
Float mSkew; Float mSkew;
}; };
struct FontDescriptor
{
uint32_t mPathLength;
uint32_t mIndex;
InstanceData mInstanceData;
};
static already_AddRefed<ScaledFont> static already_AddRefed<ScaledFont>
CreateFromInstanceData(const InstanceData& aInstanceData, CreateFromInstanceData(const InstanceData& aInstanceData,
FT_Face aFace, const char* aPathname, uint32_t aIndex, UnscaledFontFontconfig* aUnscaledFont,
Float aSize); Float aSize);
FcPattern* mPattern; FcPattern* mPattern;

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScaledFontMac.h" #include "ScaledFontMac.h"
#include "UnscaledFontMac.h"
#ifdef USE_SKIA #ifdef USE_SKIA
#include "PathSkia.h" #include "PathSkia.h"
#include "skia/include/core/SkPaint.h" #include "skia/include/core/SkPaint.h"
@ -31,6 +32,40 @@ CGPathRef CGFontGetGlyphPath(CGFontRef fontRef, CGAffineTransform *textTransform
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
// Simple helper class to automatically release a CFObject when it goes out
// of scope.
template<class T>
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; ScaledFontMac::CTFontDrawGlyphsFuncT* ScaledFontMac::CTFontDrawGlyphsPtr = nullptr;
bool ScaledFontMac::sSymbolLookupDone = false; bool ScaledFontMac::sSymbolLookupDone = false;
@ -69,7 +104,8 @@ CreateCTFontFromCGFontWithVariations(CGFontRef aCGFont, CGFloat aSize)
ScaledFontMac::ScaledFontMac(CGFontRef aFont, ScaledFontMac::ScaledFontMac(CGFontRef aFont,
const RefPtr<UnscaledFont>& aUnscaledFont, const RefPtr<UnscaledFont>& aUnscaledFont,
Float aSize) Float aSize,
bool aOwnsFont)
: ScaledFontBase(aUnscaledFont, aSize) : ScaledFontBase(aUnscaledFont, aSize)
{ {
if (!sSymbolLookupDone) { if (!sSymbolLookupDone) {
@ -78,8 +114,11 @@ ScaledFontMac::ScaledFontMac(CGFontRef aFont,
sSymbolLookupDone = true; sSymbolLookupDone = true;
} }
if (!aOwnsFont) {
// XXX: should we be taking a reference // XXX: should we be taking a reference
mFont = CGFontRetain(aFont); mFont = CGFontRetain(aFont);
}
if (CTFontDrawGlyphsPtr != nullptr) { if (CTFontDrawGlyphsPtr != nullptr) {
// only create mCTFont if we're going to be using the CTFontDrawGlyphs API // only create mCTFont if we're going to be using the CTFontDrawGlyphs API
mCTFont = CreateCTFontFromCGFontWithVariations(aFont, aSize); mCTFont = CreateCTFontFromCGFontWithVariations(aFont, aSize);
@ -214,7 +253,7 @@ static void CollectVariationSetting(const void *key, const void *value, void *co
} }
bool 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 // We'll reconstruct a TTF font from the tables we can get from the CGFont
CFArrayRef tags = CGFontCopyTableTags(mFont); CFArrayRef tags = CGFontCopyTableTags(mFont);
@ -281,6 +320,15 @@ ScaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
// set checkSumAdjust to the computed checksum // set checkSumAdjust to the computed checksum
memcpy(&buf.data[checkSumAdjustmentOffset], &fontChecksum, sizeof(fontChecksum)); 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. // Collect any variation settings that were incorporated into the CTFont.
uint32_t variationCount = 0; uint32_t variationCount = 0;
VariationSetting* variations = nullptr; VariationSetting* variations = nullptr;
@ -302,12 +350,158 @@ ScaledFontMac::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
} }
} }
// we always use an index of 0 aCb(reinterpret_cast<uint8_t*>(variations), variationCount * sizeof(VariationSetting), aBaton);
aDataCallback(buf.data, buf.offset, 0, mSize, variationCount, variations, aBaton);
delete[] variations; delete[] variations;
return true; 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<CTFontRef>
ctFont(CTFontCreateWithGraphicsFont(aCGFont, 0, nullptr, nullptr));
AutoRelease<CFArrayRef> axes(CTFontCopyVariationAxes(ctFont));
if (!axes) {
return nullptr;
}
CFIndex axisCount = CFArrayGetCount(axes);
AutoRelease<CFMutableDictionaryRef>
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<CFDictionaryRef>(axisInfo);
CFTypeRef axisTag =
CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey);
if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
return nullptr;
}
int64_t tagLong;
if (!CFNumberGetValue(static_cast<CFNumberRef>(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<CFNumberRef>(min), kCFNumberDoubleType,
&minDouble) ||
!CFNumberGetValue(static_cast<CFNumberRef>(max), kCFNumberDoubleType,
&maxDouble) ||
!CFNumberGetValue(static_cast<CFNumberRef>(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<double>(aVariations[j].mValue,
minDouble),
maxDouble);
if (value != defDouble) {
allDefaultValues = false;
}
break;
}
}
AutoRelease<CFNumberRef> 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<CFDictionaryRef>
varDict(CreateVariationDictionaryOrNull(aFont, aVariationCount, aVariations));
if (!varDict) {
return nullptr;
}
return CGFontCreateCopyWithVariations(aFont, varDict);
}
already_AddRefed<ScaledFont>
UnscaledFontMac::CreateScaledFont(Float aGlyphSize,
const uint8_t* aInstanceData,
uint32_t aInstanceDataLength)
{
uint32_t variationCount =
aInstanceDataLength / sizeof(ScaledFont::VariationSetting);
const ScaledFont::VariationSetting* variations =
reinterpret_cast<const ScaledFont::VariationSetting*>(aInstanceData);
CGFontRef fontRef = mFont;
if (variationCount > 0) {
CGFontRef varFont =
CreateCGFontWithVariations(mFont, variationCount, variations);
if (varFont) {
fontRef = varFont;
}
}
RefPtr<ScaledFontMac> 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 #ifdef USE_CAIRO_SCALED_FONT

View File

@ -40,20 +40,22 @@ private:
class ScaledFontMac : public ScaledFontBase class ScaledFontMac : public ScaledFontBase
{ {
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontMac) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontMac, override)
ScaledFontMac(CGFontRef aFont, const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize); ScaledFontMac(CGFontRef aFont, const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize, bool aOwnsFont = false);
virtual ~ScaledFontMac(); ~ScaledFontMac();
virtual FontType GetType() const { return FontType::MAC; } FontType GetType() const override { return FontType::MAC; }
#ifdef USE_SKIA #ifdef USE_SKIA
virtual SkTypeface* GetSkTypeface(); SkTypeface* GetSkTypeface() override;
#endif #endif
virtual already_AddRefed<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget); already_AddRefed<Path> GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) override;
virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton);
virtual bool CanSerialize() { return true; } bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override;
bool CanSerialize() override { return true; }
#ifdef USE_CAIRO_SCALED_FONT #ifdef USE_CAIRO_SCALED_FONT
cairo_font_face_t* GetCairoFontFace(); cairo_font_face_t* GetCairoFontFace() override;
#endif #endif
private: private:

View File

@ -4,6 +4,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScaledFontWin.h" #include "ScaledFontWin.h"
#include "UnscaledFontGDI.h"
#include "AutoHelpersWin.h" #include "AutoHelpersWin.h"
#include "Logging.h" #include "Logging.h"
@ -31,7 +32,7 @@ ScaledFontWin::ScaledFontWin(const LOGFONT* aFont,
} }
bool bool
ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) UnscaledFontGDI::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
{ {
AutoDC dc; AutoDC dc;
AutoSelectFont font(dc.GetDC(), &mLogFont); AutoSelectFont font(dc.GetDC(), &mLogFont);
@ -56,7 +57,7 @@ ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton)
return false; return false;
} }
aDataCallback(fontData.get(), tableSize, 0, mSize, 0, nullptr, aBaton); aDataCallback(fontData.get(), tableSize, 0, aBaton);
return true; return true;
} }
@ -68,21 +69,41 @@ ScaledFontWin::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton)
} }
bool bool
ScaledFontWin::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) UnscaledFontGDI::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
{ {
aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), mSize, aBaton); aCb(reinterpret_cast<uint8_t*>(&mLogFont), sizeof(mLogFont), aBaton);
return true; return true;
} }
already_AddRefed<ScaledFont> already_AddRefed<UnscaledFont>
ScaledFontWin::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize) 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<const LOGFONT*>(aData);
RefPtr<UnscaledFont> unscaledFont = new UnscaledFontGDI(*logFont);
return unscaledFont.forget();
}
already_AddRefed<ScaledFont>
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 nativeFont;
nativeFont.mType = NativeFontType::GDI_FONT_FACE; nativeFont.mType = NativeFontType::GDI_FONT_FACE;
nativeFont.mFont = (void*)aData; nativeFont.mFont = (void*)aInstanceData;
RefPtr<ScaledFont> font = RefPtr<ScaledFont> font =
Factory::CreateScaledFontForNativeFont(nativeFont, nullptr, aSize); Factory::CreateScaledFontForNativeFont(nativeFont, this, aGlyphSize);
#ifdef USE_CAIRO_SCALED_FONT #ifdef USE_CAIRO_SCALED_FONT
static_cast<ScaledFontBase*>(font.get())->PopulateCairoScaledFont(); static_cast<ScaledFontBase*>(font.get())->PopulateCairoScaledFont();

View File

@ -15,26 +15,19 @@ namespace gfx {
class ScaledFontWin : public ScaledFontBase class ScaledFontWin : public ScaledFontBase
{ {
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin, override)
ScaledFontWin(const LOGFONT* aFont, ScaledFontWin(const LOGFONT* aFont,
const RefPtr<UnscaledFont>& aUnscaledFont, const RefPtr<UnscaledFont>& aUnscaledFont,
Float aSize); Float aSize);
virtual FontType GetType() const { return FontType::GDI; } FontType GetType() const override { return FontType::GDI; }
bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override; bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override;
virtual bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override; AntialiasMode GetDefaultAAMode() override;
static already_AddRefed<ScaledFont>
CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, Float aSize);
virtual AntialiasMode GetDefaultAAMode() override;
#ifdef USE_SKIA #ifdef USE_SKIA
virtual SkTypeface* GetSkTypeface(); SkTypeface* GetSkTypeface() override;
#endif #endif
protected: protected:

View File

@ -19,9 +19,11 @@ public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontDWrite, override) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontDWrite, override)
explicit UnscaledFontDWrite(const RefPtr<IDWriteFontFace>& aFontFace, explicit UnscaledFontDWrite(const RefPtr<IDWriteFontFace>& aFontFace,
DWRITE_FONT_SIMULATIONS aSimulations = DWRITE_FONT_SIMULATIONS aSimulations =
DWRITE_FONT_SIMULATIONS_NONE) DWRITE_FONT_SIMULATIONS_NONE,
: mFontFace(aFontFace), bool aNeedsCairo = false)
mSimulations(aSimulations) : mFontFace(aFontFace)
, mSimulations(aSimulations)
, mNeedsCairo(aNeedsCairo)
{} {}
FontType GetType() const override { return FontType::DWRITE; } FontType GetType() const override { return FontType::DWRITE; }
@ -29,9 +31,17 @@ public:
const RefPtr<IDWriteFontFace> GetFontFace() const { return mFontFace; } const RefPtr<IDWriteFontFace> GetFontFace() const { return mFontFace; }
DWRITE_FONT_SIMULATIONS GetSimulations() const { return mSimulations; } DWRITE_FONT_SIMULATIONS GetSimulations() const { return mSimulations; }
bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
already_AddRefed<ScaledFont>
CreateScaledFont(Float aGlyphSize,
const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) override;
private: private:
RefPtr<IDWriteFontFace> mFontFace; RefPtr<IDWriteFontFace> mFontFace;
DWRITE_FONT_SIMULATIONS mSimulations; DWRITE_FONT_SIMULATIONS mSimulations;
bool mNeedsCairo;
}; };
} // namespace gfx } // namespace gfx

View File

@ -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<FontDescriptor*>(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

View File

@ -17,16 +17,25 @@ class UnscaledFontFreeType : public UnscaledFont
{ {
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontFreeType, override) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontFreeType, override)
explicit UnscaledFontFreeType(FT_Face aFace) explicit UnscaledFontFreeType(FT_Face aFace,
bool aOwnsFace = false)
: mFace(aFace) : mFace(aFace)
, mOwnsFace(aOwnsFace)
, mIndex(0) , mIndex(0)
{} {}
explicit UnscaledFontFreeType(const char* aFile, explicit UnscaledFontFreeType(const char* aFile,
uint32_t aIndex = 0) uint32_t aIndex = 0)
: mFace(nullptr) : mFace(nullptr)
, mOwnsFace(false)
, mFile(aFile) , mFile(aFile)
, mIndex(aIndex) , mIndex(aIndex)
{} {}
~UnscaledFontFreeType()
{
if (mOwnsFace) {
FT_Done_Face(mFace);
}
}
FontType GetType() const override { return FontType::FREETYPE; } FontType GetType() const override { return FontType::FREETYPE; }
@ -34,8 +43,19 @@ public:
const char* GetFile() const { return mFile.c_str(); } const char* GetFile() const { return mFile.c_str(); }
uint32_t GetIndex() const { return mIndex; } 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: private:
FT_Face mFace; FT_Face mFace;
bool mOwnsFace;
std::string mFile; std::string mFile;
uint32_t mIndex; uint32_t mIndex;
}; };
@ -45,8 +65,9 @@ class UnscaledFontFontconfig : public UnscaledFontFreeType
{ {
public: public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontFontconfig, override) MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontFontconfig, override)
explicit UnscaledFontFontconfig(FT_Face aFace) explicit UnscaledFontFontconfig(FT_Face aFace,
: UnscaledFontFreeType(aFace) bool aOwnsFace = false)
: UnscaledFontFreeType(aFace, aOwnsFace)
{} {}
explicit UnscaledFontFontconfig(const char* aFile, explicit UnscaledFontFontconfig(const char* aFile,
uint32_t aIndex = 0) uint32_t aIndex = 0)
@ -54,6 +75,14 @@ public:
{} {}
FontType GetType() const override { return FontType::FONTCONFIG; } FontType GetType() const override { return FontType::FONTCONFIG; }
static already_AddRefed<UnscaledFont>
CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength);
already_AddRefed<ScaledFont>
CreateScaledFont(Float aGlyphSize,
const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) override;
}; };
#endif #endif

View File

@ -24,6 +24,18 @@ public:
const LOGFONT& GetLogFont() const { return mLogFont; } const LOGFONT& GetLogFont() const { return mLogFont; }
bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override;
bool GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton) override;
static already_AddRefed<UnscaledFont>
CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength);
already_AddRefed<ScaledFont>
CreateScaledFont(Float aGlyphSize,
const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) override;
private: private:
LOGFONT mLogFont; LOGFONT mLogFont;
}; };

View File

@ -36,6 +36,18 @@ public:
CGFontRef GetFont() const { return mFont; } CGFontRef GetFont() const { return mFont; }
bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override;
already_AddRefed<ScaledFont>
CreateScaledFont(Float aGlyphSize,
const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) override;
static CGFontRef
CreateCGFontWithVariations(CGFontRef aFont,
uint32_t aVariationCount,
const ScaledFont::VariationSetting* aVariations);
private: private:
CGFontRef mFont; CGFontRef mFont;
}; };

View File

@ -98,6 +98,9 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3'):
EXPORTS.mozilla.gfx += [ EXPORTS.mozilla.gfx += [
'UnscaledFontFreeType.h', 'UnscaledFontFreeType.h',
] ]
SOURCES += [
'UnscaledFontFreeType.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'):
SOURCES += [ SOURCES += [

View File

@ -156,13 +156,11 @@ struct FontFileData
{ {
wr::ByteBuffer mFontBuffer; wr::ByteBuffer mFontBuffer;
uint32_t mFontIndex; uint32_t mFontIndex;
float mGlyphSize;
}; };
static void static void
WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex, WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
float aGlyphSize, uint32_t aVariationCount, void* aBaton)
const ScaledFont::VariationSetting* aVariations, void* aBaton)
{ {
FontFileData* data = static_cast<FontFileData*>(aBaton); FontFileData* data = static_cast<FontFileData*>(aBaton);
@ -172,7 +170,6 @@ WriteFontFileData(const uint8_t* aData, uint32_t aLength, uint32_t aIndex,
memcpy(data->mFontBuffer.mData, aData, aLength); memcpy(data->mFontBuffer.mData, aData, aLength);
data->mFontIndex = aIndex; data->mFontIndex = aIndex;
data->mGlyphSize = aGlyphSize;
} }
void void
@ -228,7 +225,7 @@ WebRenderBridgeChild::GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont)
} }
FontFileData data; FontFileData data;
if (!aScaledFont->GetFontFileData(WriteFontFileData, &data) || if (!unscaled->GetFontFileData(WriteFontFileData, &data) ||
!data.mFontBuffer.mData) { !data.mFontBuffer.mData) {
return key; return key;
} }

View File

@ -23,142 +23,6 @@
using namespace mozilla; using namespace mozilla;
using namespace mozilla::gfx; using namespace mozilla::gfx;
// Simple helper class to automatically release a CFObject when it goes out
// of scope.
template<class T>
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<gfxFontVariation>& aVariations)
{
// Avoid calling potentially buggy variation APIs on pre-Sierra macOS
// versions (see bug 1331683)
if (!nsCocoaFeatures::OnSierraOrLater()) {
return nullptr;
}
AutoRelease<CTFontRef>
ctFont(CTFontCreateWithGraphicsFont(aCGFont, 0, nullptr, nullptr));
AutoRelease<CFArrayRef> axes(CTFontCopyVariationAxes(ctFont));
if (!axes) {
return nullptr;
}
CFIndex axisCount = CFArrayGetCount(axes);
AutoRelease<CFMutableDictionaryRef>
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<CFDictionaryRef>(axisInfo);
CFTypeRef axisTag =
CFDictionaryGetValue(axis, kCTFontVariationAxisIdentifierKey);
if (!axisTag || CFGetTypeID(axisTag) != CFNumberGetTypeID()) {
return nullptr;
}
int64_t tagLong;
if (!CFNumberGetValue(static_cast<CFNumberRef>(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<CFNumberRef>(min), kCFNumberDoubleType,
&minDouble) ||
!CFNumberGetValue(static_cast<CFNumberRef>(max), kCFNumberDoubleType,
&maxDouble) ||
!CFNumberGetValue(static_cast<CFNumberRef>(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<double>(aVariations[j].mValue,
minDouble),
maxDouble);
if (value != defDouble) {
allDefaultValues = false;
}
break;
}
}
AutoRelease<CFNumberRef> 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<UnscaledFontMac>& aUnscaledFont, gfxMacFont::gfxMacFont(const RefPtr<UnscaledFontMac>& aUnscaledFont,
MacOSFontEntry *aFontEntry, MacOSFontEntry *aFontEntry,
const gfxFontStyle *aFontStyle, const gfxFontStyle *aFontStyle,
@ -177,12 +41,14 @@ gfxMacFont::gfxMacFont(const RefPtr<UnscaledFontMac>& aUnscaledFont,
mIsValid = false; mIsValid = false;
return; return;
} }
CFDictionaryRef variations = MOZ_ASSERT(sizeof(ScaledFont::VariationSetting) == sizeof(gfxFontVariation));
CreateVariationDictionaryOrNull(baseFont, aFontStyle->variationSettings); mCGFont =
if (variations) { UnscaledFontMac::CreateCGFontWithVariations(
mCGFont = ::CGFontCreateCopyWithVariations(baseFont, variations); baseFont,
::CFRelease(variations); aFontStyle->variationSettings.Length(),
} else { reinterpret_cast<const ScaledFont::VariationSetting*>(
aFontStyle->variationSettings.Elements()));
if (!mCGFont) {
::CFRetain(baseFont); ::CFRetain(baseFont);
mCGFont = baseFont; mCGFont = baseFont;
} }

View File

@ -27,6 +27,7 @@ using gfx::SourceSurface;
using gfx::FilterNode; using gfx::FilterNode;
using gfx::GradientStops; using gfx::GradientStops;
using gfx::ScaledFont; using gfx::ScaledFont;
using gfx::UnscaledFont;
using gfx::NativeFontResource; using gfx::NativeFontResource;
class PrintTranslator final : public Translator class PrintTranslator final : public Translator
@ -78,6 +79,13 @@ public:
return result; return result;
} }
UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) final
{
UnscaledFont* result = mUnscaledFonts.GetWeak(aRefPtr);
MOZ_ASSERT(result);
return result;
}
NativeFontResource* LookupNativeFontResource(uint64_t aKey) final NativeFontResource* LookupNativeFontResource(uint64_t aKey) final
{ {
NativeFontResource* result = mNativeFontResources.GetWeak(aKey); NativeFontResource* result = mNativeFontResources.GetWeak(aKey);
@ -115,6 +123,11 @@ public:
mScaledFonts.Put(aRefPtr, aScaledFont); mScaledFonts.Put(aRefPtr, aScaledFont);
} }
void AddUnscaledFont(ReferencePtr aRefPtr, UnscaledFont* aUnscaledFont) final
{
mUnscaledFonts.Put(aRefPtr, aUnscaledFont);
}
void AddNativeFontResource(uint64_t aKey, void AddNativeFontResource(uint64_t aKey,
NativeFontResource *aScaledFontResouce) final NativeFontResource *aScaledFontResouce) final
{ {
@ -151,6 +164,11 @@ public:
mScaledFonts.Remove(aRefPtr); mScaledFonts.Remove(aRefPtr);
} }
void RemoveUnscaledFont(ReferencePtr aRefPtr) final
{
mUnscaledFonts.Remove(aRefPtr);
}
already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr, already_AddRefed<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
const gfx::IntSize &aSize, const gfx::IntSize &aSize,
gfx::SurfaceFormat aFormat) final; gfx::SurfaceFormat aFormat) final;
@ -169,6 +187,7 @@ private:
nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes; nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops; nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts; nsRefPtrHashtable<nsPtrHashKey<void>, ScaledFont> mScaledFonts;
nsRefPtrHashtable<nsPtrHashKey<void>, UnscaledFont> mUnscaledFonts;
nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources; nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources;
}; };