Bug 1471261 - Add global locking around FT_Load_Glyph to work around postscript hinter global data. r=lsalzman
MozReview-Commit-ID: 9ohfqUnPxMc
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -47,16 +47,18 @@ struct _cairo_scaled_font;
typedef _cairo_scaled_font cairo_scaled_font_t;
struct FT_LibraryRec_;
typedef FT_LibraryRec_* FT_Library;
struct FT_FaceRec_;
typedef FT_FaceRec_* FT_Face;
+typedef int FT_Error;
+
struct ID3D11Texture2D;
struct ID3D11Device;
struct ID2D1Device;
struct IDWriteFactory;
struct IDWriteRenderingParams;
struct IDWriteFontFace;
class GrContext;
@@ -1773,16 +1775,17 @@ public:
static FT_Library NewFTLibrary();
static void ReleaseFTLibrary(FT_Library aFTLibrary);
static void LockFTLibrary(FT_Library aFTLibrary);
static void UnlockFTLibrary(FT_Library aFTLibrary);
static FT_Face NewFTFace(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 void ReleaseFTFace(FT_Face aFace);
+ static FT_Error LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags);
private:
static FT_Library mFTLibrary;
static Mutex* mFTLock;
public:
#endif
#ifdef WIN32
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -184,16 +184,22 @@ mozilla_NewFTFaceFromData(FT_Library aFT
}
void
mozilla_ReleaseFTFace(FT_Face aFace)
{
mozilla::gfx::Factory::ReleaseFTFace(aFace);
}
+FT_Error
+mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags)
+{
+ return mozilla::gfx::Factory::LoadFTGlyph(aFace, aGlyphIndex, aFlags);
+}
+
void
mozilla_LockFTLibrary(FT_Library aFTLibrary)
{
mozilla::gfx::Factory::LockFTLibrary(aFTLibrary);
}
void
mozilla_UnlockFTLibrary(FT_Library aFTLibrary)
@@ -774,16 +780,24 @@ Factory::ReleaseFTFace(FT_Face aFace)
if (mFTLock) {
mFTLock->Lock();
}
FT_Done_Face(aFace);
if (mFTLock) {
mFTLock->Unlock();
}
}
+
+FT_Error
+Factory::LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags)
+{
+ MOZ_ASSERT(mFTLock);
+ MutexAutoLock lock(*mFTLock);
+ return FT_Load_Glyph(aFace, aGlyphIndex, aFlags);
+}
#endif
#ifdef WIN32
already_AddRefed<DrawTarget>
Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat)
{
MOZ_ASSERT(aTexture);
--- a/gfx/cairo/cairo/src/cairo-ft-font.c
+++ b/gfx/cairo/cairo/src/cairo-ft-font.c
@@ -103,16 +103,17 @@ static setLcdFilterFunc setLcdFilter;
#define MAX_OPEN_FACES 10
/* This is the maximum font size we allow to be passed to FT_Set_Char_Size
*/
#define MAX_FONT_SIZE 2000
extern FT_Face mozilla_NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex);
extern FT_Face mozilla_NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex);
extern void mozilla_ReleaseFTFace(FT_Face aFace);
+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);
/**
* SECTION:cairo-ft
* @Title: FreeType Fonts
* @Short_Description: Font support for FreeType
* @See_Also: #cairo_font_face_t
@@ -2339,17 +2340,17 @@ static cairo_int_status_t
* maybe we should cache color and grayscale bitmaps separately
* such that users of the font (ie. the surface) can choose which
* version to use based on target content type.
*/
load_flags |= FT_LOAD_COLOR;
#endif
- error = FT_Load_Glyph (scaled_font->unscaled->face,
+ error = mozilla_LoadFTGlyph (scaled_font->unscaled->face,
_cairo_scaled_glyph_index(scaled_glyph),
load_flags);
/* XXX ignoring all other errors for now. They are not fatal, typically
* just a glyph-not-found. */
if (error == FT_Err_Out_Of_Memory) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FAIL;
}
@@ -2493,17 +2494,17 @@ static cairo_int_status_t
if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
cairo_path_fixed_t *path = NULL; /* hide compiler warning */
/*
* A kludge -- the above code will trash the outline,
* so reload it. This will probably never occur though
*/
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
- error = FT_Load_Glyph (face,
+ error = mozilla_LoadFTGlyph (face,
_cairo_scaled_glyph_index(scaled_glyph),
load_flags | FT_LOAD_NO_BITMAP);
/* XXX ignoring all other errors for now. They are not fatal, typically
* just a glyph-not-found. */
if (error == FT_Err_Out_Of_Memory) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto FAIL;
}
--- a/gfx/cairo/cairo/src/cairo-type1-subset.c
+++ b/gfx/cairo/cairo/src/cairo-type1-subset.c
@@ -56,16 +56,18 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_TYPE1_TABLES_H
#include <ctype.h>
+extern FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags);
+
typedef struct _cairo_type1_font_subset {
cairo_scaled_font_subset_t *scaled_font_subset;
struct {
cairo_unscaled_font_t *unscaled_font;
unsigned int font_id;
char *base_font;
unsigned int num_glyphs;
@@ -550,17 +552,17 @@ cairo_type1_font_subset_get_glyph_names_
char buffer[256];
FT_Error error;
/* Get glyph names and width using the freetype API */
for (i = 0; i < font->base.num_glyphs; i++) {
if (font->glyphs[i].name != NULL)
continue;
- error = FT_Load_Glyph (font->face, i,
+ error = mozilla_LoadFTGlyph (font->face, i,
FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING |
FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
if (error != FT_Err_Ok) {
/* propagate fatal errors from FreeType */
if (error == FT_Err_Out_Of_Memory)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_INT_STATUS_UNSUPPORTED;
--- a/gfx/skia/skia/src/ports/SkFontHost_cairo.cpp
+++ b/gfx/skia/skia/src/ports/SkFontHost_cairo.cpp
@@ -59,16 +59,23 @@ typedef enum FT_LcdFilter_
#endif
static cairo_user_data_key_t kSkTypefaceKey;
static bool gFontHintingEnabled = true;
static FT_Error (*gSetLcdFilter)(FT_Library, FT_LcdFilter) = nullptr;
static void (*gGlyphSlotEmbolden)(FT_GlyphSlot) = nullptr;
+extern "C"
+{
+ void mozilla_LockFTLibrary(FT_Library aLibrary);
+ void mozilla_UnlockFTLibrary(FT_Library aLibrary);
+ FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags);
+}
+
void SkInitCairoFT(bool fontHintingEnabled)
{
gFontHintingEnabled = fontHintingEnabled;
#if SK_CAN_USE_DLOPEN
gSetLcdFilter = (FT_Error (*)(FT_Library, FT_LcdFilter))dlsym(RTLD_DEFAULT, "FT_Library_SetLcdFilter");
gGlyphSlotEmbolden = (void (*)(FT_GlyphSlot))dlsym(RTLD_DEFAULT, "FT_GlyphSlot_Embolden");
#else
gSetLcdFilter = &FT_Library_SetLcdFilter;
@@ -630,17 +637,17 @@ void SkScalerContext_CairoFT::generateMe
{
SkASSERT(fScaledFont != nullptr);
glyph->zeroMetrics();
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
- FT_Error err = FT_Load_Glyph( face, glyph->getGlyphID(), fLoadGlyphFlags );
+ FT_Error err = mozilla_LoadFTGlyph( face, glyph->getGlyphID(), fLoadGlyphFlags );
if (err != 0) {
return;
}
prepareGlyph(face->glyph);
if (fRec.fFlags & SkScalerContext::kVertical_Flag) {
glyph->fAdvanceX = -SkFDot6ToFloat(face->glyph->advance.x);
@@ -734,60 +741,62 @@ void SkScalerContext_CairoFT::generateMe
}
void SkScalerContext_CairoFT::generateImage(const SkGlyph& glyph)
{
SkASSERT(fScaledFont != nullptr);
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
- FT_Error err = FT_Load_Glyph(face, glyph.getGlyphID(), fLoadGlyphFlags);
+ FT_Error err = mozilla_LoadFTGlyph(face, glyph.getGlyphID(), fLoadGlyphFlags);
if (err != 0) {
memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
return;
}
prepareGlyph(face->glyph);
bool useLcdFilter =
face->glyph->format == FT_GLYPH_FORMAT_OUTLINE &&
isLCD(glyph) &&
gSetLcdFilter;
if (useLcdFilter) {
+ mozilla_LockFTLibrary(face->glyph->library);
gSetLcdFilter(face->glyph->library, fLcdFilter);
}
SkMatrix matrix;
if (face->glyph->format == FT_GLYPH_FORMAT_BITMAP &&
fHaveShape) {
matrix = fShapeMatrix;
} else {
matrix.setIdentity();
}
generateGlyphImage(face, glyph, matrix);
if (useLcdFilter) {
gSetLcdFilter(face->glyph->library, FT_LCD_FILTER_NONE);
+ mozilla_UnlockFTLibrary(face->glyph->library);
}
}
void SkScalerContext_CairoFT::generatePath(const SkGlyphID glyphID, SkPath* path)
{
SkASSERT(fScaledFont != nullptr);
CairoLockedFTFace faceLock(fScaledFont);
FT_Face face = faceLock.getFace();
SkASSERT(path);
uint32_t flags = fLoadGlyphFlags;
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 = FT_Load_Glyph(face, glyphID, flags);
+ FT_Error err = mozilla_LoadFTGlyph(face, glyphID, flags);
if (err != 0) {
path->reset();
return;
}
prepareGlyph(face->glyph);
--- a/gfx/thebes/gfxFT2FontBase.cpp
+++ b/gfx/thebes/gfxFT2FontBase.cpp
@@ -535,17 +535,17 @@ gfxFT2FontBase::GetFTGlyphAdvance(uint16
!(face.get()->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
return false;
}
bool hinting = gfxPlatform::GetPlatform()->FontHintingEnabled();
int32_t flags =
hinting ? FT_LOAD_ADVANCE_ONLY
: FT_LOAD_ADVANCE_ONLY | FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
- FT_Error ftError = FT_Load_Glyph(face.get(), aGID, flags);
+ FT_Error ftError = Factory::LoadFTGlyph(face.get(), aGID, flags);
if (ftError != FT_Err_Ok) {
// FT_Face was somehow broken/invalid? Don't try to access glyph slot.
// This probably shouldn't happen, but does: see bug 1440938.
NS_WARNING("failed to load glyph!");
return false;
}
// Due to freetype bug 52683 we MUST use the linearHoriAdvance field when
--- a/gfx/thebes/gfxFT2Fonts.cpp
+++ b/gfx/thebes/gfxFT2Fonts.cpp
@@ -211,17 +211,17 @@ gfxFT2Font::FillGlyphDataForChar(FT_Face
NS_ASSERTION(gid != 0, "We don't have a glyph, but font indicated that it supported this char in tables?");
gd->glyphIndex = 0;
return;
}
FT_Int32 flags = gfxPlatform::GetPlatform()->FontHintingEnabled() ?
FT_LOAD_DEFAULT :
(FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
- FT_Error err = FT_Load_Glyph(face, gid, flags);
+ FT_Error err = Factory::LoadFTGlyph(face, gid, flags);
if (err) {
// hmm, this is weird, we failed to load a glyph that we had?
NS_WARNING("Failed to load glyph that we got from Get_Char_index");
gd->glyphIndex = 0;
return;
}