Bug 1547063 - Use SharedFTFace locking instead of Cairo locking. r=jfkthame

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Lee Salzman 2019-09-15 03:01:02 +00:00
Родитель b8b94ba41a
Коммит 1ad0ba9769
20 изменённых файлов: 185 добавлений и 203 удалений

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

@ -795,14 +795,30 @@ class SharedFTFace : public external::AtomicRefCounted<SharedFTFace> {
FT_Face GetFace() const { return mFace; }
SharedFTFaceData* GetData() const { return mData; }
void Lock() { mLock.Lock(); }
bool TryLock() { return mLock.TryLock(); }
/** Locks the face for exclusive access by a given owner. Returns true if
* the given owner is acquiring the lock for the first time, and false if
* the owner was the prior owner of the lock. Thus the return value can be
* used to do owner-specific initialization of the FT face such as setting
* a size or transform that may have been invalidated by a previous owner.
* If no owner is given, then the user should avoid modify any state on
* the face so as not to invalidate the prior owner's modification.
*/
bool Lock(void* aOwner = nullptr) {
mLock.Lock();
if (mLockOwner == aOwner || !aOwner) {
return true;
} else {
mLockOwner = aOwner;
return false;
}
}
void Unlock() { mLock.Unlock(); }
private:
FT_Face mFace;
SharedFTFaceData* mData;
Mutex mLock;
void* mLockOwner;
};
#endif

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

