1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxGDIFontList.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,350 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef GFX_GDIFONTLIST_H 1.10 +#define GFX_GDIFONTLIST_H 1.11 + 1.12 +#include "mozilla/MemoryReporting.h" 1.13 +#include "gfxWindowsPlatform.h" 1.14 +#include "gfxPlatformFontList.h" 1.15 +#include "nsGkAtoms.h" 1.16 + 1.17 +#include <windows.h> 1.18 + 1.19 +class AutoDC // get the global device context, and auto-release it on destruction 1.20 +{ 1.21 +public: 1.22 + AutoDC() { 1.23 + mDC = ::GetDC(nullptr); 1.24 + } 1.25 + 1.26 + ~AutoDC() { 1.27 + ::ReleaseDC(nullptr, mDC); 1.28 + } 1.29 + 1.30 + HDC GetDC() { 1.31 + return mDC; 1.32 + } 1.33 + 1.34 +private: 1.35 + HDC mDC; 1.36 +}; 1.37 + 1.38 +class AutoSelectFont // select a font into the given DC, and auto-restore 1.39 +{ 1.40 +public: 1.41 + AutoSelectFont(HDC aDC, LOGFONTW *aLogFont) 1.42 + : mOwnsFont(false) 1.43 + { 1.44 + mFont = ::CreateFontIndirectW(aLogFont); 1.45 + if (mFont) { 1.46 + mOwnsFont = true; 1.47 + mDC = aDC; 1.48 + mOldFont = (HFONT)::SelectObject(aDC, mFont); 1.49 + } else { 1.50 + mOldFont = nullptr; 1.51 + } 1.52 + } 1.53 + 1.54 + AutoSelectFont(HDC aDC, HFONT aFont) 1.55 + : mOwnsFont(false) 1.56 + { 1.57 + mDC = aDC; 1.58 + mFont = aFont; 1.59 + mOldFont = (HFONT)::SelectObject(aDC, aFont); 1.60 + } 1.61 + 1.62 + ~AutoSelectFont() { 1.63 + if (mOldFont) { 1.64 + ::SelectObject(mDC, mOldFont); 1.65 + if (mOwnsFont) { 1.66 + ::DeleteObject(mFont); 1.67 + } 1.68 + } 1.69 + } 1.70 + 1.71 + bool IsValid() const { 1.72 + return mFont != nullptr; 1.73 + } 1.74 + 1.75 + HFONT GetFont() const { 1.76 + return mFont; 1.77 + } 1.78 + 1.79 +private: 1.80 + HDC mDC; 1.81 + HFONT mFont; 1.82 + HFONT mOldFont; 1.83 + bool mOwnsFont; 1.84 +}; 1.85 + 1.86 +/** 1.87 + * List of different types of fonts we support on Windows. 1.88 + * These can generally be lumped in to 3 categories where we have to 1.89 + * do special things: Really old fonts bitmap and vector fonts (device 1.90 + * and raster), Type 1 fonts, and TrueType/OpenType fonts. 1.91 + * 1.92 + * This list is sorted in order from least prefered to most prefered. 1.93 + * We prefer Type1 fonts over OpenType fonts to avoid falling back to 1.94 + * things like Arial (opentype) when you ask for Helvetica (type1) 1.95 + **/ 1.96 +enum gfxWindowsFontType { 1.97 + GFX_FONT_TYPE_UNKNOWN = 0, 1.98 + GFX_FONT_TYPE_DEVICE, 1.99 + GFX_FONT_TYPE_RASTER, 1.100 + GFX_FONT_TYPE_TRUETYPE, 1.101 + GFX_FONT_TYPE_PS_OPENTYPE, 1.102 + GFX_FONT_TYPE_TT_OPENTYPE, 1.103 + GFX_FONT_TYPE_TYPE1 1.104 +}; 1.105 + 1.106 +// A single member of a font family (i.e. a single face, such as Times Italic) 1.107 +// represented as a LOGFONT that will resolve to the correct face. 1.108 +// This replaces FontEntry from gfxWindowsFonts.h/cpp. 1.109 +class GDIFontEntry : public gfxFontEntry 1.110 +{ 1.111 +public: 1.112 + LPLOGFONTW GetLogFont() { return &mLogFont; } 1.113 + 1.114 + nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr); 1.115 + 1.116 + virtual bool IsSymbolFont(); 1.117 + 1.118 + void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize, 1.119 + bool aUseCleartype); 1.120 + 1.121 + static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, 1.122 + DWORD fontType) 1.123 + { 1.124 + gfxWindowsFontType feType; 1.125 + if (metrics.ntmFlags & NTM_TYPE1) 1.126 + feType = GFX_FONT_TYPE_TYPE1; 1.127 + else if (metrics.ntmFlags & NTM_PS_OPENTYPE) 1.128 + feType = GFX_FONT_TYPE_PS_OPENTYPE; 1.129 + else if (metrics.ntmFlags & NTM_TT_OPENTYPE) 1.130 + feType = GFX_FONT_TYPE_TT_OPENTYPE; 1.131 + else if (fontType == TRUETYPE_FONTTYPE) 1.132 + feType = GFX_FONT_TYPE_TRUETYPE; 1.133 + else if (fontType == RASTER_FONTTYPE) 1.134 + feType = GFX_FONT_TYPE_RASTER; 1.135 + else if (fontType == DEVICE_FONTTYPE) 1.136 + feType = GFX_FONT_TYPE_DEVICE; 1.137 + else 1.138 + feType = GFX_FONT_TYPE_UNKNOWN; 1.139 + 1.140 + return feType; 1.141 + } 1.142 + 1.143 + bool IsType1() const { 1.144 + return (mFontType == GFX_FONT_TYPE_TYPE1); 1.145 + } 1.146 + 1.147 + bool IsTrueType() const { 1.148 + return (mFontType == GFX_FONT_TYPE_TRUETYPE || 1.149 + mFontType == GFX_FONT_TYPE_PS_OPENTYPE || 1.150 + mFontType == GFX_FONT_TYPE_TT_OPENTYPE); 1.151 + } 1.152 + 1.153 + virtual bool MatchesGenericFamily(const nsACString& aGeneric) const { 1.154 + if (aGeneric.IsEmpty()) { 1.155 + return true; 1.156 + } 1.157 + 1.158 + // Japanese 'Mincho' fonts do not belong to FF_MODERN even if 1.159 + // they are fixed pitch because they have variable stroke width. 1.160 + if (mWindowsFamily == FF_ROMAN && mWindowsPitch & FIXED_PITCH) { 1.161 + return aGeneric.EqualsLiteral("monospace"); 1.162 + } 1.163 + 1.164 + // Japanese 'Gothic' fonts do not belong to FF_SWISS even if 1.165 + // they are variable pitch because they have constant stroke width. 1.166 + if (mWindowsFamily == FF_MODERN && mWindowsPitch & VARIABLE_PITCH) { 1.167 + return aGeneric.EqualsLiteral("sans-serif"); 1.168 + } 1.169 + 1.170 + // All other fonts will be grouped correctly using family... 1.171 + switch (mWindowsFamily) { 1.172 + case FF_DONTCARE: 1.173 + return false; 1.174 + case FF_ROMAN: 1.175 + return aGeneric.EqualsLiteral("serif"); 1.176 + case FF_SWISS: 1.177 + return aGeneric.EqualsLiteral("sans-serif"); 1.178 + case FF_MODERN: 1.179 + return aGeneric.EqualsLiteral("monospace"); 1.180 + case FF_SCRIPT: 1.181 + return aGeneric.EqualsLiteral("cursive"); 1.182 + case FF_DECORATIVE: 1.183 + return aGeneric.EqualsLiteral("fantasy"); 1.184 + } 1.185 + 1.186 + return false; 1.187 + } 1.188 + 1.189 + virtual bool SupportsLangGroup(nsIAtom* aLangGroup) const { 1.190 + if (!aLangGroup || aLangGroup == nsGkAtoms::Unicode) { 1.191 + return true; 1.192 + } 1.193 + 1.194 + int16_t bit = -1; 1.195 + 1.196 + /* map our langgroup names in to Windows charset bits */ 1.197 + if (aLangGroup == nsGkAtoms::x_western) { 1.198 + bit = ANSI_CHARSET; 1.199 + } else if (aLangGroup == nsGkAtoms::Japanese) { 1.200 + bit = SHIFTJIS_CHARSET; 1.201 + } else if (aLangGroup == nsGkAtoms::ko) { 1.202 + bit = HANGEUL_CHARSET; 1.203 + } else if (aLangGroup == nsGkAtoms::ko_xxx) { 1.204 + bit = JOHAB_CHARSET; 1.205 + } else if (aLangGroup == nsGkAtoms::zh_cn) { 1.206 + bit = GB2312_CHARSET; 1.207 + } else if (aLangGroup == nsGkAtoms::zh_tw) { 1.208 + bit = CHINESEBIG5_CHARSET; 1.209 + } else if (aLangGroup == nsGkAtoms::el_) { 1.210 + bit = GREEK_CHARSET; 1.211 + } else if (aLangGroup == nsGkAtoms::tr) { 1.212 + bit = TURKISH_CHARSET; 1.213 + } else if (aLangGroup == nsGkAtoms::he) { 1.214 + bit = HEBREW_CHARSET; 1.215 + } else if (aLangGroup == nsGkAtoms::ar) { 1.216 + bit = ARABIC_CHARSET; 1.217 + } else if (aLangGroup == nsGkAtoms::x_baltic) { 1.218 + bit = BALTIC_CHARSET; 1.219 + } else if (aLangGroup == nsGkAtoms::x_cyrillic) { 1.220 + bit = RUSSIAN_CHARSET; 1.221 + } else if (aLangGroup == nsGkAtoms::th) { 1.222 + bit = THAI_CHARSET; 1.223 + } else if (aLangGroup == nsGkAtoms::x_central_euro) { 1.224 + bit = EASTEUROPE_CHARSET; 1.225 + } else if (aLangGroup == nsGkAtoms::x_symbol) { 1.226 + bit = SYMBOL_CHARSET; 1.227 + } 1.228 + 1.229 + if (bit != -1) { 1.230 + return mCharset.test(bit); 1.231 + } 1.232 + 1.233 + return false; 1.234 + } 1.235 + 1.236 + virtual bool SupportsRange(uint8_t range) { 1.237 + return mUnicodeRanges.test(range); 1.238 + } 1.239 + 1.240 + virtual bool SkipDuringSystemFallback() { 1.241 + return !HasCmapTable(); // explicitly skip non-SFNT fonts 1.242 + } 1.243 + 1.244 + virtual bool TestCharacterMap(uint32_t aCh); 1.245 + 1.246 + virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 1.247 + FontListSizes* aSizes) const; 1.248 + 1.249 + // create a font entry for a font with a given name 1.250 + static GDIFontEntry* CreateFontEntry(const nsAString& aName, 1.251 + gfxWindowsFontType aFontType, 1.252 + bool aItalic, 1.253 + uint16_t aWeight, int16_t aStretch, 1.254 + gfxUserFontData* aUserFontData, 1.255 + bool aFamilyHasItalicFace); 1.256 + 1.257 + // create a font entry for a font referenced by its fullname 1.258 + static GDIFontEntry* LoadLocalFont(const gfxProxyFontEntry &aProxyEntry, 1.259 + const nsAString& aFullname); 1.260 + 1.261 + uint8_t mWindowsFamily; 1.262 + uint8_t mWindowsPitch; 1.263 + 1.264 + gfxWindowsFontType mFontType; 1.265 + bool mForceGDI : 1; 1.266 + 1.267 + // For src:local user-fonts, we keep track of whether the platform family 1.268 + // contains an italic face, because in this case we can't safely ask GDI 1.269 + // to create synthetic italics (oblique) via the LOGFONT. 1.270 + // (For other types of font, this is just set to false.) 1.271 + bool mFamilyHasItalicFace : 1; 1.272 + 1.273 + gfxSparseBitSet mCharset; 1.274 + gfxSparseBitSet mUnicodeRanges; 1.275 + 1.276 +protected: 1.277 + friend class gfxWindowsFont; 1.278 + 1.279 + GDIFontEntry(const nsAString& aFaceName, gfxWindowsFontType aFontType, 1.280 + bool aItalic, uint16_t aWeight, int16_t aStretch, 1.281 + gfxUserFontData *aUserFontData, bool aFamilyHasItalicFace); 1.282 + 1.283 + void InitLogFont(const nsAString& aName, gfxWindowsFontType aFontType); 1.284 + 1.285 + virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold); 1.286 + 1.287 + virtual nsresult CopyFontTable(uint32_t aTableTag, 1.288 + FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE; 1.289 + 1.290 + LOGFONTW mLogFont; 1.291 +}; 1.292 + 1.293 +// a single font family, referencing one or more faces 1.294 +class GDIFontFamily : public gfxFontFamily 1.295 +{ 1.296 +public: 1.297 + GDIFontFamily(nsAString &aName) : 1.298 + gfxFontFamily(aName) {} 1.299 + 1.300 + virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr); 1.301 + 1.302 +private: 1.303 + static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe, 1.304 + const NEWTEXTMETRICEXW *nmetrics, 1.305 + DWORD fontType, LPARAM data); 1.306 +}; 1.307 + 1.308 +class gfxGDIFontList : public gfxPlatformFontList { 1.309 +public: 1.310 + static gfxGDIFontList* PlatformFontList() { 1.311 + return static_cast<gfxGDIFontList*>(sPlatformFontList); 1.312 + } 1.313 + 1.314 + // initialize font lists 1.315 + virtual nsresult InitFontList(); 1.316 + 1.317 + virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle); 1.318 + 1.319 + virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, 1.320 + const nsAString& aFontName); 1.321 + 1.322 + virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, 1.323 + const uint8_t *aFontData, uint32_t aLength); 1.324 + 1.325 + virtual bool ResolveFontName(const nsAString& aFontName, 1.326 + nsAString& aResolvedFontName); 1.327 + 1.328 + virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 1.329 + FontListSizes* aSizes) const; 1.330 + virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 1.331 + FontListSizes* aSizes) const; 1.332 + 1.333 +private: 1.334 + friend class gfxWindowsPlatform; 1.335 + 1.336 + gfxGDIFontList(); 1.337 + 1.338 + nsresult GetFontSubstitutes(); 1.339 + 1.340 + static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe, 1.341 + NEWTEXTMETRICEXW *lpntme, 1.342 + DWORD fontType, 1.343 + LPARAM lParam); 1.344 + 1.345 + virtual already_AddRefed<FontInfoData> CreateFontInfoData(); 1.346 + 1.347 + typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable; 1.348 + 1.349 + FontTable mFontSubstitutes; 1.350 + nsTArray<nsString> mNonExistingFonts; 1.351 +}; 1.352 + 1.353 +#endif /* GFX_GDIFONTLIST_H */