зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1156742 Part 18: Fix the way we hold custom font data so that they can be recorded with Moz2D. r=bas
This commit is contained in:
Родитель
3b91f57af4
Коммит
532eb778ab
|
@ -5,8 +5,128 @@
|
|||
|
||||
#include "gfxDWriteCommon.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
|
||||
static mozilla::Atomic<uint64_t> sNextFontFileKey;
|
||||
static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
|
||||
|
||||
IDWriteFontFileLoader* gfxDWriteFontFileLoader::mInstance = nullptr;
|
||||
|
||||
class gfxDWriteFontFileStream final : 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
|
||||
*/
|
||||
gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData,
|
||||
uint64_t aFontFileKey);
|
||||
~gfxDWriteFontFileStream();
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileStream)) {
|
||||
*ppObject = static_cast<IDWriteFontFileStream*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
}
|
||||
else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, AddRef)()
|
||||
{
|
||||
NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, Release)()
|
||||
{
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup 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:
|
||||
FallibleTArray<uint8_t> mData;
|
||||
nsAutoRefCnt mRefCnt;
|
||||
uint64_t mFontFileKey;
|
||||
};
|
||||
|
||||
gfxDWriteFontFileStream::gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData,
|
||||
uint64_t aFontFileKey)
|
||||
: mFontFileKey(aFontFileKey)
|
||||
{
|
||||
mData.SwapElements(*aData);
|
||||
}
|
||||
|
||||
gfxDWriteFontFileStream::~gfxDWriteFontFileStream()
|
||||
{
|
||||
sFontFileStreams.erase(mFontFileKey);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::GetFileSize(UINT64 *fileSize)
|
||||
{
|
||||
*fileSize = mData.Length();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::ReadFileFragment(const void **fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
void **fragmentContext)
|
||||
{
|
||||
// We are required to do bounds checking.
|
||||
if (fileOffset + fragmentSize > (UINT64)mData.Length()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
// We should be alive for the duration of this.
|
||||
*fragmentStart = &mData[fileOffset];
|
||||
*fragmentContext = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::ReleaseFileFragment(void *fragmentContext)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey,
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
|
@ -16,56 +136,42 @@ gfxDWriteFontFileLoader::CreateStreamFromKey(const void *fontFileReferenceKey,
|
|||
return E_POINTER;
|
||||
}
|
||||
|
||||
*fontFileStream =
|
||||
new gfxDWriteFontFileStream(
|
||||
static_cast<const ffReferenceKey*>(fontFileReferenceKey)->mArray);
|
||||
|
||||
if (!*fontFileStream) {
|
||||
return E_OUTOFMEMORY;
|
||||
uint64_t fontFileKey = *static_cast<const uint64_t*>(fontFileReferenceKey);
|
||||
auto found = sFontFileStreams.find(fontFileKey);
|
||||
if (found == sFontFileStreams.end()) {
|
||||
*fontFileStream = nullptr;
|
||||
return E_FAIL;
|
||||
}
|
||||
(*fontFileStream)->AddRef();
|
||||
|
||||
found->second->AddRef();
|
||||
*fontFileStream = found->second;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
gfxDWriteFontFileStream::gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData)
|
||||
/* static */
|
||||
HRESULT
|
||||
gfxDWriteFontFileLoader::CreateCustomFontFile(FallibleTArray<uint8_t>& aFontData,
|
||||
IDWriteFontFile** aFontFile,
|
||||
IDWriteFontFileStream** aFontFileStream)
|
||||
{
|
||||
mData.SwapElements(*aData);
|
||||
}
|
||||
MOZ_ASSERT(aFontFile);
|
||||
MOZ_ASSERT(aFontFileStream);
|
||||
|
||||
gfxDWriteFontFileStream::~gfxDWriteFontFileStream()
|
||||
{
|
||||
}
|
||||
IDWriteFactory *factory = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::GetFileSize(UINT64 *fileSize)
|
||||
{
|
||||
*fileSize = mData.Length();
|
||||
return S_OK;
|
||||
}
|
||||
uint64_t fontFileKey = sNextFontFileKey++;
|
||||
RefPtr<IDWriteFontFileStream> ffsRef = new gfxDWriteFontFileStream(&aFontData, fontFileKey);
|
||||
sFontFileStreams[fontFileKey] = ffsRef;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
RefPtr<IDWriteFontFile> fontFile;
|
||||
HRESULT hr = factory->CreateCustomFontFileReference(&fontFileKey, sizeof(fontFileKey), Instance(), getter_AddRefs(fontFile));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to load font file from data!");
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::ReadFileFragment(const void **fragmentStart,
|
||||
UINT64 fileOffset,
|
||||
UINT64 fragmentSize,
|
||||
void **fragmentContext)
|
||||
{
|
||||
// We are required to do bounds checking.
|
||||
if (fileOffset + fragmentSize > (UINT64)mData.Length()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
// We should be alive for the duration of this.
|
||||
*fragmentStart = &mData[fileOffset];
|
||||
*fragmentContext = nullptr;
|
||||
return S_OK;
|
||||
}
|
||||
fontFile.forget(aFontFile);
|
||||
ffsRef.forget(aFontFileStream);
|
||||
|
||||
void STDMETHODCALLTYPE
|
||||
gfxDWriteFontFileStream::ReleaseFileFragment(void *fragmentContext)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -113,8 +113,7 @@ public:
|
|||
|
||||
// IDWriteFontFileLoader methods
|
||||
/**
|
||||
* Important! Note the key here -has- to be a pointer to an
|
||||
* FallibleTArray<uint8_t>.
|
||||
* Important! Note the key here -has- to be a pointer to a uint64_t.
|
||||
*/
|
||||
virtual HRESULT STDMETHODCALLTYPE
|
||||
CreateStreamFromKey(void const* fontFileReferenceKey,
|
||||
|
@ -123,8 +122,7 @@ public:
|
|||
|
||||
/**
|
||||
* Gets the singleton loader instance. Note that when using this font
|
||||
* loader, the key must be a pointer to an FallibleTArray<uint8_t>. This
|
||||
* array will be empty when the function returns.
|
||||
* loader, the key must be a pointer to a unint64_t.
|
||||
*/
|
||||
static IDWriteFontFileLoader* Instance()
|
||||
{
|
||||
|
@ -136,71 +134,21 @@ public:
|
|||
return mInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a IDWriteFontFile and IDWriteFontFileStream from aFontData.
|
||||
* aFontData will be empty on return as it swaps out the data.
|
||||
*
|
||||
* @param aFontData the font data for the custom font file
|
||||
* @param aFontFile out param for the created font file
|
||||
* @param aFontFileStream out param for the corresponding stream
|
||||
* @return HRESULT of internal calls
|
||||
*/
|
||||
static HRESULT CreateCustomFontFile(FallibleTArray<uint8_t>& aFontData,
|
||||
IDWriteFontFile** aFontFile,
|
||||
IDWriteFontFileStream** aFontFileStream);
|
||||
|
||||
private:
|
||||
static IDWriteFontFileLoader* mInstance;
|
||||
};
|
||||
|
||||
class gfxDWriteFontFileStream final : 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
|
||||
*/
|
||||
gfxDWriteFontFileStream(FallibleTArray<uint8_t> *aData);
|
||||
~gfxDWriteFontFileStream();
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileStream)) {
|
||||
*ppObject = static_cast<IDWriteFontFileStream*>(this);
|
||||
return S_OK;
|
||||
} else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(this);
|
||||
return S_OK;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, AddRef)()
|
||||
{
|
||||
NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
|
||||
++mRefCnt;
|
||||
return mRefCnt;
|
||||
}
|
||||
|
||||
IFACEMETHOD_(ULONG, Release)()
|
||||
{
|
||||
NS_PRECONDITION(0 != mRefCnt, "dup 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:
|
||||
FallibleTArray<uint8_t> mData;
|
||||
nsAutoRefCnt mRefCnt;
|
||||
};
|
||||
|
||||
#endif /* GFX_DWRITECOMMON_H */
|
||||
|
|
|
@ -789,35 +789,12 @@ gfxDWriteFontList::MakePlatformFont(const nsAString& aFontName,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<IDWriteFontFileStream> fontFileStream;
|
||||
RefPtr<IDWriteFontFile> fontFile;
|
||||
HRESULT hr;
|
||||
|
||||
/**
|
||||
* We pass in a pointer to a structure containing a pointer to the array
|
||||
* containing the font data and a unique identifier. DWrite will
|
||||
* internally copy what is at that pointer, and pass that to
|
||||
* CreateStreamFromKey. The array will be empty when the function
|
||||
* succesfully returns since it swaps out the data.
|
||||
*/
|
||||
ffReferenceKey key;
|
||||
key.mArray = &newFontData;
|
||||
nsCOMPtr<nsIUUIDGenerator> uuidgen =
|
||||
do_GetService("@mozilla.org/uuid-generator;1");
|
||||
if (!uuidgen) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rv = uuidgen->GenerateUUIDInPlace(&key.mGUID);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateCustomFontFileReference(&key,
|
||||
sizeof(key),
|
||||
gfxDWriteFontFileLoader::Instance(),
|
||||
getter_AddRefs(fontFile));
|
||||
HRESULT hr =
|
||||
gfxDWriteFontFileLoader::CreateCustomFontFile(newFontData,
|
||||
getter_AddRefs(fontFile),
|
||||
getter_AddRefs(fontFileStream));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create custom font file reference.");
|
||||
|
@ -831,6 +808,7 @@ gfxDWriteFontList::MakePlatformFont(const nsAString& aFontName,
|
|||
gfxDWriteFontEntry *entry =
|
||||
new gfxDWriteFontEntry(uniqueName,
|
||||
fontFile,
|
||||
fontFileStream,
|
||||
aWeight,
|
||||
aStretch,
|
||||
aStyle);
|
||||
|
|
|
@ -126,17 +126,19 @@ public:
|
|||
*
|
||||
* \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),
|
||||
mForceGDIClassic(false)
|
||||
mFontFileStream(aFontFileStream), mForceGDIClassic(false)
|
||||
{
|
||||
mWeight = aWeight;
|
||||
mStretch = aStretch;
|
||||
|
@ -186,6 +188,10 @@ protected:
|
|||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче