From fb35888c83aa39138a4b3ae7449bfd08e47391de Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Mon, 21 Dec 2015 20:33:14 +0000 Subject: [PATCH] Bug 1156742 Part 24: Add new Recorded event to record font data. r=bas We create and destroy ScaledFonts for every piece of text we write. That causes a huge amount of duplicated data within the recording. This splits out the recording of the font data itself from the ScaledFont. The key generated to determine uniqueness could probably be fairly easily faked, but for our purposes that doesn't matter. --- gfx/2d/2D.h | 34 ++- gfx/2d/DrawEventRecorder.h | 11 + gfx/2d/DrawTargetRecording.cpp | 10 +- gfx/2d/Factory.cpp | 30 +- gfx/2d/NativeFontResourceDWrite.cpp | 287 +++++++++++++++++++ gfx/2d/NativeFontResourceDWrite.h | 56 ++++ gfx/2d/NativeFontResourceGDI.cpp | 112 ++++++++ gfx/2d/NativeFontResourceGDI.h | 57 ++++ gfx/2d/RecordedEvent.cpp | 95 ++++-- gfx/2d/RecordedEvent.h | 70 ++++- gfx/2d/SFNTData.cpp | 37 ++- gfx/2d/SFNTData.h | 20 ++ gfx/2d/ScaledFontDWrite.cpp | 247 ---------------- gfx/2d/ScaledFontDWrite.h | 4 - gfx/2d/ScaledFontWin.cpp | 52 ---- gfx/2d/ScaledFontWin.h | 15 - gfx/2d/moz.build | 2 + layout/printing/PrintTranslator.cpp | 2 +- layout/printing/PrintTranslator.h | 24 +- layout/printing/ipc/RemotePrintJobParent.cpp | 2 - 20 files changed, 773 insertions(+), 394 deletions(-) create mode 100644 gfx/2d/NativeFontResourceDWrite.cpp create mode 100644 gfx/2d/NativeFontResourceDWrite.h create mode 100644 gfx/2d/NativeFontResourceGDI.cpp create mode 100644 gfx/2d/NativeFontResourceGDI.h diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 98afd9e004d7..6609f550dd1b 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -667,6 +667,29 @@ protected: UserData mUserData; }; +/** + * Derived classes hold a native font resource from which to create + * ScaledFonts. + */ +class NativeFontResource : public RefCounted +{ +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResource) + + /** + * Creates a ScaledFont using the font corresponding to the index and + * the given glyph size. + * + * @param aIndex index for the font within the resource. + * @param aGlyphSize the size of ScaledFont required. + * @return an already_addrefed ScaledFont, containing nullptr if failed. + */ + virtual already_AddRefed + CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) = 0; + + virtual ~NativeFontResource() {}; +}; + /** This class is designed to allow passing additional glyph rendering * parameters to the glyph drawing functions. This is an empty wrapper class * merely used to allow holding on to and passing around platform specific @@ -1192,16 +1215,15 @@ public: CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSize); /** - * This creates a ScaledFont from TrueType data. + * This creates a NativeFontResource from TrueType data. * * @param aData Pointer to the data * @param aSize Size of the TrueType data - * @param aFaceIndex Index of the font face in the truetype data this ScaledFont needs to represent. - * @param aGlyphSize Size of the glyphs in this ScaledFont - * @param aType Type of ScaledFont that should be created. + * @param aType Type of NativeFontResource that should be created. + * @return a NativeFontResource of nullptr if failed. */ - static already_AddRefed - CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, uint32_t aFaceIndex, Float aGlyphSize, FontType aType); + static already_AddRefed + CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType); /** * This creates a scaled font with an associated cairo_scaled_font_t, and diff --git a/gfx/2d/DrawEventRecorder.h b/gfx/2d/DrawEventRecorder.h index 15d23d395865..611fd880bf66 100644 --- a/gfx/2d/DrawEventRecorder.h +++ b/gfx/2d/DrawEventRecorder.h @@ -46,6 +46,14 @@ public: return mStoredObjects.find(aObject) != mStoredObjects.end(); } + void AddStoredFontData(const uint64_t aFontDataKey) { + mStoredFontData.insert(aFontDataKey); + } + + bool HasStoredFontData(const uint64_t aFontDataKey) { + return mStoredFontData.find(aFontDataKey) != mStoredFontData.end(); + } + protected: std::ostream *mOutputStream; @@ -53,11 +61,14 @@ protected: #if defined(_MSC_VER) typedef std::unordered_set ObjectSet; + typedef std::unordered_set Uint64Set; #else typedef std::set ObjectSet; + typedef std::set Uint64Set; #endif ObjectSet mStoredObjects; + Uint64Set mStoredFontData; }; class DrawEventRecorderFile : public DrawEventRecorderPrivate diff --git a/gfx/2d/DrawTargetRecording.cpp b/gfx/2d/DrawTargetRecording.cpp index 75a3b5d37391..8940667b8f35 100644 --- a/gfx/2d/DrawTargetRecording.cpp +++ b/gfx/2d/DrawTargetRecording.cpp @@ -392,7 +392,15 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont, if (!aFont->GetUserData(reinterpret_cast(mRecorder.get()))) { // TODO support font in b2g recordings #ifndef MOZ_WIDGET_GONK - mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, aFont)); + RecordedFontData fontData(aFont); + RecordedFontDetails fontDetails; + if (fontData.GetFontDetails(fontDetails)) { + if (!mRecorder->HasStoredFontData(fontDetails.fontDataKey)) { + mRecorder->RecordEvent(fontData); + mRecorder->AddStoredFontData(fontDetails.fontDataKey); + } + mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, fontDetails)); + } #endif RecordingFontUserData *userData = new RecordingFontUserData; userData->refPtr = aFont; diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index 48dbf0eda1f0..d1b5fa724a72 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -21,6 +21,7 @@ #if defined(WIN32) #include "ScaledFontWin.h" +#include "NativeFontResourceGDI.h" #endif #ifdef XP_DARWIN @@ -36,6 +37,7 @@ #include "DrawTargetD2D.h" #include "DrawTargetD2D1.h" #include "ScaledFontDWrite.h" +#include "NativeFontResourceDWrite.h" #include #include "HelpersD2D.h" #endif @@ -540,41 +542,35 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz } } -already_AddRefed -Factory::CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, - uint32_t aFaceIndex, Float aGlyphSize, - FontType aType) +already_AddRefed +Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, + FontType aType) { switch (aType) { #ifdef WIN32 case FontType::DWRITE: { - return MakeAndAddRef(aData, aSize, aFaceIndex, aGlyphSize); + return NativeFontResourceDWrite::Create(aData, aSize, + /* aNeedsCairo = */ false); } #endif case FontType::CAIRO: { - RefPtr scaledFont; - #ifdef WIN32 if (GetDirect3D11Device()) { - scaledFont = new ScaledFontDWrite(aData, aSize, aFaceIndex, aGlyphSize); + return NativeFontResourceDWrite::Create(aData, aSize, + /* aNeedsCairo = */ true); } else { - scaledFont = new ScaledFontWin(aData, aSize, aFaceIndex, aGlyphSize); - } - - if (!scaledFont->PopulateCairoScaledFont()) { - gfxWarning() << "Unable to create cairo scaled font from truetype data"; - return nullptr; + return NativeFontResourceGDI::Create(aData, aSize, + /* aNeedsCairo = */ true); } #else gfxWarning() << "Unable to create cairo scaled font from truetype data"; + return nullptr; #endif - - return scaledFont.forget(); } default: - gfxWarning() << "Unable to create requested font type from truetype data"; + gfxWarning() << "Unable to create requested font resource from truetype data"; return nullptr; } } diff --git a/gfx/2d/NativeFontResourceDWrite.cpp b/gfx/2d/NativeFontResourceDWrite.cpp new file mode 100644 index 000000000000..10b0486de832 --- /dev/null +++ b/gfx/2d/NativeFontResourceDWrite.cpp @@ -0,0 +1,287 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "NativeFontResourceDWrite.h" + +#include + +#include "DrawTargetD2D.h" +#include "Logging.h" +#include "mozilla/RefPtr.h" + +namespace mozilla { +namespace gfx { + +static Atomic sNextFontFileKey; +static std::unordered_map sFontFileStreams; + +class DWriteFontFileLoader : public IDWriteFontFileLoader +{ +public: + DWriteFontFileLoader() + { + } + + // IUnknown interface + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) + { + if (iid == __uuidof(IDWriteFontFileLoader)) { + *ppObject = static_cast(this); + return S_OK; + } else if (iid == __uuidof(IUnknown)) { + *ppObject = static_cast(this); + return S_OK; + } else { + return E_NOINTERFACE; + } + } + + IFACEMETHOD_(ULONG, AddRef)() + { + return 1; + } + + IFACEMETHOD_(ULONG, Release)() + { + return 1; + } + + // IDWriteFontFileLoader methods + /** + * Important! Note the key here has to be a uint64_t that will have been + * generated by incrementing sNextFontFileKey. + */ + virtual HRESULT STDMETHODCALLTYPE + CreateStreamFromKey(void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + OUT IDWriteFontFileStream** fontFileStream); + + /** + * Gets the singleton loader instance. Note that when using this font + * loader, the key must be a uint64_t that has been generated by incrementing + * sNextFontFileKey. + * Also note that this is _not_ threadsafe. + */ + static IDWriteFontFileLoader* Instance() + { + if (!mInstance) { + mInstance = new DWriteFontFileLoader(); + DrawTargetD2D::GetDWriteFactory()-> + RegisterFontFileLoader(mInstance); + } + return mInstance; + } + +private: + static IDWriteFontFileLoader* mInstance; +}; + +class DWriteFontFileStream : public IDWriteFontFileStream +{ +public: + /** + * Used by the FontFileLoader to create a new font stream, + * this font stream is created from data in memory. The memory + * passed may be released after object creation, it will be + * copied internally. + * + * @param aData Font data + */ + DWriteFontFileStream(uint8_t *aData, uint32_t aSize, uint64_t aFontFileKey); + ~DWriteFontFileStream(); + + // IUnknown interface + IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) + { + if (iid == __uuidof(IDWriteFontFileStream)) { + *ppObject = static_cast(this); + return S_OK; + } else if (iid == __uuidof(IUnknown)) { + *ppObject = static_cast(this); + return S_OK; + } else { + return E_NOINTERFACE; + } + } + + IFACEMETHOD_(ULONG, AddRef)() + { + ++mRefCnt; + return mRefCnt; + } + + IFACEMETHOD_(ULONG, Release)() + { + --mRefCnt; + if (mRefCnt == 0) { + delete this; + return 0; + } + return mRefCnt; + } + + // IDWriteFontFileStream methods + virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart, + UINT64 fileOffset, + UINT64 fragmentSize, + OUT void** fragmentContext); + + virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext); + + virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize); + + virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime); + +private: + std::vector mData; + uint32_t mRefCnt; + uint64_t mFontFileKey; +}; + +IDWriteFontFileLoader* DWriteFontFileLoader::mInstance = nullptr; + +HRESULT STDMETHODCALLTYPE +DWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + IDWriteFontFileStream **fontFileStream) +{ + if (!fontFileReferenceKey || !fontFileStream) { + return E_POINTER; + } + + uint64_t fontFileKey = *static_cast(fontFileReferenceKey); + auto found = sFontFileStreams.find(fontFileKey); + if (found == sFontFileStreams.end()) { + *fontFileStream = nullptr; + return E_FAIL; + } + + found->second->AddRef(); + *fontFileStream = found->second; + return S_OK; +} + +DWriteFontFileStream::DWriteFontFileStream(uint8_t *aData, uint32_t aSize, + uint64_t aFontFileKey) + : mRefCnt(0) + , mFontFileKey(aFontFileKey) +{ + mData.resize(aSize); + memcpy(&mData.front(), aData, aSize); +} + +DWriteFontFileStream::~DWriteFontFileStream() +{ + sFontFileStreams.erase(mFontFileKey); +} + +HRESULT STDMETHODCALLTYPE +DWriteFontFileStream::GetFileSize(UINT64 *fileSize) +{ + *fileSize = mData.size(); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +DWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime) +{ + return E_NOTIMPL; +} + +HRESULT STDMETHODCALLTYPE +DWriteFontFileStream::ReadFileFragment(const void **fragmentStart, + UINT64 fileOffset, + UINT64 fragmentSize, + void **fragmentContext) +{ + // We are required to do bounds checking. + if (fileOffset + fragmentSize > mData.size()) { + return E_FAIL; + } + + // truncate the 64 bit fileOffset to size_t sized index into mData + size_t index = static_cast(fileOffset); + + // We should be alive for the duration of this. + *fragmentStart = &mData[index]; + *fragmentContext = nullptr; + return S_OK; +} + +void STDMETHODCALLTYPE +DWriteFontFileStream::ReleaseFileFragment(void *fragmentContext) +{ +} + +/* static */ +already_AddRefed +NativeFontResourceDWrite::Create(uint8_t *aFontData, uint32_t aDataLength, + bool aNeedsCairo) +{ + IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory(); + if (!factory) { + gfxWarning() << "Failed to get DWrite Factory."; + return nullptr; + } + + uint64_t fontFileKey = sNextFontFileKey++; + RefPtr ffsRef = + new DWriteFontFileStream(aFontData, aDataLength, fontFileKey); + sFontFileStreams[fontFileKey] = ffsRef; + + RefPtr fontFile; + HRESULT hr = + factory->CreateCustomFontFileReference(&fontFileKey, sizeof(fontFileKey), + DWriteFontFileLoader::Instance(), + getter_AddRefs(fontFile)); + if (FAILED(hr)) { + gfxWarning() << "Failed to load font file from data!"; + return nullptr; + } + + BOOL isSupported; + DWRITE_FONT_FILE_TYPE fileType; + DWRITE_FONT_FACE_TYPE faceType; + UINT32 numberOfFaces; + hr = fontFile->Analyze(&isSupported, &fileType, &faceType, &numberOfFaces); + if (FAILED(hr) || !isSupported) { + gfxWarning() << "Font file is not supported."; + return nullptr; + } + + RefPtr fontResource = + new NativeFontResourceDWrite(factory, fontFile.forget(), faceType, + numberOfFaces, aNeedsCairo); + return fontResource.forget(); +} + +already_AddRefed +NativeFontResourceDWrite::CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) +{ + if (aIndex >= mNumberOfFaces) { + gfxWarning() << "Font face index is too high for font resource."; + return nullptr; + } + + IDWriteFontFile *fontFile = mFontFile; + RefPtr fontFace; + if (FAILED(mFactory->CreateFontFace(mFaceType, 1, &fontFile, aIndex, + DWRITE_FONT_SIMULATIONS_NONE, getter_AddRefs(fontFace)))) { + gfxWarning() << "Failed to create font face from font file data."; + return nullptr; + } + + RefPtr scaledFont = new ScaledFontDWrite(fontFace, aGlyphSize); + if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) { + gfxWarning() << "Unable to create cairo scaled font DWrite font."; + return nullptr; + } + + return scaledFont.forget(); +} + +} // gfx +} // mozilla diff --git a/gfx/2d/NativeFontResourceDWrite.h b/gfx/2d/NativeFontResourceDWrite.h new file mode 100644 index 000000000000..0c7bf9d9335f --- /dev/null +++ b/gfx/2d/NativeFontResourceDWrite.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 mozilla_gfx_NativeFontResourceDWrite_h +#define mozilla_gfx_NativeFontResourceDWrite_h + +#include + +#include "2D.h" +#include "mozilla/AlreadyAddRefed.h" + +namespace mozilla { +namespace gfx { + +class NativeFontResourceDWrite final : public NativeFontResource +{ +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceDWrite) + /** + * Creates a NativeFontResourceDWrite if data is valid. Note aFontData will be + * copied if required and so can be released after calling. + * + * @param aFontData the SFNT data. + * @param aDataLength length of data. + * @param aNeedsCairo whether the ScaledFont created needs a cairo scaled font + * @return Referenced NativeFontResourceDWrite or nullptr if invalid. + */ + static already_AddRefed + Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo); + + already_AddRefed + CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) final; + +private: + NativeFontResourceDWrite(IDWriteFactory *aFactory, + already_AddRefed aFontFile, + DWRITE_FONT_FACE_TYPE aFaceType, + uint32_t aNumberOfFaces, bool aNeedsCairo) + : mFactory(aFactory), mFontFile(aFontFile), mFaceType(aFaceType) + , mNumberOfFaces(aNumberOfFaces), mNeedsCairo(aNeedsCairo) + {} + + IDWriteFactory *mFactory; + RefPtr mFontFile; + DWRITE_FONT_FACE_TYPE mFaceType; + uint32_t mNumberOfFaces; + bool mNeedsCairo; +}; + +} // gfx +} // mozilla + +#endif // mozilla_gfx_NativeFontResourceDWrite_h \ No newline at end of file diff --git a/gfx/2d/NativeFontResourceGDI.cpp b/gfx/2d/NativeFontResourceGDI.cpp new file mode 100644 index 000000000000..98c176a6df57 --- /dev/null +++ b/gfx/2d/NativeFontResourceGDI.cpp @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "NativeFontResourceGDI.h" + +#include "Logging.h" +#include "mozilla/RefPtr.h" +#include "ScaledFontWin.h" +#include "SFNTData.h" + +namespace mozilla { +namespace gfx { + +/* static */ +already_AddRefed +NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength, + bool aNeedsCairo) +{ + UniquePtr sfntData = SFNTData::Create(aFontData, aDataLength); + if (!sfntData) { + gfxWarning() << "Failed to create SFNTData for ScaledFontWin."; + return nullptr; + } + + Vector fontNames; + if (!sfntData->GetU16FullNames(fontNames)) { + gfxWarning() << "Failed to get font names from font."; + return nullptr; + } + + // lfFaceName has a maximum length including null. + for (size_t i = 0; i < fontNames.length(); ++i) { + if (fontNames[i].size() > LF_FACESIZE - 1) { + fontNames[i].resize(LF_FACESIZE - 1); + } + // Add null to end for easy copying later. + fontNames[i].append(1, '\0'); + } + + DWORD numberOfFontsAdded; + HANDLE fontResourceHandle = ::AddFontMemResourceEx(aFontData, aDataLength, + 0, &numberOfFontsAdded); + if (!fontResourceHandle) { + gfxWarning() << "Failed to add memory font resource."; + return nullptr; + } + + if (numberOfFontsAdded != fontNames.length()) { + gfxWarning() << + "Number of fonts added doesn't match number of names extracted."; + } + + RefPtr fontResouce = + new NativeFontResourceGDI(fontResourceHandle, Move(fontNames), aNeedsCairo); + + return fontResouce.forget(); +} + +NativeFontResourceGDI::~NativeFontResourceGDI() +{ + ::RemoveFontMemResourceEx(mFontResourceHandle); +} + +already_AddRefed +NativeFontResourceGDI::CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) +{ + if (aIndex >= mFontNames.length()) { + gfxWarning() << "Font index is too high for font resource."; + return nullptr; + } + + if (mFontNames[aIndex].empty()) { + gfxWarning() << "Font name for index is empty."; + return nullptr; + } + + LOGFONT logFont; + logFont.lfHeight = 0; + logFont.lfWidth = 0; + logFont.lfEscapement = 0; + logFont.lfOrientation = 0; + logFont.lfWeight = FW_DONTCARE; + logFont.lfItalic = FALSE; + logFont.lfUnderline = FALSE; + logFont.lfStrikeOut = FALSE; + logFont.lfCharSet = DEFAULT_CHARSET; + logFont.lfOutPrecision = OUT_DEFAULT_PRECIS; + logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; + logFont.lfQuality = DEFAULT_QUALITY; + logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + + // Copy name to mLogFont (null already included in font name). We cast here + // because for VS2015 char16_t != wchar_t, even though they are both 16 bit. + mFontNames[aIndex].copy(reinterpret_cast(logFont.lfFaceName), + mFontNames[aIndex].length()); + + // Constructor for ScaledFontWin dereferences and copies the LOGFONT, so we + // are safe to pass this reference. + RefPtr scaledFont = new ScaledFontWin(&logFont, aGlyphSize); + if (mNeedsCairo && !scaledFont->PopulateCairoScaledFont()) { + gfxWarning() << "Unable to create cairo scaled font DWrite font."; + return nullptr; + } + + return scaledFont.forget(); +} + +} // gfx +} // mozilla diff --git a/gfx/2d/NativeFontResourceGDI.h b/gfx/2d/NativeFontResourceGDI.h new file mode 100644 index 000000000000..aa5bceb97459 --- /dev/null +++ b/gfx/2d/NativeFontResourceGDI.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 mozilla_gfx_NativeFontResourceGDI_h +#define mozilla_gfx_NativeFontResourceGDI_h + +#include + +#include "2D.h" +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/Vector.h" +#include "u16string.h" + +namespace mozilla { +namespace gfx { + +class NativeFontResourceGDI final : public NativeFontResource +{ +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(NativeFontResourceGDI) + /** + * Creates a NativeFontResourceGDI if data is valid. Note aFontData will be + * copied if required and so can be released after calling. + * + * @param aFontData the SFNT data. + * @param aDataLength length of data. + * @param aNeedsCairo whether the ScaledFont created need a cairo scaled font + * @return Referenced NativeFontResourceGDI or nullptr if invalid. + */ + static already_AddRefed + Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo); + + ~NativeFontResourceGDI(); + + already_AddRefed + CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) final; + +private: + NativeFontResourceGDI(HANDLE aFontResourceHandle, + Vector&& aFontNames, + bool aNeedsCairo) + : mFontResourceHandle(aFontResourceHandle), mFontNames(Move(aFontNames)) + , mNeedsCairo(aNeedsCairo) + {} + + HANDLE mFontResourceHandle; + Vector mFontNames; + bool mNeedsCairo; +}; + +} // gfx +} // mozilla + +#endif // mozilla_gfx_NativeFontResourceGDI_h \ No newline at end of file diff --git a/gfx/2d/RecordedEvent.cpp b/gfx/2d/RecordedEvent.cpp index 2b3ead74cdd0..c386453d8311 100644 --- a/gfx/2d/RecordedEvent.cpp +++ b/gfx/2d/RecordedEvent.cpp @@ -10,6 +10,7 @@ #include "Tools.h" #include "Filters.h" #include "Logging.h" +#include "SFNTData.h" namespace mozilla { namespace gfx { @@ -78,6 +79,7 @@ RecordedEvent::LoadEventFromStream(std::istream &aStream, EventType aType) LOAD_EVENT_TYPE(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute); LOAD_EVENT_TYPE(FILTERNODESETINPUT, RecordedFilterNodeSetInput); LOAD_EVENT_TYPE(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget); + LOAD_EVENT_TYPE(FONTDATA, RecordedFontData); default: return nullptr; } @@ -153,6 +155,8 @@ RecordedEvent::GetEventName(EventType aType) return "SetInput"; case CREATESIMILARDRAWTARGET: return "CreateSimilarDrawTarget"; + case FONTDATA: + return "FontData"; default: return "Unknown"; } @@ -1387,34 +1391,85 @@ RecordedSnapshot::OutputSimpleEventInfo(stringstream &aStringStream) const aStringStream << "[" << mRefPtr << "] Snapshot Created (DT: " << mDT << ")"; } -RecordedScaledFontCreation::~RecordedScaledFontCreation() +RecordedFontData::~RecordedFontData() { - delete [] mData; + delete[] mData; +} + +void +RecordedFontData::PlayEvent(Translator *aTranslator) const +{ + RefPtr fontResource = + Factory::CreateNativeFontResource(mData, mFontDetails.size, + aTranslator->GetDesiredFontType()); + aTranslator->AddNativeFontResource(mFontDetails.fontDataKey, fontResource); +} + +void +RecordedFontData::RecordToStream(std::ostream &aStream) const +{ + MOZ_ASSERT(mGetFontFileDataSucceeded); + + WriteElement(aStream, mFontDetails.fontDataKey); + WriteElement(aStream, mFontDetails.size); + aStream.write((const char*)mData, mFontDetails.size); +} + +void +RecordedFontData::OutputSimpleEventInfo(stringstream &aStringStream) const +{ + aStringStream << "Font Data of size " << mFontDetails.size; +} + +void +RecordedFontData::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize) +{ + mData = new uint8_t[aSize]; + memcpy(mData, aData, aSize); + mFontDetails.fontDataKey = SFNTData::GetUniqueKey(aData, aSize); + mFontDetails.size = aSize; + mFontDetails.index = aIndex; + mFontDetails.glyphSize = aGlyphSize; +} + +bool +RecordedFontData::GetFontDetails(RecordedFontDetails& fontDetails) +{ + if (!mGetFontFileDataSucceeded) { + return false; + } + + fontDetails.fontDataKey = mFontDetails.fontDataKey; + fontDetails.size = mFontDetails.size; + fontDetails.glyphSize = mFontDetails.glyphSize; + fontDetails.index = mFontDetails.index; + return true; +} + +RecordedFontData::RecordedFontData(istream &aStream) + : RecordedEvent(FONTDATA) +{ + ReadElement(aStream, mFontDetails.fontDataKey); + ReadElement(aStream, mFontDetails.size); + mData = new uint8_t[mFontDetails.size]; + aStream.read((char*)mData, mFontDetails.size); } void RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const { - RefPtr scaledFont = - Factory::CreateScaledFontForTrueTypeData(mData, mSize, mIndex, mGlyphSize, - aTranslator->GetDesiredFontType()); + NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey); + RefPtr scaledFont = fontResource->CreateScaledFont(mIndex, mGlyphSize); aTranslator->AddScaledFont(mRefPtr, scaledFont); } void RecordedScaledFontCreation::RecordToStream(std::ostream &aStream) const { - if (!mGetFontFileDataSucceeded) { - gfxWarning() - << "Unable to record ScaledFont creation as no data was retrieved."; - return; - } - WriteElement(aStream, mRefPtr); + WriteElement(aStream, mFontDataKey); WriteElement(aStream, mIndex); WriteElement(aStream, mGlyphSize); - WriteElement(aStream, mSize); - aStream.write((const char*)mData, mSize); } void @@ -1423,25 +1478,13 @@ RecordedScaledFontCreation::OutputSimpleEventInfo(stringstream &aStringStream) c aStringStream << "[" << mRefPtr << "] ScaledFont Created"; } -void -RecordedScaledFontCreation::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize) -{ - mData = new uint8_t[aSize]; - memcpy(mData, aData, aSize); - mSize = aSize; - mIndex = aIndex; - mGlyphSize = aGlyphSize; -} - RecordedScaledFontCreation::RecordedScaledFontCreation(istream &aStream) : RecordedEvent(SCALEDFONTCREATION) { ReadElement(aStream, mRefPtr); + ReadElement(aStream, mFontDataKey); ReadElement(aStream, mIndex); ReadElement(aStream, mGlyphSize); - ReadElement(aStream, mSize); - mData = new uint8_t[mSize]; - aStream.read((char*)mData, mSize); } void diff --git a/gfx/2d/RecordedEvent.h b/gfx/2d/RecordedEvent.h index 190d0608c7a7..da94124a15e4 100644 --- a/gfx/2d/RecordedEvent.h +++ b/gfx/2d/RecordedEvent.h @@ -62,6 +62,14 @@ struct ReferencePtr uint64_t mLongPtr; }; +struct RecordedFontDetails +{ + uint64_t fontDataKey; + uint32_t size; + uint32_t index; + Float glyphSize; +}; + // Used by the Azure drawing debugger (player2d) inline std::string StringFromPtr(ReferencePtr aPtr) { @@ -81,6 +89,7 @@ public: virtual FilterNode *LookupFilterNode(ReferencePtr aRefPtr) = 0; virtual GradientStops *LookupGradientStops(ReferencePtr aRefPtr) = 0; virtual ScaledFont *LookupScaledFont(ReferencePtr aRefPtr) = 0; + virtual NativeFontResource *LookupNativeFontResource(uint64_t aKey) = 0; virtual void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) = 0; virtual void RemoveDrawTarget(ReferencePtr aRefPtr) = 0; virtual void AddPath(ReferencePtr aRefPtr, Path *aPath) = 0; @@ -93,6 +102,8 @@ public: virtual void RemoveGradientStops(ReferencePtr aRefPtr) = 0; virtual void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) = 0; virtual void RemoveScaledFont(ReferencePtr aRefPtr) = 0; + virtual void AddNativeFontResource(uint64_t aKey, + NativeFontResource *aNativeFontResource) = 0; virtual already_AddRefed CreateDrawTarget(ReferencePtr aRefPtr, const IntSize &aSize, @@ -179,7 +190,8 @@ public: DRAWFILTER, FILTERNODESETATTRIBUTE, FILTERNODESETINPUT, - CREATESIMILARDRAWTARGET + CREATESIMILARDRAWTARGET, + FONTDATA, }; static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1; @@ -937,20 +949,58 @@ private: MOZ_IMPLICIT RecordedSnapshot(std::istream &aStream); }; -class RecordedScaledFontCreation : public RecordedEvent { +class RecordedFontData : public RecordedEvent { public: - static void FontDataProc(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize, void* aBaton) + + static void FontDataProc(const uint8_t *aData, uint32_t aSize, + uint32_t aIndex, Float aGlyphSize, void* aBaton) { - static_cast(aBaton)->SetFontData(aData, aSize, aIndex, aGlyphSize); + auto recordedFontData = static_cast(aBaton); + recordedFontData->SetFontData(aData, aSize, aIndex, aGlyphSize); } - RecordedScaledFontCreation(ReferencePtr aRefPtr, ScaledFont *aScaledFont) - : RecordedEvent(SCALEDFONTCREATION), mRefPtr(aRefPtr), mData(nullptr) + explicit RecordedFontData(ScaledFont *aScaledFont) + : RecordedEvent(FONTDATA), mData(nullptr) { mGetFontFileDataSucceeded = aScaledFont->GetFontFileData(&FontDataProc, this); } - ~RecordedScaledFontCreation(); + ~RecordedFontData(); + + virtual void PlayEvent(Translator *aTranslator) const; + + virtual void RecordToStream(std::ostream &aStream) const; + virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const; + + virtual std::string GetName() const { return "Font Data"; } + virtual ReferencePtr GetObjectRef() const { return nullptr; }; + + void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, + Float aGlyphSize); + + bool GetFontDetails(RecordedFontDetails& fontDetails); + +private: + friend class RecordedEvent; + + uint8_t *mData; + RecordedFontDetails mFontDetails; + + bool mGetFontFileDataSucceeded = false; + + MOZ_IMPLICIT RecordedFontData(std::istream &aStream); +}; + +class RecordedScaledFontCreation : public RecordedEvent { +public: + + RecordedScaledFontCreation(ReferencePtr aRefPtr, + RecordedFontDetails aFontDetails) + : RecordedEvent(SCALEDFONTCREATION), mRefPtr(aRefPtr) + , mFontDataKey(aFontDetails.fontDataKey) + , mGlyphSize(aFontDetails.glyphSize) , mIndex(aFontDetails.index) + { + } virtual void PlayEvent(Translator *aTranslator) const; @@ -960,17 +1010,13 @@ public: virtual std::string GetName() const { return "ScaledFont Creation"; } virtual ReferencePtr GetObjectRef() const { return mRefPtr; } - void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize); - private: friend class RecordedEvent; ReferencePtr mRefPtr; - uint8_t *mData; - uint32_t mSize; + uint64_t mFontDataKey; Float mGlyphSize; uint32_t mIndex; - bool mGetFontFileDataSucceeded = false; MOZ_IMPLICIT RecordedScaledFontCreation(std::istream &aStream); }; diff --git a/gfx/2d/SFNTData.cpp b/gfx/2d/SFNTData.cpp index cc9424ac3d0e..23c42331e102 100644 --- a/gfx/2d/SFNTData.cpp +++ b/gfx/2d/SFNTData.cpp @@ -10,6 +10,7 @@ #include "BigEndianInts.h" #include "Logging.h" +#include "mozilla/HashFunctions.h" #include "SFNTNameTable.h" namespace mozilla { @@ -116,7 +117,7 @@ SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength) // Check to see if this is a font collection. if (aDataLength < sizeof(TTCHeader)) { gfxWarning() << "Font data too short."; - return false; + return nullptr; } const TTCHeader *ttcHeader = reinterpret_cast(aFontData); @@ -124,7 +125,7 @@ SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength) uint32_t numFonts = ttcHeader->numFonts; if (aDataLength < sizeof(TTCHeader) + (numFonts * sizeof(BigEndianUint32))) { gfxWarning() << "Font data too short to contain full TTC Header."; - return false; + return nullptr; } UniquePtr sfntData(new SFNTData); @@ -149,6 +150,23 @@ SFNTData::Create(const uint8_t *aFontData, uint32_t aDataLength) return Move(sfntData); } +/* static */ +uint64_t +SFNTData::GetUniqueKey(const uint8_t *aFontData, uint32_t aDataLength) +{ + uint64_t hash; + UniquePtr sfntData = SFNTData::Create(aFontData, aDataLength); + mozilla::u16string firstName; + if (sfntData && sfntData->GetU16FullName(0, firstName)) { + hash = HashString(firstName.c_str(), firstName.length()); + } else { + gfxWarning() << "Failed to get name from font data hashing whole font."; + hash = HashString(aFontData, aDataLength); + } + + return hash << 32 | aDataLength;; +} + SFNTData::~SFNTData() { for (size_t i = 0; i < mFonts.length(); ++i) { @@ -167,6 +185,21 @@ SFNTData::GetU16FullName(uint32_t aIndex, mozilla::u16string& aU16FullName) return mFonts[aIndex]->GetU16FullName(aU16FullName); } +bool +SFNTData::GetU16FullNames(Vector& aU16FullNames) +{ + bool fontFound = false; + for (size_t i = 0; i < mFonts.length(); ++i) { + mozilla::u16string name; + if (mFonts[i]->GetU16FullName(name)) { + fontFound = true; + } + aU16FullNames.append(Move(name)); + } + + return fontFound; +} + bool SFNTData::GetIndexForU16Name(const mozilla::u16string& aU16FullName, uint32_t* aIndex) diff --git a/gfx/2d/SFNTData.h b/gfx/2d/SFNTData.h index 8de8f91d1878..5205dfa1c4a4 100644 --- a/gfx/2d/SFNTData.h +++ b/gfx/2d/SFNTData.h @@ -30,6 +30,15 @@ public: static UniquePtr Create(const uint8_t *aFontData, uint32_t aDataLength); + /** + * Creates a unique key for the given font data. + * + * @param aFontData the SFNT data + * @param aDataLength length + * @return unique key to be used for caching + */ + static uint64_t GetUniqueKey(const uint8_t *aFontData, uint32_t aDataLength); + ~SFNTData(); /** @@ -45,6 +54,17 @@ public: */ bool GetU16FullName(uint32_t aIndex, mozilla::u16string& aU16FullName); + /** + * Populate a Vector with the first UTF16 full name from each name table of + * the fonts. If the full name string is not present it will use the family + * space concatenated with the style. + * This will only read names that are already UTF16. + * + * @param aU16FullNames the Vector to be populated. + * @return true if at least one name found otherwise false. + */ + bool GetU16FullNames(Vector& aU16FullNames); + /** * Returns the index for the first UTF16 name matching aU16FullName. * diff --git a/gfx/2d/ScaledFontDWrite.cpp b/gfx/2d/ScaledFontDWrite.cpp index 6323cf1c2edc..10fa10c82537 100644 --- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -5,11 +5,8 @@ #include "ScaledFontDWrite.h" #include "PathD2D.h" -#include "DrawTargetD2D.h" -#include "Logging.h" #include -#include #ifdef USE_CAIRO_SCALED_FONT #include "cairo-win32.h" @@ -18,131 +15,6 @@ namespace mozilla { namespace gfx { -static Atomic sNextFontFileKey; -static std::unordered_map sFontFileStreams; - -class DWriteFontFileLoader : public IDWriteFontFileLoader -{ -public: - DWriteFontFileLoader() - { - } - - // IUnknown interface - IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) - { - if (iid == __uuidof(IDWriteFontFileLoader)) { - *ppObject = static_cast(this); - return S_OK; - } else if (iid == __uuidof(IUnknown)) { - *ppObject = static_cast(this); - return S_OK; - } else { - return E_NOINTERFACE; - } - } - - IFACEMETHOD_(ULONG, AddRef)() - { - return 1; - } - - IFACEMETHOD_(ULONG, Release)() - { - return 1; - } - - // IDWriteFontFileLoader methods - /** - * Important! Note the key here -has- to be a pointer to an - * ffReferenceKey object. - */ - virtual HRESULT STDMETHODCALLTYPE - CreateStreamFromKey(void const* fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - OUT IDWriteFontFileStream** fontFileStream); - - /** - * Gets the singleton loader instance. Note that when using this font - * loader, the key must be a pointer to an FallibleTArray. This - * array will be empty when the function returns. - */ - static IDWriteFontFileLoader* Instance() - { - if (!mInstance) { - mInstance = new DWriteFontFileLoader(); - DrawTargetD2D::GetDWriteFactory()-> - RegisterFontFileLoader(mInstance); - } - return mInstance; - } - -private: - static IDWriteFontFileLoader* mInstance; -}; - -class DWriteFontFileStream : public IDWriteFontFileStream -{ -public: - /** - * Used by the FontFileLoader to create a new font stream, - * this font stream is created from data in memory. The memory - * passed may be released after object creation, it will be - * copied internally. - * - * @param aData Font data - */ - DWriteFontFileStream(uint8_t *aData, uint32_t aSize, uint64_t aFontFileKey); - ~DWriteFontFileStream(); - - // IUnknown interface - IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject) - { - if (iid == __uuidof(IDWriteFontFileStream)) { - *ppObject = static_cast(this); - return S_OK; - } else if (iid == __uuidof(IUnknown)) { - *ppObject = static_cast(this); - return S_OK; - } else { - return E_NOINTERFACE; - } - } - - IFACEMETHOD_(ULONG, AddRef)() - { - ++mRefCnt; - return mRefCnt; - } - - IFACEMETHOD_(ULONG, Release)() - { - --mRefCnt; - if (mRefCnt == 0) { - delete this; - return 0; - } - return mRefCnt; - } - - // IDWriteFontFileStream methods - virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(void const** fragmentStart, - UINT64 fileOffset, - UINT64 fragmentSize, - OUT void** fragmentContext); - - virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* fragmentContext); - - virtual HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64* fileSize); - - virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64* lastWriteTime); - -private: - std::vector mData; - uint32_t mRefCnt; - uint64_t mFontFileKey; -}; - static BYTE GetSystemTextQuality() { @@ -216,125 +88,6 @@ DoGrayscale(IDWriteFontFace *aDWFace, Float ppem) return true; } -IDWriteFontFileLoader* DWriteFontFileLoader::mInstance = nullptr; - -HRESULT STDMETHODCALLTYPE -DWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - IDWriteFontFileStream **fontFileStream) -{ - if (!fontFileReferenceKey || !fontFileStream) { - return E_POINTER; - } - - uint64_t fontFileKey = *static_cast(fontFileReferenceKey); - auto found = sFontFileStreams.find(fontFileKey); - if (found == sFontFileStreams.end()) { - *fontFileStream = nullptr; - return E_FAIL; - } - - found->second->AddRef(); - *fontFileStream = found->second; - return S_OK; -} - -DWriteFontFileStream::DWriteFontFileStream(uint8_t *aData, uint32_t aSize, - uint64_t aFontFileKey) - : mRefCnt(0) - , mFontFileKey(aFontFileKey) -{ - mData.resize(aSize); - memcpy(&mData.front(), aData, aSize); -} - -DWriteFontFileStream::~DWriteFontFileStream() -{ - sFontFileStreams.erase(mFontFileKey); -} - -HRESULT STDMETHODCALLTYPE -DWriteFontFileStream::GetFileSize(UINT64 *fileSize) -{ - *fileSize = mData.size(); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE -DWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime) -{ - return E_NOTIMPL; -} - -HRESULT STDMETHODCALLTYPE -DWriteFontFileStream::ReadFileFragment(const void **fragmentStart, - UINT64 fileOffset, - UINT64 fragmentSize, - void **fragmentContext) -{ - // We are required to do bounds checking. - if (fileOffset + fragmentSize > mData.size()) { - return E_FAIL; - } - - // truncate the 64 bit fileOffset to size_t sized index into mData - size_t index = static_cast(fileOffset); - - // We should be alive for the duration of this. - *fragmentStart = &mData[index]; - *fragmentContext = nullptr; - return S_OK; -} - -void STDMETHODCALLTYPE -DWriteFontFileStream::ReleaseFileFragment(void *fragmentContext) -{ -} - -ScaledFontDWrite::ScaledFontDWrite(uint8_t *aData, uint32_t aSize, - uint32_t aIndex, Float aGlyphSize) - : ScaledFontBase(aGlyphSize) -{ - IDWriteFactory *factory = DrawTargetD2D::GetDWriteFactory(); - - uint64_t fontFileKey = sNextFontFileKey++; - sFontFileStreams[fontFileKey] = - new DWriteFontFileStream(aData, aSize, fontFileKey); - RefPtr ffsRef = sFontFileStreams[fontFileKey]; - - RefPtr fontFile; - if (FAILED(factory->CreateCustomFontFileReference(&fontFileKey, sizeof(fontFileKey), DWriteFontFileLoader::Instance(), getter_AddRefs(fontFile)))) { - gfxWarning() << "Failed to load font file from data!"; - return; - } - - BOOL isSupported; - DWRITE_FONT_FILE_TYPE fileType; - DWRITE_FONT_FACE_TYPE faceType; - UINT32 numberOfFaces; - fontFile->Analyze(&isSupported, &fileType, &faceType, &numberOfFaces); - if (!isSupported) { - gfxWarning() << "Font file is not supported."; - return; - } - - if (aIndex >= numberOfFaces) { - gfxWarning() << "Font face index is greater than number of fonts in file."; - return; - } - - IDWriteFontFile *ff = fontFile; - if (FAILED(factory->CreateFontFace(faceType, 1, &ff, aIndex, DWRITE_FONT_SIMULATIONS_NONE, getter_AddRefs(mFontFace)))) { - gfxWarning() << "Failed to create font face from font file data!"; - return; - } - - // Now that we've successfully created the font take ownership of the - // reference, so that we know that the font file stream will be around if - // someone calls GetFontFileData. - mFontFileStream = ffsRef.forget(); -} - already_AddRefed ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget) { diff --git a/gfx/2d/ScaledFontDWrite.h b/gfx/2d/ScaledFontDWrite.h index 8b243ca8e91d..38bdec03fca3 100644 --- a/gfx/2d/ScaledFontDWrite.h +++ b/gfx/2d/ScaledFontDWrite.h @@ -22,7 +22,6 @@ public: : ScaledFontBase(aSize) , mFontFace(aFont) {} - ScaledFontDWrite(uint8_t *aData, uint32_t aSize, uint32_t aIndex, Float aGlyphSize); virtual FontType GetType() const { return FontType::DWRITE; } @@ -49,9 +48,6 @@ protected: #ifdef USE_CAIRO_SCALED_FONT cairo_font_face_t* GetCairoFontFace() override; #endif - -private: - RefPtr mFontFileStream; }; class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions diff --git a/gfx/2d/ScaledFontWin.cpp b/gfx/2d/ScaledFontWin.cpp index d2ced2e1a8bc..1993b7efcced 100644 --- a/gfx/2d/ScaledFontWin.cpp +++ b/gfx/2d/ScaledFontWin.cpp @@ -4,7 +4,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ScaledFontWin.h" -#include "ScaledFontBase.h" #include "AutoHelpersWin.h" #include "Logging.h" @@ -27,57 +26,6 @@ ScaledFontWin::ScaledFontWin(LOGFONT* aFont, Float aSize) { } -ScaledFontWin::ScaledFontWin(uint8_t* aFontData, uint32_t aFontDataLength, - uint32_t aIndex, Float aGlyphSize) - : ScaledFontBase(aGlyphSize) -{ - mLogFont.lfHeight = 0; - mLogFont.lfWidth = 0; - mLogFont.lfEscapement = 0; - mLogFont.lfOrientation = 0; - mLogFont.lfWeight = FW_DONTCARE; - mLogFont.lfItalic = FALSE; - mLogFont.lfUnderline = FALSE; - mLogFont.lfStrikeOut = FALSE; - mLogFont.lfCharSet = DEFAULT_CHARSET; - mLogFont.lfOutPrecision = OUT_DEFAULT_PRECIS; - mLogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; - mLogFont.lfQuality = DEFAULT_QUALITY; - mLogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; - mLogFont.lfFaceName[0] = 0; - - UniquePtr sfntData = SFNTData::Create(aFontData, aFontDataLength); - if (!sfntData) { - gfxWarning() << "Failed to create SFNTData for ScaledFontWin."; - return; - } - - mozilla::u16string fontName; - if (!sfntData->GetU16FullName(aIndex, fontName)) { - gfxWarning() << "Failed to get font name from font."; - return; - } - - // Copy name to mLogFont and add null to end. - // lfFaceName has a maximum length including null. - if (fontName.size() > LF_FACESIZE - 1) { - fontName.resize(LF_FACESIZE - 1); - } - // We cast here because for VS2015 char16_t != wchar_t, even though they are - // both 16 bit. - fontName.copy(reinterpret_cast(mLogFont.lfFaceName), - fontName.length()); - mLogFont.lfFaceName[fontName.length()] = 0; - - DWORD numberOfFontsAdded; - HANDLE fontHandle = ::AddFontMemResourceEx(aFontData, aFontDataLength, 0, - &numberOfFontsAdded); - if (fontHandle) { - mMemoryFontRemover.reset(new MemoryFontRemover(fontHandle)); - } - -} - bool ScaledFontWin::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) { diff --git a/gfx/2d/ScaledFontWin.h b/gfx/2d/ScaledFontWin.h index 0f245cae14ff..d7c00695df04 100644 --- a/gfx/2d/ScaledFontWin.h +++ b/gfx/2d/ScaledFontWin.h @@ -7,9 +7,6 @@ #define MOZILLA_GFX_SCALEDFONTWIN_H_ #include "ScaledFontBase.h" -#include - -#include "mozilla/UniquePtr.h" namespace mozilla { namespace gfx { @@ -20,9 +17,6 @@ public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin) ScaledFontWin(LOGFONT* aFont, Float aSize); - ScaledFontWin(uint8_t* aFontData, uint32_t aFontDataLength, uint32_t aIndex, - Float aGlyphSize); - virtual FontType GetType() const { return FontType::GDI; } bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton) override; @@ -41,15 +35,6 @@ private: friend class DrawTargetSkia; #endif LOGFONT mLogFont; - - struct MemoryFontRemover - { - HANDLE memFontHandle; - MemoryFontRemover(HANDLE aMemFontHandle) : memFontHandle(aMemFontHandle) {} - ~MemoryFontRemover() { ::RemoveFontMemResourceEx(memFontHandle); } - }; - - UniquePtr mMemoryFontRemover; }; } diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index 68b9cd1a85a4..5940bfdb42ff 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -71,6 +71,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': 'ExtendInputEffectD2D1.cpp', 'FilterNodeD2D1.cpp', 'JobScheduler_win32.cpp', + 'NativeFontResourceDWrite.cpp', + 'NativeFontResourceGDI.cpp', 'PathD2D.cpp', 'RadialGradientEffectD2D1.cpp', 'ScaledFontDWrite.cpp', diff --git a/layout/printing/PrintTranslator.cpp b/layout/printing/PrintTranslator.cpp index f9f02f79ebd3..686e99b4a330 100644 --- a/layout/printing/PrintTranslator.cpp +++ b/layout/printing/PrintTranslator.cpp @@ -53,7 +53,7 @@ PrintTranslator::TranslateRecording(std::istream& aRecording) static_cast(eventType))); // Make sure that the whole event was read from the stream successfully. - if (!aRecording.good()) { + if (!aRecording.good() || !recordedEvent) { return false; } diff --git a/layout/printing/PrintTranslator.h b/layout/printing/PrintTranslator.h index d2bef5cac68b..92d8bbed2bcb 100644 --- a/layout/printing/PrintTranslator.h +++ b/layout/printing/PrintTranslator.h @@ -12,7 +12,6 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/Filters.h" #include "mozilla/gfx/RecordedEvent.h" -#include "mozilla/unused.h" #include "nsRefPtrHashtable.h" class nsDeviceContext; @@ -28,6 +27,7 @@ using gfx::SourceSurface; using gfx::FilterNode; using gfx::GradientStops; using gfx::ScaledFont; +using gfx::NativeFontResource; class PrintTranslator final : public Translator { @@ -78,6 +78,13 @@ public: return result; } + NativeFontResource* LookupNativeFontResource(uint64_t aKey) final + { + NativeFontResource* result = mNativeFontResources.GetWeak(aKey); + MOZ_ASSERT(result); + return result; + } + void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget *aDT) final { mDrawTargets.Put(aRefPtr, aDT); @@ -106,7 +113,12 @@ public: void AddScaledFont(ReferencePtr aRefPtr, ScaledFont *aScaledFont) final { mScaledFonts.Put(aRefPtr, aScaledFont); - Unused << mSavedScaledFonts.PutEntry(aScaledFont); + } + + void AddNativeFontResource(uint64_t aKey, + NativeFontResource *aScaledFontResouce) final + { + mNativeFontResources.Put(aKey, aScaledFontResouce); } void RemoveDrawTarget(ReferencePtr aRefPtr) final @@ -139,8 +151,6 @@ public: mScaledFonts.Remove(aRefPtr); } - void ClearSavedFonts() { mSavedScaledFonts.Clear(); } - already_AddRefed CreateDrawTarget(ReferencePtr aRefPtr, const gfx::IntSize &aSize, gfx::SurfaceFormat aFormat) final; @@ -159,11 +169,7 @@ private: nsRefPtrHashtable, FilterNode> mFilterNodes; nsRefPtrHashtable, GradientStops> mGradientStops; nsRefPtrHashtable, ScaledFont> mScaledFonts; - - // We keep an extra reference to each scaled font, because they currently - // always get removed immediately. These can be cleared using ClearSavedFonts, - // when we know that things have been flushed to the print device. - nsTHashtable> mSavedScaledFonts; + nsRefPtrHashtable mNativeFontResources; }; } // namespace layout diff --git a/layout/printing/ipc/RemotePrintJobParent.cpp b/layout/printing/ipc/RemotePrintJobParent.cpp index af09680564bc..38ac1c762dba 100644 --- a/layout/printing/ipc/RemotePrintJobParent.cpp +++ b/layout/printing/ipc/RemotePrintJobParent.cpp @@ -118,8 +118,6 @@ RemotePrintJobParent::PrintPage(const Shmem& aStoredPage) return rv; } - mPrintTranslator->ClearSavedFonts(); - return NS_OK; }