2009-08-16 17:52:12 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
2012-05-21 15:12:37 +04:00
|
|
|
* 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/. */
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2015-05-19 21:15:34 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2017-03-13 06:39:22 +03:00
|
|
|
#include "mozilla/intl/LocaleService.h"
|
2018-03-07 05:55:22 +03:00
|
|
|
#include "mozilla/intl/MozLocale.h"
|
2017-03-22 10:27:14 +03:00
|
|
|
#include "mozilla/intl/OSPreferences.h"
|
2011-01-21 19:44:33 +03:00
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
#include "gfxPlatformFontList.h"
|
2014-09-16 13:58:12 +04:00
|
|
|
#include "gfxTextRun.h"
|
2014-04-17 18:17:22 +04:00
|
|
|
#include "gfxUserFontSet.h"
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
#include "nsCRT.h"
|
2015-09-29 04:51:28 +03:00
|
|
|
#include "nsGkAtoms.h"
|
|
|
|
#include "nsServiceManagerUtils.h"
|
2009-08-16 17:52:12 +04:00
|
|
|
#include "nsUnicharUtils.h"
|
2011-01-21 19:44:33 +03:00
|
|
|
#include "nsUnicodeRange.h"
|
2012-02-24 14:15:46 +04:00
|
|
|
#include "nsUnicodeProperties.h"
|
2017-11-02 23:29:33 +03:00
|
|
|
#include "nsXULAppAPI.h"
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2012-10-26 17:32:10 +04:00
|
|
|
#include "mozilla/Attributes.h"
|
|
|
|
#include "mozilla/Likely.h"
|
2013-06-23 16:03:39 +04:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
2017-09-12 21:05:37 +03:00
|
|
|
#include "mozilla/Mutex.h"
|
2011-06-12 06:30:16 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2011-07-27 10:42:53 +04:00
|
|
|
#include "mozilla/Telemetry.h"
|
2011-11-30 05:55:11 +04:00
|
|
|
#include "mozilla/TimeStamp.h"
|
2017-11-02 23:29:33 +03:00
|
|
|
#include "mozilla/dom/ContentParent.h"
|
2013-10-08 03:15:59 +04:00
|
|
|
#include "mozilla/gfx/2D.h"
|
2011-06-12 06:30:16 +04:00
|
|
|
|
2016-01-15 10:33:51 +03:00
|
|
|
#include <locale.h>
|
|
|
|
|
2011-06-12 06:30:16 +04:00
|
|
|
using namespace mozilla;
|
2017-03-13 06:39:22 +03:00
|
|
|
using mozilla::intl::LocaleService;
|
2018-03-07 05:55:22 +03:00
|
|
|
using mozilla::intl::Locale;
|
2017-03-22 10:27:14 +03:00
|
|
|
using mozilla::intl::OSPreferences;
|
2011-06-12 06:30:16 +04:00
|
|
|
|
2015-05-21 23:22:04 +03:00
|
|
|
#define LOG_FONTLIST(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
|
2015-06-04 01:25:57 +03:00
|
|
|
LogLevel::Debug, args)
|
2015-06-04 01:22:28 +03:00
|
|
|
#define LOG_FONTLIST_ENABLED() MOZ_LOG_TEST( \
|
2011-01-21 19:44:33 +03:00
|
|
|
gfxPlatform::GetLog(eGfxLog_fontlist), \
|
2015-06-04 01:25:57 +03:00
|
|
|
LogLevel::Debug)
|
2015-05-21 23:22:04 +03:00
|
|
|
#define LOG_FONTINIT(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontinit), \
|
2015-06-04 01:25:57 +03:00
|
|
|
LogLevel::Debug, args)
|
2015-06-04 01:22:28 +03:00
|
|
|
#define LOG_FONTINIT_ENABLED() MOZ_LOG_TEST( \
|
2013-12-11 04:58:27 +04:00
|
|
|
gfxPlatform::GetLog(eGfxLog_fontinit), \
|
2015-06-04 01:25:57 +03:00
|
|
|
LogLevel::Debug)
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
gfxPlatformFontList *gfxPlatformFontList::sPlatformFontList = nullptr;
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2014-05-05 22:59:55 +04:00
|
|
|
// Character ranges that require complex-script shaping support in the font,
|
|
|
|
// and so should be masked out by ReadCMAP if the necessary layout tables
|
|
|
|
// are not present.
|
|
|
|
// Currently used by the Mac and FT2 implementations only, but probably should
|
|
|
|
// be supported on Windows as well.
|
|
|
|
const gfxFontEntry::ScriptRange gfxPlatformFontList::sComplexScriptRanges[] = {
|
|
|
|
// Actually, now that harfbuzz supports presentation-forms shaping for
|
|
|
|
// Arabic, we can render it without layout tables. So maybe we don't
|
|
|
|
// want to mask the basic Arabic block here?
|
|
|
|
// This affects the arabic-fallback-*.html reftests, which rely on
|
|
|
|
// loading a font that *doesn't* have any GSUB table.
|
|
|
|
{ 0x0600, 0x06FF, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
|
|
|
|
{ 0x0700, 0x074F, { TRUETYPE_TAG('s','y','r','c'), 0, 0 } },
|
|
|
|
{ 0x0750, 0x077F, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
|
|
|
|
{ 0x08A0, 0x08FF, { TRUETYPE_TAG('a','r','a','b'), 0, 0 } },
|
|
|
|
{ 0x0900, 0x097F, { TRUETYPE_TAG('d','e','v','2'),
|
|
|
|
TRUETYPE_TAG('d','e','v','a'), 0 } },
|
|
|
|
{ 0x0980, 0x09FF, { TRUETYPE_TAG('b','n','g','2'),
|
|
|
|
TRUETYPE_TAG('b','e','n','g'), 0 } },
|
|
|
|
{ 0x0A00, 0x0A7F, { TRUETYPE_TAG('g','u','r','2'),
|
|
|
|
TRUETYPE_TAG('g','u','r','u'), 0 } },
|
|
|
|
{ 0x0A80, 0x0AFF, { TRUETYPE_TAG('g','j','r','2'),
|
|
|
|
TRUETYPE_TAG('g','u','j','r'), 0 } },
|
|
|
|
{ 0x0B00, 0x0B7F, { TRUETYPE_TAG('o','r','y','2'),
|
|
|
|
TRUETYPE_TAG('o','r','y','a'), 0 } },
|
|
|
|
{ 0x0B80, 0x0BFF, { TRUETYPE_TAG('t','m','l','2'),
|
|
|
|
TRUETYPE_TAG('t','a','m','l'), 0 } },
|
|
|
|
{ 0x0C00, 0x0C7F, { TRUETYPE_TAG('t','e','l','2'),
|
|
|
|
TRUETYPE_TAG('t','e','l','u'), 0 } },
|
|
|
|
{ 0x0C80, 0x0CFF, { TRUETYPE_TAG('k','n','d','2'),
|
|
|
|
TRUETYPE_TAG('k','n','d','a'), 0 } },
|
|
|
|
{ 0x0D00, 0x0D7F, { TRUETYPE_TAG('m','l','m','2'),
|
|
|
|
TRUETYPE_TAG('m','l','y','m'), 0 } },
|
|
|
|
{ 0x0D80, 0x0DFF, { TRUETYPE_TAG('s','i','n','h'), 0, 0 } },
|
|
|
|
{ 0x0E80, 0x0EFF, { TRUETYPE_TAG('l','a','o',' '), 0, 0 } },
|
|
|
|
{ 0x0F00, 0x0FFF, { TRUETYPE_TAG('t','i','b','t'), 0, 0 } },
|
|
|
|
{ 0x1000, 0x109f, { TRUETYPE_TAG('m','y','m','r'),
|
|
|
|
TRUETYPE_TAG('m','y','m','2'), 0 } },
|
|
|
|
{ 0x1780, 0x17ff, { TRUETYPE_TAG('k','h','m','r'), 0, 0 } },
|
|
|
|
// Khmer Symbols (19e0..19ff) don't seem to need any special shaping
|
|
|
|
{ 0xaa60, 0xaa7f, { TRUETYPE_TAG('m','y','m','r'),
|
|
|
|
TRUETYPE_TAG('m','y','m','2'), 0 } },
|
|
|
|
// Thai seems to be "renderable" without AAT morphing tables
|
|
|
|
{ 0, 0, { 0, 0, 0 } } // terminator
|
|
|
|
};
|
|
|
|
|
2013-04-26 11:40:44 +04:00
|
|
|
// prefs for the font info loader
|
|
|
|
#define FONT_LOADER_DELAY_PREF "gfx.font_loader.delay"
|
|
|
|
#define FONT_LOADER_INTERVAL_PREF "gfx.font_loader.interval"
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2011-06-12 06:30:16 +04:00
|
|
|
static const char* kObservedPrefs[] = {
|
|
|
|
"font.",
|
|
|
|
"font.name-list.",
|
|
|
|
"intl.accept_languages", // hmmmm...
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr
|
2011-06-12 06:30:16 +04:00
|
|
|
};
|
|
|
|
|
2016-08-23 03:06:07 +03:00
|
|
|
static const char kFontSystemWhitelistPref[] = "font.system.whitelist";
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
// xxx - this can probably be eliminated by reworking pref font handling code
|
|
|
|
static const char *gPrefLangNames[] = {
|
|
|
|
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) str_
|
|
|
|
#include "gfxFontPrefLangList.h"
|
|
|
|
#undef FONT_PREF_LANG
|
|
|
|
};
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
static_assert(MOZ_ARRAY_LENGTH(gPrefLangNames) == uint32_t(eFontPrefLang_Count),
|
|
|
|
"size of pref lang name array doesn't match pref lang enum size");
|
|
|
|
|
2015-03-21 19:28:04 +03:00
|
|
|
class gfxFontListPrefObserver final : public nsIObserver {
|
2014-06-23 22:49:07 +04:00
|
|
|
~gfxFontListPrefObserver() {}
|
2009-08-16 17:52:12 +04:00
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
};
|
|
|
|
|
2018-07-06 00:47:39 +03:00
|
|
|
static void
|
|
|
|
FontListPrefChanged(const char* aPref, void* aData = nullptr)
|
|
|
|
{
|
|
|
|
// XXX this could be made to only clear out the cache for the prefs that were changed
|
|
|
|
// but it probably isn't that big a deal.
|
|
|
|
gfxPlatformFontList::PlatformFontList()->ClearLangGroupPrefFonts();
|
|
|
|
gfxFontCache::GetCache()->AgeAllGenerations();
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
static gfxFontListPrefObserver* gFontListPrefObserver = nullptr;
|
2011-06-12 06:30:16 +04:00
|
|
|
|
2014-04-27 11:06:00 +04:00
|
|
|
NS_IMPL_ISUPPORTS(gfxFontListPrefObserver, nsIObserver)
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2017-11-21 14:02:20 +03:00
|
|
|
#define LOCALES_CHANGED_TOPIC "intl:system-locales-changed"
|
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
gfxFontListPrefObserver::Observe(nsISupports *aSubject,
|
|
|
|
const char *aTopic,
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t *aData)
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
2018-07-06 00:47:39 +03:00
|
|
|
NS_ASSERTION(!strcmp(aTopic, LOCALES_CHANGED_TOPIC), "invalid topic");
|
|
|
|
FontListPrefChanged(nullptr);
|
|
|
|
|
|
|
|
if (XRE_IsParentProcess()) {
|
2017-11-21 14:02:20 +03:00
|
|
|
gfxPlatform::ForceGlobalReflow();
|
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-12-08 09:38:32 +04:00
|
|
|
MOZ_DEFINE_MALLOC_SIZE_OF(FontListMallocSizeOf)
|
2012-03-28 01:38:39 +04:00
|
|
|
|
2014-04-27 11:06:00 +04:00
|
|
|
NS_IMPL_ISUPPORTS(gfxPlatformFontList::MemoryReporter, nsIMemoryReporter)
|
2012-03-28 01:38:39 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2014-05-21 10:06:54 +04:00
|
|
|
gfxPlatformFontList::MemoryReporter::CollectReports(
|
2016-08-24 08:23:45 +03:00
|
|
|
nsIHandleReportCallback* aHandleReport, nsISupports* aData, bool aAnonymize)
|
2012-03-28 01:38:39 +04:00
|
|
|
{
|
|
|
|
FontListSizes sizes;
|
|
|
|
sizes.mFontListSize = 0;
|
|
|
|
sizes.mFontTableCacheSize = 0;
|
|
|
|
sizes.mCharMapsSize = 0;
|
2018-04-05 23:27:07 +03:00
|
|
|
sizes.mLoaderSize = 0;
|
2012-03-28 01:38:39 +04:00
|
|
|
|
2013-10-15 06:19:47 +04:00
|
|
|
gfxPlatformFontList::PlatformFontList()->AddSizeOfIncludingThis(&FontListMallocSizeOf,
|
|
|
|
&sizes);
|
2012-03-28 01:38:39 +04:00
|
|
|
|
2016-08-24 08:23:45 +03:00
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
"explicit/gfx/font-list", KIND_HEAP, UNITS_BYTES,
|
|
|
|
sizes.mFontListSize,
|
|
|
|
"Memory used to manage the list of font families and faces.");
|
|
|
|
|
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
"explicit/gfx/font-charmaps", KIND_HEAP, UNITS_BYTES,
|
|
|
|
sizes.mCharMapsSize,
|
|
|
|
"Memory used to record the character coverage of individual fonts.");
|
2012-03-28 01:38:39 +04:00
|
|
|
|
|
|
|
if (sizes.mFontTableCacheSize) {
|
2016-08-24 08:23:45 +03:00
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
"explicit/gfx/font-tables", KIND_HEAP, UNITS_BYTES,
|
|
|
|
sizes.mFontTableCacheSize,
|
|
|
|
"Memory used for cached font metrics and layout tables.");
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
|
|
|
|
2018-04-05 23:27:07 +03:00
|
|
|
if (sizes.mLoaderSize) {
|
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
"explicit/gfx/font-loader", KIND_HEAP, UNITS_BYTES,
|
|
|
|
sizes.mLoaderSize,
|
|
|
|
"Memory used for (platform-specific) font loader.");
|
|
|
|
}
|
|
|
|
|
2012-03-28 01:38:39 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
|
2017-09-12 21:05:37 +03:00
|
|
|
: mFontFamiliesMutex("gfxPlatformFontList::mFontFamiliesMutex"), mFontFamilies(64),
|
|
|
|
mOtherFamilyNames(16), mBadUnderlineFamilyNames(8), mSharedCmaps(8),
|
2018-02-22 23:55:39 +03:00
|
|
|
mStartIndex(0), mNumFamilies(0), mFontlistInitCount(0),
|
2016-08-23 03:06:07 +03:00
|
|
|
mFontFamilyWhitelistActive(false)
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
2011-10-17 18:59:28 +04:00
|
|
|
mOtherFamilyNamesInitialized = false;
|
2010-01-29 04:41:25 +03:00
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
if (aNeedFullnamePostscriptNames) {
|
2016-04-15 22:45:37 +03:00
|
|
|
mExtraNames = MakeUnique<ExtraNames>();
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
2014-04-23 09:20:20 +04:00
|
|
|
mFaceNameListsInitialized = false;
|
2010-01-29 04:41:25 +03:00
|
|
|
|
2015-04-03 22:39:23 +03:00
|
|
|
mLangService = nsLanguageAtomService::GetService();
|
|
|
|
|
2010-01-28 09:56:16 +03:00
|
|
|
LoadBadUnderlineList();
|
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
// pref changes notification setup
|
2011-06-12 06:30:16 +04:00
|
|
|
NS_ASSERTION(!gFontListPrefObserver,
|
|
|
|
"There has been font list pref observer already");
|
|
|
|
gFontListPrefObserver = new gfxFontListPrefObserver();
|
|
|
|
NS_ADDREF(gFontListPrefObserver);
|
2018-07-06 00:47:39 +03:00
|
|
|
|
|
|
|
Preferences::RegisterPrefixCallbacks(FontListPrefChanged, kObservedPrefs);
|
2012-04-19 03:59:43 +04:00
|
|
|
|
2017-11-21 14:02:20 +03:00
|
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
|
|
if (obs) {
|
|
|
|
obs->AddObserver(gFontListPrefObserver, LOCALES_CHANGED_TOPIC, false);
|
|
|
|
}
|
|
|
|
|
2017-11-02 23:29:33 +03:00
|
|
|
// Only the parent process listens for whitelist changes; it will then
|
|
|
|
// notify its children to rebuild their font lists.
|
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
Preferences::RegisterCallback(FontWhitelistPrefChanged,
|
|
|
|
kFontSystemWhitelistPref);
|
|
|
|
}
|
2016-08-23 03:06:07 +03:00
|
|
|
|
2013-11-07 09:35:30 +04:00
|
|
|
RegisterStrongMemoryReporter(new MemoryReporter());
|
2011-06-12 06:30:16 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxPlatformFontList::~gfxPlatformFontList()
|
|
|
|
{
|
2012-04-19 03:59:43 +04:00
|
|
|
mSharedCmaps.Clear();
|
2015-09-29 04:51:29 +03:00
|
|
|
ClearLangGroupPrefFonts();
|
2011-06-12 06:30:16 +04:00
|
|
|
NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
|
2018-07-06 00:47:39 +03:00
|
|
|
|
|
|
|
Preferences::UnregisterPrefixCallbacks(FontListPrefChanged, kObservedPrefs);
|
2017-11-21 14:02:20 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
|
|
if (obs) {
|
|
|
|
obs->RemoveObserver(gFontListPrefObserver, LOCALES_CHANGED_TOPIC);
|
|
|
|
}
|
|
|
|
|
2017-11-02 23:29:33 +03:00
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
Preferences::UnregisterCallback(FontWhitelistPrefChanged,
|
|
|
|
kFontSystemWhitelistPref);
|
|
|
|
}
|
2011-06-12 06:30:16 +04:00
|
|
|
NS_RELEASE(gFontListPrefObserver);
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2017-11-02 23:29:33 +03:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::FontWhitelistPrefChanged(const char *aPref,
|
|
|
|
void *aClosure)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
gfxPlatformFontList::PlatformFontList()->UpdateFontList();
|
|
|
|
mozilla::dom::ContentParent::NotifyUpdatedFonts();
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
// number of CSS generic font families
|
|
|
|
const uint32_t kNumGenerics = 5;
|
|
|
|
|
2016-08-23 03:06:07 +03:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::ApplyWhitelist()
|
|
|
|
{
|
|
|
|
nsTArray<nsString> list;
|
|
|
|
gfxFontUtils::GetPrefsFontList(kFontSystemWhitelistPref, list);
|
|
|
|
uint32_t numFonts = list.Length();
|
|
|
|
mFontFamilyWhitelistActive = (numFonts > 0);
|
|
|
|
if (!mFontFamilyWhitelistActive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsTHashtable<nsStringHashKey> familyNamesWhitelist;
|
|
|
|
for (uint32_t i = 0; i < numFonts; i++) {
|
|
|
|
nsString key;
|
|
|
|
ToLowerCase(list[i], key);
|
|
|
|
familyNamesWhitelist.PutEntry(key);
|
|
|
|
}
|
|
|
|
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
// Don't continue if we only have one font left.
|
|
|
|
if (mFontFamilies.Count() == 1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nsString fontFamilyName(iter.Key());
|
|
|
|
ToLowerCase(fontFamilyName);
|
|
|
|
if (!familyNamesWhitelist.Contains(fontFamilyName)) {
|
|
|
|
iter.Remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-01 13:25:35 +03:00
|
|
|
bool
|
|
|
|
gfxPlatformFontList::AddWithLegacyFamilyName(const nsAString& aLegacyName,
|
|
|
|
gfxFontEntry* aFontEntry)
|
|
|
|
{
|
|
|
|
bool added = false;
|
|
|
|
nsAutoString key;
|
|
|
|
ToLowerCase(aLegacyName, key);
|
|
|
|
gfxFontFamily* family = mOtherFamilyNames.GetWeak(key);
|
|
|
|
if (!family) {
|
|
|
|
family = CreateFontFamily(aLegacyName);
|
|
|
|
family->SetHasStyles(true); // we don't want the family to search for
|
|
|
|
// faces, we're adding them directly here
|
|
|
|
mOtherFamilyNames.Put(key, family);
|
|
|
|
added = true;
|
|
|
|
}
|
|
|
|
family->AddFontEntry(aFontEntry->Clone());
|
|
|
|
return added;
|
|
|
|
}
|
|
|
|
|
2010-11-08 14:02:27 +03:00
|
|
|
nsresult
|
2010-01-29 04:41:25 +03:00
|
|
|
gfxPlatformFontList::InitFontList()
|
|
|
|
{
|
2015-08-05 05:03:41 +03:00
|
|
|
mFontlistInitCount++;
|
|
|
|
|
2015-07-31 04:10:31 +03:00
|
|
|
if (LOG_FONTINIT_ENABLED()) {
|
|
|
|
LOG_FONTINIT(("(fontinit) system fontlist initialization\n"));
|
|
|
|
}
|
|
|
|
|
2015-01-07 08:30:10 +03:00
|
|
|
// rebuilding fontlist so clear out font/word caches
|
|
|
|
gfxFontCache *fontCache = gfxFontCache::GetCache();
|
|
|
|
if (fontCache) {
|
|
|
|
fontCache->AgeAllGenerations();
|
|
|
|
fontCache->FlushShapedWordCaches();
|
|
|
|
}
|
|
|
|
|
2016-03-23 21:17:02 +03:00
|
|
|
gfxPlatform::PurgeSkiaFontCache();
|
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
CancelInitOtherFamilyNamesTask();
|
2017-09-12 21:05:37 +03:00
|
|
|
MutexAutoLock lock(mFontFamiliesMutex);
|
2010-01-29 04:41:25 +03:00
|
|
|
mFontFamilies.Clear();
|
|
|
|
mOtherFamilyNames.Clear();
|
2011-10-17 18:59:28 +04:00
|
|
|
mOtherFamilyNamesInitialized = false;
|
2017-08-03 03:33:00 +03:00
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
if (mExtraNames) {
|
|
|
|
mExtraNames->mFullnames.Clear();
|
|
|
|
mExtraNames->mPostscriptNames.Clear();
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
2014-04-23 09:20:20 +04:00
|
|
|
mFaceNameListsInitialized = false;
|
2015-09-29 04:51:29 +03:00
|
|
|
ClearLangGroupPrefFonts();
|
2012-12-19 13:42:25 +04:00
|
|
|
mReplacementCharFallbackFamily = nullptr;
|
2010-01-29 04:41:25 +03:00
|
|
|
CancelLoader();
|
|
|
|
|
|
|
|
// initialize ranges of characters for which system-wide font search should be skipped
|
|
|
|
mCodepointsWithNoFonts.reset();
|
|
|
|
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
|
|
|
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
2010-11-08 14:02:27 +03:00
|
|
|
|
|
|
|
sPlatformFontList = this;
|
|
|
|
|
2016-08-23 03:06:07 +03:00
|
|
|
nsresult rv = InitFontListForPlatform();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
ApplyWhitelist();
|
2010-11-08 14:02:27 +03:00
|
|
|
return NS_OK;
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult)
|
|
|
|
{
|
|
|
|
aResult = aKeyName;
|
|
|
|
ToLowerCase(aResult);
|
|
|
|
}
|
|
|
|
|
2015-09-24 18:31:30 +03:00
|
|
|
#define OTHERNAMES_TIMEOUT 200
|
2014-04-23 09:20:21 +04:00
|
|
|
|
2015-09-24 18:31:30 +03:00
|
|
|
void
|
2017-08-03 03:33:00 +03:00
|
|
|
gfxPlatformFontList::InitOtherFamilyNames(bool aDeferOtherFamilyNamesLoading)
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
2014-04-23 09:20:21 +04:00
|
|
|
if (mOtherFamilyNamesInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-23 12:43:32 +03:00
|
|
|
// If the font loader delay has been set to zero, we don't defer loading
|
|
|
|
// additional family names (regardless of the aDefer... parameter), as we
|
|
|
|
// take this to mean availability of font info is to be prioritized over
|
|
|
|
// potential startup perf or main-thread jank.
|
|
|
|
// (This is used so we can reliably run reftests that depend on localized
|
|
|
|
// font-family names being available.)
|
|
|
|
if (aDeferOtherFamilyNamesLoading &&
|
|
|
|
Preferences::GetUint(FONT_LOADER_DELAY_PREF) > 0) {
|
2017-08-03 03:33:00 +03:00
|
|
|
if (!mPendingOtherFamilyNameTask) {
|
|
|
|
RefPtr<mozilla::CancelableRunnable> task = new InitOtherFamilyNamesRunnable();
|
|
|
|
mPendingOtherFamilyNameTask = task;
|
|
|
|
NS_IdleDispatchToCurrentThread(task.forget());
|
2015-09-24 18:31:30 +03:00
|
|
|
}
|
2017-08-03 03:33:00 +03:00
|
|
|
} else {
|
|
|
|
InitOtherFamilyNamesInternal(false);
|
2014-04-23 09:20:21 +04:00
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
2014-04-23 09:20:20 +04:00
|
|
|
|
2015-09-24 18:31:30 +03:00
|
|
|
// time limit for loading facename lists (ms)
|
|
|
|
#define NAMELIST_TIMEOUT 200
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2014-04-23 09:20:20 +04:00
|
|
|
gfxFontEntry*
|
|
|
|
gfxPlatformFontList::SearchFamiliesForFaceName(const nsAString& aFaceName)
|
|
|
|
{
|
2013-12-11 04:58:27 +04:00
|
|
|
TimeStamp start = TimeStamp::Now();
|
2015-09-24 18:31:30 +03:00
|
|
|
bool timedOut = false;
|
|
|
|
// if mFirstChar is not 0, only load facenames for families
|
|
|
|
// that start with this character
|
|
|
|
char16_t firstChar = 0;
|
2014-04-23 09:20:20 +04:00
|
|
|
gfxFontEntry *lookup = nullptr;
|
2013-12-11 04:58:27 +04:00
|
|
|
|
2014-04-23 09:20:20 +04:00
|
|
|
// iterate over familes starting with the same letter
|
2015-09-24 18:31:30 +03:00
|
|
|
firstChar = ToLowerCase(aFaceName.CharAt(0));
|
|
|
|
|
|
|
|
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
nsStringHashKey::KeyType key = iter.Key();
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxFontFamily>& family = iter.Data();
|
2015-09-24 18:31:30 +03:00
|
|
|
|
|
|
|
// when filtering, skip names that don't start with the filter character
|
|
|
|
if (firstChar && ToLowerCase(key.CharAt(0)) != firstChar) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
family->ReadFaceNames(this, NeedFullnamePostscriptNames());
|
|
|
|
|
|
|
|
TimeDuration elapsed = TimeStamp::Now() - start;
|
|
|
|
if (elapsed.ToMilliseconds() > NAMELIST_TIMEOUT) {
|
2017-08-03 03:33:00 +03:00
|
|
|
timedOut = true;
|
|
|
|
break;
|
2015-09-24 18:31:30 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-23 09:20:20 +04:00
|
|
|
lookup = FindFaceName(aFaceName);
|
2013-12-11 04:58:27 +04:00
|
|
|
|
|
|
|
TimeStamp end = TimeStamp::Now();
|
|
|
|
Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITFACENAMELISTS,
|
|
|
|
start, end);
|
|
|
|
if (LOG_FONTINIT_ENABLED()) {
|
|
|
|
TimeDuration elapsed = end - start;
|
2014-04-23 09:20:20 +04:00
|
|
|
LOG_FONTINIT(("(fontinit) SearchFamiliesForFaceName took %8.2f ms %s %s",
|
|
|
|
elapsed.ToMilliseconds(),
|
|
|
|
(lookup ? "found name" : ""),
|
2015-09-24 18:31:30 +03:00
|
|
|
(timedOut ? "timeout" : "")));
|
2013-12-11 04:58:27 +04:00
|
|
|
}
|
2014-04-23 09:20:20 +04:00
|
|
|
|
|
|
|
return lookup;
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
|
|
|
|
2014-04-23 09:20:20 +04:00
|
|
|
gfxFontEntry*
|
|
|
|
gfxPlatformFontList::FindFaceName(const nsAString& aFaceName)
|
|
|
|
{
|
|
|
|
gfxFontEntry *lookup;
|
|
|
|
|
|
|
|
// lookup in name lookup tables, return null if not found
|
|
|
|
if (mExtraNames &&
|
|
|
|
((lookup = mExtraNames->mPostscriptNames.GetWeak(aFaceName)) ||
|
|
|
|
(lookup = mExtraNames->mFullnames.GetWeak(aFaceName)))) {
|
|
|
|
return lookup;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfxFontEntry*
|
|
|
|
gfxPlatformFontList::LookupInFaceNameLists(const nsAString& aFaceName)
|
|
|
|
{
|
|
|
|
gfxFontEntry *lookup = nullptr;
|
|
|
|
|
|
|
|
// initialize facename lookup tables if needed
|
|
|
|
// note: this can terminate early or time out, in which case
|
|
|
|
// mFaceNameListsInitialized remains false
|
|
|
|
if (!mFaceNameListsInitialized) {
|
|
|
|
lookup = SearchFamiliesForFaceName(aFaceName);
|
|
|
|
if (lookup) {
|
|
|
|
return lookup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// lookup in name lookup tables, return null if not found
|
|
|
|
if (!(lookup = FindFaceName(aFaceName))) {
|
|
|
|
// names not completely initialized, so keep track of lookup misses
|
|
|
|
if (!mFaceNameListsInitialized) {
|
|
|
|
if (!mFaceNamesMissed) {
|
2016-04-15 22:45:37 +03:00
|
|
|
mFaceNamesMissed = MakeUnique<nsTHashtable<nsStringHashKey>>(2);
|
2014-04-23 09:20:20 +04:00
|
|
|
}
|
|
|
|
mFaceNamesMissed->PutEntry(aFaceName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return lookup;
|
|
|
|
}
|
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::PreloadNamesList()
|
|
|
|
{
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<nsString, 10> preloadFonts;
|
2009-08-16 17:52:12 +04:00
|
|
|
gfxFontUtils::GetPrefsFontList("font.preload-names-list", preloadFonts);
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t numFonts = preloadFonts.Length();
|
|
|
|
for (uint32_t i = 0; i < numFonts; i++) {
|
2009-08-16 17:52:12 +04:00
|
|
|
nsAutoString key;
|
|
|
|
GenerateFontListKey(preloadFonts[i], key);
|
2014-08-06 17:31:21 +04:00
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
// only search canonical names!
|
2012-03-28 01:38:39 +04:00
|
|
|
gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key);
|
2009-08-16 17:52:12 +04:00
|
|
|
if (familyEntry) {
|
2010-01-29 04:41:25 +03:00
|
|
|
familyEntry->ReadOtherFamilyNames(this);
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-01-28 09:56:16 +03:00
|
|
|
gfxPlatformFontList::LoadBadUnderlineList()
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<nsString, 10> blacklist;
|
2009-08-16 17:52:12 +04:00
|
|
|
gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset", blacklist);
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t numFonts = blacklist.Length();
|
|
|
|
for (uint32_t i = 0; i < numFonts; i++) {
|
2009-08-16 17:52:12 +04:00
|
|
|
nsAutoString key;
|
|
|
|
GenerateFontListKey(blacklist[i], key);
|
2011-11-09 00:22:04 +04:00
|
|
|
mBadUnderlineFamilyNames.PutEntry(key);
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-17 18:17:22 +04:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::UpdateFontList()
|
|
|
|
{
|
|
|
|
InitFontList();
|
2015-07-14 05:08:31 +03:00
|
|
|
RebuildLocalFonts();
|
2014-04-17 18:17:22 +04:00
|
|
|
}
|
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
void
|
2017-10-03 01:05:19 +03:00
|
|
|
gfxPlatformFontList::GetFontList(nsAtom *aLangGroup,
|
2009-08-16 17:52:12 +04:00
|
|
|
const nsACString& aGenericFamily,
|
|
|
|
nsTArray<nsString>& aListOfFonts)
|
|
|
|
{
|
2017-09-12 21:05:37 +03:00
|
|
|
MutexAutoLock lock(mFontFamiliesMutex);
|
2015-09-24 18:31:30 +03:00
|
|
|
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxFontFamily>& family = iter.Data();
|
2017-09-11 21:24:01 +03:00
|
|
|
if (family->FilterForFontList(aLangGroup, aGenericFamily)) {
|
2015-09-24 18:31:30 +03:00
|
|
|
nsAutoString localizedFamilyName;
|
|
|
|
family->LocalizedName(localizedFamilyName);
|
|
|
|
aListOfFonts.AppendElement(localizedFamilyName);
|
|
|
|
}
|
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
|
|
|
|
aListOfFonts.Sort();
|
|
|
|
aListOfFonts.Compact();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-10-18 08:24:48 +03:00
|
|
|
gfxPlatformFontList::GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray)
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
2015-09-24 18:31:30 +03:00
|
|
|
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxFontFamily>& family = iter.Data();
|
2015-09-24 18:31:30 +03:00
|
|
|
aFamilyArray.AppendElement(family);
|
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2012-03-09 06:05:24 +04:00
|
|
|
gfxFontEntry*
|
2014-09-30 10:27:55 +04:00
|
|
|
gfxPlatformFontList::SystemFindFontForChar(uint32_t aCh, uint32_t aNextCh,
|
2016-04-21 20:58:59 +03:00
|
|
|
Script aRunScript,
|
2012-03-09 06:05:24 +04:00
|
|
|
const gfxFontStyle* aStyle)
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
gfxFontEntry* fontEntry = nullptr;
|
2012-03-09 06:05:24 +04:00
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
// is codepoint with no matching font? return null immediately
|
|
|
|
if (mCodepointsWithNoFonts.test(aCh)) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2012-12-19 13:42:25 +04:00
|
|
|
// Try to short-circuit font fallback for U+FFFD, used to represent
|
|
|
|
// encoding errors: just use cached family from last time U+FFFD was seen.
|
|
|
|
// This helps speed up pages with lots of encoding errors, binary-as-text,
|
|
|
|
// etc.
|
|
|
|
if (aCh == 0xFFFD && mReplacementCharFallbackFamily) {
|
|
|
|
fontEntry =
|
Bug 1449605 - part 1 - Rearrange thebes font code so that the decision whether to apply synthetic-bold is deferred until actually instantiating a font, not made during the font-matching process. r=jwatt
This rearranges how synthetic-bold use is determined in the font selection
& rendering code. Previously, we would decide during the font-selection
algorithm whether we need to apply synthetic-bold to the chosen face, and
then pass that decision through the fontgroup (storing it in the FamilyFace
entries of the mFonts array there) down to the actual rendering code that
instantiates fonts from the faces (font entries) we've selected.
That became a problem for variation fonts because in the case of a user
font, we may not have downloaded the resource yet, so we just have a "user
font container" entry, which carries the descriptors from the @font-face
rule and will fetch the actual resource when needed. But in the case of a
@font-face rule without a weight descriptor, we don't actually know at
font-selection time whether the face will support "true" bold (via a
variation axis) or not, so we can't reliably make the right decision about
applying synthetic bold.
So we now defer that decision until we actually instantiate a platform font
object to shape/measure/draw text. At that point, we have the requested
style and we also have the real font resource, so we can easily determine
whether fake-bold is required.
(This patch should not result in any visible behavior change; that will
come in a second patch now that the architecture supports it.)
2018-05-01 12:30:50 +03:00
|
|
|
mReplacementCharFallbackFamily->FindFontForStyle(*aStyle);
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2012-12-19 13:42:25 +04:00
|
|
|
// this should never fail, as we must have found U+FFFD in order to set
|
|
|
|
// mReplacementCharFallbackFamily at all, but better play it safe
|
2015-01-15 14:07:24 +03:00
|
|
|
if (fontEntry && fontEntry->HasCharacter(aCh)) {
|
2009-08-16 17:52:12 +04:00
|
|
|
return fontEntry;
|
2012-12-19 13:42:25 +04:00
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2011-11-30 05:55:11 +04:00
|
|
|
TimeStamp start = TimeStamp::Now();
|
|
|
|
|
2012-03-09 06:05:24 +04:00
|
|
|
// search commonly available fonts
|
2013-11-25 06:02:14 +04:00
|
|
|
bool common = true;
|
2012-12-19 13:42:25 +04:00
|
|
|
gfxFontFamily *fallbackFamily = nullptr;
|
2014-09-30 10:27:55 +04:00
|
|
|
fontEntry = CommonFontFallback(aCh, aNextCh, aRunScript, aStyle,
|
|
|
|
&fallbackFamily);
|
2012-03-09 06:05:24 +04:00
|
|
|
|
|
|
|
// if didn't find a font, do system-wide fallback (except for specials)
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t cmapCount = 0;
|
2012-03-09 06:05:24 +04:00
|
|
|
if (!fontEntry) {
|
2013-11-25 06:02:14 +04:00
|
|
|
common = false;
|
2012-12-19 13:42:25 +04:00
|
|
|
fontEntry = GlobalFontFallback(aCh, aRunScript, aStyle, cmapCount,
|
|
|
|
&fallbackFamily);
|
2012-03-09 06:05:24 +04:00
|
|
|
}
|
2011-11-30 05:55:11 +04:00
|
|
|
TimeDuration elapsed = TimeStamp::Now() - start;
|
|
|
|
|
2015-10-30 01:58:24 +03:00
|
|
|
LogModule* log = gfxPlatform::GetLog(eGfxLog_textrun);
|
2011-01-21 19:44:33 +03:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_UNLIKELY(MOZ_LOG_TEST(log, LogLevel::Warning))) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t unicodeRange = FindCharUnicodeRange(aCh);
|
2016-04-21 20:58:59 +03:00
|
|
|
Script script = mozilla::unicode::GetScriptCode(aCh);
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(log, LogLevel::Warning,\
|
2012-03-09 06:05:24 +04:00
|
|
|
("(textrun-systemfallback-%s) char: u+%6.6x "
|
2013-06-12 16:08:53 +04:00
|
|
|
"unicode-range: %d script: %d match: [%s]"
|
2012-03-09 06:05:24 +04:00
|
|
|
" time: %dus cmaps: %d\n",
|
2013-11-25 06:02:14 +04:00
|
|
|
(common ? "common" : "global"), aCh,
|
2016-12-16 06:16:31 +03:00
|
|
|
unicodeRange, static_cast<int>(script),
|
2012-03-09 06:05:24 +04:00
|
|
|
(fontEntry ? NS_ConvertUTF16toUTF8(fontEntry->Name()).get() :
|
|
|
|
"<none>"),
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t(elapsed.ToMicroseconds()),
|
2012-03-09 06:05:24 +04:00
|
|
|
cmapCount));
|
2011-01-21 19:44:33 +03:00
|
|
|
}
|
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
// no match? add to set of non-matching codepoints
|
2012-03-09 06:05:24 +04:00
|
|
|
if (!fontEntry) {
|
2012-12-19 13:42:25 +04:00
|
|
|
mCodepointsWithNoFonts.set(aCh);
|
|
|
|
} else if (aCh == 0xFFFD && fontEntry && fallbackFamily) {
|
|
|
|
mReplacementCharFallbackFamily = fallbackFamily;
|
|
|
|
}
|
2012-03-09 06:05:24 +04:00
|
|
|
|
|
|
|
// track system fallback time
|
|
|
|
static bool first = true;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t intElapsed = int32_t(first ? elapsed.ToMilliseconds() :
|
2011-11-30 05:55:11 +04:00
|
|
|
elapsed.ToMicroseconds());
|
|
|
|
Telemetry::Accumulate((first ? Telemetry::SYSTEM_FONT_FALLBACK_FIRST :
|
|
|
|
Telemetry::SYSTEM_FONT_FALLBACK),
|
|
|
|
intElapsed);
|
|
|
|
first = false;
|
|
|
|
|
2012-03-09 06:06:06 +04:00
|
|
|
// track the script for which fallback occurred (incremented one make it
|
|
|
|
// 1-based)
|
2016-04-21 20:58:59 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::SYSTEM_FONT_FALLBACK_SCRIPT,
|
|
|
|
int(aRunScript) + 1);
|
2012-03-09 06:06:06 +04:00
|
|
|
|
2012-03-09 06:05:24 +04:00
|
|
|
return fontEntry;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2012-03-09 06:05:24 +04:00
|
|
|
#define NUM_FALLBACK_FONTS 8
|
|
|
|
|
|
|
|
gfxFontEntry*
|
2014-09-30 10:27:55 +04:00
|
|
|
gfxPlatformFontList::CommonFontFallback(uint32_t aCh, uint32_t aNextCh,
|
2016-04-21 20:58:59 +03:00
|
|
|
Script aRunScript,
|
2012-12-19 13:42:25 +04:00
|
|
|
const gfxFontStyle* aMatchStyle,
|
|
|
|
gfxFontFamily** aMatchedFamily)
|
2012-03-09 06:05:24 +04:00
|
|
|
{
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<const char*,NUM_FALLBACK_FONTS> defaultFallbacks;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t i, numFallbacks;
|
2012-03-09 06:05:24 +04:00
|
|
|
|
2014-09-30 10:27:55 +04:00
|
|
|
gfxPlatform::GetPlatform()->GetCommonFallbackFonts(aCh, aNextCh,
|
|
|
|
aRunScript,
|
2012-03-09 06:05:24 +04:00
|
|
|
defaultFallbacks);
|
|
|
|
numFallbacks = defaultFallbacks.Length();
|
|
|
|
for (i = 0; i < numFallbacks; i++) {
|
|
|
|
nsAutoString familyName;
|
|
|
|
const char *fallbackFamily = defaultFallbacks[i];
|
|
|
|
|
|
|
|
familyName.AppendASCII(fallbackFamily);
|
2015-05-13 08:11:25 +03:00
|
|
|
gfxFontFamily *fallback = FindFamilyByCanonicalName(familyName);
|
2017-10-24 00:31:57 +03:00
|
|
|
if (!fallback) {
|
2012-03-09 06:05:24 +04:00
|
|
|
continue;
|
2017-10-24 00:31:57 +03:00
|
|
|
}
|
2012-03-09 06:05:24 +04:00
|
|
|
|
|
|
|
gfxFontEntry *fontEntry;
|
|
|
|
|
|
|
|
// use first font in list that supports a given character
|
Bug 1449605 - part 1 - Rearrange thebes font code so that the decision whether to apply synthetic-bold is deferred until actually instantiating a font, not made during the font-matching process. r=jwatt
This rearranges how synthetic-bold use is determined in the font selection
& rendering code. Previously, we would decide during the font-selection
algorithm whether we need to apply synthetic-bold to the chosen face, and
then pass that decision through the fontgroup (storing it in the FamilyFace
entries of the mFonts array there) down to the actual rendering code that
instantiates fonts from the faces (font entries) we've selected.
That became a problem for variation fonts because in the case of a user
font, we may not have downloaded the resource yet, so we just have a "user
font container" entry, which carries the descriptors from the @font-face
rule and will fetch the actual resource when needed. But in the case of a
@font-face rule without a weight descriptor, we don't actually know at
font-selection time whether the face will support "true" bold (via a
variation axis) or not, so we can't reliably make the right decision about
applying synthetic bold.
So we now defer that decision until we actually instantiate a platform font
object to shape/measure/draw text. At that point, we have the requested
style and we also have the real font resource, so we can easily determine
whether fake-bold is required.
(This patch should not result in any visible behavior change; that will
come in a second patch now that the architecture supports it.)
2018-05-01 12:30:50 +03:00
|
|
|
fontEntry = fallback->FindFontForStyle(*aMatchStyle);
|
2017-10-24 00:31:57 +03:00
|
|
|
if (fontEntry) {
|
|
|
|
if (fontEntry->HasCharacter(aCh)) {
|
|
|
|
*aMatchedFamily = fallback;
|
|
|
|
return fontEntry;
|
|
|
|
}
|
|
|
|
// If we requested a styled font (bold and/or italic), and the char
|
|
|
|
// was not available, check other faces of the family.
|
|
|
|
if (!fontEntry->IsNormalStyle()) {
|
|
|
|
// If style/weight/stretch was not Normal, see if we can
|
|
|
|
// fall back to a next-best face (e.g. Arial Black -> Bold,
|
|
|
|
// or Arial Narrow -> Regular).
|
2018-05-15 16:59:25 +03:00
|
|
|
GlobalFontMatch data(aCh, *aMatchStyle);
|
2017-10-24 00:31:57 +03:00
|
|
|
fallback->SearchAllFontsForChar(&data);
|
|
|
|
if (data.mBestMatch) {
|
|
|
|
*aMatchedFamily = fallback;
|
|
|
|
return data.mBestMatch;
|
|
|
|
}
|
|
|
|
}
|
2012-03-09 06:05:24 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-03-09 06:05:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxFontEntry*
|
2012-08-22 19:56:38 +04:00
|
|
|
gfxPlatformFontList::GlobalFontFallback(const uint32_t aCh,
|
2016-04-21 20:58:59 +03:00
|
|
|
Script aRunScript,
|
2012-03-09 06:05:24 +04:00
|
|
|
const gfxFontStyle* aMatchStyle,
|
2012-12-19 13:42:25 +04:00
|
|
|
uint32_t& aCmapCount,
|
|
|
|
gfxFontFamily** aMatchedFamily)
|
2012-03-09 06:05:24 +04:00
|
|
|
{
|
2017-07-13 11:40:33 +03:00
|
|
|
bool useCmaps = IsFontFamilyWhitelistActive() ||
|
|
|
|
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
|
|
|
|
if (!useCmaps) {
|
|
|
|
// Allow platform-specific fallback code to try and find a usable font
|
|
|
|
gfxFontEntry* fe =
|
|
|
|
PlatformGlobalFontFallback(aCh, aRunScript, aMatchStyle,
|
|
|
|
aMatchedFamily);
|
|
|
|
if (fe) {
|
|
|
|
return fe;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-09 06:05:24 +04:00
|
|
|
// otherwise, try to find it among local fonts
|
2018-05-15 16:59:25 +03:00
|
|
|
GlobalFontMatch data(aCh, *aMatchStyle);
|
2012-03-09 06:05:24 +04:00
|
|
|
|
|
|
|
// iterate over all font families to find a font that support the character
|
2015-09-24 18:31:30 +03:00
|
|
|
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxFontFamily>& family = iter.Data();
|
2015-09-24 18:31:30 +03:00
|
|
|
// evaluate all fonts in this family for a match
|
|
|
|
family->FindFontForChar(&data);
|
|
|
|
}
|
2012-03-09 06:05:24 +04:00
|
|
|
|
|
|
|
aCmapCount = data.mCmapsTested;
|
2012-12-19 13:42:25 +04:00
|
|
|
*aMatchedFamily = data.mMatchedFamily;
|
2012-03-09 06:05:24 +04:00
|
|
|
|
|
|
|
return data.mBestMatch;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
bool
|
2016-04-12 09:06:22 +03:00
|
|
|
gfxPlatformFontList::FindAndAddFamilies(const nsAString& aFamily,
|
2018-05-25 16:07:57 +03:00
|
|
|
nsTArray<FamilyAndGeneric>* aOutput,
|
2017-08-01 13:25:35 +03:00
|
|
|
FindFamiliesFlags aFlags,
|
2016-04-12 09:06:22 +03:00
|
|
|
gfxFontStyle* aStyle,
|
|
|
|
gfxFloat aDevToCssSize)
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
|
|
|
nsAutoString key;
|
|
|
|
GenerateFontListKey(aFamily, key);
|
|
|
|
|
2011-01-28 03:40:06 +03:00
|
|
|
NS_ASSERTION(mFontFamilies.Count() != 0, "system font list was not initialized correctly");
|
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
// lookup in canonical (i.e. English) family name list
|
2016-04-12 09:06:22 +03:00
|
|
|
gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key);
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
// if not found, lookup in other family names list (mostly localized names)
|
|
|
|
if (!familyEntry) {
|
|
|
|
familyEntry = mOtherFamilyNames.GetWeak(key);
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
// if still not found and other family names not yet fully initialized,
|
2009-08-16 17:52:12 +04:00
|
|
|
// initialize the rest of the list and try again. this is done lazily
|
2011-01-07 15:29:49 +03:00
|
|
|
// since reading name table entries is expensive.
|
|
|
|
// although ASCII localized family names are possible they don't occur
|
|
|
|
// in practice so avoid pulling in names at startup
|
2016-04-12 09:06:22 +03:00
|
|
|
if (!familyEntry && !mOtherFamilyNamesInitialized && !IsASCII(aFamily)) {
|
2017-08-01 13:25:35 +03:00
|
|
|
InitOtherFamilyNames(!(aFlags & FindFamiliesFlags::eForceOtherFamilyNamesLoading));
|
2016-04-12 09:06:22 +03:00
|
|
|
familyEntry = mOtherFamilyNames.GetWeak(key);
|
2017-11-10 02:38:30 +03:00
|
|
|
if (!familyEntry && !mOtherFamilyNamesInitialized &&
|
|
|
|
!(aFlags & FindFamiliesFlags::eNoAddToNamesMissedWhenSearching)) {
|
2014-04-23 09:20:21 +04:00
|
|
|
// localized family names load timed out, add name to list of
|
|
|
|
// names to check after localized names are loaded
|
|
|
|
if (!mOtherNamesMissed) {
|
2016-04-15 22:45:37 +03:00
|
|
|
mOtherNamesMissed = MakeUnique<nsTHashtable<nsStringHashKey>>(2);
|
2014-04-23 09:20:21 +04:00
|
|
|
}
|
|
|
|
mOtherNamesMissed->PutEntry(key);
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
familyEntry = CheckFamily(familyEntry);
|
2017-08-01 13:25:35 +03:00
|
|
|
|
|
|
|
// If we failed to find the requested family, check for a space in the
|
|
|
|
// name; if found, and if the "base" name (up to the last space) exists
|
|
|
|
// as a family, then this might be a legacy GDI-style family name for
|
|
|
|
// an additional weight/width. Try searching the faces of the base family
|
|
|
|
// and create any corresponding legacy families.
|
|
|
|
if (!familyEntry && !(aFlags & FindFamiliesFlags::eNoSearchForLegacyFamilyNames)) {
|
|
|
|
// We don't have nsAString::RFindChar, so look for a space manually
|
|
|
|
const char16_t* data = aFamily.BeginReading();
|
|
|
|
int32_t index = aFamily.Length();
|
|
|
|
while (--index > 0) {
|
|
|
|
if (data[index] == ' ') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (index > 0) {
|
|
|
|
gfxFontFamily* base =
|
|
|
|
FindFamily(Substring(aFamily, 0, index),
|
|
|
|
FindFamiliesFlags::eNoSearchForLegacyFamilyNames);
|
|
|
|
// If we found the "base" family name, and if it has members with
|
|
|
|
// legacy names, this will add corresponding font-family entries to
|
|
|
|
// the mOtherFamilyNames list; then retry the legacy-family search.
|
|
|
|
if (base && base->CheckForLegacyFamilyNames(this)) {
|
|
|
|
familyEntry = mOtherFamilyNames.GetWeak(key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
if (familyEntry) {
|
2018-05-25 16:07:57 +03:00
|
|
|
aOutput->AppendElement(FamilyAndGeneric(familyEntry));
|
2016-04-12 09:06:22 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxFontEntry*
|
Bug 1449605 - part 1 - Rearrange thebes font code so that the decision whether to apply synthetic-bold is deferred until actually instantiating a font, not made during the font-matching process. r=jwatt
This rearranges how synthetic-bold use is determined in the font selection
& rendering code. Previously, we would decide during the font-selection
algorithm whether we need to apply synthetic-bold to the chosen face, and
then pass that decision through the fontgroup (storing it in the FamilyFace
entries of the mFonts array there) down to the actual rendering code that
instantiates fonts from the faces (font entries) we've selected.
That became a problem for variation fonts because in the case of a user
font, we may not have downloaded the resource yet, so we just have a "user
font container" entry, which carries the descriptors from the @font-face
rule and will fetch the actual resource when needed. But in the case of a
@font-face rule without a weight descriptor, we don't actually know at
font-selection time whether the face will support "true" bold (via a
variation axis) or not, so we can't reliably make the right decision about
applying synthetic bold.
So we now defer that decision until we actually instantiate a platform font
object to shape/measure/draw text. At that point, we have the requested
style and we also have the real font resource, so we can easily determine
whether fake-bold is required.
(This patch should not result in any visible behavior change; that will
come in a second patch now that the architecture supports it.)
2018-05-01 12:30:50 +03:00
|
|
|
gfxPlatformFontList::FindFontForFamily(const nsAString& aFamily,
|
|
|
|
const gfxFontStyle* aStyle)
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
|
|
|
gfxFontFamily *familyEntry = FindFamily(aFamily);
|
|
|
|
|
|
|
|
if (familyEntry)
|
Bug 1449605 - part 1 - Rearrange thebes font code so that the decision whether to apply synthetic-bold is deferred until actually instantiating a font, not made during the font-matching process. r=jwatt
This rearranges how synthetic-bold use is determined in the font selection
& rendering code. Previously, we would decide during the font-selection
algorithm whether we need to apply synthetic-bold to the chosen face, and
then pass that decision through the fontgroup (storing it in the FamilyFace
entries of the mFonts array there) down to the actual rendering code that
instantiates fonts from the faces (font entries) we've selected.
That became a problem for variation fonts because in the case of a user
font, we may not have downloaded the resource yet, so we just have a "user
font container" entry, which carries the descriptors from the @font-face
rule and will fetch the actual resource when needed. But in the case of a
@font-face rule without a weight descriptor, we don't actually know at
font-selection time whether the face will support "true" bold (via a
variation axis) or not, so we can't reliably make the right decision about
applying synthetic bold.
So we now defer that decision until we actually instantiate a platform font
object to shape/measure/draw text. At that point, we have the requested
style and we also have the real font resource, so we can easily determine
whether fake-bold is required.
(This patch should not result in any visible behavior change; that will
come in a second patch now that the architecture supports it.)
2018-05-01 12:30:50 +03:00
|
|
|
return familyEntry->FindFontForStyle(*aStyle);
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName)
|
|
|
|
{
|
|
|
|
nsAutoString key;
|
|
|
|
GenerateFontListKey(aOtherFamilyName, key);
|
|
|
|
|
2012-03-28 01:38:39 +04:00
|
|
|
if (!mOtherFamilyNames.GetWeak(key)) {
|
2009-08-16 17:52:12 +04:00
|
|
|
mOtherFamilyNames.Put(key, aFamilyEntry);
|
2011-01-21 19:44:33 +03:00
|
|
|
LOG_FONTLIST(("(fontlist-otherfamily) canonical family: %s, "
|
|
|
|
"other family: %s\n",
|
|
|
|
NS_ConvertUTF16toUTF8(aFamilyEntry->Name()).get(),
|
|
|
|
NS_ConvertUTF16toUTF8(aOtherFamilyName).get()));
|
2010-02-11 15:00:07 +03:00
|
|
|
if (mBadUnderlineFamilyNames.Contains(key))
|
2010-01-28 09:56:16 +03:00
|
|
|
aFamilyEntry->SetBadUnderlineFamily();
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-29 04:41:25 +03:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname)
|
|
|
|
{
|
2013-09-02 12:41:57 +04:00
|
|
|
if (!mExtraNames->mFullnames.GetWeak(aFullname)) {
|
|
|
|
mExtraNames->mFullnames.Put(aFullname, aFontEntry);
|
2011-01-21 19:44:33 +03:00
|
|
|
LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n",
|
|
|
|
NS_ConvertUTF16toUTF8(aFontEntry->Name()).get(),
|
|
|
|
NS_ConvertUTF16toUTF8(aFullname).get()));
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName)
|
|
|
|
{
|
2013-09-02 12:41:57 +04:00
|
|
|
if (!mExtraNames->mPostscriptNames.GetWeak(aPostscriptName)) {
|
|
|
|
mExtraNames->mPostscriptNames.Put(aPostscriptName, aFontEntry);
|
2011-01-21 19:44:33 +03:00
|
|
|
LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n",
|
|
|
|
NS_ConvertUTF16toUTF8(aFontEntry->Name()).get(),
|
|
|
|
NS_ConvertUTF16toUTF8(aPostscriptName).get()));
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2009-10-07 18:13:40 +04:00
|
|
|
gfxPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
|
|
|
|
{
|
|
|
|
aFamilyName.Truncate();
|
2014-06-06 10:09:23 +04:00
|
|
|
gfxFontFamily *ff = FindFamily(aFontName);
|
|
|
|
if (!ff) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
aFamilyName.Assign(ff->Name());
|
|
|
|
return true;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2017-04-03 15:00:14 +03:00
|
|
|
gfxFontFamily*
|
|
|
|
gfxPlatformFontList::GetDefaultFontFamily(const nsACString& aLangGroup,
|
|
|
|
const nsACString& aGenericFamily)
|
|
|
|
{
|
|
|
|
if (NS_WARN_IF(aLangGroup.IsEmpty()) ||
|
|
|
|
NS_WARN_IF(aGenericFamily.IsEmpty())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
AutoTArray<nsString,4> names;
|
2017-04-12 13:32:19 +03:00
|
|
|
gfxFontUtils::AppendPrefsFontList(
|
|
|
|
NameListPref(aGenericFamily, aLangGroup).get(), names);
|
2017-04-03 15:00:14 +03:00
|
|
|
|
|
|
|
for (nsString& name : names) {
|
|
|
|
gfxFontFamily* fontFamily = FindFamily(name);
|
|
|
|
if (fontFamily) {
|
|
|
|
return fontFamily;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2012-04-19 03:59:43 +04:00
|
|
|
gfxCharacterMap*
|
|
|
|
gfxPlatformFontList::FindCharMap(gfxCharacterMap *aCmap)
|
|
|
|
{
|
|
|
|
aCmap->CalcHash();
|
|
|
|
gfxCharacterMap *cmap = AddCmap(aCmap);
|
|
|
|
cmap->mShared = true;
|
|
|
|
return cmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
// add a cmap to the shared cmap set
|
|
|
|
gfxCharacterMap*
|
|
|
|
gfxPlatformFontList::AddCmap(const gfxCharacterMap* aCharMap)
|
|
|
|
{
|
|
|
|
CharMapHashKey *found =
|
|
|
|
mSharedCmaps.PutEntry(const_cast<gfxCharacterMap*>(aCharMap));
|
|
|
|
return found->GetKey();
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove the cmap from the shared cmap set
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::RemoveCmap(const gfxCharacterMap* aCharMap)
|
|
|
|
{
|
|
|
|
// skip lookups during teardown
|
|
|
|
if (mSharedCmaps.Count() == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// cmap needs to match the entry *and* be the same ptr before removing
|
|
|
|
CharMapHashKey *found =
|
|
|
|
mSharedCmaps.GetEntry(const_cast<gfxCharacterMap*>(aCharMap));
|
|
|
|
if (found && found->GetKey() == aCharMap) {
|
2017-06-14 18:27:24 +03:00
|
|
|
mSharedCmaps.RemoveEntry(found);
|
2012-04-19 03:59:43 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
void
|
2015-09-29 04:51:29 +03:00
|
|
|
gfxPlatformFontList::ResolveGenericFontNames(
|
|
|
|
FontFamilyType aGenericType,
|
|
|
|
eFontPrefLang aPrefLang,
|
2016-04-12 09:06:22 +03:00
|
|
|
nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies)
|
2015-09-29 04:51:28 +03:00
|
|
|
{
|
2015-09-29 04:51:29 +03:00
|
|
|
const char* langGroupStr = GetPrefLangName(aPrefLang);
|
2015-11-16 02:48:40 +03:00
|
|
|
const char* generic = GetGenericName(aGenericType);
|
2015-09-29 04:51:28 +03:00
|
|
|
|
|
|
|
if (!generic) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<nsString,4> genericFamilies;
|
2015-09-29 04:51:28 +03:00
|
|
|
|
|
|
|
// load family for "font.name.generic.lang"
|
2017-04-12 13:32:19 +03:00
|
|
|
gfxFontUtils::AppendPrefsFontList(
|
|
|
|
NamePref(generic, langGroupStr).get(), genericFamilies);
|
2015-09-29 04:51:29 +03:00
|
|
|
|
|
|
|
// load fonts for "font.name-list.generic.lang"
|
2017-04-12 13:32:19 +03:00
|
|
|
gfxFontUtils::AppendPrefsFontList(
|
|
|
|
NameListPref(generic, langGroupStr).get(), genericFamilies);
|
2015-09-29 04:51:29 +03:00
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* langGroup = GetLangGroupForPrefLang(aPrefLang);
|
2015-09-29 04:51:29 +03:00
|
|
|
NS_ASSERTION(langGroup, "null lang group for pref lang");
|
|
|
|
|
2017-11-12 10:24:58 +03:00
|
|
|
gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(genericFamilies,
|
|
|
|
langGroup,
|
|
|
|
aGenericFamilies);
|
|
|
|
|
|
|
|
#if 0 // dump out generic mappings
|
|
|
|
printf("%s ===> ", prefFontName.get());
|
|
|
|
for (uint32_t k = 0; k < aGenericFamilies->Length(); k++) {
|
|
|
|
if (k > 0) printf(", ");
|
|
|
|
printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]->Name()).get());
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::ResolveEmojiFontNames(
|
|
|
|
nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies)
|
|
|
|
{
|
|
|
|
// emoji preference has no lang name
|
|
|
|
AutoTArray<nsString,4> genericFamilies;
|
|
|
|
|
|
|
|
nsAutoCString prefFontListName("font.name-list.emoji");
|
|
|
|
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(), genericFamilies);
|
|
|
|
|
|
|
|
gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(genericFamilies,
|
|
|
|
nullptr,
|
|
|
|
aGenericFamilies);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(
|
|
|
|
nsTArray<nsString>& aGenericNameFamilies,
|
|
|
|
nsAtom* aLangGroup,
|
|
|
|
nsTArray<RefPtr<gfxFontFamily>>* aGenericFamilies)
|
|
|
|
{
|
2015-09-29 04:51:29 +03:00
|
|
|
// lookup and add platform fonts uniquely
|
2017-11-12 10:24:58 +03:00
|
|
|
for (const nsString& genericFamily : aGenericNameFamilies) {
|
2015-10-08 09:04:08 +03:00
|
|
|
gfxFontStyle style;
|
2017-11-12 10:24:58 +03:00
|
|
|
style.language = aLangGroup;
|
2015-10-08 09:04:08 +03:00
|
|
|
style.systemFont = false;
|
2018-05-25 16:07:57 +03:00
|
|
|
AutoTArray<FamilyAndGeneric,10> families;
|
2017-08-01 13:25:35 +03:00
|
|
|
FindAndAddFamilies(genericFamily, &families, FindFamiliesFlags(0),
|
|
|
|
&style);
|
2018-05-25 16:07:57 +03:00
|
|
|
for (const FamilyAndGeneric& f : families) {
|
|
|
|
if (!aGenericFamilies->Contains(f.mFamily)) {
|
|
|
|
aGenericFamilies->AppendElement(f.mFamily);
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
nsTArray<RefPtr<gfxFontFamily>>*
|
2015-09-29 04:51:29 +03:00
|
|
|
gfxPlatformFontList::GetPrefFontsLangGroup(mozilla::FontFamilyType aGenericType,
|
|
|
|
eFontPrefLang aPrefLang)
|
|
|
|
{
|
|
|
|
// treat -moz-fixed as monospace
|
|
|
|
if (aGenericType == eFamily_moz_fixed) {
|
|
|
|
aGenericType = eFamily_monospace;
|
|
|
|
}
|
|
|
|
|
2017-11-12 10:24:58 +03:00
|
|
|
if (aGenericType == eFamily_moz_emoji) {
|
|
|
|
// Emoji font has no lang
|
|
|
|
PrefFontList* prefFonts = mEmojiPrefFont.get();
|
|
|
|
if (MOZ_UNLIKELY(!prefFonts)) {
|
|
|
|
prefFonts = new PrefFontList;
|
|
|
|
ResolveEmojiFontNames(prefFonts);
|
|
|
|
mEmojiPrefFont.reset(prefFonts);
|
|
|
|
}
|
|
|
|
return prefFonts;
|
|
|
|
}
|
|
|
|
|
2016-04-15 22:45:37 +03:00
|
|
|
PrefFontList* prefFonts =
|
|
|
|
mLangGroupPrefFonts[aPrefLang][aGenericType].get();
|
2015-09-29 04:51:29 +03:00
|
|
|
if (MOZ_UNLIKELY(!prefFonts)) {
|
2015-09-29 04:51:29 +03:00
|
|
|
prefFonts = new PrefFontList;
|
2015-09-29 04:51:29 +03:00
|
|
|
ResolveGenericFontNames(aGenericType, aPrefLang, prefFonts);
|
2016-04-15 22:45:37 +03:00
|
|
|
mLangGroupPrefFonts[aPrefLang][aGenericType].reset(prefFonts);
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
|
|
|
return prefFonts;
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::AddGenericFonts(mozilla::FontFamilyType aGenericType,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aLanguage,
|
2018-05-25 16:07:57 +03:00
|
|
|
nsTArray<FamilyAndGeneric>& aFamilyList)
|
2015-09-29 04:51:28 +03:00
|
|
|
{
|
2015-09-29 04:51:29 +03:00
|
|
|
// map lang ==> langGroup
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* langGroup = GetLangGroup(aLanguage);
|
2015-09-29 04:51:28 +03:00
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
// langGroup ==> prefLang
|
|
|
|
eFontPrefLang prefLang = GetFontPrefLangFor(langGroup);
|
|
|
|
|
|
|
|
// lookup pref fonts
|
2015-10-18 08:24:48 +03:00
|
|
|
nsTArray<RefPtr<gfxFontFamily>>* prefFonts =
|
2015-09-29 04:51:29 +03:00
|
|
|
GetPrefFontsLangGroup(aGenericType, prefLang);
|
|
|
|
|
|
|
|
if (!prefFonts->IsEmpty()) {
|
2018-05-25 16:07:57 +03:00
|
|
|
aFamilyList.SetCapacity(aFamilyList.Length() + prefFonts->Length());
|
|
|
|
for (auto& f : *prefFonts) {
|
|
|
|
aFamilyList.AppendElement(FamilyAndGeneric(f.get(), aGenericType));
|
|
|
|
}
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
static nsAtom* PrefLangToLangGroups(uint32_t aIndex)
|
2015-09-29 04:51:28 +03:00
|
|
|
{
|
|
|
|
// static array here avoids static constructor
|
2017-10-03 01:05:19 +03:00
|
|
|
static nsAtom* gPrefLangToLangGroups[] = {
|
2015-09-29 04:51:28 +03:00
|
|
|
#define FONT_PREF_LANG(enum_id_, str_, atom_id_) nsGkAtoms::atom_id_
|
|
|
|
#include "gfxFontPrefLangList.h"
|
|
|
|
#undef FONT_PREF_LANG
|
|
|
|
};
|
|
|
|
|
|
|
|
return aIndex < ArrayLength(gPrefLangToLangGroups)
|
|
|
|
? gPrefLangToLangGroups[aIndex]
|
|
|
|
: nsGkAtoms::Unicode;
|
|
|
|
}
|
|
|
|
|
|
|
|
eFontPrefLang
|
|
|
|
gfxPlatformFontList::GetFontPrefLangFor(const char* aLang)
|
|
|
|
{
|
|
|
|
if (!aLang || !aLang[0]) {
|
|
|
|
return eFontPrefLang_Others;
|
|
|
|
}
|
|
|
|
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); ++i) {
|
|
|
|
if (!PL_strcasecmp(gPrefLangNames[i], aLang)) {
|
|
|
|
return eFontPrefLang(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return eFontPrefLang_Others;
|
|
|
|
}
|
|
|
|
|
|
|
|
eFontPrefLang
|
2017-10-03 01:05:19 +03:00
|
|
|
gfxPlatformFontList::GetFontPrefLangFor(nsAtom *aLang)
|
2015-09-29 04:51:28 +03:00
|
|
|
{
|
|
|
|
if (!aLang)
|
|
|
|
return eFontPrefLang_Others;
|
|
|
|
nsAutoCString lang;
|
|
|
|
aLang->ToUTF8String(lang);
|
|
|
|
return GetFontPrefLangFor(lang.get());
|
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom*
|
2015-09-29 04:51:28 +03:00
|
|
|
gfxPlatformFontList::GetLangGroupForPrefLang(eFontPrefLang aLang)
|
|
|
|
{
|
|
|
|
// the special CJK set pref lang should be resolved into separate
|
|
|
|
// calls to individual CJK pref langs before getting here
|
|
|
|
NS_ASSERTION(aLang != eFontPrefLang_CJKSet, "unresolved CJK set pref lang");
|
|
|
|
|
|
|
|
return PrefLangToLangGroups(uint32_t(aLang));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char*
|
|
|
|
gfxPlatformFontList::GetPrefLangName(eFontPrefLang aLang)
|
|
|
|
{
|
|
|
|
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
|
|
|
|
return gPrefLangNames[uint32_t(aLang)];
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
eFontPrefLang
|
|
|
|
gfxPlatformFontList::GetFontPrefLangFor(uint8_t aUnicodeRange)
|
|
|
|
{
|
|
|
|
switch (aUnicodeRange) {
|
|
|
|
case kRangeSetLatin: return eFontPrefLang_Western;
|
|
|
|
case kRangeCyrillic: return eFontPrefLang_Cyrillic;
|
|
|
|
case kRangeGreek: return eFontPrefLang_Greek;
|
|
|
|
case kRangeHebrew: return eFontPrefLang_Hebrew;
|
|
|
|
case kRangeArabic: return eFontPrefLang_Arabic;
|
|
|
|
case kRangeThai: return eFontPrefLang_Thai;
|
|
|
|
case kRangeKorean: return eFontPrefLang_Korean;
|
|
|
|
case kRangeJapanese: return eFontPrefLang_Japanese;
|
|
|
|
case kRangeSChinese: return eFontPrefLang_ChineseCN;
|
|
|
|
case kRangeTChinese: return eFontPrefLang_ChineseTW;
|
|
|
|
case kRangeDevanagari: return eFontPrefLang_Devanagari;
|
|
|
|
case kRangeTamil: return eFontPrefLang_Tamil;
|
|
|
|
case kRangeArmenian: return eFontPrefLang_Armenian;
|
|
|
|
case kRangeBengali: return eFontPrefLang_Bengali;
|
|
|
|
case kRangeCanadian: return eFontPrefLang_Canadian;
|
|
|
|
case kRangeEthiopic: return eFontPrefLang_Ethiopic;
|
|
|
|
case kRangeGeorgian: return eFontPrefLang_Georgian;
|
|
|
|
case kRangeGujarati: return eFontPrefLang_Gujarati;
|
|
|
|
case kRangeGurmukhi: return eFontPrefLang_Gurmukhi;
|
|
|
|
case kRangeKhmer: return eFontPrefLang_Khmer;
|
|
|
|
case kRangeMalayalam: return eFontPrefLang_Malayalam;
|
|
|
|
case kRangeOriya: return eFontPrefLang_Oriya;
|
|
|
|
case kRangeTelugu: return eFontPrefLang_Telugu;
|
|
|
|
case kRangeKannada: return eFontPrefLang_Kannada;
|
|
|
|
case kRangeSinhala: return eFontPrefLang_Sinhala;
|
|
|
|
case kRangeTibetan: return eFontPrefLang_Tibetan;
|
|
|
|
case kRangeSetCJK: return eFontPrefLang_CJKSet;
|
|
|
|
default: return eFontPrefLang_Others;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
gfxPlatformFontList::IsLangCJK(eFontPrefLang aLang)
|
|
|
|
{
|
|
|
|
switch (aLang) {
|
|
|
|
case eFontPrefLang_Japanese:
|
|
|
|
case eFontPrefLang_ChineseTW:
|
|
|
|
case eFontPrefLang_ChineseCN:
|
|
|
|
case eFontPrefLang_ChineseHK:
|
|
|
|
case eFontPrefLang_Korean:
|
|
|
|
case eFontPrefLang_CJKSet:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::GetLangPrefs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
|
|
|
|
{
|
|
|
|
if (IsLangCJK(aCharLang)) {
|
|
|
|
AppendCJKPrefLangs(aPrefLangs, aLen, aCharLang, aPageLang);
|
|
|
|
} else {
|
|
|
|
AppendPrefLang(aPrefLangs, aLen, aCharLang);
|
|
|
|
}
|
|
|
|
|
|
|
|
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang)
|
|
|
|
{
|
|
|
|
// prefer the lang specified by the page *if* CJK
|
|
|
|
if (IsLangCJK(aPageLang)) {
|
|
|
|
AppendPrefLang(aPrefLangs, aLen, aPageLang);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if not set up, set up the default CJK order, based on accept lang settings and locale
|
|
|
|
if (mCJKPrefLangs.Length() == 0) {
|
|
|
|
|
|
|
|
// temp array
|
|
|
|
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
|
|
|
|
uint32_t tempLen = 0;
|
|
|
|
|
|
|
|
// Add the CJK pref fonts from accept languages, the order should be same order
|
2017-07-31 07:28:48 +03:00
|
|
|
nsAutoCString list;
|
|
|
|
Preferences::GetLocalizedCString("intl.accept_languages", list);
|
2015-09-29 04:51:28 +03:00
|
|
|
if (!list.IsEmpty()) {
|
|
|
|
const char kComma = ',';
|
|
|
|
const char *p, *p_end;
|
|
|
|
list.BeginReading(p);
|
|
|
|
list.EndReading(p_end);
|
|
|
|
while (p < p_end) {
|
|
|
|
while (nsCRT::IsAsciiSpace(*p)) {
|
|
|
|
if (++p == p_end)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (p == p_end)
|
|
|
|
break;
|
|
|
|
const char *start = p;
|
|
|
|
while (++p != p_end && *p != kComma)
|
|
|
|
/* nothing */ ;
|
|
|
|
nsAutoCString lang(Substring(start, p));
|
|
|
|
lang.CompressWhitespace(false, true);
|
|
|
|
eFontPrefLang fpl = gfxPlatformFontList::GetFontPrefLangFor(lang.get());
|
|
|
|
switch (fpl) {
|
|
|
|
case eFontPrefLang_Japanese:
|
|
|
|
case eFontPrefLang_Korean:
|
|
|
|
case eFontPrefLang_ChineseCN:
|
|
|
|
case eFontPrefLang_ChineseHK:
|
|
|
|
case eFontPrefLang_ChineseTW:
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, fpl);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-22 10:27:14 +03:00
|
|
|
// Try using app's locale
|
2017-03-13 06:39:22 +03:00
|
|
|
nsAutoCString localeStr;
|
|
|
|
LocaleService::GetInstance()->GetAppLocaleAsLangTag(localeStr);
|
|
|
|
|
2017-03-22 10:27:14 +03:00
|
|
|
{
|
2018-03-07 05:55:22 +03:00
|
|
|
Locale locale(localeStr);
|
|
|
|
if (locale.GetLanguage().Equals("ja")) {
|
2017-03-22 10:27:14 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
2018-03-07 05:55:22 +03:00
|
|
|
} else if (locale.GetLanguage().Equals("zh")) {
|
|
|
|
if (locale.GetRegion().Equals("CN")) {
|
2017-03-22 10:27:14 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
2018-03-07 05:55:22 +03:00
|
|
|
} else if (locale.GetRegion().Equals("TW")) {
|
2017-03-22 10:27:14 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
2018-03-07 05:55:22 +03:00
|
|
|
} else if (locale.GetRegion().Equals("HK")) {
|
2017-03-22 10:27:14 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
|
|
|
}
|
2018-03-07 05:55:22 +03:00
|
|
|
} else if (locale.GetLanguage().Equals("ko")) {
|
2017-03-22 10:27:14 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-21 14:01:46 +03:00
|
|
|
// Then add the known CJK prefs in order of system preferred locales
|
|
|
|
AutoTArray<nsCString,5> prefLocales;
|
|
|
|
prefLocales.AppendElement(NS_LITERAL_CSTRING("ja"));
|
|
|
|
prefLocales.AppendElement(NS_LITERAL_CSTRING("zh-CN"));
|
|
|
|
prefLocales.AppendElement(NS_LITERAL_CSTRING("zh-TW"));
|
|
|
|
prefLocales.AppendElement(NS_LITERAL_CSTRING("zh-HK"));
|
|
|
|
prefLocales.AppendElement(NS_LITERAL_CSTRING("ko"));
|
|
|
|
|
|
|
|
AutoTArray<nsCString,16> sysLocales;
|
|
|
|
AutoTArray<nsCString,16> negLocales;
|
2018-03-07 05:55:22 +03:00
|
|
|
if (OSPreferences::GetInstance()->GetSystemLocales(sysLocales)) {
|
2017-11-21 14:01:46 +03:00
|
|
|
LocaleService::GetInstance()->NegotiateLanguages(
|
|
|
|
sysLocales, prefLocales, NS_LITERAL_CSTRING(""),
|
2018-03-07 05:55:22 +03:00
|
|
|
LocaleService::LangNegStrategy::Filtering, negLocales);
|
2017-11-21 14:01:46 +03:00
|
|
|
for (const auto& localeStr : negLocales) {
|
2018-03-07 05:55:22 +03:00
|
|
|
Locale locale(localeStr);
|
|
|
|
|
|
|
|
if (locale.GetLanguage().Equals("ja")) {
|
2017-11-21 14:01:46 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen,
|
|
|
|
eFontPrefLang_Japanese);
|
2018-03-07 05:55:22 +03:00
|
|
|
} else if (locale.GetLanguage().Equals("zh")) {
|
|
|
|
if (locale.GetRegion().Equals("CN")) {
|
2017-11-21 14:01:46 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen,
|
|
|
|
eFontPrefLang_ChineseCN);
|
2018-03-07 05:55:22 +03:00
|
|
|
} else if (locale.GetRegion().Equals("TW")) {
|
2017-11-21 14:01:46 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen,
|
|
|
|
eFontPrefLang_ChineseTW);
|
2018-03-07 05:55:22 +03:00
|
|
|
} else if (locale.GetRegion().Equals("HK")) {
|
2017-11-21 14:01:46 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen,
|
|
|
|
eFontPrefLang_ChineseHK);
|
|
|
|
}
|
2018-03-07 05:55:22 +03:00
|
|
|
} else if (locale.GetLanguage().Equals("ko")) {
|
2017-11-21 14:01:46 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen,
|
|
|
|
eFontPrefLang_Korean);
|
|
|
|
}
|
|
|
|
}
|
2017-03-13 06:39:22 +03:00
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
|
|
|
|
// last resort... (the order is same as old gfx.)
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
|
|
|
|
|
|
|
// copy into the cached array
|
|
|
|
uint32_t j;
|
|
|
|
for (j = 0; j < tempLen; j++) {
|
|
|
|
mCJKPrefLangs.AppendElement(tempPrefLangs[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// append in cached CJK langs
|
|
|
|
uint32_t i, numCJKlangs = mCJKPrefLangs.Length();
|
|
|
|
|
|
|
|
for (i = 0; i < numCJKlangs; i++) {
|
|
|
|
AppendPrefLang(aPrefLangs, aLen, (eFontPrefLang) (mCJKPrefLangs[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::AppendPrefLang(eFontPrefLang aPrefLangs[], uint32_t& aLen, eFontPrefLang aAddLang)
|
|
|
|
{
|
|
|
|
if (aLen >= kMaxLenPrefLangList) return;
|
|
|
|
|
|
|
|
// make sure
|
|
|
|
uint32_t i = 0;
|
|
|
|
while (i < aLen && aPrefLangs[i] != aAddLang) {
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == aLen) {
|
|
|
|
aPrefLangs[aLen] = aAddLang;
|
|
|
|
aLen++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
mozilla::FontFamilyType
|
|
|
|
gfxPlatformFontList::GetDefaultGeneric(eFontPrefLang aLang)
|
|
|
|
{
|
2017-11-12 10:24:58 +03:00
|
|
|
if (aLang == eFontPrefLang_Emoji) {
|
|
|
|
return eFamily_moz_emoji;
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
// initialize lang group pref font defaults (i.e. serif/sans-serif)
|
|
|
|
if (MOZ_UNLIKELY(mDefaultGenericsLangGroup.IsEmpty())) {
|
|
|
|
mDefaultGenericsLangGroup.AppendElements(ArrayLength(gPrefLangNames));
|
|
|
|
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); i++) {
|
|
|
|
nsAutoCString prefDefaultFontType("font.default.");
|
|
|
|
prefDefaultFontType.Append(GetPrefLangName(eFontPrefLang(i)));
|
2017-07-31 07:28:48 +03:00
|
|
|
nsAutoCString serifOrSans;
|
|
|
|
Preferences::GetCString(prefDefaultFontType.get(), serifOrSans);
|
2015-09-29 04:51:29 +03:00
|
|
|
if (serifOrSans.EqualsLiteral("sans-serif")) {
|
|
|
|
mDefaultGenericsLangGroup[i] = eFamily_sans_serif;
|
|
|
|
} else {
|
|
|
|
mDefaultGenericsLangGroup[i] = eFamily_serif;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
|
|
|
|
return mDefaultGenericsLangGroup[uint32_t(aLang)];
|
|
|
|
}
|
|
|
|
return eFamily_serif;
|
|
|
|
}
|
|
|
|
|
2016-08-23 03:06:07 +03:00
|
|
|
|
|
|
|
gfxFontFamily*
|
|
|
|
gfxPlatformFontList::GetDefaultFont(const gfxFontStyle* aStyle)
|
|
|
|
{
|
|
|
|
gfxFontFamily* family = GetDefaultFontForPlatform(aStyle);
|
|
|
|
if (family) {
|
|
|
|
return family;
|
|
|
|
}
|
|
|
|
// Something has gone wrong and we were unable to retrieve a default font
|
|
|
|
// from the platform. (Likely the whitelist has blocked all potential
|
|
|
|
// default fonts.) As a last resort, we return the first font listed in
|
|
|
|
// mFontFamilies.
|
|
|
|
return mFontFamilies.Iter().Data();
|
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames)
|
|
|
|
{
|
2015-09-24 18:31:30 +03:00
|
|
|
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxFontFamily>& family = iter.Data();
|
2015-09-24 18:31:30 +03:00
|
|
|
aFontFamilyNames.AppendElement(family->Name());
|
|
|
|
}
|
2014-01-29 11:39:01 +04:00
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom*
|
|
|
|
gfxPlatformFontList::GetLangGroup(nsAtom* aLanguage)
|
2015-11-16 02:48:40 +03:00
|
|
|
{
|
|
|
|
// map lang ==> langGroup
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom *langGroup = nullptr;
|
2015-11-16 02:48:40 +03:00
|
|
|
if (aLanguage) {
|
2015-04-03 22:39:23 +03:00
|
|
|
langGroup = mLangService->GetLanguageGroup(aLanguage);
|
2015-11-16 02:48:40 +03:00
|
|
|
}
|
|
|
|
if (!langGroup) {
|
|
|
|
langGroup = nsGkAtoms::Unicode;
|
|
|
|
}
|
|
|
|
return langGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ const char*
|
|
|
|
gfxPlatformFontList::GetGenericName(FontFamilyType aGenericType)
|
|
|
|
{
|
|
|
|
static const char kGeneric_serif[] = "serif";
|
|
|
|
static const char kGeneric_sans_serif[] = "sans-serif";
|
|
|
|
static const char kGeneric_monospace[] = "monospace";
|
|
|
|
static const char kGeneric_cursive[] = "cursive";
|
|
|
|
static const char kGeneric_fantasy[] = "fantasy";
|
|
|
|
|
|
|
|
// type should be standard generic type at this point
|
|
|
|
NS_ASSERTION(aGenericType >= eFamily_serif &&
|
|
|
|
aGenericType <= eFamily_fantasy,
|
|
|
|
"standard generic font family type required");
|
|
|
|
|
|
|
|
// map generic type to string
|
|
|
|
const char *generic = nullptr;
|
|
|
|
switch (aGenericType) {
|
|
|
|
case eFamily_serif:
|
|
|
|
generic = kGeneric_serif;
|
|
|
|
break;
|
|
|
|
case eFamily_sans_serif:
|
|
|
|
generic = kGeneric_sans_serif;
|
|
|
|
break;
|
|
|
|
case eFamily_monospace:
|
|
|
|
generic = kGeneric_monospace;
|
|
|
|
break;
|
|
|
|
case eFamily_cursive:
|
|
|
|
generic = kGeneric_cursive;
|
|
|
|
break;
|
|
|
|
case eFamily_fantasy:
|
|
|
|
generic = kGeneric_fantasy;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return generic;
|
|
|
|
}
|
|
|
|
|
2015-09-24 18:31:30 +03:00
|
|
|
void
|
2009-08-16 17:52:12 +04:00
|
|
|
gfxPlatformFontList::InitLoader()
|
|
|
|
{
|
2014-01-29 11:39:01 +04:00
|
|
|
GetFontFamilyNames(mFontInfo->mFontFamiliesToLoad);
|
2009-08-16 17:52:12 +04:00
|
|
|
mStartIndex = 0;
|
2014-01-29 11:39:01 +04:00
|
|
|
mNumFamilies = mFontInfo->mFontFamiliesToLoad.Length();
|
|
|
|
memset(&(mFontInfo->mLoadStats), 0, sizeof(mFontInfo->mLoadStats));
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2013-12-06 07:47:46 +04:00
|
|
|
#define FONT_LOADER_MAX_TIMESLICE 100 // max time for one pass through RunLoader = 100ms
|
|
|
|
|
2012-03-09 06:05:40 +04:00
|
|
|
bool
|
2014-01-29 11:39:01 +04:00
|
|
|
gfxPlatformFontList::LoadFontInfo()
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
2013-12-06 07:47:46 +04:00
|
|
|
TimeStamp start = TimeStamp::Now();
|
2014-01-29 11:39:01 +04:00
|
|
|
uint32_t i, endIndex = mNumFamilies;
|
2012-03-09 06:05:40 +04:00
|
|
|
bool loadCmaps = !UsesSystemFallback() ||
|
|
|
|
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
|
2009-08-16 17:52:12 +04:00
|
|
|
|
|
|
|
// for each font family, load in various font info
|
|
|
|
for (i = mStartIndex; i < endIndex; i++) {
|
2014-01-29 11:39:01 +04:00
|
|
|
nsAutoString key;
|
|
|
|
gfxFontFamily *familyEntry;
|
|
|
|
GenerateFontListKey(mFontInfo->mFontFamiliesToLoad[i], key);
|
|
|
|
|
|
|
|
// lookup in canonical (i.e. English) family name list
|
|
|
|
if (!(familyEntry = mFontFamilies.GetWeak(key))) {
|
2010-02-11 14:59:47 +03:00
|
|
|
continue;
|
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
// read in face names
|
|
|
|
familyEntry->ReadFaceNames(this, NeedFullnamePostscriptNames(), mFontInfo);
|
|
|
|
|
2012-03-09 06:05:40 +04:00
|
|
|
// load the cmaps if needed
|
|
|
|
if (loadCmaps) {
|
2014-01-29 11:39:01 +04:00
|
|
|
familyEntry->ReadAllCMAPs(mFontInfo);
|
2012-03-09 06:05:40 +04:00
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2013-12-06 07:47:46 +04:00
|
|
|
// limit the time spent reading fonts in one pass
|
|
|
|
TimeDuration elapsed = TimeStamp::Now() - start;
|
|
|
|
if (elapsed.ToMilliseconds() > FONT_LOADER_MAX_TIMESLICE &&
|
|
|
|
i + 1 != endIndex) {
|
|
|
|
endIndex = i + 1;
|
|
|
|
break;
|
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2010-02-11 14:59:47 +03:00
|
|
|
mStartIndex = endIndex;
|
2014-01-29 11:39:01 +04:00
|
|
|
bool done = mStartIndex >= mNumFamilies;
|
|
|
|
|
|
|
|
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")));
|
|
|
|
}
|
2010-02-11 14:59:47 +03:00
|
|
|
|
2014-04-17 18:17:22 +04:00
|
|
|
if (done) {
|
|
|
|
mOtherFamilyNamesInitialized = true;
|
2017-08-03 03:33:00 +03:00
|
|
|
CancelInitOtherFamilyNamesTask();
|
2014-04-23 09:20:20 +04:00
|
|
|
mFaceNameListsInitialized = true;
|
2014-04-17 18:17:22 +04:00
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
return done;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
void
|
2014-01-29 11:39:01 +04:00
|
|
|
gfxPlatformFontList::CleanupLoader()
|
2009-08-16 17:52:12 +04:00
|
|
|
{
|
|
|
|
mFontFamiliesToLoad.Clear();
|
|
|
|
mNumFamilies = 0;
|
2014-04-23 09:20:21 +04:00
|
|
|
bool rebuilt = false, forceReflow = false;
|
2014-04-23 09:20:20 +04:00
|
|
|
|
|
|
|
// if had missed face names that are now available, force reflow all
|
2015-07-14 05:08:31 +03:00
|
|
|
if (mFaceNamesMissed) {
|
|
|
|
for (auto it = mFaceNamesMissed->Iter(); !it.Done(); it.Next()) {
|
|
|
|
if (FindFaceName(it.Get()->GetKey())) {
|
|
|
|
rebuilt = true;
|
|
|
|
RebuildLocalFonts();
|
|
|
|
break;
|
|
|
|
}
|
2014-04-23 09:20:20 +04:00
|
|
|
}
|
|
|
|
mFaceNamesMissed = nullptr;
|
|
|
|
}
|
2014-01-29 11:39:01 +04:00
|
|
|
|
2014-04-23 09:20:21 +04:00
|
|
|
if (mOtherNamesMissed) {
|
2015-07-14 05:08:31 +03:00
|
|
|
for (auto it = mOtherNamesMissed->Iter(); !it.Done(); it.Next()) {
|
2017-08-01 13:25:35 +03:00
|
|
|
if (FindFamily(it.Get()->GetKey(),
|
2017-11-10 02:38:30 +03:00
|
|
|
(FindFamiliesFlags::eForceOtherFamilyNamesLoading |
|
|
|
|
FindFamiliesFlags::eNoAddToNamesMissedWhenSearching))) {
|
2015-07-14 05:08:31 +03:00
|
|
|
forceReflow = true;
|
|
|
|
ForceGlobalReflow();
|
|
|
|
break;
|
|
|
|
}
|
2014-04-23 09:20:21 +04:00
|
|
|
}
|
2015-07-14 05:08:31 +03:00
|
|
|
mOtherNamesMissed = nullptr;
|
2014-04-23 09:20:21 +04:00
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
if (LOG_FONTINIT_ENABLED() && mFontInfo) {
|
|
|
|
LOG_FONTINIT(("(fontinit) fontloader load thread took %8.2f ms "
|
|
|
|
"%d families %d fonts %d cmaps "
|
2014-04-23 09:20:21 +04:00
|
|
|
"%d facenames %d othernames %s %s",
|
2014-01-29 11:39:01 +04:00
|
|
|
mLoadTime.ToMilliseconds(),
|
|
|
|
mFontInfo->mLoadStats.families,
|
|
|
|
mFontInfo->mLoadStats.fonts,
|
|
|
|
mFontInfo->mLoadStats.cmaps,
|
|
|
|
mFontInfo->mLoadStats.facenames,
|
2014-04-23 09:20:20 +04:00
|
|
|
mFontInfo->mLoadStats.othernames,
|
2014-04-23 09:20:21 +04:00
|
|
|
(rebuilt ? "(userfont sets rebuilt)" : ""),
|
|
|
|
(forceReflow ? "(global reflow)" : "")));
|
2014-01-29 11:39:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxFontInfoLoader::CleanupLoader();
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
2012-03-28 01:38:39 +04:00
|
|
|
|
2013-04-26 11:40:44 +04:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::GetPrefsAndStartLoader()
|
|
|
|
{
|
|
|
|
uint32_t delay =
|
|
|
|
std::max(1u, Preferences::GetUint(FONT_LOADER_DELAY_PREF));
|
|
|
|
uint32_t interval =
|
|
|
|
std::max(1u, Preferences::GetUint(FONT_LOADER_INTERVAL_PREF));
|
|
|
|
|
|
|
|
StartLoader(delay, interval);
|
|
|
|
}
|
|
|
|
|
2015-07-14 05:08:31 +03:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::RebuildLocalFonts()
|
|
|
|
{
|
|
|
|
for (auto it = mUserFontSetList.Iter(); !it.Done(); it.Next()) {
|
|
|
|
it.Get()->GetKey()->RebuildLocalRules();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::ClearLangGroupPrefFonts()
|
|
|
|
{
|
2015-09-29 04:51:29 +03:00
|
|
|
for (uint32_t i = eFontPrefLang_First;
|
|
|
|
i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
|
|
|
|
auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
|
|
|
|
for (uint32_t j = eFamily_generic_first;
|
|
|
|
j < eFamily_generic_first + eFamily_generic_count; j++) {
|
|
|
|
prefFontsLangGroup[j] = nullptr;
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
|
|
|
}
|
2017-11-21 14:02:20 +03:00
|
|
|
mCJKPrefLangs.Clear();
|
2018-05-15 12:17:12 +03:00
|
|
|
mEmojiPrefFont = nullptr;
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
|
|
|
|
2012-03-28 01:38:39 +04:00
|
|
|
// Support for memory reporting
|
|
|
|
|
2015-07-31 07:19:57 +03:00
|
|
|
// this is also used by subclasses that hold additional font tables
|
2012-03-28 01:38:39 +04:00
|
|
|
/*static*/ size_t
|
2015-07-31 07:19:57 +03:00
|
|
|
gfxPlatformFontList::SizeOfFontFamilyTableExcludingThis(
|
|
|
|
const FontFamilyTable& aTable,
|
|
|
|
MallocSizeOf aMallocSizeOf)
|
2012-03-28 01:38:39 +04:00
|
|
|
{
|
2015-07-31 07:19:57 +03:00
|
|
|
size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
// We don't count the size of the family here, because this is an
|
|
|
|
// *extra* reference to a family that will have already been counted in
|
|
|
|
// the main list.
|
|
|
|
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
|
|
}
|
|
|
|
return n;
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
|
|
|
|
2015-08-05 04:05:19 +03:00
|
|
|
/*static*/ size_t
|
|
|
|
gfxPlatformFontList::SizeOfFontEntryTableExcludingThis(
|
|
|
|
const FontEntryTable& aTable,
|
|
|
|
MallocSizeOf aMallocSizeOf)
|
|
|
|
{
|
|
|
|
size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
// The font itself is counted by its owning family; here we only care
|
|
|
|
// about the names stored in the hashtable keys.
|
|
|
|
n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2012-03-28 01:38:39 +04:00
|
|
|
void
|
2013-10-15 06:19:47 +04:00
|
|
|
gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
|
|
|
FontListSizes* aSizes) const
|
2012-03-28 01:38:39 +04:00
|
|
|
{
|
|
|
|
aSizes->mFontListSize +=
|
2015-07-31 07:19:57 +03:00
|
|
|
mFontFamilies.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (auto iter = mFontFamilies.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
aSizes->mFontListSize +=
|
|
|
|
iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
|
|
iter.Data()->AddSizeOfIncludingThis(aMallocSizeOf, aSizes);
|
|
|
|
}
|
2012-03-28 01:38:39 +04:00
|
|
|
|
|
|
|
aSizes->mFontListSize +=
|
2015-07-31 07:19:57 +03:00
|
|
|
SizeOfFontFamilyTableExcludingThis(mOtherFamilyNames, aMallocSizeOf);
|
2012-03-28 01:38:39 +04:00
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
if (mExtraNames) {
|
2012-03-28 01:38:39 +04:00
|
|
|
aSizes->mFontListSize +=
|
2015-08-05 04:05:19 +03:00
|
|
|
SizeOfFontEntryTableExcludingThis(mExtraNames->mFullnames,
|
|
|
|
aMallocSizeOf);
|
2012-03-28 01:38:39 +04:00
|
|
|
aSizes->mFontListSize +=
|
2015-08-05 04:05:19 +03:00
|
|
|
SizeOfFontEntryTableExcludingThis(mExtraNames->mPostscriptNames,
|
|
|
|
aMallocSizeOf);
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
for (uint32_t i = eFontPrefLang_First;
|
|
|
|
i < eFontPrefLang_First + eFontPrefLang_Count; i++) {
|
|
|
|
auto& prefFontsLangGroup = mLangGroupPrefFonts[i];
|
|
|
|
for (uint32_t j = eFamily_generic_first;
|
|
|
|
j < eFamily_generic_first + eFamily_generic_count; j++) {
|
2016-04-15 22:45:37 +03:00
|
|
|
PrefFontList* pf = prefFontsLangGroup[j].get();
|
2015-09-29 04:51:29 +03:00
|
|
|
if (pf) {
|
|
|
|
aSizes->mFontListSize +=
|
|
|
|
pf->ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-28 01:38:39 +04:00
|
|
|
aSizes->mFontListSize +=
|
|
|
|
mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
aSizes->mFontListSize +=
|
2015-07-29 09:24:24 +03:00
|
|
|
mFontFamiliesToLoad.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2012-03-28 01:38:39 +04:00
|
|
|
|
|
|
|
aSizes->mFontListSize +=
|
2014-08-06 00:27:41 +04:00
|
|
|
mBadUnderlineFamilyNames.SizeOfExcludingThis(aMallocSizeOf);
|
2012-04-19 03:59:43 +04:00
|
|
|
|
|
|
|
aSizes->mFontListSize +=
|
2015-07-29 11:50:52 +03:00
|
|
|
mSharedCmaps.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (auto iter = mSharedCmaps.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
aSizes->mCharMapsSize +=
|
|
|
|
iter.Get()->GetKey()->SizeOfIncludingThis(aMallocSizeOf);
|
|
|
|
}
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-10-15 06:19:47 +04:00
|
|
|
gfxPlatformFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
|
|
|
|
FontListSizes* aSizes) const
|
2012-03-28 01:38:39 +04:00
|
|
|
{
|
|
|
|
aSizes->mFontListSize += aMallocSizeOf(this);
|
2013-10-15 06:19:47 +04:00
|
|
|
AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
2016-07-26 23:19:48 +03:00
|
|
|
|
2016-08-23 03:06:07 +03:00
|
|
|
bool
|
|
|
|
gfxPlatformFontList::IsFontFamilyWhitelistActive()
|
|
|
|
{
|
|
|
|
return mFontFamilyWhitelistActive;
|
|
|
|
}
|
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
void
|
|
|
|
gfxPlatformFontList::InitOtherFamilyNamesInternal(bool aDeferOtherFamilyNamesLoading)
|
|
|
|
{
|
|
|
|
if (mOtherFamilyNamesInitialized) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aDeferOtherFamilyNamesLoading) {
|
|
|
|
TimeStamp start = TimeStamp::Now();
|
|
|
|
bool timedOut = false;
|
|
|
|
|
|
|
|
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
RefPtr<gfxFontFamily>& family = iter.Data();
|
|
|
|
family->ReadOtherFamilyNames(this);
|
|
|
|
TimeDuration elapsed = TimeStamp::Now() - start;
|
|
|
|
if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) {
|
|
|
|
timedOut = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!timedOut) {
|
|
|
|
mOtherFamilyNamesInitialized = true;
|
|
|
|
CancelInitOtherFamilyNamesTask();
|
|
|
|
}
|
|
|
|
TimeStamp end = TimeStamp::Now();
|
|
|
|
Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES,
|
|
|
|
start, end);
|
|
|
|
|
|
|
|
if (LOG_FONTINIT_ENABLED()) {
|
|
|
|
TimeDuration elapsed = end - start;
|
|
|
|
LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms %s",
|
|
|
|
elapsed.ToMilliseconds(),
|
|
|
|
(timedOut ? "timeout" : "")));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
TimeStamp start = TimeStamp::Now();
|
|
|
|
|
|
|
|
for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
|
|
|
|
RefPtr<gfxFontFamily>& family = iter.Data();
|
|
|
|
family->ReadOtherFamilyNames(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
mOtherFamilyNamesInitialized = true;
|
|
|
|
CancelInitOtherFamilyNamesTask();
|
|
|
|
|
|
|
|
TimeStamp end = TimeStamp::Now();
|
|
|
|
Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES_NO_DEFERRING,
|
|
|
|
start, end);
|
|
|
|
|
|
|
|
if (LOG_FONTINIT_ENABLED()) {
|
|
|
|
TimeDuration elapsed = end - start;
|
|
|
|
LOG_FONTINIT(("(fontinit) InitOtherFamilyNames without deferring took %8.2f ms",
|
|
|
|
elapsed.ToMilliseconds()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxPlatformFontList::CancelInitOtherFamilyNamesTask()
|
|
|
|
{
|
|
|
|
if (mPendingOtherFamilyNameTask) {
|
|
|
|
mPendingOtherFamilyNameTask->Cancel();
|
|
|
|
mPendingOtherFamilyNameTask = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-26 23:19:48 +03:00
|
|
|
#undef LOG
|
|
|
|
#undef LOG_ENABLED
|