diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index d1673c9bf2f3..24cac481de59 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -57,6 +57,9 @@ typedef FT_FaceRec_* FT_Face; typedef int FT_Error; +struct _FcPattern; +typedef _FcPattern FcPattern; + struct ID3D11Texture2D; struct ID3D11Device; struct ID2D1Device; @@ -746,6 +749,63 @@ struct GlyphMetrics { Float mHeight; }; +#ifdef MOZ_ENABLE_FREETYPE +class SharedFTFace; + +/** SharedFTFaceData abstracts data that may be used to back a SharedFTFace. + * Its main function is to manage the lifetime of the data and ensure that it + * lasts as long as the face. + */ +class SharedFTFaceData { + public: + /** Utility for creating a new face from this data. */ + virtual already_AddRefed CloneFace(int aFaceIndex = 0) { + return nullptr; + } + /** Binds the data's lifetime to the face. */ + virtual void BindData() = 0; + /** Signals that the data is no longer needed by a face. */ + virtual void ReleaseData() = 0; +}; + +/** Wrapper class for ref-counted SharedFTFaceData that handles calling the + * appropriate ref-counting methods + */ +template +class SharedFTFaceRefCountedData : public SharedFTFaceData { + public: + void BindData() { static_cast(this)->AddRef(); } + void ReleaseData() { static_cast(this)->Release(); } +}; + +/** SharedFTFace is a shared wrapper around an FT_Face. It is ref-counted, + * unlike FT_Face itself, so that it may be shared among many users with + * RefPtr. Users should take care to lock SharedFTFace before accessing any + * FT_Face fields that may change to ensure exclusive access to it. It also + * allows backing data's lifetime to be bound to it via SharedFTFaceData so + * that the data will not disappear before the face does. + */ +class SharedFTFace : public external::AtomicRefCounted { + public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SharedFTFace) + + explicit SharedFTFace(FT_Face aFace, SharedFTFaceData* aData = nullptr); + virtual ~SharedFTFace(); + + FT_Face GetFace() const { return mFace; } + SharedFTFaceData* GetData() const { return mData; } + + void Lock() { mLock.Lock(); } + bool TryLock() { return mLock.TryLock(); } + void Unlock() { mLock.Unlock(); } + + private: + FT_Face mFace; + SharedFTFaceData* mData; + Mutex mLock; +}; +#endif + class UnscaledFont : public SupportsThreadSafeWeakPtr { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFont) @@ -813,7 +873,7 @@ class ScaledFont : public SupportsThreadSafeWeakPtr { virtual FontType GetType() const = 0; virtual Float GetSize() const = 0; - virtual AntialiasMode GetDefaultAAMode(); + virtual AntialiasMode GetDefaultAAMode() { return AntialiasMode::DEFAULT; } static uint32_t DeletionCounter() { return sDeletionCounter; } @@ -1662,6 +1722,19 @@ class GFX2D_API Factory { bool aApplySyntheticBold = false); #endif +#ifdef MOZ_WIDGET_GTK + static already_AddRefed CreateScaledFontForFontconfigFont( + const RefPtr& aUnscaledFont, Float aSize, + cairo_scaled_font_t* aScaledFont, RefPtr aFace, + FcPattern* aPattern); +#endif + +#ifdef MOZ_WIDGET_ANDROID + static already_AddRefed CreateScaledFontForFreeTypeFont( + const RefPtr& aUnscaledFont, Float aSize, + cairo_scaled_font_t* aScaledFont, RefPtr aFace); +#endif + /** * This creates a NativeFontResource from TrueType data. * @@ -1799,8 +1872,14 @@ class GFX2D_API Factory { static FT_Face NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex); + static already_AddRefed NewSharedFTFace(FT_Library aFTLibrary, + const char* aFilename, + int aFaceIndex); static FT_Face NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex); + static already_AddRefed NewSharedFTFaceFromData( + FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, + int aFaceIndex, SharedFTFaceData* aSharedData = nullptr); static void ReleaseFTFace(FT_Face aFace); static FT_Error LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags); diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index 621ffbb05c51..89f87f221345 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -911,29 +911,6 @@ void DrawTargetSkia::Fill(const Path* aPath, const Pattern& aPattern, mCanvas->drawPath(skiaPath->GetPath(), paint.mPaint); } -bool DrawTargetSkia::ShouldLCDRenderText(FontType aFontType, - AntialiasMode aAntialiasMode) { - // Only allow subpixel AA if explicitly permitted. - if (!GetPermitSubpixelAA()) { - return false; - } - - if (aAntialiasMode == AntialiasMode::DEFAULT) { - switch (aFontType) { - case FontType::MAC: - case FontType::GDI: - case FontType::DWRITE: - case FontType::FONTCONFIG: - return true; - case FontType::FREETYPE: - default: - // TODO: Figure out what to do for the other platforms. - return false; - } - } - return (aAntialiasMode == AntialiasMode::SUBPIXEL); -} - #ifdef MOZ_WIDGET_COCOA static inline CGAffineTransform GfxMatrixToCGAffineTransform(const Matrix& m) { CGAffineTransform t; @@ -1321,56 +1298,14 @@ void DrawTargetSkia::DrawGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer, SkFont font(sk_ref_sp(typeface), SkFloatToScalar(skiaFont->mSize)); - bool useSubpixelAA = ShouldLCDRenderText(aFont->GetType(), aaMode); + bool useSubpixelAA = + GetPermitSubpixelAA() && + (aaMode == AntialiasMode::DEFAULT || aaMode == AntialiasMode::SUBPIXEL); font.setEdging(useSubpixelAA ? SkFont::Edging::kSubpixelAntiAlias : (aaEnabled ? SkFont::Edging::kAntiAlias : SkFont::Edging::kAlias)); - bool useSubpixelText = true; - switch (aFont->GetType()) { - case FontType::FREETYPE: - case FontType::FONTCONFIG: - // SkFontHost_cairo does not support subpixel text positioning, - // so only enable it for other font hosts. - useSubpixelText = false; - break; - case FontType::MAC: - if (aaMode == AntialiasMode::GRAY) { - // Normally, Skia enables LCD FontSmoothing which creates thicker fonts - // and also enables subpixel AA. CoreGraphics without font smoothing - // explicitly creates thinner fonts and grayscale AA. - // CoreGraphics doesn't support a configuration that produces thicker - // fonts with grayscale AA as LCD Font Smoothing enables or disables - // both. However, Skia supports it by enabling font smoothing (producing - // subpixel AA) and converts it to grayscale AA. Since Skia doesn't - // support subpixel AA on transparent backgrounds, we still want font - // smoothing for the thicker fonts, even if it is grayscale AA. - // - // With explicit Grayscale AA (from -moz-osx-font-smoothing:grayscale), - // we want to have grayscale AA with no smoothing at all. This means - // disabling the LCD font smoothing behaviour. - // To accomplish this we have to explicitly disable hinting, - // and disable LCDRenderText. - font.setHinting(kNo_SkFontHinting); - } - break; -#ifdef XP_WIN - case FontType::DWRITE: { - ScaledFontDWrite* dwriteFont = static_cast(aFont); - if (dwriteFont->ForceGDIMode()) { - font.setEmbeddedBitmaps(true); - useSubpixelText = false; - } else { - font.setEmbeddedBitmaps(dwriteFont->UseEmbeddedBitmaps()); - } - break; - } -#endif - default: - break; - } - - font.setSubpixel(useSubpixelText); + skiaFont->SetupSkFontDrawOptions(font); // Limit the amount of internal batch allocations Skia does. const uint32_t kMaxGlyphBatchSize = 8192; diff --git a/gfx/2d/DrawTargetSkia.h b/gfx/2d/DrawTargetSkia.h index bbe6acfc59af..9285048722e7 100644 --- a/gfx/2d/DrawTargetSkia.h +++ b/gfx/2d/DrawTargetSkia.h @@ -147,8 +147,6 @@ class DrawTargetSkia : public DrawTarget { void MarkChanged(); - bool ShouldLCDRenderText(FontType aFontType, AntialiasMode aAntialiasMode); - void DrawGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer, const Pattern& aPattern, const StrokeOptions* aStrokeOptions = nullptr, diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index 2e4cda6cc217..e044ffad6897 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -157,19 +157,24 @@ static inline bool HasCPUIDBit(unsigned int level, CPUIDRegister reg, #ifdef MOZ_ENABLE_FREETYPE extern "C" { -FT_Face mozilla_NewFTFace(FT_Library aFTLibrary, const char* aFileName, - int aFaceIndex) { - return mozilla::gfx::Factory::NewFTFace(aFTLibrary, aFileName, aFaceIndex); +void mozilla_AddRefSharedFTFace(void* aContext) { + if (aContext) { + static_cast(aContext)->AddRef(); + } } -FT_Face mozilla_NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, - size_t aDataSize, int aFaceIndex) { - return mozilla::gfx::Factory::NewFTFaceFromData(aFTLibrary, aData, aDataSize, - aFaceIndex); +void mozilla_ReleaseSharedFTFace(void* aContext) { + if (aContext) { + static_cast(aContext)->Release(); + } } -void mozilla_ReleaseFTFace(FT_Face aFace) { - mozilla::gfx::Factory::ReleaseFTFace(aFace); +void mozilla_LockSharedFTFace(void* aContext) { + static_cast(aContext)->Lock(); +} + +void mozilla_UnlockSharedFTFace(void* aContext) { + static_cast(aContext)->Unlock(); } FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, @@ -554,16 +559,6 @@ already_AddRefed Factory::CreateScaledFontForNativeFont( # endif return font.forget(); } -#elif defined(MOZ_WIDGET_GTK) - case NativeFontType::FONTCONFIG_PATTERN: - return MakeAndAddRef( - aScaledFont, static_cast(aNativeFont.mFont), - aUnscaledFont, aSize); -#elif defined(MOZ_WIDGET_ANDROID) - case NativeFontType::FREETYPE_FACE: - return MakeAndAddRef( - aScaledFont, static_cast(aNativeFont.mFont), aUnscaledFont, - aSize); #endif default: gfxWarning() << "Invalid native font type specified."; @@ -634,6 +629,25 @@ already_AddRefed Factory::CreateScaledFontForMacFont( } #endif +#ifdef MOZ_WIDGET_GTK +already_AddRefed Factory::CreateScaledFontForFontconfigFont( + const RefPtr& aUnscaledFont, Float aSize, + cairo_scaled_font_t* aScaledFont, RefPtr aFace, + FcPattern* aPattern) { + return MakeAndAddRef(aScaledFont, std::move(aFace), + aPattern, aUnscaledFont, aSize); +} +#endif + +#ifdef MOZ_WIDGET_ANDROID +already_AddRefed Factory::CreateScaledFontForFreeTypeFont( + const RefPtr& aUnscaledFont, Float aSize, + cairo_scaled_font_t* aScaledFont, RefPtr aFace) { + return MakeAndAddRef(aScaledFont, std::move(aFace), + aUnscaledFont, aSize); +} +#endif + already_AddRefed Factory::CreateDualDrawTarget( DrawTarget* targetA, DrawTarget* targetB) { MOZ_ASSERT(targetA && targetB); @@ -663,6 +677,20 @@ void Factory::SetBGRSubpixelOrder(bool aBGR) { mBGRSubpixelOrder = aBGR; } bool Factory::GetBGRSubpixelOrder() { return mBGRSubpixelOrder; } #ifdef MOZ_ENABLE_FREETYPE +SharedFTFace::SharedFTFace(FT_Face aFace, SharedFTFaceData* aData) + : mFace(aFace), mData(aData), mLock("SharedFTFace::mLock") { + if (mData) { + mData->BindData(); + } +} + +SharedFTFace::~SharedFTFace() { + Factory::ReleaseFTFace(mFace); + if (mData) { + mData->ReleaseData(); + } +} + void Factory::SetFTLibrary(FT_Library aFTLibrary) { mFTLibrary = aFTLibrary; } FT_Library Factory::GetFTLibrary() { @@ -699,6 +727,16 @@ FT_Face Factory::NewFTFace(FT_Library aFTLibrary, const char* aFileName, return face; } +already_AddRefed Factory::NewSharedFTFace(FT_Library aFTLibrary, + const char* aFilename, + int aFaceIndex) { + if (FT_Face face = NewFTFace(aFTLibrary, aFilename, aFaceIndex)) { + return MakeAndAddRef(face); + } else { + return nullptr; + } +} + FT_Face Factory::NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex) { StaticMutexAutoLock lock(mFTLock); @@ -713,6 +751,17 @@ FT_Face Factory::NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, return face; } +already_AddRefed Factory::NewSharedFTFaceFromData( + FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, + int aFaceIndex, SharedFTFaceData* aSharedData) { + if (FT_Face face = + NewFTFaceFromData(aFTLibrary, aData, aDataSize, aFaceIndex)) { + return MakeAndAddRef(face, aSharedData); + } else { + return nullptr; + } +} + void Factory::ReleaseFTFace(FT_Face aFace) { StaticMutexAutoLock lock(mFTLock); FT_Done_Face(aFace); diff --git a/gfx/2d/HelpersWinFonts.h b/gfx/2d/HelpersWinFonts.h index 7320a898de43..9bfa69c9b7b9 100644 --- a/gfx/2d/HelpersWinFonts.h +++ b/gfx/2d/HelpersWinFonts.h @@ -4,8 +4,6 @@ * 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 "mozilla/StaticPrefs_gfx.h" - namespace mozilla { namespace gfx { @@ -15,9 +13,6 @@ static BYTE GetSystemTextQuality() { return sSystemTextQuality; } static AntialiasMode GetSystemDefaultAAMode() { AntialiasMode defaultMode = AntialiasMode::SUBPIXEL; - if (StaticPrefs::gfx_text_disable_aa_AtStartup()) { - return AntialiasMode::NONE; - } switch (GetSystemTextQuality()) { case CLEARTYPE_QUALITY: diff --git a/gfx/2d/NativeFontResourceFreeType.cpp b/gfx/2d/NativeFontResourceFreeType.cpp index da9faa39ccb4..49234c0694ae 100644 --- a/gfx/2d/NativeFontResourceFreeType.cpp +++ b/gfx/2d/NativeFontResourceFreeType.cpp @@ -12,15 +12,13 @@ namespace mozilla { namespace gfx { NativeFontResourceFreeType::NativeFontResourceFreeType( - UniquePtr&& aFontData, uint32_t aDataLength, FT_Face aFace) - : mFontData(std::move(aFontData)), mDataLength(aDataLength), mFace(aFace) {} + UniquePtr&& aFontData, uint32_t aDataLength, + FT_Library aFTLibrary) + : mFontData(std::move(aFontData)), + mDataLength(aDataLength), + mFTLibrary(aFTLibrary) {} -NativeFontResourceFreeType::~NativeFontResourceFreeType() { - if (mFace) { - Factory::ReleaseFTFace(mFace); - mFace = nullptr; - } -} +NativeFontResourceFreeType::~NativeFontResourceFreeType() {} template already_AddRefed NativeFontResourceFreeType::CreateInternal( @@ -34,18 +32,7 @@ already_AddRefed NativeFontResourceFreeType::CreateInternal( } memcpy(fontData.get(), aFontData, aDataLength); - FT_Face face = - Factory::NewFTFaceFromData(aFTLibrary, fontData.get(), aDataLength, 0); - if (!face) { - return nullptr; - } - if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != FT_Err_Ok && - FT_Select_Charmap(face, FT_ENCODING_MS_SYMBOL) != FT_Err_Ok) { - Factory::ReleaseFTFace(face); - return nullptr; - } - - RefPtr resource = new T(std::move(fontData), aDataLength, face); + RefPtr resource = new T(std::move(fontData), aDataLength, aFTLibrary); return resource.forget(); } @@ -59,26 +46,40 @@ already_AddRefed NativeFontResourceFreeType::Create( already_AddRefed NativeFontResourceFreeType::CreateUnscaledFont( uint32_t aIndex, const uint8_t* aInstanceData, uint32_t aInstanceDataLength) { - RefPtr unscaledFont = new UnscaledFontFreeType(mFace, this); - return unscaledFont.forget(); + if (RefPtr face = CloneFace()) { + return MakeAndAddRef(std::move(face)); + } + return nullptr; } #endif -FT_Face NativeFontResourceFreeType::CloneFace() { - return Factory::NewFTFaceFromData(mFace->glyph->library, mFontData.get(), - mDataLength, 0); +already_AddRefed NativeFontResourceFreeType::CloneFace( + int aFaceIndex) { + RefPtr face = Factory::NewSharedFTFaceFromData( + mFTLibrary, mFontData.get(), mDataLength, aFaceIndex, this); + if (!face || + (FT_Select_Charmap(face->GetFace(), FT_ENCODING_UNICODE) != FT_Err_Ok && + FT_Select_Charmap(face->GetFace(), FT_ENCODING_MS_SYMBOL) != + FT_Err_Ok)) { + return nullptr; + } + return face.forget(); } #ifdef MOZ_WIDGET_GTK NativeFontResourceFontconfig::NativeFontResourceFontconfig( - UniquePtr&& aFontData, uint32_t aDataLength, FT_Face aFace) - : NativeFontResourceFreeType(std::move(aFontData), aDataLength, aFace) {} + UniquePtr&& aFontData, uint32_t aDataLength, + FT_Library aFTLibrary) + : NativeFontResourceFreeType(std::move(aFontData), aDataLength, + aFTLibrary) {} already_AddRefed NativeFontResourceFontconfig::CreateUnscaledFont( uint32_t aIndex, const uint8_t* aInstanceData, uint32_t aInstanceDataLength) { - RefPtr unscaledFont = new UnscaledFontFontconfig(mFace, this); - return unscaledFont.forget(); + if (RefPtr face = CloneFace()) { + return MakeAndAddRef(std::move(face)); + } + return nullptr; } already_AddRefed diff --git a/gfx/2d/NativeFontResourceFreeType.h b/gfx/2d/NativeFontResourceFreeType.h index 594529539606..381dfe0c0b3a 100644 --- a/gfx/2d/NativeFontResourceFreeType.h +++ b/gfx/2d/NativeFontResourceFreeType.h @@ -15,7 +15,9 @@ namespace mozilla { namespace gfx { -class NativeFontResourceFreeType : public NativeFontResource { +class NativeFontResourceFreeType + : public NativeFontResource, + public SharedFTFaceRefCountedData { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceFreeType, override) @@ -31,11 +33,12 @@ class NativeFontResourceFreeType : public NativeFontResource { ~NativeFontResourceFreeType(); - FT_Face CloneFace(); + already_AddRefed CloneFace(int aFaceIndex = 0) override; protected: NativeFontResourceFreeType(UniquePtr&& aFontData, - uint32_t aDataLength, FT_Face aFace); + uint32_t aDataLength, + FT_Library aFTLibrary = nullptr); template static already_AddRefed CreateInternal(uint8_t* aFontData, @@ -44,7 +47,7 @@ class NativeFontResourceFreeType : public NativeFontResource { UniquePtr mFontData; uint32_t mDataLength; - FT_Face mFace; + FT_Library mFTLibrary; }; #ifdef MOZ_WIDGET_GTK @@ -65,7 +68,8 @@ class NativeFontResourceFontconfig final : public NativeFontResourceFreeType { friend class NativeFontResourceFreeType; NativeFontResourceFontconfig(UniquePtr&& aFontData, - uint32_t aDataLength, FT_Face aFace); + uint32_t aDataLength, + FT_Library aFTLibrary = nullptr); }; #endif diff --git a/gfx/2d/ScaledFontBase.cpp b/gfx/2d/ScaledFontBase.cpp index 28076703bd8a..9fc83d66a60e 100644 --- a/gfx/2d/ScaledFontBase.cpp +++ b/gfx/2d/ScaledFontBase.cpp @@ -6,8 +6,6 @@ #include "ScaledFontBase.h" -#include "mozilla/StaticPrefs_gfx.h" - #ifdef USE_SKIA # include "PathSkia.h" # include "skia/include/core/SkFont.h" @@ -33,14 +31,6 @@ Atomic ScaledFont::sDeletionCounter(0); ScaledFont::~ScaledFont() { sDeletionCounter++; } -AntialiasMode ScaledFont::GetDefaultAAMode() { - if (StaticPrefs::gfx_text_disable_aa_AtStartup()) { - return AntialiasMode::NONE; - } - - return AntialiasMode::DEFAULT; -} - ScaledFontBase::~ScaledFontBase() { #ifdef USE_SKIA SkSafeUnref(mTypeface); diff --git a/gfx/2d/ScaledFontBase.h b/gfx/2d/ScaledFontBase.h index d0d4b5d411de..ad4f405b1a44 100644 --- a/gfx/2d/ScaledFontBase.h +++ b/gfx/2d/ScaledFontBase.h @@ -15,6 +15,7 @@ #endif #ifdef USE_SKIA +# include "skia/include/core/SkFont.h" # include "skia/include/core/SkPath.h" # include "skia/include/core/SkTypeface.h" #endif @@ -47,6 +48,7 @@ class ScaledFontBase : public ScaledFont { #ifdef USE_SKIA SkTypeface* GetSkTypeface(); + virtual void SetupSkFontDrawOptions(SkFont& aFont) {} #endif #ifdef USE_CAIRO_SCALED_FONT diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp index 8088e5d91f6b..52a0f049b3ae 100644 --- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -185,6 +185,16 @@ SkTypeface* ScaledFontDWrite::CreateSkTypeface() { return SkCreateTypefaceFromDWriteFont(factory, mFontFace, mStyle, mRenderingMode, gamma, contrast); } + +void ScaledFontDWrite::SetupSkFontDrawOptions(SkFont& aFont) { + if (ForceGDIMode()) { + aFont.setEmbeddedBitmaps(true); + aFont.setSubpixel(false); + } else { + aFont.setEmbeddedBitmaps(UseEmbeddedBitmaps()); + aFont.setSubpixel(true); + } +} #endif void ScaledFontDWrite::CopyGlyphsToBuilder(const GlyphBuffer& aBuffer, diff --git a/gfx/2d/ScaledFontDWrite.h b/gfx/2d/ScaledFontDWrite.h index 45237350e5f5..5f4b9a498532 100644 --- a/gfx/2d/ScaledFontDWrite.h +++ b/gfx/2d/ScaledFontDWrite.h @@ -74,6 +74,7 @@ class ScaledFontDWrite final : public ScaledFontBase { #ifdef USE_SKIA SkTypeface* CreateSkTypeface() override; + void SetupSkFontDrawOptions(SkFont& aFont) override; SkFontStyle mStyle; #endif diff --git a/gfx/2d/ScaledFontFontconfig.cpp b/gfx/2d/ScaledFontFontconfig.cpp index 161545c0e51e..f677ed00c059 100644 --- a/gfx/2d/ScaledFontFontconfig.cpp +++ b/gfx/2d/ScaledFontFontconfig.cpp @@ -8,15 +8,16 @@ #include "UnscaledFontFreeType.h" #include "NativeFontResourceFreeType.h" #include "Logging.h" -#include "StackArray.h" #include "mozilla/webrender/WebRenderTypes.h" #ifdef USE_SKIA # include "skia/include/ports/SkTypeface_cairo.h" +# include "HelpersSkia.h" #endif #include +#include FT_LCD_FILTER_H #include FT_MULTIPLE_MASTERS_H namespace mozilla { @@ -27,39 +28,72 @@ namespace gfx { // This is mainly because FT_Face is not good for sharing between libraries, // which is a requirement when we consider runtime switchable backends and so on ScaledFontFontconfig::ScaledFontFontconfig( - cairo_scaled_font_t* aScaledFont, FcPattern* aPattern, - const RefPtr& aUnscaledFont, Float aSize) - : ScaledFontBase(aUnscaledFont, aSize), mPattern(aPattern) { + cairo_scaled_font_t* aScaledFont, RefPtr&& aFace, + FcPattern* aPattern, const RefPtr& aUnscaledFont, Float aSize) + : ScaledFontBase(aUnscaledFont, aSize), + mFace(std::move(aFace)), + mInstanceData(aScaledFont, aPattern) { SetCairoScaledFont(aScaledFont); - FcPatternReference(aPattern); } -ScaledFontFontconfig::~ScaledFontFontconfig() { FcPatternDestroy(mPattern); } +ScaledFontFontconfig::ScaledFontFontconfig( + cairo_scaled_font_t* aScaledFont, RefPtr&& aFace, + const InstanceData& aInstanceData, + const RefPtr& aUnscaledFont, Float aSize) + : ScaledFontBase(aUnscaledFont, aSize), + mFace(std::move(aFace)), + mInstanceData(aInstanceData) { + SetCairoScaledFont(aScaledFont); +} #ifdef USE_SKIA SkTypeface* ScaledFontFontconfig::CreateSkTypeface() { - return SkCreateTypefaceFromCairoFTFontWithFontconfig(mScaledFont, mPattern); + SkPixelGeometry geo = mInstanceData.mFlags & InstanceData::SUBPIXEL_BGR + ? (mInstanceData.mFlags & InstanceData::LCD_VERTICAL + ? kBGR_V_SkPixelGeometry + : kBGR_H_SkPixelGeometry) + : (mInstanceData.mFlags & InstanceData::LCD_VERTICAL + ? kRGB_V_SkPixelGeometry + : kRGB_H_SkPixelGeometry); + return SkCreateTypefaceFromCairoFTFont(mScaledFont, mFace->GetFace(), + mFace.get(), geo, + mInstanceData.mLcdFilter); +} + +void ScaledFontFontconfig::SetupSkFontDrawOptions(SkFont& aFont) { + // SkFontHost_cairo does not support subpixel text positioning + aFont.setSubpixel(false); + + if (mInstanceData.mFlags & InstanceData::AUTOHINT) { + aFont.setForceAutoHinting(true); + } + if (mInstanceData.mFlags & InstanceData::EMBEDDED_BITMAP) { + aFont.setEmbeddedBitmaps(true); + } + if (mInstanceData.mFlags & InstanceData::EMBOLDEN) { + aFont.setEmbolden(true); + } + + aFont.setHinting(GfxHintingToSkiaHinting(mInstanceData.mHinting)); } #endif +AntialiasMode ScaledFontFontconfig::GetDefaultAAMode() { + return mInstanceData.mAntialias; +} + ScaledFontFontconfig::InstanceData::InstanceData( cairo_scaled_font_t* aScaledFont, FcPattern* aPattern) : mFlags(0), - mHintStyle(FC_HINT_NONE), - mSubpixelOrder(FC_RGBA_UNKNOWN), - mLcdFilter(FC_LCD_LEGACY) { + mAntialias(AntialiasMode::NONE), + mHinting(FontHinting::NONE), + mLcdFilter(FT_LCD_FILTER_LEGACY) { // Record relevant Fontconfig properties into instance data. FcBool autohint; if (FcPatternGetBool(aPattern, FC_AUTOHINT, 0, &autohint) == FcResultMatch && autohint) { mFlags |= AUTOHINT; } - FcBool bitmap; - if (FcPatternGetBool(aPattern, FC_EMBEDDED_BITMAP, 0, &bitmap) == - FcResultMatch && - bitmap) { - mFlags |= EMBEDDED_BITMAP; - } FcBool embolden; if (FcPatternGetBool(aPattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch && embolden) { @@ -72,24 +106,6 @@ ScaledFontFontconfig::InstanceData::InstanceData( mFlags |= VERTICAL_LAYOUT; } - FcBool antialias; - if (FcPatternGetBool(aPattern, FC_ANTIALIAS, 0, &antialias) != - FcResultMatch || - antialias) { - mFlags |= ANTIALIAS; - - // Only record subpixel order and lcd filtering if antialiasing is enabled. - int rgba; - if (FcPatternGetInteger(aPattern, FC_RGBA, 0, &rgba) == FcResultMatch) { - mSubpixelOrder = rgba; - } - int filter; - if (FcPatternGetInteger(aPattern, FC_LCD_FILTER, 0, &filter) == - FcResultMatch) { - mLcdFilter = filter; - } - } - cairo_font_options_t* fontOptions = cairo_font_options_create(); cairo_scaled_font_get_font_options(aScaledFont, fontOptions); // For printer fonts, Cairo hint metrics and hinting will be disabled. @@ -106,19 +122,96 @@ ScaledFontFontconfig::InstanceData::InstanceData( FcResultMatch) { hintstyle = FC_HINT_FULL; } - mHintStyle = hintstyle; + switch (hintstyle) { + case FC_HINT_SLIGHT: + mHinting = FontHinting::LIGHT; + break; + case FC_HINT_MEDIUM: + mHinting = FontHinting::NORMAL; + break; + case FC_HINT_FULL: + mHinting = FontHinting::FULL; + break; + case FC_HINT_NONE: + default: + break; + } } } cairo_font_options_destroy(fontOptions); + + FcBool antialias; + if (FcPatternGetBool(aPattern, FC_ANTIALIAS, 0, &antialias) == + FcResultMatch && + !antialias) { + // If AA is explicitly disabled, leave bitmaps enabled. + mFlags |= EMBEDDED_BITMAP; + } else { + mAntialias = AntialiasMode::GRAY; + + // Otherwise, if AA is enabled, disable embedded bitmaps unless explicitly + // enabled. + FcBool bitmap; + if (mHinting != FontHinting::NONE && + FcPatternGetBool(aPattern, FC_EMBEDDED_BITMAP, 0, &bitmap) == + FcResultMatch && + bitmap) { + mFlags |= EMBEDDED_BITMAP; + } + + // Only record subpixel order and lcd filtering if antialiasing is enabled. + int rgba; + if (mFlags & HINT_METRICS && + FcPatternGetInteger(aPattern, FC_RGBA, 0, &rgba) == FcResultMatch) { + switch (rgba) { + case FC_RGBA_RGB: + case FC_RGBA_BGR: + case FC_RGBA_VRGB: + case FC_RGBA_VBGR: + mAntialias = AntialiasMode::SUBPIXEL; + if (rgba == FC_RGBA_VRGB || rgba == FC_RGBA_VBGR) { + mFlags |= LCD_VERTICAL; + } + if (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR) { + mFlags |= SUBPIXEL_BGR; + } + break; + case FC_RGBA_NONE: + case FC_RGBA_UNKNOWN: + default: + break; + } + } + + int filter; + if (mAntialias == AntialiasMode::SUBPIXEL && + FcPatternGetInteger(aPattern, FC_LCD_FILTER, 0, &filter) == + FcResultMatch) { + switch (filter) { + case FC_LCD_NONE: + mLcdFilter = FT_LCD_FILTER_NONE; + break; + case FC_LCD_DEFAULT: + mLcdFilter = FT_LCD_FILTER_DEFAULT; + break; + case FC_LCD_LIGHT: + mLcdFilter = FT_LCD_FILTER_LIGHT; + break; + case FC_LCD_LEGACY: + default: + break; + } + } + } } ScaledFontFontconfig::InstanceData::InstanceData( const wr::FontInstanceOptions* aOptions, const wr::FontInstancePlatformOptions* aPlatformOptions) : mFlags(HINT_METRICS), - mHintStyle(FC_HINT_FULL), - mSubpixelOrder(FC_RGBA_UNKNOWN), - mLcdFilter(FC_LCD_LEGACY) { + mAntialias(AntialiasMode::NONE), + mHinting(FontHinting::FULL), + mLcdFilter(FT_LCD_FILTER_LEGACY) { if (aOptions) { if (aOptions->flags & wr::FontInstanceFlags_FORCE_AUTOHINT) { mFlags |= AUTOHINT; @@ -132,44 +225,41 @@ ScaledFontFontconfig::InstanceData::InstanceData( if (aOptions->flags & wr::FontInstanceFlags_VERTICAL_LAYOUT) { mFlags |= VERTICAL_LAYOUT; } - if (aOptions->render_mode != wr::FontRenderMode::Mono) { - mFlags |= ANTIALIAS; - if (aOptions->render_mode == wr::FontRenderMode::Subpixel) { - if (aOptions->flags & wr::FontInstanceFlags_SUBPIXEL_BGR) { - mSubpixelOrder = aOptions->flags & wr::FontInstanceFlags_LCD_VERTICAL - ? FC_RGBA_VBGR - : FC_RGBA_BGR; - } else { - mSubpixelOrder = aOptions->flags & wr::FontInstanceFlags_LCD_VERTICAL - ? FC_RGBA_VRGB - : FC_RGBA_RGB; - } + if (aOptions->render_mode == wr::FontRenderMode::Subpixel) { + mAntialias = AntialiasMode::SUBPIXEL; + if (aOptions->flags & wr::FontInstanceFlags_SUBPIXEL_BGR) { + mFlags |= SUBPIXEL_BGR; } + if (aOptions->flags & wr::FontInstanceFlags_LCD_VERTICAL) { + mFlags |= LCD_VERTICAL; + } + } else if (aOptions->render_mode != wr::FontRenderMode::Mono) { + mAntialias = AntialiasMode::GRAY; } } if (aPlatformOptions) { switch (aPlatformOptions->hinting) { case wr::FontHinting::None: - mHintStyle = FC_HINT_NONE; + mHinting = FontHinting::NONE; break; case wr::FontHinting::Light: - mHintStyle = FC_HINT_SLIGHT; + mHinting = FontHinting::LIGHT; break; case wr::FontHinting::Normal: - mHintStyle = FC_HINT_MEDIUM; + mHinting = FontHinting::NORMAL; break; default: break; } switch (aPlatformOptions->lcd_filter) { case wr::FontLCDFilter::None: - mLcdFilter = FC_LCD_NONE; + mLcdFilter = FT_LCD_FILTER_NONE; break; case wr::FontLCDFilter::Default: - mLcdFilter = FC_LCD_DEFAULT; + mLcdFilter = FT_LCD_FILTER_DEFAULT; break; case wr::FontLCDFilter::Light: - mLcdFilter = FC_LCD_LIGHT; + mLcdFilter = FT_LCD_FILTER_LIGHT; break; default: break; @@ -177,120 +267,99 @@ ScaledFontFontconfig::InstanceData::InstanceData( } } -void ScaledFontFontconfig::InstanceData::SetupPattern( - FcPattern* aPattern) const { - if (mFlags & AUTOHINT) { - FcPatternAddBool(aPattern, FC_AUTOHINT, FcTrue); - } - if (mFlags & EMBEDDED_BITMAP) { - FcPatternAddBool(aPattern, FC_EMBEDDED_BITMAP, FcTrue); - } - if (mFlags & EMBOLDEN) { - FcPatternAddBool(aPattern, FC_EMBOLDEN, FcTrue); - } - if (mFlags & VERTICAL_LAYOUT) { - FcPatternAddBool(aPattern, FC_VERTICAL_LAYOUT, FcTrue); - } - - if (mFlags & ANTIALIAS) { - FcPatternAddBool(aPattern, FC_ANTIALIAS, FcTrue); - if (mSubpixelOrder != FC_RGBA_UNKNOWN) { - FcPatternAddInteger(aPattern, FC_RGBA, mSubpixelOrder); - } - if (mLcdFilter != FC_LCD_LEGACY) { - FcPatternAddInteger(aPattern, FC_LCD_FILTER, mLcdFilter); - } - } else { - FcPatternAddBool(aPattern, FC_ANTIALIAS, FcFalse); - } - - if (mHintStyle) { - FcPatternAddBool(aPattern, FC_HINTING, FcTrue); - FcPatternAddInteger(aPattern, FC_HINT_STYLE, mHintStyle); - } else { - FcPatternAddBool(aPattern, FC_HINTING, FcFalse); - } -} - void ScaledFontFontconfig::InstanceData::SetupFontOptions( - cairo_font_options_t* aFontOptions) const { + cairo_font_options_t* aFontOptions, int* aOutLoadFlags, + unsigned int* aOutSynthFlags) const { + // For regular (non-printer) fonts, enable hint metrics as well as hinting + // and (possibly subpixel) antialiasing. + cairo_font_options_set_hint_metrics(aFontOptions, mFlags & HINT_METRICS ? CAIRO_HINT_METRICS_ON : CAIRO_HINT_METRICS_OFF); + + cairo_hint_style_t hinting; + switch (mHinting) { + case FontHinting::NONE: + hinting = CAIRO_HINT_STYLE_NONE; + break; + case FontHinting::LIGHT: + hinting = CAIRO_HINT_STYLE_SLIGHT; + break; + case FontHinting::NORMAL: + hinting = CAIRO_HINT_STYLE_MEDIUM; + break; + case FontHinting::FULL: + hinting = CAIRO_HINT_STYLE_FULL; + break; + } + cairo_font_options_set_hint_style(aFontOptions, hinting); + + switch (mAntialias) { + case AntialiasMode::NONE: + cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_NONE); + break; + case AntialiasMode::GRAY: + default: + cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_GRAY); + break; + case AntialiasMode::SUBPIXEL: { + cairo_font_options_set_antialias(aFontOptions, + CAIRO_ANTIALIAS_SUBPIXEL); + cairo_font_options_set_subpixel_order( + aFontOptions, + mFlags & SUBPIXEL_BGR + ? (mFlags & LCD_VERTICAL ? CAIRO_SUBPIXEL_ORDER_VBGR + : CAIRO_SUBPIXEL_ORDER_BGR) + : (mFlags & LCD_VERTICAL ? CAIRO_SUBPIXEL_ORDER_VRGB + : CAIRO_SUBPIXEL_ORDER_RGB)); + cairo_lcd_filter_t lcdFilter = CAIRO_LCD_FILTER_DEFAULT; + switch (mLcdFilter) { + case FT_LCD_FILTER_NONE: + lcdFilter = CAIRO_LCD_FILTER_NONE; + break; + case FT_LCD_FILTER_DEFAULT: + lcdFilter = CAIRO_LCD_FILTER_FIR5; + break; + case FT_LCD_FILTER_LIGHT: + lcdFilter = CAIRO_LCD_FILTER_FIR3; + break; + case FT_LCD_FILTER_LEGACY: + lcdFilter = CAIRO_LCD_FILTER_INTRA_PIXEL; + break; + } + cairo_font_options_set_lcd_filter(aFontOptions, lcdFilter); + break; + } + } + // Try to build a sane initial set of Cairo font options based on the // Fontconfig pattern. - if (mFlags & HINT_METRICS) { - // For regular (non-printer) fonts, enable hint metrics as well as hinting - // and (possibly subpixel) antialiasing. - cairo_font_options_set_hint_metrics(aFontOptions, CAIRO_HINT_METRICS_ON); + int loadFlags = FT_LOAD_DEFAULT; + unsigned int synthFlags = 0; - cairo_hint_style_t hinting; - switch (mHintStyle) { - case FC_HINT_NONE: - hinting = CAIRO_HINT_STYLE_NONE; - break; - case FC_HINT_SLIGHT: - hinting = CAIRO_HINT_STYLE_SLIGHT; - break; - case FC_HINT_MEDIUM: - default: - hinting = CAIRO_HINT_STYLE_MEDIUM; - break; - case FC_HINT_FULL: - hinting = CAIRO_HINT_STYLE_FULL; - break; - } - cairo_font_options_set_hint_style(aFontOptions, hinting); - - if (mFlags & ANTIALIAS) { - cairo_subpixel_order_t subpixel = CAIRO_SUBPIXEL_ORDER_DEFAULT; - switch (mSubpixelOrder) { - case FC_RGBA_RGB: - subpixel = CAIRO_SUBPIXEL_ORDER_RGB; - break; - case FC_RGBA_BGR: - subpixel = CAIRO_SUBPIXEL_ORDER_BGR; - break; - case FC_RGBA_VRGB: - subpixel = CAIRO_SUBPIXEL_ORDER_VRGB; - break; - case FC_RGBA_VBGR: - subpixel = CAIRO_SUBPIXEL_ORDER_VBGR; - break; - default: - break; - } - if (subpixel != CAIRO_SUBPIXEL_ORDER_DEFAULT) { - cairo_font_options_set_antialias(aFontOptions, - CAIRO_ANTIALIAS_SUBPIXEL); - cairo_font_options_set_subpixel_order(aFontOptions, subpixel); - } else { - cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_GRAY); - } - } else { - cairo_font_options_set_antialias(aFontOptions, CAIRO_ANTIALIAS_NONE); - } - } else { - // For printer fonts, disable hint metrics and hinting. Don't allow subpixel - // antialiasing. - cairo_font_options_set_hint_metrics(aFontOptions, CAIRO_HINT_METRICS_OFF); - cairo_font_options_set_hint_style(aFontOptions, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_antialias(aFontOptions, mFlags & ANTIALIAS - ? CAIRO_ANTIALIAS_GRAY - : CAIRO_ANTIALIAS_NONE); + if (!(mFlags & EMBEDDED_BITMAP)) { + loadFlags |= FT_LOAD_NO_BITMAP; } + if (mFlags & AUTOHINT) { + loadFlags |= FT_LOAD_FORCE_AUTOHINT; + } + if (mFlags & VERTICAL_LAYOUT) { + loadFlags |= FT_LOAD_VERTICAL_LAYOUT; + } + if (mFlags & EMBOLDEN) { + synthFlags |= CAIRO_FT_SYNTHESIZE_BOLD; + } + + *aOutLoadFlags = loadFlags; + *aOutSynthFlags = synthFlags; } bool ScaledFontFontconfig::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) { - InstanceData instance(GetCairoScaledFont(), mPattern); - std::vector variations; if (HasVariationSettings()) { - FT_Face face = nullptr; - if (FcPatternGetFTFace(mPattern, FC_FT_FACE, 0, &face) == FcResultMatch) { - UnscaledFontFreeType::GetVariationSettingsFromFace(&variations, face); - } + UnscaledFontFreeType::GetVariationSettingsFromFace(&variations, + mFace->GetFace()); } - aCb(reinterpret_cast(&instance), sizeof(instance), + aCb(reinterpret_cast(&mInstanceData), sizeof(mInstanceData), variations.data(), variations.size(), aBaton); return true; } @@ -312,110 +381,67 @@ bool ScaledFontFontconfig::GetWRFontInstanceOptions( platformOptions.lcd_filter = wr::FontLCDFilter::Legacy; platformOptions.hinting = wr::FontHinting::Normal; - FcBool autohint; - if (FcPatternGetBool(mPattern, FC_AUTOHINT, 0, &autohint) == FcResultMatch && - autohint) { + if (mInstanceData.mFlags & InstanceData::AUTOHINT) { options.flags |= wr::FontInstanceFlags_FORCE_AUTOHINT; } - FcBool embolden; - if (FcPatternGetBool(mPattern, FC_EMBOLDEN, 0, &embolden) == FcResultMatch && - embolden) { + if (mInstanceData.mFlags & InstanceData::EMBOLDEN) { options.flags |= wr::FontInstanceFlags_SYNTHETIC_BOLD; } - FcBool vertical; - if (FcPatternGetBool(mPattern, FC_VERTICAL_LAYOUT, 0, &vertical) == - FcResultMatch && - vertical) { + if (mInstanceData.mFlags & InstanceData::VERTICAL_LAYOUT) { options.flags |= wr::FontInstanceFlags_VERTICAL_LAYOUT; } - - FcBool antialias; - if (FcPatternGetBool(mPattern, FC_ANTIALIAS, 0, &antialias) != - FcResultMatch || - antialias) { - int rgba; - if (FcPatternGetInteger(mPattern, FC_RGBA, 0, &rgba) == FcResultMatch) { - switch (rgba) { - case FC_RGBA_RGB: - case FC_RGBA_BGR: - case FC_RGBA_VRGB: - case FC_RGBA_VBGR: - options.render_mode = wr::FontRenderMode::Subpixel; - if (rgba == FC_RGBA_VRGB || rgba == FC_RGBA_VBGR) { - options.flags |= wr::FontInstanceFlags_LCD_VERTICAL; - } - platformOptions.hinting = wr::FontHinting::LCD; - if (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR) { - options.flags |= wr::FontInstanceFlags_SUBPIXEL_BGR; - } - break; - case FC_RGBA_NONE: - case FC_RGBA_UNKNOWN: - default: - break; + if (mInstanceData.mFlags & InstanceData::EMBEDDED_BITMAP) { + options.flags |= wr::FontInstanceFlags_EMBEDDED_BITMAPS; + } + if (mInstanceData.mAntialias != AntialiasMode::NONE) { + if (mInstanceData.mAntialias == AntialiasMode::SUBPIXEL) { + options.render_mode = wr::FontRenderMode::Subpixel; + platformOptions.hinting = wr::FontHinting::LCD; + if (mInstanceData.mFlags & InstanceData::LCD_VERTICAL) { + options.flags |= wr::FontInstanceFlags_LCD_VERTICAL; + } + if (mInstanceData.mFlags & InstanceData::SUBPIXEL_BGR) { + options.flags |= wr::FontInstanceFlags_SUBPIXEL_BGR; } } - if (options.render_mode == wr::FontRenderMode::Subpixel) { - int filter; - if (FcPatternGetInteger(mPattern, FC_LCD_FILTER, 0, &filter) == - FcResultMatch) { - switch (filter) { - case FC_LCD_NONE: - platformOptions.lcd_filter = wr::FontLCDFilter::None; - break; - case FC_LCD_DEFAULT: - platformOptions.lcd_filter = wr::FontLCDFilter::Default; - break; - case FC_LCD_LIGHT: - platformOptions.lcd_filter = wr::FontLCDFilter::Light; - break; - case FC_LCD_LEGACY: - default: - break; - } - } + switch (mInstanceData.mLcdFilter) { + case FT_LCD_FILTER_NONE: + platformOptions.lcd_filter = wr::FontLCDFilter::None; + break; + case FT_LCD_FILTER_DEFAULT: + platformOptions.lcd_filter = wr::FontLCDFilter::Default; + break; + case FT_LCD_FILTER_LIGHT: + platformOptions.lcd_filter = wr::FontLCDFilter::Light; + break; + case FT_LCD_FILTER_LEGACY: + default: + break; } - // Match cairo-ft's handling of embeddedbitmap: - // If AA is explicitly disabled, leave bitmaps enabled. - // Otherwise, disable embedded bitmaps unless explicitly enabled. - FcBool bitmap; - if (FcPatternGetBool(mPattern, FC_EMBEDDED_BITMAP, 0, &bitmap) == - FcResultMatch && - bitmap) { - options.flags |= wr::FontInstanceFlags_EMBEDDED_BITMAPS; + switch (mInstanceData.mHinting) { + case FontHinting::NONE: + platformOptions.hinting = wr::FontHinting::None; + break; + case FontHinting::LIGHT: + platformOptions.hinting = wr::FontHinting::Light; + break; + case FontHinting::NORMAL: + platformOptions.hinting = wr::FontHinting::Normal; + break; + case FontHinting::FULL: + break; } } else { options.render_mode = wr::FontRenderMode::Mono; - platformOptions.hinting = wr::FontHinting::Mono; - options.flags |= wr::FontInstanceFlags_EMBEDDED_BITMAPS; - } - FcBool hinting; - int hintstyle; - if (FcPatternGetBool(mPattern, FC_HINTING, 0, &hinting) != FcResultMatch || - hinting) { - if (FcPatternGetInteger(mPattern, FC_HINT_STYLE, 0, &hintstyle) != - FcResultMatch) { - hintstyle = FC_HINT_FULL; - } - } else { - hintstyle = FC_HINT_NONE; - } - - if (hintstyle == FC_HINT_NONE) { - platformOptions.hinting = wr::FontHinting::None; - } else if (options.render_mode != wr::FontRenderMode::Mono) { - switch (hintstyle) { - case FC_HINT_SLIGHT: - platformOptions.hinting = wr::FontHinting::Light; + switch (mInstanceData.mHinting) { + case FontHinting::NONE: + platformOptions.hinting = wr::FontHinting::None; break; - case FC_HINT_MEDIUM: - platformOptions.hinting = wr::FontHinting::Normal; - break; - case FC_HINT_FULL: default: + platformOptions.hinting = wr::FontHinting::Mono; break; } } @@ -424,27 +450,13 @@ bool ScaledFontFontconfig::GetWRFontInstanceOptions( *aOutPlatformOptions = Some(platformOptions); if (HasVariationSettings()) { - FT_Face face = nullptr; - if (FcPatternGetFTFace(mPattern, FC_FT_FACE, 0, &face) == FcResultMatch) { - UnscaledFontFreeType::GetVariationSettingsFromFace(aOutVariations, face); - } + UnscaledFontFreeType::GetVariationSettingsFromFace(aOutVariations, + mFace->GetFace()); } return true; } -static cairo_user_data_key_t sNativeFontResourceKey; - -static void ReleaseNativeFontResource(void* aData) { - static_cast(aData)->Release(); -} - -static cairo_user_data_key_t sFaceKey; - -static void ReleaseFace(void* aData) { - Factory::ReleaseFTFace(static_cast(aData)); -} - already_AddRefed UnscaledFontFontconfig::CreateScaledFont( Float aSize, const uint8_t* aInstanceData, uint32_t aInstanceDataLength, const FontVariation* aVariations, uint32_t aNumVariations) { @@ -456,86 +468,38 @@ already_AddRefed UnscaledFontFontconfig::CreateScaledFont( *reinterpret_cast( aInstanceData); - FcPattern* pattern = FcPatternCreate(); - if (!pattern) { - gfxWarning() << "Failed initializing Fontconfig pattern for scaled font"; + RefPtr face(InitFace()); + if (!face) { + gfxWarning() << "Attempted to deserialize Fontconfig scaled font without " + "FreeType face"; return nullptr; } - FT_Face face = GetFace(); - NativeFontResourceFreeType* nfr = - static_cast(mNativeFontResource.get()); - FT_Face varFace = nullptr; - if (face) { - if (nfr && aNumVariations > 0) { - varFace = nfr->CloneFace(); - if (!varFace) { - gfxWarning() << "Failed cloning face for variations"; - } + + if (aNumVariations > 0 && face->GetData()) { + if (RefPtr varFace = face->GetData()->CloneFace()) { + face = varFace; } - FcPatternAddFTFace(pattern, FC_FT_FACE, varFace ? varFace : face); - } else { - FcPatternAddString(pattern, FC_FILE, - reinterpret_cast(GetFile())); - FcPatternAddInteger(pattern, FC_INDEX, GetIndex()); - } - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize); - instanceData.SetupPattern(pattern); - - StackArray coords(aNumVariations); - for (uint32_t i = 0; i < aNumVariations; i++) { - coords[i] = std::round(aVariations[i].mValue * 65536.0); } - cairo_font_face_t* font = cairo_ft_font_face_create_for_pattern( - pattern, coords.data(), aNumVariations); + cairo_font_options_t* fontOptions = cairo_font_options_create(); + int loadFlags; + unsigned int synthFlags; + instanceData.SetupFontOptions(fontOptions, &loadFlags, &synthFlags); + + cairo_font_face_t* font = cairo_ft_font_face_create_for_ft_face( + face->GetFace(), loadFlags, synthFlags, face.get()); if (cairo_font_face_status(font) != CAIRO_STATUS_SUCCESS) { gfxWarning() << "Failed creating Cairo font face for Fontconfig pattern"; - FcPatternDestroy(pattern); - if (varFace) { - Factory::ReleaseFTFace(varFace); - } + cairo_font_options_destroy(fontOptions); return nullptr; } - if (nfr) { - // Bug 1362117 - Cairo may keep the font face alive after the owning - // NativeFontResource was freed. To prevent this, we must bind the - // NativeFontResource to the font face so that it stays alive at least as - // long as the font face. - nfr->AddRef(); - cairo_status_t err = CAIRO_STATUS_SUCCESS; - bool cleanupFace = false; - if (varFace) { - err = - cairo_font_face_set_user_data(font, &sFaceKey, varFace, ReleaseFace); - } - if (err != CAIRO_STATUS_SUCCESS) { - cleanupFace = true; - } else { - err = cairo_font_face_set_user_data(font, &sNativeFontResourceKey, nfr, - ReleaseNativeFontResource); - } - if (err != CAIRO_STATUS_SUCCESS) { - gfxWarning() << "Failed binding NativeFontResource to Cairo font face"; - if (varFace && cleanupFace) { - Factory::ReleaseFTFace(varFace); - } - nfr->Release(); - cairo_font_face_destroy(font); - FcPatternDestroy(pattern); - return nullptr; - } - } - cairo_matrix_t sizeMatrix; cairo_matrix_init(&sizeMatrix, aSize, 0, 0, aSize, 0, 0); cairo_matrix_t identityMatrix; cairo_matrix_init_identity(&identityMatrix); - cairo_font_options_t* fontOptions = cairo_font_options_create(); - instanceData.SetupFontOptions(fontOptions); - cairo_scaled_font_t* cairoScaledFont = cairo_scaled_font_create(font, &sizeMatrix, &identityMatrix, fontOptions); @@ -544,21 +508,18 @@ already_AddRefed UnscaledFontFontconfig::CreateScaledFont( if (cairo_scaled_font_status(cairoScaledFont) != CAIRO_STATUS_SUCCESS) { gfxWarning() << "Failed creating Cairo scaled font for font face"; - FcPatternDestroy(pattern); return nullptr; } - RefPtr scaledFont = - new ScaledFontFontconfig(cairoScaledFont, pattern, this, aSize); + // Only apply variations if we have an explicitly cloned face. + if (aNumVariations > 0 && face != GetFace()) { + ApplyVariationsToFace(aVariations, aNumVariations, face->GetFace()); + } + + RefPtr scaledFont = new ScaledFontFontconfig( + cairoScaledFont, std::move(face), instanceData, this, aSize); cairo_scaled_font_destroy(cairoScaledFont); - FcPatternDestroy(pattern); - - // Only apply variations if we have an explicitly cloned face. Otherwise, - // if the pattern holds the pathname, Cairo will handle setting of variations. - if (varFace) { - ApplyVariationsToFace(aVariations, aNumVariations, varFace); - } return scaledFont.forget(); } @@ -574,11 +535,10 @@ already_AddRefed UnscaledFontFontconfig::CreateScaledFontFromWRFont( bool ScaledFontFontconfig::HasVariationSettings() { // Check if the FT face has been cloned. - FT_Face face = nullptr; - return FcPatternGetFTFace(mPattern, FC_FT_FACE, 0, &face) == FcResultMatch && - face && face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS && - face != static_cast(mUnscaledFont.get()) - ->GetFace(); + return mFace && + mFace->GetFace()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS && + mFace != static_cast(mUnscaledFont.get()) + ->GetFace(); } already_AddRefed UnscaledFontFontconfig::CreateFromFontDescriptor( diff --git a/gfx/2d/ScaledFontFontconfig.h b/gfx/2d/ScaledFontFontconfig.h index 9767dfa96cc8..b7a3522cd5fd 100644 --- a/gfx/2d/ScaledFontFontconfig.h +++ b/gfx/2d/ScaledFontFontconfig.h @@ -20,16 +20,19 @@ class UnscaledFontFontconfig; class ScaledFontFontconfig : public ScaledFontBase { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontFontconfig, override) - ScaledFontFontconfig(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern, + ScaledFontFontconfig(cairo_scaled_font_t* aScaledFont, + RefPtr&& aFace, FcPattern* aPattern, const RefPtr& aUnscaledFont, Float aSize); - ~ScaledFontFontconfig(); FontType GetType() const override { return FontType::FONTCONFIG; } #ifdef USE_SKIA SkTypeface* CreateSkTypeface() override; + void SetupSkFontDrawOptions(SkFont& aFont) override; #endif + AntialiasMode GetDefaultAAMode() override; + bool CanSerialize() override { return true; } bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override; @@ -47,28 +50,36 @@ class ScaledFontFontconfig : public ScaledFontBase { struct InstanceData { enum { - ANTIALIAS = 1 << 0, - AUTOHINT = 1 << 1, - EMBEDDED_BITMAP = 1 << 2, - EMBOLDEN = 1 << 3, - VERTICAL_LAYOUT = 1 << 4, - HINT_METRICS = 1 << 5 + AUTOHINT = 1 << 0, + EMBEDDED_BITMAP = 1 << 1, + EMBOLDEN = 1 << 2, + VERTICAL_LAYOUT = 1 << 3, + HINT_METRICS = 1 << 4, + LCD_VERTICAL = 1 << 5, + SUBPIXEL_BGR = 1 << 6, }; InstanceData(cairo_scaled_font_t* aScaledFont, FcPattern* aPattern); InstanceData(const wr::FontInstanceOptions* aOptions, const wr::FontInstancePlatformOptions* aPlatformOptions); - void SetupPattern(FcPattern* aPattern) const; - void SetupFontOptions(cairo_font_options_t* aFontOptions) const; + void SetupFontOptions(cairo_font_options_t* aFontOptions, + int* aOutLoadFlags, + unsigned int* aOutSynthFlags) const; uint8_t mFlags; - uint8_t mHintStyle; - uint8_t mSubpixelOrder; + AntialiasMode mAntialias; + FontHinting mHinting; uint8_t mLcdFilter; }; - FcPattern* mPattern; + ScaledFontFontconfig(cairo_scaled_font_t* aScaledFont, + RefPtr&& aFace, + const InstanceData& aInstanceData, + const RefPtr& aUnscaledFont, Float aSize); + + RefPtr mFace; + InstanceData mInstanceData; }; } // namespace gfx diff --git a/gfx/2d/ScaledFontFreeType.cpp b/gfx/2d/ScaledFontFreeType.cpp index fd7586a1d07b..213215abaf4c 100644 --- a/gfx/2d/ScaledFontFreeType.cpp +++ b/gfx/2d/ScaledFontFreeType.cpp @@ -8,7 +8,6 @@ #include "UnscaledFontFreeType.h" #include "NativeFontResourceFreeType.h" #include "Logging.h" -#include "StackArray.h" #include "mozilla/webrender/WebRenderTypes.h" #ifdef USE_SKIA @@ -25,15 +24,23 @@ namespace gfx { // This is mainly because FT_Face is not good for sharing between libraries, // which is a requirement when we consider runtime switchable backends and so on ScaledFontFreeType::ScaledFontFreeType( - cairo_scaled_font_t* aScaledFont, FT_Face aFace, + cairo_scaled_font_t* aScaledFont, RefPtr&& aFace, const RefPtr& aUnscaledFont, Float aSize) - : ScaledFontBase(aUnscaledFont, aSize), mFace(aFace) { + : ScaledFontBase(aUnscaledFont, aSize), mFace(std::move(aFace)) { SetCairoScaledFont(aScaledFont); } #ifdef USE_SKIA SkTypeface* ScaledFontFreeType::CreateSkTypeface() { - return SkCreateTypefaceFromCairoFTFont(mScaledFont, mFace); + return SkCreateTypefaceFromCairoFTFont(mScaledFont, mFace->GetFace(), + mFace.get()); +} + +void ScaledFontFreeType::SetupSkFontDrawOptions(SkFont& aFont) { + // SkFontHost_cairo does not support subpixel text positioning + aFont.setSubpixel(false); + + aFont.setEmbeddedBitmaps(true); } #endif @@ -41,7 +48,8 @@ bool ScaledFontFreeType::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) { std::vector variations; if (HasVariationSettings()) { - UnscaledFontFreeType::GetVariationSettingsFromFace(&variations, mFace); + UnscaledFontFreeType::GetVariationSettingsFromFace(&variations, + mFace->GetFace()); } aCb(nullptr, 0, variations.data(), variations.size(), aBaton); @@ -70,113 +78,41 @@ bool ScaledFontFreeType::GetWRFontInstanceOptions( *aOutPlatformOptions = Some(platformOptions); if (HasVariationSettings()) { - UnscaledFontFreeType::GetVariationSettingsFromFace(aOutVariations, mFace); + UnscaledFontFreeType::GetVariationSettingsFromFace(aOutVariations, + mFace->GetFace()); } return true; } -FT_Face UnscaledFontFreeType::InitFace() { - if (mFace) { - return mFace; - } - if (mFile.empty()) { - return nullptr; - } - FT_Face face = Factory::NewFTFace(nullptr, mFile.c_str(), mIndex); - if (!face) { - gfxWarning() << "Failed initializing FreeType face from filename"; - return nullptr; - } - mOwnsFace = true; - mFace = face; - return mFace; -} - -static cairo_user_data_key_t sNativeFontResourceKey; - -static void ReleaseNativeFontResource(void* aData) { - static_cast(aData)->Release(); -} - -static cairo_user_data_key_t sFaceKey; - -static void ReleaseFace(void* aData) { - Factory::ReleaseFTFace(static_cast(aData)); -} - already_AddRefed UnscaledFontFreeType::CreateScaledFont( Float aGlyphSize, const uint8_t* aInstanceData, uint32_t aInstanceDataLength, const FontVariation* aVariations, uint32_t aNumVariations) { - FT_Face face = InitFace(); + RefPtr face(InitFace()); if (!face) { gfxWarning() << "Attempted to deserialize FreeType scaled font without " "FreeType face"; return nullptr; } - NativeFontResourceFreeType* nfr = - static_cast(mNativeFontResource.get()); - FT_Face varFace = nullptr; - if (nfr && aNumVariations > 0) { - varFace = nfr->CloneFace(); - if (varFace) { + if (aNumVariations > 0 && face->GetData()) { + if (RefPtr varFace = face->GetData()->CloneFace()) { face = varFace; - } else { - gfxWarning() << "Failed cloning face for variations"; } } - StackArray coords(aNumVariations); - for (uint32_t i = 0; i < aNumVariations; i++) { - coords[i] = std::round(aVariations[i].mValue * 65536.0); - } - int flags = FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING; - if (face->face_flags & FT_FACE_FLAG_TRICKY) { + if (face->GetFace()->face_flags & FT_FACE_FLAG_TRICKY) { flags &= ~FT_LOAD_NO_AUTOHINT; } cairo_font_face_t* font = cairo_ft_font_face_create_for_ft_face( - face, flags, coords.data(), aNumVariations); + face->GetFace(), flags, 0, face.get()); if (cairo_font_face_status(font) != CAIRO_STATUS_SUCCESS) { gfxWarning() << "Failed creating Cairo font face for FreeType face"; - if (varFace) { - Factory::ReleaseFTFace(varFace); - } return nullptr; } - if (nfr) { - // Bug 1362117 - Cairo may keep the font face alive after the owning - // NativeFontResource was freed. To prevent this, we must bind the - // NativeFontResource to the font face so that it stays alive at least as - // long as the font face. - nfr->AddRef(); - cairo_status_t err = CAIRO_STATUS_SUCCESS; - bool cleanupFace = false; - if (varFace) { - err = - cairo_font_face_set_user_data(font, &sFaceKey, varFace, ReleaseFace); - } - - if (err != CAIRO_STATUS_SUCCESS) { - cleanupFace = true; - } else { - err = cairo_font_face_set_user_data(font, &sNativeFontResourceKey, nfr, - ReleaseNativeFontResource); - } - if (err != CAIRO_STATUS_SUCCESS) { - gfxWarning() << "Failed binding NativeFontResource to Cairo font face"; - if (varFace && cleanupFace) { - Factory::ReleaseFTFace(varFace); - } - nfr->Release(); - cairo_font_face_destroy(font); - return nullptr; - } - } - cairo_matrix_t sizeMatrix; cairo_matrix_init(&sizeMatrix, aGlyphSize, 0, 0, aGlyphSize, 0, 0); @@ -198,23 +134,23 @@ already_AddRefed UnscaledFontFreeType::CreateScaledFont( return nullptr; } - RefPtr scaledFont = - new ScaledFontFreeType(cairoScaledFont, face, this, aGlyphSize); + // Only apply variations if we have an explicitly cloned face. + if (aNumVariations > 0 && face != GetFace()) { + ApplyVariationsToFace(aVariations, aNumVariations, face->GetFace()); + } + + RefPtr scaledFont = new ScaledFontFreeType( + cairoScaledFont, std::move(face), this, aGlyphSize); cairo_scaled_font_destroy(cairoScaledFont); - // Only apply variations if we have an explicitly cloned face. Otherwise, - // if the pattern holds the pathname, Cairo will handle setting of variations. - if (varFace) { - ApplyVariationsToFace(aVariations, aNumVariations, varFace); - } - return scaledFont.forget(); } bool ScaledFontFreeType::HasVariationSettings() { // Check if the FT face has been cloned. - return mFace && mFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS && + return mFace && + mFace->GetFace()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS && mFace != static_cast(mUnscaledFont.get())->GetFace(); } diff --git a/gfx/2d/ScaledFontFreeType.h b/gfx/2d/ScaledFontFreeType.h index b3827c2f615a..966fc3212ff6 100644 --- a/gfx/2d/ScaledFontFreeType.h +++ b/gfx/2d/ScaledFontFreeType.h @@ -18,15 +18,19 @@ class ScaledFontFreeType : public ScaledFontBase { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontFreeType, override) - ScaledFontFreeType(cairo_scaled_font_t* aScaledFont, FT_Face aFace, + ScaledFontFreeType(cairo_scaled_font_t* aScaledFont, + RefPtr&& aFace, const RefPtr& aUnscaledFont, Float aSize); FontType GetType() const override { return FontType::FREETYPE; } #ifdef USE_SKIA - virtual SkTypeface* CreateSkTypeface() override; + SkTypeface* CreateSkTypeface() override; + void SetupSkFontDrawOptions(SkFont& aFont) override; #endif + AntialiasMode GetDefaultAAMode() override { return AntialiasMode::GRAY; } + bool CanSerialize() override { return true; } bool GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton) override; @@ -39,7 +43,7 @@ class ScaledFontFreeType : public ScaledFontBase { bool HasVariationSettings() override; private: - FT_Face mFace; + RefPtr mFace; }; } // namespace gfx diff --git a/gfx/2d/ScaledFontMac.cpp b/gfx/2d/ScaledFontMac.cpp index 8bcbdce3f789..374a74c7c7fb 100644 --- a/gfx/2d/ScaledFontMac.cpp +++ b/gfx/2d/ScaledFontMac.cpp @@ -174,6 +174,29 @@ SkTypeface* ScaledFontMac::CreateSkTypeface() { return typeface; } } + +void ScaledFontMac::SetupSkFontDrawOptions(SkFont& aFont) { + aFont.setSubpixel(true); + + // Normally, Skia enables LCD FontSmoothing which creates thicker fonts + // and also enables subpixel AA. CoreGraphics without font smoothing + // explicitly creates thinner fonts and grayscale AA. + // CoreGraphics doesn't support a configuration that produces thicker + // fonts with grayscale AA as LCD Font Smoothing enables or disables + // both. However, Skia supports it by enabling font smoothing (producing + // subpixel AA) and converts it to grayscale AA. Since Skia doesn't + // support subpixel AA on transparent backgrounds, we still want font + // smoothing for the thicker fonts, even if it is grayscale AA. + // + // With explicit Grayscale AA (from -moz-osx-font-smoothing:grayscale), + // we want to have grayscale AA with no smoothing at all. This means + // disabling the LCD font smoothing behaviour. + // To accomplish this we have to explicitly disable hinting, + // and disable LCDRenderText. + if (aFont.getEdging() == SkFont::Edging::kAntiAlias && !mUseFontSmoothing) { + aFont.setHinting(kNo_SkFontHinting); + } +} #endif // private API here are the public options on OS X diff --git a/gfx/2d/ScaledFontMac.h b/gfx/2d/ScaledFontMac.h index 5df41cb9a299..387050654c9e 100644 --- a/gfx/2d/ScaledFontMac.h +++ b/gfx/2d/ScaledFontMac.h @@ -32,6 +32,7 @@ class ScaledFontMac : public ScaledFontBase { FontType GetType() const override { return FontType::MAC; } #ifdef USE_SKIA SkTypeface* CreateSkTypeface() override; + void SetupSkFontDrawOptions(SkFont& aFont) override; #endif already_AddRefed GetPathForGlyphs(const GlyphBuffer& aBuffer, const DrawTarget* aTarget) override; diff --git a/gfx/2d/Types.h b/gfx/2d/Types.h index 6f709faca6dc..e517cef91c3a 100644 --- a/gfx/2d/Types.h +++ b/gfx/2d/Types.h @@ -304,8 +304,6 @@ enum class NativeSurfaceType : int8_t { enum class NativeFontType : int8_t { GDI_LOGFONT, - FREETYPE_FACE, - FONTCONFIG_PATTERN, }; enum class FontStyle : int8_t { NORMAL, ITALIC, BOLD, BOLD_ITALIC }; diff --git a/gfx/2d/UnscaledFontFreeType.cpp b/gfx/2d/UnscaledFontFreeType.cpp index 24262461aad4..ffdf407d0ee2 100644 --- a/gfx/2d/UnscaledFontFreeType.cpp +++ b/gfx/2d/UnscaledFontFreeType.cpp @@ -54,9 +54,11 @@ bool UnscaledFontFreeType::GetFontFileData(FontFileDataOutput aDataCallback, 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) { + if (FT_Load_Sfnt_Table(mFace->GetFace(), 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) { + if (FT_Load_Sfnt_Table(mFace->GetFace(), 0, 0, fontData, &length) == + FT_Err_Ok) { aDataCallback(fontData, length, 0, aBaton); success = true; } @@ -87,6 +89,21 @@ bool UnscaledFontFreeType::GetWRFontDescriptor(WRFontDescriptorOutput aCb, return true; } +RefPtr UnscaledFontFreeType::InitFace() { + if (mFace) { + return mFace; + } + if (mFile.empty()) { + return nullptr; + } + mFace = Factory::NewSharedFTFace(nullptr, mFile.c_str(), mIndex); + if (!mFace) { + gfxWarning() << "Failed initializing FreeType face from filename"; + return nullptr; + } + return mFace; +} + void UnscaledFontFreeType::GetVariationSettingsFromFace( std::vector* aVariations, FT_Face aFace) { if (!aFace || !(aFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) { diff --git a/gfx/2d/UnscaledFontFreeType.h b/gfx/2d/UnscaledFontFreeType.h index fa9d0ca5f90e..696cb560ce5d 100644 --- a/gfx/2d/UnscaledFontFreeType.h +++ b/gfx/2d/UnscaledFontFreeType.h @@ -20,34 +20,20 @@ class ScaledFontFontconfig; class UnscaledFontFreeType : public UnscaledFont { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontFreeType, override) - 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) {} - explicit UnscaledFontFreeType(std::string&& aFile, uint32_t aIndex = 0) - : mFace(nullptr), - mOwnsFace(false), - mFile(std::move(aFile)), - mIndex(aIndex) {} - UnscaledFontFreeType(FT_Face aFace, NativeFontResource* aNativeFontResource) - : mFace(aFace), - mOwnsFace(false), - mIndex(0), - mNativeFontResource(aNativeFontResource) {} - virtual ~UnscaledFontFreeType() { - if (mOwnsFace) { - Factory::ReleaseFTFace(mFace); - } - } + explicit UnscaledFontFreeType(const RefPtr& aFace) + : mFace(aFace), mIndex(0) {} + explicit UnscaledFontFreeType(const char* aFile, uint32_t aIndex = 0, + RefPtr aFace = nullptr) + : mFace(std::move(aFace)), mFile(aFile), mIndex(aIndex) {} + explicit UnscaledFontFreeType(std::string&& aFile, uint32_t aIndex = 0, + RefPtr aFace = nullptr) + : mFace(std::move(aFace)), mFile(std::move(aFile)), mIndex(aIndex) {} FontType GetType() const override { return FontType::FREETYPE; } - FT_Face GetFace() const { return mFace; } - const char* GetFile() const { return mFile.c_str(); } + const RefPtr& GetFace() const { return mFace; } + const std::string& GetFile() const { return mFile; } uint32_t GetIndex() const { return mIndex; } - const RefPtr& GetNativeFontResource() const { - return mNativeFontResource; - } bool GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton) override; @@ -55,9 +41,9 @@ class UnscaledFontFreeType : public UnscaledFont { bool GetWRFontDescriptor(WRFontDescriptorOutput aCb, void* aBaton) override; -#ifdef MOZ_WIDGET_ANDROID - FT_Face InitFace(); + RefPtr InitFace(); +#ifdef MOZ_WIDGET_ANDROID already_AddRefed CreateScaledFont( Float aGlyphSize, const uint8_t* aInstanceData, uint32_t aInstanceDataLength, const FontVariation* aVariations, @@ -65,11 +51,9 @@ class UnscaledFontFreeType : public UnscaledFont { #endif protected: - FT_Face mFace; - bool mOwnsFace; + RefPtr mFace; std::string mFile; uint32_t mIndex; - RefPtr mNativeFontResource; friend class ScaledFontFreeType; friend class ScaledFontFontconfig; @@ -85,14 +69,14 @@ class UnscaledFontFreeType : public UnscaledFont { class UnscaledFontFontconfig : public UnscaledFontFreeType { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontFontconfig, override) - explicit UnscaledFontFontconfig(FT_Face aFace, bool aOwnsFace = false) - : UnscaledFontFreeType(aFace, aOwnsFace) {} - explicit UnscaledFontFontconfig(const char* aFile, uint32_t aIndex = 0) - : UnscaledFontFreeType(aFile, aIndex) {} - explicit UnscaledFontFontconfig(std::string&& aFile, uint32_t aIndex = 0) - : UnscaledFontFreeType(std::move(aFile), aIndex) {} - UnscaledFontFontconfig(FT_Face aFace, NativeFontResource* aNativeFontResource) - : UnscaledFontFreeType(aFace, aNativeFontResource) {} + explicit UnscaledFontFontconfig(const RefPtr& aFace) + : UnscaledFontFreeType(aFace) {} + explicit UnscaledFontFontconfig(const char* aFile, uint32_t aIndex = 0, + RefPtr aFace = nullptr) + : UnscaledFontFreeType(aFile, aIndex, std::move(aFace)) {} + explicit UnscaledFontFontconfig(std::string&& aFile, uint32_t aIndex = 0, + RefPtr aFace = nullptr) + : UnscaledFontFreeType(std::move(aFile), aIndex, std::move(aFace)) {} FontType GetType() const override { return FontType::FONTCONFIG; }