2009-10-07 18:13:40 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
2012-05-21 15:12:37 +04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2012-12-15 03:58:45 +04:00
|
|
|
#include "mozilla/DebugOnly.h"
|
2013-01-15 16:22:03 +04:00
|
|
|
#include <algorithm>
|
2011-10-11 09:50:08 +04:00
|
|
|
|
2015-05-19 21:15:34 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2016-08-17 01:41:12 +03:00
|
|
|
#include "mozilla/Sprintf.h"
|
2011-01-21 19:44:33 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
#include "gfxGDIFontList.h"
|
|
|
|
#include "gfxWindowsPlatform.h"
|
|
|
|
#include "gfxUserFontSet.h"
|
|
|
|
#include "gfxFontUtils.h"
|
2010-03-15 12:34:25 +03:00
|
|
|
#include "gfxGDIFont.h"
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
#include "nsServiceManagerUtils.h"
|
|
|
|
#include "nsTArray.h"
|
|
|
|
#include "nsUnicharUtils.h"
|
|
|
|
|
|
|
|
#include "nsDirectoryServiceUtils.h"
|
|
|
|
#include "nsDirectoryServiceDefs.h"
|
|
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
|
|
#include "nsISimpleEnumerator.h"
|
|
|
|
#include "nsIWindowsRegKey.h"
|
2013-10-08 03:15:59 +04:00
|
|
|
#include "gfxFontConstants.h"
|
2016-01-15 13:38:03 +03:00
|
|
|
#include "GeckoProfiler.h"
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2013-06-23 16:03:39 +04:00
|
|
|
#include "mozilla/MemoryReporting.h"
|
2011-07-27 10:42:53 +04:00
|
|
|
#include "mozilla/Telemetry.h"
|
|
|
|
|
2010-03-15 12:34:25 +03:00
|
|
|
#include <usp10.h>
|
|
|
|
|
2011-07-27 10:42:53 +04:00
|
|
|
using namespace mozilla;
|
2017-04-07 00:41:02 +03:00
|
|
|
using namespace mozilla::gfx;
|
2011-07-27 10:42:53 +04:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
#define ROUND(x) floor((x) + 0.5)
|
|
|
|
|
2015-05-21 23:22:04 +03:00
|
|
|
#define LOG_FONTLIST(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
|
2015-06-04 01:25:57 +03:00
|
|
|
LogLevel::Debug, args)
|
2015-06-04 01:22:28 +03:00
|
|
|
#define LOG_FONTLIST_ENABLED() MOZ_LOG_TEST( \
|
2011-01-21 19:44:33 +03:00
|
|
|
gfxPlatform::GetLog(eGfxLog_fontlist), \
|
2015-06-04 01:25:57 +03:00
|
|
|
LogLevel::Debug)
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2015-06-04 01:22:28 +03:00
|
|
|
#define LOG_CMAPDATA_ENABLED() MOZ_LOG_TEST( \
|
2012-03-09 06:05:14 +04:00
|
|
|
gfxPlatform::GetLog(eGfxLog_cmapdata), \
|
2015-06-04 01:25:57 +03:00
|
|
|
LogLevel::Debug)
|
2012-03-09 06:05:14 +04:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
static __inline void
|
|
|
|
BuildKeyNameFromFontName(nsAString &aName)
|
|
|
|
{
|
|
|
|
if (aName.Length() >= LF_FACESIZE)
|
|
|
|
aName.Truncate(LF_FACESIZE - 1);
|
|
|
|
ToLowerCase(aName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implementation of gfxPlatformFontList for Win32 GDI,
|
|
|
|
// using GDI font enumeration APIs to get the list of fonts
|
|
|
|
|
|
|
|
class WinUserFontData : public gfxUserFontData {
|
|
|
|
public:
|
2016-12-16 10:54:32 +03:00
|
|
|
explicit WinUserFontData(HANDLE aFontRef)
|
2013-07-09 05:40:03 +04:00
|
|
|
: mFontRef(aFontRef)
|
2009-10-07 18:13:40 +04:00
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual ~WinUserFontData()
|
|
|
|
{
|
2013-07-09 05:40:03 +04:00
|
|
|
DebugOnly<BOOL> success;
|
|
|
|
success = RemoveFontMemResourceEx(mFontRef);
|
2010-07-17 05:32:18 +04:00
|
|
|
#if DEBUG
|
2013-07-09 05:40:03 +04:00
|
|
|
if (!success) {
|
|
|
|
char buf[256];
|
2016-08-17 01:41:12 +03:00
|
|
|
SprintfLiteral(buf, "error deleting font handle (%p) - RemoveFontMemResourceEx failed", mFontRef);
|
2013-07-09 05:40:03 +04:00
|
|
|
NS_ASSERTION(success, buf);
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2013-07-09 05:40:03 +04:00
|
|
|
#endif
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2016-08-17 01:41:12 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
HANDLE mFontRef;
|
|
|
|
};
|
|
|
|
|
2018-10-13 01:16:45 +03:00
|
|
|
BYTE
|
2012-08-22 19:56:38 +04:00
|
|
|
FontTypeToOutPrecision(uint8_t fontType)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
|
|
|
BYTE ret;
|
|
|
|
switch (fontType) {
|
|
|
|
case GFX_FONT_TYPE_TT_OPENTYPE:
|
|
|
|
case GFX_FONT_TYPE_TRUETYPE:
|
|
|
|
ret = OUT_TT_ONLY_PRECIS;
|
|
|
|
break;
|
|
|
|
case GFX_FONT_TYPE_PS_OPENTYPE:
|
|
|
|
ret = OUT_PS_ONLY_PRECIS;
|
|
|
|
break;
|
|
|
|
case GFX_FONT_TYPE_TYPE1:
|
|
|
|
ret = OUT_OUTLINE_PRECIS;
|
|
|
|
break;
|
|
|
|
case GFX_FONT_TYPE_RASTER:
|
|
|
|
ret = OUT_RASTER_PRECIS;
|
|
|
|
break;
|
|
|
|
case GFX_FONT_TYPE_DEVICE:
|
|
|
|
ret = OUT_DEVICE_PRECIS;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = OUT_DEFAULT_PRECIS;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
*
|
|
|
|
* GDIFontEntry
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
GDIFontEntry::GDIFontEntry(const nsACString& aFaceName,
|
2011-09-05 11:34:40 +04:00
|
|
|
gfxWindowsFontType aFontType,
|
2018-04-25 09:18:23 +03:00
|
|
|
SlantStyleRange aStyle,
|
|
|
|
WeightRange aWeight,
|
|
|
|
StretchRange aStretch,
|
2017-11-23 22:38:17 +03:00
|
|
|
gfxUserFontData *aUserFontData)
|
2011-09-05 11:34:40 +04:00
|
|
|
: gfxFontEntry(aFaceName),
|
|
|
|
mFontType(aFontType),
|
2012-04-19 03:59:43 +04:00
|
|
|
mForceGDI(false),
|
2017-09-11 21:22:15 +03:00
|
|
|
mUnicodeRanges()
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
2016-04-15 22:45:37 +03:00
|
|
|
mUserFontData.reset(aUserFontData);
|
2018-04-25 09:18:23 +03:00
|
|
|
mStyleRange = aStyle;
|
|
|
|
mWeightRange = aWeight;
|
|
|
|
mStretchRange = aStretch;
|
2009-10-07 18:13:40 +04:00
|
|
|
if (IsType1())
|
2011-10-17 18:59:28 +04:00
|
|
|
mForceGDI = true;
|
2014-09-08 11:23:20 +04:00
|
|
|
mIsDataUserFont = aUserFontData != nullptr;
|
2010-05-27 09:05:30 +04:00
|
|
|
|
2010-06-09 04:33:13 +04:00
|
|
|
InitLogFont(aFaceName, aFontType);
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2017-08-01 13:25:35 +03:00
|
|
|
gfxFontEntry*
|
|
|
|
GDIFontEntry::Clone() const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!IsUserFont(), "we can only clone installed fonts!");
|
2018-04-25 09:18:23 +03:00
|
|
|
return new GDIFontEntry(Name(), mFontType, SlantStyle(), Weight(),
|
|
|
|
Stretch(), nullptr);
|
2017-08-01 13:25:35 +03:00
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
nsresult
|
2014-01-29 11:39:01 +04:00
|
|
|
GDIFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
|
|
|
AUTO_PROFILER_LABEL("GDIFontEntry::ReadCMAP", OTHER);
|
2016-01-15 13:38:03 +03:00
|
|
|
|
2012-04-19 03:59:43 +04:00
|
|
|
// attempt this once, if errors occur leave a blank cmap
|
|
|
|
if (mCharacterMap) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-06-25 16:43:10 +04:00
|
|
|
// skip non-SFNT fonts completely
|
2018-10-13 01:16:45 +03:00
|
|
|
if (mFontType != GFX_FONT_TYPE_PS_OPENTYPE &&
|
2010-06-25 16:43:10 +04:00
|
|
|
mFontType != GFX_FONT_TYPE_TT_OPENTYPE &&
|
2018-10-13 01:16:45 +03:00
|
|
|
mFontType != GFX_FONT_TYPE_TRUETYPE)
|
2010-06-25 16:43:10 +04:00
|
|
|
{
|
2012-04-19 03:59:43 +04:00
|
|
|
mCharacterMap = new gfxCharacterMap();
|
2012-04-27 12:26:41 +04:00
|
|
|
mCharacterMap->mBuildOnTheFly = true;
|
2010-06-25 16:43:10 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxCharacterMap> charmap;
|
2012-04-19 03:59:43 +04:00
|
|
|
nsresult rv;
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
if (aFontInfoData && (charmap = GetCMAPFromFontInfo(aFontInfoData,
|
2017-09-11 21:23:30 +03:00
|
|
|
mUVSOffset))) {
|
2014-01-29 11:39:01 +04:00
|
|
|
rv = NS_OK;
|
|
|
|
} else {
|
|
|
|
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
|
|
|
charmap = new gfxCharacterMap();
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<uint8_t, 16384> cmap;
|
2014-01-29 11:39:01 +04:00
|
|
|
rv = CopyFontTable(kCMAP, cmap);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
2017-09-11 21:23:30 +03:00
|
|
|
*charmap, mUVSOffset);
|
2014-01-29 11:39:01 +04:00
|
|
|
}
|
2012-04-19 03:59:43 +04:00
|
|
|
}
|
|
|
|
|
2009-10-07 21:16:52 +04:00
|
|
|
mHasCmapTable = NS_SUCCEEDED(rv);
|
2012-04-19 03:59:43 +04:00
|
|
|
if (mHasCmapTable) {
|
|
|
|
gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
|
|
|
|
mCharacterMap = pfl->FindCharMap(charmap);
|
|
|
|
} else {
|
|
|
|
// if error occurred, initialize to null cmap
|
|
|
|
mCharacterMap = new gfxCharacterMap();
|
|
|
|
// For fonts where we failed to read the character map,
|
|
|
|
// we can take a slow path to look up glyphs character by character
|
|
|
|
mCharacterMap->mBuildOnTheFly = true;
|
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2012-04-19 03:59:43 +04:00
|
|
|
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n",
|
2018-09-12 22:34:57 +03:00
|
|
|
mName.get(),
|
2012-04-19 03:59:43 +04:00
|
|
|
charmap->SizeOfIncludingThis(moz_malloc_size_of),
|
|
|
|
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
|
2012-03-09 06:05:14 +04:00
|
|
|
if (LOG_CMAPDATA_ENABLED()) {
|
|
|
|
char prefix[256];
|
2016-08-17 01:41:12 +03:00
|
|
|
SprintfLiteral(prefix, "(cmapdata) name: %.220s",
|
2018-09-12 22:34:57 +03:00
|
|
|
mName.get());
|
2012-04-19 03:59:43 +04:00
|
|
|
charmap->Dump(prefix, eGfxLog_cmapdata);
|
2012-03-09 06:05:14 +04:00
|
|
|
}
|
2012-04-19 03:59:43 +04:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2009-10-07 19:26:58 +04:00
|
|
|
gfxFont *
|
Bug 1449605 - part 1 - Rearrange thebes font code so that the decision whether to apply synthetic-bold is deferred until actually instantiating a font, not made during the font-matching process. r=jwatt
This rearranges how synthetic-bold use is determined in the font selection
& rendering code. Previously, we would decide during the font-selection
algorithm whether we need to apply synthetic-bold to the chosen face, and
then pass that decision through the fontgroup (storing it in the FamilyFace
entries of the mFonts array there) down to the actual rendering code that
instantiates fonts from the faces (font entries) we've selected.
That became a problem for variation fonts because in the case of a user
font, we may not have downloaded the resource yet, so we just have a "user
font container" entry, which carries the descriptors from the @font-face
rule and will fetch the actual resource when needed. But in the case of a
@font-face rule without a weight descriptor, we don't actually know at
font-selection time whether the face will support "true" bold (via a
variation axis) or not, so we can't reliably make the right decision about
applying synthetic bold.
So we now defer that decision until we actually instantiate a platform font
object to shape/measure/draw text. At that point, we have the requested
style and we also have the real font resource, so we can easily determine
whether fake-bold is required.
(This patch should not result in any visible behavior change; that will
come in a second patch now that the architecture supports it.)
2018-05-01 12:30:50 +03:00
|
|
|
GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle)
|
2009-10-07 19:26:58 +04:00
|
|
|
{
|
Bug 1449605 - part 1 - Rearrange thebes font code so that the decision whether to apply synthetic-bold is deferred until actually instantiating a font, not made during the font-matching process. r=jwatt
This rearranges how synthetic-bold use is determined in the font selection
& rendering code. Previously, we would decide during the font-selection
algorithm whether we need to apply synthetic-bold to the chosen face, and
then pass that decision through the fontgroup (storing it in the FamilyFace
entries of the mFonts array there) down to the actual rendering code that
instantiates fonts from the faces (font entries) we've selected.
That became a problem for variation fonts because in the case of a user
font, we may not have downloaded the resource yet, so we just have a "user
font container" entry, which carries the descriptors from the @font-face
rule and will fetch the actual resource when needed. But in the case of a
@font-face rule without a weight descriptor, we don't actually know at
font-selection time whether the face will support "true" bold (via a
variation axis) or not, so we can't reliably make the right decision about
applying synthetic bold.
So we now defer that decision until we actually instantiate a platform font
object to shape/measure/draw text. At that point, we have the requested
style and we also have the real font resource, so we can easily determine
whether fake-bold is required.
(This patch should not result in any visible behavior change; that will
come in a second patch now that the architecture supports it.)
2018-05-01 12:30:50 +03:00
|
|
|
return new gfxGDIFont(this, aFontStyle);
|
2009-10-07 19:26:58 +04:00
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
nsresult
|
2016-02-02 18:36:30 +03:00
|
|
|
GDIFontEntry::CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>& aBuffer)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
2010-06-11 23:14:38 +04:00
|
|
|
if (!IsTrueType()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
AutoDC dc;
|
|
|
|
AutoSelectFont font(dc.GetDC(), &mLogFont);
|
|
|
|
if (font.IsValid()) {
|
2012-10-04 12:35:15 +04:00
|
|
|
uint32_t tableSize =
|
2013-04-24 11:40:33 +04:00
|
|
|
::GetFontData(dc.GetDC(),
|
2013-07-31 19:44:31 +04:00
|
|
|
NativeEndian::swapToBigEndian(aTableTag),
|
|
|
|
0, nullptr, 0);
|
2009-10-07 18:13:40 +04:00
|
|
|
if (tableSize != GDI_ERROR) {
|
2015-06-11 00:30:41 +03:00
|
|
|
if (aBuffer.SetLength(tableSize, fallible)) {
|
2013-04-24 11:40:33 +04:00
|
|
|
::GetFontData(dc.GetDC(),
|
|
|
|
NativeEndian::swapToBigEndian(aTableTag), 0,
|
2010-06-11 23:14:38 +04:00
|
|
|
aBuffer.Elements(), tableSize);
|
2009-10-07 18:13:40 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2017-04-07 00:41:02 +03:00
|
|
|
already_AddRefed<UnscaledFontGDI>
|
|
|
|
GDIFontEntry::LookupUnscaledFont(HFONT aFont)
|
|
|
|
{
|
2017-10-18 21:22:09 +03:00
|
|
|
RefPtr<UnscaledFontGDI> unscaledFont(mUnscaledFont);
|
2017-04-07 00:41:02 +03:00
|
|
|
if (!unscaledFont) {
|
|
|
|
LOGFONT lf;
|
|
|
|
GetObject(aFont, sizeof(LOGFONT), &lf);
|
|
|
|
unscaledFont = new UnscaledFontGDI(lf);
|
|
|
|
mUnscaledFont = unscaledFont;
|
|
|
|
}
|
|
|
|
|
|
|
|
return unscaledFont.forget();
|
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
void
|
2012-02-14 12:24:26 +04:00
|
|
|
GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
|
2018-04-16 22:26:08 +03:00
|
|
|
LONG aWeight,
|
2018-04-13 22:34:37 +03:00
|
|
|
gfxFloat aSize)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
|
|
|
memcpy(aLogFont, &mLogFont, sizeof(LOGFONTW));
|
|
|
|
|
|
|
|
aLogFont->lfHeight = (LONG)-ROUND(aSize);
|
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
if (aLogFont->lfHeight == 0) {
|
2009-10-07 18:13:40 +04:00
|
|
|
aLogFont->lfHeight = -1;
|
2012-02-14 12:24:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// If a non-zero weight is passed in, use this to override the original
|
|
|
|
// weight in the entry's logfont. This is used to control synthetic bolding
|
|
|
|
// for installed families with no bold face, and for downloaded fonts
|
|
|
|
// (but NOT for local user fonts, because it could cause a different,
|
|
|
|
// glyph-incompatible face to be used)
|
2018-04-16 22:26:08 +03:00
|
|
|
if (aWeight != 0) {
|
|
|
|
aLogFont->lfWeight = aWeight;
|
2012-02-14 12:24:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// for non-local() user fonts, we never want to apply italics here;
|
|
|
|
// if the face is described as italic, we should use it as-is,
|
|
|
|
// and if it's not, but then the element is styled italic, we'll use
|
|
|
|
// a cairo transform to create fake italic (oblique)
|
2014-09-08 11:23:20 +04:00
|
|
|
if (mIsDataUserFont) {
|
2012-02-14 12:24:26 +04:00
|
|
|
aLogFont->lfItalic = 0;
|
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2011-02-22 20:04:37 +03:00
|
|
|
#define MISSING_GLYPH 0x1F // glyph index returned for missing characters
|
|
|
|
// on WinXP with .fon fonts, but not Type1 (.pfb)
|
2010-06-25 16:43:10 +04:00
|
|
|
|
2018-10-13 01:16:45 +03:00
|
|
|
bool
|
2012-08-22 19:56:38 +04:00
|
|
|
GDIFontEntry::TestCharacterMap(uint32_t aCh)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
2012-04-19 03:59:43 +04:00
|
|
|
if (!mCharacterMap) {
|
2012-10-04 12:35:15 +04:00
|
|
|
ReadCMAP();
|
2012-04-19 03:59:43 +04:00
|
|
|
NS_ASSERTION(mCharacterMap, "failed to initialize a character map");
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2012-04-19 03:59:43 +04:00
|
|
|
if (mCharacterMap->mBuildOnTheFly) {
|
2009-10-07 18:13:40 +04:00
|
|
|
if (aCh > 0xFFFF)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
// previous code was using the group style
|
2015-10-19 05:16:43 +03:00
|
|
|
gfxFontStyle fakeStyle;
|
|
|
|
if (!IsUpright()) {
|
2018-04-23 17:52:20 +03:00
|
|
|
fakeStyle.style = FontSlantStyle::Italic();
|
2015-10-19 05:16:43 +03:00
|
|
|
}
|
2018-04-25 09:18:23 +03:00
|
|
|
fakeStyle.weight = Weight().Min();
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2018-08-30 15:08:27 +03:00
|
|
|
RefPtr<gfxFont> tempFont = FindOrMakeFont(&fakeStyle, nullptr);
|
2010-03-15 12:34:25 +03:00
|
|
|
if (!tempFont || !tempFont->Valid())
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2010-03-15 12:34:25 +03:00
|
|
|
gfxGDIFont *font = static_cast<gfxGDIFont*>(tempFont.get());
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
HDC dc = GetDC((HWND)nullptr);
|
2009-10-07 18:13:40 +04:00
|
|
|
SetGraphicsMode(dc, GM_ADVANCED);
|
|
|
|
HFONT hfont = font->GetHFONT();
|
|
|
|
HFONT oldFont = (HFONT)SelectObject(dc, hfont);
|
|
|
|
|
2016-03-21 23:17:16 +03:00
|
|
|
wchar_t str[1] = { (wchar_t)aCh };
|
2009-10-07 18:13:40 +04:00
|
|
|
WORD glyph[1];
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hasGlyph = false;
|
2010-06-25 16:43:10 +04:00
|
|
|
|
2018-10-13 01:16:45 +03:00
|
|
|
// Bug 573038 - in some cases GetGlyphIndicesW returns 0xFFFF for a
|
|
|
|
// missing glyph or 0x1F in other cases to indicate the "invalid"
|
2010-06-25 16:43:10 +04:00
|
|
|
// glyph. Map both cases to "not found"
|
2010-03-15 12:34:25 +03:00
|
|
|
if (IsType1() || mForceGDI) {
|
2018-10-13 01:16:45 +03:00
|
|
|
// Type1 fonts and uniscribe APIs don't get along.
|
2010-06-25 16:43:10 +04:00
|
|
|
// ScriptGetCMap will return E_HANDLE
|
2018-10-13 01:16:45 +03:00
|
|
|
DWORD ret = GetGlyphIndicesW(dc, str, 1,
|
2010-06-25 16:43:10 +04:00
|
|
|
glyph, GGI_MARK_NONEXISTING_GLYPHS);
|
|
|
|
if (ret != GDI_ERROR
|
2011-02-22 20:04:37 +03:00
|
|
|
&& glyph[0] != 0xFFFF
|
|
|
|
&& (IsType1() || glyph[0] != MISSING_GLYPH))
|
2010-06-25 16:43:10 +04:00
|
|
|
{
|
2011-10-17 18:59:28 +04:00
|
|
|
hasGlyph = true;
|
2010-06-25 16:43:10 +04:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
} else {
|
2018-10-13 01:16:45 +03:00
|
|
|
// ScriptGetCMap works better than GetGlyphIndicesW
|
2010-06-25 16:43:10 +04:00
|
|
|
// for things like bitmap/vector fonts
|
2013-07-31 19:44:31 +04:00
|
|
|
SCRIPT_CACHE sc = nullptr;
|
2010-03-15 12:34:25 +03:00
|
|
|
HRESULT rv = ScriptGetCMap(dc, &sc, str, 1, 0, glyph);
|
2009-10-07 18:13:40 +04:00
|
|
|
if (rv == S_OK)
|
2011-10-17 18:59:28 +04:00
|
|
|
hasGlyph = true;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
SelectObject(dc, oldFont);
|
2013-07-31 19:44:31 +04:00
|
|
|
ReleaseDC(nullptr, dc);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
if (hasGlyph) {
|
2012-04-19 03:59:43 +04:00
|
|
|
mCharacterMap->set(aCh);
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// font had a cmap so simply check that
|
2012-04-19 03:59:43 +04:00
|
|
|
return mCharacterMap->test(aCh);
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-09-12 22:34:57 +03:00
|
|
|
GDIFontEntry::InitLogFont(const nsACString& aName,
|
2011-09-05 11:34:40 +04:00
|
|
|
gfxWindowsFontType aFontType)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
|
|
|
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
|
2012-07-03 14:42:07 +04:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
mLogFont.lfHeight = -1;
|
|
|
|
|
|
|
|
// Fill in logFont structure
|
|
|
|
mLogFont.lfWidth = 0;
|
|
|
|
mLogFont.lfEscapement = 0;
|
|
|
|
mLogFont.lfOrientation = 0;
|
|
|
|
mLogFont.lfUnderline = FALSE;
|
|
|
|
mLogFont.lfStrikeOut = FALSE;
|
|
|
|
mLogFont.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
mLogFont.lfOutPrecision = FontTypeToOutPrecision(aFontType);
|
|
|
|
mLogFont.lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
|
2010-06-09 04:33:13 +04:00
|
|
|
mLogFont.lfQuality = DEFAULT_QUALITY;
|
2009-10-07 18:13:40 +04:00
|
|
|
mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
|
|
|
// always force lfItalic if we want it. Font selection code will
|
|
|
|
// do its best to give us an italic font entry, but if no face exists
|
|
|
|
// it may give us a regular one based on weight. Windows should
|
|
|
|
// do fake italic for us in that case.
|
2015-10-19 05:16:43 +03:00
|
|
|
mLogFont.lfItalic = !IsUpright();
|
2018-04-25 09:18:23 +03:00
|
|
|
mLogFont.lfWeight = Weight().Min().ToIntRounded();
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF8toUTF16 name(aName);
|
|
|
|
int len = std::min<int>(name.Length(), LF_FACESIZE - 1);
|
|
|
|
memcpy(&mLogFont.lfFaceName, name.BeginReading(), len * sizeof(char16_t));
|
2009-10-07 18:13:40 +04:00
|
|
|
mLogFont.lfFaceName[len] = '\0';
|
|
|
|
}
|
|
|
|
|
2018-10-13 01:16:45 +03:00
|
|
|
GDIFontEntry*
|
2018-09-12 22:34:57 +03:00
|
|
|
GDIFontEntry::CreateFontEntry(const nsACString& aName,
|
2015-10-19 05:16:43 +03:00
|
|
|
gfxWindowsFontType aFontType,
|
2018-04-25 09:18:23 +03:00
|
|
|
SlantStyleRange aStyle,
|
|
|
|
WeightRange aWeight,
|
|
|
|
StretchRange aStretch,
|
2017-11-23 22:38:17 +03:00
|
|
|
gfxUserFontData* aUserFontData)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
|
|
|
// jtdfix - need to set charset, unicode ranges, pitch/family
|
|
|
|
|
2015-10-19 05:16:43 +03:00
|
|
|
GDIFontEntry *fe = new GDIFontEntry(aName, aFontType, aStyle,
|
2017-11-23 22:38:17 +03:00
|
|
|
aWeight, aStretch, aUserFontData);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
return fe;
|
|
|
|
}
|
|
|
|
|
2012-03-28 01:38:39 +04:00
|
|
|
void
|
2013-10-15 06:19:47 +04:00
|
|
|
GDIFontEntry::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
|
|
|
|
FontListSizes* aSizes) const
|
2012-03-28 01:38:39 +04:00
|
|
|
{
|
|
|
|
aSizes->mFontListSize += aMallocSizeOf(this);
|
2013-10-15 06:19:47 +04:00
|
|
|
AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
/***************************************************************
|
|
|
|
*
|
|
|
|
* GDIFontFamily
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2017-03-29 12:38:41 +03:00
|
|
|
static bool
|
2018-09-12 22:34:57 +03:00
|
|
|
ShouldIgnoreItalicStyle(const nsACString& aName)
|
2017-03-29 12:38:41 +03:00
|
|
|
{
|
|
|
|
// Ignore italic style's "Meiryo" because "Meiryo (Bold) Italic" has
|
|
|
|
// non-italic style glyphs as Japanese characters. However, using it
|
|
|
|
// causes serious problem if web pages wants some elements to be
|
|
|
|
// different style from others only with font-style. For example,
|
|
|
|
// <em> and <i> should be rendered as italic in the default style.
|
|
|
|
return aName.EqualsLiteral("Meiryo") ||
|
2018-09-12 22:34:57 +03:00
|
|
|
aName.EqualsLiteral("\xe3\x83\xa1\xe3\x82\xa4\xe3\x83\xaa\xe3\x82\xaa");
|
2017-03-29 12:38:41 +03:00
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
int CALLBACK
|
|
|
|
GDIFontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
|
|
|
|
const NEWTEXTMETRICEXW *nmetrics,
|
|
|
|
DWORD fontType, LPARAM data)
|
|
|
|
{
|
|
|
|
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
|
|
|
LOGFONTW logFont = lpelfe->elfLogFont;
|
|
|
|
GDIFontFamily *ff = reinterpret_cast<GDIFontFamily*>(data);
|
|
|
|
|
2017-03-29 12:38:41 +03:00
|
|
|
if (logFont.lfItalic && ShouldIgnoreItalicStyle(ff->mName)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
// Some fonts claim to support things > 900, but we don't so clamp the sizes
|
2011-10-28 22:33:28 +04:00
|
|
|
logFont.lfWeight = clamped(logFont.lfWeight, LONG(100), LONG(900));
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
gfxWindowsFontType feType = GDIFontEntry::DetermineFontType(metrics, fontType);
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
GDIFontEntry *fe = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < ff->mAvailableFonts.Length(); ++i) {
|
2009-10-07 18:13:40 +04:00
|
|
|
fe = static_cast<GDIFontEntry*>(ff->mAvailableFonts[i].get());
|
|
|
|
if (feType > fe->mFontType) {
|
|
|
|
// if the new type is better than the old one, remove the old entries
|
|
|
|
ff->mAvailableFonts.RemoveElementAt(i);
|
|
|
|
--i;
|
|
|
|
} else if (feType < fe->mFontType) {
|
|
|
|
// otherwise if the new type is worse, skip it
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < ff->mAvailableFonts.Length(); ++i) {
|
2009-10-07 18:13:40 +04:00
|
|
|
fe = static_cast<GDIFontEntry*>(ff->mAvailableFonts[i].get());
|
|
|
|
// check if we already know about this face
|
2018-04-25 09:18:23 +03:00
|
|
|
if (fe->Weight().Min() == FontWeight(int32_t(logFont.lfWeight)) &&
|
2015-10-19 05:16:43 +03:00
|
|
|
fe->IsItalic() == (logFont.lfItalic == 0xFF)) {
|
2009-10-07 18:13:40 +04:00
|
|
|
// update the charset bit here since this could be different
|
2017-09-11 21:22:15 +03:00
|
|
|
// XXX Can we still do this now that we store mCharset
|
|
|
|
// on the font family rather than the font entry?
|
|
|
|
ff->mCharset.set(metrics.tmCharSet);
|
2018-10-13 01:16:45 +03:00
|
|
|
return 1;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-03 14:42:07 +04:00
|
|
|
// We can't set the hasItalicFace flag correctly here,
|
|
|
|
// because we might not have seen the family's italic face(s) yet.
|
2012-12-12 18:09:50 +04:00
|
|
|
// So we'll set that flag for all members after loading all the faces.
|
2018-04-23 17:52:20 +03:00
|
|
|
auto italicStyle = (logFont.lfItalic == 0xFF ?
|
|
|
|
FontSlantStyle::Italic() : FontSlantStyle::Normal());
|
2018-09-12 22:34:57 +03:00
|
|
|
fe = GDIFontEntry::CreateFontEntry(NS_ConvertUTF16toUTF8(lpelfe->elfFullName),
|
2018-04-25 09:18:23 +03:00
|
|
|
feType, SlantStyleRange(italicStyle),
|
|
|
|
WeightRange(FontWeight(int32_t(logFont.lfWeight))),
|
|
|
|
StretchRange(FontStretch::Normal()),
|
2017-11-23 22:38:17 +03:00
|
|
|
nullptr);
|
2009-10-07 18:13:40 +04:00
|
|
|
if (!fe)
|
|
|
|
return 1;
|
|
|
|
|
2011-01-27 06:05:55 +03:00
|
|
|
ff->AddFontEntry(fe);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
if (nmetrics->ntmFontSig.fsUsb[0] != 0x00000000 &&
|
|
|
|
nmetrics->ntmFontSig.fsUsb[1] != 0x00000000 &&
|
|
|
|
nmetrics->ntmFontSig.fsUsb[2] != 0x00000000 &&
|
|
|
|
nmetrics->ntmFontSig.fsUsb[3] != 0x00000000) {
|
|
|
|
|
|
|
|
// set the unicode ranges
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t x = 0;
|
|
|
|
for (uint32_t i = 0; i < 4; ++i) {
|
2009-10-07 18:13:40 +04:00
|
|
|
DWORD range = nmetrics->ntmFontSig.fsUsb[i];
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t k = 0; k < 32; ++k) {
|
2010-01-15 00:31:06 +03:00
|
|
|
fe->mUnicodeRanges.set(x++, (range & (1 << k)) != 0);
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-21 19:44:33 +03:00
|
|
|
if (LOG_FONTLIST_ENABLED()) {
|
|
|
|
LOG_FONTLIST(("(fontlist) added (%s) to family (%s)"
|
2018-04-25 09:18:23 +03:00
|
|
|
" with style: %s weight: %d stretch: normal",
|
2018-09-12 22:34:57 +03:00
|
|
|
fe->Name().get(),
|
|
|
|
ff->Name().get(),
|
2009-10-07 18:13:40 +04:00
|
|
|
(logFont.lfItalic == 0xff) ? "italic" : "normal",
|
2018-04-25 09:18:23 +03:00
|
|
|
logFont.lfWeight));
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-01-29 11:39:01 +04:00
|
|
|
GDIFontFamily::FindStyleVariations(FontInfoData *aFontInfoData)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
|
|
|
if (mHasStyles)
|
|
|
|
return;
|
2011-10-17 18:59:28 +04:00
|
|
|
mHasStyles = true;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
HDC hdc = GetDC(nullptr);
|
2009-10-07 18:13:40 +04:00
|
|
|
SetGraphicsMode(hdc, GM_ADVANCED);
|
|
|
|
|
|
|
|
LOGFONTW logFont;
|
|
|
|
memset(&logFont, 0, sizeof(LOGFONTW));
|
|
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
logFont.lfPitchAndFamily = 0;
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF8toUTF16 name(mName);
|
|
|
|
uint32_t l = std::min<uint32_t>(name.Length(), LF_FACESIZE - 1);
|
|
|
|
memcpy(logFont.lfFaceName, name.get(), l * sizeof(char16_t));
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
EnumFontFamiliesExW(hdc, &logFont,
|
|
|
|
(FONTENUMPROCW)GDIFontFamily::FamilyAddStylesProc,
|
|
|
|
(LPARAM)this, 0);
|
2011-01-21 19:44:33 +03:00
|
|
|
if (LOG_FONTLIST_ENABLED() && mAvailableFonts.Length() == 0) {
|
|
|
|
LOG_FONTLIST(("(fontlist) no styles available in family \"%s\"",
|
2018-09-12 22:34:57 +03:00
|
|
|
mName.get()));
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
ReleaseDC(nullptr, hdc);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2012-12-12 18:09:50 +04:00
|
|
|
if (mIsBadUnderlineFamily) {
|
2009-10-07 18:13:40 +04:00
|
|
|
SetBadUnderlineFonts();
|
2012-12-12 18:09:50 +04:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************
|
|
|
|
*
|
|
|
|
* gfxGDIFontList
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
gfxGDIFontList::gfxGDIFontList()
|
2014-08-06 17:31:21 +04:00
|
|
|
: mFontSubstitutes(32)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
2014-05-29 16:00:59 +04:00
|
|
|
#ifdef MOZ_BUNDLED_FONTS
|
|
|
|
ActivateBundledFonts();
|
|
|
|
#endif
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
RemoveCharsetFromFontSubstitute(nsAString &aName)
|
|
|
|
{
|
2014-01-04 19:02:17 +04:00
|
|
|
int32_t comma = aName.FindChar(char16_t(','));
|
2009-10-07 18:13:40 +04:00
|
|
|
if (comma >= 0)
|
|
|
|
aName.Truncate(comma);
|
|
|
|
}
|
|
|
|
|
2011-01-21 19:44:32 +03:00
|
|
|
#define MAX_VALUE_NAME 512
|
|
|
|
#define MAX_VALUE_DATA 512
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
nsresult
|
|
|
|
gfxGDIFontList::GetFontSubstitutes()
|
|
|
|
{
|
2011-01-21 19:44:32 +03:00
|
|
|
HKEY hKey;
|
|
|
|
DWORD i, rv, lenAlias, lenActual, valueType;
|
|
|
|
WCHAR aliasName[MAX_VALUE_NAME];
|
|
|
|
WCHAR actualName[MAX_VALUE_DATA];
|
|
|
|
|
2018-10-13 01:16:45 +03:00
|
|
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
2011-01-21 19:44:32 +03:00
|
|
|
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes",
|
|
|
|
0, KEY_READ, &hKey) != ERROR_SUCCESS)
|
|
|
|
{
|
2009-10-07 18:13:40 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2011-01-21 19:44:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, rv = ERROR_SUCCESS; rv != ERROR_NO_MORE_ITEMS; i++) {
|
|
|
|
aliasName[0] = 0;
|
2011-10-11 09:50:08 +04:00
|
|
|
lenAlias = ArrayLength(aliasName);
|
2011-01-21 19:44:32 +03:00
|
|
|
actualName[0] = 0;
|
|
|
|
lenActual = sizeof(actualName);
|
2013-07-31 19:44:31 +04:00
|
|
|
rv = RegEnumValueW(hKey, i, aliasName, &lenAlias, nullptr, &valueType,
|
2011-01-21 19:44:32 +03:00
|
|
|
(LPBYTE)actualName, &lenActual);
|
|
|
|
|
|
|
|
if (rv != ERROR_SUCCESS || valueType != REG_SZ || lenAlias == 0) {
|
2009-10-07 18:13:40 +04:00
|
|
|
continue;
|
2011-01-21 19:44:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (aliasName[0] == WCHAR('@')) {
|
2009-10-07 18:13:40 +04:00
|
|
|
continue;
|
2011-01-21 19:44:32 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
nsAutoString substituteName((char16_t*) aliasName);
|
|
|
|
nsAutoString actualFontName((char16_t*) actualName);
|
2009-10-07 18:13:40 +04:00
|
|
|
RemoveCharsetFromFontSubstitute(substituteName);
|
|
|
|
BuildKeyNameFromFontName(substituteName);
|
|
|
|
RemoveCharsetFromFontSubstitute(actualFontName);
|
|
|
|
BuildKeyNameFromFontName(actualFontName);
|
|
|
|
gfxFontFamily *ff;
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 substitute(substituteName);
|
|
|
|
NS_ConvertUTF16toUTF8 actual(actualFontName);
|
2018-10-13 01:16:45 +03:00
|
|
|
if (!actual.IsEmpty() &&
|
2018-09-12 22:34:57 +03:00
|
|
|
(ff = mFontFamilies.GetWeak(actual))) {
|
|
|
|
mFontSubstitutes.Put(substitute, ff);
|
2009-10-07 18:13:40 +04:00
|
|
|
} else {
|
2018-09-12 22:34:57 +03:00
|
|
|
mNonExistingFonts.AppendElement(substitute);
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
}
|
2011-10-28 17:58:49 +04:00
|
|
|
|
|
|
|
// "Courier" on a default Windows install is an ugly bitmap font.
|
|
|
|
// If there is no substitution for Courier in the registry
|
|
|
|
// substitute "Courier" with "Courier New".
|
|
|
|
nsAutoString substituteName;
|
|
|
|
substituteName.AssignLiteral("Courier");
|
|
|
|
BuildKeyNameFromFontName(substituteName);
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 substitute(substituteName);
|
|
|
|
if (!mFontSubstitutes.GetWeak(substitute)) {
|
2011-10-28 17:58:49 +04:00
|
|
|
gfxFontFamily *ff;
|
|
|
|
nsAutoString actualFontName;
|
|
|
|
actualFontName.AssignLiteral("Courier New");
|
|
|
|
BuildKeyNameFromFontName(actualFontName);
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 actual(actualFontName);
|
|
|
|
ff = mFontFamilies.GetWeak(actual);
|
2011-10-28 17:58:49 +04:00
|
|
|
if (ff) {
|
2018-09-12 22:34:57 +03:00
|
|
|
mFontSubstitutes.Put(substitute, ff);
|
2011-10-28 17:58:49 +04:00
|
|
|
}
|
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-11-08 14:02:27 +03:00
|
|
|
nsresult
|
2016-08-23 03:06:07 +03:00
|
|
|
gfxGDIFontList::InitFontListForPlatform()
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
2011-07-27 10:42:53 +04:00
|
|
|
Telemetry::AutoTimer<Telemetry::GDI_INITFONTLIST_TOTAL> timer;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
mFontSubstitutes.Clear();
|
|
|
|
mNonExistingFonts.Clear();
|
|
|
|
|
|
|
|
// iterate over available families
|
|
|
|
LOGFONTW logfont;
|
|
|
|
memset(&logfont, 0, sizeof(logfont));
|
|
|
|
logfont.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
|
|
|
|
AutoDC hdc;
|
2018-10-13 01:21:40 +03:00
|
|
|
(void)EnumFontFamiliesExW(hdc.GetDC(), &logfont,
|
|
|
|
(FONTENUMPROCW)&EnumFontFamExProc, 0, 0);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
GetFontSubstitutes();
|
|
|
|
|
2013-04-26 11:40:44 +04:00
|
|
|
GetPrefsAndStartLoader();
|
2010-11-08 14:02:27 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2010-11-08 14:02:27 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
int CALLBACK
|
|
|
|
gfxGDIFontList::EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe,
|
|
|
|
NEWTEXTMETRICEXW *lpntme,
|
|
|
|
DWORD fontType,
|
|
|
|
LPARAM lParam)
|
|
|
|
{
|
2017-09-11 21:22:15 +03:00
|
|
|
const NEWTEXTMETRICW& metrics = lpntme->ntmTm;
|
2009-10-07 18:13:40 +04:00
|
|
|
const LOGFONTW& lf = lpelfe->elfLogFont;
|
|
|
|
|
|
|
|
if (lf.lfFaceName[0] == '@') {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString name(lf.lfFaceName);
|
|
|
|
BuildKeyNameFromFontName(name);
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 key(name);
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
gfxGDIFontList *fontList = PlatformFontList();
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
if (!fontList->mFontFamilies.GetWeak(key)) {
|
|
|
|
NS_ConvertUTF16toUTF8 faceName(lf.lfFaceName);
|
2017-09-11 21:22:15 +03:00
|
|
|
RefPtr<GDIFontFamily> family = new GDIFontFamily(faceName);
|
2018-09-12 22:34:57 +03:00
|
|
|
fontList->mFontFamilies.Put(key, family);
|
2011-01-07 15:29:49 +03:00
|
|
|
|
|
|
|
// if locale is such that CJK font names are the default coming from
|
|
|
|
// GDI, then if a family name is non-ASCII immediately read in other
|
|
|
|
// family names. This assures that MS Gothic, MS Mincho are all found
|
|
|
|
// before lookups begin.
|
|
|
|
if (!IsASCII(faceName)) {
|
|
|
|
family->ReadOtherFamilyNames(gfxPlatformFontList::PlatformFontList());
|
|
|
|
}
|
|
|
|
|
2018-11-15 19:11:45 +03:00
|
|
|
if (fontList->mBadUnderlineFamilyNames.ContainsSorted(key)) {
|
2010-01-28 09:56:16 +03:00
|
|
|
family->SetBadUnderlineFamily();
|
2018-11-15 19:11:45 +03:00
|
|
|
}
|
2017-09-11 21:22:15 +03:00
|
|
|
|
|
|
|
family->mWindowsFamily = lf.lfPitchAndFamily & 0xF0;
|
|
|
|
family->mWindowsPitch = lf.lfPitchAndFamily & 0x0F;
|
|
|
|
|
|
|
|
// mark the charset bit
|
|
|
|
family->mCharset.set(metrics.tmCharSet);
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-10-13 01:16:45 +03:00
|
|
|
gfxFontEntry*
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxGDIFontList::LookupLocalFont(const nsACString& aFontName,
|
2018-04-25 09:18:23 +03:00
|
|
|
WeightRange aWeightForEntry,
|
|
|
|
StretchRange aStretchForEntry,
|
|
|
|
SlantStyleRange aStyleForEntry)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
2010-01-29 04:41:25 +03:00
|
|
|
gfxFontEntry *lookup;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2014-09-08 11:23:19 +04:00
|
|
|
lookup = LookupInFaceNameLists(aFontName);
|
2014-04-23 09:20:20 +04:00
|
|
|
if (!lookup) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2010-01-29 04:41:25 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isCFF = false; // jtdfix -- need to determine this
|
2018-10-13 01:16:45 +03:00
|
|
|
|
2010-01-29 04:41:25 +03:00
|
|
|
// use the face name from the lookup font entry, which will be the localized
|
|
|
|
// face name which GDI mapping tables use (e.g. with the system locale set to
|
|
|
|
// Dutch, a fullname of 'Arial Bold' will find a font entry with the face name
|
|
|
|
// 'Arial Vet' which can be used as a key in GDI font lookups).
|
2018-10-13 01:16:45 +03:00
|
|
|
GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(lookup->Name(),
|
|
|
|
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
|
2018-04-25 09:18:23 +03:00
|
|
|
lookup->SlantStyle(), lookup->Weight(), aStretchForEntry, nullptr);
|
2015-10-19 05:16:43 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
if (!fe)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
fe->mIsLocalUserFont = true;
|
2012-06-28 13:59:37 +04:00
|
|
|
|
2014-09-08 11:23:20 +04:00
|
|
|
// make the new font entry match the userfont entry style characteristics
|
2018-04-25 09:18:23 +03:00
|
|
|
fe->mWeightRange = aWeightForEntry;
|
|
|
|
fe->mStyleRange = aStyleForEntry;
|
|
|
|
fe->mStretchRange = aStretchForEntry;
|
2012-06-28 13:59:37 +04:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
return fe;
|
|
|
|
}
|
|
|
|
|
2016-08-18 19:22:45 +03:00
|
|
|
// If aFontData contains only a MS/Symbol cmap subtable, not MS/Unicode,
|
|
|
|
// we modify the subtable header to mark it as Unicode instead, because
|
|
|
|
// otherwise GDI will refuse to load the font.
|
|
|
|
// NOTE that this function does not bounds-check every access to the font data.
|
|
|
|
// This is OK because we only use it on data that has already been validated
|
|
|
|
// by OTS, and therefore we will not hit out-of-bounds accesses here.
|
|
|
|
static bool
|
|
|
|
FixupSymbolEncodedFont(uint8_t* aFontData, uint32_t aLength)
|
|
|
|
{
|
|
|
|
struct CmapHeader {
|
|
|
|
AutoSwap_PRUint16 version;
|
|
|
|
AutoSwap_PRUint16 numTables;
|
|
|
|
};
|
|
|
|
struct CmapEncodingRecord {
|
|
|
|
AutoSwap_PRUint16 platformID;
|
|
|
|
AutoSwap_PRUint16 encodingID;
|
|
|
|
AutoSwap_PRUint32 offset;
|
|
|
|
};
|
|
|
|
const uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
|
|
|
const TableDirEntry* dir =
|
|
|
|
gfxFontUtils::FindTableDirEntry(aFontData, kCMAP);
|
|
|
|
if (dir && uint32_t(dir->length) >= sizeof(CmapHeader)) {
|
|
|
|
CmapHeader *cmap =
|
|
|
|
reinterpret_cast<CmapHeader*>(aFontData + uint32_t(dir->offset));
|
|
|
|
CmapEncodingRecord *encRec =
|
|
|
|
reinterpret_cast<CmapEncodingRecord*>(cmap + 1);
|
|
|
|
int32_t symbolSubtable = -1;
|
|
|
|
for (uint32_t i = 0; i < (uint16_t)cmap->numTables; ++i) {
|
|
|
|
if (uint16_t(encRec[i].platformID) !=
|
|
|
|
gfxFontUtils::PLATFORM_ID_MICROSOFT) {
|
|
|
|
continue; // only interested in MS platform
|
|
|
|
}
|
|
|
|
if (uint16_t(encRec[i].encodingID) ==
|
|
|
|
gfxFontUtils::ENCODING_ID_MICROSOFT_UNICODEBMP) {
|
|
|
|
// We've got a Microsoft/Unicode table, so don't interfere.
|
|
|
|
symbolSubtable = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (uint16_t(encRec[i].encodingID) ==
|
|
|
|
gfxFontUtils::ENCODING_ID_MICROSOFT_SYMBOL) {
|
|
|
|
// Found a symbol subtable; remember it for possible fixup,
|
|
|
|
// but if we subsequently find a Microsoft/Unicode subtable,
|
|
|
|
// we'll cancel this.
|
|
|
|
symbolSubtable = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (symbolSubtable != -1) {
|
|
|
|
// We found a windows/symbol cmap table, and no windows/unicode one;
|
|
|
|
// change the encoding ID so that AddFontMemResourceEx will accept it
|
|
|
|
encRec[symbolSubtable].encodingID =
|
|
|
|
gfxFontUtils::ENCODING_ID_MICROSOFT_UNICODEBMP;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-09-08 11:23:19 +04:00
|
|
|
gfxFontEntry*
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxGDIFontList::MakePlatformFont(const nsACString& aFontName,
|
2018-04-25 09:18:23 +03:00
|
|
|
WeightRange aWeightForEntry,
|
|
|
|
StretchRange aStretchForEntry,
|
|
|
|
SlantStyleRange aStyleForEntry,
|
2014-09-08 11:23:19 +04:00
|
|
|
const uint8_t* aFontData,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aLength)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
2015-04-01 08:29:55 +03:00
|
|
|
// MakePlatformFont is responsible for deleting the font data with free
|
2009-10-07 18:13:40 +04:00
|
|
|
// so we set up a stack object to ensure it is freed even if we take an
|
|
|
|
// early exit
|
|
|
|
struct FontDataDeleter {
|
2016-12-16 10:54:32 +03:00
|
|
|
explicit FontDataDeleter(const uint8_t* aFontData)
|
2009-10-07 18:13:40 +04:00
|
|
|
: mFontData(aFontData) { }
|
2015-04-01 08:29:55 +03:00
|
|
|
~FontDataDeleter() { free((void*)mFontData); }
|
2012-08-22 19:56:38 +04:00
|
|
|
const uint8_t *mFontData;
|
2009-10-07 18:13:40 +04:00
|
|
|
};
|
|
|
|
FontDataDeleter autoDelete(aFontData);
|
|
|
|
|
2013-07-09 05:40:03 +04:00
|
|
|
bool isCFF = gfxFontUtils::IsCffFont(aFontData);
|
2011-03-24 23:11:38 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
nsresult rv;
|
2012-07-30 18:20:58 +04:00
|
|
|
HANDLE fontRef = nullptr;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
nsAutoString uniqueName;
|
|
|
|
rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName);
|
|
|
|
if (NS_FAILED(rv))
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2013-07-09 05:40:03 +04:00
|
|
|
FallibleTArray<uint8_t> newFontData;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2013-07-09 05:40:03 +04:00
|
|
|
rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2013-07-09 05:40:03 +04:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return nullptr;
|
2018-10-13 01:16:45 +03:00
|
|
|
|
2013-07-09 05:40:03 +04:00
|
|
|
DWORD numFonts = 0;
|
|
|
|
|
|
|
|
uint8_t *fontData = reinterpret_cast<uint8_t*> (newFontData.Elements());
|
|
|
|
uint32_t fontLength = newFontData.Length();
|
|
|
|
NS_ASSERTION(fontData, "null font data after renaming");
|
|
|
|
|
|
|
|
// http://msdn.microsoft.com/en-us/library/ms533942(VS.85).aspx
|
2018-10-13 01:16:45 +03:00
|
|
|
// "A font that is added by AddFontMemResourceEx is always private
|
2013-07-09 05:40:03 +04:00
|
|
|
// to the process that made the call and is not enumerable."
|
2018-10-13 01:16:45 +03:00
|
|
|
fontRef = AddFontMemResourceEx(fontData, fontLength,
|
2013-07-09 05:40:03 +04:00
|
|
|
0 /* reserved */, &numFonts);
|
2016-08-18 19:22:45 +03:00
|
|
|
if (!fontRef) {
|
|
|
|
if (FixupSymbolEncodedFont(fontData, fontLength)) {
|
|
|
|
fontRef = AddFontMemResourceEx(fontData, fontLength, 0, &numFonts);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!fontRef) {
|
2013-07-09 05:40:03 +04:00
|
|
|
return nullptr;
|
2016-08-18 19:22:45 +03:00
|
|
|
}
|
2013-07-09 05:40:03 +04:00
|
|
|
|
|
|
|
// only load fonts with a single face contained in the data
|
|
|
|
// AddFontMemResourceEx generates an additional face name for
|
|
|
|
// vertical text if the font supports vertical writing but since
|
|
|
|
// the font is referenced via the name this can be ignored
|
|
|
|
if (fontRef && numFonts > 2) {
|
|
|
|
RemoveFontMemResourceEx(fontRef);
|
|
|
|
return nullptr;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// make a new font entry using the unique name
|
2013-07-09 05:40:03 +04:00
|
|
|
WinUserFontData *winUserFontData = new WinUserFontData(fontRef);
|
2018-09-12 22:34:57 +03:00
|
|
|
GDIFontEntry *fe = GDIFontEntry::CreateFontEntry(NS_ConvertUTF16toUTF8(uniqueName),
|
2015-10-19 05:16:43 +03:00
|
|
|
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
|
2018-04-25 09:18:23 +03:00
|
|
|
aStyleForEntry, aWeightForEntry, aStretchForEntry, winUserFontData);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2017-01-10 08:21:40 +03:00
|
|
|
if (fe) {
|
|
|
|
fe->mIsDataUserFont = true;
|
2010-07-17 05:32:18 +04:00
|
|
|
}
|
2013-11-22 07:35:40 +04:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
return fe;
|
|
|
|
}
|
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
bool
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxGDIFontList::FindAndAddFamilies(const nsACString& aFamily,
|
2018-05-25 16:07:57 +03:00
|
|
|
nsTArray<FamilyAndGeneric>* aOutput,
|
2017-08-01 13:25:35 +03:00
|
|
|
FindFamiliesFlags aFlags,
|
2016-04-12 09:06:22 +03:00
|
|
|
gfxFontStyle* aStyle,
|
|
|
|
gfxFloat aDevToCssSize)
|
2014-06-06 10:09:23 +04:00
|
|
|
{
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF8toUTF16 key16(aFamily);
|
|
|
|
BuildKeyNameFromFontName(key16);
|
|
|
|
NS_ConvertUTF16toUTF8 keyName(key16);
|
2014-06-06 10:09:23 +04:00
|
|
|
|
|
|
|
gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
|
|
|
|
if (ff) {
|
2018-05-25 16:07:57 +03:00
|
|
|
aOutput->AppendElement(FamilyAndGeneric(ff));
|
2016-04-12 09:06:22 +03:00
|
|
|
return true;
|
2014-06-06 10:09:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mNonExistingFonts.Contains(keyName)) {
|
2016-04-12 09:06:22 +03:00
|
|
|
return false;
|
2014-06-06 10:09:23 +04:00
|
|
|
}
|
|
|
|
|
2017-08-03 03:33:00 +03:00
|
|
|
return gfxPlatformFontList::FindAndAddFamilies(aFamily,
|
|
|
|
aOutput,
|
2017-08-01 13:25:35 +03:00
|
|
|
aFlags,
|
2017-08-03 03:33:00 +03:00
|
|
|
aStyle,
|
2016-04-12 09:06:22 +03:00
|
|
|
aDevToCssSize);
|
2014-06-06 10:09:23 +04:00
|
|
|
}
|
|
|
|
|
2012-12-19 13:42:25 +04:00
|
|
|
gfxFontFamily*
|
2016-08-23 03:06:07 +03:00
|
|
|
gfxGDIFontList::GetDefaultFontForPlatform(const gfxFontStyle* aStyle)
|
2009-10-07 18:13:40 +04:00
|
|
|
{
|
2014-06-06 10:09:23 +04:00
|
|
|
gfxFontFamily *ff = nullptr;
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
// this really shouldn't fail to find a font....
|
|
|
|
NONCLIENTMETRICSW ncm;
|
|
|
|
ncm.cbSize = sizeof(ncm);
|
2018-10-13 01:16:45 +03:00
|
|
|
BOOL status = ::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
|
2009-10-07 18:13:40 +04:00
|
|
|
sizeof(ncm), &ncm, 0);
|
|
|
|
if (status) {
|
2018-09-12 22:34:57 +03:00
|
|
|
ff = FindFamily(NS_ConvertUTF16toUTF8(ncm.lfMessageFont.lfFaceName));
|
2015-01-22 01:12:18 +03:00
|
|
|
if (ff) {
|
|
|
|
return ff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ...but just in case, try another (long-deprecated) approach as well
|
|
|
|
HGDIOBJ hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
|
|
|
|
LOGFONTW logFont;
|
|
|
|
if (hGDI && ::GetObjectW(hGDI, sizeof(logFont), &logFont)) {
|
2018-09-12 22:34:57 +03:00
|
|
|
ff = FindFamily(NS_ConvertUTF16toUTF8(logFont.lfFaceName));
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2014-06-06 10:09:23 +04:00
|
|
|
return ff;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2012-03-28 01:38:39 +04:00
|
|
|
|
|
|
|
void
|
2013-10-15 06:19:47 +04:00
|
|
|
gfxGDIFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
|
|
|
FontListSizes* aSizes) const
|
2012-03-28 01:38:39 +04:00
|
|
|
{
|
2013-10-15 06:19:47 +04:00
|
|
|
gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
2012-03-28 01:38:39 +04:00
|
|
|
aSizes->mFontListSize +=
|
2015-07-31 07:19:57 +03:00
|
|
|
SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf);
|
2012-03-28 01:38:39 +04:00
|
|
|
aSizes->mFontListSize +=
|
2015-07-29 09:24:24 +03:00
|
|
|
mNonExistingFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < mNonExistingFonts.Length(); ++i) {
|
2012-03-28 01:38:39 +04:00
|
|
|
aSizes->mFontListSize +=
|
|
|
|
mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-10-15 06:19:47 +04:00
|
|
|
gfxGDIFontList::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
|
|
|
|
FontListSizes* aSizes) const
|
2012-03-28 01:38:39 +04:00
|
|
|
{
|
|
|
|
aSizes->mFontListSize += aMallocSizeOf(this);
|
2013-10-15 06:19:47 +04:00
|
|
|
AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
|
2012-03-28 01:38:39 +04:00
|
|
|
}
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
// used to load system-wide font info on off-main thread
|
|
|
|
class GDIFontInfo : public FontInfoData {
|
|
|
|
public:
|
|
|
|
GDIFontInfo(bool aLoadOtherNames,
|
|
|
|
bool aLoadFaceNames,
|
|
|
|
bool aLoadCmaps) :
|
|
|
|
FontInfoData(aLoadOtherNames, aLoadFaceNames, aLoadCmaps)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~GDIFontInfo() {}
|
|
|
|
|
|
|
|
virtual void Load() {
|
|
|
|
mHdc = GetDC(nullptr);
|
|
|
|
SetGraphicsMode(mHdc, GM_ADVANCED);
|
|
|
|
FontInfoData::Load();
|
|
|
|
ReleaseDC(nullptr, mHdc);
|
|
|
|
}
|
|
|
|
|
|
|
|
// loads font data for all members of a given family
|
2018-09-12 22:34:57 +03:00
|
|
|
virtual void LoadFontFamilyData(const nsACString& aFamilyName);
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
// callback for GDI EnumFontFamiliesExW call
|
|
|
|
static int CALLBACK EnumerateFontsForFamily(const ENUMLOGFONTEXW *lpelfe,
|
|
|
|
const NEWTEXTMETRICEXW *nmetrics,
|
|
|
|
DWORD fontType, LPARAM data);
|
|
|
|
|
|
|
|
HDC mHdc;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EnumerateFontsForFamilyData {
|
2018-09-12 22:34:57 +03:00
|
|
|
EnumerateFontsForFamilyData(const nsACString& aFamilyName,
|
2014-01-29 11:39:01 +04:00
|
|
|
GDIFontInfo& aFontInfo)
|
|
|
|
: mFamilyName(aFamilyName), mFontInfo(aFontInfo)
|
|
|
|
{}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
nsCString mFamilyName;
|
|
|
|
nsTArray<nsCString> mOtherFamilyNames;
|
2014-01-29 11:39:01 +04:00
|
|
|
GDIFontInfo& mFontInfo;
|
2018-09-12 22:34:57 +03:00
|
|
|
nsCString mPreviousFontName;
|
2014-01-29 11:39:01 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
int CALLBACK GDIFontInfo::EnumerateFontsForFamily(
|
|
|
|
const ENUMLOGFONTEXW *lpelfe,
|
|
|
|
const NEWTEXTMETRICEXW *nmetrics,
|
|
|
|
DWORD fontType, LPARAM data)
|
|
|
|
{
|
|
|
|
EnumerateFontsForFamilyData *famData =
|
|
|
|
reinterpret_cast<EnumerateFontsForFamilyData*>(data);
|
|
|
|
HDC hdc = famData->mFontInfo.mHdc;
|
|
|
|
LOGFONTW logFont = lpelfe->elfLogFont;
|
|
|
|
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
|
|
|
|
|
|
|
AutoSelectFont font(hdc, &logFont);
|
|
|
|
if (!font.IsValid()) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
FontFaceData fontData;
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 fontName(lpelfe->elfFullName);
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
// callback called for each style-charset so return if style already seen
|
|
|
|
if (fontName.Equals(famData->mPreviousFontName)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
famData->mPreviousFontName = fontName;
|
|
|
|
famData->mFontInfo.mLoadStats.fonts++;
|
|
|
|
|
|
|
|
// read name table info
|
|
|
|
bool nameDataLoaded = false;
|
|
|
|
if (famData->mFontInfo.mLoadFaceNames || famData->mFontInfo.mLoadOtherNames) {
|
|
|
|
uint32_t kNAME =
|
|
|
|
NativeEndian::swapToBigEndian(TRUETYPE_TAG('n','a','m','e'));
|
|
|
|
uint32_t nameSize;
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<uint8_t, 1024> nameData;
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
nameSize = ::GetFontData(hdc, kNAME, 0, nullptr, 0);
|
|
|
|
if (nameSize != GDI_ERROR &&
|
|
|
|
nameSize > 0 &&
|
2015-06-11 00:30:41 +03:00
|
|
|
nameData.SetLength(nameSize, fallible)) {
|
2014-01-29 11:39:01 +04:00
|
|
|
::GetFontData(hdc, kNAME, 0, nameData.Elements(), nameSize);
|
|
|
|
|
|
|
|
// face names
|
|
|
|
if (famData->mFontInfo.mLoadFaceNames) {
|
|
|
|
gfxFontUtils::ReadCanonicalName((const char*)(nameData.Elements()), nameSize,
|
|
|
|
gfxFontUtils::NAME_ID_FULL,
|
|
|
|
fontData.mFullName);
|
|
|
|
gfxFontUtils::ReadCanonicalName((const char*)(nameData.Elements()), nameSize,
|
|
|
|
gfxFontUtils::NAME_ID_POSTSCRIPT,
|
|
|
|
fontData.mPostscriptName);
|
|
|
|
nameDataLoaded = true;
|
|
|
|
famData->mFontInfo.mLoadStats.facenames++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// other family names
|
|
|
|
if (famData->mFontInfo.mLoadOtherNames) {
|
|
|
|
gfxFontFamily::ReadOtherFamilyNamesForFace(famData->mFamilyName,
|
|
|
|
(const char*)(nameData.Elements()),
|
|
|
|
nameSize,
|
|
|
|
famData->mOtherFamilyNames,
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// read cmap
|
|
|
|
bool cmapLoaded = false;
|
|
|
|
gfxWindowsFontType feType =
|
|
|
|
GDIFontEntry::DetermineFontType(metrics, fontType);
|
|
|
|
if (famData->mFontInfo.mLoadCmaps &&
|
|
|
|
(feType == GFX_FONT_TYPE_PS_OPENTYPE ||
|
|
|
|
feType == GFX_FONT_TYPE_TT_OPENTYPE ||
|
|
|
|
feType == GFX_FONT_TYPE_TRUETYPE))
|
|
|
|
{
|
|
|
|
uint32_t kCMAP =
|
|
|
|
NativeEndian::swapToBigEndian(TRUETYPE_TAG('c','m','a','p'));
|
|
|
|
uint32_t cmapSize;
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<uint8_t, 1024> cmapData;
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
cmapSize = ::GetFontData(hdc, kCMAP, 0, nullptr, 0);
|
|
|
|
if (cmapSize != GDI_ERROR &&
|
|
|
|
cmapSize > 0 &&
|
2015-06-11 00:30:41 +03:00
|
|
|
cmapData.SetLength(cmapSize, fallible)) {
|
2014-01-29 11:39:01 +04:00
|
|
|
::GetFontData(hdc, kCMAP, 0, cmapData.Elements(), cmapSize);
|
|
|
|
bool cmapLoaded = false;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
2014-01-29 11:39:01 +04:00
|
|
|
uint32_t offset;
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(gfxFontUtils::ReadCMAP(cmapData.Elements(),
|
|
|
|
cmapSize, *charmap,
|
2017-09-11 21:23:30 +03:00
|
|
|
offset))) {
|
2014-01-29 11:39:01 +04:00
|
|
|
fontData.mCharacterMap = charmap;
|
|
|
|
fontData.mUVSOffset = offset;
|
|
|
|
cmapLoaded = true;
|
|
|
|
famData->mFontInfo.mLoadStats.cmaps++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmapLoaded || nameDataLoaded) {
|
|
|
|
famData->mFontInfo.mFontFaceData.Put(fontName, fontData);
|
|
|
|
}
|
|
|
|
|
2016-02-05 04:24:00 +03:00
|
|
|
return famData->mFontInfo.mCanceled ? 0 : 1;
|
2014-01-29 11:39:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-09-12 22:34:57 +03:00
|
|
|
GDIFontInfo::LoadFontFamilyData(const nsACString& aFamilyName)
|
2014-01-29 11:39:01 +04:00
|
|
|
{
|
|
|
|
// iterate over the family
|
|
|
|
LOGFONTW logFont;
|
|
|
|
memset(&logFont, 0, sizeof(LOGFONTW));
|
|
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
logFont.lfPitchAndFamily = 0;
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF8toUTF16 name(aFamilyName);
|
|
|
|
uint32_t l = std::min<uint32_t>(name.Length(), LF_FACESIZE - 1);
|
|
|
|
memcpy(logFont.lfFaceName, name.BeginReading(), l * sizeof(char16_t));
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
EnumerateFontsForFamilyData data(aFamilyName, *this);
|
|
|
|
|
|
|
|
EnumFontFamiliesExW(mHdc, &logFont,
|
|
|
|
(FONTENUMPROCW)GDIFontInfo::EnumerateFontsForFamily,
|
|
|
|
(LPARAM)(&data), 0);
|
|
|
|
|
|
|
|
// if found other names, insert them
|
|
|
|
if (data.mOtherFamilyNames.Length() != 0) {
|
|
|
|
mOtherFamilyNames.Put(aFamilyName, data.mOtherFamilyNames);
|
|
|
|
mLoadStats.othernames += data.mOtherFamilyNames.Length();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<FontInfoData>
|
|
|
|
gfxGDIFontList::CreateFontInfoData()
|
|
|
|
{
|
|
|
|
bool loadCmaps = !UsesSystemFallback() ||
|
|
|
|
gfxPlatform::GetPlatform()->UseCmapsDuringSystemFallback();
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<GDIFontInfo> fi =
|
2014-01-29 11:39:01 +04:00
|
|
|
new GDIFontInfo(true, NeedFullnamePostscriptNames(), loadCmaps);
|
|
|
|
|
|
|
|
return fi.forget();
|
|
|
|
}
|
2014-05-29 16:00:59 +04:00
|
|
|
|
2017-08-01 13:25:35 +03:00
|
|
|
gfxFontFamily*
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxGDIFontList::CreateFontFamily(const nsACString& aName) const
|
2017-08-01 13:25:35 +03:00
|
|
|
{
|
|
|
|
return new GDIFontFamily(aName);
|
|
|
|
}
|
|
|
|
|
2014-05-29 16:00:59 +04:00
|
|
|
#ifdef MOZ_BUNDLED_FONTS
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxGDIFontList::ActivateBundledFonts()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIFile> localDir;
|
|
|
|
nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(localDir));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (NS_FAILED(localDir->Append(NS_LITERAL_STRING("fonts")))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bool isDir;
|
|
|
|
if (NS_FAILED(localDir->IsDirectory(&isDir)) || !isDir) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-20 06:17:45 +03:00
|
|
|
nsCOMPtr<nsIDirectoryEnumerator> e;
|
2014-05-29 16:00:59 +04:00
|
|
|
rv = localDir->GetDirectoryEntries(getter_AddRefs(e));
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-20 06:17:45 +03:00
|
|
|
nsCOMPtr<nsIFile> file;
|
|
|
|
while (NS_SUCCEEDED(e->GetNextFile(getter_AddRefs(file))) && file) {
|
2016-01-05 13:08:56 +03:00
|
|
|
nsAutoString path;
|
|
|
|
if (NS_FAILED(file->GetPath(path))) {
|
2014-05-29 16:00:59 +04:00
|
|
|
continue;
|
|
|
|
}
|
2016-01-05 13:08:56 +03:00
|
|
|
AddFontResourceExW(path.get(), FR_PRIVATE, nullptr);
|
2014-05-29 16:00:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|