зеркало из https://github.com/mozilla/gecko-dev.git
Bug 962440 - async font info loader infrastructure with OSX implementation. r=bas
This commit is contained in:
Родитель
9df88fff38
Коммит
031132973a
|
@ -147,7 +147,7 @@ GetDirectWriteFaceName(IDWriteFont *aFont,
|
|||
}
|
||||
|
||||
void
|
||||
gfxDWriteFontFamily::FindStyleVariations()
|
||||
gfxDWriteFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (mHasStyles) {
|
||||
|
@ -496,30 +496,38 @@ gfxDWriteFontEntry::GetFontTable(uint32_t aTag)
|
|||
}
|
||||
|
||||
nsresult
|
||||
gfxDWriteFontEntry::ReadCMAP()
|
||||
gfxDWriteFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
if (mCharacterMap) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
nsRefPtr<gfxCharacterMap> charmap;
|
||||
nsresult rv;
|
||||
bool symbolFont;
|
||||
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
AutoTable cmapTable(this, kCMAP);
|
||||
if (cmapTable) {
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
uint32_t cmapLen;
|
||||
const uint8_t* cmapData =
|
||||
reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable,
|
||||
&cmapLen));
|
||||
rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen,
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData,
|
||||
mUVSOffset,
|
||||
symbolFont))) {
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
charmap = new gfxCharacterMap();
|
||||
AutoTable cmapTable(this, kCMAP);
|
||||
|
||||
if (cmapTable) {
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
uint32_t cmapLen;
|
||||
const uint8_t* cmapData =
|
||||
reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable,
|
||||
&cmapLen));
|
||||
rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen,
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
} else {
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
|
|
|
@ -43,7 +43,7 @@ public:
|
|||
: gfxFontFamily(aName), mDWFamily(aFamily), mForceGDIClassic(false) {}
|
||||
virtual ~gfxDWriteFontFamily();
|
||||
|
||||
virtual void FindStyleVariations();
|
||||
virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
virtual void LocalizedName(nsAString& aLocalizedName);
|
||||
|
||||
|
@ -149,7 +149,7 @@ public:
|
|||
|
||||
virtual hb_blob_t* GetFontTable(uint32_t aTableTag) MOZ_OVERRIDE;
|
||||
|
||||
nsresult ReadCMAP();
|
||||
nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
bool IsCJKFont();
|
||||
|
||||
|
|
|
@ -463,7 +463,7 @@ FT2FontEntry::CairoFontFace()
|
|||
}
|
||||
|
||||
nsresult
|
||||
FT2FontEntry::ReadCMAP()
|
||||
FT2FontEntry::ReadCMAP(FontInfoData *aFontInfoData)
|
||||
{
|
||||
if (mCharacterMap) {
|
||||
return NS_OK;
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
// This may fail and return null, so caller must be prepared to handle this.
|
||||
cairo_scaled_font_t *CreateScaledFont(const gfxFontStyle *aStyle);
|
||||
|
||||
nsresult ReadCMAP();
|
||||
nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
virtual hb_blob_t* GetFontTable(uint32_t aTableTag) MOZ_OVERRIDE;
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ uint16_t gfxFontEntry::GetUVSGlyph(uint32_t aCh, uint32_t aVS)
|
|||
return 0;
|
||||
}
|
||||
|
||||
nsresult gfxFontEntry::ReadCMAP()
|
||||
nsresult gfxFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
|
||||
{
|
||||
NS_ASSERTION(false, "using default no-op implementation of ReadCMAP");
|
||||
mCharacterMap = new gfxCharacterMap();
|
||||
|
@ -564,6 +564,18 @@ gfxFontEntry::GetTableFromFontData(const void* aFontData, uint32_t aTableTag)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<gfxCharacterMap>
|
||||
gfxFontEntry::GetCMAPFromFontInfo(FontInfoData *aFontInfoData,
|
||||
uint32_t& aUVSOffset,
|
||||
bool& aSymbolFont)
|
||||
{
|
||||
if (!aFontInfoData || !aFontInfoData->mLoadCmaps) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return aFontInfoData->GetCMAP(mName, aUVSOffset, aSymbolFont);
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxFontEntry::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
|
@ -905,6 +917,11 @@ gfxFontFamily::FindFontForStyle(const gfxFontStyle& aFontStyle,
|
|||
void
|
||||
gfxFontFamily::CheckForSimpleFamily()
|
||||
{
|
||||
// already checked this family
|
||||
if (mIsSimpleFamily) {
|
||||
return;
|
||||
};
|
||||
|
||||
uint32_t count = mAvailableFonts.Length();
|
||||
if (count > 4 || count == 0) {
|
||||
return; // can't be "simple" if there are >4 faces;
|
||||
|
@ -1266,18 +1283,46 @@ gfxFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList)
|
|||
|
||||
void
|
||||
gfxFontFamily::ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
|
||||
bool aNeedFullnamePostscriptNames)
|
||||
bool aNeedFullnamePostscriptNames,
|
||||
FontInfoData *aFontInfoData)
|
||||
{
|
||||
// if all needed names have already been read, skip
|
||||
if (mOtherFamilyNamesInitialized &&
|
||||
(mFaceNamesInitialized || !aNeedFullnamePostscriptNames))
|
||||
return;
|
||||
|
||||
FindStyleVariations();
|
||||
if (!mOtherFamilyNamesInitialized &&
|
||||
aFontInfoData &&
|
||||
aFontInfoData->mLoadOtherNames)
|
||||
{
|
||||
nsAutoTArray<nsString,4> otherFamilyNames;
|
||||
bool foundOtherNames =
|
||||
aFontInfoData->GetOtherFamilyNames(mName, otherFamilyNames);
|
||||
if (foundOtherNames) {
|
||||
uint32_t i, n = otherFamilyNames.Length();
|
||||
for (i = 0; i < n; i++) {
|
||||
aPlatformFontList->AddOtherFamilyName(this, otherFamilyNames[i]);
|
||||
}
|
||||
}
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
}
|
||||
|
||||
// if all needed data has been initialized, return
|
||||
if (mOtherFamilyNamesInitialized &&
|
||||
(mFaceNamesInitialized || !aNeedFullnamePostscriptNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
FindStyleVariations(aFontInfoData);
|
||||
|
||||
// check again, as style enumeration code may have loaded names
|
||||
if (mOtherFamilyNamesInitialized &&
|
||||
(mFaceNamesInitialized || !aNeedFullnamePostscriptNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t i, numFonts = mAvailableFonts.Length();
|
||||
const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e');
|
||||
nsAutoString fullname, psname;
|
||||
|
||||
bool firstTime = true, readAllFaces = false;
|
||||
for (i = 0; i < numFonts; ++i) {
|
||||
|
@ -1285,11 +1330,35 @@ gfxFontFamily::ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
|
|||
if (!fe) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoString fullname, psname;
|
||||
bool foundFaceNames = false;
|
||||
if (!mFaceNamesInitialized &&
|
||||
aNeedFullnamePostscriptNames &&
|
||||
aFontInfoData &&
|
||||
aFontInfoData->mLoadFaceNames) {
|
||||
aFontInfoData->GetFaceNames(fe->Name(), fullname, psname);
|
||||
if (!fullname.IsEmpty()) {
|
||||
aPlatformFontList->AddFullname(fe, fullname);
|
||||
}
|
||||
if (!psname.IsEmpty()) {
|
||||
aPlatformFontList->AddPostscriptName(fe, psname);
|
||||
}
|
||||
foundFaceNames = true;
|
||||
|
||||
// found everything needed? skip to next font
|
||||
if (mOtherFamilyNamesInitialized) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// load directly from the name table
|
||||
gfxFontEntry::AutoTable nameTable(fe, kNAME);
|
||||
if (!nameTable) {
|
||||
continue;
|
||||
}
|
||||
if (aNeedFullnamePostscriptNames) {
|
||||
|
||||
if (aNeedFullnamePostscriptNames && !foundFaceNames) {
|
||||
if (gfxFontUtils::ReadCanonicalName(
|
||||
nameTable, gfxFontUtils::NAME_ID_FULL, fullname) == NS_OK)
|
||||
{
|
||||
|
@ -1341,8 +1410,10 @@ gfxFontFamily::FindFont(const nsAString& aPostscriptName)
|
|||
}
|
||||
|
||||
void
|
||||
gfxFontFamily::ReadAllCMAPs()
|
||||
gfxFontFamily::ReadAllCMAPs(FontInfoData *aFontInfoData)
|
||||
{
|
||||
FindStyleVariations(aFontInfoData);
|
||||
|
||||
uint32_t i, numFonts = mAvailableFonts.Length();
|
||||
for (i = 0; i < numFonts; i++) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
|
@ -1350,7 +1421,7 @@ gfxFontFamily::ReadAllCMAPs()
|
|||
if (!fe || fe->mIsProxy) {
|
||||
continue;
|
||||
}
|
||||
fe->ReadCMAP();
|
||||
fe->ReadCMAP(aFontInfoData);
|
||||
mFamilyCharacterMap.Union(*(fe->mCharacterMap));
|
||||
}
|
||||
mFamilyCharacterMap.Compact();
|
||||
|
|
|
@ -49,6 +49,7 @@ class gfxShapedText;
|
|||
class gfxShapedWord;
|
||||
class gfxSVGGlyphs;
|
||||
class gfxTextContextPaint;
|
||||
class FontInfoData;
|
||||
|
||||
class nsILanguageAtomService;
|
||||
|
||||
|
@ -299,7 +300,7 @@ public:
|
|||
// ReadCMAP() must *always* set the mCharacterMap pointer to a valid
|
||||
// gfxCharacterMap, even if empty, as other code assumes this pointer
|
||||
// can be safely dereferenced.
|
||||
virtual nsresult ReadCMAP();
|
||||
virtual nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
bool TryGetSVGData(gfxFont* aFont);
|
||||
bool HasSVGGlyph(uint32_t aGlyphId);
|
||||
|
@ -491,6 +492,12 @@ protected:
|
|||
// caller is responsible to do any sanitization/validation necessary.
|
||||
hb_blob_t* GetTableFromFontData(const void* aFontData, uint32_t aTableTag);
|
||||
|
||||
// lookup the cmap in cached font data
|
||||
virtual already_AddRefed<gfxCharacterMap>
|
||||
GetCMAPFromFontInfo(FontInfoData *aFontInfoData,
|
||||
uint32_t& aUVSOffset,
|
||||
bool& aSymbolFont);
|
||||
|
||||
// Font's unitsPerEm from the 'head' table, if available (will be set to
|
||||
// kInvalidUPEM for non-sfnt font formats)
|
||||
uint16_t mUnitsPerEm;
|
||||
|
@ -693,6 +700,7 @@ public:
|
|||
}
|
||||
|
||||
// note that the styles for this family have been added
|
||||
bool HasStyles() { return mHasStyles; }
|
||||
void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
|
||||
|
||||
// choose a specific face to match a style using CSS font matching
|
||||
|
@ -729,17 +737,18 @@ public:
|
|||
// read in other localized family names, fullnames and Postscript names
|
||||
// for all faces and append to lookup tables
|
||||
virtual void ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
|
||||
bool aNeedFullnamePostscriptNames);
|
||||
bool aNeedFullnamePostscriptNames,
|
||||
FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
// find faces belonging to this family (platform implementations override this;
|
||||
// should be made pure virtual once all subclasses have been updated)
|
||||
virtual void FindStyleVariations() { }
|
||||
virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) { }
|
||||
|
||||
// search for a specific face using the Postscript name
|
||||
gfxFontEntry* FindFont(const nsAString& aPostscriptName);
|
||||
|
||||
// read in cmaps for all the faces
|
||||
void ReadAllCMAPs();
|
||||
void ReadAllCMAPs(FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
bool TestCharacterMap(uint32_t aCh) {
|
||||
if (!mFamilyCharacterMapInitialized) {
|
||||
|
|
|
@ -6,10 +6,86 @@
|
|||
#include "gfxFontInfoLoader.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsThreadUtils.h" // for nsRunnable
|
||||
#include "gfxPlatformFontList.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using mozilla::services::GetObserverService;
|
||||
|
||||
void
|
||||
FontInfoData::Load()
|
||||
{
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
|
||||
uint32_t i, n = mFontFamiliesToLoad.Length();
|
||||
mLoadStats.families = n;
|
||||
for (i = 0; i < n; i++) {
|
||||
LoadFontFamilyData(mFontFamiliesToLoad[i]);
|
||||
}
|
||||
|
||||
mLoadTime = TimeStamp::Now() - start;
|
||||
}
|
||||
|
||||
class FontInfoLoadCompleteEvent : public nsRunnable {
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
FontInfoLoadCompleteEvent(FontInfoData *aFontInfo) :
|
||||
mFontInfo(aFontInfo)
|
||||
{}
|
||||
virtual ~FontInfoLoadCompleteEvent() {}
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
nsRefPtr<FontInfoData> mFontInfo;
|
||||
};
|
||||
|
||||
class AsyncFontInfoLoader : public nsRunnable {
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
AsyncFontInfoLoader(FontInfoData *aFontInfo) :
|
||||
mFontInfo(aFontInfo)
|
||||
{
|
||||
mCompleteEvent = new FontInfoLoadCompleteEvent(aFontInfo);
|
||||
}
|
||||
virtual ~AsyncFontInfoLoader() {}
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
nsRefPtr<FontInfoData> mFontInfo;
|
||||
nsRefPtr<FontInfoLoadCompleteEvent> mCompleteEvent;
|
||||
};
|
||||
|
||||
// runs on main thread after async font info loading is done
|
||||
nsresult
|
||||
FontInfoLoadCompleteEvent::Run()
|
||||
{
|
||||
gfxFontInfoLoader *loader =
|
||||
static_cast<gfxFontInfoLoader*>(gfxPlatformFontList::PlatformFontList());
|
||||
|
||||
loader->FinalizeLoader(mFontInfo);
|
||||
|
||||
mFontInfo = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(FontInfoLoadCompleteEvent, nsIRunnable);
|
||||
|
||||
// runs on separate thread
|
||||
nsresult
|
||||
AsyncFontInfoLoader::Run()
|
||||
{
|
||||
// load platform-specific font info
|
||||
mFontInfo->Load();
|
||||
|
||||
// post a completion event that transfer the data to the fontlist
|
||||
NS_DispatchToMainThread(mCompleteEvent, NS_DISPATCH_NORMAL);
|
||||
mFontInfo = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(AsyncFontInfoLoader, nsIRunnable);
|
||||
|
||||
NS_IMPL_ISUPPORTS1(gfxFontInfoLoader::ShutdownObserver, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -31,7 +107,9 @@ gfxFontInfoLoader::StartLoader(uint32_t aDelay, uint32_t aInterval)
|
|||
mInterval = aInterval;
|
||||
|
||||
// sanity check
|
||||
if (mState != stateInitial && mState != stateTimerOff) {
|
||||
if (mState != stateInitial &&
|
||||
mState != stateTimerOff &&
|
||||
mState != stateTimerOnDelay) {
|
||||
CancelLoader();
|
||||
}
|
||||
|
||||
|
@ -44,28 +122,55 @@ gfxFontInfoLoader::StartLoader(uint32_t aDelay, uint32_t aInterval)
|
|||
}
|
||||
}
|
||||
|
||||
// need an initial delay?
|
||||
uint32_t timerInterval;
|
||||
AddShutdownObserver();
|
||||
|
||||
// delay? ==> start async thread after a delay
|
||||
if (aDelay) {
|
||||
mState = stateTimerOnDelay;
|
||||
timerInterval = aDelay;
|
||||
} else {
|
||||
mState = stateTimerOnInterval;
|
||||
timerInterval = mInterval;
|
||||
mTimer->InitWithFuncCallback(DelayedStartCallback, this, aDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
return;
|
||||
}
|
||||
|
||||
mFontInfo = CreateFontInfoData();
|
||||
|
||||
// initialize
|
||||
InitLoader();
|
||||
|
||||
// start timer
|
||||
mTimer->InitWithFuncCallback(LoaderTimerCallback, this, timerInterval,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
if (obs) {
|
||||
mObserver = new ShutdownObserver(this);
|
||||
obs->AddObserver(mObserver, "quit-application", false);
|
||||
// start async load
|
||||
mState = stateAsyncLoad;
|
||||
nsresult rv = NS_NewNamedThread("Font Loader",
|
||||
getter_AddRefs(mFontLoaderThread),
|
||||
nullptr);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> loadEvent = new AsyncFontInfoLoader(mFontInfo);
|
||||
|
||||
mFontLoaderThread->Dispatch(loadEvent, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontInfoLoader::FinalizeLoader(FontInfoData *aFontInfo)
|
||||
{
|
||||
// avoid loading data if loader has already been canceled
|
||||
if (mState != stateAsyncLoad) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLoadTime = mFontInfo->mLoadTime;
|
||||
|
||||
// try to load all font data immediately
|
||||
if (LoadFontInfo()) {
|
||||
CancelLoader();
|
||||
return;
|
||||
}
|
||||
|
||||
// not all work completed ==> run load on interval
|
||||
mState = stateTimerOnInterval;
|
||||
mTimer->InitWithFuncCallback(LoadFontInfoCallback, this, mInterval,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -79,19 +184,23 @@ gfxFontInfoLoader::CancelLoader()
|
|||
mTimer->Cancel();
|
||||
mTimer = nullptr;
|
||||
}
|
||||
if (mFontLoaderThread) {
|
||||
mFontLoaderThread->Shutdown();
|
||||
mFontLoaderThread = nullptr;
|
||||
}
|
||||
RemoveShutdownObserver();
|
||||
FinishLoader();
|
||||
CleanupLoader();
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontInfoLoader::LoaderTimerFire()
|
||||
gfxFontInfoLoader::LoadFontInfoTimerFire()
|
||||
{
|
||||
if (mState == stateTimerOnDelay) {
|
||||
mState = stateTimerOnInterval;
|
||||
mTimer->SetDelay(mInterval);
|
||||
}
|
||||
|
||||
bool done = RunLoader();
|
||||
bool done = LoadFontInfo();
|
||||
if (done) {
|
||||
CancelLoader();
|
||||
}
|
||||
|
@ -102,6 +211,20 @@ gfxFontInfoLoader::~gfxFontInfoLoader()
|
|||
RemoveShutdownObserver();
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontInfoLoader::AddShutdownObserver()
|
||||
{
|
||||
if (mObserver) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
if (obs) {
|
||||
mObserver = new ShutdownObserver(this);
|
||||
obs->AddObserver(mObserver, "quit-application", false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontInfoLoader::RemoveShutdownObserver()
|
||||
{
|
||||
|
|
|
@ -6,11 +6,143 @@
|
|||
#ifndef GFX_FONT_INFO_LOADER_H
|
||||
#define GFX_FONT_INFO_LOADER_H
|
||||
|
||||
#include "nsAutoPtr.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/TimeStamp.h"
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
// helper class for loading in font info spaced out at regular intervals
|
||||
// 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)
|
||||
{
|
||||
MOZ_COUNT_CTOR(FontInfoData);
|
||||
}
|
||||
|
||||
virtual ~FontInfoData() {
|
||||
MOZ_COUNT_DTOR(FontInfoData);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
class gfxFontInfoLoader {
|
||||
public:
|
||||
|
@ -26,6 +158,7 @@ public:
|
|||
typedef enum {
|
||||
stateInitial,
|
||||
stateTimerOnDelay,
|
||||
stateAsyncLoad,
|
||||
stateTimerOnInterval,
|
||||
stateTimerOff
|
||||
} TimerState;
|
||||
|
@ -40,9 +173,14 @@ public:
|
|||
// 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
|
||||
{
|
||||
|
@ -61,29 +199,51 @@ protected:
|
|||
gfxFontInfoLoader *mLoader;
|
||||
};
|
||||
|
||||
// Init - initialization at start time after initial delay
|
||||
virtual void InitLoader() = 0;
|
||||
|
||||
// Run - called at intervals, return true to indicate done
|
||||
virtual bool RunLoader() = 0;
|
||||
|
||||
// Finish - cleanup after done
|
||||
virtual void FinishLoader() = 0;
|
||||
|
||||
// Timer interval callbacks
|
||||
static void LoaderTimerCallback(nsITimer *aTimer, void *aThis) {
|
||||
gfxFontInfoLoader *loader = static_cast<gfxFontInfoLoader*>(aThis);
|
||||
loader->LoaderTimerFire();
|
||||
// CreateFontInfo - create platform-specific object used
|
||||
// to load system-wide font info
|
||||
virtual already_AddRefed<FontInfoData> CreateFontInfoData() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void LoaderTimerFire();
|
||||
// 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
|
||||
nsRefPtr<FontInfoData> mFontInfo;
|
||||
|
||||
// time spent on the loader thread
|
||||
mozilla::TimeDuration mLoadTime;
|
||||
};
|
||||
|
||||
#endif /* GFX_FONT_INFO_LOADER_H */
|
||||
|
|
|
@ -146,7 +146,7 @@ GDIFontEntry::GDIFontEntry(const nsAString& aFaceName,
|
|||
}
|
||||
|
||||
nsresult
|
||||
GDIFontEntry::ReadCMAP()
|
||||
GDIFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
|
||||
{
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
if (mCharacterMap) {
|
||||
|
@ -163,22 +163,28 @@ GDIFontEntry::ReadCMAP()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
nsRefPtr<gfxCharacterMap> charmap;
|
||||
nsresult rv;
|
||||
bool unicodeFont = false, symbolFont = false;
|
||||
|
||||
AutoFallibleTArray<uint8_t,16384> cmap;
|
||||
rv = CopyFontTable(kCMAP, cmap);
|
||||
if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData,
|
||||
mUVSOffset,
|
||||
symbolFont))) {
|
||||
mSymbolFont = symbolFont;
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
charmap = new gfxCharacterMap();
|
||||
AutoFallibleTArray<uint8_t,16384> cmap;
|
||||
rv = CopyFontTable(kCMAP, cmap);
|
||||
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
mSymbolFont = symbolFont;
|
||||
}
|
||||
mSymbolFont = symbolFont;
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
if (mHasCmapTable) {
|
||||
|
@ -512,7 +518,7 @@ GDIFontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
|||
}
|
||||
|
||||
void
|
||||
GDIFontFamily::FindStyleVariations()
|
||||
GDIFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
|
||||
{
|
||||
if (mHasStyles)
|
||||
return;
|
||||
|
|
|
@ -108,7 +108,7 @@ class GDIFontEntry : public gfxFontEntry
|
|||
public:
|
||||
LPLOGFONTW GetLogFont() { return &mLogFont; }
|
||||
|
||||
nsresult ReadCMAP();
|
||||
nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
virtual bool IsSymbolFont();
|
||||
|
||||
|
@ -294,7 +294,7 @@ public:
|
|||
GDIFontFamily(nsAString &aName) :
|
||||
gfxFontFamily(aName) {}
|
||||
|
||||
virtual void FindStyleVariations();
|
||||
virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
private:
|
||||
static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
|
||||
nsresult ReadCMAP();
|
||||
nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
|
||||
|
||||
bool RequiresAATLayout() const { return mRequiresAAT; }
|
||||
|
||||
|
@ -116,6 +116,8 @@ private:
|
|||
|
||||
virtual bool UsesSystemFallback() { return true; }
|
||||
|
||||
virtual already_AddRefed<FontInfoData> CreateFontInfoData();
|
||||
|
||||
enum {
|
||||
kATSGenerationInitial = -1
|
||||
};
|
||||
|
|
|
@ -222,30 +222,38 @@ SupportsScriptInGSUB(gfxFontEntry* aFontEntry, const hb_tag_t* aScriptTags)
|
|||
}
|
||||
|
||||
nsresult
|
||||
MacOSFontEntry::ReadCMAP()
|
||||
MacOSFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
|
||||
{
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
if (mCharacterMap) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
|
||||
AutoTable cmapTable(this, kCMAP);
|
||||
nsRefPtr<gfxCharacterMap> charmap;
|
||||
nsresult rv;
|
||||
bool symbolFont;
|
||||
|
||||
if (cmapTable) {
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
uint32_t cmapLen;
|
||||
const char* cmapData = hb_blob_get_data(cmapTable, &cmapLen);
|
||||
rv = gfxFontUtils::ReadCMAP((const uint8_t*)cmapData, cmapLen,
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData,
|
||||
mUVSOffset,
|
||||
symbolFont))) {
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
charmap = new gfxCharacterMap();
|
||||
AutoTable cmapTable(this, kCMAP);
|
||||
|
||||
if (cmapTable) {
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
uint32_t cmapLen;
|
||||
const uint8_t* cmapData =
|
||||
reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable,
|
||||
&cmapLen));
|
||||
rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen,
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
} else {
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !HasGraphiteTables()) {
|
||||
|
@ -446,7 +454,7 @@ public:
|
|||
|
||||
virtual void LocalizedName(nsAString& aLocalizedName);
|
||||
|
||||
virtual void FindStyleVariations();
|
||||
virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr);
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -474,7 +482,7 @@ gfxMacFontFamily::LocalizedName(nsAString& aLocalizedName)
|
|||
}
|
||||
|
||||
void
|
||||
gfxMacFontFamily::FindStyleVariations()
|
||||
gfxMacFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
|
||||
{
|
||||
if (mHasStyles)
|
||||
return;
|
||||
|
@ -1014,3 +1022,139 @@ gfxMacPlatformFontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
|
|||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// used to load system-wide font info on off-main thread
|
||||
class MacFontInfo : public FontInfoData {
|
||||
public:
|
||||
MacFontInfo(bool aLoadOtherNames,
|
||||
bool aLoadFaceNames,
|
||||
bool aLoadCmaps) :
|
||||
FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps)
|
||||
{}
|
||||
|
||||
virtual ~MacFontInfo() {}
|
||||
|
||||
virtual void Load() {
|
||||
nsAutoreleasePool localPool;
|
||||
FontInfoData::Load();
|
||||
}
|
||||
|
||||
// loads font data for all members of a given family
|
||||
virtual void LoadFontFamilyData(const nsAString& aFamilyName);
|
||||
};
|
||||
|
||||
void
|
||||
MacFontInfo::LoadFontFamilyData(const nsAString& aFamilyName)
|
||||
{
|
||||
// family name ==> CTFontDescriptor
|
||||
NSString *famName = GetNSStringForString(aFamilyName);
|
||||
CFStringRef family = CFStringRef(famName);
|
||||
|
||||
CFMutableDictionaryRef attr =
|
||||
CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
CFDictionaryAddValue(attr, kCTFontFamilyNameAttribute, family);
|
||||
CTFontDescriptorRef fd = CTFontDescriptorCreateWithAttributes(attr);
|
||||
CFRelease(attr);
|
||||
CFArrayRef matchingFonts =
|
||||
CTFontDescriptorCreateMatchingFontDescriptors(fd, NULL);
|
||||
CFRelease(fd);
|
||||
if (!matchingFonts) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<nsString> otherFamilyNames;
|
||||
bool hasOtherFamilyNames = true;
|
||||
|
||||
// iterate over faces in the family
|
||||
int f, numFaces = (int) CFArrayGetCount(matchingFonts);
|
||||
for (f = 0; f < numFaces; f++) {
|
||||
mLoadStats.fonts++;
|
||||
|
||||
CTFontDescriptorRef faceDesc =
|
||||
(CTFontDescriptorRef)CFArrayGetValueAtIndex(matchingFonts, f);
|
||||
if (!faceDesc) {
|
||||
continue;
|
||||
}
|
||||
CTFontRef fontRef = CTFontCreateWithFontDescriptor(faceDesc,
|
||||
0.0, nullptr);
|
||||
|
||||
if (mLoadCmaps) {
|
||||
// face name
|
||||
CFStringRef faceName = (CFStringRef)
|
||||
CTFontDescriptorCopyAttribute(faceDesc, kCTFontNameAttribute);
|
||||
|
||||
nsAutoTArray<UniChar, 1024> buffer;
|
||||
CFIndex len = CFStringGetLength(faceName);
|
||||
buffer.SetLength(len+1);
|
||||
CFStringGetCharacters(faceName, ::CFRangeMake(0, len),
|
||||
buffer.Elements());
|
||||
buffer[len] = 0;
|
||||
nsAutoString fontName(reinterpret_cast<char16_t*>(buffer.Elements()),
|
||||
len);
|
||||
|
||||
// load the cmap data
|
||||
FontFaceData fontData;
|
||||
CFDataRef cmapTable = CTFontCopyTable(fontRef, kCTFontTableCmap,
|
||||
kCTFontTableOptionNoOptions);
|
||||
if (cmapTable) {
|
||||
bool unicodeFont = false, symbolFont = false; // ignored
|
||||
const uint8_t *cmapData =
|
||||
(const uint8_t*)CFDataGetBytePtr(cmapTable);
|
||||
uint32_t cmapLen = CFDataGetLength(cmapTable);
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
uint32_t offset;
|
||||
nsresult rv;
|
||||
|
||||
rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen, *charmap, offset,
|
||||
unicodeFont, symbolFont);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
fontData.mCharacterMap = charmap;
|
||||
fontData.mUVSOffset = offset;
|
||||
fontData.mSymbolFont = symbolFont;
|
||||
mLoadStats.cmaps++;
|
||||
}
|
||||
CFRelease(cmapTable);
|
||||
}
|
||||
|
||||
mFontFaceData.Put(fontName, fontData);
|
||||
CFRelease(faceName);
|
||||
}
|
||||
|
||||
if (mLoadOtherNames && hasOtherFamilyNames) {
|
||||
CFDataRef nameTable = CTFontCopyTable(fontRef, kCTFontTableName,
|
||||
kCTFontTableOptionNoOptions);
|
||||
if (nameTable) {
|
||||
const char *nameData = (const char*)CFDataGetBytePtr(nameTable);
|
||||
uint32_t nameLen = CFDataGetLength(nameTable);
|
||||
gfxFontFamily::ReadOtherFamilyNamesForFace(aFamilyName,
|
||||
nameData, nameLen,
|
||||
otherFamilyNames,
|
||||
false);
|
||||
hasOtherFamilyNames = otherFamilyNames.Length() != 0;
|
||||
CFRelease(nameTable);
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(fontRef);
|
||||
}
|
||||
CFRelease(matchingFonts);
|
||||
|
||||
// if found other names, insert them in the hash table
|
||||
if (otherFamilyNames.Length() != 0) {
|
||||
mOtherFamilyNames.Put(aFamilyName, otherFamilyNames);
|
||||
mLoadStats.othernames += otherFamilyNames.Length();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<FontInfoData>
|
||||
gfxMacPlatformFontList::CreateFontInfoData()
|
||||
{
|
||||
bool loadCmaps = !UsesSystemFallback() ||
|
||||
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
|
||||
|
||||
nsRefPtr<MacFontInfo> fi =
|
||||
new MacFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps);
|
||||
return fi.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -558,6 +558,25 @@ static void LogRegistryEvent(const wchar_t *msg)
|
|||
}
|
||||
#endif
|
||||
|
||||
gfxFontFamily*
|
||||
gfxPlatformFontList::CheckFamily(gfxFontFamily *aFamily)
|
||||
{
|
||||
if (aFamily && !aFamily->HasStyles()) {
|
||||
aFamily->FindStyleVariations();
|
||||
aFamily->CheckForSimpleFamily();
|
||||
}
|
||||
|
||||
if (aFamily && aFamily->GetFontList().Length() == 0) {
|
||||
// failed to load any faces for this family, so discard it
|
||||
nsAutoString key;
|
||||
GenerateFontListKey(aFamily->Name(), key);
|
||||
mFontFamilies.Remove(key);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return aFamily;
|
||||
}
|
||||
|
||||
gfxFontFamily*
|
||||
gfxPlatformFontList::FindFamily(const nsAString& aFamily)
|
||||
{
|
||||
|
@ -569,12 +588,12 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily)
|
|||
|
||||
// lookup in canonical (i.e. English) family name list
|
||||
if ((familyEntry = mFontFamilies.GetWeak(key))) {
|
||||
return familyEntry;
|
||||
return CheckFamily(familyEntry);
|
||||
}
|
||||
|
||||
// lookup in other family names list (mostly localized names)
|
||||
if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nullptr) {
|
||||
return familyEntry;
|
||||
return CheckFamily(familyEntry);
|
||||
}
|
||||
|
||||
// name not found and other family names not yet fully initialized so
|
||||
|
@ -585,7 +604,7 @@ gfxPlatformFontList::FindFamily(const nsAString& aFamily)
|
|||
if (!mOtherFamilyNamesInitialized && !IsASCII(aFamily)) {
|
||||
InitOtherFamilyNames();
|
||||
if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nullptr) {
|
||||
return familyEntry;
|
||||
return CheckFamily(familyEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,49 +724,59 @@ gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap)
|
|||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator AppendFamilyToList(nsStringHashKey::KeyType aKey,
|
||||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void *aUserArg)
|
||||
{
|
||||
nsTArray<nsString> *familyNames = static_cast<nsTArray<nsString> *>(aUserArg);
|
||||
familyNames->AppendElement(aFamilyEntry->Name());
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames)
|
||||
{
|
||||
mFontFamilies.Enumerate(AppendFamilyToList, &aFontFamilyNames);
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::InitLoader()
|
||||
{
|
||||
GetFontFamilyList(mFontFamiliesToLoad);
|
||||
GetFontFamilyNames(mFontInfo->mFontFamiliesToLoad);
|
||||
mStartIndex = 0;
|
||||
mNumFamilies = mFontFamiliesToLoad.Length();
|
||||
mNumFamilies = mFontInfo->mFontFamiliesToLoad.Length();
|
||||
memset(&(mFontInfo->mLoadStats), 0, sizeof(mFontInfo->mLoadStats));
|
||||
}
|
||||
|
||||
#define FONT_LOADER_MAX_TIMESLICE 100 // max time for one pass through RunLoader = 100ms
|
||||
|
||||
bool
|
||||
gfxPlatformFontList::RunLoader()
|
||||
gfxPlatformFontList::LoadFontInfo()
|
||||
{
|
||||
TimeStamp start = TimeStamp::Now();
|
||||
uint32_t i, endIndex = (mStartIndex + mIncrement < mNumFamilies ? mStartIndex + mIncrement : mNumFamilies);
|
||||
uint32_t i, endIndex = mNumFamilies;
|
||||
bool loadCmaps = !UsesSystemFallback() ||
|
||||
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
|
||||
|
||||
// for each font family, load in various font info
|
||||
for (i = mStartIndex; i < endIndex; i++) {
|
||||
gfxFontFamily* familyEntry = mFontFamiliesToLoad[i];
|
||||
nsAutoString key;
|
||||
gfxFontFamily *familyEntry;
|
||||
GenerateFontListKey(mFontInfo->mFontFamiliesToLoad[i], key);
|
||||
|
||||
// find all faces that are members of this family
|
||||
familyEntry->FindStyleVariations();
|
||||
if (familyEntry->GetFontList().Length() == 0) {
|
||||
// failed to load any faces for this family, so discard it
|
||||
nsAutoString key;
|
||||
GenerateFontListKey(familyEntry->Name(), key);
|
||||
mFontFamilies.Remove(key);
|
||||
// lookup in canonical (i.e. English) family name list
|
||||
if (!(familyEntry = mFontFamilies.GetWeak(key))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// read in face names
|
||||
familyEntry->ReadFaceNames(this, NeedFullnamePostscriptNames(), mFontInfo);
|
||||
|
||||
// load the cmaps if needed
|
||||
if (loadCmaps) {
|
||||
familyEntry->ReadAllCMAPs();
|
||||
familyEntry->ReadAllCMAPs(mFontInfo);
|
||||
}
|
||||
|
||||
// read in face names
|
||||
familyEntry->ReadFaceNames(this, NeedFullnamePostscriptNames());
|
||||
|
||||
// check whether the family can be considered "simple" for style matching
|
||||
familyEntry->CheckForSimpleFamily();
|
||||
|
||||
// limit the time spent reading fonts in one pass
|
||||
TimeDuration elapsed = TimeStamp::Now() - start;
|
||||
if (elapsed.ToMilliseconds() > FONT_LOADER_MAX_TIMESLICE &&
|
||||
|
@ -758,15 +787,42 @@ gfxPlatformFontList::RunLoader()
|
|||
}
|
||||
|
||||
mStartIndex = endIndex;
|
||||
bool done = mStartIndex >= mNumFamilies;
|
||||
|
||||
return (mStartIndex >= mNumFamilies);
|
||||
#ifdef PR_LOGGING
|
||||
if (LOG_FONTINIT_ENABLED()) {
|
||||
TimeDuration elapsed = TimeStamp::Now() - start;
|
||||
LOG_FONTINIT(("(fontinit) fontloader load pass %8.2f ms done %s\n",
|
||||
elapsed.ToMilliseconds(), (done ? "true" : "false")));
|
||||
}
|
||||
#endif
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformFontList::FinishLoader()
|
||||
gfxPlatformFontList::CleanupLoader()
|
||||
{
|
||||
mFontFamiliesToLoad.Clear();
|
||||
mNumFamilies = 0;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (LOG_FONTINIT_ENABLED() && mFontInfo) {
|
||||
LOG_FONTINIT(("(fontinit) fontloader load thread took %8.2f ms "
|
||||
"%d families %d fonts %d cmaps "
|
||||
"%d facenames %d othernames",
|
||||
mLoadTime.ToMilliseconds(),
|
||||
mFontInfo->mLoadStats.families,
|
||||
mFontInfo->mLoadStats.fonts,
|
||||
mFontInfo->mLoadStats.cmaps,
|
||||
mFontInfo->mLoadStats.facenames,
|
||||
mFontInfo->mLoadStats.othernames));
|
||||
}
|
||||
#endif
|
||||
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
mFaceNamesInitialized = true;
|
||||
gfxFontInfoLoader::CleanupLoader();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -82,7 +82,7 @@ struct FontListSizes {
|
|||
uint32_t mCharMapsSize; // memory used for cmap coverage info
|
||||
};
|
||||
|
||||
class gfxPlatformFontList : protected gfxFontInfoLoader
|
||||
class gfxPlatformFontList : public gfxFontInfoLoader
|
||||
{
|
||||
public:
|
||||
static gfxPlatformFontList* PlatformFontList() {
|
||||
|
@ -211,6 +211,9 @@ protected:
|
|||
// if system fallback is used, no need to load all cmaps
|
||||
virtual bool UsesSystemFallback() { return false; }
|
||||
|
||||
// verifies that a family contains a non-zero font count
|
||||
gfxFontFamily* CheckFamily(gfxFontFamily *aFamily);
|
||||
|
||||
// separate initialization for reading in name tables, since this is expensive
|
||||
void InitOtherFamilyNames();
|
||||
|
||||
|
@ -241,10 +244,12 @@ protected:
|
|||
nsRefPtr<gfxFontFamily>& aFamilyEntry,
|
||||
void* aUserArg);
|
||||
|
||||
virtual void GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames);
|
||||
|
||||
// gfxFontInfoLoader overrides, used to load in font cmaps
|
||||
virtual void InitLoader();
|
||||
virtual bool RunLoader();
|
||||
virtual void FinishLoader();
|
||||
virtual bool LoadFontInfo();
|
||||
virtual void CleanupLoader();
|
||||
|
||||
// read the loader initialization prefs, and start it
|
||||
void GetPrefsAndStartLoader();
|
||||
|
|
Загрузка…
Ссылка в новой задаче