diff options
Diffstat (limited to 'gfx/thebes/gfxDWriteFontList.h')
-rw-r--r-- | gfx/thebes/gfxDWriteFontList.h | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h new file mode 100644 index 000000000..6bf094afa --- /dev/null +++ b/gfx/thebes/gfxDWriteFontList.h @@ -0,0 +1,445 @@ +/* -*- 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_DWRITEFONTLIST_H +#define GFX_DWRITEFONTLIST_H + +#include "mozilla/MemoryReporting.h" +#include "gfxDWriteCommon.h" + +#include "gfxFont.h" +#include "gfxUserFontSet.h" +#include "cairo-win32.h" + +#include "gfxPlatformFontList.h" +#include "gfxPlatform.h" +#include <algorithm> + + +/** + * gfxDWriteFontFamily is a class that describes one of the fonts on the + * users system. It holds each gfxDWriteFontEntry (maps more directly to + * a font face) which holds font type, charset info and character map info. + */ +class gfxDWriteFontEntry; + +/** + * \brief Class representing directwrite font family. + */ +class gfxDWriteFontFamily : public gfxFontFamily +{ +public: + /** + * Constructs a new DWriteFont Family. + * + * \param aName Name identifying the family + * \param aFamily IDWriteFontFamily object representing the directwrite + * family object. + */ + gfxDWriteFontFamily(const nsAString& aName, + IDWriteFontFamily *aFamily) + : gfxFontFamily(aName), mDWFamily(aFamily), mForceGDIClassic(false) {} + virtual ~gfxDWriteFontFamily(); + + void FindStyleVariations(FontInfoData *aFontInfoData = nullptr) final; + + void LocalizedName(nsAString& aLocalizedName) final; + + void ReadFaceNames(gfxPlatformFontList *aPlatformFontList, + bool aNeedFullnamePostscriptNames, + FontInfoData *aFontInfoData = nullptr) final; + + void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } + + void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, + FontListSizes* aSizes) const final; + void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, + FontListSizes* aSizes) const final; + +protected: + /** This font family's directwrite fontfamily object */ + RefPtr<IDWriteFontFamily> mDWFamily; + bool mForceGDIClassic; +}; + +/** + * \brief Class representing DirectWrite FontEntry (a unique font style/family) + */ +class gfxDWriteFontEntry : public gfxFontEntry +{ +public: + /** + * Constructs a font entry. + * + * \param aFaceName The name of the corresponding font face. + * \param aFont DirectWrite font object + */ + gfxDWriteFontEntry(const nsAString& aFaceName, + IDWriteFont *aFont) + : gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr), + mForceGDIClassic(false) + { + DWRITE_FONT_STYLE dwriteStyle = aFont->GetStyle(); + mStyle = (dwriteStyle == DWRITE_FONT_STYLE_ITALIC ? + NS_FONT_STYLE_ITALIC : + (dwriteStyle == DWRITE_FONT_STYLE_OBLIQUE ? + NS_FONT_STYLE_OBLIQUE : NS_FONT_STYLE_NORMAL)); + mStretch = FontStretchFromDWriteStretch(aFont->GetStretch()); + uint16_t weight = NS_ROUNDUP(aFont->GetWeight() - 50, 100); + + weight = std::max<uint16_t>(100, weight); + weight = std::min<uint16_t>(900, weight); + mWeight = weight; + + mIsCJK = UNINITIALIZED_VALUE; + } + + /** + * Constructs a font entry using a font. But with custom font values. + * This is used for creating correct font entries for @font-face with local + * font source. + * + * \param aFaceName The name of the corresponding font face. + * \param aFont DirectWrite font object + * \param aWeight Weight of the font + * \param aStretch Stretch of the font + * \param aStyle italic or oblique of font + */ + gfxDWriteFontEntry(const nsAString& aFaceName, + IDWriteFont *aFont, + uint16_t aWeight, + int16_t aStretch, + uint8_t aStyle) + : gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr), + mForceGDIClassic(false) + { + mWeight = aWeight; + mStretch = aStretch; + mStyle = aStyle; + mIsLocalUserFont = true; + mIsCJK = UNINITIALIZED_VALUE; + } + + /** + * Constructs a font entry using a font file. + * + * \param aFaceName The name of the corresponding font face. + * \param aFontFile DirectWrite fontfile object + * \param aFontFileStream DirectWrite fontfile stream object + * \param aWeight Weight of the font + * \param aStretch Stretch of the font + * \param aStyle italic or oblique of font + */ + gfxDWriteFontEntry(const nsAString& aFaceName, + IDWriteFontFile *aFontFile, + IDWriteFontFileStream *aFontFileStream, + uint16_t aWeight, + int16_t aStretch, + uint8_t aStyle) + : gfxFontEntry(aFaceName), mFont(nullptr), mFontFile(aFontFile), + mFontFileStream(aFontFileStream), mForceGDIClassic(false) + { + mWeight = aWeight; + mStretch = aStretch; + mStyle = aStyle; + mIsDataUserFont = true; + mIsCJK = UNINITIALIZED_VALUE; + } + + virtual ~gfxDWriteFontEntry(); + + virtual bool IsSymbolFont(); + + virtual hb_blob_t* GetFontTable(uint32_t aTableTag) override; + + nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr); + + bool IsCJKFont(); + + void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } + bool GetForceGDIClassic() { return mForceGDIClassic; } + + virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, + FontListSizes* aSizes) const; + virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, + FontListSizes* aSizes) const; + +protected: + friend class gfxDWriteFont; + friend class gfxDWriteFontList; + + virtual nsresult CopyFontTable(uint32_t aTableTag, + nsTArray<uint8_t>& aBuffer) override; + + virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, + bool aNeedsBold); + + nsresult CreateFontFace( + IDWriteFontFace **aFontFace, + DWRITE_FONT_SIMULATIONS aSimulations = DWRITE_FONT_SIMULATIONS_NONE); + + static bool InitLogFont(IDWriteFont *aFont, LOGFONTW *aLogFont); + + /** + * A fontentry only needs to have either of these. If it has both only + * the IDWriteFont will be used. + */ + RefPtr<IDWriteFont> mFont; + RefPtr<IDWriteFontFile> mFontFile; + + // For custom fonts, we hold a reference to the IDWriteFontFileStream for + // for the IDWriteFontFile, so that the data is available. + RefPtr<IDWriteFontFileStream> mFontFileStream; + + // font face corresponding to the mFont/mFontFile *without* any DWrite + // style simulations applied + RefPtr<IDWriteFontFace> mFontFace; + + DWRITE_FONT_FACE_TYPE mFaceType; + + int8_t mIsCJK; + bool mForceGDIClassic; +}; + +// custom text renderer used to determine the fallback font for a given char +class DWriteFontFallbackRenderer final : public IDWriteTextRenderer +{ +public: + DWriteFontFallbackRenderer(IDWriteFactory *aFactory) + : mRefCount(0) + { + HRESULT hr = S_OK; + + hr = aFactory->GetSystemFontCollection(getter_AddRefs(mSystemFonts)); + NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); + } + + ~DWriteFontFallbackRenderer() + {} + + // IDWriteTextRenderer methods + IFACEMETHOD(DrawGlyphRun)( + void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_MEASURING_MODE measuringMode, + DWRITE_GLYPH_RUN const* glyphRun, + DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, + IUnknown* clientDrawingEffect + ); + + IFACEMETHOD(DrawUnderline)( + void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_UNDERLINE const* underline, + IUnknown* clientDrawingEffect + ) + { + return E_NOTIMPL; + } + + + IFACEMETHOD(DrawStrikethrough)( + void* clientDrawingContext, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + DWRITE_STRIKETHROUGH const* strikethrough, + IUnknown* clientDrawingEffect + ) + { + return E_NOTIMPL; + } + + + IFACEMETHOD(DrawInlineObject)( + void* clientDrawingContext, + FLOAT originX, + FLOAT originY, + IDWriteInlineObject* inlineObject, + BOOL isSideways, + BOOL isRightToLeft, + IUnknown* clientDrawingEffect + ) + { + return E_NOTIMPL; + } + + // IDWritePixelSnapping methods + + IFACEMETHOD(IsPixelSnappingDisabled)( + void* clientDrawingContext, + BOOL* isDisabled + ) + { + *isDisabled = FALSE; + return S_OK; + } + + IFACEMETHOD(GetCurrentTransform)( + void* clientDrawingContext, + DWRITE_MATRIX* transform + ) + { + const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; + *transform = ident; + return S_OK; + } + + IFACEMETHOD(GetPixelsPerDip)( + void* clientDrawingContext, + FLOAT* pixelsPerDip + ) + { + *pixelsPerDip = 1.0f; + return S_OK; + } + + // IUnknown methods + + IFACEMETHOD_(unsigned long, AddRef) () + { + return InterlockedIncrement(&mRefCount); + } + + IFACEMETHOD_(unsigned long, Release) () + { + unsigned long newCount = InterlockedDecrement(&mRefCount); + if (newCount == 0) + { + delete this; + return 0; + } + + return newCount; + } + + IFACEMETHOD(QueryInterface) (IID const& riid, void** ppvObject) + { + if (__uuidof(IDWriteTextRenderer) == riid) { + *ppvObject = this; + } else if (__uuidof(IDWritePixelSnapping) == riid) { + *ppvObject = this; + } else if (__uuidof(IUnknown) == riid) { + *ppvObject = this; + } else { + *ppvObject = nullptr; + return E_FAIL; + } + + this->AddRef(); + return S_OK; + } + + const nsString& FallbackFamilyName() { return mFamilyName; } + +protected: + long mRefCount; + RefPtr<IDWriteFontCollection> mSystemFonts; + nsString mFamilyName; +}; + + + +class gfxDWriteFontList : public gfxPlatformFontList { +public: + gfxDWriteFontList(); + + static gfxDWriteFontList* PlatformFontList() { + return static_cast<gfxDWriteFontList*>(sPlatformFontList); + } + + // initialize font lists + virtual nsresult InitFontListForPlatform() 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); + + bool GetStandardFamilyName(const nsAString& aFontName, + nsAString& aFamilyName); + + IDWriteGdiInterop *GetGDIInterop() { return mGDIInterop; } + bool UseGDIFontTableAccess() { return mGDIFontTableAccess; } + + bool FindAndAddFamilies(const nsAString& aFamily, + nsTArray<gfxFontFamily*>* aOutput, + gfxFontStyle* aStyle = nullptr, + gfxFloat aDevToCssSize = 1.0) override; + + gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; } + + 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; + + // attempt to use platform-specific fallback for the given character, + // return null if no usable result found + gfxFontEntry* + PlatformGlobalFontFallback(const uint32_t aCh, + Script aRunScript, + const gfxFontStyle* aMatchStyle, + gfxFontFamily** aMatchedFamily) override; + +private: + friend class gfxDWriteFontFamily; + + nsresult GetFontSubstitutes(); + + void GetDirectWriteSubstitutes(); + + virtual bool UsesSystemFallback() { return true; } + + void GetFontsFromCollection(IDWriteFontCollection* aCollection); + +#ifdef MOZ_BUNDLED_FONTS + already_AddRefed<IDWriteFontCollection> + CreateBundledFontsCollection(IDWriteFactory* aFactory); +#endif + + /** + * Fonts listed in the registry as substitutes but for which no actual + * font family is found. + */ + nsTArray<nsString> mNonExistingFonts; + + /** + * Table of font substitutes, we grab this from the registry to get + * alternative font names. + */ + FontFamilyTable mFontSubstitutes; + + virtual already_AddRefed<FontInfoData> CreateFontInfoData(); + + gfxFloat mForceGDIClassicMaxFontSize; + + // whether to use GDI font table access routines + bool mGDIFontTableAccess; + RefPtr<IDWriteGdiInterop> mGDIInterop; + + RefPtr<DWriteFontFallbackRenderer> mFallbackRenderer; + RefPtr<IDWriteTextFormat> mFallbackFormat; + + RefPtr<IDWriteFontCollection> mSystemFonts; +#ifdef MOZ_BUNDLED_FONTS + RefPtr<IDWriteFontCollection> mBundledFonts; +#endif +}; + + +#endif /* GFX_DWRITEFONTLIST_H */ |