michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef GFX_DWRITEFONTLIST_H michael@0: #define GFX_DWRITEFONTLIST_H michael@0: michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "gfxDWriteCommon.h" michael@0: michael@0: #include "gfxFont.h" michael@0: #include "gfxUserFontSet.h" michael@0: #include "cairo-win32.h" michael@0: michael@0: #include "gfxPlatformFontList.h" michael@0: #include "gfxPlatform.h" michael@0: #include michael@0: michael@0: michael@0: /** michael@0: * gfxDWriteFontFamily is a class that describes one of the fonts on the michael@0: * users system. It holds each gfxDWriteFontEntry (maps more directly to michael@0: * a font face) which holds font type, charset info and character map info. michael@0: */ michael@0: class gfxDWriteFontEntry; michael@0: michael@0: /** michael@0: * \brief Class representing directwrite font family. michael@0: */ michael@0: class gfxDWriteFontFamily : public gfxFontFamily michael@0: { michael@0: public: michael@0: /** michael@0: * Constructs a new DWriteFont Family. michael@0: * michael@0: * \param aName Name identifying the family michael@0: * \param aFamily IDWriteFontFamily object representing the directwrite michael@0: * family object. michael@0: */ michael@0: gfxDWriteFontFamily(const nsAString& aName, michael@0: IDWriteFontFamily *aFamily) michael@0: : gfxFontFamily(aName), mDWFamily(aFamily), mForceGDIClassic(false) {} michael@0: virtual ~gfxDWriteFontFamily(); michael@0: michael@0: virtual void FindStyleVariations(FontInfoData *aFontInfoData = nullptr); michael@0: michael@0: virtual void LocalizedName(nsAString& aLocalizedName); michael@0: michael@0: virtual void ReadFaceNames(gfxPlatformFontList *aPlatformFontList, michael@0: bool aNeedFullnamePostscriptNames); michael@0: michael@0: void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } michael@0: michael@0: virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: FontListSizes* aSizes) const; michael@0: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: FontListSizes* aSizes) const; michael@0: michael@0: protected: michael@0: /** This font family's directwrite fontfamily object */ michael@0: nsRefPtr mDWFamily; michael@0: bool mForceGDIClassic; michael@0: }; michael@0: michael@0: /** michael@0: * \brief Class representing DirectWrite FontEntry (a unique font style/family) michael@0: */ michael@0: class gfxDWriteFontEntry : public gfxFontEntry michael@0: { michael@0: public: michael@0: /** michael@0: * Constructs a font entry. michael@0: * michael@0: * \param aFaceName The name of the corresponding font face. michael@0: * \param aFont DirectWrite font object michael@0: */ michael@0: gfxDWriteFontEntry(const nsAString& aFaceName, michael@0: IDWriteFont *aFont) michael@0: : gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr), michael@0: mForceGDIClassic(false) michael@0: { michael@0: mItalic = (aFont->GetStyle() == DWRITE_FONT_STYLE_ITALIC || michael@0: aFont->GetStyle() == DWRITE_FONT_STYLE_OBLIQUE); michael@0: mStretch = FontStretchFromDWriteStretch(aFont->GetStretch()); michael@0: uint16_t weight = NS_ROUNDUP(aFont->GetWeight() - 50, 100); michael@0: michael@0: weight = std::max(100, weight); michael@0: weight = std::min(900, weight); michael@0: mWeight = weight; michael@0: michael@0: mIsCJK = UNINITIALIZED_VALUE; michael@0: } michael@0: michael@0: /** michael@0: * Constructs a font entry using a font. But with custom font values. michael@0: * This is used for creating correct font entries for @font-face with local michael@0: * font source. michael@0: * michael@0: * \param aFaceName The name of the corresponding font face. michael@0: * \param aFont DirectWrite font object michael@0: * \param aWeight Weight of the font michael@0: * \param aStretch Stretch of the font michael@0: * \param aItalic True if italic michael@0: */ michael@0: gfxDWriteFontEntry(const nsAString& aFaceName, michael@0: IDWriteFont *aFont, michael@0: uint16_t aWeight, michael@0: int16_t aStretch, michael@0: bool aItalic) michael@0: : gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr), michael@0: mForceGDIClassic(false) michael@0: { michael@0: mWeight = aWeight; michael@0: mStretch = aStretch; michael@0: mItalic = aItalic; michael@0: mIsUserFont = true; michael@0: mIsLocalUserFont = true; michael@0: mIsCJK = UNINITIALIZED_VALUE; michael@0: } michael@0: michael@0: /** michael@0: * Constructs a font entry using a font file. michael@0: * michael@0: * \param aFaceName The name of the corresponding font face. michael@0: * \param aFontFile DirectWrite fontfile object michael@0: * \param aWeight Weight of the font michael@0: * \param aStretch Stretch of the font michael@0: * \param aItalic True if italic michael@0: */ michael@0: gfxDWriteFontEntry(const nsAString& aFaceName, michael@0: IDWriteFontFile *aFontFile, michael@0: uint16_t aWeight, michael@0: int16_t aStretch, michael@0: bool aItalic) michael@0: : gfxFontEntry(aFaceName), mFont(nullptr), mFontFile(aFontFile), michael@0: mForceGDIClassic(false) michael@0: { michael@0: mWeight = aWeight; michael@0: mStretch = aStretch; michael@0: mItalic = aItalic; michael@0: mIsUserFont = true; michael@0: mIsCJK = UNINITIALIZED_VALUE; michael@0: } michael@0: michael@0: virtual ~gfxDWriteFontEntry(); michael@0: michael@0: virtual bool IsSymbolFont(); michael@0: michael@0: virtual hb_blob_t* GetFontTable(uint32_t aTableTag) MOZ_OVERRIDE; michael@0: michael@0: nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr); michael@0: michael@0: bool IsCJKFont(); michael@0: michael@0: void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; } michael@0: bool GetForceGDIClassic() { return mForceGDIClassic; } michael@0: michael@0: virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: FontListSizes* aSizes) const; michael@0: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: FontListSizes* aSizes) const; michael@0: michael@0: protected: michael@0: friend class gfxDWriteFont; michael@0: friend class gfxDWriteFontList; michael@0: michael@0: virtual nsresult CopyFontTable(uint32_t aTableTag, michael@0: FallibleTArray& aBuffer) MOZ_OVERRIDE; michael@0: michael@0: virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, michael@0: bool aNeedsBold); michael@0: michael@0: nsresult CreateFontFace( michael@0: IDWriteFontFace **aFontFace, michael@0: DWRITE_FONT_SIMULATIONS aSimulations = DWRITE_FONT_SIMULATIONS_NONE); michael@0: michael@0: static bool InitLogFont(IDWriteFont *aFont, LOGFONTW *aLogFont); michael@0: michael@0: /** michael@0: * A fontentry only needs to have either of these. If it has both only michael@0: * the IDWriteFont will be used. michael@0: */ michael@0: nsRefPtr mFont; michael@0: nsRefPtr mFontFile; michael@0: michael@0: // font face corresponding to the mFont/mFontFile *without* any DWrite michael@0: // style simulations applied michael@0: nsRefPtr mFontFace; michael@0: michael@0: DWRITE_FONT_FACE_TYPE mFaceType; michael@0: michael@0: int8_t mIsCJK; michael@0: bool mForceGDIClassic; michael@0: }; michael@0: michael@0: // custom text renderer used to determine the fallback font for a given char michael@0: class FontFallbackRenderer MOZ_FINAL : public IDWriteTextRenderer michael@0: { michael@0: public: michael@0: FontFallbackRenderer(IDWriteFactory *aFactory) michael@0: : mRefCount(0) michael@0: { michael@0: HRESULT hr = S_OK; michael@0: michael@0: hr = aFactory->GetSystemFontCollection(getter_AddRefs(mSystemFonts)); michael@0: NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); michael@0: } michael@0: michael@0: ~FontFallbackRenderer() michael@0: {} michael@0: michael@0: // IDWriteTextRenderer methods michael@0: IFACEMETHOD(DrawGlyphRun)( michael@0: void* clientDrawingContext, michael@0: FLOAT baselineOriginX, michael@0: FLOAT baselineOriginY, michael@0: DWRITE_MEASURING_MODE measuringMode, michael@0: DWRITE_GLYPH_RUN const* glyphRun, michael@0: DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, michael@0: IUnknown* clientDrawingEffect michael@0: ); michael@0: michael@0: IFACEMETHOD(DrawUnderline)( michael@0: void* clientDrawingContext, michael@0: FLOAT baselineOriginX, michael@0: FLOAT baselineOriginY, michael@0: DWRITE_UNDERLINE const* underline, michael@0: IUnknown* clientDrawingEffect michael@0: ) michael@0: { michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: michael@0: IFACEMETHOD(DrawStrikethrough)( michael@0: void* clientDrawingContext, michael@0: FLOAT baselineOriginX, michael@0: FLOAT baselineOriginY, michael@0: DWRITE_STRIKETHROUGH const* strikethrough, michael@0: IUnknown* clientDrawingEffect michael@0: ) michael@0: { michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: michael@0: IFACEMETHOD(DrawInlineObject)( michael@0: void* clientDrawingContext, michael@0: FLOAT originX, michael@0: FLOAT originY, michael@0: IDWriteInlineObject* inlineObject, michael@0: BOOL isSideways, michael@0: BOOL isRightToLeft, michael@0: IUnknown* clientDrawingEffect michael@0: ) michael@0: { michael@0: return E_NOTIMPL; michael@0: } michael@0: michael@0: // IDWritePixelSnapping methods michael@0: michael@0: IFACEMETHOD(IsPixelSnappingDisabled)( michael@0: void* clientDrawingContext, michael@0: BOOL* isDisabled michael@0: ) michael@0: { michael@0: *isDisabled = FALSE; michael@0: return S_OK; michael@0: } michael@0: michael@0: IFACEMETHOD(GetCurrentTransform)( michael@0: void* clientDrawingContext, michael@0: DWRITE_MATRIX* transform michael@0: ) michael@0: { michael@0: const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; michael@0: *transform = ident; michael@0: return S_OK; michael@0: } michael@0: michael@0: IFACEMETHOD(GetPixelsPerDip)( michael@0: void* clientDrawingContext, michael@0: FLOAT* pixelsPerDip michael@0: ) michael@0: { michael@0: *pixelsPerDip = 1.0f; michael@0: return S_OK; michael@0: } michael@0: michael@0: // IUnknown methods michael@0: michael@0: IFACEMETHOD_(unsigned long, AddRef) () michael@0: { michael@0: return InterlockedIncrement(&mRefCount); michael@0: } michael@0: michael@0: IFACEMETHOD_(unsigned long, Release) () michael@0: { michael@0: unsigned long newCount = InterlockedDecrement(&mRefCount); michael@0: if (newCount == 0) michael@0: { michael@0: delete this; michael@0: return 0; michael@0: } michael@0: michael@0: return newCount; michael@0: } michael@0: michael@0: IFACEMETHOD(QueryInterface) (IID const& riid, void** ppvObject) michael@0: { michael@0: if (__uuidof(IDWriteTextRenderer) == riid) { michael@0: *ppvObject = this; michael@0: } else if (__uuidof(IDWritePixelSnapping) == riid) { michael@0: *ppvObject = this; michael@0: } else if (__uuidof(IUnknown) == riid) { michael@0: *ppvObject = this; michael@0: } else { michael@0: *ppvObject = nullptr; michael@0: return E_FAIL; michael@0: } michael@0: michael@0: this->AddRef(); michael@0: return S_OK; michael@0: } michael@0: michael@0: const nsString& FallbackFamilyName() { return mFamilyName; } michael@0: michael@0: protected: michael@0: long mRefCount; michael@0: nsRefPtr mSystemFonts; michael@0: nsString mFamilyName; michael@0: }; michael@0: michael@0: michael@0: michael@0: class gfxDWriteFontList : public gfxPlatformFontList { michael@0: public: michael@0: gfxDWriteFontList(); michael@0: michael@0: static gfxDWriteFontList* PlatformFontList() { michael@0: return static_cast(sPlatformFontList); michael@0: } michael@0: michael@0: // initialize font lists michael@0: virtual nsresult InitFontList(); michael@0: michael@0: virtual gfxFontFamily* GetDefaultFont(const gfxFontStyle* aStyle); michael@0: michael@0: virtual gfxFontEntry* LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, michael@0: const nsAString& aFontName); michael@0: michael@0: virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, michael@0: const uint8_t *aFontData, michael@0: uint32_t aLength); michael@0: michael@0: virtual bool ResolveFontName(const nsAString& aFontName, michael@0: nsAString& aResolvedFontName); michael@0: michael@0: bool GetStandardFamilyName(const nsAString& aFontName, michael@0: nsAString& aFamilyName); michael@0: michael@0: IDWriteGdiInterop *GetGDIInterop() { return mGDIInterop; } michael@0: bool UseGDIFontTableAccess() { return mGDIFontTableAccess; } michael@0: michael@0: virtual gfxFontFamily* FindFamily(const nsAString& aFamily); michael@0: michael@0: virtual void GetFontFamilyList(nsTArray >& aFamilyArray); michael@0: michael@0: gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; } michael@0: michael@0: virtual void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: FontListSizes* aSizes) const; michael@0: virtual void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: FontListSizes* aSizes) const; michael@0: michael@0: private: michael@0: friend class gfxDWriteFontFamily; michael@0: michael@0: nsresult GetFontSubstitutes(); michael@0: michael@0: void GetDirectWriteSubstitutes(); michael@0: michael@0: // search fonts system-wide for a given character, null otherwise michael@0: virtual gfxFontEntry* GlobalFontFallback(const uint32_t aCh, michael@0: int32_t aRunScript, michael@0: const gfxFontStyle* aMatchStyle, michael@0: uint32_t& aCmapCount, michael@0: gfxFontFamily** aMatchedFamily); michael@0: michael@0: virtual bool UsesSystemFallback() { return true; } michael@0: michael@0: /** michael@0: * Fonts listed in the registry as substitutes but for which no actual michael@0: * font family is found. michael@0: */ michael@0: nsTArray mNonExistingFonts; michael@0: michael@0: typedef nsRefPtrHashtable FontTable; michael@0: michael@0: /** michael@0: * Table of font substitutes, we grab this from the registry to get michael@0: * alternative font names. michael@0: */ michael@0: FontTable mFontSubstitutes; michael@0: michael@0: bool mInitialized; michael@0: virtual nsresult DelayedInitFontList(); michael@0: michael@0: virtual already_AddRefed CreateFontInfoData(); michael@0: michael@0: gfxFloat mForceGDIClassicMaxFontSize; michael@0: michael@0: // whether to use GDI font table access routines michael@0: bool mGDIFontTableAccess; michael@0: nsRefPtr mGDIInterop; michael@0: michael@0: nsRefPtr mFallbackRenderer; michael@0: nsRefPtr mFallbackFormat; michael@0: }; michael@0: michael@0: michael@0: #endif /* GFX_DWRITEFONTLIST_H */