Bug 1547063 - add SharedFTFace abstraction of FT_Face. r=jfkthame

Differential Revision: https://phabricator.services.mozilla.com/D44491

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Lee Salzman 2019-09-16 17:03:04 +00:00
Родитель bd229a5c73
Коммит 2d38529fad
20 изменённых файлов: 627 добавлений и 629 удалений

Просмотреть файл

@ -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<SharedFTFace> 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 T>
class SharedFTFaceRefCountedData : public SharedFTFaceData {
public:
void BindData() { static_cast<T*>(this)->AddRef(); }
void ReleaseData() { static_cast<T*>(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<SharedFTFace> {
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<UnscaledFont> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFont)
@ -813,7 +873,7 @@ class ScaledFont : public SupportsThreadSafeWeakPtr<ScaledFont> {
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<ScaledFont> CreateScaledFontForFontconfigFont(
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace> aFace,
FcPattern* aPattern);
#endif
#ifdef MOZ_WIDGET_ANDROID
static already_AddRefed<ScaledFont> CreateScaledFontForFreeTypeFont(
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace> 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<SharedFTFace> 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<SharedFTFace> 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);

Просмотреть файл

@ -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<ScaledFontDWrite*>(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;

Просмотреть файл

@ -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,

Просмотреть файл

@ -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<mozilla::gfx::SharedFTFace*>(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<mozilla::gfx::SharedFTFace*>(aContext)->Release();
}
}
void mozilla_ReleaseFTFace(FT_Face aFace) {
mozilla::gfx::Factory::ReleaseFTFace(aFace);
void mozilla_LockSharedFTFace(void* aContext) {
static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Lock();
}
void mozilla_UnlockSharedFTFace(void* aContext) {
static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Unlock();
}
FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex,
@ -554,16 +559,6 @@ already_AddRefed<ScaledFont> Factory::CreateScaledFontForNativeFont(
# endif
return font.forget();
}
#elif defined(MOZ_WIDGET_GTK)
case NativeFontType::FONTCONFIG_PATTERN:
return MakeAndAddRef<ScaledFontFontconfig>(
aScaledFont, static_cast<FcPattern*>(aNativeFont.mFont),
aUnscaledFont, aSize);
#elif defined(MOZ_WIDGET_ANDROID)
case NativeFontType::FREETYPE_FACE:
return MakeAndAddRef<ScaledFontFreeType>(
aScaledFont, static_cast<FT_Face>(aNativeFont.mFont), aUnscaledFont,
aSize);
#endif
default:
gfxWarning() << "Invalid native font type specified.";
@ -634,6 +629,25 @@ already_AddRefed<ScaledFont> Factory::CreateScaledFontForMacFont(
}
#endif
#ifdef MOZ_WIDGET_GTK
already_AddRefed<ScaledFont> Factory::CreateScaledFontForFontconfigFont(
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace> aFace,
FcPattern* aPattern) {
return MakeAndAddRef<ScaledFontFontconfig>(aScaledFont, std::move(aFace),
aPattern, aUnscaledFont, aSize);
}
#endif
#ifdef MOZ_WIDGET_ANDROID
already_AddRefed<ScaledFont> Factory::CreateScaledFontForFreeTypeFont(
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize,
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace> aFace) {
return MakeAndAddRef<ScaledFontFreeType>(aScaledFont, std::move(aFace),
aUnscaledFont, aSize);
}
#endif
already_AddRefed<DrawTarget> 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<SharedFTFace> Factory::NewSharedFTFace(FT_Library aFTLibrary,
const char* aFilename,
int aFaceIndex) {
if (FT_Face face = NewFTFace(aFTLibrary, aFilename, aFaceIndex)) {
return MakeAndAddRef<SharedFTFace>(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<SharedFTFace> 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<SharedFTFace>(face, aSharedData);
} else {
return nullptr;
}
}
void Factory::ReleaseFTFace(FT_Face aFace) {
StaticMutexAutoLock lock(mFTLock);
FT_Done_Face(aFace);

Просмотреть файл

@ -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:

Просмотреть файл

@ -12,15 +12,13 @@ namespace mozilla {
namespace gfx {
NativeFontResourceFreeType::NativeFontResourceFreeType(
UniquePtr<uint8_t[]>&& aFontData, uint32_t aDataLength, FT_Face aFace)
: mFontData(std::move(aFontData)), mDataLength(aDataLength), mFace(aFace) {}
UniquePtr<uint8_t[]>&& 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 <class T>
already_AddRefed<T> NativeFontResourceFreeType::CreateInternal(
@ -34,18 +32,7 @@ already_AddRefed<T> 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<T> resource = new T(std::move(fontData), aDataLength, face);
RefPtr<T> resource = new T(std::move(fontData), aDataLength, aFTLibrary);
return resource.forget();
}
@ -59,26 +46,40 @@ already_AddRefed<NativeFontResourceFreeType> NativeFontResourceFreeType::Create(
already_AddRefed<UnscaledFont> NativeFontResourceFreeType::CreateUnscaledFont(
uint32_t aIndex, const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) {
RefPtr<UnscaledFont> unscaledFont = new UnscaledFontFreeType(mFace, this);
return unscaledFont.forget();
if (RefPtr<SharedFTFace> face = CloneFace()) {
return MakeAndAddRef<UnscaledFontFreeType>(std::move(face));
}
return nullptr;
}
#endif
FT_Face NativeFontResourceFreeType::CloneFace() {
return Factory::NewFTFaceFromData(mFace->glyph->library, mFontData.get(),
mDataLength, 0);
already_AddRefed<SharedFTFace> NativeFontResourceFreeType::CloneFace(
int aFaceIndex) {
RefPtr<SharedFTFace> 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<uint8_t[]>&& aFontData, uint32_t aDataLength, FT_Face aFace)
: NativeFontResourceFreeType(std::move(aFontData), aDataLength, aFace) {}
UniquePtr<uint8_t[]>&& aFontData, uint32_t aDataLength,
FT_Library aFTLibrary)
: NativeFontResourceFreeType(std::move(aFontData), aDataLength,
aFTLibrary) {}
already_AddRefed<UnscaledFont> NativeFontResourceFontconfig::CreateUnscaledFont(
uint32_t aIndex, const uint8_t* aInstanceData,
uint32_t aInstanceDataLength) {
RefPtr<UnscaledFont> unscaledFont = new UnscaledFontFontconfig(mFace, this);
return unscaledFont.forget();
if (RefPtr<SharedFTFace> face = CloneFace()) {
return MakeAndAddRef<UnscaledFontFontconfig>(std::move(face));
}
return nullptr;
}
already_AddRefed<NativeFontResourceFontconfig>

Просмотреть файл

@ -15,7 +15,9 @@
namespace mozilla {
namespace gfx {
class NativeFontResourceFreeType : public NativeFontResource {
class NativeFontResourceFreeType
: public NativeFontResource,
public SharedFTFaceRefCountedData<NativeFontResourceFreeType> {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceFreeType, override)
@ -31,11 +33,12 @@ class NativeFontResourceFreeType : public NativeFontResource {
~NativeFontResourceFreeType();
FT_Face CloneFace();
already_AddRefed<SharedFTFace> CloneFace(int aFaceIndex = 0) override;
protected:
NativeFontResourceFreeType(UniquePtr<uint8_t[]>&& aFontData,
uint32_t aDataLength, FT_Face aFace);
uint32_t aDataLength,
FT_Library aFTLibrary = nullptr);
template <class T>
static already_AddRefed<T> CreateInternal(uint8_t* aFontData,
@ -44,7 +47,7 @@ class NativeFontResourceFreeType : public NativeFontResource {
UniquePtr<uint8_t[]> 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<uint8_t[]>&& aFontData,
uint32_t aDataLength, FT_Face aFace);
uint32_t aDataLength,
FT_Library aFTLibrary = nullptr);
};
#endif

Просмотреть файл

@ -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<uint32_t> 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<SkTypeface>(mTypeface);

Просмотреть файл

@ -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

Просмотреть файл

@ -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,

Просмотреть файл

@ -74,6 +74,7 @@ class ScaledFontDWrite final : public ScaledFontBase {
#ifdef USE_SKIA
SkTypeface* CreateSkTypeface() override;
void SetupSkFontDrawOptions(SkFont& aFont) override;
SkFontStyle mStyle;
#endif

Просмотреть файл

@ -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 <fontconfig/fcfreetype.h>
#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<UnscaledFont>& aUnscaledFont, Float aSize)
: ScaledFontBase(aUnscaledFont, aSize), mPattern(aPattern) {
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace>&& aFace,
FcPattern* aPattern, const RefPtr<UnscaledFont>& 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<SharedFTFace>&& aFace,
const InstanceData& aInstanceData,
const RefPtr<UnscaledFont>& 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<FontVariation> 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<uint8_t*>(&instance), sizeof(instance),
aCb(reinterpret_cast<uint8_t*>(&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<NativeFontResource*>(aData)->Release();
}
static cairo_user_data_key_t sFaceKey;
static void ReleaseFace(void* aData) {
Factory::ReleaseFTFace(static_cast<FT_Face>(aData));
}
already_AddRefed<ScaledFont> UnscaledFontFontconfig::CreateScaledFont(
Float aSize, const uint8_t* aInstanceData, uint32_t aInstanceDataLength,
const FontVariation* aVariations, uint32_t aNumVariations) {
@ -456,86 +468,38 @@ already_AddRefed<ScaledFont> UnscaledFontFontconfig::CreateScaledFont(
*reinterpret_cast<const ScaledFontFontconfig::InstanceData*>(
aInstanceData);
FcPattern* pattern = FcPatternCreate();
if (!pattern) {
gfxWarning() << "Failed initializing Fontconfig pattern for scaled font";
RefPtr<SharedFTFace> face(InitFace());
if (!face) {
gfxWarning() << "Attempted to deserialize Fontconfig scaled font without "
"FreeType face";
return nullptr;
}
FT_Face face = GetFace();
NativeFontResourceFreeType* nfr =
static_cast<NativeFontResourceFreeType*>(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<SharedFTFace> varFace = face->GetData()->CloneFace()) {
face = varFace;
}
FcPatternAddFTFace(pattern, FC_FT_FACE, varFace ? varFace : face);
} else {
FcPatternAddString(pattern, FC_FILE,
reinterpret_cast<const FcChar8*>(GetFile()));
FcPatternAddInteger(pattern, FC_INDEX, GetIndex());
}
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize);
instanceData.SetupPattern(pattern);
StackArray<FT_Fixed, 32> 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<ScaledFont> 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<ScaledFontFontconfig> 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<ScaledFontFontconfig> 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<ScaledFont> 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<UnscaledFontFontconfig*>(mUnscaledFont.get())
->GetFace();
return mFace &&
mFace->GetFace()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS &&
mFace != static_cast<UnscaledFontFontconfig*>(mUnscaledFont.get())
->GetFace();
}
already_AddRefed<UnscaledFont> UnscaledFontFontconfig::CreateFromFontDescriptor(

Просмотреть файл

@ -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<SharedFTFace>&& aFace, FcPattern* aPattern,
const RefPtr<UnscaledFont>& 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<SharedFTFace>&& aFace,
const InstanceData& aInstanceData,
const RefPtr<UnscaledFont>& aUnscaledFont, Float aSize);
RefPtr<SharedFTFace> mFace;
InstanceData mInstanceData;
};
} // namespace gfx

Просмотреть файл

@ -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<SharedFTFace>&& aFace,
const RefPtr<UnscaledFont>& 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<FontVariation> 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<NativeFontResource*>(aData)->Release();
}
static cairo_user_data_key_t sFaceKey;
static void ReleaseFace(void* aData) {
Factory::ReleaseFTFace(static_cast<FT_Face>(aData));
}
already_AddRefed<ScaledFont> UnscaledFontFreeType::CreateScaledFont(
Float aGlyphSize, const uint8_t* aInstanceData,
uint32_t aInstanceDataLength, const FontVariation* aVariations,
uint32_t aNumVariations) {
FT_Face face = InitFace();
RefPtr<SharedFTFace> face(InitFace());
if (!face) {
gfxWarning() << "Attempted to deserialize FreeType scaled font without "
"FreeType face";
return nullptr;
}
NativeFontResourceFreeType* nfr =
static_cast<NativeFontResourceFreeType*>(mNativeFontResource.get());
FT_Face varFace = nullptr;
if (nfr && aNumVariations > 0) {
varFace = nfr->CloneFace();
if (varFace) {
if (aNumVariations > 0 && face->GetData()) {
if (RefPtr<SharedFTFace> varFace = face->GetData()->CloneFace()) {
face = varFace;
} else {
gfxWarning() << "Failed cloning face for variations";
}
}
StackArray<FT_Fixed, 32> 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<ScaledFont> UnscaledFontFreeType::CreateScaledFont(
return nullptr;
}
RefPtr<ScaledFontFreeType> 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<ScaledFontFreeType> 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<UnscaledFontFreeType*>(mUnscaledFont.get())->GetFace();
}

Просмотреть файл

@ -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<SharedFTFace>&& aFace,
const RefPtr<UnscaledFont>& 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<SharedFTFace> mFace;
};
} // namespace gfx

Просмотреть файл

@ -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

Просмотреть файл

@ -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<Path> GetPathForGlyphs(const GlyphBuffer& aBuffer,
const DrawTarget* aTarget) override;

Просмотреть файл

@ -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 };

Просмотреть файл

@ -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<SharedFTFace> 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<FontVariation>* aVariations, FT_Face aFace) {
if (!aFace || !(aFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {

Просмотреть файл

@ -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<SharedFTFace>& aFace)
: mFace(aFace), mIndex(0) {}
explicit UnscaledFontFreeType(const char* aFile, uint32_t aIndex = 0,
RefPtr<SharedFTFace> aFace = nullptr)
: mFace(std::move(aFace)), mFile(aFile), mIndex(aIndex) {}
explicit UnscaledFontFreeType(std::string&& aFile, uint32_t aIndex = 0,
RefPtr<SharedFTFace> 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<SharedFTFace>& GetFace() const { return mFace; }
const std::string& GetFile() const { return mFile; }
uint32_t GetIndex() const { return mIndex; }
const RefPtr<NativeFontResource>& 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<SharedFTFace> InitFace();
#ifdef MOZ_WIDGET_ANDROID
already_AddRefed<ScaledFont> 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<SharedFTFace> mFace;
std::string mFile;
uint32_t mIndex;
RefPtr<NativeFontResource> 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<SharedFTFace>& aFace)
: UnscaledFontFreeType(aFace) {}
explicit UnscaledFontFontconfig(const char* aFile, uint32_t aIndex = 0,
RefPtr<SharedFTFace> aFace = nullptr)
: UnscaledFontFreeType(aFile, aIndex, std::move(aFace)) {}
explicit UnscaledFontFontconfig(std::string&& aFile, uint32_t aIndex = 0,
RefPtr<SharedFTFace> aFace = nullptr)
: UnscaledFontFreeType(std::move(aFile), aIndex, std::move(aFace)) {}
FontType GetType() const override { return FontType::FONTCONFIG; }