gfx/thebes/gfxGDIFontList.h

changeset 0
6474c204b198
     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 */

mercurial