Skip to content

Commit

Permalink
Bug 1547063 - add SharedFTFace abstraction of FT_Face. r=jfkthame
Browse files Browse the repository at this point in the history
  • Loading branch information
lsalzman committed Sep 16, 2019
1 parent baed4ec commit bc38074
Show file tree
Hide file tree
Showing 20 changed files with 623 additions and 625 deletions.
81 changes: 80 additions & 1 deletion gfx/2d/2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ typedef FT_FaceRec_* FT_Face;

typedef int FT_Error;

struct _FcPattern;
typedef _FcPattern FcPattern;

struct ID3D11Texture2D;
struct ID3D11Device;
struct ID2D1Device;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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; }

Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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);
Expand Down
73 changes: 4 additions & 69 deletions gfx/2d/DrawTargetSkia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 0 additions & 2 deletions gfx/2d/DrawTargetSkia.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
87 changes: 68 additions & 19 deletions gfx/2d/Factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

void mozilla_ReleaseSharedFTFace(void* aContext) {
if (aContext) {
static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Release();
}
}

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_LockSharedFTFace(void* aContext) {
static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Lock();
}

void mozilla_ReleaseFTFace(FT_Face aFace) {
mozilla::gfx::Factory::ReleaseFTFace(aFace);
void mozilla_UnlockSharedFTFace(void* aContext) {
static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Unlock();
}

FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex,
Expand Down Expand Up @@ -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.";
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
5 changes: 0 additions & 5 deletions gfx/2d/HelpersWinFonts.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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:
Expand Down
Loading

0 comments on commit bc38074

Please sign in to comment.