Bug 906643. Part 7: Hook up animation support for gfxSVGGlyphs. r=jfkthame

There's a few things mashed together in this patch:
-- Enable animations in glyph documents
-- Make gfxSVGGlyphsDocument monitor the document's refresh driver to detect
updates
-- Forward updates to the gfxFontEntry
This commit is contained in:
Robert O'Callahan 2013-08-20 01:08:45 +12:00
parent 4e461c3ef8
commit 82ad22f4ba
4 changed files with 131 additions and 83 deletions

View File

@ -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)) {

View File

@ -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<gfxCharacterMap> mCharacterMap;
uint32_t mUVSOffset;
nsAutoArrayPtr<uint8_t> mUVSData;
gfxUserFontData* mUserFontData;
gfxSVGGlyphs *mSVGGlyphs;
nsAutoPtr<gfxUserFontData> mUserFontData;
nsAutoPtr<gfxSVGGlyphs> mSVGGlyphs;
// list of gfxFonts that are using SVG glyphs
nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
nsTArray<gfxFontFeature> 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");

View File

@ -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<const Header*>(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<nsICategoryManager> 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<nsIPresShell> 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<nsIInputStream> &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<nsIStreamListener> listener;

View File

@ -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<nsIDocument> mDocument;
nsCOMPtr<nsIContentViewer> mViewer;
nsCOMPtr<nsIPresShell> 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<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
hb_blob_t *mSVGData;
gfxFontEntry *mFontEntry;
const struct Header {
mozilla::AutoSwap_PRUint16 mVersion;