@ -169,8 +169,8 @@ void mozilla_ReleaseSharedFTFace(void* aContext) {
}
}
void mozilla_LockSharedFTFace(void* aContext) {
static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Lock();
int mozilla_LockSharedFTFace(void* aContext, void* aOwner) {
return int(static_cast<mozilla::gfx::SharedFTFace*>(aContext)->Lock(aOwner));
}
void mozilla_UnlockSharedFTFace(void* aContext) {
@ -678,7 +678,10 @@ bool Factory::GetBGRSubpixelOrder() { return mBGRSubpixelOrder; }
#ifdef MOZ_ENABLE_FREETYPE
SharedFTFace::SharedFTFace(FT_Face aFace, SharedFTFaceData* aData)
: mFace(aFace), mData(aData), mLock("SharedFTFace::mLock") {
: mFace(aFace),
mData(aData),
mLock("SharedFTFace::mLock"),
mLockOwner(nullptr) {
if (mData) {
mData->BindData();
}

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

@ -55,8 +55,7 @@ SkTypeface* ScaledFontFontconfig::CreateSkTypeface() {
: (mInstanceData.mFlags & InstanceData::LCD_VERTICAL
? kRGB_V_SkPixelGeometry
: kRGB_H_SkPixelGeometry);
return SkCreateTypefaceFromCairoFTFont(mScaledFont, mFace->GetFace(),
mFace.get(), geo,
return SkCreateTypefaceFromCairoFTFont(mFace->GetFace(), mFace.get(), geo,
mInstanceData.mLcdFilter);
}

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

@ -32,8 +32,7 @@ ScaledFontFreeType::ScaledFontFreeType(
#ifdef USE_SKIA
SkTypeface* ScaledFontFreeType::CreateSkTypeface() {
return SkCreateTypefaceFromCairoFTFont(mScaledFont, mFace->GetFace(),
mFace.get());
return SkCreateTypefaceFromCairoFTFont(mFace->GetFace(), mFace.get());
}
void ScaledFontFreeType::SetupSkFontDrawOptions(SkFont& aFont) {

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

@ -107,14 +107,21 @@ static setLcdFilterFunc setLcdFilter;
extern void mozilla_AddRefSharedFTFace(void* aContext);
extern void mozilla_ReleaseSharedFTFace(void* aContext);
extern void mozilla_LockSharedFTFace(void* aContext);
/* Returns true if the face's state has been modifide by another owner. */
extern int mozilla_LockSharedFTFace(void* aContext, void* aOwner);
extern void mozilla_UnlockSharedFTFace(void* aContext);
extern FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags);
extern void mozilla_LockFTLibrary(FT_Library aFTLibrary);
extern void mozilla_UnlockFTLibrary(FT_Library aFTLibrary);
#define CAIRO_FT_LOCK(unscaled) ((unscaled)->face_context ? mozilla_LockSharedFTFace((unscaled)->face_context) : (void)CAIRO_MUTEX_LOCK((unscaled)->mutex))
#define CAIRO_FT_UNLOCK(unscaled) ((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled)->face_context) : (void)CAIRO_MUTEX_UNLOCK((unscaled)->mutex))
#define CAIRO_FT_LOCK(unscaled) \
((unscaled)->face_context \
? (void)mozilla_LockSharedFTFace((unscaled)->face_context, NULL) \
: (void)CAIRO_MUTEX_LOCK((unscaled)->mutex))
#define CAIRO_FT_UNLOCK(unscaled) \
((unscaled)->face_context \
? mozilla_UnlockSharedFTFace((unscaled)->face_context) \
: (void)CAIRO_MUTEX_UNLOCK((unscaled)->mutex))
/**
* SECTION:cairo-ft
@ -666,7 +673,13 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
FT_Face face = NULL;
FT_Error error;
CAIRO_FT_LOCK (unscaled);
if (unscaled->face_context) {
if (!mozilla_LockSharedFTFace(unscaled->face_context, unscaled)) {
unscaled->have_scale = FALSE;
}
} else {
CAIRO_FT_LOCK(unscaled);
}
unscaled->lock_count++;
if (unscaled->face)
@ -3354,8 +3367,7 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
* opportunity for creating deadlock. This is obviously unsafe,
* but as documented, the user must add manual locking when using
* this function. */
// BEWARE: Mozilla's tree Cairo keeps the lock across calls for thread-safety.
// CAIRO_FT_UNLOCK (scaled_font->unscaled);
CAIRO_FT_UNLOCK(scaled_font->unscaled);
return face;
}
@ -3386,8 +3398,7 @@ cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
* cairo_ft_scaled_font_lock_face, so we have to acquire it again
* as _cairo_ft_unscaled_font_unlock_face expects it to be held
* when we call into it. */
// BEWARE: Mozilla's tree Cairo keeps the lock across calls for thread-safety.
//CAIRO_FT_LOCK (scaled_font->unscaled);
CAIRO_FT_LOCK(scaled_font->unscaled);
_cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
}

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

@ -1,15 +1,18 @@
#ifndef SkTypeface_cairo_DEFINED
#define SkTypeface_cairo_DEFINED
#include <cairo.h>
#include <cairo-ft.h>
#include "SkTypeface.h"
#include "SkSurfaceProps.h"
struct FT_FaceRec_;
typedef FT_FaceRec_* FT_Face;
SK_API extern void SkInitCairoFT(bool fontHintingEnabled);
SK_API extern SkTypeface* SkCreateTypefaceFromCairoFTFont(cairo_scaled_font_t* scaledFont, FT_Face face = nullptr, void* faceContext = nullptr, SkPixelGeometry pixelGeometry = kUnknown_SkPixelGeometry, uint8_t lcdFilter = 0);
SK_API extern SkTypeface* SkCreateTypefaceFromCairoFTFont(
FT_Face face = nullptr, void* faceContext = nullptr,
SkPixelGeometry pixelGeometry = kUnknown_SkPixelGeometry,
uint8_t lcdFilter = 0);
#endif

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

@ -6,9 +6,6 @@
* found in the LICENSE file.
*/
#include "cairo.h"
#include "cairo-ft.h"
#include "SkFontHost_FreeType_common.h"
#include "SkAdvancedTypefaceMetrics.h"
@ -69,7 +66,7 @@ extern "C"
void mozilla_UnlockFTLibrary(FT_Library aLibrary);
void mozilla_AddRefSharedFTFace(void* aContext);
void mozilla_ReleaseSharedFTFace(void* aContext);
void mozilla_LockSharedFTFace(void* aContext);
int mozilla_LockSharedFTFace(void* aContext, void* aOwner);
void mozilla_UnlockSharedFTFace(void* aContext);
FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags);
}
@ -94,14 +91,25 @@ void SkInitCairoFT(bool fontHintingEnabled)
class SkScalerContext_CairoFT : public SkScalerContext_FreeType_Base {
public:
SkScalerContext_CairoFT(sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects, const SkDescriptor* desc,
cairo_font_face_t* fontFace, SkPixelGeometry pixelGeometry, FT_LcdFilter lcdFilter);
SkScalerContext_CairoFT(sk_sp<SkTypeface> typeface,
const SkScalerContextEffects& effects,
const SkDescriptor* desc, FT_Face face,
void* faceContext, SkPixelGeometry pixelGeometry,
FT_LcdFilter lcdFilter);
virtual ~SkScalerContext_CairoFT();
bool isValid() const {
return fScaledFont != nullptr;
bool isValid() const { return fFTFaceContext != nullptr; }
void Lock() {
if (!mozilla_LockSharedFTFace(fFTFaceContext, this)) {
FT_Set_Transform(fFTFace, fHaveShape ? &fShapeMatrixFT : nullptr, nullptr);
FT_Set_Char_Size(fFTFace, FT_F26Dot6(fScaleX * 64.0f + 0.5f),
FT_F26Dot6(fScaleY * 64.0f + 0.5f), 0, 0);
}
}
void Unlock() { mozilla_UnlockSharedFTFace(fFTFaceContext); }
protected:
virtual unsigned generateGlyphCount() override;
virtual uint16_t generateCharToGlyph(SkUnichar uniChar) override;
@ -115,7 +123,8 @@ private:
bool computeShapeMatrix(const SkMatrix& m);
void prepareGlyph(FT_GlyphSlot glyph);
cairo_scaled_font_t* fScaledFont;
FT_Face fFTFace;
void* fFTFaceContext;
FT_Int32 fLoadGlyphFlags;
FT_LcdFilter fLcdFilter;
SkScalar fScaleX;
@ -125,26 +134,17 @@ private:
bool fHaveShape;
};
class CairoLockedFTFace {
class AutoLockFTFace {
public:
CairoLockedFTFace(cairo_scaled_font_t* scaledFont)
: fScaledFont(scaledFont)
, fFace(cairo_ft_scaled_font_lock_face(scaledFont))
{}
~CairoLockedFTFace()
{
cairo_ft_scaled_font_unlock_face(fScaledFont);
AutoLockFTFace(SkScalerContext_CairoFT* scalerContext)
: fScalerContext(scalerContext) {
fScalerContext->Lock();
}
FT_Face getFace()
{
return fFace;
}
~AutoLockFTFace() { fScalerContext->Unlock(); }
private:
cairo_scaled_font_t* fScaledFont;
FT_Face fFace;
SkScalerContext_CairoFT* fScalerContext;
};
template<typename T> static bool isLCD(const T& rec) {
@ -174,9 +174,9 @@ public:
virtual SkScalerContext* onCreateScalerContext(const SkScalerContextEffects& effects, const SkDescriptor* desc) const override
{
SkScalerContext_CairoFT* ctx =
new SkScalerContext_CairoFT(sk_ref_sp(const_cast<SkCairoFTTypeface*>(this)),
effects, desc, fFontFace, fPixelGeometry, fLcdFilter);
SkScalerContext_CairoFT* ctx = new SkScalerContext_CairoFT(
sk_ref_sp(const_cast<SkCairoFTTypeface*>(this)), effects, desc,
fFTFace, fFTFaceContext, fPixelGeometry, fLcdFilter);
if (!ctx->isValid()) {
delete ctx;
return nullptr;
@ -242,19 +242,18 @@ public:
return 0;
}
SkCairoFTTypeface(cairo_font_face_t* fontFace, FT_Face face, void* faceContext, SkPixelGeometry pixelGeometry, FT_LcdFilter lcdFilter)
SkCairoFTTypeface(FT_Face face, void* faceContext,
SkPixelGeometry pixelGeometry, FT_LcdFilter lcdFilter)
: SkTypeface(SkFontStyle::Normal())
, fFontFace(fontFace)
, fFTFace(face)
, fFTFaceContext(faceContext)
, fPixelGeometry(pixelGeometry)
, fLcdFilter(lcdFilter)
{
mozilla_AddRefSharedFTFace(fFTFaceContext);
cairo_font_face_reference(fFontFace);
}
cairo_font_face_t* GetCairoFontFace() const { return fFontFace; }
void* GetFTFaceContext() const { return fFTFaceContext; }
virtual bool hasColorGlyphs() const override
{
@ -270,52 +269,46 @@ public:
private:
~SkCairoFTTypeface()
{
cairo_font_face_destroy(fFontFace);
mozilla_ReleaseSharedFTFace(fFTFaceContext);
}
cairo_font_face_t* fFontFace;
FT_Face fFTFace;
void* fFTFaceContext;
SkPixelGeometry fPixelGeometry;
FT_LcdFilter fLcdFilter;
};
static bool FindByCairoFontFace(SkTypeface* typeface, void* context) {
return static_cast<SkCairoFTTypeface*>(typeface)->GetCairoFontFace() == static_cast<cairo_font_face_t*>(context);
static bool FindByFTFaceContext(SkTypeface* typeface, void* context) {
return static_cast<SkCairoFTTypeface*>(typeface)->GetFTFaceContext() == context;
}
SkTypeface* SkCreateTypefaceFromCairoFTFont(cairo_scaled_font_t* scaledFont, FT_Face face, void* faceContext, SkPixelGeometry pixelGeometry, uint8_t lcdFilter)
SkTypeface* SkCreateTypefaceFromCairoFTFont(FT_Face face, void* faceContext,
SkPixelGeometry pixelGeometry,
uint8_t lcdFilter)
{
cairo_font_face_t* fontFace = cairo_scaled_font_get_font_face(scaledFont);
SkASSERT(cairo_font_face_status(fontFace) == CAIRO_STATUS_SUCCESS);
SkASSERT(cairo_font_face_get_type(fontFace) == CAIRO_FONT_TYPE_FT);
sk_sp<SkTypeface> typeface = SkTypefaceCache::FindByProcAndRef(FindByCairoFontFace, fontFace);
sk_sp<SkTypeface> typeface =
SkTypefaceCache::FindByProcAndRef(FindByFTFaceContext, faceContext);
if (!typeface) {
typeface = sk_make_sp<SkCairoFTTypeface>(fontFace, face, faceContext, pixelGeometry, (FT_LcdFilter)lcdFilter);
typeface = sk_make_sp<SkCairoFTTypeface>(face, faceContext, pixelGeometry,
(FT_LcdFilter)lcdFilter);
SkTypefaceCache::Add(typeface);
}
return typeface.release();
}
SkScalerContext_CairoFT::SkScalerContext_CairoFT(sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects, const SkDescriptor* desc,
cairo_font_face_t* fontFace, SkPixelGeometry pixelGeometry, FT_LcdFilter lcdFilter)
SkScalerContext_CairoFT::SkScalerContext_CairoFT(
sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
const SkDescriptor* desc, FT_Face face, void* faceContext,
SkPixelGeometry pixelGeometry, FT_LcdFilter lcdFilter)
: SkScalerContext_FreeType_Base(std::move(typeface), effects, desc)
, fFTFace(face)
, fFTFaceContext(faceContext)
, fLcdFilter(lcdFilter)
{
SkMatrix matrix;
fRec.getSingleMatrix(&matrix);
cairo_matrix_t fontMatrix, ctMatrix;
cairo_matrix_init(&fontMatrix, matrix.getScaleX(), matrix.getSkewY(), matrix.getSkewX(), matrix.getScaleY(), 0.0, 0.0);
cairo_matrix_init_identity(&ctMatrix);
cairo_font_options_t *fontOptions = cairo_font_options_create();
fScaledFont = cairo_scaled_font_create(fontFace, &fontMatrix, &ctMatrix, fontOptions);
cairo_font_options_destroy(fontOptions);
computeShapeMatrix(matrix);
FT_Int32 loadFlags = FT_LOAD_DEFAULT;
@ -378,9 +371,7 @@ SkScalerContext_CairoFT::SkScalerContext_CairoFT(sk_sp<SkTypeface> typeface, con
// Disable autohinting when asked to disable hinting, except for "tricky" fonts.
if (!gFontHintingEnabled) {
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
if (face && !(face->face_flags & FT_FACE_FLAG_TRICKY)) {
if (fFTFace && !(fFTFace->face_flags & FT_FACE_FLAG_TRICKY)) {
loadFlags |= FT_LOAD_NO_AUTOHINT;
}
}
@ -401,7 +392,6 @@ SkScalerContext_CairoFT::SkScalerContext_CairoFT(sk_sp<SkTypeface> typeface, con
SkScalerContext_CairoFT::~SkScalerContext_CairoFT()
{
cairo_scaled_font_destroy(fScaledFont);
}
bool SkScalerContext_CairoFT::computeShapeMatrix(const SkMatrix& m)
@ -426,16 +416,14 @@ bool SkScalerContext_CairoFT::computeShapeMatrix(const SkMatrix& m)
minor = SkTMax(minor, 1.0);
// If the font is not scalable, then choose the best available size.
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
if (face && !FT_IS_SCALABLE(face)) {
if (fFTFace && !FT_IS_SCALABLE(fFTFace)) {
double bestDist = DBL_MAX;
FT_Int bestSize = -1;
for (FT_Int i = 0; i < face->num_fixed_sizes; i++) {
for (FT_Int i = 0; i < fFTFace->num_fixed_sizes; i++) {
// Distance is positive if strike is larger than desired size,
// or negative if smaller. If previously a found smaller strike,
// then prefer a larger strike. Otherwise, minimize distance.
double dist = face->available_sizes[i].y_ppem / 64.0 - minor;
double dist = fFTFace->available_sizes[i].y_ppem / 64.0 - minor;
if (bestDist < 0 ? dist >= bestDist : fabs(dist) <= bestDist) {
bestDist = dist;
bestSize = i;
@ -447,11 +435,11 @@ bool SkScalerContext_CairoFT::computeShapeMatrix(const SkMatrix& m)
fHaveShape = false;
return false;
}
major = face->available_sizes[bestSize].x_ppem / 64.0;
minor = face->available_sizes[bestSize].y_ppem / 64.0;
major = fFTFace->available_sizes[bestSize].x_ppem / 64.0;
minor = fFTFace->available_sizes[bestSize].y_ppem / 64.0;
fHaveShape = true;
} else {
fHaveShape = !m.isScaleTranslate();
fHaveShape = !m.isScaleTranslate() || scaleX < 0.0 || scaleY < 0.0;
}
fScaleX = SkDoubleToScalar(major);
@ -472,14 +460,13 @@ bool SkScalerContext_CairoFT::computeShapeMatrix(const SkMatrix& m)
unsigned SkScalerContext_CairoFT::generateGlyphCount()
{
CairoLockedFTFace faceLock(fScaledFont);
return faceLock.getFace()->num_glyphs;
return fFTFace->num_glyphs;
}
uint16_t SkScalerContext_CairoFT::generateCharToGlyph(SkUnichar uniChar)
{
CairoLockedFTFace faceLock(fScaledFont);
return SkToU16(FT_Get_Char_Index(faceLock.getFace(), uniChar));
AutoLockFTFace faceLock(this);
return SkToU16(FT_Get_Char_Index(fFTFace, uniChar));
}
bool SkScalerContext_CairoFT::generateAdvance(SkGlyph* glyph)
@ -498,34 +485,31 @@ void SkScalerContext_CairoFT::prepareGlyph(FT_GlyphSlot glyph)
void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
{
SkASSERT(fScaledFont != nullptr);
glyph->fMaskFormat = fRec.fMaskFormat;
glyph->zeroMetrics();
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
AutoLockFTFace faceLock(this);
FT_Error err = mozilla_LoadFTGlyph( face, glyph->getGlyphID(), fLoadGlyphFlags );
FT_Error err = mozilla_LoadFTGlyph(fFTFace, glyph->getGlyphID(), fLoadGlyphFlags);
if (err != 0) {
return;
}
prepareGlyph(face->glyph);
prepareGlyph(fFTFace->glyph);
glyph->fAdvanceX = SkFDot6ToFloat(face->glyph->advance.x);
glyph->fAdvanceY = -SkFDot6ToFloat(face->glyph->advance.y);
glyph->fAdvanceX = SkFDot6ToFloat(fFTFace->glyph->advance.x);
glyph->fAdvanceY = -SkFDot6ToFloat(fFTFace->glyph->advance.y);
SkIRect bounds;
switch (face->glyph->format) {
switch (fFTFace->glyph->format) {
case FT_GLYPH_FORMAT_OUTLINE:
if (!face->glyph->outline.n_contours) {
if (!fFTFace->glyph->outline.n_contours) {
return;
}
FT_BBox bbox;
FT_Outline_Get_CBox(&face->glyph->outline, &bbox);
FT_Outline_Get_CBox(&fFTFace->glyph->outline, &bbox);
bbox.xMin &= ~63;
bbox.yMin &= ~63;
bbox.xMax = (bbox.xMax + 63) & ~63;
@ -552,7 +536,7 @@ void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
}
break;
case FT_GLYPH_FORMAT_BITMAP:
if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
if (fFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
glyph->fMaskFormat = SkMask::kARGB32_Format;
}
@ -569,10 +553,10 @@ void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
// Apply the shape matrix to the glyph's bounding box.
SkRect srcRect = SkRect::MakeXYWH(
SkIntToScalar(face->glyph->bitmap_left),
-SkIntToScalar(face->glyph->bitmap_top),
SkIntToScalar(face->glyph->bitmap.width),
SkIntToScalar(face->glyph->bitmap.rows));
SkIntToScalar(fFTFace->glyph->bitmap_left),
-SkIntToScalar(fFTFace->glyph->bitmap_top),
SkIntToScalar(fFTFace->glyph->bitmap.width),
SkIntToScalar(fFTFace->glyph->bitmap.rows));
SkRect destRect;
fShapeMatrix.mapRect(&destRect, srcRect);
SkIRect glyphRect = destRect.roundOut();
@ -581,10 +565,10 @@ void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
glyphRect.width(),
glyphRect.height());
} else {
bounds = SkIRect::MakeXYWH(face->glyph->bitmap_left,
-face->glyph->bitmap_top,
face->glyph->bitmap.width,
face->glyph->bitmap.rows);
bounds = SkIRect::MakeXYWH(fFTFace->glyph->bitmap_left,
-fFTFace->glyph->bitmap_top,
fFTFace->glyph->bitmap.width,
fFTFace->glyph->bitmap.rows);
}
break;
default:
@ -602,48 +586,44 @@ void SkScalerContext_CairoFT::generateMetrics(SkGlyph* glyph)
void SkScalerContext_CairoFT::generateImage(const SkGlyph& glyph)
{
SkASSERT(fScaledFont != nullptr);
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
AutoLockFTFace faceLock(this);
FT_Error err = mozilla_LoadFTGlyph(face, glyph.getGlyphID(), fLoadGlyphFlags);
FT_Error err = mozilla_LoadFTGlyph(fFTFace, glyph.getGlyphID(), fLoadGlyphFlags);
if (err != 0) {
memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
return;
}
prepareGlyph(face->glyph);
prepareGlyph(fFTFace->glyph);
bool useLcdFilter =
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE &&
fFTFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE &&
isLCD(glyph) &&
gSetLcdFilter;
if (useLcdFilter) {
mozilla_LockFTLibrary(face->glyph->library);
gSetLcdFilter(face->glyph->library, fLcdFilter);
mozilla_LockFTLibrary(fFTFace->glyph->library);
gSetLcdFilter(fFTFace->glyph->library, fLcdFilter);
}
SkMatrix matrix;
if (face->glyph->format == FT_GLYPH_FORMAT_BITMAP &&
if (fFTFace->glyph->format == FT_GLYPH_FORMAT_BITMAP &&
fHaveShape) {
matrix = fShapeMatrix;
} else {
matrix.setIdentity();
}
generateGlyphImage(face, glyph, matrix);
generateGlyphImage(fFTFace, glyph, matrix);
if (useLcdFilter) {
gSetLcdFilter(face->glyph->library, FT_LCD_FILTER_NONE);
mozilla_UnlockFTLibrary(face->glyph->library);
gSetLcdFilter(fFTFace->glyph->library, FT_LCD_FILTER_NONE);
mozilla_UnlockFTLibrary(fFTFace->glyph->library);
}
}
bool SkScalerContext_CairoFT::generatePath(SkGlyphID glyphID, SkPath* path)
{
SkASSERT(fScaledFont != nullptr);
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
AutoLockFTFace faceLock(this);
SkASSERT(path);
@ -651,16 +631,16 @@ bool SkScalerContext_CairoFT::generatePath(SkGlyphID glyphID, SkPath* path)
flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get the outline
flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline)
FT_Error err = mozilla_LoadFTGlyph(face, glyphID, flags);
FT_Error err = mozilla_LoadFTGlyph(fFTFace, glyphID, flags);
if (err != 0) {
path->reset();
return false;
}
prepareGlyph(face->glyph);
prepareGlyph(fFTFace->glyph);
return generateGlyphPath(face, path);
return generateGlyphPath(fFTFace, path);
}
void SkScalerContext_CairoFT::generateFontMetrics(SkFontMetrics* metrics)

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

@ -246,8 +246,6 @@ gfxFontGroup* gfxAndroidPlatform::CreateFontGroup(
aDevToCssSize);
}
FT_Library gfxAndroidPlatform::GetFTLibrary() { return gPlatformFTLibrary; }
bool gfxAndroidPlatform::FontHintingEnabled() {
// In "mobile" builds, we sometimes use non-reflow-zoom, so we
// might not want hinting. Let's see.

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

@ -50,8 +50,6 @@ class gfxAndroidPlatform : public gfxPlatform {
bool FontHintingEnabled() override;
bool RequiresLinearZoom() override;
FT_Library GetFTLibrary() override;
already_AddRefed<mozilla::gfx::VsyncSource> CreateHardwareVsyncSource()
override;

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

@ -25,20 +25,37 @@ using namespace mozilla::gfx;
gfxFT2FontBase::gfxFT2FontBase(
const RefPtr<UnscaledFontFreeType>& aUnscaledFont,
cairo_scaled_font_t* aScaledFont, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle)
cairo_scaled_font_t* aScaledFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle, gfxFloat aAdjustedSize)
: gfxFont(aUnscaledFont, aFontEntry, aFontStyle, kAntialiasDefault,
aScaledFont),
mFTFace(std::move(aFTFace)),
mSpaceGlyph(0) {
mEmbolden = aFontStyle->NeedsSyntheticBold(aFontEntry);
cairo_scaled_font_reference(mScaledFont);
mAdjustedSize = aAdjustedSize;
InitMetrics();
}
gfxFT2FontBase::~gfxFT2FontBase() { cairo_scaled_font_destroy(mScaledFont); }
FT_Face gfxFT2FontBase::LockFTFace() {
if (!mFTFace->Lock(this)) {
FT_Set_Transform(mFTFace->GetFace(), nullptr, nullptr);
gfxFloat size = std::max(GetAdjustedSize(), 1.0);
FT_Set_Char_Size(mFTFace->GetFace(), FT_F26Dot6(size * 64.0 + 0.5),
FT_F26Dot6(size * 64.0 + 0.5), 0, 0);
}
return mFTFace->GetFace();
}
void gfxFT2FontBase::UnlockFTFace() { mFTFace->Unlock(); }
uint32_t gfxFT2FontBase::GetGlyph(uint32_t aCharCode) {
// FcFreeTypeCharIndex needs to lock the FT_Face and can end up searching
// through all the postscript glyph names in the font. Therefore use a
@ -183,7 +200,7 @@ void gfxFT2FontBase::InitMetrics() {
// Explicitly lock the face so we can release it early before calling
// back into Cairo below.
FT_Face face = cairo_ft_scaled_font_lock_face(GetCairoScaledFont());
FT_Face face = LockFTFace();
if (MOZ_UNLIKELY(!face)) {
// No face. This unfortunate situation might happen if the font
@ -358,7 +375,7 @@ void gfxFT2FontBase::InitMetrics() {
// Release the face lock to safely load glyphs with GetCharExtents if
// necessary without recursively locking.
cairo_ft_scaled_font_unlock_face(GetCairoScaledFont());
UnlockFTFace();
gfxFloat width;
mSpaceGlyph = GetCharWidth(' ', &width);

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

@ -18,8 +18,9 @@ class gfxFT2FontBase : public gfxFont {
public:
gfxFT2FontBase(
const RefPtr<mozilla::gfx::UnscaledFontFreeType>& aUnscaledFont,
cairo_scaled_font_t* aScaledFont, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle);
cairo_scaled_font_t* aScaledFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle, gfxFloat aAdjustedSize = 0.0);
virtual ~gfxFT2FontBase();
uint32_t GetGlyph(uint32_t aCharCode);
@ -39,6 +40,9 @@ class gfxFT2FontBase : public gfxFont {
const nsTArray<gfxFontVariation>& aVariations,
FT_Face aFTFace);
FT_Face LockFTFace();
void UnlockFTFace();
private:
uint32_t GetCharExtents(char aChar, cairo_text_extents_t* aExtents);
uint32_t GetCharWidth(char aChar, gfxFloat* aWidth);
@ -53,6 +57,8 @@ class gfxFT2FontBase : public gfxFont {
protected:
const Metrics& GetHorizontalMetrics() override;
RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
uint32_t mSpaceGlyph;
Metrics mMetrics;
bool mEmbolden;

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

@ -156,9 +156,9 @@ gfxFT2Font::gfxFT2Font(const RefPtr<UnscaledFontFreeType>& aUnscaledFont,
cairo_scaled_font_t* aCairoFont,
RefPtr<mozilla::gfx::SharedFTFace>&& aFTFace,
FT2FontEntry* aFontEntry, const gfxFontStyle* aFontStyle)
: gfxFT2FontBase(aUnscaledFont, aCairoFont, aFontEntry, aFontStyle),
mCharGlyphCache(32),
mFTFace(std::move(aFTFace)) {
: gfxFT2FontBase(aUnscaledFont, aCairoFont, std::move(aFTFace), aFontEntry,
aFontStyle),
mCharGlyphCache(32) {
NS_ASSERTION(mFontEntry,
"Unable to find font entry for font. Something is whack.");
// TODO: use FreeType emboldening instead of multi-strike?

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

@ -74,7 +74,6 @@ class gfxFT2Font : public gfxFT2FontBase {
CharGlyphMapEntryType;
typedef nsTHashtable<CharGlyphMapEntryType> CharGlyphMap;
CharGlyphMap mCharGlyphCache;
RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
};
#endif /* GFX_FT2FONTS_H */

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

@ -29,11 +29,10 @@ typedef struct FT_FaceRec_* FT_Face;
class MOZ_STACK_CLASS gfxFT2LockedFace {
public:
explicit gfxFT2LockedFace(gfxFT2FontBase* aFont)
: mGfxFont(aFont),
mFace(cairo_ft_scaled_font_lock_face(aFont->GetCairoScaledFont())) {}
: mGfxFont(aFont), mFace(aFont->LockFTFace()) {}
~gfxFT2LockedFace() {
if (mFace) {
cairo_ft_scaled_font_unlock_face(mGfxFont->GetCairoScaledFont());
mGfxFont->UnlockFTFace();
}
}

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

@ -91,8 +91,6 @@ static const char* ToCharPtr(const FcChar8* aStr) {
return reinterpret_cast<const char*>(aStr);
}
FT_Library gfxFcPlatformFontList::sCairoFTLibrary = nullptr;
// canonical name ==> first en name or first name if no en name
// This is the required logic for fullname lookups as per CSS3 Fonts spec.
static uint32_t FindCanonicalNameIndex(FcPattern* aFont,
@ -1348,10 +1346,9 @@ gfxFontconfigFont::gfxFontconfigFont(
cairo_scaled_font_t* aScaledFont, RefPtr<SharedFTFace>&& aFTFace,
FcPattern* aPattern, gfxFloat aAdjustedSize, gfxFontEntry* aFontEntry,
const gfxFontStyle* aFontStyle)
: gfxFT2FontBase(aUnscaledFont, aScaledFont, aFontEntry, aFontStyle),
mFTFace(std::move(aFTFace)),
: gfxFT2FontBase(aUnscaledFont, aScaledFont, std::move(aFTFace), aFontEntry,
aFontStyle, aAdjustedSize),
mPattern(aPattern) {
mAdjustedSize = aAdjustedSize;
}
gfxFontconfigFont::~gfxFontconfigFont() {}
@ -2218,43 +2215,6 @@ void gfxFcPlatformFontList::ClearLangGroupPrefFonts() {
mAlwaysUseFontconfigGenerics = PrefFontListsUseOnlyGenerics();
}
/* static */
FT_Library gfxFcPlatformFontList::GetFTLibrary() {
if (!sCairoFTLibrary) {
// Use cairo's FT_Library so that cairo takes care of shutdown of the
// FT_Library after it has destroyed its font_faces, and FT_Done_Face
// has been called on each FT_Face, at least until this bug is fixed:
// https://bugs.freedesktop.org/show_bug.cgi?id=18857
//
// Cairo keeps it's own FT_Library object for creating FT_Face
// instances, so use that. There's no simple API for accessing this
// so use the hacky method below of making a font and extracting
// the library pointer from that.
FcPattern* pat =
FcPatternBuild(0, FC_FAMILY, FcTypeString, "serif", (char*)0);
cairo_font_face_t* face = cairo_ft_font_face_create_for_pattern(pat);
FcPatternDestroy(pat);
cairo_matrix_t identity;
cairo_matrix_init_identity(&identity);
cairo_font_options_t* options = cairo_font_options_create();
cairo_scaled_font_t* sf =
cairo_scaled_font_create(face, &identity, &identity, options);
cairo_font_options_destroy(options);
cairo_font_face_destroy(face);
FT_Face ft = cairo_ft_scaled_font_lock_face(sf);
sCairoFTLibrary = ft->glyph->library;
cairo_ft_scaled_font_unlock_face(sf);
cairo_scaled_font_destroy(sf);
}
return sCairoFTLibrary;
}
gfxPlatformFontList::PrefFontList* gfxFcPlatformFontList::FindGenericFamilies(
const nsCString& aGeneric, nsAtom* aLanguage) {
// set up name

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

@ -220,7 +220,6 @@ class gfxFontconfigFont : public gfxFT2FontBase {
private:
virtual ~gfxFontconfigFont();
RefPtr<mozilla::gfx::SharedFTFace> mFTFace;
nsCountedRef<FcPattern> mPattern;
};
@ -286,8 +285,6 @@ class gfxFcPlatformFontList : public gfxPlatformFontList {
void GetSampleLangForGroup(nsAtom* aLanguage, nsACString& aLangStr,
bool aForFontEnumerationThread = false);
static FT_Library GetFTLibrary();
protected:
virtual ~gfxFcPlatformFontList();
@ -360,7 +357,7 @@ class gfxFcPlatformFontList : public gfxPlatformFontList {
// Note: langGroup == x-math is handled separately
bool mAlwaysUseFontconfigGenerics;
static FT_Library sCairoFTLibrary;
static FT_Library sFTLibrary;
};
#endif /* GFXPLATFORMFONTLIST_H_ */

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

@ -1013,10 +1013,6 @@ void gfxPlatform::Init() {
gPlatform->ComputeTileSize();
#ifdef MOZ_ENABLE_FREETYPE
Factory::SetFTLibrary(gPlatform->GetFTLibrary());
#endif
gPlatform->mHasVariationFontSupport = gPlatform->CheckVariationFontSupport();
nsresult rv;

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

@ -720,8 +720,6 @@ class gfxPlatform : public mozilla::layers::MemoryPressureListener {
*/
virtual void ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData& aData);
virtual FT_Library GetFTLibrary() { return nullptr; }
bool HasVariationFontSupport() const { return mHasVariationFontSupport; }
bool HasNativeColrFontSupport() const { return mHasNativeColrFontSupport; }

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

@ -72,6 +72,8 @@ using namespace mozilla::gfx;
using namespace mozilla::unicode;
using mozilla::dom::SystemFontListEntry;
static FT_Library gPlatformFTLibrary = nullptr;
gfxPlatformGtk::gfxPlatformGtk() {
if (!gfxPlatform::IsHeadless()) {
gtk_init(nullptr, nullptr);
@ -105,6 +107,10 @@ gfxPlatformGtk::gfxPlatformGtk() {
// Set default display fps to 60
mWaylandFrameDelay = 1000 / 60;
#endif
gPlatformFTLibrary = Factory::NewFTLibrary();
MOZ_ASSERT(gPlatformFTLibrary);
Factory::SetFTLibrary(gPlatformFTLibrary);
}
gfxPlatformGtk::~gfxPlatformGtk() {
@ -113,6 +119,9 @@ gfxPlatformGtk::~gfxPlatformGtk() {
XCloseDisplay(mCompositorDisplay);
}
#endif // MOZ_X11
Factory::ReleaseFTLibrary(gPlatformFTLibrary);
gPlatformFTLibrary = nullptr;
}
void gfxPlatformGtk::FlushContentDrawing() {
@ -264,10 +273,6 @@ gfxFontGroup* gfxPlatformGtk::CreateFontGroup(
aDevToCssSize);
}
FT_Library gfxPlatformGtk::GetFTLibrary() {
return gfxFcPlatformFontList::GetFTLibrary();
}
static int32_t sDPI = 0;
int32_t gfxPlatformGtk::GetFontScaleDPI() {
@ -468,7 +473,7 @@ bool gfxPlatformGtk::CheckVariationFontSupport() {
// in older versions, it seems too incomplete/unstable for us to use
// until at least 2.7.1.
FT_Int major, minor, patch;
FT_Library_Version(GetFTLibrary(), &major, &minor, &patch);
FT_Library_Version(Factory::GetFTLibrary(), &major, &minor, &patch);
return major * 1000000 + minor * 1000 + patch >= 2007001;
}

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

@ -58,8 +58,6 @@ class gfxPlatformGtk : public gfxPlatform {
*/
void FlushContentDrawing() override;
FT_Library GetFTLibrary() override;
static int32_t GetFontScaleDPI();
static double GetFontScaleFactor();