2018-11-30 22:52:05 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
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"
|
2021-01-04 17:20:17 +03:00
|
|
|
#include "mozilla/gfx/Logging.h"
|
2021-11-04 19:36:03 +03:00
|
|
|
#include "mozilla/intl/Locale.h"
|
2017-03-13 06:39:22 +03:00
|
|
|
#include "mozilla/intl/LocaleService.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"
|
2019-04-27 18:37:29 +03:00
|
|
|
#include "SharedFontList-impl.h"
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
#include "GeckoProfiler.h"
|
2015-09-29 04:51:28 +03:00
|
|
|
#include "nsCRT.h"
|
2015-09-29 04:51:28 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2021-09-08 15:18:17 +03:00
|
|
|
#include "nsPresContext.h"
|
2015-09-29 04:51:28 +03:00
|
|
|
#include "nsServiceManagerUtils.h"
|
2009-08-16 17:52:12 +04:00
|
|
|
#include "nsUnicharUtils.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
|
|
|
|
2021-06-07 00:24:44 +03:00
|
|
|
#include "mozilla/AppShutdown.h"
|
2012-10-26 17:32:10 +04:00
|
|
|
#include "mozilla/Attributes.h"
|
2021-08-06 17:06:53 +03:00
|
|
|
#include "mozilla/BinarySearch.h"
|
2012-10-26 17:32:10 +04:00
|
|
|
#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"
|
2019-07-26 04:10:23 +03:00
|
|
|
#include "mozilla/StaticPrefs_gfx.h"
|
2020-05-08 00:10:46 +03:00
|
|
|
#include "mozilla/StaticPrefs_layout.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"
|
2019-04-27 18:37:58 +03:00
|
|
|
#include "mozilla/dom/BlobImpl.h"
|
|
|
|
#include "mozilla/dom/ContentChild.h"
|
2017-11-02 23:29:33 +03:00
|
|
|
#include "mozilla/dom/ContentParent.h"
|
2019-04-27 18:37:58 +03:00
|
|
|
#include "mozilla/dom/ContentProcessMessageManager.h"
|
2013-10-08 03:15:59 +04:00
|
|
|
#include "mozilla/gfx/2D.h"
|
2019-04-27 18:37:58 +03:00
|
|
|
#include "mozilla/ipc/FileDescriptorUtils.h"
|
|
|
|
#include "mozilla/ResultExtensions.h"
|
2019-09-18 11:26:34 +03:00
|
|
|
#include "mozilla/TextUtils.h"
|
2019-04-27 18:37:58 +03:00
|
|
|
#include "mozilla/Unused.h"
|
|
|
|
|
|
|
|
#include "base/eintr_wrapper.h"
|
2011-06-12 06:30:16 +04:00
|
|
|
|
2016-01-15 10:33:51 +03:00
|
|
|
#include <locale.h>
|
2021-03-23 13:36:36 +03:00
|
|
|
#include <numeric>
|
2016-01-15 10:33:51 +03:00
|
|
|
|
2011-06-12 06:30:16 +04:00
|
|
|
using namespace mozilla;
|
2021-11-04 19:36:03 +03:00
|
|
|
using mozilla::intl::Locale;
|
|
|
|
using mozilla::intl::LocaleParser;
|
2017-03-13 06:39:22 +03:00
|
|
|
using mozilla::intl::LocaleService;
|
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), LogLevel::Debug, args)
|
2015-06-04 01:22:28 +03:00
|
|
|
#define LOG_FONTLIST_ENABLED() \
|
2011-01-21 19:44:33 +03:00
|
|
|
MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_fontlist), LogLevel::Debug)
|
2015-05-21 23:22:04 +03:00
|
|
|
#define LOG_FONTINIT(args) \
|
|
|
|
MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontinit), LogLevel::Debug, args)
|
2015-06-04 01:22:28 +03:00
|
|
|
#define LOG_FONTINIT_ENABLED() \
|
2013-12-11 04:58:27 +04:00
|
|
|
MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_fontinit), 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.
|
2018-12-08 16:44:55 +03:00
|
|
|
{0x0600, 0x06FF, 1, {TRUETYPE_TAG('a', 'r', 'a', 'b'), 0, 0}},
|
|
|
|
{0x0700, 0x074F, 1, {TRUETYPE_TAG('s', 'y', 'r', 'c'), 0, 0}},
|
|
|
|
{0x0750, 0x077F, 1, {TRUETYPE_TAG('a', 'r', 'a', 'b'), 0, 0}},
|
|
|
|
{0x08A0, 0x08FF, 1, {TRUETYPE_TAG('a', 'r', 'a', 'b'), 0, 0}},
|
2014-05-05 22:59:55 +04:00
|
|
|
{0x0900,
|
|
|
|
0x097F,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('d', 'e', 'v', '2'), TRUETYPE_TAG('d', 'e', 'v', 'a'), 0}},
|
|
|
|
{0x0980,
|
|
|
|
0x09FF,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('b', 'n', 'g', '2'), TRUETYPE_TAG('b', 'e', 'n', 'g'), 0}},
|
|
|
|
{0x0A00,
|
|
|
|
0x0A7F,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('g', 'u', 'r', '2'), TRUETYPE_TAG('g', 'u', 'r', 'u'), 0}},
|
|
|
|
{0x0A80,
|
|
|
|
0x0AFF,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('g', 'j', 'r', '2'), TRUETYPE_TAG('g', 'u', 'j', 'r'), 0}},
|
|
|
|
{0x0B00,
|
|
|
|
0x0B7F,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('o', 'r', 'y', '2'), TRUETYPE_TAG('o', 'r', 'y', 'a'), 0}},
|
|
|
|
{0x0B80,
|
|
|
|
0x0BFF,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('t', 'm', 'l', '2'), TRUETYPE_TAG('t', 'a', 'm', 'l'), 0}},
|
|
|
|
{0x0C00,
|
|
|
|
0x0C7F,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('t', 'e', 'l', '2'), TRUETYPE_TAG('t', 'e', 'l', 'u'), 0}},
|
|
|
|
{0x0C80,
|
|
|
|
0x0CFF,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('k', 'n', 'd', '2'), TRUETYPE_TAG('k', 'n', 'd', 'a'), 0}},
|
|
|
|
{0x0D00,
|
|
|
|
0x0D7F,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('m', 'l', 'm', '2'), TRUETYPE_TAG('m', 'l', 'y', 'm'), 0}},
|
2018-12-08 16:44:55 +03:00
|
|
|
{0x0D80, 0x0DFF, 1, {TRUETYPE_TAG('s', 'i', 'n', 'h'), 0, 0}},
|
|
|
|
{0x0E80, 0x0EFF, 1, {TRUETYPE_TAG('l', 'a', 'o', ' '), 0, 0}},
|
|
|
|
{0x0F00, 0x0FFF, 1, {TRUETYPE_TAG('t', 'i', 'b', 't'), 0, 0}},
|
2014-05-05 22:59:55 +04:00
|
|
|
{0x1000,
|
|
|
|
0x109f,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('m', 'y', 'm', 'r'), TRUETYPE_TAG('m', 'y', 'm', '2'), 0}},
|
2018-12-08 16:44:55 +03:00
|
|
|
{0x1780, 0x17ff, 1, {TRUETYPE_TAG('k', 'h', 'm', 'r'), 0, 0}},
|
2014-05-05 22:59:55 +04:00
|
|
|
// Khmer Symbols (19e0..19ff) don't seem to need any special shaping
|
|
|
|
{0xaa60,
|
|
|
|
0xaa7f,
|
2018-12-08 16:44:55 +03:00
|
|
|
2,
|
2014-05-05 22:59:55 +04:00
|
|
|
{TRUETYPE_TAG('m', 'y', 'm', 'r'), TRUETYPE_TAG('m', 'y', 'm', '2'), 0}},
|
|
|
|
// Thai seems to be "renderable" without AAT morphing tables
|
2018-12-08 16:44:55 +03:00
|
|
|
{0, 0, 0, {0, 0, 0}} // terminator
|
2014-05-05 22:59:55 +04:00
|
|
|
};
|
|
|
|
|
2021-09-08 15:18:17 +03:00
|
|
|
static const char* kObservedPrefs[] = {"font.", "font.name-list.",
|
2011-06-12 06:30:16 +04:00
|
|
|
"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";
|
|
|
|
|
2019-11-20 02:18:30 +03:00
|
|
|
static const char kCJKFallbackOrderPref[] = "font.cjk_pref_fallback_order";
|
|
|
|
|
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 {
|
2020-03-04 18:39:20 +03:00
|
|
|
~gfxFontListPrefObserver() = default;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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) {
|
2018-07-06 00:47:39 +03:00
|
|
|
NS_ASSERTION(!strcmp(aTopic, LOCALES_CHANGED_TOPIC), "invalid topic");
|
|
|
|
FontListPrefChanged(nullptr);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-07-06 00:47:39 +03:00
|
|
|
if (XRE_IsParentProcess()) {
|
2021-08-27 02:17:54 +03:00
|
|
|
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No);
|
2017-11-21 14:02:20 +03:00
|
|
|
}
|
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;
|
2019-04-27 18:37:58 +03:00
|
|
|
sizes.mSharedSize = 0;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2013-10-15 06:19:47 +04:00
|
|
|
gfxPlatformFontList::PlatformFontList()->AddSizeOfIncludingThis(
|
|
|
|
&FontListMallocSizeOf, &sizes);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2016-08-24 08:23:45 +03:00
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
"explicit/gfx/font-list", KIND_HEAP, UNITS_BYTES, sizes.mFontListSize,
|
2013-10-15 06:19:47 +04:00
|
|
|
"Memory used to manage the list of font families and faces.");
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2016-08-24 08:23:45 +03:00
|
|
|
MOZ_COLLECT_REPORT(
|
2013-10-15 06:19:47 +04:00
|
|
|
"explicit/gfx/font-charmaps", KIND_HEAP, UNITS_BYTES, sizes.mCharMapsSize,
|
2016-08-24 08:23:45 +03:00
|
|
|
"Memory used to record the character coverage of individual fonts.");
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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.");
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2016-08-24 08:23:45 +03:00
|
|
|
|
2012-03-28 01:38:39 +04:00
|
|
|
if (sizes.mLoaderSize) {
|
2016-08-24 08:23:45 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
if (sizes.mSharedSize) {
|
|
|
|
MOZ_COLLECT_REPORT(
|
|
|
|
"font-list-shmem", KIND_NONHEAP, UNITS_BYTES, sizes.mSharedSize,
|
|
|
|
"Shared memory for system font list and character coverage data.");
|
|
|
|
}
|
|
|
|
|
2012-03-28 01:38:39 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
PRThread* gfxPlatformFontList::sInitFontListThread = nullptr;
|
|
|
|
|
|
|
|
static void InitFontListCallback(void* aFontList) {
|
|
|
|
AUTO_PROFILER_REGISTER_THREAD("InitFontList");
|
|
|
|
PR_SetCurrentThreadName("InitFontList");
|
|
|
|
|
|
|
|
if (!static_cast<gfxPlatformFontList*>(aFontList)->InitFontList()) {
|
|
|
|
gfxPlatformFontList::Shutdown();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
bool gfxPlatformFontList::Initialize(gfxPlatformFontList* aList) {
|
|
|
|
sPlatformFontList = aList;
|
|
|
|
if (XRE_IsParentProcess() &&
|
|
|
|
StaticPrefs::gfx_font_list_omt_enabled_AtStartup() &&
|
2021-10-28 20:10:45 +03:00
|
|
|
StaticPrefs::gfx_e10s_font_list_shared_AtStartup() &&
|
2021-05-18 14:10:43 +03:00
|
|
|
!gfxPlatform::InSafeMode()) {
|
|
|
|
sInitFontListThread = PR_CreateThread(
|
|
|
|
PR_USER_THREAD, InitFontListCallback, aList, PR_PRIORITY_NORMAL,
|
|
|
|
PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (aList->InitFontList()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
Shutdown();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
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),
|
2018-11-15 19:11:45 +03:00
|
|
|
mOtherFamilyNames(16),
|
2021-05-18 14:10:43 +03:00
|
|
|
mSharedCmaps(8) {
|
2015-04-03 22:39:23 +03:00
|
|
|
if (aNeedFullnamePostscriptNames) {
|
|
|
|
mExtraNames = MakeUnique<ExtraNames>();
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-04-03 22:39:23 +03:00
|
|
|
|
2010-01-28 09:56:16 +03:00
|
|
|
mLangService = nsLanguageAtomService::GetService();
|
|
|
|
|
2011-06-12 06:30:16 +04:00
|
|
|
LoadBadUnderlineList();
|
2018-07-06 00:47:39 +03:00
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
gfxFontUtils::GetPrefsFontList(kFontSystemWhitelistPref, mEnabledFontsList);
|
|
|
|
|
2018-07-06 00:47:39 +03:00
|
|
|
// pref changes notification setup
|
|
|
|
NS_ASSERTION(!gFontListPrefObserver,
|
|
|
|
"There has been font list pref observer already");
|
|
|
|
gFontListPrefObserver = new gfxFontListPrefObserver();
|
2011-06-12 06:30:16 +04:00
|
|
|
NS_ADDREF(gFontListPrefObserver);
|
2012-04-19 03:59:43 +04:00
|
|
|
|
2017-11-21 14:02:20 +03:00
|
|
|
Preferences::RegisterPrefixCallbacks(FontListPrefChanged, kObservedPrefs);
|
|
|
|
|
2017-11-02 23:29:33 +03:00
|
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
|
|
if (obs) {
|
|
|
|
obs->AddObserver(gFontListPrefObserver, LOCALES_CHANGED_TOPIC, false);
|
|
|
|
}
|
2016-08-23 03:06:07 +03:00
|
|
|
|
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);
|
2018-11-30 13:46:48 +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());
|
2020-12-31 03:33:48 +03:00
|
|
|
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
|
|
|
pfl->UpdateFontList(true);
|
|
|
|
dom::ContentParent::NotifyUpdatedFonts(true);
|
2017-11-02 23:29:33 +03:00
|
|
|
}
|
|
|
|
|
2016-08-23 03:06:07 +03:00
|
|
|
void gfxPlatformFontList::ApplyWhitelist() {
|
2021-05-18 14:10:43 +03:00
|
|
|
uint32_t numFonts = mEnabledFontsList.Length();
|
2016-08-23 03:06:07 +03:00
|
|
|
mFontFamilyWhitelistActive = (numFonts > 0);
|
|
|
|
if (!mFontFamilyWhitelistActive) {
|
|
|
|
return;
|
|
|
|
}
|
2021-03-23 13:36:36 +03:00
|
|
|
nsTHashSet<nsCString> familyNamesWhitelist;
|
2018-09-12 22:34:57 +03:00
|
|
|
for (uint32_t i = 0; i < numFonts; i++) {
|
|
|
|
nsAutoCString key;
|
2021-05-18 14:10:43 +03:00
|
|
|
ToLowerCase(mEnabledFontsList[i], key);
|
2021-03-23 13:36:36 +03:00
|
|
|
familyNamesWhitelist.Insert(key);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2019-06-30 04:35:29 +03:00
|
|
|
AutoTArray<RefPtr<gfxFontFamily>, 128> accepted;
|
2020-04-02 15:36:24 +03:00
|
|
|
bool whitelistedFontFound = false;
|
2021-03-12 19:14:58 +03:00
|
|
|
for (const auto& entry : mFontFamilies) {
|
|
|
|
if (entry.GetData()->IsHidden()) {
|
2020-04-02 15:36:24 +03:00
|
|
|
// Hidden system fonts are exempt from whitelisting, but don't count
|
|
|
|
// towards determining whether we "kept" any (user-visible) fonts
|
2021-03-12 19:14:58 +03:00
|
|
|
accepted.AppendElement(entry.GetData());
|
2020-04-02 15:36:24 +03:00
|
|
|
continue;
|
|
|
|
}
|
2021-03-12 19:14:58 +03:00
|
|
|
nsAutoCString fontFamilyName(entry.GetKey());
|
2017-08-01 13:25:35 +03:00
|
|
|
ToLowerCase(fontFamilyName);
|
2019-06-30 04:35:29 +03:00
|
|
|
if (familyNamesWhitelist.Contains(fontFamilyName)) {
|
2021-03-12 19:14:58 +03:00
|
|
|
accepted.AppendElement(entry.GetData());
|
2020-04-02 15:36:24 +03:00
|
|
|
whitelistedFontFound = true;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
2020-04-02 15:36:24 +03:00
|
|
|
if (!whitelistedFontFound) {
|
2019-06-30 04:35:29 +03:00
|
|
|
// No whitelisted fonts found! Ignore the whitelist.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Replace the original full list with the accepted subset.
|
|
|
|
mFontFamilies.Clear();
|
|
|
|
for (auto& f : accepted) {
|
|
|
|
nsAutoCString fontFamilyName(f->Name());
|
|
|
|
ToLowerCase(fontFamilyName);
|
2021-02-26 12:11:46 +03:00
|
|
|
mFontFamilies.InsertOrUpdate(fontFamilyName, std::move(f));
|
2019-06-30 04:35:29 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
void gfxPlatformFontList::ApplyWhitelist(
|
|
|
|
nsTArray<fontlist::Family::InitData>& aFamilies) {
|
2021-05-18 14:10:43 +03:00
|
|
|
mFontFamilyWhitelistActive = !mEnabledFontsList.IsEmpty();
|
2019-04-27 18:37:58 +03:00
|
|
|
if (!mFontFamilyWhitelistActive) {
|
|
|
|
return;
|
|
|
|
}
|
2021-03-23 13:36:36 +03:00
|
|
|
nsTHashSet<nsCString> familyNamesWhitelist;
|
2021-05-18 14:10:43 +03:00
|
|
|
for (const auto& item : mEnabledFontsList) {
|
2019-04-27 18:37:58 +03:00
|
|
|
nsAutoCString key;
|
|
|
|
ToLowerCase(item, key);
|
2021-03-23 13:36:36 +03:00
|
|
|
familyNamesWhitelist.Insert(key);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2019-06-30 04:35:29 +03:00
|
|
|
AutoTArray<fontlist::Family::InitData, 128> accepted;
|
2019-04-27 18:37:58 +03:00
|
|
|
bool keptNonHidden = false;
|
2019-06-30 04:35:29 +03:00
|
|
|
for (auto& f : aFamilies) {
|
2020-04-02 15:36:24 +03:00
|
|
|
if (f.mVisibility == FontVisibility::Hidden ||
|
|
|
|
familyNamesWhitelist.Contains(f.mKey)) {
|
2019-06-30 04:35:29 +03:00
|
|
|
accepted.AppendElement(f);
|
2020-04-02 15:36:24 +03:00
|
|
|
if (f.mVisibility != FontVisibility::Hidden) {
|
2019-06-30 04:35:29 +03:00
|
|
|
keptNonHidden = true;
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
}
|
2019-06-30 04:35:29 +03:00
|
|
|
if (!keptNonHidden) {
|
|
|
|
// No (visible) families were whitelisted: ignore the whitelist
|
|
|
|
// and just leave the fontlist unchanged.
|
|
|
|
return;
|
|
|
|
}
|
2020-05-05 13:56:14 +03:00
|
|
|
aFamilies = std::move(accepted);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
|
2020-04-02 04:38:21 +03:00
|
|
|
bool gfxPlatformFontList::FamilyInList(const nsACString& aName,
|
|
|
|
const char* aList[], size_t aCount) {
|
|
|
|
size_t result;
|
2021-08-06 17:06:53 +03:00
|
|
|
return BinarySearchIf(
|
|
|
|
aList, 0, aCount,
|
|
|
|
[&](const char* const aVal) -> int {
|
|
|
|
return nsCaseInsensitiveUTF8StringComparator(
|
|
|
|
aName.BeginReading(), aVal, aName.Length(), strlen(aVal));
|
|
|
|
},
|
|
|
|
&result);
|
2020-04-02 04:38:21 +03:00
|
|
|
}
|
|
|
|
|
2020-07-26 14:08:50 +03:00
|
|
|
void gfxPlatformFontList::CheckFamilyList(const char* aList[], size_t aCount) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
MOZ_ASSERT(aCount > 0, "empty font family list?");
|
|
|
|
const char* a = aList[0];
|
|
|
|
uint32_t aLen = strlen(a);
|
|
|
|
for (size_t i = 1; i < aCount; ++i) {
|
|
|
|
const char* b = aList[i];
|
|
|
|
uint32_t bLen = strlen(b);
|
|
|
|
MOZ_ASSERT(nsCaseInsensitiveUTF8StringComparator(a, b, aLen, bLen) < 0,
|
|
|
|
"incorrectly sorted font family list!");
|
|
|
|
a = b;
|
|
|
|
aLen = bLen;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-08-01 13:25:35 +03:00
|
|
|
bool gfxPlatformFontList::AddWithLegacyFamilyName(const nsACString& aLegacyName,
|
2020-04-02 15:36:24 +03:00
|
|
|
gfxFontEntry* aFontEntry,
|
|
|
|
FontVisibility aVisibility) {
|
2017-08-01 13:25:35 +03:00
|
|
|
bool added = false;
|
|
|
|
nsAutoCString key;
|
|
|
|
ToLowerCase(aLegacyName, key);
|
2021-03-01 12:59:29 +03:00
|
|
|
mOtherFamilyNames
|
|
|
|
.LookupOrInsertWith(
|
|
|
|
key,
|
|
|
|
[&] {
|
|
|
|
RefPtr<gfxFontFamily> family =
|
|
|
|
CreateFontFamily(aLegacyName, aVisibility);
|
|
|
|
family->SetHasStyles(
|
|
|
|
true); // we don't want the family to search for
|
|
|
|
// faces, we're adding them directly here
|
|
|
|
added = true;
|
|
|
|
return family;
|
|
|
|
})
|
|
|
|
->AddFontEntry(aFontEntry->Clone());
|
2015-08-05 05:03:41 +03:00
|
|
|
return added;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2021-05-18 14:10:42 +03:00
|
|
|
bool gfxPlatformFontList::InitFontList() {
|
2021-05-18 14:10:43 +03:00
|
|
|
MutexAutoLock lock(mFontFamiliesMutex);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-07-31 04:10:31 +03:00
|
|
|
if (LOG_FONTINIT_ENABLED()) {
|
|
|
|
LOG_FONTINIT(("(fontinit) system fontlist initialization\n"));
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2021-05-21 19:39:17 +03:00
|
|
|
if (IsInitialized()) {
|
2021-05-18 14:10:43 +03:00
|
|
|
// Font-list reinitialization always occurs on the main thread, in response
|
|
|
|
// to a change notification; it's only the initial creation during startup
|
|
|
|
// that may be on another thread.
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
// Rebuilding fontlist so clear out font/word caches.
|
|
|
|
gfxFontCache* fontCache = gfxFontCache::GetCache();
|
|
|
|
if (fontCache) {
|
|
|
|
fontCache->FlushShapedWordCaches();
|
|
|
|
fontCache->Flush();
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
gfxPlatform::PurgeSkiaFontCache();
|
2019-09-13 17:49:36 +03:00
|
|
|
|
2021-09-23 19:35:32 +03:00
|
|
|
// There's no need to broadcast this reflow request to child processes, as
|
|
|
|
// ContentParent::NotifyUpdatedFonts deals with it by re-entering into this
|
|
|
|
// function on child processes.
|
2021-05-18 14:10:43 +03:00
|
|
|
if (NS_IsMainThread()) {
|
2021-09-23 19:35:32 +03:00
|
|
|
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes,
|
|
|
|
gfxPlatform::BroadcastToChildren::No);
|
2021-05-18 14:10:43 +03:00
|
|
|
} else {
|
|
|
|
NS_DispatchToMainThread(
|
|
|
|
NS_NewRunnableFunction("font-info-updated notification callback", [] {
|
2021-10-18 16:38:24 +03:00
|
|
|
gfxPlatform::ForceGlobalReflow(
|
|
|
|
gfxPlatform::NeedsReframe::Yes,
|
|
|
|
gfxPlatform::BroadcastToChildren::No);
|
2021-05-18 14:10:43 +03:00
|
|
|
}));
|
|
|
|
}
|
2019-08-30 16:14:26 +03:00
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
mAliasTable.Clear();
|
|
|
|
mLocalNameTable.Clear();
|
2020-12-31 03:33:48 +03:00
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
CancelLoadCmapsTask();
|
|
|
|
mStartedLoadingCmapsFrom = 0xffffffffu;
|
|
|
|
|
|
|
|
CancelInitOtherFamilyNamesTask();
|
|
|
|
mFontFamilies.Clear();
|
|
|
|
mOtherFamilyNames.Clear();
|
|
|
|
mOtherFamilyNamesInitialized = false;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
if (mExtraNames) {
|
|
|
|
mExtraNames->mFullnames.Clear();
|
|
|
|
mExtraNames->mPostscriptNames.Clear();
|
|
|
|
}
|
|
|
|
mFaceNameListsInitialized = false;
|
|
|
|
ClearLangGroupPrefFonts();
|
|
|
|
CancelLoader();
|
|
|
|
|
2021-10-18 23:59:15 +03:00
|
|
|
// Clear cached family records that will no longer be valid.
|
|
|
|
for (auto& f : mReplacementCharFallbackFamily) {
|
|
|
|
f = FontFamily();
|
|
|
|
}
|
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
gfxFontUtils::GetPrefsFontList(kFontSystemWhitelistPref, mEnabledFontsList);
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2021-05-18 14:10:43 +03:00
|
|
|
// From here, gfxPlatformFontList::IsInitialized will return true,
|
|
|
|
// unless InitFontListForPlatform() fails and we reset it below.
|
|
|
|
mFontlistInitCount++;
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
// Try to initialize the cross-process shared font list if enabled by prefs,
|
|
|
|
// but not if we're running in Safe Mode.
|
2019-07-22 05:10:14 +03:00
|
|
|
if (StaticPrefs::gfx_e10s_font_list_shared_AtStartup() &&
|
|
|
|
!gfxPlatform::InSafeMode()) {
|
2021-03-24 20:56:49 +03:00
|
|
|
for (const auto& entry : mFontEntries.Values()) {
|
|
|
|
if (!entry) {
|
2019-10-01 23:35:28 +03:00
|
|
|
continue;
|
|
|
|
}
|
2021-03-24 20:56:49 +03:00
|
|
|
entry->mShmemCharacterMap = nullptr;
|
|
|
|
entry->mShmemFace = nullptr;
|
|
|
|
entry->mFamilyName.Truncate();
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
mFontEntries.Clear();
|
|
|
|
mShmemCharMaps.Clear();
|
|
|
|
bool oldSharedList = mSharedFontList != nullptr;
|
|
|
|
mSharedFontList.reset(new fontlist::FontList(mFontlistInitCount));
|
|
|
|
InitSharedFontListForPlatform();
|
2020-12-11 20:47:47 +03:00
|
|
|
if (mSharedFontList && mSharedFontList->Initialized()) {
|
2019-04-27 18:37:58 +03:00
|
|
|
if (mLocalNameTable.Count()) {
|
|
|
|
SharedFontList()->SetLocalNames(mLocalNameTable);
|
|
|
|
mLocalNameTable.Clear();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// something went wrong, fall back to in-process list
|
2020-11-05 15:22:20 +03:00
|
|
|
gfxCriticalNote << "Failed to initialize shared font list, "
|
|
|
|
"falling back to in-process list.";
|
2019-04-27 18:37:58 +03:00
|
|
|
mSharedFontList.reset(nullptr);
|
|
|
|
}
|
2021-05-18 14:10:42 +03:00
|
|
|
if (oldSharedList && XRE_IsParentProcess()) {
|
|
|
|
// notify all children of the change
|
2021-05-18 14:10:43 +03:00
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
dom::ContentParent::NotifyUpdatedFonts(true);
|
|
|
|
} else {
|
|
|
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
|
|
"NotifyUpdatedFonts callback",
|
|
|
|
[] { dom::ContentParent::NotifyUpdatedFonts(true); }));
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SharedFontList()) {
|
2021-05-18 14:10:42 +03:00
|
|
|
if (NS_FAILED(InitFontListForPlatform())) {
|
2021-05-18 14:10:43 +03:00
|
|
|
mFontlistInitCount = 0;
|
2021-05-18 14:10:42 +03:00
|
|
|
return false;
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
ApplyWhitelist();
|
2016-08-23 03:06:07 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2019-10-03 12:49:04 +03:00
|
|
|
// Set up mDefaultFontEntry as a "last resort" default that we can use
|
|
|
|
// to avoid crashing if the font list is otherwise unusable.
|
|
|
|
gfxFontStyle defStyle;
|
2021-09-08 15:18:17 +03:00
|
|
|
FontFamily fam = GetDefaultFont(nullptr, &defStyle);
|
2019-10-03 12:49:04 +03:00
|
|
|
if (fam.mIsShared) {
|
|
|
|
auto face = fam.mShared->FindFaceForStyle(SharedFontList(), defStyle);
|
2021-05-18 14:10:42 +03:00
|
|
|
mDefaultFontEntry =
|
|
|
|
face ? GetOrCreateFontEntry(face, fam.mShared) : nullptr;
|
2019-10-03 12:49:04 +03:00
|
|
|
} else {
|
|
|
|
mDefaultFontEntry = fam.mUnshared->FindFontForStyle(defStyle);
|
|
|
|
}
|
|
|
|
|
2021-05-18 14:10:42 +03:00
|
|
|
return true;
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2020-12-31 03:33:48 +03:00
|
|
|
void gfxPlatformFontList::InitializeCodepointsWithNoFonts() {
|
2021-09-08 15:18:17 +03:00
|
|
|
for (auto& bitset : mCodepointsWithNoFonts) {
|
|
|
|
bitset.reset();
|
|
|
|
bitset.SetRange(0, 0x1f); // C0 controls
|
|
|
|
bitset.SetRange(0x7f, 0x9f); // C1 controls
|
|
|
|
bitset.SetRange(0xE000, 0xF8FF); // PUA
|
|
|
|
bitset.SetRange(0xF0000, 0x10FFFD); // Supplementary PUA
|
|
|
|
bitset.SetRange(0xfdd0, 0xfdef); // noncharacters
|
|
|
|
for (unsigned i = 0; i <= 0x100000; i += 0x10000) {
|
|
|
|
bitset.SetRange(i + 0xfffe, i + 0xffff); // noncharacters
|
|
|
|
}
|
2021-09-08 14:48:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
void gfxPlatformFontList::FontListChanged() {
|
|
|
|
MOZ_ASSERT(!XRE_IsParentProcess());
|
2020-12-31 03:33:48 +03:00
|
|
|
InitializeCodepointsWithNoFonts();
|
2020-05-21 16:18:06 +03:00
|
|
|
if (SharedFontList()) {
|
|
|
|
// If we're using a shared local face-name list, this may have changed
|
|
|
|
// such that existing font entries held by user font sets are no longer
|
|
|
|
// safe to use: ensure they all get flushed.
|
|
|
|
RebuildLocalFonts(/*aForgetLocalFaces*/ true);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2021-08-27 02:17:54 +03:00
|
|
|
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::Yes);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
void gfxPlatformFontList::GenerateFontListKey(const nsACString& aKeyName,
|
|
|
|
nsACString& aResult) {
|
|
|
|
aResult = aKeyName;
|
|
|
|
ToLowerCase(aResult);
|
|
|
|
}
|
|
|
|
|
2019-10-31 17:41:15 +03:00
|
|
|
// Used if a stylo thread wants to trigger InitOtherFamilyNames in the main
|
|
|
|
// process: we can't do IPC from the stylo thread so we post this to the main
|
|
|
|
// thread instead.
|
|
|
|
class InitOtherFamilyNamesForStylo : public mozilla::Runnable {
|
|
|
|
public:
|
|
|
|
explicit InitOtherFamilyNamesForStylo(bool aDeferOtherFamilyNamesLoading)
|
|
|
|
: Runnable("gfxPlatformFontList::InitOtherFamilyNamesForStylo"),
|
|
|
|
mDefer(aDeferOtherFamilyNamesLoading) {}
|
|
|
|
|
|
|
|
NS_IMETHOD Run() override {
|
|
|
|
auto pfl = gfxPlatformFontList::PlatformFontList();
|
|
|
|
auto list = pfl->SharedFontList();
|
|
|
|
if (!list) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
dom::ContentChild::GetSingleton()->SendInitOtherFamilyNames(
|
|
|
|
list->GetGeneration(), mDefer, &pfl->mOtherFamilyNamesInitialized);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool mDefer;
|
|
|
|
};
|
|
|
|
|
2015-09-24 18:31:30 +03:00
|
|
|
#define OTHERNAMES_TIMEOUT 200
|
2014-04-23 09:20:21 +04:00
|
|
|
|
2020-12-26 20:11:44 +03:00
|
|
|
bool gfxPlatformFontList::InitOtherFamilyNames(
|
2017-08-03 03:33:00 +03:00
|
|
|
bool aDeferOtherFamilyNamesLoading) {
|
2014-04-23 09:20:21 +04:00
|
|
|
if (mOtherFamilyNamesInitialized) {
|
2020-12-26 20:11:44 +03:00
|
|
|
return true;
|
2014-04-23 09:20:21 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
if (SharedFontList() && !XRE_IsParentProcess()) {
|
2019-10-31 17:41:15 +03:00
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
dom::ContentChild::GetSingleton()->SendInitOtherFamilyNames(
|
|
|
|
SharedFontList()->GetGeneration(), aDeferOtherFamilyNamesLoading,
|
|
|
|
&mOtherFamilyNamesInitialized);
|
|
|
|
} else {
|
|
|
|
NS_DispatchToMainThread(
|
|
|
|
new InitOtherFamilyNamesForStylo(aDeferOtherFamilyNamesLoading));
|
|
|
|
}
|
2020-12-26 20:11:44 +03:00
|
|
|
return mOtherFamilyNamesInitialized;
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
|
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 &&
|
2020-10-03 19:03:54 +03:00
|
|
|
StaticPrefs::gfx_font_loader_delay_AtStartup() > 0) {
|
2017-08-03 03:33:00 +03:00
|
|
|
if (!mPendingOtherFamilyNameTask) {
|
|
|
|
RefPtr<mozilla::CancelableRunnable> task =
|
|
|
|
new InitOtherFamilyNamesRunnable();
|
|
|
|
mPendingOtherFamilyNameTask = task;
|
2019-01-26 20:18:05 +03:00
|
|
|
NS_DispatchToMainThreadQueue(task.forget(), EventQueuePriority::Idle);
|
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
|
|
|
}
|
2020-12-26 20:11:44 +03:00
|
|
|
return mOtherFamilyNamesInitialized;
|
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
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxFontEntry* gfxPlatformFontList::SearchFamiliesForFaceName(
|
|
|
|
const nsACString& 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));
|
|
|
|
|
2021-03-12 19:14:58 +03:00
|
|
|
for (const auto& entry : mFontFamilies) {
|
|
|
|
nsCStringHashKey::KeyType key = entry.GetKey();
|
|
|
|
const RefPtr<gfxFontFamily>& family = entry.GetData();
|
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
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxFontEntry* gfxPlatformFontList::FindFaceName(const nsACString& aFaceName) {
|
2014-04-23 09:20:20 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxFontEntry* gfxPlatformFontList::LookupInFaceNameLists(
|
|
|
|
const nsACString& aFaceName) {
|
2014-04-23 09:20:20 +04:00
|
|
|
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;
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2014-04-23 09:20:20 +04:00
|
|
|
|
|
|
|
// 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) {
|
2021-03-23 13:36:36 +03:00
|
|
|
mFaceNamesMissed = MakeUnique<nsTHashSet<nsCString>>(2);
|
2014-04-23 09:20:20 +04:00
|
|
|
}
|
2021-03-23 13:36:36 +03:00
|
|
|
mFaceNamesMissed->Insert(aFaceName);
|
2014-04-23 09:20:20 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2014-04-23 09:20:20 +04:00
|
|
|
|
|
|
|
return lookup;
|
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
gfxFontEntry* gfxPlatformFontList::LookupInSharedFaceNameList(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, const nsACString& aFaceName,
|
|
|
|
WeightRange aWeightForEntry, StretchRange aStretchForEntry,
|
|
|
|
SlantStyleRange aStyleForEntry) {
|
2019-04-27 18:37:58 +03:00
|
|
|
nsAutoCString keyName(aFaceName);
|
|
|
|
ToLowerCase(keyName);
|
|
|
|
fontlist::FontList* list = SharedFontList();
|
|
|
|
fontlist::Family* family = nullptr;
|
|
|
|
fontlist::Face* face = nullptr;
|
|
|
|
if (list->NumLocalFaces()) {
|
|
|
|
fontlist::LocalFaceRec* rec = list->FindLocalFace(keyName);
|
|
|
|
if (rec) {
|
2020-07-03 12:02:54 +03:00
|
|
|
auto* families = list->Families();
|
|
|
|
if (families) {
|
|
|
|
family = &families[rec->mFamilyIndex];
|
|
|
|
face = static_cast<fontlist::Face*>(
|
|
|
|
family->Faces(list)[rec->mFaceIndex].ToPtr(list));
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
list->SearchForLocalFace(keyName, &family, &face);
|
|
|
|
}
|
|
|
|
if (!face || !family) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2021-09-08 15:18:17 +03:00
|
|
|
FontVisibility level =
|
|
|
|
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
|
|
|
|
if (!IsVisibleToCSS(*family, level)) {
|
2021-09-23 16:36:18 +03:00
|
|
|
if (aPresContext) {
|
|
|
|
aPresContext->ReportBlockedFontFamily(*family);
|
|
|
|
}
|
2021-09-08 15:18:17 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
gfxFontEntry* fe = CreateFontEntry(face, family);
|
|
|
|
if (fe) {
|
|
|
|
fe->mIsLocalUserFont = true;
|
|
|
|
fe->mWeightRange = aWeightForEntry;
|
|
|
|
fe->mStretchRange = aStretchForEntry;
|
|
|
|
fe->mStyleRange = aStyleForEntry;
|
|
|
|
}
|
|
|
|
return fe;
|
|
|
|
}
|
|
|
|
|
2010-01-28 09:56:16 +03:00
|
|
|
void gfxPlatformFontList::LoadBadUnderlineList() {
|
2018-11-15 19:11:45 +03:00
|
|
|
gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset",
|
|
|
|
mBadUnderlineFamilyNames);
|
|
|
|
for (auto& fam : mBadUnderlineFamilyNames) {
|
|
|
|
ToLowerCase(fam);
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
2018-11-15 19:11:45 +03:00
|
|
|
mBadUnderlineFamilyNames.Compact();
|
|
|
|
mBadUnderlineFamilyNames.Sort();
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2020-12-31 03:33:48 +03:00
|
|
|
void gfxPlatformFontList::UpdateFontList(bool aFullRebuild) {
|
2019-04-27 18:37:58 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2020-12-31 03:33:48 +03:00
|
|
|
if (aFullRebuild) {
|
|
|
|
InitFontList();
|
|
|
|
RebuildLocalFonts();
|
|
|
|
} else {
|
2021-01-25 21:25:42 +03:00
|
|
|
// The font list isn't being fully rebuilt, we're just being notified that
|
|
|
|
// character maps have been updated and so font fallback needs to be re-
|
|
|
|
// done. We only care about this if we have previously encountered a
|
|
|
|
// fallback that required cmaps that were not yet available, and so we
|
|
|
|
// asked for the async cmap loader to run.
|
|
|
|
if (mStartedLoadingCmapsFrom != 0xffffffffu) {
|
|
|
|
InitializeCodepointsWithNoFonts();
|
|
|
|
mStartedLoadingCmapsFrom = 0xffffffffu;
|
2021-08-27 02:17:54 +03:00
|
|
|
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No);
|
2021-01-25 21:25:42 +03:00
|
|
|
}
|
2020-12-31 03:33:48 +03:00
|
|
|
}
|
2014-04-17 18:17:22 +04:00
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:17 +03:00
|
|
|
bool gfxPlatformFontList::IsVisibleToCSS(const gfxFontFamily& aFamily,
|
|
|
|
FontVisibility aVisibility) const {
|
|
|
|
return aFamily.Visibility() <= aVisibility || IsFontFamilyWhitelistActive();
|
2020-05-08 00:10:46 +03:00
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:17 +03:00
|
|
|
bool gfxPlatformFontList::IsVisibleToCSS(const fontlist::Family& aFamily,
|
|
|
|
FontVisibility aVisibility) const {
|
|
|
|
return aFamily.Visibility() <= aVisibility || IsFontFamilyWhitelistActive();
|
2020-05-08 00:10:46 +03:00
|
|
|
}
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
void gfxPlatformFontList::GetFontList(nsAtom* aLangGroup,
|
2009-08-16 17:52:12 +04:00
|
|
|
const nsACString& aGenericFamily,
|
|
|
|
nsTArray<nsString>& aListOfFonts) {
|
2019-04-27 18:37:58 +03:00
|
|
|
if (SharedFontList()) {
|
|
|
|
fontlist::FontList* list = SharedFontList();
|
|
|
|
const fontlist::Family* families = list->Families();
|
2020-07-03 12:02:54 +03:00
|
|
|
if (families) {
|
|
|
|
for (uint32_t i = 0; i < list->NumFamilies(); i++) {
|
|
|
|
auto& f = families[i];
|
2021-09-08 15:18:17 +03:00
|
|
|
if (!IsVisibleToCSS(f, FontVisibility::User) || f.IsAltLocaleFamily()) {
|
2020-07-03 12:02:54 +03:00
|
|
|
continue;
|
|
|
|
}
|
2020-07-04 12:38:43 +03:00
|
|
|
// XXX TODO: filter families for aGenericFamily, if supported by
|
|
|
|
// platform
|
2020-07-03 12:02:54 +03:00
|
|
|
aListOfFonts.AppendElement(
|
2020-10-14 15:49:37 +03:00
|
|
|
NS_ConvertUTF8toUTF16(list->LocalizedFamilyName(&f)));
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-12 21:05:37 +03:00
|
|
|
MutexAutoLock lock(mFontFamiliesMutex);
|
2021-03-24 20:56:49 +03:00
|
|
|
for (const RefPtr<gfxFontFamily>& family : mFontFamilies.Values()) {
|
2021-09-08 15:18:17 +03:00
|
|
|
if (!IsVisibleToCSS(*family, FontVisibility::User)) {
|
2020-04-02 15:36:24 +03:00
|
|
|
continue;
|
|
|
|
}
|
2017-09-11 21:24:01 +03:00
|
|
|
if (family->FilterForFontList(aLangGroup, aGenericFamily)) {
|
2018-09-12 22:34:57 +03:00
|
|
|
nsAutoCString localizedFamilyName;
|
2015-09-24 18:31:30 +03:00
|
|
|
family->LocalizedName(localizedFamilyName);
|
2018-09-12 22:34:57 +03:00
|
|
|
aListOfFonts.AppendElement(NS_ConvertUTF8toUTF16(localizedFamilyName));
|
2015-09-24 18:31:30 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
|
|
|
|
aListOfFonts.Sort();
|
|
|
|
aListOfFonts.Compact();
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
void gfxPlatformFontList::GetFontFamilyList(
|
|
|
|
nsTArray<RefPtr<gfxFontFamily>>& aFamilyArray) {
|
2021-03-24 20:56:49 +03:00
|
|
|
MOZ_ASSERT(aFamilyArray.IsEmpty());
|
|
|
|
// This doesn't use ToArray, because the caller passes an AutoTArray.
|
|
|
|
aFamilyArray.SetCapacity(mFontFamilies.Count());
|
|
|
|
for (const auto& family : mFontFamilies.Values()) {
|
2015-09-24 18:31:30 +03:00
|
|
|
aFamilyArray.AppendElement(family);
|
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2020-08-26 12:31:58 +03:00
|
|
|
gfxFont* gfxPlatformFontList::SystemFindFontForChar(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh,
|
|
|
|
Script aRunScript, eFontPresentation aPresentation,
|
|
|
|
const gfxFontStyle* aStyle, FontVisibility* aVisibility) {
|
|
|
|
FontVisibility level =
|
|
|
|
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
|
|
|
|
MOZ_ASSERT(!mCodepointsWithNoFonts[level].test(aCh),
|
2019-08-22 23:59:57 +03:00
|
|
|
"don't call for codepoints already known to be unsupported");
|
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.
|
2019-04-01 17:33:34 +03:00
|
|
|
if (aCh == 0xFFFD) {
|
2020-08-26 12:31:58 +03:00
|
|
|
gfxFontEntry* fontEntry = nullptr;
|
2021-09-08 15:18:17 +03:00
|
|
|
auto& fallbackFamily = mReplacementCharFallbackFamily[level];
|
2021-09-08 15:18:17 +03:00
|
|
|
if (fallbackFamily.mIsShared && fallbackFamily.mShared) {
|
2019-04-27 18:37:58 +03:00
|
|
|
fontlist::Face* face =
|
2021-09-08 15:18:17 +03:00
|
|
|
fallbackFamily.mShared->FindFaceForStyle(SharedFontList(), *aStyle);
|
2019-04-27 18:37:58 +03:00
|
|
|
if (face) {
|
2021-09-08 15:18:17 +03:00
|
|
|
fontEntry = GetOrCreateFontEntry(face, fallbackFamily.mShared);
|
|
|
|
*aVisibility = fallbackFamily.mShared->Visibility();
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2021-09-08 15:18:17 +03:00
|
|
|
} else if (!fallbackFamily.mIsShared && fallbackFamily.mUnshared) {
|
|
|
|
fontEntry = fallbackFamily.mUnshared->FindFontForStyle(*aStyle);
|
|
|
|
*aVisibility = fallbackFamily.mUnshared->Visibility();
|
2019-04-01 17:33:34 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-12-19 13:42:25 +04:00
|
|
|
// this should never fail, as we must have found U+FFFD in order to set
|
2021-09-08 15:18:17 +03:00
|
|
|
// mReplacementCharFallbackFamily[...] at all, but better play it safe
|
2015-01-15 14:07:24 +03:00
|
|
|
if (fontEntry && fontEntry->HasCharacter(aCh)) {
|
2020-08-26 12:31:58 +03:00
|
|
|
return fontEntry->FindOrMakeFont(aStyle);
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2011-11-30 05:55:11 +04:00
|
|
|
TimeStamp start = TimeStamp::Now();
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-03-09 06:05:24 +04:00
|
|
|
// search commonly available fonts
|
2013-11-25 06:02:14 +04:00
|
|
|
bool common = true;
|
2019-04-01 17:33:34 +03:00
|
|
|
FontFamily fallbackFamily;
|
2021-09-08 15:18:17 +03:00
|
|
|
gfxFont* candidate =
|
|
|
|
CommonFontFallback(aPresContext, aCh, aNextCh, aRunScript, aPresentation,
|
|
|
|
aStyle, fallbackFamily);
|
2020-08-26 12:31:58 +03:00
|
|
|
gfxFont* font = nullptr;
|
|
|
|
if (candidate) {
|
|
|
|
if (aPresentation == eFontPresentation::Any) {
|
|
|
|
font = candidate;
|
|
|
|
} else {
|
|
|
|
bool hasColorGlyph = candidate->HasColorGlyphFor(aCh, aNextCh);
|
2020-09-01 10:43:53 +03:00
|
|
|
if (hasColorGlyph == PrefersColor(aPresentation)) {
|
2020-08-26 12:31:58 +03:00
|
|
|
font = candidate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2020-08-26 12:31:58 +03:00
|
|
|
// If we didn't find a common font, or it was not the preferred type (color
|
|
|
|
// or monochrome), do system-wide fallback (except for specials).
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t cmapCount = 0;
|
2020-08-26 12:31:58 +03:00
|
|
|
if (!font) {
|
2013-11-25 06:02:14 +04:00
|
|
|
common = false;
|
2021-09-08 15:18:17 +03:00
|
|
|
font = GlobalFontFallback(aPresContext, aCh, aNextCh, aRunScript,
|
|
|
|
aPresentation, aStyle, cmapCount, fallbackFamily);
|
2020-08-26 12:31:58 +03:00
|
|
|
// If the font we found doesn't match the requested type, and we also found
|
|
|
|
// a candidate above, prefer that one.
|
|
|
|
if (font && aPresentation != eFontPresentation::Any && candidate) {
|
|
|
|
bool hasColorGlyph = font->HasColorGlyphFor(aCh, aNextCh);
|
2020-09-01 10:43:53 +03:00
|
|
|
if (hasColorGlyph != PrefersColor(aPresentation)) {
|
2020-09-01 07:30:57 +03:00
|
|
|
// We're discarding `font` and using `candidate` instead, so ensure
|
|
|
|
// `font` is known to the global cache expiration tracker.
|
|
|
|
RefPtr<gfxFont> autoRefDeref(font);
|
2020-08-26 12:31:58 +03:00
|
|
|
font = candidate;
|
|
|
|
}
|
|
|
|
}
|
2012-03-09 06:05:24 +04:00
|
|
|
}
|
2011-11-30 05:55:11 +04:00
|
|
|
TimeDuration elapsed = TimeStamp::Now() - start;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-10-30 01:58:24 +03:00
|
|
|
LogModule* log = gfxPlatform::GetLog(eGfxLog_textrun);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_UNLIKELY(MOZ_LOG_TEST(log, LogLevel::Warning))) {
|
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 "
|
2019-04-11 00:43:22 +03:00
|
|
|
"script: %d match: [%s]"
|
2012-03-09 06:05:24 +04:00
|
|
|
" time: %dus cmaps: %d\n",
|
2019-04-11 00:43:22 +03:00
|
|
|
(common ? "common" : "global"), aCh, static_cast<int>(script),
|
2020-08-26 12:31:58 +03:00
|
|
|
(font ? font->GetFontEntry()->Name().get() : "<none>"),
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t(elapsed.ToMicroseconds()), cmapCount));
|
2011-01-21 19:44:33 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
// no match? add to set of non-matching codepoints
|
2020-08-26 12:31:58 +03:00
|
|
|
if (!font) {
|
2021-09-08 15:18:17 +03:00
|
|
|
mCodepointsWithNoFonts[level].set(aCh);
|
2020-04-02 04:38:18 +03:00
|
|
|
} else {
|
|
|
|
*aVisibility = fallbackFamily.mIsShared
|
|
|
|
? fallbackFamily.mShared->Visibility()
|
|
|
|
: fallbackFamily.mUnshared->Visibility();
|
|
|
|
if (aCh == 0xFFFD) {
|
2021-09-08 15:18:17 +03:00
|
|
|
mReplacementCharFallbackFamily[level] = fallbackFamily;
|
2020-04-02 04:38:18 +03:00
|
|
|
}
|
2012-12-19 13:42:25 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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() : elapsed.ToMicroseconds());
|
2011-11-30 05:55:11 +04:00
|
|
|
Telemetry::Accumulate((first ? Telemetry::SYSTEM_FONT_FALLBACK_FIRST
|
|
|
|
: Telemetry::SYSTEM_FONT_FALLBACK),
|
|
|
|
intElapsed);
|
|
|
|
first = false;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2020-08-26 12:31:58 +03:00
|
|
|
return font;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-03-09 06:05:24 +04:00
|
|
|
#define NUM_FALLBACK_FONTS 8
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2020-08-26 12:31:58 +03:00
|
|
|
gfxFont* gfxPlatformFontList::CommonFontFallback(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh,
|
|
|
|
Script aRunScript, eFontPresentation aPresentation,
|
|
|
|
const gfxFontStyle* aMatchStyle, FontFamily& aMatchedFamily) {
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<const char*, NUM_FALLBACK_FONTS> defaultFallbacks;
|
2020-08-26 12:31:58 +03:00
|
|
|
gfxPlatform::GetPlatform()->GetCommonFallbackFonts(
|
|
|
|
aCh, aRunScript, aPresentation, defaultFallbacks);
|
|
|
|
GlobalFontMatch data(aCh, aNextCh, *aMatchStyle, aPresentation);
|
2021-09-08 15:18:17 +03:00
|
|
|
FontVisibility level =
|
|
|
|
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
|
2019-04-27 18:37:58 +03:00
|
|
|
if (SharedFontList()) {
|
|
|
|
for (const auto name : defaultFallbacks) {
|
2021-09-08 15:18:17 +03:00
|
|
|
fontlist::Family* family =
|
|
|
|
FindSharedFamily(aPresContext, nsDependentCString(name));
|
|
|
|
if (!family || !IsVisibleToCSS(*family, level)) {
|
2019-04-27 18:37:58 +03:00
|
|
|
continue;
|
|
|
|
}
|
2020-12-31 03:33:48 +03:00
|
|
|
// XXX(jfkthame) Should we fire the async cmap-loader here, or let it
|
|
|
|
// always do a potential sync initialization of the family?
|
2019-04-27 18:37:58 +03:00
|
|
|
family->SearchAllFontsForChar(SharedFontList(), &data);
|
2019-02-08 13:05:56 +03:00
|
|
|
if (data.mBestMatch) {
|
2020-05-08 00:10:46 +03:00
|
|
|
aMatchedFamily = FontFamily(family);
|
2020-08-26 12:31:58 +03:00
|
|
|
return data.mBestMatch->FindOrMakeFont(aMatchStyle);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2012-03-09 06:05:24 +04:00
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
} else {
|
|
|
|
for (const auto name : defaultFallbacks) {
|
|
|
|
gfxFontFamily* fallback =
|
|
|
|
FindFamilyByCanonicalName(nsDependentCString(name));
|
2021-09-08 15:18:17 +03:00
|
|
|
if (!fallback || !IsVisibleToCSS(*fallback, level)) {
|
2020-05-08 00:10:46 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
fallback->FindFontForChar(&data);
|
|
|
|
if (data.mBestMatch) {
|
|
|
|
aMatchedFamily = FontFamily(fallback);
|
2020-08-26 12:31:58 +03:00
|
|
|
return data.mBestMatch->FindOrMakeFont(aMatchStyle);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-03-09 06:05:24 +04:00
|
|
|
}
|
|
|
|
|
2020-08-26 12:31:58 +03:00
|
|
|
gfxFont* gfxPlatformFontList::GlobalFontFallback(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, uint32_t aCh, uint32_t aNextCh,
|
|
|
|
Script aRunScript, eFontPresentation aPresentation,
|
|
|
|
const gfxFontStyle* aMatchStyle, uint32_t& aCmapCount,
|
|
|
|
FontFamily& aMatchedFamily) {
|
2017-07-13 11:40:33 +03:00
|
|
|
bool useCmaps = IsFontFamilyWhitelistActive() ||
|
|
|
|
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
|
2021-09-08 15:18:17 +03:00
|
|
|
FontVisibility level =
|
|
|
|
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
|
2017-07-13 11:40:33 +03:00
|
|
|
if (!useCmaps) {
|
|
|
|
// Allow platform-specific fallback code to try and find a usable font
|
2021-09-08 15:18:17 +03:00
|
|
|
gfxFontEntry* fe = PlatformGlobalFontFallback(aPresContext, aCh, aRunScript,
|
|
|
|
aMatchStyle, aMatchedFamily);
|
2017-07-13 11:40:33 +03:00
|
|
|
if (fe) {
|
2020-05-08 11:58:08 +03:00
|
|
|
if (aMatchedFamily.mIsShared) {
|
2021-09-08 15:18:17 +03:00
|
|
|
if (IsVisibleToCSS(*aMatchedFamily.mShared, level)) {
|
2020-08-26 12:31:58 +03:00
|
|
|
gfxFont* font = fe->FindOrMakeFont(aMatchStyle);
|
|
|
|
if (font) {
|
|
|
|
if (aPresentation == eFontPresentation::Any) {
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
bool hasColorGlyph = font->HasColorGlyphFor(aCh, aNextCh);
|
2020-09-01 10:43:53 +03:00
|
|
|
if (hasColorGlyph == PrefersColor(aPresentation)) {
|
2020-08-26 12:31:58 +03:00
|
|
|
return font;
|
|
|
|
}
|
2021-02-15 21:59:20 +03:00
|
|
|
// If we don't use this font, we need to touch its refcount
|
|
|
|
// to trigger gfxFontCache expiration tracking.
|
|
|
|
RefPtr<gfxFont> autoRefDeref(font);
|
2020-08-26 12:31:58 +03:00
|
|
|
}
|
2020-05-08 11:58:08 +03:00
|
|
|
}
|
|
|
|
} else {
|
2021-09-08 15:18:17 +03:00
|
|
|
if (IsVisibleToCSS(*aMatchedFamily.mUnshared, level)) {
|
2020-08-26 12:31:58 +03:00
|
|
|
gfxFont* font = fe->FindOrMakeFont(aMatchStyle);
|
|
|
|
if (font) {
|
|
|
|
if (aPresentation == eFontPresentation::Any) {
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
bool hasColorGlyph = font->HasColorGlyphFor(aCh, aNextCh);
|
2020-09-01 10:43:53 +03:00
|
|
|
if (hasColorGlyph == PrefersColor(aPresentation)) {
|
2020-08-26 12:31:58 +03:00
|
|
|
return font;
|
|
|
|
}
|
2021-02-15 21:59:20 +03:00
|
|
|
RefPtr<gfxFont> autoRefDeref(font);
|
2020-08-26 12:31:58 +03:00
|
|
|
}
|
2020-05-08 11:58:08 +03:00
|
|
|
}
|
2020-05-08 00:10:46 +03:00
|
|
|
}
|
2017-07-13 11:40:33 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2017-07-13 11:40:33 +03:00
|
|
|
|
2012-03-09 06:05:24 +04:00
|
|
|
// otherwise, try to find it among local fonts
|
2020-08-26 12:31:58 +03:00
|
|
|
GlobalFontMatch data(aCh, aNextCh, *aMatchStyle, aPresentation);
|
2019-04-27 18:37:58 +03:00
|
|
|
if (SharedFontList()) {
|
|
|
|
fontlist::Family* families = SharedFontList()->Families();
|
2020-07-03 12:02:54 +03:00
|
|
|
if (families) {
|
|
|
|
for (uint32_t i = 0; i < SharedFontList()->NumFamilies(); i++) {
|
|
|
|
fontlist::Family& family = families[i];
|
2021-09-08 15:18:17 +03:00
|
|
|
if (!IsVisibleToCSS(family, level)) {
|
2020-07-03 12:02:54 +03:00
|
|
|
continue;
|
|
|
|
}
|
2020-12-31 03:33:48 +03:00
|
|
|
if (!family.IsFullyInitialized() &&
|
2021-06-14 20:09:21 +03:00
|
|
|
StaticPrefs::gfx_font_rendering_fallback_async() &&
|
|
|
|
!XRE_IsParentProcess()) {
|
2020-12-31 03:33:48 +03:00
|
|
|
// Start loading all the missing charmaps; but this is async,
|
|
|
|
// so for now we just continue, ignoring this family.
|
|
|
|
StartCmapLoadingFromFamily(i);
|
|
|
|
} else {
|
|
|
|
family.SearchAllFontsForChar(SharedFontList(), &data);
|
|
|
|
if (data.mMatchDistance == 0.0) {
|
|
|
|
// no better style match is possible, so stop searching
|
|
|
|
break;
|
|
|
|
}
|
2020-07-03 12:02:54 +03:00
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2020-07-03 12:02:54 +03:00
|
|
|
if (data.mBestMatch) {
|
|
|
|
aMatchedFamily = FontFamily(data.mMatchedSharedFamily);
|
2020-08-26 12:31:58 +03:00
|
|
|
return data.mBestMatch->FindOrMakeFont(aMatchStyle);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// iterate over all font families to find a font that support the
|
|
|
|
// character
|
2021-03-24 20:56:49 +03:00
|
|
|
for (const RefPtr<gfxFontFamily>& family : mFontFamilies.Values()) {
|
2021-09-08 15:18:17 +03:00
|
|
|
if (!IsVisibleToCSS(*family, level)) {
|
2020-05-08 00:10:46 +03:00
|
|
|
continue;
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
// evaluate all fonts in this family for a match
|
|
|
|
family->FindFontForChar(&data);
|
|
|
|
if (data.mMatchDistance == 0.0) {
|
|
|
|
// no better style match is possible, so stop searching
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-03-09 06:05:24 +04:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
aCmapCount = data.mCmapsTested;
|
|
|
|
if (data.mBestMatch) {
|
2020-05-08 00:10:46 +03:00
|
|
|
aMatchedFamily = FontFamily(data.mMatchedFamily);
|
2020-08-26 12:31:58 +03:00
|
|
|
return data.mBestMatch->FindOrMakeFont(aMatchStyle);
|
2019-03-19 13:49:53 +03:00
|
|
|
}
|
2015-09-24 18:31:30 +03:00
|
|
|
}
|
2012-03-09 06:05:24 +04:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
return nullptr;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2020-12-31 03:33:48 +03:00
|
|
|
class StartCmapLoadingRunnable : public mozilla::Runnable {
|
|
|
|
public:
|
|
|
|
explicit StartCmapLoadingRunnable(uint32_t aStartIndex)
|
|
|
|
: Runnable("gfxPlatformFontList::StartCmapLoadingRunnable"),
|
|
|
|
mStartIndex(aStartIndex) {}
|
|
|
|
|
|
|
|
NS_IMETHOD Run() override {
|
|
|
|
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
|
|
|
auto* list = pfl->SharedFontList();
|
|
|
|
if (!list) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
if (mStartIndex >= list->NumFamilies()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
pfl->StartCmapLoading(list->GetGeneration(), mStartIndex);
|
|
|
|
} else {
|
|
|
|
dom::ContentChild::GetSingleton()->SendStartCmapLoading(
|
|
|
|
list->GetGeneration(), mStartIndex);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint32_t mStartIndex;
|
|
|
|
};
|
|
|
|
|
|
|
|
void gfxPlatformFontList::StartCmapLoadingFromFamily(uint32_t aStartIndex) {
|
|
|
|
if (aStartIndex > mStartedLoadingCmapsFrom) {
|
|
|
|
// We already initiated cmap-loading from somewhere earlier in the list;
|
|
|
|
// no need to do it again here.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mStartedLoadingCmapsFrom = aStartIndex;
|
|
|
|
|
|
|
|
// If we're already on the main thread, don't bother dispatching a runnable
|
|
|
|
// here to kick off the loading process, just do it directly.
|
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
auto* list = SharedFontList();
|
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
StartCmapLoading(list->GetGeneration(), aStartIndex);
|
|
|
|
} else {
|
|
|
|
dom::ContentChild::GetSingleton()->SendStartCmapLoading(
|
|
|
|
list->GetGeneration(), aStartIndex);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
NS_DispatchToMainThread(new StartCmapLoadingRunnable(aStartIndex));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class LoadCmapsRunnable : public CancelableRunnable {
|
2021-06-07 00:24:44 +03:00
|
|
|
class WillShutdownObserver : public nsIObserver {
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
|
|
|
|
explicit WillShutdownObserver(LoadCmapsRunnable* aRunnable)
|
|
|
|
: mRunnable(aRunnable) {}
|
|
|
|
|
|
|
|
void Remove() {
|
|
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
|
|
if (obs) {
|
|
|
|
obs->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);
|
|
|
|
}
|
|
|
|
mRunnable = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual ~WillShutdownObserver() = default;
|
|
|
|
|
|
|
|
LoadCmapsRunnable* mRunnable;
|
|
|
|
};
|
|
|
|
|
2020-12-31 03:33:48 +03:00
|
|
|
public:
|
|
|
|
explicit LoadCmapsRunnable(uint32_t aGeneration, uint32_t aFamilyIndex)
|
|
|
|
: CancelableRunnable("gfxPlatformFontList::LoadCmapsRunnable"),
|
|
|
|
mGeneration(aGeneration),
|
|
|
|
mStartIndex(aFamilyIndex),
|
2021-06-07 00:24:44 +03:00
|
|
|
mIndex(aFamilyIndex) {
|
|
|
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
|
|
if (obs) {
|
|
|
|
mObserver = new WillShutdownObserver(this);
|
|
|
|
obs->AddObserver(mObserver, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~LoadCmapsRunnable() {
|
|
|
|
if (mObserver) {
|
|
|
|
mObserver->Remove();
|
|
|
|
}
|
|
|
|
}
|
2020-12-31 03:33:48 +03:00
|
|
|
|
|
|
|
// Reset the current family index, if the value passed is earlier than our
|
|
|
|
// original starting position. We don't "reset" if it would move the current
|
|
|
|
// position forward, or back into the already-scanned range.
|
|
|
|
// We could optimize further by remembering the current position reached,
|
|
|
|
// and then skipping ahead from the original start, but it doesn't seem worth
|
|
|
|
// extra complexity for a task that usually only happens once, and already-
|
|
|
|
// processed families will be skipped pretty quickly in Run() anyhow.
|
|
|
|
void MaybeResetIndex(uint32_t aFamilyIndex) {
|
|
|
|
if (aFamilyIndex < mStartIndex) {
|
|
|
|
mStartIndex = aFamilyIndex;
|
|
|
|
mIndex = aFamilyIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult Cancel() override {
|
|
|
|
mIsCanceled = true;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run() override {
|
|
|
|
if (mIsCanceled) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
auto* pfl = gfxPlatformFontList::PlatformFontList();
|
|
|
|
auto* list = pfl->SharedFontList();
|
|
|
|
MOZ_ASSERT(list);
|
|
|
|
if (!list) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
if (mGeneration != list->GetGeneration()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
uint32_t numFamilies = list->NumFamilies();
|
|
|
|
if (mIndex >= numFamilies) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
auto* families = list->Families();
|
|
|
|
// Skip any families that are already initialized.
|
|
|
|
while (mIndex < numFamilies && families[mIndex].IsFullyInitialized()) {
|
|
|
|
++mIndex;
|
|
|
|
}
|
|
|
|
// Fully process one family, and advance index.
|
|
|
|
if (mIndex < numFamilies) {
|
|
|
|
Unused << pfl->InitializeFamily(&families[mIndex], true);
|
|
|
|
++mIndex;
|
|
|
|
}
|
|
|
|
// If there are more families to initialize, post ourselves back to the
|
|
|
|
// idle queue to handle the next one; otherwise we're finished and we need
|
|
|
|
// to notify content processes to update their rendering.
|
|
|
|
if (mIndex < numFamilies) {
|
|
|
|
RefPtr<CancelableRunnable> task = this;
|
|
|
|
NS_DispatchToMainThreadQueue(task.forget(), EventQueuePriority::Idle);
|
|
|
|
} else {
|
|
|
|
pfl->CancelLoadCmapsTask();
|
|
|
|
pfl->InitializeCodepointsWithNoFonts();
|
|
|
|
dom::ContentParent::NotifyUpdatedFonts(false);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint32_t mGeneration;
|
|
|
|
uint32_t mStartIndex;
|
|
|
|
uint32_t mIndex;
|
|
|
|
bool mIsCanceled = false;
|
2021-06-07 00:24:44 +03:00
|
|
|
|
|
|
|
RefPtr<WillShutdownObserver> mObserver;
|
2020-12-31 03:33:48 +03:00
|
|
|
};
|
|
|
|
|
2021-06-07 00:24:44 +03:00
|
|
|
NS_IMPL_ISUPPORTS(LoadCmapsRunnable::WillShutdownObserver, nsIObserver)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
LoadCmapsRunnable::WillShutdownObserver::Observe(nsISupports* aSubject,
|
|
|
|
const char* aTopic,
|
|
|
|
const char16_t* aData) {
|
|
|
|
if (!nsCRT::strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID)) {
|
|
|
|
if (mRunnable) {
|
|
|
|
mRunnable->Cancel();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT_UNREACHABLE("unexpected notification topic");
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2020-12-31 03:33:48 +03:00
|
|
|
void gfxPlatformFontList::StartCmapLoading(uint32_t aGeneration,
|
|
|
|
uint32_t aStartIndex) {
|
|
|
|
MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
|
|
|
|
if (aGeneration != SharedFontList()->GetGeneration()) {
|
|
|
|
return;
|
|
|
|
}
|
2021-06-07 00:24:44 +03:00
|
|
|
if (AppShutdown::IsShuttingDown()) {
|
|
|
|
return;
|
|
|
|
}
|
2020-12-31 03:33:48 +03:00
|
|
|
if (mLoadCmapsRunnable) {
|
|
|
|
// We already have a runnable; just make sure it covers the full range of
|
|
|
|
// families needed.
|
|
|
|
static_cast<LoadCmapsRunnable*>(mLoadCmapsRunnable.get())
|
|
|
|
->MaybeResetIndex(aStartIndex);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mLoadCmapsRunnable = new LoadCmapsRunnable(aGeneration, aStartIndex);
|
|
|
|
RefPtr<CancelableRunnable> task = mLoadCmapsRunnable;
|
|
|
|
NS_DispatchToMainThreadQueue(task.forget(), EventQueuePriority::Idle);
|
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
gfxFontFamily* gfxPlatformFontList::CheckFamily(gfxFontFamily* aFamily) {
|
|
|
|
if (aFamily && !aFamily->HasStyles()) {
|
|
|
|
aFamily->FindStyleVariations();
|
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
if (aFamily && aFamily->GetFontList().Length() == 0) {
|
2017-08-01 13:25:35 +03:00
|
|
|
// failed to load any faces for this family, so discard it
|
2018-09-12 22:34:57 +03:00
|
|
|
nsAutoCString key;
|
2014-01-29 11:39:01 +04:00
|
|
|
GenerateFontListKey(aFamily->Name(), key);
|
|
|
|
mFontFamilies.Remove(key);
|
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
return aFamily;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
bool gfxPlatformFontList::FindAndAddFamilies(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, StyleGenericFontFamily aGeneric,
|
|
|
|
const nsACString& aFamily, nsTArray<FamilyAndGeneric>* aOutput,
|
|
|
|
FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage,
|
|
|
|
gfxFloat aDevToCssSize) {
|
2018-09-12 22:34:57 +03:00
|
|
|
nsAutoCString key;
|
2009-08-16 17:52:12 +04:00
|
|
|
GenerateFontListKey(aFamily, key);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2020-04-02 15:36:24 +03:00
|
|
|
bool allowHidden = bool(aFlags & FindFamiliesFlags::eSearchHiddenFamilies);
|
2021-09-08 15:18:17 +03:00
|
|
|
FontVisibility visibilityLevel =
|
|
|
|
aPresContext ? aPresContext->GetFontVisibility() : FontVisibility::User;
|
2019-04-27 18:37:58 +03:00
|
|
|
if (SharedFontList()) {
|
2020-05-08 00:10:46 +03:00
|
|
|
fontlist::Family* family = SharedFontList()->FindFamily(key);
|
2019-04-27 18:37:58 +03:00
|
|
|
// If not found, and other family names have not yet been initialized,
|
|
|
|
// initialize the rest of the list and try again. This is done lazily
|
|
|
|
// 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.
|
2020-04-02 04:38:18 +03:00
|
|
|
if (!family && !mOtherFamilyNamesInitialized) {
|
2019-10-23 13:40:16 +03:00
|
|
|
bool triggerLoading = true;
|
|
|
|
bool mayDefer =
|
|
|
|
!(aFlags & FindFamiliesFlags::eForceOtherFamilyNamesLoading);
|
|
|
|
if (IsAscii(key)) {
|
|
|
|
// If `key` is an ASCII name, only trigger loading if it includes a
|
|
|
|
// space, and the "base" name (up to the last space) exists as a known
|
|
|
|
// family, so that this might be a legacy styled-family name.
|
|
|
|
const char* data = key.BeginReading();
|
|
|
|
int32_t index = key.Length();
|
|
|
|
while (--index > 0) {
|
|
|
|
if (data[index] == ' ') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-12-26 20:12:17 +03:00
|
|
|
if (index <= 0 ||
|
|
|
|
!SharedFontList()->FindFamily(nsAutoCString(key.get(), index))) {
|
2019-10-23 13:40:16 +03:00
|
|
|
triggerLoading = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (triggerLoading) {
|
2020-12-26 20:12:17 +03:00
|
|
|
if (InitOtherFamilyNames(mayDefer)) {
|
|
|
|
family = SharedFontList()->FindFamily(key);
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
if (!family && !mOtherFamilyNamesInitialized &&
|
|
|
|
!(aFlags & FindFamiliesFlags::eNoAddToNamesMissedWhenSearching)) {
|
|
|
|
// localized family names load timed out, add name to list of
|
|
|
|
// names to check after localized names are loaded
|
|
|
|
if (!mOtherNamesMissed) {
|
2021-03-23 13:36:36 +03:00
|
|
|
mOtherNamesMissed = MakeUnique<nsTHashSet<nsCString>>(2);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2021-03-23 13:36:36 +03:00
|
|
|
mOtherNamesMissed->Insert(key);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2020-04-06 02:38:48 +03:00
|
|
|
}
|
2020-05-08 00:10:46 +03:00
|
|
|
// Check whether the family we found is actually allowed to be looked up,
|
|
|
|
// according to current font-visibility prefs.
|
2021-09-23 16:36:18 +03:00
|
|
|
if (family) {
|
|
|
|
bool visible = IsVisibleToCSS(*family, visibilityLevel);
|
|
|
|
if (visible || (allowHidden && family->IsHidden())) {
|
|
|
|
aOutput->AppendElement(FamilyAndGeneric(family, aGeneric));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (aPresContext) {
|
|
|
|
aPresContext->ReportBlockedFontFamily(*family);
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-28 03:40:06 +03:00
|
|
|
NS_ASSERTION(mFontFamilies.Count() != 0,
|
|
|
|
"system font list was not initialized correctly");
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2021-09-23 16:36:18 +03:00
|
|
|
auto isBlockedByVisibilityLevel = [=](gfxFontFamily* aFamily) -> bool {
|
|
|
|
bool visible = IsVisibleToCSS(*aFamily, visibilityLevel);
|
|
|
|
if (visible || (allowHidden && aFamily->IsHidden())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (aPresContext) {
|
|
|
|
aPresContext->ReportBlockedFontFamily(*aFamily);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
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);
|
2021-09-23 16:36:18 +03:00
|
|
|
if (familyEntry) {
|
|
|
|
if (isBlockedByVisibilityLevel(familyEntry)) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-04-02 15:36:24 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03: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
|
|
|
}
|
2021-09-23 16:36:18 +03:00
|
|
|
if (familyEntry) {
|
|
|
|
if (isBlockedByVisibilityLevel(familyEntry)) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-04-02 15:36:24 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03: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
|
2019-09-18 11:26:34 +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) {
|
2021-03-23 13:36:36 +03:00
|
|
|
mOtherNamesMissed = MakeUnique<nsTHashSet<nsCString>>(2);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2021-03-23 13:36:36 +03:00
|
|
|
mOtherNamesMissed->Insert(key);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2021-09-23 16:36:18 +03:00
|
|
|
if (familyEntry) {
|
|
|
|
if (isBlockedByVisibilityLevel(familyEntry)) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-04-02 15:36:24 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
familyEntry = CheckFamily(familyEntry);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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
|
2018-09-12 22:34:57 +03:00
|
|
|
const char* data = aFamily.BeginReading();
|
2017-08-01 13:25:35 +03:00
|
|
|
int32_t index = aFamily.Length();
|
|
|
|
while (--index > 0) {
|
|
|
|
if (data[index] == ' ') {
|
2018-11-30 13:46:48 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-08-01 13:25:35 +03:00
|
|
|
if (index > 0) {
|
|
|
|
gfxFontFamily* base =
|
2021-09-08 15:18:17 +03:00
|
|
|
FindUnsharedFamily(aPresContext, Substring(aFamily, 0, index),
|
2019-04-27 18:37:58 +03:00
|
|
|
FindFamiliesFlags::eNoSearchForLegacyFamilyNames);
|
2017-08-01 13:25:35 +03:00
|
|
|
// 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)) {
|
2016-04-12 09:06:22 +03:00
|
|
|
familyEntry = mOtherFamilyNames.GetWeak(key);
|
2017-08-01 13:25:35 +03:00
|
|
|
}
|
2021-09-23 16:36:18 +03:00
|
|
|
if (familyEntry) {
|
|
|
|
if (isBlockedByVisibilityLevel(familyEntry)) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-04-02 15:36:24 +03:00
|
|
|
}
|
2017-08-01 13:25:35 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2017-08-01 13:25:35 +03:00
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
if (familyEntry) {
|
2019-04-27 18:37:58 +03:00
|
|
|
aOutput->AppendElement(FamilyAndGeneric(familyEntry, aGeneric));
|
2016-04-12 09:06:22 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
fontlist::Family* gfxPlatformFontList::FindSharedFamily(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, const nsACString& aFamily,
|
|
|
|
FindFamiliesFlags aFlags, gfxFontStyle* aStyle, nsAtom* aLanguage,
|
|
|
|
gfxFloat aDevToCss) {
|
2019-04-27 18:37:58 +03:00
|
|
|
if (!SharedFontList()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
AutoTArray<FamilyAndGeneric, 1> families;
|
2021-09-08 15:18:17 +03:00
|
|
|
if (!FindAndAddFamilies(aPresContext, StyleGenericFontFamily::None, aFamily,
|
|
|
|
&families, aFlags, aStyle, aLanguage, aDevToCss) ||
|
2019-04-27 18:37:58 +03:00
|
|
|
!families[0].mFamily.mIsShared) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
fontlist::Family* family = families[0].mFamily.mShared;
|
|
|
|
if (!family->IsInitialized()) {
|
|
|
|
if (!InitializeFamily(family)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return family;
|
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2019-07-22 23:08:57 +03:00
|
|
|
class InitializeFamilyRunnable : public mozilla::Runnable {
|
|
|
|
public:
|
2020-07-23 00:12:11 +03:00
|
|
|
explicit InitializeFamilyRunnable(uint32_t aFamilyIndex, bool aLoadCmaps)
|
2019-07-22 23:08:57 +03:00
|
|
|
: Runnable("gfxPlatformFontList::InitializeFamilyRunnable"),
|
2020-07-23 00:12:11 +03:00
|
|
|
mIndex(aFamilyIndex),
|
|
|
|
mLoadCmaps(aLoadCmaps) {}
|
2019-07-22 23:08:57 +03:00
|
|
|
|
|
|
|
NS_IMETHOD Run() override {
|
|
|
|
auto list = gfxPlatformFontList::PlatformFontList()->SharedFontList();
|
|
|
|
if (!list) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
if (mIndex >= list->NumFamilies()) {
|
|
|
|
// Out of range? Maybe the list got reinitialized since this request
|
|
|
|
// was posted - just ignore it.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
dom::ContentChild::GetSingleton()->SendInitializeFamily(
|
2020-07-23 00:12:11 +03:00
|
|
|
list->GetGeneration(), mIndex, mLoadCmaps);
|
2019-07-22 23:08:57 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint32_t mIndex;
|
2020-07-23 00:12:11 +03:00
|
|
|
bool mLoadCmaps;
|
2019-07-22 23:08:57 +03:00
|
|
|
};
|
|
|
|
|
2020-07-23 00:12:11 +03:00
|
|
|
bool gfxPlatformFontList::InitializeFamily(fontlist::Family* aFamily,
|
|
|
|
bool aLoadCmaps) {
|
2019-04-27 18:37:58 +03:00
|
|
|
MOZ_ASSERT(SharedFontList());
|
|
|
|
auto list = SharedFontList();
|
|
|
|
if (!XRE_IsParentProcess()) {
|
2020-07-03 12:02:54 +03:00
|
|
|
auto* families = list->Families();
|
|
|
|
if (!families) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
uint32_t index = aFamily - families;
|
2020-08-01 02:57:22 +03:00
|
|
|
if (index >= list->NumFamilies()) {
|
|
|
|
return false;
|
|
|
|
}
|
2019-07-22 23:08:57 +03:00
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
dom::ContentChild::GetSingleton()->SendInitializeFamily(
|
2020-07-23 00:12:11 +03:00
|
|
|
list->GetGeneration(), index, aLoadCmaps);
|
2019-07-22 23:08:57 +03:00
|
|
|
} else {
|
2020-07-23 00:12:11 +03:00
|
|
|
NS_DispatchToMainThread(new InitializeFamilyRunnable(index, aLoadCmaps));
|
2019-07-22 23:08:57 +03:00
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
return aFamily->IsInitialized();
|
|
|
|
}
|
2020-07-23 00:12:11 +03:00
|
|
|
|
|
|
|
if (!aFamily->IsInitialized()) {
|
|
|
|
// The usual case: we're being asked to populate the face list.
|
|
|
|
AutoTArray<fontlist::Face::InitData, 16> faceList;
|
|
|
|
GetFacesInitDataForFamily(aFamily, faceList, aLoadCmaps);
|
|
|
|
aFamily->AddFaces(list, faceList);
|
|
|
|
} else {
|
|
|
|
// The family's face list was already initialized, but if aLoadCmaps is
|
|
|
|
// true we also want to eagerly load character maps. This is used when a
|
|
|
|
// child process is doing SearchAllFontsForChar, to have the parent load
|
|
|
|
// all the cmaps at once and reduce IPC traffic (and content-process file
|
|
|
|
// access overhead, which is crippling for DirectWrite on Windows).
|
|
|
|
if (aLoadCmaps) {
|
|
|
|
auto* faces = aFamily->Faces(list);
|
|
|
|
if (faces) {
|
|
|
|
for (size_t i = 0; i < aFamily->NumFaces(); i++) {
|
|
|
|
auto* face = static_cast<fontlist::Face*>(faces[i].ToPtr(list));
|
|
|
|
if (face && face->mCharacterMap.IsNull()) {
|
|
|
|
// We don't want to cache this font entry, as the parent will most
|
|
|
|
// likely never use it again; it's just to populate the charmap for
|
|
|
|
// the benefit of the child process.
|
|
|
|
RefPtr<gfxFontEntry> fe = CreateFontEntry(face, aFamily);
|
|
|
|
if (fe) {
|
|
|
|
fe->ReadCMAP();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aLoadCmaps && aFamily->IsInitialized()) {
|
|
|
|
aFamily->SetupFamilyCharMap(list);
|
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
return aFamily->IsInitialized();
|
|
|
|
}
|
2009-08-16 17:52:12 +04:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
gfxFontEntry* gfxPlatformFontList::FindFontForFamily(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, const nsACString& aFamily,
|
|
|
|
const gfxFontStyle* aStyle) {
|
2019-04-27 18:37:58 +03:00
|
|
|
nsAutoCString key;
|
|
|
|
GenerateFontListKey(aFamily, key);
|
2021-09-08 15:18:17 +03:00
|
|
|
FontFamily family = FindFamily(aPresContext, key);
|
2019-04-27 18:37:58 +03:00
|
|
|
if (family.IsNull()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (family.mIsShared) {
|
|
|
|
auto face = family.mShared->FindFaceForStyle(SharedFontList(), *aStyle);
|
|
|
|
if (!face) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return GetOrCreateFontEntry(face, family.mShared);
|
|
|
|
}
|
|
|
|
return family.mUnshared->FindFontForStyle(*aStyle);
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:29 +03:00
|
|
|
gfxFontEntry* gfxPlatformFontList::GetOrCreateFontEntry(
|
|
|
|
fontlist::Face* aFace, const fontlist::Family* aFamily) {
|
2021-02-22 15:07:46 +03:00
|
|
|
return mFontEntries
|
2021-02-26 12:11:45 +03:00
|
|
|
.LookupOrInsertWith(aFace,
|
|
|
|
[=] { return CreateFontEntry(aFace, aFamily); })
|
2021-02-22 15:07:46 +03:00
|
|
|
.get();
|
2019-04-27 18:37:29 +03:00
|
|
|
}
|
|
|
|
|
2020-05-05 13:56:14 +03:00
|
|
|
void gfxPlatformFontList::AddOtherFamilyName(
|
|
|
|
gfxFontFamily* aFamilyEntry, const nsCString& aOtherFamilyName) {
|
2018-09-12 22:34:57 +03:00
|
|
|
nsAutoCString key;
|
2009-08-16 17:52:12 +04:00
|
|
|
GenerateFontListKey(aOtherFamilyName, key);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2021-03-01 12:59:29 +03:00
|
|
|
mOtherFamilyNames.LookupOrInsertWith(key, [&] {
|
2011-01-21 19:44:33 +03:00
|
|
|
LOG_FONTLIST(
|
|
|
|
("(fontlist-otherfamily) canonical family: %s, "
|
|
|
|
"other family: %s\n",
|
2018-09-12 22:34:57 +03:00
|
|
|
aFamilyEntry->Name().get(), aOtherFamilyName.get()));
|
2018-11-15 19:11:45 +03:00
|
|
|
if (mBadUnderlineFamilyNames.ContainsSorted(key)) {
|
2010-01-28 09:56:16 +03:00
|
|
|
aFamilyEntry->SetBadUnderlineFamily();
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
2021-03-01 12:59:29 +03:00
|
|
|
return RefPtr{aFamilyEntry};
|
|
|
|
});
|
2009-08-16 17:52:12 +04:00
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
void gfxPlatformFontList::AddFullname(gfxFontEntry* aFontEntry,
|
|
|
|
const nsCString& aFullname) {
|
2021-03-01 12:59:29 +03:00
|
|
|
mExtraNames->mFullnames.LookupOrInsertWith(aFullname, [&] {
|
2011-01-21 19:44:33 +03:00
|
|
|
LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n",
|
2018-09-12 22:34:57 +03:00
|
|
|
aFontEntry->Name().get(), aFullname.get()));
|
2021-03-01 12:59:29 +03:00
|
|
|
return RefPtr{aFontEntry};
|
|
|
|
});
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
void gfxPlatformFontList::AddPostscriptName(gfxFontEntry* aFontEntry,
|
|
|
|
const nsCString& aPostscriptName) {
|
2021-03-01 12:59:29 +03:00
|
|
|
mExtraNames->mPostscriptNames.LookupOrInsertWith(aPostscriptName, [&] {
|
2011-01-21 19:44:33 +03:00
|
|
|
LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n",
|
2018-09-12 22:34:57 +03:00
|
|
|
aFontEntry->Name().get(), aPostscriptName.get()));
|
2021-03-01 12:59:29 +03:00
|
|
|
return RefPtr{aFontEntry};
|
|
|
|
});
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
bool gfxPlatformFontList::GetStandardFamilyName(const nsCString& aFontName,
|
|
|
|
nsACString& aFamilyName) {
|
2021-09-08 15:18:17 +03:00
|
|
|
FontFamily family = FindFamily(nullptr, aFontName);
|
2019-04-27 18:37:58 +03:00
|
|
|
if (family.IsNull()) {
|
2014-06-06 10:09:23 +04:00
|
|
|
return false;
|
|
|
|
}
|
2021-09-08 15:18:17 +03:00
|
|
|
return GetLocalizedFamilyName(family, aFamilyName);
|
2020-10-14 15:49:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool gfxPlatformFontList::GetLocalizedFamilyName(const FontFamily& aFamily,
|
|
|
|
nsACString& aFamilyName) {
|
|
|
|
if (aFamily.mIsShared) {
|
|
|
|
if (aFamily.mShared) {
|
|
|
|
aFamilyName = SharedFontList()->LocalizedFamilyName(aFamily.mShared);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (aFamily.mUnshared) {
|
|
|
|
aFamily.mUnshared->LocalizedName(aFamilyName);
|
2019-04-27 18:37:58 +03:00
|
|
|
return true;
|
|
|
|
}
|
2020-10-14 15:49:37 +03:00
|
|
|
return false; // leaving the aFamilyName outparam untouched
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
FamilyAndGeneric gfxPlatformFontList::GetDefaultFontFamily(
|
2017-04-03 15:00:14 +03:00
|
|
|
const nsACString& aLangGroup, const nsACString& aGenericFamily) {
|
|
|
|
if (NS_WARN_IF(aLangGroup.IsEmpty()) ||
|
|
|
|
NS_WARN_IF(aGenericFamily.IsEmpty())) {
|
2019-04-27 18:37:58 +03:00
|
|
|
return FamilyAndGeneric();
|
2017-04-03 15:00:14 +03:00
|
|
|
}
|
|
|
|
|
2018-09-18 11:34:24 +03:00
|
|
|
AutoTArray<nsCString, 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
|
|
|
|
2018-09-18 11:34:24 +03:00
|
|
|
for (const nsCString& name : names) {
|
2021-09-08 15:18:17 +03:00
|
|
|
FontFamily family = FindFamily(nullptr, name);
|
2019-04-27 18:37:58 +03:00
|
|
|
if (!family.IsNull()) {
|
|
|
|
return FamilyAndGeneric(family);
|
2017-04-03 15:00:14 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
|
|
|
|
return FamilyAndGeneric();
|
|
|
|
}
|
|
|
|
|
|
|
|
ShmemCharMapHashEntry::ShmemCharMapHashEntry(const gfxSparseBitSet* aCharMap)
|
|
|
|
: mList(gfxPlatformFontList::PlatformFontList()->SharedFontList()),
|
|
|
|
mCharMap(),
|
|
|
|
mHash(aCharMap->GetChecksum()) {
|
|
|
|
size_t len = SharedBitSet::RequiredSize(*aCharMap);
|
|
|
|
mCharMap = mList->Alloc(len);
|
|
|
|
SharedBitSet::Create(mCharMap.ToPtr(mList), len, *aCharMap);
|
|
|
|
}
|
|
|
|
|
|
|
|
fontlist::Pointer gfxPlatformFontList::GetShmemCharMap(
|
|
|
|
const gfxSparseBitSet* aCmap) {
|
|
|
|
auto* entry = mShmemCharMaps.GetEntry(aCmap);
|
|
|
|
if (!entry) {
|
|
|
|
entry = mShmemCharMaps.PutEntry(aCmap);
|
|
|
|
}
|
|
|
|
return entry->GetCharMap();
|
2017-04-03 15:00:14 +03:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-27 14:11:51 +03:00
|
|
|
static void GetSystemUIFontFamilies([[maybe_unused]] nsAtom* aLangGroup,
|
|
|
|
nsTArray<nsCString>& aFamilies) {
|
|
|
|
// TODO: On macOS, use CTCreateUIFontForLanguage or such thing (though the
|
|
|
|
// code below ends up using [NSFont systemFontOfSize: 0.0].
|
|
|
|
nsFont systemFont;
|
|
|
|
gfxFontStyle fontStyle;
|
|
|
|
nsAutoString systemFontName;
|
|
|
|
if (!LookAndFeel::GetFont(StyleSystemFont::Menu, systemFontName, fontStyle)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
systemFontName.Trim("\"'");
|
|
|
|
CopyUTF16toUTF8(systemFontName, *aFamilies.AppendElement());
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
void gfxPlatformFontList::ResolveGenericFontNames(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, StyleGenericFontFamily aGenericType,
|
|
|
|
eFontPrefLang aPrefLang, PrefFontList* aGenericFamilies) {
|
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;
|
|
|
|
}
|
|
|
|
|
2018-09-18 11:34:24 +03:00
|
|
|
AutoTArray<nsCString, 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);
|
2021-07-27 14:11:51 +03:00
|
|
|
MOZ_ASSERT(langGroup, "null lang group for pref lang");
|
|
|
|
|
|
|
|
if (aGenericType == StyleGenericFontFamily::SystemUi) {
|
|
|
|
GetSystemUIFontFamilies(langGroup, genericFamilies);
|
|
|
|
}
|
2015-09-29 04:51:29 +03:00
|
|
|
|
2021-09-08 15:18:17 +03:00
|
|
|
GetFontFamiliesFromGenericFamilies(
|
|
|
|
aPresContext, aGenericType, genericFamilies, langGroup, aGenericFamilies);
|
2017-11-12 10:24:58 +03:00
|
|
|
|
|
|
|
#if 0 // dump out generic mappings
|
2019-04-27 18:37:58 +03:00
|
|
|
printf("%s ===> ", NamePref(generic, langGroupStr).get());
|
2017-11-12 10:24:58 +03:00
|
|
|
for (uint32_t k = 0; k < aGenericFamilies->Length(); k++) {
|
|
|
|
if (k > 0) printf(", ");
|
2019-04-27 18:37:58 +03:00
|
|
|
printf("%s", (*aGenericFamilies)[k].mIsShared
|
|
|
|
? (*aGenericFamilies)[k].mShared->DisplayName().AsString(SharedFontList()).get()
|
|
|
|
: (*aGenericFamilies)[k].mUnshared->Name().get());
|
2017-11-12 10:24:58 +03:00
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void gfxPlatformFontList::ResolveEmojiFontNames(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, PrefFontList* aGenericFamilies) {
|
2018-09-18 11:34:24 +03:00
|
|
|
// emoji preference has no lang name
|
2018-05-25 16:07:57 +03:00
|
|
|
AutoTArray<nsCString, 4> genericFamilies;
|
2015-09-29 04:51:28 +03:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
nsAutoCString prefFontListName("font.name-list.emoji");
|
2015-09-29 04:51:29 +03:00
|
|
|
gfxFontUtils::AppendPrefsFontList(prefFontListName.get(), genericFamilies);
|
|
|
|
|
2021-09-08 15:18:17 +03:00
|
|
|
GetFontFamiliesFromGenericFamilies(
|
|
|
|
aPresContext, StyleGenericFontFamily::MozEmoji, genericFamilies, nullptr,
|
|
|
|
aGenericFamilies);
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
void gfxPlatformFontList::GetFontFamiliesFromGenericFamilies(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, StyleGenericFontFamily aGenericType,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsTArray<nsCString>& aGenericNameFamilies, nsAtom* aLangGroup,
|
2019-04-01 17:33:16 +03:00
|
|
|
PrefFontList* aGenericFamilies) {
|
2015-09-29 04:51:29 +03:00
|
|
|
// lookup and add platform fonts uniquely
|
2018-05-25 16:07:57 +03:00
|
|
|
for (const nsCString& genericFamily : aGenericNameFamilies) {
|
|
|
|
AutoTArray<FamilyAndGeneric, 10> families;
|
2021-09-08 15:18:17 +03:00
|
|
|
FindAndAddFamilies(aPresContext, aGenericType, genericFamily, &families,
|
2020-11-13 16:15:39 +03:00
|
|
|
FindFamiliesFlags(0), nullptr, aLangGroup);
|
2015-09-29 04:51:29 +03:00
|
|
|
for (const FamilyAndGeneric& f : families) {
|
2018-05-25 16:07:57 +03:00
|
|
|
if (!aGenericFamilies->Contains(f.mFamily)) {
|
|
|
|
aGenericFamilies->AppendElement(f.mFamily);
|
|
|
|
}
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
|
2019-04-01 17:33:16 +03:00
|
|
|
gfxPlatformFontList::PrefFontList* gfxPlatformFontList::GetPrefFontsLangGroup(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, StyleGenericFontFamily aGenericType,
|
|
|
|
eFontPrefLang aPrefLang) {
|
2021-02-01 13:47:40 +03:00
|
|
|
if (aGenericType == StyleGenericFontFamily::MozEmoji ||
|
|
|
|
aPrefLang == eFontPrefLang_Emoji) {
|
2015-09-29 04:51:28 +03:00
|
|
|
// Emoji font has no lang
|
|
|
|
PrefFontList* prefFonts = mEmojiPrefFont.get();
|
|
|
|
if (MOZ_UNLIKELY(!prefFonts)) {
|
|
|
|
prefFonts = new PrefFontList;
|
2021-09-08 15:18:17 +03:00
|
|
|
ResolveEmojiFontNames(aPresContext, prefFonts);
|
2015-09-29 04:51:28 +03:00
|
|
|
mEmojiPrefFont.reset(prefFonts);
|
|
|
|
}
|
|
|
|
return prefFonts;
|
|
|
|
}
|
|
|
|
|
2019-04-02 00:47:59 +03:00
|
|
|
auto index = static_cast<size_t>(aGenericType);
|
|
|
|
PrefFontList* prefFonts = mLangGroupPrefFonts[aPrefLang][index].get();
|
2015-09-29 04:51:28 +03:00
|
|
|
if (MOZ_UNLIKELY(!prefFonts)) {
|
2017-11-12 10:24:58 +03:00
|
|
|
prefFonts = new PrefFontList;
|
2021-09-08 15:18:17 +03:00
|
|
|
ResolveGenericFontNames(aPresContext, aGenericType, aPrefLang, prefFonts);
|
2019-04-02 00:47:59 +03:00
|
|
|
mLangGroupPrefFonts[aPrefLang][index].reset(prefFonts);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
return prefFonts;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gfxPlatformFontList::AddGenericFonts(
|
2021-09-08 15:18:17 +03:00
|
|
|
nsPresContext* aPresContext, StyleGenericFontFamily aGenericType,
|
|
|
|
nsAtom* aLanguage, nsTArray<FamilyAndGeneric>& aFamilyList) {
|
2015-09-29 04:51:28 +03:00
|
|
|
// map lang ==> langGroup
|
|
|
|
nsAtom* langGroup = GetLangGroup(aLanguage);
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
// langGroup ==> prefLang
|
2015-09-29 04:51:28 +03:00
|
|
|
eFontPrefLang prefLang = GetFontPrefLangFor(langGroup);
|
|
|
|
|
|
|
|
// lookup pref fonts
|
2021-09-08 15:18:17 +03:00
|
|
|
PrefFontList* prefFonts =
|
|
|
|
GetPrefFontsLangGroup(aPresContext, aGenericType, prefLang);
|
2015-09-29 04:51:28 +03:00
|
|
|
|
|
|
|
if (!prefFonts->IsEmpty()) {
|
|
|
|
aFamilyList.SetCapacity(aFamilyList.Length() + prefFonts->Length());
|
|
|
|
for (auto& f : *prefFonts) {
|
2019-04-01 17:33:34 +03:00
|
|
|
aFamilyList.AppendElement(FamilyAndGeneric(f, aGenericType));
|
2015-09-29 04:51:28 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static nsAtom* PrefLangToLangGroups(uint32_t aIndex) {
|
|
|
|
// static array here avoids static constructor
|
|
|
|
static nsAtom* gPrefLangToLangGroups[] = {
|
|
|
|
#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;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); ++i) {
|
|
|
|
if (!PL_strcasecmp(gPrefLangNames[i], aLang)) {
|
|
|
|
return eFontPrefLang(i);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Others;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
eFontPrefLang gfxPlatformFontList::GetFontPrefLangFor(nsAtom* aLang) {
|
|
|
|
if (!aLang) return eFontPrefLang_Others;
|
|
|
|
nsAutoCString lang;
|
|
|
|
aLang->ToUTF8String(lang);
|
|
|
|
return GetFontPrefLangFor(lang.get());
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
nsAtom* 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");
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-07-31 07:28:48 +03:00
|
|
|
return PrefLangToLangGroups(uint32_t(aLang));
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2017-07-31 07:28:48 +03:00
|
|
|
const char* gfxPlatformFontList::GetPrefLangName(eFontPrefLang aLang) {
|
|
|
|
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
|
|
|
|
return gPrefLangNames[uint32_t(aLang)];
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2017-07-31 07:28:48 +03:00
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2019-04-11 00:43:22 +03:00
|
|
|
eFontPrefLang gfxPlatformFontList::GetFontPrefLangFor(uint32_t aCh) {
|
|
|
|
switch (ublock_getCode(aCh)) {
|
|
|
|
case UBLOCK_BASIC_LATIN:
|
|
|
|
case UBLOCK_LATIN_1_SUPPLEMENT:
|
|
|
|
case UBLOCK_LATIN_EXTENDED_A:
|
|
|
|
case UBLOCK_LATIN_EXTENDED_B:
|
|
|
|
case UBLOCK_IPA_EXTENSIONS:
|
|
|
|
case UBLOCK_SPACING_MODIFIER_LETTERS:
|
|
|
|
case UBLOCK_LATIN_EXTENDED_ADDITIONAL:
|
|
|
|
case UBLOCK_LATIN_EXTENDED_C:
|
|
|
|
case UBLOCK_LATIN_EXTENDED_D:
|
|
|
|
case UBLOCK_LATIN_EXTENDED_E:
|
|
|
|
case UBLOCK_PHONETIC_EXTENSIONS:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Western;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_GREEK:
|
|
|
|
case UBLOCK_GREEK_EXTENDED:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Greek;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_CYRILLIC:
|
|
|
|
case UBLOCK_CYRILLIC_SUPPLEMENT:
|
|
|
|
case UBLOCK_CYRILLIC_EXTENDED_A:
|
|
|
|
case UBLOCK_CYRILLIC_EXTENDED_B:
|
|
|
|
case UBLOCK_CYRILLIC_EXTENDED_C:
|
|
|
|
return eFontPrefLang_Cyrillic;
|
|
|
|
case UBLOCK_ARMENIAN:
|
|
|
|
return eFontPrefLang_Armenian;
|
|
|
|
case UBLOCK_HEBREW:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Hebrew;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_ARABIC:
|
|
|
|
case UBLOCK_ARABIC_PRESENTATION_FORMS_A:
|
|
|
|
case UBLOCK_ARABIC_PRESENTATION_FORMS_B:
|
|
|
|
case UBLOCK_ARABIC_SUPPLEMENT:
|
|
|
|
case UBLOCK_ARABIC_EXTENDED_A:
|
|
|
|
case UBLOCK_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Arabic;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_DEVANAGARI:
|
|
|
|
case UBLOCK_DEVANAGARI_EXTENDED:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Devanagari;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_BENGALI:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Bengali;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_GURMUKHI:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Gurmukhi;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_GUJARATI:
|
|
|
|
return eFontPrefLang_Gujarati;
|
|
|
|
case UBLOCK_ORIYA:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Oriya;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_TAMIL:
|
|
|
|
return eFontPrefLang_Tamil;
|
|
|
|
case UBLOCK_TELUGU:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Telugu;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_KANNADA:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Kannada;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_MALAYALAM:
|
|
|
|
return eFontPrefLang_Malayalam;
|
|
|
|
case UBLOCK_SINHALA:
|
|
|
|
case UBLOCK_SINHALA_ARCHAIC_NUMBERS:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Sinhala;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_THAI:
|
|
|
|
return eFontPrefLang_Thai;
|
|
|
|
case UBLOCK_TIBETAN:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_Tibetan;
|
2019-04-11 00:43:22 +03:00
|
|
|
case UBLOCK_GEORGIAN:
|
|
|
|
case UBLOCK_GEORGIAN_SUPPLEMENT:
|
|
|
|
case UBLOCK_GEORGIAN_EXTENDED:
|
|
|
|
return eFontPrefLang_Georgian;
|
|
|
|
case UBLOCK_HANGUL_JAMO:
|
|
|
|
case UBLOCK_HANGUL_COMPATIBILITY_JAMO:
|
|
|
|
case UBLOCK_HANGUL_SYLLABLES:
|
|
|
|
case UBLOCK_HANGUL_JAMO_EXTENDED_A:
|
|
|
|
case UBLOCK_HANGUL_JAMO_EXTENDED_B:
|
|
|
|
return eFontPrefLang_Korean;
|
|
|
|
case UBLOCK_ETHIOPIC:
|
|
|
|
case UBLOCK_ETHIOPIC_EXTENDED:
|
|
|
|
case UBLOCK_ETHIOPIC_SUPPLEMENT:
|
|
|
|
case UBLOCK_ETHIOPIC_EXTENDED_A:
|
|
|
|
return eFontPrefLang_Ethiopic;
|
|
|
|
case UBLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS:
|
|
|
|
case UBLOCK_UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED:
|
|
|
|
return eFontPrefLang_Canadian;
|
|
|
|
case UBLOCK_KHMER:
|
|
|
|
case UBLOCK_KHMER_SYMBOLS:
|
|
|
|
return eFontPrefLang_Khmer;
|
|
|
|
case UBLOCK_CJK_RADICALS_SUPPLEMENT:
|
|
|
|
case UBLOCK_KANGXI_RADICALS:
|
|
|
|
case UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS:
|
|
|
|
case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION:
|
|
|
|
case UBLOCK_HIRAGANA:
|
|
|
|
case UBLOCK_KATAKANA:
|
|
|
|
case UBLOCK_BOPOMOFO:
|
|
|
|
case UBLOCK_KANBUN:
|
|
|
|
case UBLOCK_BOPOMOFO_EXTENDED:
|
|
|
|
case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS:
|
|
|
|
case UBLOCK_CJK_COMPATIBILITY:
|
|
|
|
case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A:
|
|
|
|
case UBLOCK_CJK_UNIFIED_IDEOGRAPHS:
|
|
|
|
case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS:
|
|
|
|
case UBLOCK_CJK_COMPATIBILITY_FORMS:
|
|
|
|
case UBLOCK_SMALL_FORM_VARIANTS:
|
|
|
|
case UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS:
|
|
|
|
case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B:
|
|
|
|
case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT:
|
|
|
|
case UBLOCK_KATAKANA_PHONETIC_EXTENSIONS:
|
|
|
|
case UBLOCK_CJK_STROKES:
|
|
|
|
case UBLOCK_VERTICAL_FORMS:
|
|
|
|
case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C:
|
|
|
|
case UBLOCK_KANA_SUPPLEMENT:
|
|
|
|
case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D:
|
|
|
|
case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E:
|
|
|
|
case UBLOCK_IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION:
|
|
|
|
case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F:
|
|
|
|
case UBLOCK_KANA_EXTENDED_A:
|
2015-09-29 04:51:28 +03:00
|
|
|
return eFontPrefLang_CJKSet;
|
2020-08-16 21:25:07 +03:00
|
|
|
case UBLOCK_MATHEMATICAL_OPERATORS:
|
|
|
|
case UBLOCK_MATHEMATICAL_ALPHANUMERIC_SYMBOLS:
|
|
|
|
case UBLOCK_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A:
|
|
|
|
case UBLOCK_MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B:
|
|
|
|
case UBLOCK_SUPPLEMENTAL_MATHEMATICAL_OPERATORS:
|
|
|
|
return eFontPrefLang_Mathematics;
|
2015-09-29 04:51:28 +03:00
|
|
|
default:
|
|
|
|
return eFontPrefLang_Others;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
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;
|
2018-11-30 13:46:48 +03:00
|
|
|
default:
|
2015-09-29 04:51:28 +03:00
|
|
|
return false;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang_Others);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
// if not set up, set up the default CJK order, based on accept lang
|
|
|
|
// settings and locale
|
2015-09-29 04:51:28 +03:00
|
|
|
if (mCJKPrefLangs.Length() == 0) {
|
|
|
|
// temp array
|
2017-03-22 10:27:14 +03:00
|
|
|
eFontPrefLang tempPrefLangs[kMaxLenPrefLangList];
|
2015-09-29 04:51:28 +03:00
|
|
|
uint32_t tempLen = 0;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
// Add the CJK pref fonts from accept languages, the order should be same
|
2019-11-20 02:37:57 +03:00
|
|
|
// order. We use gfxFontUtils::GetPrefsFontList to read the list even
|
|
|
|
// though it's not actually a list of fonts but of lang codes; the format
|
|
|
|
// is the same.
|
|
|
|
AutoTArray<nsCString, 5> list;
|
|
|
|
gfxFontUtils::GetPrefsFontList("intl.accept_languages", list, true);
|
|
|
|
for (const auto& lang : list) {
|
|
|
|
eFontPrefLang fpl = 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;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
2017-03-22 10:27:14 +03:00
|
|
|
|
2017-11-21 14:01:46 +03:00
|
|
|
// Try using app's locale
|
|
|
|
nsAutoCString localeStr;
|
2020-01-17 22:29:09 +03:00
|
|
|
LocaleService::GetInstance()->GetAppLocaleAsBCP47(localeStr);
|
2015-09-29 04:51:28 +03:00
|
|
|
|
2018-11-30 13:46:48 +03:00
|
|
|
{
|
2021-11-04 19:36:03 +03:00
|
|
|
Locale locale;
|
|
|
|
if (LocaleParser::tryParse(localeStr, locale).isOk() &&
|
|
|
|
locale.canonicalize().isOk()) {
|
|
|
|
if (locale.language().equalTo("ja")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
|
|
|
} else if (locale.language().equalTo("zh")) {
|
|
|
|
if (locale.region().equalTo("CN")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
|
|
|
} else if (locale.region().equalTo("TW")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
|
|
|
} else if (locale.region().equalTo("HK")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
|
|
|
}
|
|
|
|
} else if (locale.language().equalTo("ko")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
2015-09-29 04:51:28 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-09-29 04:51:28 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
// Then add the known CJK prefs in order of system preferred locales
|
|
|
|
AutoTArray<nsCString, 5> prefLocales;
|
|
|
|
prefLocales.AppendElement("ja"_ns);
|
|
|
|
prefLocales.AppendElement("zh-CN"_ns);
|
|
|
|
prefLocales.AppendElement("zh-TW"_ns);
|
|
|
|
prefLocales.AppendElement("zh-HK"_ns);
|
|
|
|
prefLocales.AppendElement("ko"_ns);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-11-21 14:01:46 +03:00
|
|
|
AutoTArray<nsCString, 16> sysLocales;
|
2015-09-29 04:51:28 +03:00
|
|
|
AutoTArray<nsCString, 16> negLocales;
|
|
|
|
if (NS_SUCCEEDED(
|
|
|
|
OSPreferences::GetInstance()->GetSystemLocales(sysLocales))) {
|
2015-09-29 04:51:29 +03:00
|
|
|
LocaleService::GetInstance()->NegotiateLanguages(
|
|
|
|
sysLocales, prefLocales, ""_ns,
|
|
|
|
LocaleService::kLangNegStrategyFiltering, negLocales);
|
|
|
|
for (const auto& localeStr : negLocales) {
|
2021-11-04 19:36:03 +03:00
|
|
|
Locale locale;
|
|
|
|
if (LocaleParser::tryParse(localeStr, locale).isOk() &&
|
|
|
|
locale.canonicalize().isOk()) {
|
|
|
|
if (locale.language().equalTo("ja")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
|
|
|
} else if (locale.language().equalTo("zh")) {
|
|
|
|
if (locale.region().equalTo("CN")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
|
|
|
} else if (locale.region().equalTo("TW")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
|
|
|
} else if (locale.region().equalTo("HK")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
|
|
|
}
|
|
|
|
} else if (locale.language().equalTo("ko")) {
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2019-11-20 02:18:30 +03:00
|
|
|
// Last resort... set up CJK font prefs in the order listed by the user-
|
|
|
|
// configurable ordering pref.
|
|
|
|
gfxFontUtils::GetPrefsFontList(kCJKFallbackOrderPref, list);
|
|
|
|
for (const auto& item : list) {
|
|
|
|
eFontPrefLang fpl = GetFontPrefLangFor(item.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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Truly-last resort... try Chinese font prefs before Japanese because
|
|
|
|
// they tend to have more complete character coverage, and therefore less
|
|
|
|
// risk of "ransom-note" effects.
|
|
|
|
// (If the kCJKFallbackOrderPref was fully populated, as it is by default,
|
|
|
|
// this will do nothing as all these values are already present.)
|
2017-03-22 10:27:14 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
2019-10-31 11:50:12 +03:00
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
|
|
|
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
// copy into the cached array
|
2019-11-20 02:37:57 +03:00
|
|
|
for (const auto lang : Span<eFontPrefLang>(tempPrefLangs, tempLen)) {
|
|
|
|
mCJKPrefLangs.AppendElement(lang);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
// append in cached CJK langs
|
2019-11-20 02:37:57 +03:00
|
|
|
for (const auto lang : mCJKPrefLangs) {
|
|
|
|
AppendPrefLang(aPrefLangs, aLen, eFontPrefLang(lang));
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:28 +03:00
|
|
|
void gfxPlatformFontList::AppendPrefLang(eFontPrefLang aPrefLangs[],
|
|
|
|
uint32_t& aLen,
|
2017-11-12 10:24:58 +03:00
|
|
|
eFontPrefLang aAddLang) {
|
2019-11-20 02:37:57 +03:00
|
|
|
if (aLen >= kMaxLenPrefLangList) {
|
|
|
|
return;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2019-11-20 02:37:57 +03:00
|
|
|
// If the lang is already present, just ignore the addition.
|
|
|
|
for (const auto lang : Span<eFontPrefLang>(aPrefLangs, aLen)) {
|
|
|
|
if (lang == aAddLang) {
|
|
|
|
return;
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2019-11-20 02:37:57 +03:00
|
|
|
|
|
|
|
aPrefLangs[aLen++] = aAddLang;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
StyleGenericFontFamily gfxPlatformFontList::GetDefaultGeneric(
|
2017-11-12 10:24:58 +03:00
|
|
|
eFontPrefLang aLang) {
|
|
|
|
if (aLang == eFontPrefLang_Emoji) {
|
2019-04-02 00:47:59 +03:00
|
|
|
return StyleGenericFontFamily::MozEmoji;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
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));
|
2015-09-29 04:51:28 +03:00
|
|
|
for (uint32_t i = 0; i < ArrayLength(gPrefLangNames); i++) {
|
2015-09-29 04:51:29 +03:00
|
|
|
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")) {
|
2019-04-02 00:47:59 +03:00
|
|
|
mDefaultGenericsLangGroup[i] = StyleGenericFontFamily::SansSerif;
|
2018-11-30 13:46:48 +03:00
|
|
|
} else {
|
2019-04-02 00:47:59 +03:00
|
|
|
mDefaultGenericsLangGroup[i] = StyleGenericFontFamily::Serif;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-29 04:51:29 +03:00
|
|
|
if (uint32_t(aLang) < ArrayLength(gPrefLangNames)) {
|
|
|
|
return mDefaultGenericsLangGroup[uint32_t(aLang)];
|
|
|
|
}
|
2019-04-02 00:47:59 +03:00
|
|
|
return StyleGenericFontFamily::Serif;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:17 +03:00
|
|
|
FontFamily gfxPlatformFontList::GetDefaultFont(nsPresContext* aPresContext,
|
|
|
|
const gfxFontStyle* aStyle) {
|
|
|
|
FontFamily family = GetDefaultFontForPlatform(aPresContext, aStyle);
|
2019-04-27 18:37:58 +03:00
|
|
|
if (!family.IsNull()) {
|
2016-08-23 03:06:07 +03:00
|
|
|
return family;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2016-08-23 03:06:07 +03:00
|
|
|
// Something has gone wrong and we were unable to retrieve a default font
|
|
|
|
// from the platform. (Likely the whitelist has blocked all potential
|
2019-04-27 18:37:58 +03:00
|
|
|
// default fonts.) As a last resort, we return the first font in our list.
|
|
|
|
if (SharedFontList()) {
|
|
|
|
MOZ_RELEASE_ASSERT(SharedFontList()->NumFamilies() > 0);
|
|
|
|
return FontFamily(SharedFontList()->Families());
|
|
|
|
}
|
|
|
|
MOZ_RELEASE_ASSERT(mFontFamilies.Count() > 0);
|
2021-03-12 19:14:58 +03:00
|
|
|
return FontFamily(mFontFamilies.ConstIter().Data());
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
void gfxPlatformFontList::GetFontFamilyNames(
|
|
|
|
nsTArray<nsCString>& aFontFamilyNames) {
|
2019-04-27 18:37:58 +03:00
|
|
|
if (SharedFontList()) {
|
|
|
|
fontlist::FontList* list = SharedFontList();
|
|
|
|
const fontlist::Family* families = list->Families();
|
2020-07-03 12:02:54 +03:00
|
|
|
if (families) {
|
|
|
|
for (uint32_t i = 0, n = list->NumFamilies(); i < n; i++) {
|
|
|
|
const fontlist::Family& family = families[i];
|
|
|
|
if (!family.IsHidden()) {
|
|
|
|
aFontFamilyNames.AppendElement(family.DisplayName().AsString(list));
|
|
|
|
}
|
2020-04-09 12:30:40 +03:00
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
} else {
|
2021-03-24 20:56:49 +03:00
|
|
|
for (const RefPtr<gfxFontFamily>& family : mFontFamilies.Values()) {
|
2020-04-09 12:30:40 +03:00
|
|
|
if (!family->IsHidden()) {
|
|
|
|
aFontFamilyNames.AppendElement(family->Name());
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03: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);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-11-16 02:48:40 +03:00
|
|
|
if (!langGroup) {
|
|
|
|
langGroup = nsGkAtoms::Unicode;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-11-16 02:48:40 +03:00
|
|
|
return langGroup;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2015-11-16 02:48:40 +03:00
|
|
|
/* static */ const char* gfxPlatformFontList::GetGenericName(
|
2019-04-02 00:47:59 +03:00
|
|
|
StyleGenericFontFamily aGenericType) {
|
2015-11-16 02:48:40 +03:00
|
|
|
// type should be standard generic type at this point
|
|
|
|
// map generic type to string
|
|
|
|
switch (aGenericType) {
|
2019-04-02 00:47:59 +03:00
|
|
|
case StyleGenericFontFamily::Serif:
|
2020-10-30 13:10:06 +03:00
|
|
|
return "serif";
|
2019-04-02 00:47:59 +03:00
|
|
|
case StyleGenericFontFamily::SansSerif:
|
2020-10-30 13:10:06 +03:00
|
|
|
return "sans-serif";
|
2019-04-02 00:47:59 +03:00
|
|
|
case StyleGenericFontFamily::Monospace:
|
2020-10-30 13:10:06 +03:00
|
|
|
return "monospace";
|
2019-04-02 00:47:59 +03:00
|
|
|
case StyleGenericFontFamily::Cursive:
|
2020-10-30 13:10:06 +03:00
|
|
|
return "cursive";
|
2019-04-02 00:47:59 +03:00
|
|
|
case StyleGenericFontFamily::Fantasy:
|
2020-10-30 13:10:06 +03:00
|
|
|
return "fantasy";
|
2021-07-27 14:11:51 +03:00
|
|
|
case StyleGenericFontFamily::SystemUi:
|
|
|
|
return "system-ui";
|
2020-10-30 13:10:06 +03:00
|
|
|
case StyleGenericFontFamily::MozEmoji:
|
|
|
|
return "-moz-emoji";
|
|
|
|
case StyleGenericFontFamily::None:
|
|
|
|
break;
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
2020-10-30 13:10:06 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE("Unknown generic");
|
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
void 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));
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2013-12-06 07:47:46 +04:00
|
|
|
#define FONT_LOADER_MAX_TIMESLICE \
|
2020-10-03 19:03:54 +03:00
|
|
|
20 // max time for one pass through RunLoader = 20ms
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
bool gfxPlatformFontList::LoadFontInfo() {
|
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;
|
2019-04-27 18:37:58 +03:00
|
|
|
fontlist::FontList* list = SharedFontList();
|
|
|
|
bool loadCmaps =
|
2019-05-24 14:26:01 +03:00
|
|
|
!list && (!UsesSystemFallback() ||
|
|
|
|
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback());
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2009-08-16 17:52:12 +04:00
|
|
|
// for each font family, load in various font info
|
|
|
|
for (i = mStartIndex; i < endIndex; i++) {
|
2018-09-12 22:34:57 +03:00
|
|
|
nsAutoCString key;
|
2014-01-29 11:39:01 +04:00
|
|
|
GenerateFontListKey(mFontInfo->mFontFamiliesToLoad[i], key);
|
2016-08-23 03:06:07 +03:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
if (list) {
|
|
|
|
fontlist::Family* family = list->FindFamily(key);
|
|
|
|
if (!family) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ReadFaceNamesForFamily(family, NeedFullnamePostscriptNames());
|
|
|
|
} else {
|
|
|
|
// lookup in canonical (i.e. English) family name list
|
|
|
|
gfxFontFamily* familyEntry = mFontFamilies.GetWeak(key);
|
|
|
|
if (!familyEntry) {
|
|
|
|
continue;
|
|
|
|
}
|
2016-08-23 03:06:07 +03:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
// read in face names
|
|
|
|
familyEntry->ReadFaceNames(this, NeedFullnamePostscriptNames(),
|
|
|
|
mFontInfo);
|
2014-01-29 11:39:01 +04:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
// load the cmaps if needed
|
|
|
|
if (loadCmaps) {
|
|
|
|
familyEntry->ReadAllCMAPs(mFontInfo);
|
|
|
|
}
|
2015-11-16 02:48:40 +03:00
|
|
|
}
|
|
|
|
|
2020-10-03 19:03:54 +03:00
|
|
|
// Limit the time spent reading fonts in one pass, unless the font-loader
|
|
|
|
// delay was set to zero, in which case we run to completion even if it
|
|
|
|
// causes some jank.
|
|
|
|
if (StaticPrefs::gfx_font_loader_delay_AtStartup() > 0) {
|
|
|
|
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
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
void 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) {
|
2021-03-23 13:36:36 +03:00
|
|
|
rebuilt = std::any_of(mFaceNamesMissed->cbegin(), mFaceNamesMissed->cend(),
|
|
|
|
[&](const auto& key) { return FindFaceName(key); });
|
|
|
|
if (rebuilt) {
|
|
|
|
RebuildLocalFonts();
|
2014-04-23 09:20:20 +04:00
|
|
|
}
|
2021-03-23 13:36:36 +03:00
|
|
|
|
2014-04-23 09:20:20 +04:00
|
|
|
mFaceNamesMissed = nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2014-01-29 11:39:01 +04:00
|
|
|
|
2014-04-23 09:20:21 +04:00
|
|
|
if (mOtherNamesMissed) {
|
2021-03-23 13:36:36 +03:00
|
|
|
forceReflow = std::any_of(
|
|
|
|
mOtherNamesMissed->cbegin(), mOtherNamesMissed->cend(),
|
|
|
|
[&](const auto& key) {
|
|
|
|
return FindUnsharedFamily(
|
2021-09-08 15:18:17 +03:00
|
|
|
nullptr, key,
|
|
|
|
(FindFamiliesFlags::eForceOtherFamilyNamesLoading |
|
|
|
|
FindFamiliesFlags::eNoAddToNamesMissedWhenSearching));
|
2021-03-23 13:36:36 +03:00
|
|
|
});
|
|
|
|
if (forceReflow) {
|
2021-08-27 02:17:54 +03:00
|
|
|
gfxPlatform::ForceGlobalReflow(gfxPlatform::NeedsReframe::No);
|
2014-04-23 09:20:21 +04:00
|
|
|
}
|
2021-03-23 13:36:36 +03:00
|
|
|
|
2015-07-14 05:08:31 +03:00
|
|
|
mOtherNamesMissed = nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
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,
|
2014-04-23 09:20:20 +04:00
|
|
|
mFontInfo->mLoadStats.facenames, 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() {
|
2020-10-03 19:03:54 +03:00
|
|
|
uint32_t delay = std::max(1u, StaticPrefs::gfx_font_loader_delay_AtStartup());
|
2021-05-18 14:10:43 +03:00
|
|
|
if (NS_IsMainThread()) {
|
|
|
|
StartLoader(delay);
|
|
|
|
} else {
|
|
|
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
|
|
"StartLoader callback",
|
|
|
|
[delay, fontList = this] { fontList->StartLoader(delay); }));
|
|
|
|
}
|
2013-04-26 11:40:44 +04:00
|
|
|
}
|
|
|
|
|
2020-05-21 16:18:06 +03:00
|
|
|
void gfxPlatformFontList::RebuildLocalFonts(bool aForgetLocalFaces) {
|
2021-03-23 13:36:36 +03:00
|
|
|
for (auto* fontset : mUserFontSetList) {
|
2020-05-21 16:18:06 +03:00
|
|
|
if (aForgetLocalFaces) {
|
|
|
|
fontset->ForgetLocalFaces();
|
|
|
|
}
|
|
|
|
fontset->RebuildLocalRules();
|
2015-07-14 05:08:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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];
|
2019-04-02 00:47:59 +03:00
|
|
|
for (auto& pref : prefFontsLangGroup) {
|
|
|
|
pref = nullptr;
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +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
|
2019-02-26 01:07:19 +03:00
|
|
|
/*static*/
|
|
|
|
size_t gfxPlatformFontList::SizeOfFontFamilyTableExcludingThis(
|
2015-07-31 07:19:57 +03:00
|
|
|
const FontFamilyTable& aTable, MallocSizeOf aMallocSizeOf) {
|
2021-03-23 13:36:36 +03:00
|
|
|
return std::accumulate(
|
|
|
|
aTable.Keys().cbegin(), aTable.Keys().cend(),
|
|
|
|
aTable.ShallowSizeOfExcludingThis(aMallocSizeOf),
|
|
|
|
[&](size_t oldValue, const nsACString& key) {
|
|
|
|
// 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.
|
|
|
|
return oldValue + key.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
|
|
});
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/*static*/
|
|
|
|
size_t gfxPlatformFontList::SizeOfFontEntryTableExcludingThis(
|
2015-08-05 04:05:19 +03:00
|
|
|
const FontEntryTable& aTable, MallocSizeOf aMallocSizeOf) {
|
2021-03-23 13:36:36 +03:00
|
|
|
return std::accumulate(
|
|
|
|
aTable.Keys().cbegin(), aTable.Keys().cend(),
|
|
|
|
aTable.ShallowSizeOfExcludingThis(aMallocSizeOf),
|
|
|
|
[&](size_t oldValue, const nsACString& key) {
|
|
|
|
// The font itself is counted by its owning family; here we only care
|
|
|
|
// about the names stored in the hashtable keys.
|
|
|
|
|
|
|
|
return oldValue + key.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
|
|
});
|
2015-08-05 04:05:19 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2013-10-15 06:19:47 +04:00
|
|
|
void 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);
|
2021-03-12 19:14:58 +03:00
|
|
|
for (const auto& entry : mFontFamilies) {
|
2012-03-28 01:38:39 +04:00
|
|
|
aSizes->mFontListSize +=
|
2021-03-12 19:14:58 +03:00
|
|
|
entry.GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
|
|
entry.GetData()->AddSizeOfIncludingThis(aMallocSizeOf, aSizes);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2015-07-31 07:19:57 +03:00
|
|
|
aSizes->mFontListSize +=
|
|
|
|
SizeOfFontFamilyTableExcludingThis(mOtherFamilyNames, aMallocSizeOf);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2013-09-02 12:41:57 +04:00
|
|
|
if (mExtraNames) {
|
2015-08-05 04:05:19 +03:00
|
|
|
aSizes->mFontListSize += SizeOfFontEntryTableExcludingThis(
|
|
|
|
mExtraNames->mFullnames, aMallocSizeOf);
|
|
|
|
aSizes->mFontListSize += SizeOfFontEntryTableExcludingThis(
|
|
|
|
mExtraNames->mPostscriptNames, aMallocSizeOf);
|
2018-11-30 13:46:48 +03: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];
|
2019-04-02 00:47:59 +03:00
|
|
|
for (const UniquePtr<PrefFontList>& pf : prefFontsLangGroup) {
|
2015-09-29 04:51:29 +03:00
|
|
|
if (pf) {
|
2015-07-29 09:24:24 +03:00
|
|
|
aSizes->mFontListSize += pf->ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-08 15:18:17 +03:00
|
|
|
for (const auto& bitset : mCodepointsWithNoFonts) {
|
|
|
|
aSizes->mFontListSize += bitset.SizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
}
|
2015-07-31 07:19:57 +03:00
|
|
|
aSizes->mFontListSize +=
|
2015-07-29 09:24:24 +03:00
|
|
|
mFontFamiliesToLoad.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-07-31 07:19:57 +03:00
|
|
|
aSizes->mFontListSize +=
|
2018-11-15 19:11:45 +03:00
|
|
|
mBadUnderlineFamilyNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
|
|
|
for (const auto& i : mBadUnderlineFamilyNames) {
|
2015-08-05 04:05:19 +03:00
|
|
|
aSizes->mFontListSize += i.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2015-07-31 07:19:57 +03:00
|
|
|
aSizes->mFontListSize +=
|
2015-07-29 11:50:52 +03:00
|
|
|
mSharedCmaps.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2021-03-12 19:14:58 +03:00
|
|
|
for (const auto& entry : mSharedCmaps) {
|
|
|
|
aSizes->mCharMapsSize += entry.GetKey()->SizeOfIncludingThis(aMallocSizeOf);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
|
|
|
|
aSizes->mFontListSize +=
|
|
|
|
mFontEntries.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2021-03-24 20:56:49 +03:00
|
|
|
for (const auto& entry : mFontEntries.Values()) {
|
|
|
|
if (entry) {
|
|
|
|
entry->AddSizeOfIncludingThis(aMallocSizeOf, aSizes);
|
2020-11-14 21:21:06 +03:00
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (SharedFontList()) {
|
|
|
|
aSizes->mFontListSize +=
|
|
|
|
SharedFontList()->SizeOfIncludingThis(aMallocSizeOf);
|
|
|
|
if (XRE_IsParentProcess()) {
|
|
|
|
aSizes->mSharedSize += SharedFontList()->AllocatedShmemSize();
|
|
|
|
}
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2013-10-15 06:19:47 +04:00
|
|
|
void 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);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
void gfxPlatformFontList::InitOtherFamilyNamesInternal(
|
|
|
|
bool aDeferOtherFamilyNamesLoading) {
|
|
|
|
if (mOtherFamilyNamesInitialized) {
|
2018-11-30 13:46:48 +03:00
|
|
|
return;
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
if (aDeferOtherFamilyNamesLoading) {
|
|
|
|
TimeStamp start = TimeStamp::Now();
|
|
|
|
bool timedOut = false;
|
2012-03-28 01:38:39 +04:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
auto list = SharedFontList();
|
|
|
|
if (list) {
|
2020-12-26 20:12:04 +03:00
|
|
|
// If the gfxFontInfoLoader task is not yet running, kick it off now so
|
|
|
|
// that it will load remaining names etc as soon as idle time permits.
|
|
|
|
if (mState == stateInitial || mState == stateTimerOnDelay) {
|
|
|
|
StartLoader(0);
|
|
|
|
timedOut = true;
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
} else {
|
2021-03-24 20:56:49 +03:00
|
|
|
for (const RefPtr<gfxFontFamily>& family : mFontFamilies.Values()) {
|
2019-04-27 18:37:58 +03:00
|
|
|
family->ReadOtherFamilyNames(this);
|
|
|
|
TimeDuration elapsed = TimeStamp::Now() - start;
|
|
|
|
if (elapsed.ToMilliseconds() > OTHERNAMES_TIMEOUT) {
|
|
|
|
timedOut = true;
|
|
|
|
break;
|
|
|
|
}
|
2015-09-29 04:51:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
if (!timedOut) {
|
2018-11-15 19:11:45 +03:00
|
|
|
mOtherFamilyNamesInitialized = true;
|
|
|
|
CancelInitOtherFamilyNamesTask();
|
|
|
|
}
|
2017-08-03 03:33:00 +03:00
|
|
|
TimeStamp end = TimeStamp::Now();
|
|
|
|
Telemetry::AccumulateTimeDelta(Telemetry::FONTLIST_INITOTHERFAMILYNAMES,
|
|
|
|
start, end);
|
2012-04-19 03:59:43 +04:00
|
|
|
|
2015-07-29 11:50:52 +03:00
|
|
|
if (LOG_FONTINIT_ENABLED()) {
|
|
|
|
TimeDuration elapsed = end - start;
|
|
|
|
LOG_FONTINIT(("(fontinit) InitOtherFamilyNames took %8.2f ms %s",
|
|
|
|
elapsed.ToMilliseconds(), (timedOut ? "timeout" : "")));
|
|
|
|
}
|
2012-03-28 01:38:39 +04:00
|
|
|
} else {
|
2016-08-23 03:06:07 +03:00
|
|
|
TimeStamp start = TimeStamp::Now();
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
auto list = SharedFontList();
|
|
|
|
if (list) {
|
|
|
|
for (auto& f : mozilla::Range<fontlist::Family>(list->Families(),
|
|
|
|
list->NumFamilies())) {
|
|
|
|
ReadFaceNamesForFamily(&f, false);
|
|
|
|
}
|
|
|
|
} else {
|
2021-03-24 20:56:49 +03:00
|
|
|
for (const RefPtr<gfxFontFamily>& family : mFontFamilies.Values()) {
|
2019-04-27 18:37:58 +03:00
|
|
|
family->ReadOtherFamilyNames(this);
|
|
|
|
}
|
2017-08-03 03:33:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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()));
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2017-08-03 03:33:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfxPlatformFontList::CancelInitOtherFamilyNamesTask() {
|
|
|
|
if (mPendingOtherFamilyNameTask) {
|
|
|
|
mPendingOtherFamilyNameTask->Cancel();
|
|
|
|
mPendingOtherFamilyNameTask = nullptr;
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
auto list = SharedFontList();
|
2019-08-30 16:14:26 +03:00
|
|
|
if (list && XRE_IsParentProcess()) {
|
2019-04-27 18:37:58 +03:00
|
|
|
bool forceReflow = false;
|
|
|
|
if (!mAliasTable.IsEmpty()) {
|
|
|
|
list->SetAliases(mAliasTable);
|
|
|
|
mAliasTable.Clear();
|
|
|
|
forceReflow = true;
|
|
|
|
}
|
|
|
|
if (mLocalNameTable.Count()) {
|
|
|
|
list->SetLocalNames(mLocalNameTable);
|
|
|
|
mLocalNameTable.Clear();
|
|
|
|
forceReflow = true;
|
|
|
|
}
|
|
|
|
if (forceReflow) {
|
|
|
|
dom::ContentParent::BroadcastFontListChanged();
|
|
|
|
}
|
|
|
|
}
|
2017-08-03 03:33:00 +03:00
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:29 +03:00
|
|
|
void gfxPlatformFontList::ShareFontListShmBlockToProcess(
|
2020-04-07 15:30:17 +03:00
|
|
|
uint32_t aGeneration, uint32_t aIndex, base::ProcessId aPid,
|
|
|
|
base::SharedMemoryHandle* aOut) {
|
2019-04-27 18:37:58 +03:00
|
|
|
auto list = SharedFontList();
|
|
|
|
if (!list) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!aGeneration || list->GetGeneration() == aGeneration) {
|
2020-04-07 15:30:17 +03:00
|
|
|
list->ShareShmBlockToProcess(aIndex, aPid, aOut);
|
2019-04-27 18:37:29 +03:00
|
|
|
} else {
|
2020-04-07 15:30:17 +03:00
|
|
|
*aOut = base::SharedMemory::NULLHandle();
|
2019-04-27 18:37:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-26 12:30:17 +03:00
|
|
|
void gfxPlatformFontList::ShareFontListToProcess(
|
|
|
|
nsTArray<base::SharedMemoryHandle>* aBlocks, base::ProcessId aPid) {
|
|
|
|
auto list = SharedFontList();
|
|
|
|
if (list) {
|
|
|
|
list->ShareBlocksToProcess(aBlocks, aPid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-13 17:30:09 +03:00
|
|
|
base::SharedMemoryHandle gfxPlatformFontList::ShareShmBlockToProcess(
|
|
|
|
uint32_t aIndex, base::ProcessId aPid) {
|
|
|
|
MOZ_RELEASE_ASSERT(SharedFontList());
|
|
|
|
return SharedFontList()->ShareBlockToProcess(aIndex, aPid);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gfxPlatformFontList::ShmBlockAdded(uint32_t aGeneration, uint32_t aIndex,
|
|
|
|
base::SharedMemoryHandle aHandle) {
|
|
|
|
if (SharedFontList()) {
|
2021-11-05 14:21:04 +03:00
|
|
|
SharedFontList()->ShmBlockAdded(aGeneration, aIndex, aHandle);
|
2021-05-13 17:30:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:29 +03:00
|
|
|
void gfxPlatformFontList::InitializeFamily(uint32_t aGeneration,
|
2020-07-23 00:12:11 +03:00
|
|
|
uint32_t aFamilyIndex,
|
|
|
|
bool aLoadCmaps) {
|
2019-04-27 18:37:58 +03:00
|
|
|
auto list = SharedFontList();
|
|
|
|
MOZ_ASSERT(list);
|
|
|
|
if (!list) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (list->GetGeneration() != aGeneration) {
|
2019-04-27 18:37:29 +03:00
|
|
|
return;
|
|
|
|
}
|
2021-06-07 00:24:44 +03:00
|
|
|
if (AppShutdown::IsShuttingDown()) {
|
|
|
|
return;
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
if (aFamilyIndex >= list->NumFamilies()) {
|
2019-04-27 18:37:29 +03:00
|
|
|
return;
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
fontlist::Family* family = list->Families() + aFamilyIndex;
|
2020-08-11 01:45:51 +03:00
|
|
|
if (!family->IsInitialized() || aLoadCmaps) {
|
2020-07-23 00:12:11 +03:00
|
|
|
Unused << InitializeFamily(family, aLoadCmaps);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2019-04-27 18:37:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void gfxPlatformFontList::SetCharacterMap(uint32_t aGeneration,
|
|
|
|
const fontlist::Pointer& aFacePtr,
|
|
|
|
const gfxSparseBitSet& aMap) {
|
2020-02-23 15:15:00 +03:00
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
2019-04-27 18:37:58 +03:00
|
|
|
auto list = SharedFontList();
|
|
|
|
MOZ_ASSERT(list);
|
|
|
|
if (!list) {
|
2019-04-27 18:37:29 +03:00
|
|
|
return;
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
if (list->GetGeneration() != aGeneration) {
|
|
|
|
return;
|
|
|
|
}
|
2021-06-07 00:24:44 +03:00
|
|
|
if (AppShutdown::IsShuttingDown()) {
|
|
|
|
return;
|
|
|
|
}
|
2019-04-27 18:37:58 +03:00
|
|
|
fontlist::Face* face = static_cast<fontlist::Face*>(aFacePtr.ToPtr(list));
|
|
|
|
if (face) {
|
2020-02-23 15:15:00 +03:00
|
|
|
face->mCharacterMap = GetShmemCharMap(&aMap);
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
2019-04-27 18:37:29 +03:00
|
|
|
}
|
|
|
|
|
2019-04-27 18:39:26 +03:00
|
|
|
void gfxPlatformFontList::SetupFamilyCharMap(
|
|
|
|
uint32_t aGeneration, const fontlist::Pointer& aFamilyPtr) {
|
2020-07-14 18:41:01 +03:00
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
2019-04-27 18:39:26 +03:00
|
|
|
auto list = SharedFontList();
|
|
|
|
MOZ_ASSERT(list);
|
|
|
|
if (!list) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (list->GetGeneration() != aGeneration) {
|
|
|
|
return;
|
|
|
|
}
|
2021-06-07 00:24:44 +03:00
|
|
|
if (AppShutdown::IsShuttingDown()) {
|
|
|
|
return;
|
|
|
|
}
|
2020-07-14 18:41:01 +03:00
|
|
|
|
|
|
|
// aFamilyPtr was passed from a content process which may not be trusted,
|
|
|
|
// so we cannot assume it is valid or safe to use. If the Pointer value is
|
|
|
|
// bad, we must not crash or do anything bad, just bail out.
|
|
|
|
// (In general, if the child process was trying to use an invalid pointer it
|
|
|
|
// should have hit the MOZ_DIAGNOSTIC_ASSERT in FontList::ToSharedPointer
|
|
|
|
// rather than passing a null or bad pointer to the parent.)
|
|
|
|
|
|
|
|
auto* family = static_cast<fontlist::Family*>(aFamilyPtr.ToPtr(list));
|
|
|
|
if (!family) {
|
|
|
|
// Unable to resolve to a native pointer (or it was null).
|
|
|
|
NS_WARNING("unexpected null Family pointer");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Validate the pointer before trying to use it: check that it points to a
|
|
|
|
// correctly-aligned offset within the Families() or AliasFamilies() array.
|
|
|
|
// We just assert (in debug builds only) on failure, and return safely.
|
|
|
|
// A misaligned pointer here would indicate a buggy (or compromised) child
|
|
|
|
// process, but crashing the parent would be unnecessary and does not yield
|
|
|
|
// any useful insight.
|
2019-04-27 18:39:26 +03:00
|
|
|
if (family >= list->Families() &&
|
|
|
|
family < list->Families() + list->NumFamilies()) {
|
|
|
|
size_t offset = (char*)family - (char*)list->Families();
|
|
|
|
if (offset % sizeof(fontlist::Family) != 0) {
|
2020-07-14 18:41:01 +03:00
|
|
|
MOZ_ASSERT(false, "misaligned Family pointer");
|
2019-04-27 18:39:26 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (family >= list->AliasFamilies() &&
|
|
|
|
family < list->AliasFamilies() + list->NumAliases()) {
|
|
|
|
size_t offset = (char*)family - (char*)list->AliasFamilies();
|
|
|
|
if (offset % sizeof(fontlist::Family) != 0) {
|
2020-07-14 18:41:01 +03:00
|
|
|
MOZ_ASSERT(false, "misaligned Family pointer");
|
2019-04-27 18:39:26 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2020-07-14 18:41:01 +03:00
|
|
|
MOZ_ASSERT(false, "not a valid Family or AliasFamily pointer");
|
2019-04-27 18:39:26 +03:00
|
|
|
return;
|
|
|
|
}
|
2020-07-14 18:41:01 +03:00
|
|
|
|
2019-04-27 18:39:26 +03:00
|
|
|
family->SetupFamilyCharMap(list);
|
|
|
|
}
|
|
|
|
|
2020-12-26 20:11:44 +03:00
|
|
|
bool gfxPlatformFontList::InitOtherFamilyNames(uint32_t aGeneration,
|
2019-04-27 18:37:29 +03:00
|
|
|
bool aDefer) {
|
2019-04-27 18:37:58 +03:00
|
|
|
auto list = SharedFontList();
|
|
|
|
MOZ_ASSERT(list);
|
|
|
|
if (!list) {
|
2020-12-26 20:11:44 +03:00
|
|
|
return false;
|
2019-04-27 18:37:58 +03:00
|
|
|
}
|
|
|
|
if (list->GetGeneration() != aGeneration) {
|
2020-12-26 20:11:44 +03:00
|
|
|
return false;
|
2019-04-27 18:37:29 +03:00
|
|
|
}
|
2021-06-07 00:24:44 +03:00
|
|
|
if (AppShutdown::IsShuttingDown()) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-12-26 20:11:44 +03:00
|
|
|
return InitOtherFamilyNames(aDefer);
|
2019-04-27 18:37:29 +03:00
|
|
|
}
|
|
|
|
|
2019-11-17 14:49:20 +03:00
|
|
|
uint32_t gfxPlatformFontList::GetGeneration() const {
|
|
|
|
return SharedFontList() ? SharedFontList()->GetGeneration() : 0;
|
|
|
|
}
|
|
|
|
|
2016-07-26 23:19:48 +03:00
|
|
|
#undef LOG
|
|
|
|
#undef LOG_ENABLED
|