From a7c14e2f29831f4bc5eb18e23e55eb6f7a4e3431 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 8 Apr 2024 17:12:12 +0200 Subject: Merging upstream version 115.8.0esr. Signed-off-by: Daniel Baumann --- gfx/2d/DrawTarget.cpp | 5 +- gfx/2d/ScaledFontBase.cpp | 16 +++++-- gfx/gl/GLContext.cpp | 6 +++ gfx/gl/GLContext.h | 2 + gfx/gl/GLContextProviderCGL.mm | 2 + gfx/gl/GLContextProviderEAGL.mm | 2 + gfx/gl/GLContextProviderWGL.cpp | 10 +++- gfx/gl/GLLibraryEGL.h | 8 +++- gfx/gl/GLXLibrary.h | 3 +- gfx/ipc/InProcessCompositorSession.cpp | 5 +- gfx/ipc/RemoteCompositorSession.cpp | 5 +- gfx/thebes/SharedFontList-impl.h | 6 --- gfx/thebes/SharedFontList.cpp | 83 ++++++++++++++++++++++------------ gfx/thebes/SharedFontList.h | 7 ++- gfx/thebes/gfxDWriteFontList.cpp | 12 +++-- gfx/thebes/gfxDWriteFonts.cpp | 12 +++-- gfx/thebes/gfxFT2FontList.cpp | 2 +- gfx/thebes/gfxFcPlatformFontList.cpp | 2 +- gfx/thebes/gfxFontEntry.cpp | 3 +- gfx/thebes/gfxFontEntry.h | 1 + gfx/thebes/gfxMacPlatformFontList.h | 30 ++++++------ gfx/thebes/gfxMacPlatformFontList.mm | 23 +++++++++- gfx/thebes/gfxPlatformFontList.cpp | 76 +++++++++++++++---------------- gfx/thebes/gfxPlatformFontList.h | 8 ++-- 24 files changed, 206 insertions(+), 123 deletions(-) (limited to 'gfx') diff --git a/gfx/2d/DrawTarget.cpp b/gfx/2d/DrawTarget.cpp index eb7b23f3be..7f95dc6661 100644 --- a/gfx/2d/DrawTarget.cpp +++ b/gfx/2d/DrawTarget.cpp @@ -183,8 +183,9 @@ void DrawTarget::StrokeGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer, const Pattern& aPattern, const StrokeOptions& aStrokeOptions, const DrawOptions& aOptions) { - RefPtr path = aFont->GetPathForGlyphs(aBuffer, this); - Stroke(path, aPattern, aStrokeOptions, aOptions); + if (RefPtr path = aFont->GetPathForGlyphs(aBuffer, this)) { + Stroke(path, aPattern, aStrokeOptions, aOptions); + } } already_AddRefed DrawTarget::IntoLuminanceSource( diff --git a/gfx/2d/ScaledFontBase.cpp b/gfx/2d/ScaledFontBase.cpp index d62dcb0127..cd52df3ccd 100644 --- a/gfx/2d/ScaledFontBase.cpp +++ b/gfx/2d/ScaledFontBase.cpp @@ -127,7 +127,11 @@ already_AddRefed ScaledFontBase::GetPathForGlyphs( } #ifdef USE_CAIRO if (aTarget->GetBackendType() == BackendType::CAIRO) { - MOZ_ASSERT(mScaledFont); + auto* cairoScaledFont = GetCairoScaledFont(); + if (!cairoScaledFont) { + MOZ_ASSERT_UNREACHABLE("Invalid scaled font"); + return nullptr; + } DrawTarget* dt = const_cast(aTarget); cairo_t* ctx = static_cast( @@ -141,7 +145,7 @@ already_AddRefed ScaledFontBase::GetPathForGlyphs( cairo_set_matrix(ctx, &mat); } - cairo_set_scaled_font(ctx, mScaledFont); + cairo_set_scaled_font(ctx, cairoScaledFont); // Convert our GlyphBuffer into an array of Cairo glyphs. std::vector glyphs(aBuffer.mNumGlyphs); @@ -181,7 +185,11 @@ void ScaledFontBase::CopyGlyphsToBuilder(const GlyphBuffer& aBuffer, } #ifdef USE_CAIRO if (backendType == BackendType::CAIRO) { - MOZ_ASSERT(mScaledFont); + auto* cairoScaledFont = GetCairoScaledFont(); + if (!cairoScaledFont) { + MOZ_ASSERT_UNREACHABLE("Invalid scaled font"); + return; + } PathBuilderCairo* builder = static_cast(aBuilder); cairo_t* ctx = cairo_create(DrawTargetCairo::GetDummySurface()); @@ -200,7 +208,7 @@ void ScaledFontBase::CopyGlyphsToBuilder(const GlyphBuffer& aBuffer, glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y; } - cairo_set_scaled_font(ctx, mScaledFont); + cairo_set_scaled_font(ctx, cairoScaledFont); cairo_glyph_path(ctx, &glyphs[0], aBuffer.mNumGlyphs); RefPtr cairoPath = new PathCairo(ctx); diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index f67aedd0b2..d11c131c45 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -2432,6 +2432,12 @@ uint32_t GetBytesPerTexel(GLenum format, GLenum type) { return 0; } +void GLContext::ResetTLSCurrentContext() { + if (sCurrentContext.init()) { + sCurrentContext.set(nullptr); + } +} + bool GLContext::MakeCurrent(bool aForce) const { if (MOZ_UNLIKELY(IsContextLost())) return false; diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index d88b96019f..41dbe92bee 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -185,6 +185,8 @@ class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr { bool mImplicitMakeCurrent = false; bool mUseTLSIsCurrent; + static void ResetTLSCurrentContext(); + class TlsScope final { const WeakPtr mGL; const bool mWasTlsOk; diff --git a/gfx/gl/GLContextProviderCGL.mm b/gfx/gl/GLContextProviderCGL.mm index 1b4049de3e..a01701f571 100644 --- a/gfx/gl/GLContextProviderCGL.mm +++ b/gfx/gl/GLContextProviderCGL.mm @@ -84,6 +84,8 @@ CGLContextObj GLContextCGL::GetCGLContext() const { bool GLContextCGL::MakeCurrentImpl() const { if (mContext) { + GLContext::ResetTLSCurrentContext(); + [mContext makeCurrentContext]; MOZ_ASSERT(IsCurrentImpl()); // Use non-blocking swap in "ASAP mode". diff --git a/gfx/gl/GLContextProviderEAGL.mm b/gfx/gl/GLContextProviderEAGL.mm index 4aabe89df1..b90adaacf3 100644 --- a/gfx/gl/GLContextProviderEAGL.mm +++ b/gfx/gl/GLContextProviderEAGL.mm @@ -90,6 +90,8 @@ bool GLContextEAGL::RecreateRB() { bool GLContextEAGL::MakeCurrentImpl() const { if (mContext) { + GLContext::ResetTLSCurrentContext(); + if (![EAGLContext setCurrentContext:mContext]) { return false; } diff --git a/gfx/gl/GLContextProviderWGL.cpp b/gfx/gl/GLContextProviderWGL.cpp index 2720cab14e..5d90ee5169 100644 --- a/gfx/gl/GLContextProviderWGL.cpp +++ b/gfx/gl/GLContextProviderWGL.cpp @@ -158,12 +158,16 @@ bool WGLLibrary::EnsureInitialized() { const auto curCtx = mSymbols.fGetCurrentContext(); const auto curDC = mSymbols.fGetCurrentDC(); + GLContext::ResetTLSCurrentContext(); + if (!mSymbols.fMakeCurrent(mRootDc, mDummyGlrc)) { NS_WARNING("wglMakeCurrent failed"); return false; } - const auto resetContext = - MakeScopeExit([&]() { mSymbols.fMakeCurrent(curDC, curCtx); }); + const auto resetContext = MakeScopeExit([&]() { + GLContext::ResetTLSCurrentContext(); + mSymbols.fMakeCurrent(curDC, curCtx); + }); const auto loader = GetSymbolLoader(); @@ -297,6 +301,8 @@ GLContextWGL::~GLContextWGL() { } bool GLContextWGL::MakeCurrentImpl() const { + GLContext::ResetTLSCurrentContext(); + const bool succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext); NS_ASSERTION(succeeded, "Failed to make GL context current!"); return succeeded; diff --git a/gfx/gl/GLLibraryEGL.h b/gfx/gl/GLLibraryEGL.h index 28f84b27f4..0a853e67c9 100644 --- a/gfx/gl/GLLibraryEGL.h +++ b/gfx/gl/GLLibraryEGL.h @@ -11,7 +11,7 @@ #include "base/platform_thread.h" // for PlatformThreadId #include "gfxEnv.h" -#include "GLTypes.h" +#include "GLContext.h" #include "mozilla/EnumTypeTraits.h" #include "mozilla/gfx/Logging.h" #include "mozilla/Maybe.h" @@ -264,7 +264,6 @@ class GLLibraryEGL final { const bool CHECK_CONTEXT_OWNERSHIP = true; if (CHECK_CONTEXT_OWNERSHIP) { const MutexAutoLock lock(mMutex); - const auto tid = PlatformThread::CurrentId(); const auto prevCtx = fGetCurrentContext(); @@ -287,6 +286,11 @@ class GLLibraryEGL final { } } + // Always reset the TLS current context. + // If we're called by TLS-caching MakeCurrent, after we return true, + // the caller will set the TLS correctly anyway. + GLContext::ResetTLSCurrentContext(); + WRAP(fMakeCurrent(dpy, draw, read, ctx)); } diff --git a/gfx/gl/GLXLibrary.h b/gfx/gl/GLXLibrary.h index 7a004762ff..d2577c935c 100644 --- a/gfx/gl/GLXLibrary.h +++ b/gfx/gl/GLXLibrary.h @@ -6,7 +6,7 @@ #ifndef GFX_GLXLIBRARY_H #define GFX_GLXLIBRARY_H -#include "GLContextTypes.h" +#include "GLContext.h" #include "mozilla/Assertions.h" #include "mozilla/DataMutex.h" #include "mozilla/gfx/XlibDisplay.h" @@ -65,6 +65,7 @@ class GLXLibrary final { Bool fMakeCurrent(Display* display, GLXDrawable drawable, GLXContext context) const { DECL_WRAPPER_SCOPE(display) + GLContext::ResetTLSCurrentContext(); return mSymbols.fMakeCurrent(display, drawable, context); } diff --git a/gfx/ipc/InProcessCompositorSession.cpp b/gfx/ipc/InProcessCompositorSession.cpp index f5f94461cb..9efb83b57a 100644 --- a/gfx/ipc/InProcessCompositorSession.cpp +++ b/gfx/ipc/InProcessCompositorSession.cpp @@ -61,7 +61,10 @@ RefPtr InProcessCompositorSession::Create( } void InProcessCompositorSession::NotifySessionLost() { - mWidget->NotifyCompositorSessionLost(this); + // Hold a reference to mWidget since NotifyCompositorSessionLost may + // release the last reference mid-execution. + RefPtr widget(mWidget); + widget->NotifyCompositorSessionLost(this); } CompositorBridgeParent* InProcessCompositorSession::GetInProcessBridge() const { diff --git a/gfx/ipc/RemoteCompositorSession.cpp b/gfx/ipc/RemoteCompositorSession.cpp index bbd8ddd13f..34b7cd4856 100644 --- a/gfx/ipc/RemoteCompositorSession.cpp +++ b/gfx/ipc/RemoteCompositorSession.cpp @@ -46,10 +46,13 @@ RemoteCompositorSession::~RemoteCompositorSession() { } void RemoteCompositorSession::NotifySessionLost() { + // Hold a reference to mWidget since NotifyCompositorSessionLost may + // release the last reference mid-execution. + RefPtr widget(mWidget); // Re-entrancy should be impossible: when we are being notified of a lost // session, we have by definition not shut down yet. We will shutdown, but // then will be removed from the notification list. - mWidget->NotifyCompositorSessionLost(this); + widget->NotifyCompositorSessionLost(this); } CompositorBridgeParent* RemoteCompositorSession::GetInProcessBridge() const { diff --git a/gfx/thebes/SharedFontList-impl.h b/gfx/thebes/SharedFontList-impl.h index e39e4dd47d..928e9eb2d6 100644 --- a/gfx/thebes/SharedFontList-impl.h +++ b/gfx/thebes/SharedFontList-impl.h @@ -200,12 +200,6 @@ class FontList { */ Pointer Alloc(uint32_t aSize); - /** - * Convert a native pointer to a shared-memory Pointer record that can be - * passed between processes. - */ - Pointer ToSharedPointer(const void* aPtr); - uint32_t GetGeneration() { return GetHeader().mGeneration; } /** diff --git a/gfx/thebes/SharedFontList.cpp b/gfx/thebes/SharedFontList.cpp index e9f64089be..f97e7e2832 100644 --- a/gfx/thebes/SharedFontList.cpp +++ b/gfx/thebes/SharedFontList.cpp @@ -138,11 +138,13 @@ Family::Family(FontList* aList, const InitData& aData) class SetCharMapRunnable : public mozilla::Runnable { public: - SetCharMapRunnable(uint32_t aListGeneration, Pointer aFacePtr, - gfxCharacterMap* aCharMap) + SetCharMapRunnable(uint32_t aListGeneration, + std::pair aFamilyIndex, + uint32_t aFaceIndex, gfxCharacterMap* aCharMap) : Runnable("SetCharMapRunnable"), mListGeneration(aListGeneration), - mFacePtr(aFacePtr), + mFamilyIndex(aFamilyIndex), + mFaceIndex(aFaceIndex), mCharMap(aCharMap) {} NS_IMETHOD Run() override { @@ -150,26 +152,39 @@ class SetCharMapRunnable : public mozilla::Runnable { if (!list || list->GetGeneration() != mListGeneration) { return NS_OK; } - dom::ContentChild::GetSingleton()->SendSetCharacterMap(mListGeneration, - mFacePtr, *mCharMap); + dom::ContentChild::GetSingleton()->SendSetCharacterMap( + mListGeneration, mFamilyIndex.first, mFamilyIndex.second, mFaceIndex, + *mCharMap); return NS_OK; } private: uint32_t mListGeneration; - Pointer mFacePtr; + std::pair mFamilyIndex; + uint32_t mFaceIndex; RefPtr mCharMap; }; -void Face::SetCharacterMap(FontList* aList, gfxCharacterMap* aCharMap) { +void Face::SetCharacterMap(FontList* aList, gfxCharacterMap* aCharMap, + const Family* aFamily) { if (!XRE_IsParentProcess()) { - Pointer ptr = aList->ToSharedPointer(this); + std::pair familyIndex = aFamily->FindIndex(aList); + const auto* faces = aFamily->Faces(aList); + uint32_t faceIndex = 0; + while (faceIndex < aFamily->NumFaces()) { + if (faces[faceIndex].ToPtr(aList) == this) { + break; + } + ++faceIndex; + } + MOZ_RELEASE_ASSERT(faceIndex < aFamily->NumFaces(), "Face ptr not found!"); if (NS_IsMainThread()) { dom::ContentChild::GetSingleton()->SendSetCharacterMap( - aList->GetGeneration(), ptr, *aCharMap); + aList->GetGeneration(), familyIndex.first, familyIndex.second, + faceIndex, *aCharMap); } else { - NS_DispatchToMainThread( - new SetCharMapRunnable(aList->GetGeneration(), ptr, aCharMap)); + NS_DispatchToMainThread(new SetCharMapRunnable( + aList->GetGeneration(), familyIndex, faceIndex, aCharMap)); } return; } @@ -240,7 +255,7 @@ void Family::AddFaces(FontList* aList, const nsTArray& aFaces) { (void)new (face) Face(aList, *initData); facePtrs[i] = fp; if (initData->mCharMap) { - face->SetCharacterMap(aList, initData->mCharMap); + face->SetCharacterMap(aList, initData->mCharMap, this); } } } @@ -613,16 +628,19 @@ void Family::SetupFamilyCharMap(FontList* aList) { } if (!XRE_IsParentProcess()) { // |this| could be a Family record in either the Families() or Aliases() - // arrays + // arrays; FindIndex will map it back to its index and which array. + std::pair index = FindIndex(aList); if (NS_IsMainThread()) { dom::ContentChild::GetSingleton()->SendSetupFamilyCharMap( - aList->GetGeneration(), aList->ToSharedPointer(this)); + aList->GetGeneration(), index.first, index.second); return; } NS_DispatchToMainThread(NS_NewRunnableFunction( "SetupFamilyCharMap callback", - [gen = aList->GetGeneration(), ptr = aList->ToSharedPointer(this)] { - dom::ContentChild::GetSingleton()->SendSetupFamilyCharMap(gen, ptr); + [gen = aList->GetGeneration(), idx = index.first, + alias = index.second] { + dom::ContentChild::GetSingleton()->SendSetupFamilyCharMap(gen, idx, + alias); })); return; } @@ -667,6 +685,26 @@ void Family::SetupFamilyCharMap(FontList* aList) { } } +std::pair Family::FindIndex(FontList* aList) const { + const auto* start = aList->Families(); + const auto* end = start + aList->NumFamilies(); + if (this >= start && this < end) { + uint32_t index = this - start; + MOZ_RELEASE_ASSERT(start + index == this, "misaligned Family ptr!"); + return std::pair(index, false); + } + + start = aList->AliasFamilies(); + end = start + aList->NumAliases(); + if (this >= start && this < end) { + uint32_t index = this - start; + MOZ_RELEASE_ASSERT(start + index == this, "misaligned AliasFamily ptr!"); + return std::pair(index, true); + } + + MOZ_CRASH("invalid font-list Family ptr!"); +} + FontList::FontList(uint32_t aGeneration) { if (XRE_IsParentProcess()) { // Create the initial shared block, and initialize Header @@ -1322,19 +1360,6 @@ void FontList::SearchForLocalFace(const nsACString& aName, Family** aFamily, } } -Pointer FontList::ToSharedPointer(const void* aPtr) { - const char* p = (const char*)aPtr; - const uint32_t blockCount = mBlocks.Length(); - for (uint32_t i = 0; i < blockCount; ++i) { - const char* blockAddr = (const char*)mBlocks[i]->Memory(); - if (p >= blockAddr && p < blockAddr + SHM_BLOCK_SIZE) { - return Pointer(i, p - blockAddr); - } - } - MOZ_DIAGNOSTIC_ASSERT(false, "invalid shared-memory pointer"); - return Pointer::Null(); -} - size_t FontList::SizeOfIncludingThis( mozilla::MallocSizeOf aMallocSizeOf) const { return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); diff --git a/gfx/thebes/SharedFontList.h b/gfx/thebes/SharedFontList.h index f2eaf28223..279bbd1a57 100644 --- a/gfx/thebes/SharedFontList.h +++ b/gfx/thebes/SharedFontList.h @@ -198,7 +198,8 @@ struct Face { return !mDescriptor.IsNull() && mIndex != uint16_t(-1); } - void SetCharacterMap(FontList* aList, gfxCharacterMap* aCharMap); + void SetCharacterMap(FontList* aList, gfxCharacterMap* aCharMap, + const Family* aFamily); String mDescriptor; uint16_t mIndex; @@ -330,6 +331,10 @@ struct Family { void SetupFamilyCharMap(FontList* aList); + // Return the index of this family in the font-list's Families() or + // AliasFamilies() list, and which of those it belongs to. + std::pair FindIndex(FontList* aList) const; + private: // Returns true if there are specifically-sized bitmap faces in the list, // so size selection still needs to be done. (Currently only on Linux.) diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index d31ba05deb..cb88fd86d9 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -554,7 +554,7 @@ nsresult gfxDWriteFontEntry::ReadCMAP(FontInfoData* aFontInfoData) { gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); fontlist::FontList* sharedFontList = pfl->SharedFontList(); if (!IsUserFont() && mShmemFace) { - mShmemFace->SetCharacterMap(sharedFontList, charmap); // async + mShmemFace->SetCharacterMap(sharedFontList, charmap, mShmemFamily); if (TrySetShmemCharacterMap()) { setCharMap = false; } @@ -674,11 +674,13 @@ gfxFont* gfxDWriteFontEntry::CreateFontInstance( switch (StaticPrefs::gfx_font_rendering_directwrite_bold_simulation()) { case 0: // never use the DWrite simulation break; - case 1: // use DWrite simulation for installed fonts but not webfonts - useBoldSim = !mIsDataUserFont; + case 1: // use DWrite simulation for installed fonts except COLR fonts, + // but not webfonts + useBoldSim = + !mIsDataUserFont && !HasFontTable(TRUETYPE_TAG('C', 'O', 'L', 'R')); break; - default: // always use DWrite bold simulation - useBoldSim = true; + default: // always use DWrite bold simulation, except for COLR fonts + useBoldSim = !HasFontTable(TRUETYPE_TAG('C', 'O', 'L', 'R')); break; } } diff --git a/gfx/thebes/gfxDWriteFonts.cpp b/gfx/thebes/gfxDWriteFonts.cpp index fa6bc48cf9..a77dfee6be 100644 --- a/gfx/thebes/gfxDWriteFonts.cpp +++ b/gfx/thebes/gfxDWriteFonts.cpp @@ -96,11 +96,15 @@ gfxDWriteFont::gfxDWriteFont(const RefPtr& aUnscaledFont, case 0: // never use the DWrite simulation mApplySyntheticBold = true; break; - case 1: // use DWrite simulation for installed fonts but not webfonts - mApplySyntheticBold = aFontEntry->mIsDataUserFont; + case 1: // use DWrite simulation for installed fonts except COLR fonts, + // but not webfonts + mApplySyntheticBold = + aFontEntry->mIsDataUserFont || + aFontEntry->HasFontTable(TRUETYPE_TAG('C', 'O', 'L', 'R')); break; - default: // always use DWrite bold simulation - // the flag is initialized to false in gfxFont + default: // always use DWrite bold simulation, except for COLR fonts + mApplySyntheticBold = + aFontEntry->HasFontTable(TRUETYPE_TAG('C', 'O', 'L', 'R')); break; } } diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index 372abce92d..b68fcac3e0 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -427,7 +427,7 @@ nsresult FT2FontEntry::ReadCMAP(FontInfoData* aFontInfoData) { gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); fontlist::FontList* sharedFontList = pfl->SharedFontList(); if (!IsUserFont() && mShmemFace) { - mShmemFace->SetCharacterMap(sharedFontList, charmap); // async + mShmemFace->SetCharacterMap(sharedFontList, charmap, mShmemFamily); if (TrySetShmemCharacterMap()) { setCharMap = false; } diff --git a/gfx/thebes/gfxFcPlatformFontList.cpp b/gfx/thebes/gfxFcPlatformFontList.cpp index 4ecbe0d657..ff5c8d4acf 100644 --- a/gfx/thebes/gfxFcPlatformFontList.cpp +++ b/gfx/thebes/gfxFcPlatformFontList.cpp @@ -448,7 +448,7 @@ nsresult gfxFontconfigFontEntry::ReadCMAP(FontInfoData* aFontInfoData) { gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); fontlist::FontList* sharedFontList = pfl->SharedFontList(); if (!IsUserFont() && mShmemFace) { - mShmemFace->SetCharacterMap(sharedFontList, charmap); // async + mShmemFace->SetCharacterMap(sharedFontList, charmap, mShmemFamily); if (TrySetShmemCharacterMap()) { setCharMap = false; } diff --git a/gfx/thebes/gfxFontEntry.cpp b/gfx/thebes/gfxFontEntry.cpp index 6d32cc2cfc..9918fc1c4d 100644 --- a/gfx/thebes/gfxFontEntry.cpp +++ b/gfx/thebes/gfxFontEntry.cpp @@ -132,12 +132,13 @@ gfxFontEntry::~gfxFontEntry() { // the entry, so locking not required. void gfxFontEntry::InitializeFrom(fontlist::Face* aFace, const fontlist::Family* aFamily) { + mShmemFace = aFace; + mShmemFamily = aFamily; mStyleRange = aFace->mStyle; mWeightRange = aFace->mWeight; mStretchRange = aFace->mStretch; mFixedPitch = aFace->mFixedPitch; mIsBadUnderlineFont = aFamily->IsBadUnderlineFamily(); - mShmemFace = aFace; auto* list = gfxPlatformFontList::PlatformFontList()->SharedFontList(); mFamilyName = aFamily->DisplayName().AsString(list); mHasCmapTable = TrySetShmemCharacterMap(); diff --git a/gfx/thebes/gfxFontEntry.h b/gfx/thebes/gfxFontEntry.h index 86d2445d0b..a721f7f6b6 100644 --- a/gfx/thebes/gfxFontEntry.h +++ b/gfx/thebes/gfxFontEntry.h @@ -555,6 +555,7 @@ class gfxFontEntry { gfxCharacterMap* GetCharacterMap() const { return mCharacterMap; } mozilla::fontlist::Face* mShmemFace = nullptr; + const mozilla::fontlist::Family* mShmemFamily = nullptr; mozilla::Atomic mShmemCharacterMap; const SharedBitSet* GetShmemCharacterMap() const { diff --git a/gfx/thebes/gfxMacPlatformFontList.h b/gfx/thebes/gfxMacPlatformFontList.h index 518c58d3af..dd24eebe69 100644 --- a/gfx/thebes/gfxMacPlatformFontList.h +++ b/gfx/thebes/gfxMacPlatformFontList.h @@ -54,7 +54,7 @@ class MacOSFontEntry final : public gfxFontEntry { // returns it; if not, the instance returned will be owned solely by the // caller.) // Note that in the case of a broken font, this could return null. - CGFontRef CreateOrCopyFontRef(); + CGFontRef CreateOrCopyFontRef() MOZ_REQUIRES_SHARED(mLock); // override gfxFontEntry table access function to bypass table cache, // use CGFontRef API to get direct access to system font data @@ -84,19 +84,19 @@ class MacOSFontEntry final : public gfxFontEntry { static void DestroyBlobFunc(void* aUserData); - CGFontRef - mFontRef; // owning reference to the CGFont, released on destruction + CGFontRef mFontRef MOZ_GUARDED_BY(mLock); // owning reference - double mSizeHint; + const double mSizeHint; - bool mFontRefInitialized; - bool mRequiresAAT; - bool mIsCFF; - bool mIsCFFInitialized; - bool mHasVariations; - bool mHasVariationsInitialized; - bool mHasAATSmallCaps; - bool mHasAATSmallCapsInitialized; + bool mFontRefInitialized MOZ_GUARDED_BY(mLock); + + mozilla::Atomic mRequiresAAT; + mozilla::Atomic mIsCFF; + mozilla::Atomic mIsCFFInitialized; + mozilla::Atomic mHasVariations; + mozilla::Atomic mHasVariationsInitialized; + mozilla::Atomic mHasAATSmallCaps; + mozilla::Atomic mHasAATSmallCapsInitialized; // To work around Core Text's mishandling of the default value for 'opsz', // we need to record whether the font has an a optical size axis, what its @@ -105,10 +105,10 @@ class MacOSFontEntry final : public gfxFontEntry { // These fields are used by gfxMacFont, but stored in the font entry so // that only a single font instance needs to inspect the available // variations. - gfxFontVariationAxis mOpszAxis; - float mAdjustedDefaultOpsz; + gfxFontVariationAxis mOpszAxis MOZ_GUARDED_BY(mLock); + float mAdjustedDefaultOpsz MOZ_GUARDED_BY(mLock); - nsTHashtable mAvailableTables; + nsTHashtable mAvailableTables MOZ_GUARDED_BY(mLock); mozilla::ThreadSafeWeakPtr mUnscaledFont; }; diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm index b95c6fa1d1..8942a4247a 100644 --- a/gfx/thebes/gfxMacPlatformFontList.mm +++ b/gfx/thebes/gfxMacPlatformFontList.mm @@ -414,8 +414,8 @@ nsresult MacOSFontEntry::ReadCMAP(FontInfoData* aFontInfoData) { if (NS_SUCCEEDED(rv)) { gfxPlatformFontList* pfl = gfxPlatformFontList::PlatformFontList(); fontlist::FontList* sharedFontList = pfl->SharedFontList(); - if (!IsUserFont() && mShmemFace) { - mShmemFace->SetCharacterMap(sharedFontList, charmap); // async + if (!IsUserFont() && mShmemFace && mShmemFamily) { + mShmemFace->SetCharacterMap(sharedFontList, charmap, mShmemFamily); if (TrySetShmemCharacterMap()) { setCharMap = false; } @@ -552,6 +552,13 @@ gfxFontEntry* MacOSFontEntry::Clone() const { } CGFontRef MacOSFontEntry::GetFontRef() { + { + AutoReadLock lock(mLock); + if (mFontRefInitialized) { + return mFontRef; + } + } + AutoWriteLock lock(mLock); if (!mFontRefInitialized) { // Cache the CGFontRef, to be released by our destructor. mFontRef = CreateOrCopyFontRef(); @@ -616,7 +623,9 @@ class FontTableRec { } hb_blob_t* MacOSFontEntry::GetFontTable(uint32_t aTag) { + mLock.ReadLock(); AutoCFRelease fontRef = CreateOrCopyFontRef(); + mLock.ReadUnlock(); if (!fontRef) { return nullptr; } @@ -637,6 +646,16 @@ hb_blob_t* MacOSFontEntry::GetFontTable(uint32_t aTag) { } bool MacOSFontEntry::HasFontTable(uint32_t aTableTag) { + { + // If we've already initialized mAvailableTables, we can return without + // needing to take an exclusive lock. + AutoReadLock lock(mLock); + if (mAvailableTables.Count()) { + return mAvailableTables.GetEntry(aTableTag); + } + } + + AutoWriteLock lock(mLock); if (mAvailableTables.Count() == 0) { nsAutoreleasePool localPool; diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp index 1131ecb513..282fb36195 100644 --- a/gfx/thebes/gfxPlatformFontList.cpp +++ b/gfx/thebes/gfxPlatformFontList.cpp @@ -3014,7 +3014,8 @@ void gfxPlatformFontList::InitializeFamily(uint32_t aGeneration, } void gfxPlatformFontList::SetCharacterMap(uint32_t aGeneration, - const fontlist::Pointer& aFacePtr, + uint32_t aFamilyIndex, bool aAlias, + uint32_t aFaceIndex, const gfxSparseBitSet& aMap) { MOZ_ASSERT(XRE_IsParentProcess()); auto list = SharedFontList(); @@ -3028,14 +3029,35 @@ void gfxPlatformFontList::SetCharacterMap(uint32_t aGeneration, if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) { return; } - auto* face = aFacePtr.ToPtr(list); - if (face) { + + const fontlist::Family* family; + if (aAlias) { + if (aFamilyIndex >= list->NumAliases()) { + MOZ_ASSERT(false, "AliasFamily index out of range"); + return; + } + family = list->AliasFamilies() + aFamilyIndex; + } else { + if (aFamilyIndex >= list->NumFamilies()) { + MOZ_ASSERT(false, "Family index out of range"); + return; + } + family = list->Families() + aFamilyIndex; + } + + if (aFaceIndex >= family->NumFaces()) { + MOZ_ASSERT(false, "Face index out of range"); + return; + } + + if (auto* face = + family->Faces(list)[aFaceIndex].ToPtr(list)) { face->mCharacterMap = GetShmemCharMap(&aMap); } } -void gfxPlatformFontList::SetupFamilyCharMap( - uint32_t aGeneration, const fontlist::Pointer& aFamilyPtr) { +void gfxPlatformFontList::SetupFamilyCharMap(uint32_t aGeneration, + uint32_t aIndex, bool aAlias) { MOZ_ASSERT(XRE_IsParentProcess()); auto list = SharedFontList(); MOZ_ASSERT(list); @@ -3049,46 +3071,20 @@ void gfxPlatformFontList::SetupFamilyCharMap( return; } - // aFamilyPtr was passed from a content process which may not be trusted, - // so we cannot assume it is valid or safe to use. If the Pointer value is - // bad, we must not crash or do anything bad, just bail out. - // (In general, if the child process was trying to use an invalid pointer it - // should have hit the MOZ_DIAGNOSTIC_ASSERT in FontList::ToSharedPointer - // rather than passing a null or bad pointer to the parent.) - - auto* family = aFamilyPtr.ToPtr(list); - if (!family) { - // Unable to resolve to a native pointer (or it was null). - NS_WARNING("unexpected null Family pointer"); - return; - } - - // Validate the pointer before trying to use it: check that it points to a - // correctly-aligned offset within the Families() or AliasFamilies() array. - // We just assert (in debug builds only) on failure, and return safely. - // A misaligned pointer here would indicate a buggy (or compromised) child - // process, but crashing the parent would be unnecessary and does not yield - // any useful insight. - if (family >= list->Families() && - family < list->Families() + list->NumFamilies()) { - size_t offset = (char*)family - (char*)list->Families(); - if (offset % sizeof(fontlist::Family) != 0) { - MOZ_ASSERT(false, "misaligned Family pointer"); + if (aAlias) { + if (aIndex >= list->NumAliases()) { + MOZ_ASSERT(false, "AliasFamily index out of range"); return; } - } else if (family >= list->AliasFamilies() && - family < list->AliasFamilies() + list->NumAliases()) { - size_t offset = (char*)family - (char*)list->AliasFamilies(); - if (offset % sizeof(fontlist::Family) != 0) { - MOZ_ASSERT(false, "misaligned Family pointer"); - return; - } - } else { - MOZ_ASSERT(false, "not a valid Family or AliasFamily pointer"); + list->AliasFamilies()[aIndex].SetupFamilyCharMap(list); return; } - family->SetupFamilyCharMap(list); + if (aIndex >= list->NumFamilies()) { + MOZ_ASSERT(false, "Family index out of range"); + return; + } + list->Families()[aIndex].SetupFamilyCharMap(list); } bool gfxPlatformFontList::InitOtherFamilyNames(uint32_t aGeneration, diff --git a/gfx/thebes/gfxPlatformFontList.h b/gfx/thebes/gfxPlatformFontList.h index 930026d8cc..cd17a3b4cd 100644 --- a/gfx/thebes/gfxPlatformFontList.h +++ b/gfx/thebes/gfxPlatformFontList.h @@ -357,12 +357,10 @@ class gfxPlatformFontList : public gfxFontInfoLoader { base::SharedMemoryHandle ShareShmBlockToProcess(uint32_t aIndex, base::ProcessId aPid); - void SetCharacterMap(uint32_t aGeneration, - const mozilla::fontlist::Pointer& aFacePtr, - const gfxSparseBitSet& aMap); + void SetCharacterMap(uint32_t aGeneration, uint32_t aFamilyIndex, bool aAlias, + uint32_t aFaceIndex, const gfxSparseBitSet& aMap); - void SetupFamilyCharMap(uint32_t aGeneration, - const mozilla::fontlist::Pointer& aFamilyPtr); + void SetupFamilyCharMap(uint32_t aGeneration, uint32_t aIndex, bool aAlias); // Start the async cmap loading process, if not already under way, from the // given family index. (For use in any process that needs font lookups.) -- cgit v1.2.3