Bug 412859. Some code to dump the contents of the textrun word cache. debug only. r=pavlov
--- a/gfx/thebes/public/gfxFont.h
+++ b/gfx/thebes/public/gfxFont.h
@@ -47,16 +47,20 @@
#include "nsTHashtable.h"
#include "nsHashKeys.h"
#include "gfxSkipChars.h"
#include "gfxRect.h"
#include "nsExpirationTracker.h"
#include "nsMathUtils.h"
#include "nsBidiUtils.h"
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
class gfxContext;
class gfxTextRun;
class nsIAtom;
class gfxFont;
class gfxFontGroup;
#define FONT_STYLE_NORMAL 0
#define FONT_STYLE_ITALIC 1
@@ -1255,16 +1259,18 @@ public:
PRPackedBool mPartIsStartOfLigature;
PRPackedBool mPartIsEndOfLigature;
};
#ifdef DEBUG
// number of entries referencing this textrun in the gfxTextRunWordCache
PRUint32 mCachedWords;
+
+ void Dump(FILE* aOutput);
#endif
protected:
// Allocates extra space for the CompressedGlyph array and the text
// (if needed)
void *operator new(size_t aSize, PRUint32 aLength, PRUint32 aFlags);
/**
--- a/gfx/thebes/src/gfxFont.cpp
+++ b/gfx/thebes/src/gfxFont.cpp
@@ -1974,8 +1974,41 @@ gfxTextRun::FetchGlyphExtents(gfxContext
#endif
font->SetupGlyphExtents(aRefContext, glyphIndex, PR_TRUE, extents);
}
}
}
}
}
}
+
+#ifdef DEBUG
+void
+gfxTextRun::Dump(FILE* aOutput) {
+ if (!aOutput) {
+ aOutput = stdout;
+ }
+
+ PRUint32 i;
+ fputc('"', aOutput);
+ for (i = 0; i < mCharacterCount; ++i) {
+ PRUnichar ch = GetChar(i);
+ if (ch >= 32 && ch < 128) {
+ fputc(ch, aOutput);
+ } else {
+ fprintf(aOutput, "\\u%4x", ch);
+ }
+ }
+ fputs("\" [", aOutput);
+ for (i = 0; i < mGlyphRuns.Length(); ++i) {
+ if (i > 0) {
+ fputc(',', aOutput);
+ }
+ gfxFont* font = mGlyphRuns[i].mFont;
+ const gfxFontStyle* style = font->GetStyle();
+ NS_ConvertUTF16toUTF8 fontName(font->GetName());
+ fprintf(aOutput, "%d: %s %f/%d/%d/%s", mGlyphRuns[i].mCharacterOffset,
+ fontName.get(), style->size,
+ style->weight, style->style, style->langGroup.get());
+ }
+ fputc(']', aOutput);
+}
+#endif
--- a/gfx/thebes/src/gfxTextRunWordCache.cpp
+++ b/gfx/thebes/src/gfxTextRunWordCache.cpp
@@ -32,16 +32,20 @@
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "gfxTextRunWordCache.h"
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
/**
* Cache individual "words" (strings delimited by white-space or white-space-like
* characters that don't involve kerning or ligatures) in textruns.
*/
class TextRunWordCache {
public:
TextRunWordCache() {
mCache.Init(100);
@@ -78,16 +82,20 @@ public:
PRUint32 aFlags);
/**
* Remove a textrun from the cache. This must be called before aTextRun
* is deleted! The text in the textrun must still be valid.
*/
void RemoveTextRun(gfxTextRun *aTextRun);
+#ifdef DEBUG
+ void Dump();
+#endif
+
protected:
struct CacheHashKey {
void *mFontOrGroup;
const void *mString;
PRUint32 mLength;
PRUint32 mAppUnitsPerDevUnit;
PRUint32 mStringHash;
PRPackedBool mIsDoubleByteText;
@@ -153,16 +161,20 @@ protected:
void FinishTextRun(gfxTextRun *aTextRun, gfxTextRun *aNewRun,
gfxContext *aContext,
const nsTArray<DeferredWord>& aDeferredWords,
PRBool aSuccessful);
void RemoveWord(gfxTextRun *aTextRun, PRUint32 aStart,
PRUint32 aEnd, PRUint32 aHash);
nsTHashtable<CacheHashEntry> mCache;
+
+#ifdef DEBUG
+ static PLDHashOperator PR_CALLBACK CacheDumpEntry(CacheHashEntry* aEntry, void* userArg);
+#endif
};
static PRLogModuleInfo *gWordCacheLog = PR_NewLogModule("wordCache");
static inline PRUint32
HashMix(PRUint32 aHash, PRUnichar aCh)
{
return (aHash >> 28) ^ (aHash << 4) ^ aCh;
@@ -655,16 +667,38 @@ TextRunWordCache::CacheHashEntry::KeyEqu
PLDHashNumber
TextRunWordCache::CacheHashEntry::HashKey(const KeyTypePointer aKey)
{
return aKey->mStringHash + (long)aKey->mFontOrGroup + aKey->mAppUnitsPerDevUnit +
aKey->mIsDoubleByteText + aKey->mIsRTL*2 + aKey->mEnabledOptionalLigatures*4 +
aKey->mOptimizeSpeed*8;
}
+#ifdef DEBUG
+PLDHashOperator PR_CALLBACK
+TextRunWordCache::CacheDumpEntry(CacheHashEntry* aEntry, void* userArg)
+{
+ FILE* output = static_cast<FILE*>(userArg);
+ if (!aEntry->mTextRun) {
+ fprintf(output, "<EMPTY>\n");
+ return PL_DHASH_NEXT;
+ }
+ fprintf(output, "Word at %x:%d => ", aEntry->mTextRun, aEntry->mWordOffset);
+ aEntry->mTextRun->Dump(output);
+ fprintf(output, " (hashed by %s)\n", aEntry->mHashedByFont ? "font" : "fontgroup");
+ return PL_DHASH_NEXT;
+}
+
+void
+TextRunWordCache::Dump()
+{
+ mCache.EnumerateEntries(CacheDumpEntry, stdout);
+}
+#endif
+
static TextRunWordCache *gTextRunWordCache = nsnull;
nsresult
gfxTextRunWordCache::Init()
{
gTextRunWordCache = new TextRunWordCache();
return gTextRunWordCache ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}