commit 2e216f0f8869446dee03f3d12f233dfdbbe5cfb8
parent c96f3ae833a3612015ea23101b651699904b66ae
Author: Frédéric Wang <fwang@igalia.com>
Date: Mon, 5 Jan 2026 18:19:15 +0000
Bug 2008530 - Part 1 Statically initialize the MathML unicode table for stretchy operators. r=layout-reviewers,dshin
Differential Revision: https://phabricator.services.mozilla.com/D277859
Diffstat:
1 file changed, 26 insertions(+), 125 deletions(-)
diff --git a/layout/mathml/nsMathMLChar.cpp b/layout/mathml/nsMathMLChar.cpp
@@ -23,7 +23,6 @@
#include "mozilla/dom/Document.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/intl/UnicodeScriptCodes.h"
-#include "nsCOMPtr.h"
#include "nsCSSRendering.h"
#include "nsContentUtils.h"
#include "nsDeviceContext.h"
@@ -97,16 +96,10 @@ class nsGlyphTable {
gfxFontGroup* aFontGroup, const nsGlyphCode& aGlyph) = 0;
protected:
- nsGlyphTable() : mCharCache(0), mFlags(gfx::ShapedTextFlags()) {}
- explicit nsGlyphTable(gfx::ShapedTextFlags aFlags)
- : mCharCache(0), mFlags(aFlags) {}
-
// For speedy re-use, we always cache the last data used in the table.
// mCharCache is the Unicode point of the last char that was queried in this
// table.
- char16_t mCharCache;
-
- gfx::ShapedTextFlags mFlags;
+ char16_t mCharCache = 0;
};
// A Unicode construction is a set of all the stretchy MathML characters that
@@ -174,7 +167,7 @@ static const UnicodeConstruction gUnicodeTableConstructions[] = {
class nsUnicodeTable final : public nsGlyphTable {
public:
- nsUnicodeTable() { MOZ_COUNT_CTOR(nsUnicodeTable); }
+ constexpr nsUnicodeTable() { MOZ_COUNT_CTOR(nsUnicodeTable); }
MOZ_COUNTED_DTOR(nsUnicodeTable)
@@ -232,9 +225,11 @@ class nsUnicodeTable final : public nsGlyphTable {
: mTarget(aTarget) {}
const char16_t mTarget;
};
- size_t mCachedIndex;
+ size_t mCachedIndex = 0;
};
+static constinit nsUnicodeTable gUnicodeTable;
+
/* virtual */
nsGlyphCode nsUnicodeTable::ElementAt(DrawTarget* /* aDrawTarget */,
int32_t /* aAppUnitsPerDevPixel */,
@@ -272,7 +267,7 @@ already_AddRefed<gfxTextRun> nsUnicodeTable::MakeTextRun(
NS_ASSERTION(!aGlyph.isGlyphID,
"nsUnicodeTable can only access glyphs by code point");
return aFontGroup->MakeTextRun(&aGlyph.code, 1, aDrawTarget,
- aAppUnitsPerDevPixel, mFlags,
+ aAppUnitsPerDevPixel, gfx::ShapedTextFlags(),
nsTextFrameUtils::Flags(), nullptr);
}
@@ -321,12 +316,13 @@ class nsOpenTypeTable final : public nsGlyphTable {
RefPtr<gfxFont> mFont;
nsCString mFontFamilyName;
uint32_t mGlyphID;
+ gfx::ShapedTextFlags mFlags;
nsOpenTypeTable(gfxFont* aFont, gfx::ShapedTextFlags aFlags)
- : nsGlyphTable(aFlags),
- mFont(aFont),
+ : mFont(aFont),
mFontFamilyName(aFont->GetFontEntry()->FamilyName()),
- mGlyphID(0) {
+ mGlyphID(0),
+ mFlags(aFlags) {
MOZ_COUNT_CTOR(nsOpenTypeTable);
}
@@ -439,96 +435,6 @@ already_AddRefed<gfxTextRun> nsOpenTypeTable::MakeTextRun(
}
// -----------------------------------------------------------------------------
-// This is the list of all the applicable glyph tables.
-// We will maintain a single global instance that will only reveal those
-// glyph tables that are associated to fonts currently installed on the
-// user' system. The class is an XPCOM shutdown observer to allow us to
-// free its allocated data at shutdown
-
-class nsGlyphTableList final : public nsIObserver {
- public:
- NS_DECL_ISUPPORTS
- NS_DECL_NSIOBSERVER
-
- nsUnicodeTable mUnicodeTable;
-
- nsGlyphTableList() {}
-
- nsresult Initialize();
- nsresult Finalize();
-
- private:
- ~nsGlyphTableList() = default;
-};
-
-NS_IMPL_ISUPPORTS(nsGlyphTableList, nsIObserver)
-
-// -----------------------------------------------------------------------------
-// Here is the global list of applicable glyph tables that we will be using
-static nsGlyphTableList* gGlyphTableList = nullptr;
-
-static bool gGlyphTableInitialized = false;
-
-// XPCOM shutdown observer
-NS_IMETHODIMP
-nsGlyphTableList::Observe(nsISupports* aSubject, const char* aTopic,
- const char16_t* someData) {
- Finalize();
- return NS_OK;
-}
-
-// Add an observer to XPCOM shutdown so that we can free our data at shutdown
-nsresult nsGlyphTableList::Initialize() {
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (!obs) {
- return NS_ERROR_FAILURE;
- }
-
- nsresult rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
- NS_ENSURE_SUCCESS(rv, rv);
-
- return NS_OK;
-}
-
-// Remove our observer and free the memory that were allocated for us
-nsresult nsGlyphTableList::Finalize() {
- // Remove our observer from the observer service
- nsresult rv = NS_OK;
- nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
- if (obs) {
- rv = obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
- } else {
- rv = NS_ERROR_FAILURE;
- }
-
- gGlyphTableInitialized = false;
- // our oneself will be destroyed when our |Release| is called by the observer
- NS_IF_RELEASE(gGlyphTableList);
- return rv;
-}
-
-// -----------------------------------------------------------------------------
-
-static nsresult InitCharGlobals() {
- NS_ASSERTION(!gGlyphTableInitialized, "Error -- already initialized");
- gGlyphTableInitialized = true;
-
- // Allocate the placeholders for the preferred parts and variants
- nsresult rv = NS_ERROR_OUT_OF_MEMORY;
- auto glyphTableList = MakeRefPtr<nsGlyphTableList>();
- if (glyphTableList) {
- rv = glyphTableList->Initialize();
- }
- if (NS_FAILED(rv)) {
- return rv;
- }
- // The gGlyphTableList has been successfully registered as a shutdown
- // observer and will be deleted at shutdown.
- glyphTableList.forget(&gGlyphTableList);
- return rv;
-}
-
-// -----------------------------------------------------------------------------
// And now the implementation of nsMathMLChar
nsMathMLChar::~nsMathMLChar() { MOZ_COUNT_DTOR(nsMathMLChar); }
@@ -544,16 +450,13 @@ void nsMathMLChar::SetComputedStyle(ComputedStyle* aComputedStyle) {
}
void nsMathMLChar::SetData(nsString& aData) {
- if (!gGlyphTableInitialized) {
- InitCharGlobals();
- }
mData = aData;
// some assumptions until proven otherwise
// note that mGlyph is not initialized
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
mBoundingMetrics = nsBoundingMetrics();
// check if stretching is applicable ...
- if (gGlyphTableList && (1 == mData.Length())) {
+ if (1 == mData.Length()) {
mDirection = nsMathMLOperators::GetStretchyDirection(mData);
// default tentative table (not the one that is necessarily going
// to be used)
@@ -758,7 +661,7 @@ bool nsMathMLChar::SetFontFamily(nsPresContext* aPresContext,
// Set the font if it is an unicode table or if the same family name has
// been found.
const bool shouldSetFont = [&] {
- if (aGlyphTable == &gGlyphTableList->mUnicodeTable) {
+ if (aGlyphTable == &gUnicodeTable) {
return true;
}
@@ -1034,7 +937,7 @@ bool nsMathMLChar::StretchEnumContext::TryParts(
// For the Unicode table, we check that all the glyphs are actually found and
// come from the same font.
- if (aGlyphTable == &gGlyphTableList->mUnicodeTable) {
+ if (aGlyphTable == &gUnicodeTable) {
gfxFont* unicodeFont = nullptr;
for (int32_t i = 0; i < 4; i++) {
if (!textRun[i]) {
@@ -1189,20 +1092,19 @@ bool nsMathMLChar::StretchEnumContext::EnumCallback(
// Determine the glyph table to use for this font.
UniquePtr<nsOpenTypeTable> openTypeTable;
- nsGlyphTable* glyphTable;
- if (aFamily.IsGeneric()) {
- // This is a generic font, use the Unicode table.
- glyphTable = &gGlyphTableList->mUnicodeTable;
- } else {
- // If the font contains an Open Type MATH table, use it.
- RefPtr<gfxFont> font = fontGroup->GetFirstValidFont();
- openTypeTable = nsOpenTypeTable::Create(font, aFlags);
- if (openTypeTable) {
- glyphTable = openTypeTable.get();
- } else {
- glyphTable = &gGlyphTableList->mUnicodeTable;
+ auto glyphTable = [&aFamily, &fontGroup, &openTypeTable,
+ &aFlags]() -> nsGlyphTable* {
+ if (!aFamily.IsGeneric()) {
+ // If the font contains an Open Type MATH table, use it.
+ RefPtr<gfxFont> font = fontGroup->GetFirstValidFont();
+ openTypeTable = nsOpenTypeTable::Create(font, aFlags);
+ if (openTypeTable) {
+ return openTypeTable.get();
+ }
}
- }
+ // Fallback to the Unicode table.
+ return &gUnicodeTable;
+ }();
if (!openTypeTable) {
// Make sure we only try the UnicodeTable once.
@@ -1216,8 +1118,7 @@ bool nsMathMLChar::StretchEnumContext::EnumCallback(
// special table is being used then the font in this family should have the
// specified glyphs.
const StyleFontFamilyList& familyList =
- glyphTable == &gGlyphTableList->mUnicodeTable ? context->mFamilyList
- : family;
+ glyphTable == &gUnicodeTable ? context->mFamilyList : family;
return (context->mTryVariants &&
context->TryVariants(glyphTable, &fontGroup, familyList, aRtl)) ||