1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef GFX_GDIFONTLIST_H 7 #define GFX_GDIFONTLIST_H 8 9 #include "mozilla/FontPropertyTypes.h" 10 #include "mozilla/MemoryReporting.h" 11 #include "gfxWindowsPlatform.h" 12 #include "gfxPlatformFontList.h" 13 #include "nsGkAtoms.h" 14 #include "mozilla/gfx/UnscaledFontGDI.h" 15 16 #include <windows.h> 17 18 class AutoDC // get the global device context, and auto-release it on 19 // destruction 20 { 21 public: AutoDC()22 AutoDC() { mDC = ::GetDC(nullptr); } 23 ~AutoDC()24 ~AutoDC() { ::ReleaseDC(nullptr, mDC); } 25 GetDC()26 HDC GetDC() { return mDC; } 27 28 private: 29 HDC mDC; 30 }; 31 32 class AutoSelectFont // select a font into the given DC, and auto-restore 33 { 34 public: AutoSelectFont(HDC aDC,LOGFONTW * aLogFont)35 AutoSelectFont(HDC aDC, LOGFONTW* aLogFont) : mOwnsFont(false) { 36 mFont = ::CreateFontIndirectW(aLogFont); 37 if (mFont) { 38 mOwnsFont = true; 39 mDC = aDC; 40 mOldFont = (HFONT)::SelectObject(aDC, mFont); 41 } else { 42 mOldFont = nullptr; 43 } 44 } 45 AutoSelectFont(HDC aDC,HFONT aFont)46 AutoSelectFont(HDC aDC, HFONT aFont) : mOwnsFont(false) { 47 mDC = aDC; 48 mFont = aFont; 49 mOldFont = (HFONT)::SelectObject(aDC, aFont); 50 } 51 ~AutoSelectFont()52 ~AutoSelectFont() { 53 if (mOldFont) { 54 ::SelectObject(mDC, mOldFont); 55 if (mOwnsFont) { 56 ::DeleteObject(mFont); 57 } 58 } 59 } 60 IsValid()61 bool IsValid() const { return mFont != nullptr; } 62 GetFont()63 HFONT GetFont() const { return mFont; } 64 65 private: 66 HDC mDC; 67 HFONT mFont; 68 HFONT mOldFont; 69 bool mOwnsFont; 70 }; 71 72 /** 73 * List of different types of fonts we support on Windows. 74 * These can generally be lumped in to 3 categories where we have to 75 * do special things: Really old fonts bitmap and vector fonts (device 76 * and raster), Type 1 fonts, and TrueType/OpenType fonts. 77 * 78 * This list is sorted in order from least prefered to most prefered. 79 * We prefer Type1 fonts over OpenType fonts to avoid falling back to 80 * things like Arial (opentype) when you ask for Helvetica (type1) 81 **/ 82 enum gfxWindowsFontType { 83 GFX_FONT_TYPE_UNKNOWN = 0, 84 GFX_FONT_TYPE_DEVICE, 85 GFX_FONT_TYPE_RASTER, 86 GFX_FONT_TYPE_TRUETYPE, 87 GFX_FONT_TYPE_PS_OPENTYPE, 88 GFX_FONT_TYPE_TT_OPENTYPE, 89 GFX_FONT_TYPE_TYPE1 90 }; 91 92 // A single member of a font family (i.e. a single face, such as Times Italic) 93 // represented as a LOGFONT that will resolve to the correct face. 94 // This replaces FontEntry from gfxWindowsFonts.h/cpp. 95 class GDIFontEntry final : public gfxFontEntry { 96 public: GetLogFont()97 LPLOGFONTW GetLogFont() { return &mLogFont; } 98 99 nsresult ReadCMAP(FontInfoData* aFontInfoData = nullptr) override; 100 101 void FillLogFont(LOGFONTW* aLogFont, LONG aWeight, gfxFloat aSize); 102 DetermineFontType(const NEWTEXTMETRICW & metrics,DWORD fontType)103 static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, 104 DWORD fontType) { 105 gfxWindowsFontType feType; 106 if (metrics.ntmFlags & NTM_TYPE1) 107 feType = GFX_FONT_TYPE_TYPE1; 108 else if (metrics.ntmFlags & NTM_PS_OPENTYPE) 109 feType = GFX_FONT_TYPE_PS_OPENTYPE; 110 else if (metrics.ntmFlags & NTM_TT_OPENTYPE) 111 feType = GFX_FONT_TYPE_TT_OPENTYPE; 112 else if (fontType == TRUETYPE_FONTTYPE) 113 feType = GFX_FONT_TYPE_TRUETYPE; 114 else if (fontType == RASTER_FONTTYPE) 115 feType = GFX_FONT_TYPE_RASTER; 116 else if (fontType == DEVICE_FONTTYPE) 117 feType = GFX_FONT_TYPE_DEVICE; 118 else 119 feType = GFX_FONT_TYPE_UNKNOWN; 120 121 return feType; 122 } 123 IsType1()124 bool IsType1() const { return (mFontType == GFX_FONT_TYPE_TYPE1); } 125 IsTrueType()126 bool IsTrueType() const { 127 return (mFontType == GFX_FONT_TYPE_TRUETYPE || 128 mFontType == GFX_FONT_TYPE_PS_OPENTYPE || 129 mFontType == GFX_FONT_TYPE_TT_OPENTYPE); 130 } 131 SupportsRange(uint8_t range)132 virtual bool SupportsRange(uint8_t range) { 133 return mUnicodeRanges.test(range); 134 } 135 SkipDuringSystemFallback()136 virtual bool SkipDuringSystemFallback() { 137 return !HasCmapTable(); // explicitly skip non-SFNT fonts 138 } 139 140 virtual bool TestCharacterMap(uint32_t aCh); 141 142 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 143 FontListSizes* aSizes) const; 144 145 gfxFontEntry* Clone() const override; 146 147 // GDI backend doesn't support font variations: HasVariations()148 bool HasVariations() override { return false; } GetVariationAxes(nsTArray<gfxFontVariationAxis> &)149 void GetVariationAxes(nsTArray<gfxFontVariationAxis>&) override {} GetVariationInstances(nsTArray<gfxFontVariationInstance> &)150 void GetVariationInstances(nsTArray<gfxFontVariationInstance>&) override {} 151 152 // create a font entry for a font with a given name 153 static GDIFontEntry* CreateFontEntry(const nsACString& aName, 154 gfxWindowsFontType aFontType, 155 SlantStyleRange aStyle, 156 WeightRange aWeight, 157 StretchRange aStretch, 158 gfxUserFontData* aUserFontData); 159 160 gfxWindowsFontType mFontType; 161 bool mForceGDI; 162 163 gfxSparseBitSet mUnicodeRanges; 164 165 protected: 166 friend class gfxGDIFont; 167 168 GDIFontEntry(const nsACString& aFaceName, gfxWindowsFontType aFontType, 169 SlantStyleRange aStyle, WeightRange aWeight, 170 StretchRange aStretch, gfxUserFontData* aUserFontData); 171 172 void InitLogFont(const nsACString& aName, gfxWindowsFontType aFontType); 173 174 gfxFont* CreateFontInstance(const gfxFontStyle* aFontStyle) override; 175 176 virtual nsresult CopyFontTable(uint32_t aTableTag, 177 nsTArray<uint8_t>& aBuffer) override; 178 179 already_AddRefed<mozilla::gfx::UnscaledFontGDI> LookupUnscaledFont( 180 HFONT aFont); 181 182 LOGFONTW mLogFont; 183 184 mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontGDI> mUnscaledFont; 185 }; 186 187 // a single font family, referencing one or more faces 188 class GDIFontFamily final : public gfxFontFamily { 189 public: GDIFontFamily(const nsACString & aName,FontVisibility aVisibility)190 GDIFontFamily(const nsACString& aName, FontVisibility aVisibility) 191 : gfxFontFamily(aName, aVisibility), 192 mWindowsFamily(0), 193 mWindowsPitch(0), 194 mCharset() {} 195 196 virtual void FindStyleVariations(FontInfoData* aFontInfoData = nullptr); 197 FilterForFontList(nsAtom * aLangGroup,const nsACString & aGeneric)198 bool FilterForFontList(nsAtom* aLangGroup, 199 const nsACString& aGeneric) const final { 200 return !IsSymbolFontFamily() && SupportsLangGroup(aLangGroup) && 201 MatchesGenericFamily(aGeneric); 202 } 203 204 protected: 205 friend class gfxGDIFontList; 206 207 // helpers for FilterForFontList IsSymbolFontFamily()208 bool IsSymbolFontFamily() const { return mCharset.test(SYMBOL_CHARSET); } 209 MatchesGenericFamily(const nsACString & aGeneric)210 bool MatchesGenericFamily(const nsACString& aGeneric) const { 211 if (aGeneric.IsEmpty()) { 212 return true; 213 } 214 215 // Japanese 'Mincho' fonts do not belong to FF_MODERN even if 216 // they are fixed pitch because they have variable stroke width. 217 if (mWindowsFamily == FF_ROMAN && mWindowsPitch & FIXED_PITCH) { 218 return aGeneric.EqualsLiteral("monospace"); 219 } 220 221 // Japanese 'Gothic' fonts do not belong to FF_SWISS even if 222 // they are variable pitch because they have constant stroke width. 223 if (mWindowsFamily == FF_MODERN && mWindowsPitch & VARIABLE_PITCH) { 224 return aGeneric.EqualsLiteral("sans-serif"); 225 } 226 227 // All other fonts will be grouped correctly using family... 228 switch (mWindowsFamily) { 229 case FF_DONTCARE: 230 return false; 231 case FF_ROMAN: 232 return aGeneric.EqualsLiteral("serif"); 233 case FF_SWISS: 234 return aGeneric.EqualsLiteral("sans-serif"); 235 case FF_MODERN: 236 return aGeneric.EqualsLiteral("monospace"); 237 case FF_SCRIPT: 238 return aGeneric.EqualsLiteral("cursive"); 239 case FF_DECORATIVE: 240 return aGeneric.EqualsLiteral("fantasy"); 241 } 242 243 return false; 244 } 245 SupportsLangGroup(nsAtom * aLangGroup)246 bool SupportsLangGroup(nsAtom* aLangGroup) const { 247 if (!aLangGroup || aLangGroup == nsGkAtoms::Unicode) { 248 return true; 249 } 250 251 int16_t bit = -1; 252 253 /* map our langgroup names in to Windows charset bits */ 254 if (aLangGroup == nsGkAtoms::x_western) { 255 bit = ANSI_CHARSET; 256 } else if (aLangGroup == nsGkAtoms::Japanese) { 257 bit = SHIFTJIS_CHARSET; 258 } else if (aLangGroup == nsGkAtoms::ko) { 259 bit = HANGEUL_CHARSET; 260 } else if (aLangGroup == nsGkAtoms::zh_cn) { 261 bit = GB2312_CHARSET; 262 } else if (aLangGroup == nsGkAtoms::zh_tw) { 263 bit = CHINESEBIG5_CHARSET; 264 } else if (aLangGroup == nsGkAtoms::el) { 265 bit = GREEK_CHARSET; 266 } else if (aLangGroup == nsGkAtoms::he) { 267 bit = HEBREW_CHARSET; 268 } else if (aLangGroup == nsGkAtoms::ar) { 269 bit = ARABIC_CHARSET; 270 } else if (aLangGroup == nsGkAtoms::x_cyrillic) { 271 bit = RUSSIAN_CHARSET; 272 } else if (aLangGroup == nsGkAtoms::th) { 273 bit = THAI_CHARSET; 274 } 275 276 if (bit != -1) { 277 return mCharset.test(bit); 278 } 279 280 return false; 281 } 282 283 uint8_t mWindowsFamily; 284 uint8_t mWindowsPitch; 285 286 gfxSparseBitSet mCharset; 287 288 private: 289 static int CALLBACK FamilyAddStylesProc(const ENUMLOGFONTEXW* lpelfe, 290 const NEWTEXTMETRICEXW* nmetrics, 291 DWORD fontType, LPARAM data); 292 }; 293 294 class gfxGDIFontList final : public gfxPlatformFontList { 295 public: PlatformFontList()296 static gfxGDIFontList* PlatformFontList() { 297 return static_cast<gfxGDIFontList*>( 298 gfxPlatformFontList::PlatformFontList()); 299 } 300 301 // initialize font lists 302 virtual nsresult InitFontListForPlatform() override; 303 304 gfxFontFamily* CreateFontFamily(const nsACString& aName, 305 FontVisibility aVisibility) const override; 306 307 bool FindAndAddFamilies(mozilla::StyleGenericFontFamily aGeneric, 308 const nsACString& aFamily, 309 nsTArray<FamilyAndGeneric>* aOutput, 310 FindFamiliesFlags aFlags, 311 gfxFontStyle* aStyle = nullptr, 312 nsAtom* aLanguage = nullptr, 313 gfxFloat aDevToCssSize = 1.0) override; 314 315 virtual gfxFontEntry* LookupLocalFont(const nsACString& aFontName, 316 WeightRange aWeightForEntry, 317 StretchRange aStretchForEntry, 318 SlantStyleRange aStyleForEntry); 319 320 virtual gfxFontEntry* MakePlatformFont(const nsACString& aFontName, 321 WeightRange aWeightForEntry, 322 StretchRange aStretchForEntry, 323 SlantStyleRange aStyleForEntry, 324 const uint8_t* aFontData, 325 uint32_t aLength); 326 327 virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, 328 FontListSizes* aSizes) const; 329 virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, 330 FontListSizes* aSizes) const; 331 332 protected: 333 FontFamily GetDefaultFontForPlatform(const gfxFontStyle* aStyle, 334 nsAtom* aLanguage = nullptr) override; 335 336 private: 337 friend class gfxWindowsPlatform; 338 339 gfxGDIFontList(); 340 341 nsresult GetFontSubstitutes(); 342 343 static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW* lpelfe, 344 NEWTEXTMETRICEXW* lpntme, 345 DWORD fontType, LPARAM lParam); 346 347 virtual already_AddRefed<FontInfoData> CreateFontInfoData(); 348 349 #ifdef MOZ_BUNDLED_FONTS 350 void ActivateBundledFonts(); 351 #endif 352 353 FontFamilyTable mFontSubstitutes; 354 nsTArray<nsCString> mNonExistingFonts; 355 }; 356 357 #endif /* GFX_GDIFONTLIST_H */ 358