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-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), 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)
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-06-04 01:22:28 +03:00
|
|
|
#define LOG_CMAPDATA_ENABLED() \
|
2012-03-09 06:05:14 +04:00
|
|
|
MOZ_LOG_TEST(gfxPlatform::GetLog(eGfxLog_cmapdata), LogLevel::Debug)
|
2018-11-30 13:46:48 +03: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) : mFontRef(aFontRef) {}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
#endif
|
|
|
|
}
|
2016-08-17 01:41:12 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
HANDLE mFontRef;
|
|
|
|
};
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
BYTE 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, SlantStyleRange aStyle,
|
2018-04-25 09:18:23 +03:00
|
|
|
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() {
|
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;
|
2011-10-17 18:59:28 +04:00
|
|
|
if (IsType1()) mForceGDI = true;
|
2014-09-08 11:23:20 +04:00
|
|
|
mIsDataUserFont = aUserFontData != nullptr;
|
2018-11-30 13:46:48 +03: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
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
nsresult GDIFontEntry::ReadCMAP(FontInfoData* aFontInfoData) {
|
|
|
|
AUTO_PROFILER_LABEL("GDIFontEntry::ReadCMAP", OTHER);
|
2012-04-19 03:59:43 +04:00
|
|
|
|
|
|
|
// attempt this once, if errors occur leave a blank cmap
|
|
|
|
if (mCharacterMap) {
|
|
|
|
return NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
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) {
|
2012-04-19 03:59:43 +04:00
|
|
|
mCharacterMap = new gfxCharacterMap();
|
|
|
|
mCharacterMap->mBuildOnTheFly = true;
|
2010-06-25 16:43:10 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2012-04-19 03:59:43 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<gfxCharacterMap> charmap;
|
2012-04-19 03:59:43 +04:00
|
|
|
nsresult rv;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
if (aFontInfoData &&
|
2012-04-19 03:59:43 +04:00
|
|
|
(charmap = GetCMAPFromFontInfo(aFontInfoData, mUVSOffset))) {
|
|
|
|
rv = NS_OK;
|
2018-11-30 13:46:48 +03:00
|
|
|
} else {
|
2012-04-19 03:59:43 +04:00
|
|
|
uint32_t kCMAP = TRUETYPE_TAG('c', 'm', 'a', 'p');
|
|
|
|
charmap = new gfxCharacterMap();
|
|
|
|
AutoTArray<uint8_t, 16384> cmap;
|
2012-03-09 06:05:14 +04:00
|
|
|
rv = CopyFontTable(kCMAP, cmap);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-03-09 06:05:14 +04:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2012-04-19 03:59:43 +04:00
|
|
|
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(), *charmap,
|
|
|
|
mUVSOffset);
|
2012-03-09 06:05:14 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03: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);
|
2018-11-30 13:46:48 +03:00
|
|
|
} else {
|
2012-04-19 03:59:43 +04:00
|
|
|
// 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
|
2012-04-27 12:26:41 +04:00
|
|
|
mCharacterMap->mBuildOnTheFly = true;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2012-04-19 03:59:43 +04:00
|
|
|
LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d hash: %8.8x%s\n",
|
|
|
|
mName.get(), charmap->SizeOfIncludingThis(moz_malloc_size_of),
|
2015-10-18 08:24:48 +03:00
|
|
|
charmap->mHash, mCharacterMap == charmap ? " new" : ""));
|
2011-01-21 19:44:33 +03:00
|
|
|
if (LOG_CMAPDATA_ENABLED()) {
|
2012-03-09 06:05:14 +04:00
|
|
|
char prefix[256];
|
2016-08-17 01:41:12 +03:00
|
|
|
SprintfLiteral(prefix, "(cmapdata) name: %.220s", mName.get());
|
2012-04-19 03:59:43 +04:00
|
|
|
charmap->Dump(prefix, eGfxLog_cmapdata);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
gfxFont* GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle) {
|
|
|
|
return new gfxGDIFont(this, aFontStyle);
|
2009-10-07 19:26:58 +04:00
|
|
|
}
|
|
|
|
|
2016-02-02 18:36:30 +03:00
|
|
|
nsresult GDIFontEntry::CopyFontTable(uint32_t aTableTag,
|
2015-06-11 00:30:41 +03:00
|
|
|
nsTArray<uint8_t>& aBuffer) {
|
|
|
|
if (!IsTrueType()) {
|
2009-10-07 18:13:40 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
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 = ::GetFontData(
|
2013-04-24 11:40:33 +04:00
|
|
|
dc.GetDC(), 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;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
2010-06-11 23:14:38 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
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;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2017-04-07 00:41:02 +03:00
|
|
|
return unscaledFont.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GDIFontEntry::FillLogFont(LOGFONTW* aLogFont, 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));
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-04-07 00:41:02 +03:00
|
|
|
aLogFont->lfHeight = (LONG)-ROUND(aSize);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
if (aLogFont->lfHeight == 0) {
|
2009-10-07 18:13:40 +04:00
|
|
|
aLogFont->lfHeight = -1;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
// If a non-zero weight is passed in, use this to override the original
|
2017-04-07 00:41:02 +03:00
|
|
|
// weight in the entry's logfont. This is used to control synthetic bolding
|
|
|
|
// for installed families with no bold face, and for downloaded fonts
|
2012-02-14 12:24:26 +04:00
|
|
|
// (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;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2017-04-07 00:41:02 +03: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,
|
2012-02-14 12:24:26 +04:00
|
|
|
// 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;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2017-04-07 00:41:02 +03:00
|
|
|
}
|
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
#define MISSING_GLYPH \
|
|
|
|
0x1F // glyph index returned for missing characters
|
2009-10-07 18:13:40 +04:00
|
|
|
// on WinXP with .fon fonts, but not Type1 (.pfb)
|
|
|
|
|
|
|
|
bool GDIFontEntry::TestCharacterMap(uint32_t aCh) {
|
|
|
|
if (!mCharacterMap) {
|
2012-10-04 12:35:15 +04:00
|
|
|
ReadCMAP();
|
2009-10-07 18:13:40 +04:00
|
|
|
NS_ASSERTION(mCharacterMap, "failed to initialize a character map");
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
if (mCharacterMap->mBuildOnTheFly) {
|
|
|
|
if (aCh > 0xFFFF) return false;
|
|
|
|
|
|
|
|
// previous code was using the group style
|
|
|
|
gfxFontStyle fakeStyle;
|
|
|
|
if (!IsUpright()) {
|
|
|
|
fakeStyle.style = FontSlantStyle::Italic();
|
|
|
|
}
|
|
|
|
fakeStyle.weight = Weight().Min();
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
RefPtr<gfxFont> tempFont = FindOrMakeFont(&fakeStyle, nullptr);
|
|
|
|
if (!tempFont || !tempFont->Valid()) return false;
|
|
|
|
gfxGDIFont* font = static_cast<gfxGDIFont*>(tempFont.get());
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
HDC dc = GetDC((HWND) nullptr);
|
|
|
|
SetGraphicsMode(dc, GM_ADVANCED);
|
2009-10-07 18:13:40 +04:00
|
|
|
HFONT hfont = font->GetHFONT();
|
|
|
|
HFONT oldFont = (HFONT)SelectObject(dc, hfont);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
wchar_t str[1] = {(wchar_t)aCh};
|
2009-10-07 18:13:40 +04:00
|
|
|
WORD glyph[1];
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hasGlyph = false;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-02-14 12:24:26 +04:00
|
|
|
// Bug 573038 - in some cases GetGlyphIndicesW returns 0xFFFF for a
|
|
|
|
// missing glyph or 0x1F in other cases to indicate the "invalid"
|
|
|
|
// glyph. Map both cases to "not found"
|
2010-03-15 12:34:25 +03:00
|
|
|
if (IsType1() || mForceGDI) {
|
2012-02-14 12:24:26 +04: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 =
|
2012-02-14 12:24:26 +04:00
|
|
|
GetGlyphIndicesW(dc, str, 1, glyph, GGI_MARK_NONEXISTING_GLYPHS);
|
|
|
|
if (ret != GDI_ERROR && glyph[0] != 0xFFFF &&
|
2011-02-22 20:04:37 +03:00
|
|
|
(IsType1() || glyph[0] != MISSING_GLYPH)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
hasGlyph = true;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
} else {
|
2012-02-14 12:24:26 +04:00
|
|
|
// ScriptGetCMap works better than GetGlyphIndicesW
|
|
|
|
// for things like bitmap/vector fonts
|
|
|
|
SCRIPT_CACHE sc = nullptr;
|
|
|
|
HRESULT rv = ScriptGetCMap(dc, &sc, str, 1, 0, glyph);
|
|
|
|
if (rv == S_OK) hasGlyph = true;
|
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2011-02-22 20:04:37 +03:00
|
|
|
SelectObject(dc, oldFont);
|
2013-07-31 19:44:31 +04:00
|
|
|
ReleaseDC(nullptr, dc);
|
2010-06-25 16:43:10 +04:00
|
|
|
|
2012-04-19 03:59:43 +04:00
|
|
|
if (hasGlyph) {
|
|
|
|
mCharacterMap->set(aCh);
|
|
|
|
return true;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
} else {
|
2009-10-07 18:13:40 +04:00
|
|
|
// font had a cmap so simply check that
|
2012-04-19 03:59:43 +04:00
|
|
|
return mCharacterMap->test(aCh);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2018-10-13 01:16:45 +03:00
|
|
|
return false;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
void 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;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
// 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();
|
2018-11-30 13:46:48 +03: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-09-12 22:34:57 +03:00
|
|
|
GDIFontEntry* 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, aWeight,
|
2017-11-23 22:38:17 +03:00
|
|
|
aStretch, aUserFontData);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
|
|
|
return fe;
|
|
|
|
}
|
|
|
|
|
2013-10-15 06:19:47 +04:00
|
|
|
void 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
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
static bool 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) {
|
2017-03-29 12:38:41 +03:00
|
|
|
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
2011-10-28 22:33:28 +04:00
|
|
|
LOGFONTW logFont = lpelfe->elfLogFont;
|
2009-10-07 18:13:40 +04:00
|
|
|
GDIFontFamily* ff = reinterpret_cast<GDIFontFamily*>(data);
|
|
|
|
|
2017-03-29 12:38:41 +03:00
|
|
|
if (logFont.lfItalic && ShouldIgnoreItalicStyle(ff->mName)) {
|
|
|
|
return 1;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
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));
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
gfxWindowsFontType feType =
|
|
|
|
GDIFontEntry::DetermineFontType(metrics, fontType);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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());
|
2018-04-25 09:18:23 +03:00
|
|
|
if (feType > fe->mFontType) {
|
2009-10-07 18:13:40 +04:00
|
|
|
// if the new type is better than the old one, remove the old entries
|
2017-09-11 21:22:15 +03:00
|
|
|
ff->mAvailableFonts.RemoveElementAt(i);
|
2018-11-30 13:46:48 +03:00
|
|
|
--i;
|
2017-09-11 21:22:15 +03:00
|
|
|
} else if (feType < fe->mFontType) {
|
|
|
|
// otherwise if the new type is worse, skip it
|
2018-10-13 01:16:45 +03:00
|
|
|
return 1;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2018-04-23 17:52:20 +03:00
|
|
|
for (uint32_t i = 0; i < ff->mAvailableFonts.Length(); ++i) {
|
2018-09-12 22:34:57 +03: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)) &&
|
2009-10-07 18:13:40 +04:00
|
|
|
fe->IsItalic() == (logFont.lfItalic == 0xFF)) {
|
|
|
|
// update the charset bit here since this could be different
|
|
|
|
// XXX Can we still do this now that we store mCharset
|
|
|
|
// on the font family rather than the font entry?
|
2010-01-15 00:31:06 +03:00
|
|
|
ff->mCharset.set(metrics.tmCharSet);
|
2017-03-29 12:38:41 +03:00
|
|
|
return 1;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2011-01-21 19:44:33 +03:00
|
|
|
// We can't set the hasItalicFace flag correctly here,
|
2018-04-25 09:18:23 +03:00
|
|
|
// because we might not have seen the family's italic face(s) yet.
|
|
|
|
// So we'll set that flag for all members after loading all the faces.
|
2009-10-07 18:13:40 +04:00
|
|
|
auto italicStyle = (logFont.lfItalic == 0xFF ? FontSlantStyle::Italic()
|
|
|
|
: FontSlantStyle::Normal());
|
2018-10-13 01:16:45 +03:00
|
|
|
fe = GDIFontEntry::CreateFontEntry(
|
2009-10-07 18:13:40 +04:00
|
|
|
NS_ConvertUTF16toUTF8(lpelfe->elfFullName), feType,
|
2018-04-25 09:18:23 +03:00
|
|
|
SlantStyleRange(italicStyle),
|
|
|
|
WeightRange(FontWeight(int32_t(logFont.lfWeight))),
|
|
|
|
StretchRange(FontStretch::Normal()), nullptr);
|
2017-03-29 12:38:41 +03:00
|
|
|
if (!fe) return 1;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2011-01-27 06:05:55 +03:00
|
|
|
ff->AddFontEntry(fe);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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) {
|
2016-08-18 19:22:45 +03:00
|
|
|
// 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) {
|
2018-04-25 09:18:23 +03:00
|
|
|
fe->mUnicodeRanges.set(x++, (range & (1 << k)) != 0);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03: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(),
|
2015-10-19 05:16:43 +03:00
|
|
|
(logFont.lfItalic == 0xff) ? "italic" : "normal", logFont.lfWeight));
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
void 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;
|
2018-11-30 13:46:48 +03: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);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
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));
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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\"", mName.get()));
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
ReleaseDC(nullptr, hdc);
|
2018-11-30 13:46:48 +03: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() : mFontSubstitutes(32) {
|
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;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2011-01-21 19:44:32 +03:00
|
|
|
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-10-28 17:58:49 +04:00
|
|
|
|
|
|
|
nsAutoString substituteName((char16_t*)aliasName);
|
|
|
|
nsAutoString actualFontName((char16_t*)actualName);
|
|
|
|
RemoveCharsetFromFontSubstitute(substituteName);
|
|
|
|
BuildKeyNameFromFontName(substituteName);
|
2009-10-07 18:13:40 +04:00
|
|
|
RemoveCharsetFromFontSubstitute(actualFontName);
|
|
|
|
BuildKeyNameFromFontName(actualFontName);
|
|
|
|
gfxFontFamily* ff;
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 substitute(substituteName);
|
|
|
|
NS_ConvertUTF16toUTF8 actual(actualFontName);
|
|
|
|
if (!actual.IsEmpty() && (ff = mFontFamilies.GetWeak(actual))) {
|
|
|
|
mFontSubstitutes.Put(substitute, ff);
|
2011-10-28 17:58:49 +04:00
|
|
|
} else {
|
2018-09-12 22:34:57 +03:00
|
|
|
mNonExistingFonts.AppendElement(substitute);
|
2011-10-28 17:58:49 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03: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".
|
2014-01-04 19:02:17 +04:00
|
|
|
nsAutoString substituteName;
|
2011-10-28 17:58:49 +04:00
|
|
|
substituteName.AssignLiteral("Courier");
|
2009-10-07 18:13:40 +04:00
|
|
|
BuildKeyNameFromFontName(substituteName);
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 substitute(substituteName);
|
|
|
|
if (!mFontSubstitutes.GetWeak(substitute)) {
|
2009-10-07 18:13:40 +04:00
|
|
|
gfxFontFamily* ff;
|
2011-10-28 17:58:49 +04:00
|
|
|
nsAutoString actualFontName;
|
|
|
|
actualFontName.AssignLiteral("Courier New");
|
2009-10-07 18:13:40 +04:00
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-08-23 03:06:07 +03:00
|
|
|
nsresult gfxGDIFontList::InitFontListForPlatform() {
|
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;
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
if (lf.lfFaceName[0] == '@') {
|
|
|
|
return 1;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2018-09-12 22:34:57 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
nsAutoString name(lf.lfFaceName);
|
|
|
|
BuildKeyNameFromFontName(name);
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 key(name);
|
2011-01-07 15:29:49 +03:00
|
|
|
|
|
|
|
gfxGDIFontList* fontList = PlatformFontList();
|
|
|
|
|
2018-11-15 19:11:45 +03:00
|
|
|
if (!fontList->mFontFamilies.GetWeak(key)) {
|
|
|
|
NS_ConvertUTF16toUTF8 faceName(lf.lfFaceName);
|
2010-01-28 09:56:16 +03:00
|
|
|
RefPtr<GDIFontFamily> family = new GDIFontFamily(faceName);
|
|
|
|
fontList->mFontFamilies.Put(key, family);
|
2017-09-11 21:22:15 +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
|
2011-01-07 15:29:49 +03:00
|
|
|
// before lookups begin.
|
|
|
|
if (!IsASCII(faceName)) {
|
2017-09-11 21:22:15 +03:00
|
|
|
family->ReadOtherFamilyNames(gfxPlatformFontList::PlatformFontList());
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2017-09-11 21:22:15 +03:00
|
|
|
|
|
|
|
if (fontList->mBadUnderlineFamilyNames.ContainsSorted(key)) {
|
|
|
|
family->SetBadUnderlineFamily();
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
|
|
|
|
2017-09-11 21:22:15 +03:00
|
|
|
family->mWindowsFamily = lf.lfPitchAndFamily & 0xF0;
|
|
|
|
family->mWindowsPitch = lf.lfPitchAndFamily & 0x0F;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-09-11 21:22:15 +03:00
|
|
|
// mark the charset bit
|
|
|
|
family->mCharset.set(metrics.tmCharSet);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxFontEntry* gfxGDIFontList::LookupLocalFont(const nsACString& aFontName,
|
2018-04-25 09:18:23 +03:00
|
|
|
WeightRange aWeightForEntry,
|
|
|
|
StretchRange aStretchForEntry,
|
|
|
|
SlantStyleRange aStyleForEntry) {
|
2010-01-29 04:41:25 +03:00
|
|
|
gfxFontEntry* lookup;
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
lookup = LookupInFaceNameLists(aFontName);
|
|
|
|
if (!lookup) {
|
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2018-10-13 01:16:45 +03:00
|
|
|
|
2010-01-29 04:41:25 +03:00
|
|
|
bool isCFF = false; // jtdfix -- need to determine this
|
2015-10-19 05:16:43 +03:00
|
|
|
|
2010-01-29 04:41:25 +03:00
|
|
|
// use the face name from the lookup font entry, which will be the localized
|
2009-10-07 18:13:40 +04:00
|
|
|
// 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).
|
|
|
|
GDIFontEntry* fe = GDIFontEntry::CreateFontEntry(
|
2018-10-13 01:16:45 +03:00
|
|
|
lookup->Name(),
|
|
|
|
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE
|
2009-10-07 18:13:40 +04:00
|
|
|
: GFX_FONT_TYPE_TRUETYPE) /*type*/,
|
2012-07-30 18:20:58 +04:00
|
|
|
lookup->SlantStyle(), lookup->Weight(), aStretchForEntry, nullptr);
|
2009-10-07 18:13:40 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
if (!fe) return nullptr;
|
2012-06-28 13:59:37 +04:00
|
|
|
|
2018-04-25 09:18:23 +03: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;
|
2018-11-30 13:46:48 +03: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;
|
2018-09-12 22:34:57 +03:00
|
|
|
for (uint32_t i = 0; i < (uint16_t)cmap->numTables; ++i) {
|
|
|
|
if (uint16_t(encRec[i].platformID) !=
|
2015-04-01 08:29:55 +03:00
|
|
|
gfxFontUtils::PLATFORM_ID_MICROSOFT) {
|
|
|
|
continue; // only interested in MS platform
|
|
|
|
}
|
2013-07-09 05:40:03 +04:00
|
|
|
if (uint16_t(encRec[i].encodingID) ==
|
|
|
|
gfxFontUtils::ENCODING_ID_MICROSOFT_UNICODEBMP) {
|
|
|
|
// We've got a Microsoft/Unicode table, so don't interfere.
|
|
|
|
symbolSubtable = -1;
|
2018-11-30 13:46:48 +03:00
|
|
|
break;
|
|
|
|
}
|
2013-07-09 05:40:03 +04:00
|
|
|
if (uint16_t(encRec[i].encodingID) ==
|
2016-08-18 19:22:45 +03:00
|
|
|
gfxFontUtils::ENCODING_ID_MICROSOFT_SYMBOL) {
|
2013-07-09 05:40:03 +04:00
|
|
|
// Found a symbol subtable; remember it for possible fixup,
|
|
|
|
// but if we subsequently find a Microsoft/Unicode subtable,
|
|
|
|
// we'll cancel this.
|
|
|
|
symbolSubtable = i;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2016-08-18 19:22:45 +03:00
|
|
|
if (symbolSubtable != -1) {
|
2009-10-07 18:13:40 +04:00
|
|
|
// We found a windows/symbol cmap table, and no windows/unicode one;
|
|
|
|
// change the encoding ID so that AddFontMemResourceEx will accept it
|
2018-09-12 22:34:57 +03:00
|
|
|
encRec[symbolSubtable].encodingID =
|
|
|
|
gfxFontUtils::ENCODING_ID_MICROSOFT_UNICODEBMP;
|
2017-01-10 08:21:40 +03:00
|
|
|
return true;
|
2010-07-17 05:32:18 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2009-10-07 18:13:40 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxFontEntry* gfxGDIFontList::MakePlatformFont(const nsACString& aFontName,
|
|
|
|
WeightRange aWeightForEntry,
|
2018-05-25 16:07:57 +03:00
|
|
|
StretchRange aStretchForEntry,
|
2016-04-12 09:06:22 +03:00
|
|
|
SlantStyleRange aStyleForEntry,
|
|
|
|
const uint8_t* aFontData,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aLength) {
|
2016-04-12 09:06:22 +03:00
|
|
|
// MakePlatformFont is responsible for deleting the font data with free
|
|
|
|
// so we set up a stack object to ensure it is freed even if we take an
|
2009-10-07 18:13:40 +04:00
|
|
|
// early exit
|
|
|
|
struct FontDataDeleter {
|
2016-04-12 09:06:22 +03:00
|
|
|
explicit FontDataDeleter(const uint8_t* aFontData) : mFontData(aFontData) {}
|
2018-09-12 22:34:57 +03:00
|
|
|
~FontDataDeleter() { free((void*)mFontData); }
|
|
|
|
const uint8_t* mFontData;
|
2018-11-30 13:46:48 +03:00
|
|
|
};
|
2018-09-12 22:34:57 +03:00
|
|
|
FontDataDeleter autoDelete(aFontData);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
bool isCFF = gfxFontUtils::IsCffFont(aFontData);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2009-10-07 18:13:40 +04:00
|
|
|
nsresult rv;
|
2012-07-30 18:20:58 +04:00
|
|
|
HANDLE fontRef = nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
nsAutoString uniqueName;
|
2014-06-06 10:09:23 +04:00
|
|
|
rv = gfxFontUtils::MakeUniqueUserFontName(uniqueName);
|
|
|
|
if (NS_FAILED(rv)) return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-05-25 16:07:57 +03:00
|
|
|
FallibleTArray<uint8_t> newFontData;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-05-25 16:07:57 +03:00
|
|
|
rv = gfxFontUtils::RenameFont(uniqueName, aFontData, aLength, &newFontData);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
if (NS_FAILED(rv)) return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2013-07-09 05:40:03 +04:00
|
|
|
DWORD numFonts = 0;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2013-07-09 05:40:03 +04:00
|
|
|
uint8_t* fontData = reinterpret_cast<uint8_t*>(newFontData.Elements());
|
|
|
|
uint32_t fontLength = newFontData.Length();
|
|
|
|
NS_ASSERTION(fontData, "null font data after renaming");
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2013-07-09 05:40:03 +04:00
|
|
|
// 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
|
2016-04-12 09:06:22 +03:00
|
|
|
// to the process that made the call and is not enumerable."
|
2012-07-30 18:20:58 +04:00
|
|
|
fontRef =
|
2016-08-18 19:22:45 +03:00
|
|
|
AddFontMemResourceEx(fontData, fontLength, 0 /* reserved */, &numFonts);
|
|
|
|
if (!fontRef) {
|
|
|
|
if (FixupSymbolEncodedFont(fontData, fontLength)) {
|
|
|
|
fontRef = AddFontMemResourceEx(fontData, fontLength, 0, &numFonts);
|
2014-06-06 10:09:23 +04:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2016-08-18 19:22:45 +03:00
|
|
|
if (!fontRef) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +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);
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:23:20 +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-10-13 01:16:45 +03:00
|
|
|
GDIFontEntry* fe = GDIFontEntry::CreateFontEntry(
|
2018-09-12 22:34:57 +03:00
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-01-10 08:21:40 +03:00
|
|
|
if (fe) {
|
|
|
|
fe->mIsDataUserFont = true;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2016-04-12 09:06:22 +03:00
|
|
|
return fe;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2014-06-06 10:09:23 +04:00
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
bool gfxGDIFontList::FindAndAddFamilies(StyleGenericFontFamily aGeneric,
|
|
|
|
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-08-23 03:06:07 +03:00
|
|
|
gfxFontStyle* aStyle,
|
2016-04-12 09:06:22 +03:00
|
|
|
gfxFloat aDevToCssSize) {
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF8toUTF16 key16(aFamily);
|
2009-10-07 18:13:40 +04:00
|
|
|
BuildKeyNameFromFontName(key16);
|
2018-09-12 22:34:57 +03:00
|
|
|
NS_ConvertUTF16toUTF8 keyName(key16);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2015-07-31 07:19:57 +03:00
|
|
|
gfxFontFamily* ff = mFontSubstitutes.GetWeak(keyName);
|
2015-01-22 01:12:18 +03:00
|
|
|
if (ff) {
|
2019-04-27 18:37:58 +03:00
|
|
|
aOutput->AppendElement(FamilyAndGeneric(ff, aGeneric));
|
2016-08-18 19:22:45 +03:00
|
|
|
return true;
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
return gfxPlatformFontList::FindAndAddFamilies(aGeneric, aFamily, aOutput,
|
|
|
|
aFlags, aStyle, aDevToCssSize);
|
2014-06-06 10:09:23 +04:00
|
|
|
}
|
|
|
|
|
2019-04-01 17:33:34 +03:00
|
|
|
FontFamily gfxGDIFontList::GetDefaultFontForPlatform(
|
2016-08-23 03:06:07 +03:00
|
|
|
const gfxFontStyle* aStyle) {
|
2019-04-27 18:37:58 +03:00
|
|
|
FontFamily ff;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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, sizeof(ncm), &ncm, 0);
|
2009-10-07 18:13:40 +04:00
|
|
|
if (status) {
|
2018-09-12 22:34:57 +03:00
|
|
|
ff = FindFamily(NS_ConvertUTF16toUTF8(ncm.lfMessageFont.lfFaceName));
|
2019-04-27 18:37:58 +03:00
|
|
|
if (!ff.IsNull()) {
|
|
|
|
return ff;
|
2015-01-22 01:12:18 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2015-01-22 01:12:18 +03:00
|
|
|
|
|
|
|
// ...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
|
|
|
}
|
|
|
|
|
2019-04-27 18:37:58 +03:00
|
|
|
return ff;
|
2009-10-07 18:13:40 +04:00
|
|
|
}
|
2012-03-28 01:38:39 +04:00
|
|
|
|
2013-10-15 06:19:47 +04:00
|
|
|
void gfxGDIFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
|
|
|
|
FontListSizes* aSizes) const {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-15 06:19:47 +04:00
|
|
|
void 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) {}
|
|
|
|
|
2019-04-11 15:36:51 +03:00
|
|
|
virtual ~GDIFontInfo() = default;
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
virtual void Load() {
|
|
|
|
mHdc = GetDC(nullptr);
|
|
|
|
SetGraphicsMode(mHdc, GM_ADVANCED);
|
|
|
|
FontInfoData::Load();
|
|
|
|
ReleaseDC(nullptr, mHdc);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
// loads font data for all members of a given family
|
2018-09-12 22:34:57 +03:00
|
|
|
virtual void LoadFontFamilyData(const nsACString& aFamilyName);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
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-11-30 13:46:48 +03:00
|
|
|
|
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;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
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++;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
// 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;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
// 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++;
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
// other family names
|
|
|
|
if (famData->mFontInfo.mLoadOtherNames) {
|
2019-04-01 17:33:46 +03:00
|
|
|
gfxFontUtils::ReadOtherFamilyNamesForFace(
|
2014-01-29 11:39:01 +04:00
|
|
|
famData->mFamilyName, (const char*)(nameData.Elements()), nameSize,
|
|
|
|
famData->mOtherFamilyNames, false);
|
|
|
|
}
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
// 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;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
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;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
if (NS_SUCCEEDED(gfxFontUtils::ReadCMAP(cmapData.Elements(), cmapSize,
|
2017-09-11 21:23:30 +03:00
|
|
|
*charmap, offset))) {
|
2014-01-29 11:39:01 +04:00
|
|
|
fontData.mCharacterMap = charmap;
|
|
|
|
fontData.mUVSOffset = offset;
|
|
|
|
cmapLoaded = true;
|
|
|
|
famData->mFontInfo.mLoadStats.cmaps++;
|
|
|
|
}
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2014-01-29 11:39:01 +04:00
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
void 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));
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
EnumerateFontsForFamilyData data(aFamilyName, *this);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
EnumFontFamiliesExW(mHdc, &logFont,
|
|
|
|
(FONTENUMPROCW)GDIFontInfo::EnumerateFontsForFamily,
|
|
|
|
(LPARAM)(&data), 0);
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2014-01-29 11:39:01 +04:00
|
|
|
// 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
|
|
|
|
2018-09-12 22:34:57 +03:00
|
|
|
gfxFontFamily* 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-11-30 13:46:48 +03:00
|
|
|
|
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-11-30 13:46:48 +03:00
|
|
|
|
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);
|
2018-11-30 13:46:48 +03:00
|
|
|
}
|
2014-05-29 16:00:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|