2014-01-28 23:39:01 -08:00
|
|
|
/* -*- 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
|
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
#include "nsAutoPtr.h"
|
2014-01-28 23:39:01 -08:00
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsIObserver.h"
|
|
|
|
#include "nsITimer.h"
|
2014-01-28 23:39:01 -08:00
|
|
|
#include "nsIThread.h"
|
|
|
|
#include "nsRefPtrHashtable.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "gfxFont.h"
|
|
|
|
#include "nsIRunnable.h"
|
|
|
|
#include "mozilla/TimeStamp.h"
|
2014-02-26 13:36:35 -08:00
|
|
|
#include "nsISupportsImpl.h"
|
2014-01-28 23:39:01 -08:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
nsRefPtr<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) :
|
|
|
|
mLoadOtherNames(aLoadOtherNames),
|
|
|
|
mLoadFaceNames(aLoadFaceNames),
|
|
|
|
mLoadCmaps(aLoadCmaps)
|
2014-04-04 09:27:02 -07:00
|
|
|
{
|
2014-01-28 23:39:01 -08:00
|
|
|
MOZ_COUNT_CTOR(FontInfoData);
|
2014-04-04 09:27:02 -07:00
|
|
|
}
|
2014-01-28 23:39:01 -08:00
|
|
|
|
2014-04-04 09:27:02 -07:00
|
|
|
protected:
|
|
|
|
// Protected destructor, to discourage deletion outside of Release():
|
2014-01-28 23:39:01 -08:00
|
|
|
virtual ~FontInfoData() {
|
|
|
|
MOZ_COUNT_DTOR(FontInfoData);
|
|
|
|
}
|
|
|
|
|
2014-04-04 09:27:02 -07:00
|
|
|
public:
|
2014-01-28 23:39:01 -08:00
|
|
|
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;
|
|
|
|
nsRefPtr<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);
|
|
|
|
}
|
2014-01-28 23:39:01 -08:00
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
nsTArray<nsString> mFontFamiliesToLoad;
|
|
|
|
|
|
|
|
// 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
|
2014-01-28 23:39:01 -08:00
|
|
|
|
|
|
|
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,
|
2014-01-28 23:39:01 -08:00
|
|
|
stateAsyncLoad,
|
2014-01-28 23:39:01 -08:00
|
|
|
stateTimerOnInterval,
|
|
|
|
stateTimerOff
|
|
|
|
} TimerState;
|
|
|
|
|
|
|
|
gfxFontInfoLoader() :
|
|
|
|
mInterval(0), mState(stateInitial)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~gfxFontInfoLoader();
|
|
|
|
|
|
|
|
// start timer with an initial delay, then call Run method at regular intervals
|
|
|
|
void StartLoader(uint32_t aDelay, uint32_t aInterval);
|
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
// Finalize - async load complete, transfer data (on intervals if necessary)
|
|
|
|
virtual void FinalizeLoader(FontInfoData *aFontInfo);
|
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
// cancel the timer and cleanup
|
|
|
|
void CancelLoader();
|
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
uint32_t GetInterval() { return mInterval; }
|
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
protected:
|
|
|
|
class ShutdownObserver : public nsIObserver
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
|
|
|
|
ShutdownObserver(gfxFontInfoLoader *aLoader)
|
|
|
|
: mLoader(aLoader)
|
|
|
|
{ }
|
|
|
|
|
2014-06-23 11:49:07 -07:00
|
|
|
protected:
|
2014-01-28 23:39:01 -08:00
|
|
|
virtual ~ShutdownObserver()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
gfxFontInfoLoader *mLoader;
|
|
|
|
};
|
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
// 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
|
2014-01-28 23:39:01 -08:00
|
|
|
virtual void InitLoader() = 0;
|
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
// LoadFontInfo - transfer font info data within a time limit, return
|
|
|
|
// true when done
|
|
|
|
virtual bool LoadFontInfo() = 0;
|
2014-01-28 23:39:01 -08:00
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
// Cleanup - finish and cleanup after done, including possible reflows
|
|
|
|
virtual void CleanupLoader() {
|
|
|
|
mFontInfo = nullptr;
|
|
|
|
}
|
2014-01-28 23:39:01 -08:00
|
|
|
|
|
|
|
// Timer interval callbacks
|
2014-01-28 23:39:01 -08:00
|
|
|
static void LoadFontInfoCallback(nsITimer *aTimer, void *aThis) {
|
2014-01-28 23:39:01 -08:00
|
|
|
gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis);
|
2014-01-28 23:39:01 -08:00
|
|
|
loader->LoadFontInfoTimerFire();
|
2014-01-28 23:39:01 -08:00
|
|
|
}
|
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
static void DelayedStartCallback(nsITimer *aTimer, void *aThis) {
|
|
|
|
gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis);
|
|
|
|
loader->StartLoader(0, loader->GetInterval());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LoadFontInfoTimerFire();
|
2014-01-28 23:39:01 -08:00
|
|
|
|
2014-01-28 23:39:01 -08:00
|
|
|
void AddShutdownObserver();
|
2014-01-28 23:39:01 -08:00
|
|
|
void RemoveShutdownObserver();
|
|
|
|
|
|
|
|
nsCOMPtr<nsITimer> mTimer;
|
|
|
|
nsCOMPtr<nsIObserver> mObserver;
|
2014-01-28 23:39:01 -08:00
|
|
|
nsCOMPtr<nsIThread> mFontLoaderThread;
|
2014-01-28 23:39:01 -08:00
|
|
|
uint32_t mInterval;
|
|
|
|
TimerState mState;
|
2014-01-28 23:39:01 -08:00
|
|
|
|
|
|
|
// after async font loader completes, data is stored here
|
|
|
|
nsRefPtr<FontInfoData> mFontInfo;
|
|
|
|
|
|
|
|
// time spent on the loader thread
|
|
|
|
mozilla::TimeDuration mLoadTime;
|
2014-01-28 23:39:01 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* GFX_FONT_INFO_LOADER_H */
|