mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
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.
This commit is contained in:
parent
016d8435c1
commit
fb35888c83
34
gfx/2d/2D.h
34
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<NativeFontResource>
|
||||
{
|
||||
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<ScaledFont>
|
||||
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<ScaledFont>
|
||||
CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize, uint32_t aFaceIndex, Float aGlyphSize, FontType aType);
|
||||
static already_AddRefed<NativeFontResource>
|
||||
CreateNativeFontResource(uint8_t *aData, uint32_t aSize, FontType aType);
|
||||
|
||||
/**
|
||||
* This creates a scaled font with an associated cairo_scaled_font_t, and
|
||||
|
@ -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<const void*> ObjectSet;
|
||||
typedef std::unordered_set<uint64_t> Uint64Set;
|
||||
#else
|
||||
typedef std::set<const void*> ObjectSet;
|
||||
typedef std::set<uint64_t> Uint64Set;
|
||||
#endif
|
||||
|
||||
ObjectSet mStoredObjects;
|
||||
Uint64Set mStoredFontData;
|
||||
};
|
||||
|
||||
class DrawEventRecorderFile : public DrawEventRecorderPrivate
|
||||
|
@ -392,7 +392,15 @@ DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
|
||||
if (!aFont->GetUserData(reinterpret_cast<UserDataKey*>(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;
|
||||
|
@ -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 <d3d10_1.h>
|
||||
#include "HelpersD2D.h"
|
||||
#endif
|
||||
@ -540,41 +542,35 @@ Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, Float aSiz
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
Factory::CreateScaledFontForTrueTypeData(uint8_t *aData, uint32_t aSize,
|
||||
uint32_t aFaceIndex, Float aGlyphSize,
|
||||
FontType aType)
|
||||
already_AddRefed<NativeFontResource>
|
||||
Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize,
|
||||
FontType aType)
|
||||
{
|
||||
switch (aType) {
|
||||
#ifdef WIN32
|
||||
case FontType::DWRITE:
|
||||
{
|
||||
return MakeAndAddRef<ScaledFontDWrite>(aData, aSize, aFaceIndex, aGlyphSize);
|
||||
return NativeFontResourceDWrite::Create(aData, aSize,
|
||||
/* aNeedsCairo = */ false);
|
||||
}
|
||||
#endif
|
||||
case FontType::CAIRO:
|
||||
{
|
||||
RefPtr<ScaledFontBase> 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;
|
||||
}
|
||||
}
|
||||
|
287
gfx/2d/NativeFontResourceDWrite.cpp
Normal file
287
gfx/2d/NativeFontResourceDWrite.cpp
Normal file
@ -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 <unordered_map>
|
||||
|
||||
#include "DrawTargetD2D.h"
|
||||
#include "Logging.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static Atomic<uint64_t> sNextFontFileKey;
|
||||
static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
|
||||
|
||||
class DWriteFontFileLoader : public IDWriteFontFileLoader
|
||||
{
|
||||
public:
|
||||
DWriteFontFileLoader()
|
||||
{
|
||||
}
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileLoader)) {
|
||||
*ppObject = static_cast<IDWriteFontFileLoader*>(this);
|
||||
return S_OK;
|
||||
} else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(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<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)()
|
||||
{
|
||||
++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<uint8_t> 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<const uint64_t*>(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<size_t>(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>
|
||||
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<IDWriteFontFileStream> ffsRef =
|
||||
new DWriteFontFileStream(aFontData, aDataLength, fontFileKey);
|
||||
sFontFileStreams[fontFileKey] = ffsRef;
|
||||
|
||||
RefPtr<IDWriteFontFile> 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<NativeFontResourceDWrite> fontResource =
|
||||
new NativeFontResourceDWrite(factory, fontFile.forget(), faceType,
|
||||
numberOfFaces, aNeedsCairo);
|
||||
return fontResource.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
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<IDWriteFontFace> 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<ScaledFontBase> 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
|
56
gfx/2d/NativeFontResourceDWrite.h
Normal file
56
gfx/2d/NativeFontResourceDWrite.h
Normal file
@ -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 <dwrite.h>
|
||||
|
||||
#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<NativeFontResourceDWrite>
|
||||
Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo);
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) final;
|
||||
|
||||
private:
|
||||
NativeFontResourceDWrite(IDWriteFactory *aFactory,
|
||||
already_AddRefed<IDWriteFontFile> aFontFile,
|
||||
DWRITE_FONT_FACE_TYPE aFaceType,
|
||||
uint32_t aNumberOfFaces, bool aNeedsCairo)
|
||||
: mFactory(aFactory), mFontFile(aFontFile), mFaceType(aFaceType)
|
||||
, mNumberOfFaces(aNumberOfFaces), mNeedsCairo(aNeedsCairo)
|
||||
{}
|
||||
|
||||
IDWriteFactory *mFactory;
|
||||
RefPtr<IDWriteFontFile> mFontFile;
|
||||
DWRITE_FONT_FACE_TYPE mFaceType;
|
||||
uint32_t mNumberOfFaces;
|
||||
bool mNeedsCairo;
|
||||
};
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_NativeFontResourceDWrite_h
|
112
gfx/2d/NativeFontResourceGDI.cpp
Normal file
112
gfx/2d/NativeFontResourceGDI.cpp
Normal file
@ -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>
|
||||
NativeFontResourceGDI::Create(uint8_t *aFontData, uint32_t aDataLength,
|
||||
bool aNeedsCairo)
|
||||
{
|
||||
UniquePtr<SFNTData> sfntData = SFNTData::Create(aFontData, aDataLength);
|
||||
if (!sfntData) {
|
||||
gfxWarning() << "Failed to create SFNTData for ScaledFontWin.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Vector<mozilla::u16string> 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<NativeFontResourceGDI> fontResouce =
|
||||
new NativeFontResourceGDI(fontResourceHandle, Move(fontNames), aNeedsCairo);
|
||||
|
||||
return fontResouce.forget();
|
||||
}
|
||||
|
||||
NativeFontResourceGDI::~NativeFontResourceGDI()
|
||||
{
|
||||
::RemoveFontMemResourceEx(mFontResourceHandle);
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
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<char16_t*>(logFont.lfFaceName),
|
||||
mFontNames[aIndex].length());
|
||||
|
||||
// Constructor for ScaledFontWin dereferences and copies the LOGFONT, so we
|
||||
// are safe to pass this reference.
|
||||
RefPtr<ScaledFontBase> 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
|
57
gfx/2d/NativeFontResourceGDI.h
Normal file
57
gfx/2d/NativeFontResourceGDI.h
Normal file
@ -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 <windows.h>
|
||||
|
||||
#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<NativeFontResourceGDI>
|
||||
Create(uint8_t *aFontData, uint32_t aDataLength, bool aNeedsCairo);
|
||||
|
||||
~NativeFontResourceGDI();
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
CreateScaledFont(uint32_t aIndex, uint32_t aGlyphSize) final;
|
||||
|
||||
private:
|
||||
NativeFontResourceGDI(HANDLE aFontResourceHandle,
|
||||
Vector<mozilla::u16string>&& aFontNames,
|
||||
bool aNeedsCairo)
|
||||
: mFontResourceHandle(aFontResourceHandle), mFontNames(Move(aFontNames))
|
||||
, mNeedsCairo(aNeedsCairo)
|
||||
{}
|
||||
|
||||
HANDLE mFontResourceHandle;
|
||||
Vector<mozilla::u16string> mFontNames;
|
||||
bool mNeedsCairo;
|
||||
};
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_gfx_NativeFontResourceGDI_h
|
@ -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<NativeFontResource> 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> scaledFont =
|
||||
Factory::CreateScaledFontForTrueTypeData(mData, mSize, mIndex, mGlyphSize,
|
||||
aTranslator->GetDesiredFontType());
|
||||
NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey);
|
||||
RefPtr<ScaledFont> 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
|
||||
|
@ -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<DrawTarget> 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<RecordedScaledFontCreation*>(aBaton)->SetFontData(aData, aSize, aIndex, aGlyphSize);
|
||||
auto recordedFontData = static_cast<RecordedFontData*>(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);
|
||||
};
|
||||
|
@ -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<const TTCHeader*>(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> 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 = 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<mozilla::u16string>& 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)
|
||||
|
@ -30,6 +30,15 @@ public:
|
||||
static UniquePtr<SFNTData> 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<mozilla::u16string>& aU16FullNames);
|
||||
|
||||
/**
|
||||
* Returns the index for the first UTF16 name matching aU16FullName.
|
||||
*
|
||||
|
@ -5,11 +5,8 @@
|
||||
|
||||
#include "ScaledFontDWrite.h"
|
||||
#include "PathD2D.h"
|
||||
#include "DrawTargetD2D.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef USE_CAIRO_SCALED_FONT
|
||||
#include "cairo-win32.h"
|
||||
@ -18,131 +15,6 @@
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static Atomic<uint64_t> sNextFontFileKey;
|
||||
static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
|
||||
|
||||
class DWriteFontFileLoader : public IDWriteFontFileLoader
|
||||
{
|
||||
public:
|
||||
DWriteFontFileLoader()
|
||||
{
|
||||
}
|
||||
|
||||
// IUnknown interface
|
||||
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
|
||||
{
|
||||
if (iid == __uuidof(IDWriteFontFileLoader)) {
|
||||
*ppObject = static_cast<IDWriteFontFileLoader*>(this);
|
||||
return S_OK;
|
||||
} else if (iid == __uuidof(IUnknown)) {
|
||||
*ppObject = static_cast<IUnknown*>(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<uint8_t>. 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<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)()
|
||||
{
|
||||
++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<uint8_t> 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<const uint64_t*>(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<size_t>(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<IDWriteFontFileStream> ffsRef = sFontFileStreams[fontFileKey];
|
||||
|
||||
RefPtr<IDWriteFontFile> 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<Path>
|
||||
ScaledFontDWrite::GetPathForGlyphs(const GlyphBuffer &aBuffer, const DrawTarget *aTarget)
|
||||
{
|
||||
|
@ -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<IDWriteFontFileStream> mFontFileStream;
|
||||
};
|
||||
|
||||
class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions
|
||||
|
@ -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 = 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<char16_t*>(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)
|
||||
{
|
||||
|
@ -7,9 +7,6 @@
|
||||
#define MOZILLA_GFX_SCALEDFONTWIN_H_
|
||||
|
||||
#include "ScaledFontBase.h"
|
||||
#include <windows.h>
|
||||
|
||||
#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<MemoryFontRemover> mMemoryFontRemover;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -53,7 +53,7 @@ PrintTranslator::TranslateRecording(std::istream& aRecording)
|
||||
static_cast<RecordedEvent::EventType>(eventType)));
|
||||
|
||||
// Make sure that the whole event was read from the stream successfully.
|
||||
if (!aRecording.good()) {
|
||||
if (!aRecording.good() || !recordedEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -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<DrawTarget> CreateDrawTarget(ReferencePtr aRefPtr,
|
||||
const gfx::IntSize &aSize,
|
||||
gfx::SurfaceFormat aFormat) final;
|
||||
@ -159,11 +169,7 @@ private:
|
||||
nsRefPtrHashtable<nsPtrHashKey<void>, FilterNode> mFilterNodes;
|
||||
nsRefPtrHashtable<nsPtrHashKey<void>, GradientStops> mGradientStops;
|
||||
nsRefPtrHashtable<nsPtrHashKey<void>, 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<nsRefPtrHashKey<ScaledFont>> mSavedScaledFonts;
|
||||
nsRefPtrHashtable<nsUint64HashKey, NativeFontResource> mNativeFontResources;
|
||||
};
|
||||
|
||||
} // namespace layout
|
||||
|
@ -118,8 +118,6 @@ RemotePrintJobParent::PrintPage(const Shmem& aStoredPage)
|
||||
return rv;
|
||||
}
|
||||
|
||||
mPrintTranslator->ClearSavedFonts();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user