diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 8c0de06e83c..ddb2ed44633 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -89,6 +89,61 @@ gfxCharacterMap::NotifyReleased() delete this; } +gfxFontEntry::gfxFontEntry() : + mItalic(false), mFixedPitch(false), + mIsProxy(false), mIsValid(true), + mIsBadUnderlineFont(false), + mIsUserFont(false), + mIsLocalUserFont(false), + mStandardFace(false), + mSymbolFont(false), + mIgnoreGDEF(false), + mIgnoreGSUB(false), + mSVGInitialized(false), + mHasSpaceFeaturesInitialized(false), + mHasSpaceFeatures(false), + mHasSpaceFeaturesKerning(false), + mHasSpaceFeaturesNonKerning(false), + mHasSpaceFeaturesSubDefault(false), + mCheckedForGraphiteTables(false), + mHasCmapTable(false), + mGrFaceInitialized(false), + mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL), + mUVSOffset(0), mUVSData(nullptr), + mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE), + mHBFace(nullptr), + mGrFace(nullptr), + mGrFaceRefCnt(0) +{ +} + +gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) : + mName(aName), mItalic(false), mFixedPitch(false), + mIsProxy(false), mIsValid(true), + mIsBadUnderlineFont(false), mIsUserFont(false), + mIsLocalUserFont(false), mStandardFace(aIsStandardFace), + mSymbolFont(false), + mIgnoreGDEF(false), + mIgnoreGSUB(false), + mSVGInitialized(false), + mHasSpaceFeaturesInitialized(false), + mHasSpaceFeatures(false), + mHasSpaceFeaturesKerning(false), + mHasSpaceFeaturesNonKerning(false), + mHasSpaceFeaturesSubDefault(false), + mCheckedForGraphiteTables(false), + mHasCmapTable(false), + mGrFaceInitialized(false), + mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL), + mUVSOffset(0), mUVSData(nullptr), + mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE), + mHBFace(nullptr), + mGrFace(nullptr), + mGrFaceRefCnt(0) +{ + memset(&mHasSpaceFeaturesSub, 0, sizeof(mHasSpaceFeaturesSub)); +} + gfxFontEntry::~gfxFontEntry() { // For downloaded fonts, we need to tell the user font cache that this @@ -102,11 +157,6 @@ gfxFontEntry::~gfxFontEntry() // face objects should have been released. MOZ_ASSERT(!mHBFace); MOZ_ASSERT(!mGrFaceInitialized); - - if (mSVGGlyphs) { - delete mSVGGlyphs; - } - delete mUserFontData; } bool gfxFontEntry::IsSymbolFont() @@ -266,7 +316,7 @@ gfxFontEntry::TryGetSVGData(gfxFont* aFont) // gfxSVGGlyphs will hb_blob_destroy() the table when it is finished // with it. - mSVGGlyphs = new gfxSVGGlyphs(svgTable); + mSVGGlyphs = new gfxSVGGlyphs(svgTable, this); } if (!mFontsUsingSVGGlyphs.Contains(aFont)) { diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index b6c05985c4d..8642488dfcf 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -228,35 +228,7 @@ class gfxFontEntry { public: NS_INLINE_DECL_REFCOUNTING(gfxFontEntry) - gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false) : - mName(aName), mItalic(false), mFixedPitch(false), - mIsProxy(false), mIsValid(true), - mIsBadUnderlineFont(false), mIsUserFont(false), - mIsLocalUserFont(false), mStandardFace(aIsStandardFace), - mSymbolFont(false), - mIgnoreGDEF(false), - mIgnoreGSUB(false), - mSVGInitialized(false), - mHasSpaceFeaturesInitialized(false), - mHasSpaceFeatures(false), - mHasSpaceFeaturesKerning(false), - mHasSpaceFeaturesNonKerning(false), - mHasSpaceFeaturesSubDefault(false), - mCheckedForGraphiteTables(false), - mHasCmapTable(false), - mGrFaceInitialized(false), - mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL), - mUVSOffset(0), mUVSData(nullptr), - mUserFontData(nullptr), - mSVGGlyphs(nullptr), - mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE), - mHBFace(nullptr), - mGrFace(nullptr), - mGrFaceRefCnt(0) - { - memset(&mHasSpaceFeaturesSub, 0, sizeof(mHasSpaceFeaturesSub)); - } - + gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false); virtual ~gfxFontEntry(); // unique name for the face, *not* the family; not necessarily the @@ -462,8 +434,8 @@ public: nsRefPtr mCharacterMap; uint32_t mUVSOffset; nsAutoArrayPtr mUVSData; - gfxUserFontData* mUserFontData; - gfxSVGGlyphs *mSVGGlyphs; + nsAutoPtr mUserFontData; + nsAutoPtr mSVGGlyphs; // list of gfxFonts that are using SVG glyphs nsTArray mFontsUsingSVGGlyphs; nsTArray mFeatureSettings; @@ -476,34 +448,7 @@ protected: friend class gfxFontFamily; friend class gfxSingleFaceMacFontFamily; - gfxFontEntry() : - mItalic(false), mFixedPitch(false), - mIsProxy(false), mIsValid(true), - mIsBadUnderlineFont(false), - mIsUserFont(false), - mIsLocalUserFont(false), - mStandardFace(false), - mSymbolFont(false), - mIgnoreGDEF(false), - mIgnoreGSUB(false), - mSVGInitialized(false), - mHasSpaceFeaturesInitialized(false), - mHasSpaceFeatures(false), - mHasSpaceFeaturesKerning(false), - mHasSpaceFeaturesNonKerning(false), - mHasSpaceFeaturesSubDefault(false), - mCheckedForGraphiteTables(false), - mHasCmapTable(false), - mGrFaceInitialized(false), - mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL), - mUVSOffset(0), mUVSData(nullptr), - mUserFontData(nullptr), - mSVGGlyphs(nullptr), - mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE), - mHBFace(nullptr), - mGrFace(nullptr), - mGrFaceRefCnt(0) - { } + gfxFontEntry(); virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) { NS_NOTREACHED("oops, somebody didn't override CreateFontInstance"); diff --git a/gfx/thebes/gfxSVGGlyphs.cpp b/gfx/thebes/gfxSVGGlyphs.cpp index b06ffc4d193..d3e304e31cb 100644 --- a/gfx/thebes/gfxSVGGlyphs.cpp +++ b/gfx/thebes/gfxSVGGlyphs.cpp @@ -31,11 +31,15 @@ #include "nsIScriptSecurityManager.h" #include "nsHostObjectProtocolHandler.h" #include "nsContentUtils.h" +#include "gfxFont.h" +#include "nsSMILAnimationController.h" #include "harfbuzz/hb.h" #define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml") #define UTF8_CHARSET NS_LITERAL_CSTRING("utf-8") +using namespace mozilla; + typedef mozilla::dom::Element Element; mozilla::gfx::UserDataKey gfxTextContextPaint::sUserDataKey; @@ -44,10 +48,10 @@ const float gfxSVGGlyphs::SVG_UNITS_PER_EM = 1000.0f; const gfxRGBA SimpleTextContextPaint::sZero = gfxRGBA(0.0f, 0.0f, 0.0f, 0.0f); -gfxSVGGlyphs::gfxSVGGlyphs(hb_blob_t *aSVGTable) +gfxSVGGlyphs::gfxSVGGlyphs(hb_blob_t *aSVGTable, gfxFontEntry *aFontEntry) + : mSVGData(aSVGTable) + , mFontEntry(aFontEntry) { - mSVGData = aSVGTable; - unsigned int length; const char* svgData = hb_blob_get_data(mSVGData, &length); mHeader = reinterpret_cast(svgData); @@ -70,6 +74,12 @@ gfxSVGGlyphs::~gfxSVGGlyphs() hb_blob_destroy(mSVGData); } +void +gfxSVGGlyphs::DidRefresh() +{ + mFontEntry->NotifyGlyphsChanged(); +} + /* * Comparison operator for finding a range containing a given glyph ID. Simply * checks whether |key| is less (greater) than every element of |range|, in @@ -120,7 +130,7 @@ gfxSVGGlyphs::FindOrCreateGlyphsDocument(uint32_t aGlyphId) if (entry->mDocOffset > 0 && uint64_t(mHeader->mDocIndexOffset) + entry->mDocOffset + entry->mDocLength <= length) { result = new gfxSVGGlyphsDocument(data + mHeader->mDocIndexOffset + entry->mDocOffset, - entry->mDocLength); + entry->mDocLength, this); mGlyphDocs.Put(entry->mDocOffset, result); } } @@ -131,8 +141,6 @@ gfxSVGGlyphs::FindOrCreateGlyphsDocument(uint32_t aGlyphId) nsresult gfxSVGGlyphsDocument::SetupPresentation() { - mDocument->SetIsBeingUsedAsImage(); - nsCOMPtr catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID); nsXPIDLCString contractId; nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", "image/svg+xml", getter_Copies(contractId)); @@ -154,22 +162,36 @@ gfxSVGGlyphsDocument::SetupPresentation() nsCOMPtr presShell; rv = viewer->GetPresShell(getter_AddRefs(presShell)); NS_ENSURE_SUCCESS(rv, rv); - presShell->GetPresContext()->SetIsGlyph(true); + nsPresContext* presContext = presShell->GetPresContext(); + presContext->SetIsGlyph(true); if (!presShell->DidInitialize()) { - nsRect rect = presShell->GetPresContext()->GetVisibleArea(); + nsRect rect = presContext->GetVisibleArea(); rv = presShell->Initialize(rect.width, rect.height); NS_ENSURE_SUCCESS(rv, rv); } mDocument->FlushPendingNotifications(Flush_Layout); + nsSMILAnimationController* controller = mDocument->GetAnimationController(); + if (controller) { + controller->Resume(nsSMILTimeContainer::PAUSE_IMAGE); + } + mDocument->SetImagesNeedAnimating(true); + mViewer = viewer; mPresShell = presShell; + mPresShell->AddPostRefreshObserver(this); return NS_OK; } +void +gfxSVGGlyphsDocument::DidRefresh() +{ + mOwner->DidRefresh(); +} + /** * Walk the DOM tree to find all glyph elements and insert them into the lookup * table @@ -251,7 +273,10 @@ gfxSVGGlyphsDocument::GetGlyphElement(uint32_t aGlyphId) return mGlyphIdMap.Get(aGlyphId); } -gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBufLen) +gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t *aBuffer, + uint32_t aBufLen, + gfxSVGGlyphs *aSVGGlyphs) + : mOwner(aSVGGlyphs) { ParseDocument(aBuffer, aBufLen); if (!mDocument) { @@ -274,6 +299,22 @@ gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBuf FindGlyphElements(root); } +gfxSVGGlyphsDocument::~gfxSVGGlyphsDocument() +{ + if (mDocument) { + nsSMILAnimationController* controller = mDocument->GetAnimationController(); + if (controller) { + controller->Pause(nsSMILTimeContainer::PAUSE_PAGEHIDE); + } + } + if (mPresShell) { + mPresShell->RemovePostRefreshObserver(this); + } + if (mViewer) { + mViewer->Destroy(); + } +} + static nsresult CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen, nsCOMPtr &aResult) @@ -339,6 +380,8 @@ gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen) channel->SetOwner(principal); + // Set this early because various decisions during page-load depend on it. + document->SetIsBeingUsedAsImage(); document->SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED); nsCOMPtr listener; diff --git a/gfx/thebes/gfxSVGGlyphs.h b/gfx/thebes/gfxSVGGlyphs.h index 7d8f5c925a9..0174b6eff9d 100644 --- a/gfx/thebes/gfxSVGGlyphs.h +++ b/gfx/thebes/gfxSVGGlyphs.h @@ -17,6 +17,9 @@ #include "gfxPattern.h" #include "gfxFont.h" #include "mozilla/gfx/UserData.h" +#include "nsRefreshDriver.h" + +class gfxSVGGlyphs; /** @@ -27,21 +30,20 @@ * Finds and looks up elements contained in the SVG document which have glyph * mappings to be drawn by gfxSVGGlyphs */ -class gfxSVGGlyphsDocument +class gfxSVGGlyphsDocument MOZ_FINAL : public nsAPostRefreshObserver { typedef mozilla::dom::Element Element; typedef gfxFont::DrawMode DrawMode; public: - gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBufLen); + gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBufLen, + gfxSVGGlyphs *aSVGGlyphs); Element *GetGlyphElement(uint32_t aGlyphId); - ~gfxSVGGlyphsDocument() { - if (mViewer) { - mViewer->Destroy(); - } - } + ~gfxSVGGlyphsDocument(); + + virtual void DidRefresh() MOZ_OVERRIDE; private: nsresult ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen); @@ -52,6 +54,8 @@ private: void InsertGlyphId(Element *aGlyphElement); + // Weak so as not to create a cycle. mOwner owns us so this can't dangle. + gfxSVGGlyphs* mOwner; nsCOMPtr mDocument; nsCOMPtr mViewer; nsCOMPtr mPresShell; @@ -83,13 +87,18 @@ public: * that are passed in, and will hb_blob_destroy() them when finished; * the caller should -not- destroy these references. */ - gfxSVGGlyphs(hb_blob_t *aSVGTable); + gfxSVGGlyphs(hb_blob_t *aSVGTable, gfxFontEntry *aFontEntry); /** - * Releases our references to the SVG table. + * Releases our references to the SVG table and cleans up everything else. */ ~gfxSVGGlyphs(); + /** + * This is called when the refresh driver has ticked. + */ + void DidRefresh(); + /** * Find the |gfxSVGGlyphsDocument| containing an SVG glyph for |aGlyphId|. * If |aGlyphId| does not map to an SVG document, return null. @@ -126,6 +135,7 @@ private: nsBaseHashtable mGlyphIdMap; hb_blob_t *mSVGData; + gfxFontEntry *mFontEntry; const struct Header { mozilla::AutoSwap_PRUint16 mVersion;