diff options
Diffstat (limited to 'gfx/thebes/gfxGDIFontList.h')
-rw-r--r-- | gfx/thebes/gfxGDIFontList.h | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/gfx/thebes/gfxGDIFontList.h b/gfx/thebes/gfxGDIFontList.h new file mode 100644 index 000000000..ffb513d64 --- /dev/null +++ b/gfx/thebes/gfxGDIFontList.h @@ -0,0 +1,354 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * 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/. */ + +#ifndef GFX_GDIFONTLIST_H +#define GFX_GDIFONTLIST_H + +#include "mozilla/MemoryReporting.h" +#include "gfxWindowsPlatform.h" +#include "gfxPlatformFontList.h" +#include "nsGkAtoms.h" + +#include <windows.h> + +class AutoDC // get the global device context, and auto-release it on destruction +{ +public: + AutoDC() { + mDC = ::GetDC(nullptr); + } + + ~AutoDC() { + ::ReleaseDC(nullptr, mDC); + } + + HDC GetDC() { + return mDC; + } + +private: + HDC mDC; +}; + +class AutoSelectFont // select a font into the given DC, and auto-restore +{ +public: + AutoSelectFont(HDC aDC, LOGFONTW *aLogFont) + : mOwnsFont(false) + { + mFont = ::CreateFontIndirectW(aLogFont); + if (mFont) { + mOwnsFont = true; + mDC = aDC; + mOldFont = (HFONT)::SelectObject(aDC, mFont); + } else { + mOldFont = nullptr; + } + } + + AutoSelectFont(HDC aDC, HFONT aFont) + : mOwnsFont(false) + { + mDC = aDC; + mFont = aFont; + mOldFont = (HFONT)::SelectObject(aDC, aFont); + } + + ~AutoSelectFont() { + if (mOldFont) { + ::SelectObject(mDC, mOldFont); + if (mOwnsFont) { + ::DeleteObject(mFont); + } + } + } + + bool IsValid() const { + return mFont != nullptr; + } + + HFONT GetFont() const { + return mFont; + } + +private: + HDC mDC; + HFONT mFont; + HFONT mOldFont; + bool mOwnsFont; +}; + +/** + * List of different types of fonts we support on Windows. + * These can generally be lumped in to 3 categories where we have to + * do special things: Really old fonts bitmap and vector fonts (device + * and raster), Type 1 fonts, and TrueType/OpenType fonts. + * + * This list is sorted in order from least prefered to most prefered. + * We prefer Type1 fonts over OpenType fonts to avoid falling back to + * things like Arial (opentype) when you ask for Helvetica (type1) + **/ +enum gfxWindowsFontType { + GFX_FONT_TYPE_UNKNOWN = 0, + GFX_FONT_TYPE_DEVICE, + GFX_FONT_TYPE_RASTER, + GFX_FONT_TYPE_TRUETYPE, + GFX_FONT_TYPE_PS_OPENTYPE, + GFX_FONT_TYPE_TT_OPENTYPE, + GFX_FONT_TYPE_TYPE1 +}; + +// A single member of a font family (i.e. a single face, such as Times Italic) +// represented as a LOGFONT that will resolve to the correct face. +// This replaces FontEntry from gfxWindowsFonts.h/cpp. +class GDIFontEntry : public gfxFontEntry +{ +public: + LPLOGFONTW GetLogFont() { return &mLogFont; } + + nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr); + + virtual bool IsSymbolFont(); + + void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize, + bool aUseCleartype); + + static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, + DWORD fontType) + { + gfxWindowsFontType feType; + if (metrics.ntmFlags & NTM_TYPE1) + feType = GFX_FONT_TYPE_TYPE1; + else if (metrics.ntmFlags & NTM_PS_OPENTYPE) + feType = GFX_FONT_TYPE_PS_OPENTYPE; + else if (metrics.ntmFlags & NTM_TT_OPENTYPE) + feType = GFX_FONT_TYPE_TT_OPENTYPE; + else if (fontType == TRUETYPE_FONTTYPE) + feType = GFX_FONT_TYPE_TRUETYPE; + else if (fontType == RASTER_FONTTYPE) + feType = GFX_FONT_TYPE_RASTER; + else if (fontType == DEVICE_FONTTYPE) + feType = GFX_FONT_TYPE_DEVICE; + else + feType = GFX_FONT_TYPE_UNKNOWN; + + return feType; + } + + bool IsType1() const { + return (mFontType == GFX_FONT_TYPE_TYPE1); + } + + bool IsTrueType() const { + return (mFontType == GFX_FONT_TYPE_TRUETYPE || + mFontType == GFX_FONT_TYPE_PS_OPENTYPE || + mFontType == GFX_FONT_TYPE_TT_OPENTYPE); + } + + virtual bool MatchesGenericFamily(const nsACString& aGeneric) const { + if (aGeneric.IsEmpty()) { + return true; + } + + // Japanese 'Mincho' fonts do not belong to FF_MODERN even if + // they are fixed pitch because they have variable stroke width. + if (mWindowsFamily == FF_ROMAN && mWindowsPitch & FIXED_PITCH) { + return aGeneric.EqualsLiteral("monospace"); + } + + // Japanese 'Gothic' fonts do not belong to FF_SWISS even if + // they are variable pitch because they have constant stroke width. + if (mWindowsFamily == FF_MODERN && mWindowsPitch & VARIABLE_PITCH) { + return aGeneric.EqualsLiteral("sans-serif"); + } + + // All other fonts will be grouped correctly using family... + switch (mWindowsFamily) { + case FF_DONTCARE: + return false; + case FF_ROMAN: + return aGeneric.EqualsLiteral("serif"); + case FF_SWISS: + return aGeneric.EqualsLiteral("sans-serif"); + case FF_MODERN: + return aGeneric.EqualsLiteral("monospace"); + case FF_SCRIPT: + return aGeneric.EqualsLiteral("cursive"); + case FF_DECORATIVE: + return aGeneric.EqualsLiteral("fantasy"); + } + + return false; + } + + virtual bool SupportsLangGroup(nsIAtom* aLangGroup) const override { + if (!aLangGroup || aLangGroup == nsGkAtoms::Unicode) { + return true; + } + + int16_t bit = -1; + + /* map our langgroup names in to Windows charset bits */ + if (aLangGroup == nsGkAtoms::x_western) { + bit = ANSI_CHARSET; + } else if (aLangGroup == nsGkAtoms::Japanese) { + bit = SHIFTJIS_CHARSET; + } else if (aLangGroup == nsGkAtoms::ko) { + bit = HANGEUL_CHARSET; + } else if (aLangGroup == nsGkAtoms::zh_cn) { + bit = GB2312_CHARSET; + } else if (aLangGroup == nsGkAtoms::zh_tw) { + bit = CHINESEBIG5_CHARSET; + } else if (aLangGroup == nsGkAtoms::el_) { + bit = GREEK_CHARSET; + } else if (aLangGroup == nsGkAtoms::he) { + bit = HEBREW_CHARSET; + } else if (aLangGroup == nsGkAtoms::ar) { + bit = ARABIC_CHARSET; + } else if (aLangGroup == nsGkAtoms::x_cyrillic) { + bit = RUSSIAN_CHARSET; + } else if (aLangGroup == nsGkAtoms::th) { + bit = THAI_CHARSET; + } + + if (bit != -1) { + return mCharset.test(bit); + } + + return false; + } + + virtual bool SupportsRange(uint8_t range) { + return mUnicodeRanges.test(range); + } + + virtual bool SkipDuringSystemFallback() { + return !HasCmapTable(); // explicitly skip non-SFNT fonts + } + + virtual bool TestCharacterMap(uint32_t aCh); + + virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, + FontListSizes* aSizes) const; + + // create a font entry for a font with a given name + static GDIFontEntry* CreateFontEntry(const nsAString& aName, + gfxWindowsFontType aFontType, + uint8_t aStyle, + uint16_t aWeight, int16_t aStretch, + gfxUserFontData* aUserFontData, + bool aFamilyHasItalicFace); + + // create a font entry for a font referenced by its fullname + static GDIFontEntry* LoadLocalFont(const nsAString& aFontName, + uint16_t aWeight, + int16_t aStretch, + uint8_t aStyle); + + uint8_t mWindowsFamily; + uint8_t mWindowsPitch; + + gfxWindowsFontType mFontType; + bool mForceGDI : 1; + + // For src:local user-fonts, we keep track of whether the platform family + // contains an italic face, because in this case we can't safely ask GDI + // to create synthetic italics (oblique) via the LOGFONT. + // (For other types of font, this is just set to false.) + bool mFamilyHasItalicFace : 1; + + gfxSparseBitSet mCharset; + gfxSparseBitSet mUnicodeRanges; + +protected: + friend class gfxWindowsFont; + + GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType, + uint8_t aStyle, uint16_t aWeight, int16_t aStretch, + gfxUserFontData *aUserFontData, bool aFamilyHasItalicFace); + + void InitLogFont(const nsAString& aName, gfxWindowsFontType aFontType); + + virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold); + + virtual nsresult CopyFontTable(uint32_t aTableTag, + nsTArray<uint8_t>& aBuffer) override; + + LOGFONTW mLogFont; +}; + +// a single font family, referencing one or more faces +class GDIFontFamily : public gfxFontFamily +{ +public: + GDIFontFamily(nsAString &aName) : + gfxFontFamily(aName) {} + + virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr); + +private: + static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe, + const NEWTEXTMETRICEXW *nmetrics, + DWORD fontType, LPARAM data); +}; + +class gfxGDIFontList : public gfxPlatformFontList { +public: + static gfxGDIFontList* PlatformFontList() { + return static_cast<gfxGDIFontList*>(sPlatformFontList); + } + + // initialize font lists + virtual nsresult InitFontListForPlatform() override; + + bool FindAndAddFamilies(const nsAString& aFamily, + nsTArray<gfxFontFamily*>* aOutput, + gfxFontStyle* aStyle = nullptr, + gfxFloat aDevToCssSize = 1.0) override; + + virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, + uint16_t aWeight, + int16_t aStretch, + uint8_t aStyle); + + virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, + uint16_t aWeight, + int16_t aStretch, + uint8_t aStyle, + const uint8_t* aFontData, + uint32_t aLength); + + virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, + FontListSizes* aSizes) const; + +protected: + virtual gfxFontFamily* + GetDefaultFontForPlatform(const gfxFontStyle* aStyle) override; + +private: + friend class gfxWindowsPlatform; + + gfxGDIFontList(); + + nsresult GetFontSubstitutes(); + + static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe, + NEWTEXTMETRICEXW *lpntme, + DWORD fontType, + LPARAM lParam); + + virtual already_AddRefed<FontInfoData> CreateFontInfoData(); + +#ifdef MOZ_BUNDLED_FONTS + void ActivateBundledFonts(); +#endif + + FontFamilyTable mFontSubstitutes; + nsTArray<nsString> mNonExistingFonts; +}; + +#endif /* GFX_GDIFONTLIST_H */ |