зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
bd229a5c73
Коммит
2d38529fad
81
gfx/2d/2D.h
81
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<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; }
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче