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:
Bob Owen 2016-01-05 10:08:57 +00:00
Родитель 3b91f57af4
Коммит 532eb778ab
4 изменённых файлов: 176 добавлений и 138 удалений

Просмотреть файл

@ -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;