gecko-dev/gfx/thebes/gfxFontInfoLoader.h

259 lines
7.7 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_FONT_INFO_LOADER_H
#define GFX_FONT_INFO_LOADER_H
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsITimer.h"
#include "nsIThread.h"
#include "nsRefPtrHashtable.h"
#include "nsString.h"
#include "gfxFont.h"
#include "nsIRunnable.h"
#include "mozilla/Atomics.h"
#include "mozilla/TimeStamp.h"
#include "nsISupportsImpl.h"
// data retrieved for a given face
struct FontFaceData {
FontFaceData() : mUVSOffset(0), mSymbolFont(false) {}
FontFaceData(const FontFaceData& aFontFaceData) {
mFullName = aFontFaceData.mFullName;
mPostscriptName = aFontFaceData.mPostscriptName;
mCharacterMap = aFontFaceData.mCharacterMap;
mUVSOffset = aFontFaceData.mUVSOffset;
mSymbolFont = aFontFaceData.mSymbolFont;
}
nsString mFullName;
nsString mPostscriptName;
RefPtr<gfxCharacterMap> mCharacterMap;
uint32_t mUVSOffset;
bool mSymbolFont;
};
// base class used to contain cached system-wide font info.
// methods in this class are called on off-main threads so
// all methods use only static methods or other thread-safe
// font data access API's. specifically, no use is made of
// gfxPlatformFontList, gfxFontFamily, gfxFamily or any
// harfbuzz API methods within FontInfoData subclasses.
class FontInfoData {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FontInfoData)
FontInfoData(bool aLoadOtherNames,
bool aLoadFaceNames,
bool aLoadCmaps) :
mCanceled(false),
mLoadOtherNames(aLoadOtherNames),
mLoadFaceNames(aLoadFaceNames),
mLoadCmaps(aLoadCmaps)
{
MOZ_COUNT_CTOR(FontInfoData);
}
protected:
// Protected destructor, to discourage deletion outside of Release():
virtual ~FontInfoData() {
MOZ_COUNT_DTOR(FontInfoData);
}
public:
virtual void Load();
// loads font data for all fonts of a given family
// (called on async thread)
virtual void LoadFontFamilyData(const nsAString& aFamilyName) = 0;
// -- methods overriden by platform-specific versions --
// fetches cmap data for a particular font from cached font data
virtual already_AddRefed<gfxCharacterMap>
GetCMAP(const nsAString& aFontName,
uint32_t& aUVSOffset,
bool& aSymbolFont)
{
FontFaceData faceData;
if (!mFontFaceData.Get(aFontName, &faceData) ||
!faceData.mCharacterMap) {
return nullptr;
}
aUVSOffset = faceData.mUVSOffset;
aSymbolFont = faceData.mSymbolFont;
RefPtr<gfxCharacterMap> cmap = faceData.mCharacterMap;
return cmap.forget();
}
// fetches fullname/postscript names from cached font data
virtual void GetFaceNames(const nsAString& aFontName,
nsAString& aFullName,
nsAString& aPostscriptName)
{
FontFaceData faceData;
if (!mFontFaceData.Get(aFontName, &faceData)) {
return;
}
aFullName = faceData.mFullName;
aPostscriptName = faceData.mPostscriptName;
}
// fetches localized family name data from cached font data
virtual bool GetOtherFamilyNames(const nsAString& aFamilyName,
nsTArray<nsString>& aOtherFamilyNames)
{
return mOtherFamilyNames.Get(aFamilyName, &aOtherFamilyNames);
}
nsTArray<nsString> mFontFamiliesToLoad;
// currently non-issue but beware,
// this is also set during cleanup after finishing
mozilla::Atomic<bool> mCanceled;
// time spent on the loader thread
mozilla::TimeDuration mLoadTime;
struct FontCounts {
uint32_t families;
uint32_t fonts;
uint32_t cmaps;
uint32_t facenames;
uint32_t othernames;
};
FontCounts mLoadStats;
bool mLoadOtherNames;
bool mLoadFaceNames;
bool mLoadCmaps;
// face name ==> per-face data
nsDataHashtable<nsStringHashKey, FontFaceData> mFontFaceData;
// canonical family name ==> array of localized family names
nsDataHashtable<nsStringHashKey, nsTArray<nsString> > mOtherFamilyNames;
};
// gfxFontInfoLoader - helper class for loading font info on async thread
// For large, "all fonts on system" data, data needed on a given platform
// (e.g. localized names, face names, cmaps) are loaded async.
// helper class for loading in font info on a separate async thread
// once async thread completes, completion process is run on regular
// intervals to prevent tying up the main thread
class gfxFontInfoLoader {
public:
// state transitions:
// initial ---StartLoader with delay---> timer on delay
// initial ---StartLoader without delay---> timer on interval
// timer on delay ---LoaderTimerFire---> timer on interval
// timer on delay ---CancelLoader---> timer off
// timer on interval ---CancelLoader---> timer off
// timer off ---StartLoader with delay---> timer on delay
// timer off ---StartLoader without delay---> timer on interval
typedef enum {
stateInitial,
stateTimerOnDelay,
stateAsyncLoad,
stateTimerOnInterval,
stateTimerOff
} TimerState;
gfxFontInfoLoader() :
mInterval(0), mState(stateInitial)
{
MOZ_COUNT_CTOR(gfxFontInfoLoader);
}
virtual ~gfxFontInfoLoader();
// start timer with an initial delay, then call Run method at regular intervals
void StartLoader(uint32_t aDelay, uint32_t aInterval);
// Finalize - async load complete, transfer data (on intervals if necessary)
virtual void FinalizeLoader(FontInfoData *aFontInfo);
// cancel the timer and cleanup
void CancelLoader();
uint32_t GetInterval() { return mInterval; }
protected:
class ShutdownObserver : public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
explicit ShutdownObserver(gfxFontInfoLoader *aLoader)
: mLoader(aLoader)
{ }
protected:
virtual ~ShutdownObserver()
{ }
gfxFontInfoLoader *mLoader;
};
// CreateFontInfo - create platform-specific object used
// to load system-wide font info
virtual already_AddRefed<FontInfoData> CreateFontInfoData() {
return nullptr;
}
// Init - initialization before async loader thread runs
virtual void InitLoader() = 0;
// LoadFontInfo - transfer font info data within a time limit, return
// true when done
virtual bool LoadFontInfo() = 0;
// Cleanup - finish and cleanup after done, including possible reflows
virtual void CleanupLoader() {
mFontInfo = nullptr;
}
// Timer interval callbacks
static void LoadFontInfoCallback(nsITimer *aTimer, void *aThis) {
gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis);
loader->LoadFontInfoTimerFire();
}
static void DelayedStartCallback(nsITimer *aTimer, void *aThis) {
gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis);
loader->StartLoader(0, loader->GetInterval());
}
void LoadFontInfoTimerFire();
void AddShutdownObserver();
void RemoveShutdownObserver();
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsIObserver> mObserver;
nsCOMPtr<nsIThread> mFontLoaderThread;
uint32_t mInterval;
TimerState mState;
// after async font loader completes, data is stored here
RefPtr<FontInfoData> mFontInfo;
// time spent on the loader thread
mozilla::TimeDuration mLoadTime;
};
#endif /* GFX_FONT_INFO_LOADER_H */