mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 22:04:36 +00:00
Backout changeset 0a6d36fc3749 for conflicting with the backout of bug 549861.
This commit is contained in:
parent
713151feb2
commit
63c2282db0
@ -22,8 +22,6 @@
|
||||
|
||||
#include "nsIWindowsRegKey.h"
|
||||
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define LOG_FONTLIST(args) PR_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
|
||||
@ -266,8 +264,8 @@ UsingArabicOrHebrewScriptSystemLocale()
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxDWriteFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t> &aBuffer)
|
||||
gfxDWriteFontEntry::GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t> &aBuffer)
|
||||
{
|
||||
gfxDWriteFontList *pFontList = gfxDWriteFontList::PlatformFontList();
|
||||
|
||||
@ -303,8 +301,12 @@ gfxDWriteFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
nsresult rv;
|
||||
nsRefPtr<IDWriteFontFace> fontFace;
|
||||
nsresult rv = CreateFontFace(getter_AddRefs(fontFace));
|
||||
|
||||
rv = CreateFontFace(getter_AddRefs(fontFace));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -313,83 +315,29 @@ gfxDWriteFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
uint32_t len;
|
||||
void *tableContext = NULL;
|
||||
BOOL exists;
|
||||
HRESULT hr =
|
||||
fontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTableTag),
|
||||
(const void**)&tableData, &len,
|
||||
&tableContext, &exists);
|
||||
hr = fontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTableTag),
|
||||
(const void**)&tableData,
|
||||
&len,
|
||||
&tableContext,
|
||||
&exists);
|
||||
|
||||
if (FAILED(hr) || !exists) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (aBuffer.SetLength(len)) {
|
||||
memcpy(aBuffer.Elements(), tableData, len);
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
if (!aBuffer.SetLength(len)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(aBuffer.Elements(), tableData, len);
|
||||
if (tableContext) {
|
||||
fontFace->ReleaseFontTable(&tableContext);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Access to font tables packaged in hb_blob_t form
|
||||
|
||||
// object attached to the Harfbuzz blob, used to release
|
||||
// the table when the blob is destroyed
|
||||
class FontTableRec {
|
||||
public:
|
||||
FontTableRec(IDWriteFontFace *aFontFace, void *aContext)
|
||||
: mFontFace(aFontFace), mContext(aContext)
|
||||
{ }
|
||||
|
||||
~FontTableRec() {
|
||||
mFontFace->ReleaseFontTable(mContext);
|
||||
}
|
||||
|
||||
private:
|
||||
IDWriteFontFace *mFontFace;
|
||||
void *mContext;
|
||||
};
|
||||
|
||||
static void
|
||||
DestroyBlobFunc(void* aUserData)
|
||||
{
|
||||
FontTableRec *ftr = static_cast<FontTableRec*>(aUserData);
|
||||
delete ftr;
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxDWriteFontEntry::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
// try to avoid potentially expensive DWrite call if we haven't actually
|
||||
// created the font face yet, by using the gfxFontEntry method that will
|
||||
// use CopyFontTable and then cache the data
|
||||
if (!mFontFace) {
|
||||
return gfxFontEntry::GetFontTable(aTag);
|
||||
}
|
||||
|
||||
const void *data;
|
||||
UINT32 size;
|
||||
void *context;
|
||||
BOOL exists;
|
||||
HRESULT hr = mFontFace->TryGetFontTable(NativeEndian::swapToBigEndian(aTag),
|
||||
&data, &size, &context, &exists);
|
||||
if (SUCCEEDED(hr) && exists) {
|
||||
FontTableRec *ftr = new FontTableRec(mFontFace, context);
|
||||
return hb_blob_create(static_cast<const char*>(data), size,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
ftr, DestroyBlobFunc);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxDWriteFontEntry::ReadCMAP()
|
||||
{
|
||||
HRESULT hr;
|
||||
nsresult rv;
|
||||
|
||||
// attempt this once, if errors occur leave a blank cmap
|
||||
@ -399,17 +347,47 @@ gfxDWriteFontEntry::ReadCMAP()
|
||||
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
AutoTable cmapTable(this, kCMAP);
|
||||
if (cmapTable) {
|
||||
// if loading via GDI, just use GetFontTable
|
||||
if (mFont && gfxDWriteFontList::PlatformFontList()->UseGDIFontTableAccess()) {
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
|
||||
AutoFallibleTArray<uint8_t,16384> cmap;
|
||||
rv = GetFontTable(kCMAP, cmap);
|
||||
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
uint32_t cmapLen;
|
||||
const uint8_t* cmapData =
|
||||
reinterpret_cast<const uint8_t*>(hb_blob_get_data(cmapTable,
|
||||
&cmapLen));
|
||||
rv = gfxFontUtils::ReadCMAP(cmapData, cmapLen,
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
} else {
|
||||
// loading using dwrite, don't use GetFontTable to avoid copy
|
||||
nsRefPtr<IDWriteFontFace> fontFace;
|
||||
rv = CreateFontFace(getter_AddRefs(fontFace));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
const uint32_t kCmapTag = DWRITE_MAKE_OPENTYPE_TAG('c', 'm', 'a', 'p');
|
||||
uint8_t *tableData;
|
||||
uint32_t len;
|
||||
void *tableContext = NULL;
|
||||
BOOL exists;
|
||||
hr = fontFace->TryGetFontTable(kCmapTag, (const void**)&tableData,
|
||||
&len, &tableContext, &exists);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
bool isSymbol = fontFace->IsSymbolFont();
|
||||
bool isUnicode = true;
|
||||
if (exists) {
|
||||
rv = gfxFontUtils::ReadCMAP(tableData, len, *charmap,
|
||||
mUVSOffset, isUnicode,
|
||||
isSymbol);
|
||||
}
|
||||
fontFace->ReleaseFontTable(tableContext);
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mHasCmapTable = NS_SUCCEEDED(rv);
|
||||
@ -448,60 +426,52 @@ nsresult
|
||||
gfxDWriteFontEntry::CreateFontFace(IDWriteFontFace **aFontFace,
|
||||
DWRITE_FONT_SIMULATIONS aSimulations)
|
||||
{
|
||||
// initialize mFontFace if this hasn't been done before
|
||||
if (!mFontFace) {
|
||||
HRESULT hr;
|
||||
if (mFont) {
|
||||
hr = mFont->CreateFontFace(getter_AddRefs(mFontFace));
|
||||
} else if (mFontFile) {
|
||||
IDWriteFontFile *fontFile = mFontFile.get();
|
||||
HRESULT hr;
|
||||
if (mFont) {
|
||||
hr = mFont->CreateFontFace(aFontFace);
|
||||
if (SUCCEEDED(hr) && (aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) &&
|
||||
!((*aFontFace)->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD)) {
|
||||
// need to replace aFontFace with a version that has the Bold
|
||||
// simulation - unfortunately, DWrite doesn't provide a simple API
|
||||
// for this
|
||||
nsRefPtr<IDWriteFontFace> origFace = (*aFontFace);
|
||||
(*aFontFace)->Release();
|
||||
*aFontFace = NULL;
|
||||
UINT32 numberOfFiles = 0;
|
||||
hr = origFace->GetFiles(&numberOfFiles, NULL);
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoTArray<IDWriteFontFile*,1> files;
|
||||
files.AppendElements(numberOfFiles);
|
||||
hr = origFace->GetFiles(&numberOfFiles, files.Elements());
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateFontFace(mFaceType,
|
||||
1,
|
||||
&fontFile,
|
||||
0,
|
||||
DWRITE_FONT_SIMULATIONS_NONE,
|
||||
getter_AddRefs(mFontFace));
|
||||
} else {
|
||||
NS_NOTREACHED("invalid font entry");
|
||||
return NS_ERROR_FAILURE;
|
||||
CreateFontFace(origFace->GetType(),
|
||||
numberOfFiles,
|
||||
files.Elements(),
|
||||
origFace->GetIndex(),
|
||||
aSimulations,
|
||||
aFontFace);
|
||||
for (UINT32 i = 0; i < numberOfFiles; ++i) {
|
||||
files[i]->Release();
|
||||
}
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// check whether we need to add a DWrite simulated style
|
||||
if ((aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) &&
|
||||
!(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD)) {
|
||||
// if so, we need to return not mFontFace itself but a version that
|
||||
// has the Bold simulation - unfortunately, DWrite doesn't provide
|
||||
// a simple API for this
|
||||
UINT32 numberOfFiles = 0;
|
||||
if (FAILED(mFontFace->GetFiles(&numberOfFiles, NULL))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoTArray<IDWriteFontFile*,1> files;
|
||||
files.AppendElements(numberOfFiles);
|
||||
if (FAILED(mFontFace->GetFiles(&numberOfFiles, files.Elements()))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
HRESULT hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateFontFace(mFontFace->GetType(),
|
||||
numberOfFiles,
|
||||
files.Elements(),
|
||||
mFontFace->GetIndex(),
|
||||
} else if (mFontFile) {
|
||||
IDWriteFontFile *fontFile = mFontFile.get();
|
||||
hr = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory()->
|
||||
CreateFontFace(mFaceType,
|
||||
1,
|
||||
&fontFile,
|
||||
0,
|
||||
aSimulations,
|
||||
aFontFace);
|
||||
for (UINT32 i = 0; i < numberOfFiles; ++i) {
|
||||
files[i]->Release();
|
||||
}
|
||||
return FAILED(hr) ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
// no simulation: we can just add a reference to mFontFace and return that
|
||||
*aFontFace = mFontFace;
|
||||
(*aFontFace)->AddRef();
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -528,7 +498,7 @@ gfxDWriteFontEntry::IsCJKFont()
|
||||
|
||||
const uint32_t kOS2Tag = TRUETYPE_TAG('O','S','/','2');
|
||||
AutoFallibleTArray<uint8_t,128> buffer;
|
||||
if (CopyFontTable(kOS2Tag, buffer) != NS_OK) {
|
||||
if (GetFontTable(kOS2Tag, buffer) != NS_OK) {
|
||||
return mIsCJK;
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,8 @@ public:
|
||||
|
||||
virtual bool IsSymbolFont();
|
||||
|
||||
virtual hb_blob_t* GetFontTable(uint32_t aTableTag) MOZ_OVERRIDE;
|
||||
virtual nsresult GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer);
|
||||
|
||||
nsresult ReadCMAP();
|
||||
|
||||
@ -161,9 +162,6 @@ protected:
|
||||
friend class gfxDWriteFont;
|
||||
friend class gfxDWriteFontList;
|
||||
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
|
||||
|
||||
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
|
||||
bool aNeedsBold);
|
||||
|
||||
@ -179,11 +177,6 @@ protected:
|
||||
*/
|
||||
nsRefPtr<IDWriteFont> mFont;
|
||||
nsRefPtr<IDWriteFontFile> mFontFile;
|
||||
|
||||
// font face corresponding to the mFont/mFontFile *without* any DWrite
|
||||
// style simulations applied
|
||||
nsRefPtr<IDWriteFontFace> mFontFace;
|
||||
|
||||
DWRITE_FONT_FACE_TYPE mFaceType;
|
||||
|
||||
int8_t mIsCJK;
|
||||
|
@ -19,7 +19,6 @@
|
||||
// Chosen this as to resemble DWrite's own oblique face style.
|
||||
#define OBLIQUE_SKEW_FACTOR 0.3
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
// This is also in gfxGDIFont.cpp. Would be nice to put it somewhere common,
|
||||
@ -230,16 +229,24 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
mMetrics->maxAdvance = mAdjustedSize;
|
||||
|
||||
// try to get the true maxAdvance value from 'hhea'
|
||||
gfxFontEntry::AutoTable hheaTable(GetFontEntry(),
|
||||
TRUETYPE_TAG('h','h','e','a'));
|
||||
if (hheaTable) {
|
||||
uint32_t len;
|
||||
const HheaTable* hhea =
|
||||
reinterpret_cast<const HheaTable*>(hb_blob_get_data(hheaTable, &len));
|
||||
if (len >= sizeof(HheaTable)) {
|
||||
uint8_t *tableData;
|
||||
uint32_t len;
|
||||
void *tableContext = NULL;
|
||||
BOOL exists;
|
||||
HRESULT hr =
|
||||
mFontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('h', 'h', 'e', 'a'),
|
||||
(const void**)&tableData,
|
||||
&len,
|
||||
&tableContext,
|
||||
&exists);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (exists && len >= sizeof(mozilla::HheaTable)) {
|
||||
const mozilla::HheaTable* hhea =
|
||||
reinterpret_cast<const mozilla::HheaTable*>(tableData);
|
||||
mMetrics->maxAdvance =
|
||||
uint16_t(hhea->advanceWidthMax) * mFUnitsConvFactor;
|
||||
}
|
||||
mFontFace->ReleaseFontTable(tableContext);
|
||||
}
|
||||
|
||||
mMetrics->internalLeading = std::max(mMetrics->maxHeight - mMetrics->emHeight, 0.0);
|
||||
@ -252,19 +259,22 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
// if the table is not available or if using hinted/pixel-snapped widths
|
||||
if (mUseSubpixelPositions) {
|
||||
mMetrics->aveCharWidth = 0;
|
||||
gfxFontEntry::AutoTable os2Table(GetFontEntry(),
|
||||
TRUETYPE_TAG('O','S','/','2'));
|
||||
if (os2Table) {
|
||||
uint32_t len;
|
||||
const OS2Table* os2 =
|
||||
reinterpret_cast<const OS2Table*>(hb_blob_get_data(os2Table, &len));
|
||||
if (len >= 4) {
|
||||
hr = mFontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('O', 'S', '/', '2'),
|
||||
(const void**)&tableData,
|
||||
&len,
|
||||
&tableContext,
|
||||
&exists);
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (exists && len >= 4) {
|
||||
// Not checking against sizeof(mozilla::OS2Table) here because older
|
||||
// versions of the table have different sizes; we only need the first
|
||||
// two 16-bit fields here.
|
||||
const mozilla::OS2Table* os2 =
|
||||
reinterpret_cast<const mozilla::OS2Table*>(tableData);
|
||||
mMetrics->aveCharWidth =
|
||||
int16_t(os2->xAvgCharWidth) * mFUnitsConvFactor;
|
||||
}
|
||||
mFontFace->ReleaseFontTable(tableContext);
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,6 +601,60 @@ gfxDWriteFont::Measure(gfxTextRun *aTextRun,
|
||||
return metrics;
|
||||
}
|
||||
|
||||
// Access to font tables packaged in hb_blob_t form
|
||||
|
||||
// object attached to the Harfbuzz blob, used to release
|
||||
// the table when the blob is destroyed
|
||||
class FontTableRec {
|
||||
public:
|
||||
FontTableRec(IDWriteFontFace *aFontFace, void *aContext)
|
||||
: mFontFace(aFontFace), mContext(aContext)
|
||||
{ }
|
||||
|
||||
~FontTableRec() {
|
||||
mFontFace->ReleaseFontTable(mContext);
|
||||
}
|
||||
|
||||
private:
|
||||
IDWriteFontFace *mFontFace;
|
||||
void *mContext;
|
||||
};
|
||||
|
||||
/*static*/ void
|
||||
gfxDWriteFont::DestroyBlobFunc(void* aUserData)
|
||||
{
|
||||
FontTableRec *ftr = static_cast<FontTableRec*>(aUserData);
|
||||
delete ftr;
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxDWriteFont::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
const void *data;
|
||||
UINT32 size;
|
||||
void *context;
|
||||
BOOL exists;
|
||||
HRESULT hr = mFontFace->TryGetFontTable(mozilla::NativeEndian::swapToBigEndian(aTag),
|
||||
&data, &size, &context, &exists);
|
||||
if (SUCCEEDED(hr) && exists) {
|
||||
FontTableRec *ftr = new FontTableRec(mFontFace, context);
|
||||
return hb_blob_create(static_cast<const char*>(data), size,
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
ftr, DestroyBlobFunc);
|
||||
}
|
||||
|
||||
if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
|
||||
// for downloaded fonts, there may be layout tables cached in the entry
|
||||
// even though they're absent from the sanitized platform font
|
||||
hb_blob_t *blob;
|
||||
if (mFontEntry->GetExistingFontTable(aTag, &blob)) {
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxDWriteFont::ProvidesGlyphWidths()
|
||||
{
|
||||
|
@ -52,6 +52,10 @@ public:
|
||||
gfxContext *aContextForTightBoundingBox,
|
||||
Spacing *aSpacing);
|
||||
|
||||
// override gfxFont table access function to bypass gfxFontEntry cache,
|
||||
// use DWrite API to get direct access to system font data
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
|
||||
virtual bool ProvidesGlyphWidths();
|
||||
|
||||
virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID);
|
||||
@ -84,6 +88,8 @@ protected:
|
||||
|
||||
gfxFloat MeasureGlyphWidth(uint16_t aGlyph);
|
||||
|
||||
static void DestroyBlobFunc(void* userArg);
|
||||
|
||||
DWRITE_MEASURING_MODE GetMeasuringMode();
|
||||
bool GetForceGDIClassic();
|
||||
|
||||
|
@ -146,6 +146,22 @@ gfxFT2FontBase::GetSpaceGlyph()
|
||||
return mSpaceGlyph;
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxFT2FontBase::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
if (mFontEntry->GetExistingFontTable(aTag, &blob))
|
||||
return blob;
|
||||
|
||||
FallibleTArray<uint8_t> buffer;
|
||||
bool haveTable = gfxFT2LockedFace(this).GetFontTable(aTag, buffer);
|
||||
|
||||
// Cache even when there is no table to save having to open the FT_Face
|
||||
// again.
|
||||
return mFontEntry->ShareFontTableAndGetBlob(aTag,
|
||||
haveTable ? &buffer : nullptr);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gfxFT2FontBase::GetGlyph(uint32_t unicode, uint32_t variation_selector)
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ public:
|
||||
cairo_text_extents_t* aExtents);
|
||||
virtual const gfxFont::Metrics& GetMetrics();
|
||||
virtual uint32_t GetSpaceGlyph();
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
virtual bool ProvidesGetGlyph() const { return true; }
|
||||
virtual uint32_t GetGlyph(uint32_t unicode, uint32_t variation_selector);
|
||||
virtual bool ProvidesGlyphWidths() { return true; }
|
||||
|
@ -416,7 +416,7 @@ FT2FontEntry::ReadCMAP()
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
AutoFallibleTArray<uint8_t,16384> buffer;
|
||||
nsresult rv = CopyFontTable(TTAG_cmap, buffer);
|
||||
nsresult rv = GetFontTable(TTAG_cmap, buffer);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
bool unicodeFont;
|
||||
@ -438,8 +438,8 @@ FT2FontEntry::ReadCMAP()
|
||||
}
|
||||
|
||||
nsresult
|
||||
FT2FontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
FT2FontEntry::GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
AutoFTFace face(this);
|
||||
if (!face) {
|
||||
|
@ -66,9 +66,7 @@ public:
|
||||
cairo_scaled_font_t *CreateScaledFont(const gfxFontStyle *aStyle);
|
||||
|
||||
nsresult ReadCMAP();
|
||||
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
|
||||
nsresult GetFontTable(uint32_t aTableTag, FallibleTArray<uint8_t>& aBuffer);
|
||||
|
||||
// Check for various kinds of brokenness, and set flags on the entry
|
||||
// accordingly so that we avoid using bad font tables
|
||||
|
@ -318,6 +318,31 @@ gfxFT2LockedFace::GetUVSGlyph(uint32_t aCharCode, uint32_t aVariantSelector)
|
||||
return (*sGetCharVariantPtr)(mFace, aCharCode, aVariantSelector);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFT2LockedFace::GetFontTable(uint32_t aTag, FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
if (!mFace || !FT_IS_SFNT(mFace))
|
||||
return false;
|
||||
|
||||
FT_ULong length = 0;
|
||||
// TRUETYPE_TAG is defined equivalent to FT_MAKE_TAG
|
||||
FT_Error error = FT_Load_Sfnt_Table(mFace, aTag, 0, NULL, &length);
|
||||
if (error != 0)
|
||||
return false;
|
||||
|
||||
if (MOZ_UNLIKELY(length > static_cast<FallibleTArray<uint8_t>::size_type>(-1))
|
||||
|| MOZ_UNLIKELY(!aBuffer.SetLength(length)))
|
||||
return false;
|
||||
|
||||
error = FT_Load_Sfnt_Table(mFace, aTag, 0, aBuffer.Elements(), &length);
|
||||
if (MOZ_UNLIKELY(error != 0)) {
|
||||
aBuffer.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gfxFT2LockedFace::GetCharExtents(char aChar, cairo_text_extents_t* aExtents)
|
||||
{
|
||||
|
@ -48,6 +48,8 @@ public:
|
||||
|
||||
void GetMetrics(gfxFont::Metrics* aMetrics, uint32_t* aSpaceGlyph);
|
||||
|
||||
bool GetFontTable(uint32_t aTag, FallibleTArray<uint8_t>& aBuffer);
|
||||
|
||||
// A scale factor for use in converting horizontal metrics from font units
|
||||
// to pixels.
|
||||
gfxFloat XScale()
|
||||
|
@ -45,7 +45,6 @@
|
||||
|
||||
#include "harfbuzz/hb.h"
|
||||
#include "harfbuzz/hb-ot.h"
|
||||
#include "graphite2/Font.h"
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "GeckoProfiler.h"
|
||||
@ -96,12 +95,6 @@ gfxFontEntry::~gfxFontEntry()
|
||||
gfxUserFontSet::UserFontCache::ForgetFont(this);
|
||||
}
|
||||
|
||||
// By the time the entry is destroyed, all font instances that were
|
||||
// using it should already have been deleted, and so the HB and/or Gr
|
||||
// face objects should have been released.
|
||||
MOZ_ASSERT(!mHBFace);
|
||||
MOZ_ASSERT(!mGrFaceInitialized);
|
||||
|
||||
if (mSVGGlyphs) {
|
||||
delete mSVGGlyphs;
|
||||
}
|
||||
@ -137,19 +130,17 @@ nsresult gfxFontEntry::InitializeUVSMap()
|
||||
|
||||
if (!mUVSData) {
|
||||
const uint32_t kCmapTag = TRUETYPE_TAG('c','m','a','p');
|
||||
AutoTable cmapTable(this, kCmapTag);
|
||||
if (!cmapTable) {
|
||||
AutoFallibleTArray<uint8_t,16384> buffer;
|
||||
if (GetFontTable(kCmapTag, buffer) != NS_OK) {
|
||||
mUVSOffset = 0; // don't bother to read the table again
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint8_t* uvsData;
|
||||
unsigned int cmapLen;
|
||||
const char* cmapData = hb_blob_get_data(cmapTable, &cmapLen);
|
||||
nsresult rv = gfxFontUtils::ReadCMAPTableFormat14(
|
||||
(const uint8_t*)cmapData + mUVSOffset,
|
||||
cmapLen - mUVSOffset, uvsData);
|
||||
|
||||
buffer.Elements() + mUVSOffset,
|
||||
buffer.Length() - mUVSOffset,
|
||||
uvsData);
|
||||
if (NS_FAILED(rv)) {
|
||||
mUVSOffset = 0; // don't bother to read the table again
|
||||
return rv;
|
||||
@ -182,10 +173,11 @@ nsresult gfxFontEntry::ReadCMAP()
|
||||
nsString
|
||||
gfxFontEntry::RealFaceName()
|
||||
{
|
||||
AutoTable nameTable(this, TRUETYPE_TAG('n','a','m','e'));
|
||||
if (nameTable) {
|
||||
FallibleTArray<uint8_t> nameTable;
|
||||
nsresult rv = GetFontTable(TRUETYPE_TAG('n','a','m','e'), nameTable);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoString name;
|
||||
nsresult rv = gfxFontUtils::GetFullNameFromTable(nameTable, name);
|
||||
rv = gfxFontUtils::GetFullNameFromTable(nameTable, name);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return name;
|
||||
}
|
||||
@ -256,22 +248,16 @@ gfxFontEntry::TryGetSVGData()
|
||||
if (!mSVGInitialized) {
|
||||
mSVGInitialized = true;
|
||||
|
||||
// We don't use AutoTable here because we'll pass ownership of these
|
||||
// blobs to the gfxSVGGlyphs, once we've confirmed the tables exist
|
||||
hb_blob_t *svgTable = GetFontTable(TRUETYPE_TAG('S','V','G',' '));
|
||||
if (!svgTable) {
|
||||
FallibleTArray<uint8_t> svgTable;
|
||||
nsresult rv = GetFontTable(TRUETYPE_TAG('S', 'V', 'G', ' '), svgTable);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hb_blob_t *cmapTable = GetFontTable(TRUETYPE_TAG('c','m','a','p'));
|
||||
if (!cmapTable) {
|
||||
NS_NOTREACHED("using a font with no cmap!");
|
||||
hb_blob_destroy(svgTable);
|
||||
return false;
|
||||
}
|
||||
FallibleTArray<uint8_t> cmapTable;
|
||||
rv = GetFontTable(TRUETYPE_TAG('c', 'm', 'a', 'p'), cmapTable);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
// gfxSVGGlyphs will hb_blob_destroy() the tables when it is finished
|
||||
// with them.
|
||||
mSVGGlyphs = new gfxSVGGlyphs(svgTable, cmapTable);
|
||||
}
|
||||
|
||||
@ -441,136 +427,12 @@ gfxFontEntry::ShareFontTableAndGetBlob(uint32_t aTag,
|
||||
return entry->ShareTableAndGetBlob(*aBuffer, &mFontTableCache);
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxFontEntry::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
if (GetExistingFontTable(aTag, &blob)) {
|
||||
return blob;
|
||||
}
|
||||
|
||||
FallibleTArray<uint8_t> buffer;
|
||||
bool haveTable = NS_SUCCEEDED(CopyFontTable(aTag, buffer));
|
||||
|
||||
return ShareFontTableAndGetBlob(aTag, haveTable ? &buffer : nullptr);
|
||||
}
|
||||
|
||||
// callback for HarfBuzz to get a font table (in hb_blob_t form)
|
||||
// from the font entry (passed as aUserData)
|
||||
/*static*/ hb_blob_t *
|
||||
gfxFontEntry::HBGetTable(hb_face_t *face, uint32_t aTag, void *aUserData)
|
||||
{
|
||||
gfxFontEntry *fontEntry = static_cast<gfxFontEntry*>(aUserData);
|
||||
|
||||
// bug 589682 - ignore the GDEF table in buggy fonts (applies to
|
||||
// Italic and BoldItalic faces of Times New Roman)
|
||||
if (aTag == TRUETYPE_TAG('G','D','E','F') &&
|
||||
fontEntry->IgnoreGDEF()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// bug 721719 - ignore the GSUB table in buggy fonts (applies to Roboto,
|
||||
// at least on some Android ICS devices; set in gfxFT2FontList.cpp)
|
||||
if (aTag == TRUETYPE_TAG('G','S','U','B') &&
|
||||
fontEntry->IgnoreGSUB()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fontEntry->GetFontTable(aTag);
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
gfxFontEntry::HBFaceDeletedCallback(void *aUserData)
|
||||
{
|
||||
gfxFontEntry *fe = static_cast<gfxFontEntry*>(aUserData);
|
||||
fe->ForgetHBFace();
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontEntry::ForgetHBFace()
|
||||
{
|
||||
mHBFace = nullptr;
|
||||
}
|
||||
|
||||
hb_face_t*
|
||||
gfxFontEntry::GetHBFace()
|
||||
{
|
||||
if (!mHBFace) {
|
||||
mHBFace = hb_face_create_for_tables(HBGetTable, this,
|
||||
HBFaceDeletedCallback);
|
||||
return mHBFace;
|
||||
}
|
||||
return hb_face_reference(mHBFace);
|
||||
}
|
||||
|
||||
/*static*/ const void*
|
||||
gfxFontEntry::GrGetTable(const void *aAppFaceHandle, unsigned int aName,
|
||||
size_t *aLen)
|
||||
{
|
||||
gfxFontEntry *fontEntry =
|
||||
static_cast<gfxFontEntry*>(const_cast<void*>(aAppFaceHandle));
|
||||
hb_blob_t *blob = fontEntry->GetFontTable(aName);
|
||||
if (blob) {
|
||||
unsigned int blobLength;
|
||||
const void *tableData = hb_blob_get_data(blob, &blobLength);
|
||||
fontEntry->mGrTableMap->Put(tableData, blob);
|
||||
*aLen = blobLength;
|
||||
return tableData;
|
||||
}
|
||||
*aLen = 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
gfxFontEntry::GrReleaseTable(const void *aAppFaceHandle,
|
||||
const void *aTableBuffer)
|
||||
{
|
||||
gfxFontEntry *fontEntry =
|
||||
static_cast<gfxFontEntry*>(const_cast<void*>(aAppFaceHandle));
|
||||
void *data;
|
||||
if (fontEntry->mGrTableMap->Get(aTableBuffer, &data)) {
|
||||
fontEntry->mGrTableMap->Remove(aTableBuffer);
|
||||
hb_blob_destroy(static_cast<hb_blob_t*>(data));
|
||||
}
|
||||
}
|
||||
|
||||
gr_face*
|
||||
gfxFontEntry::GetGrFace()
|
||||
{
|
||||
if (!mGrFaceInitialized) {
|
||||
gr_face_ops faceOps = {
|
||||
sizeof(gr_face_ops),
|
||||
GrGetTable,
|
||||
GrReleaseTable
|
||||
};
|
||||
mGrTableMap = new nsDataHashtable<nsPtrHashKey<const void>,void*>;
|
||||
mGrTableMap->Init();
|
||||
mGrFace = gr_make_face_with_ops(this, &faceOps, gr_face_default);
|
||||
mGrFaceInitialized = true;
|
||||
}
|
||||
++mGrFaceRefCnt;
|
||||
return mGrFace;
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontEntry::ReleaseGrFace(gr_face *aFace)
|
||||
{
|
||||
MOZ_ASSERT(aFace == mGrFace); // sanity-check
|
||||
MOZ_ASSERT(mGrFaceRefCnt > 0);
|
||||
if (--mGrFaceRefCnt == 0) {
|
||||
gr_face_destroy(mGrFace);
|
||||
mGrFace = nullptr;
|
||||
mGrFaceInitialized = false;
|
||||
delete mGrTableMap;
|
||||
mGrTableMap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxFontEntry::CheckForGraphiteTables()
|
||||
{
|
||||
AutoTable silfTable(this, TRUETYPE_TAG('S','i','l','f'));
|
||||
mHasGraphiteTables = silfTable && hb_blob_get_length(silfTable) > 0;
|
||||
AutoFallibleTArray<uint8_t,16384> buffer;
|
||||
mHasGraphiteTables =
|
||||
NS_SUCCEEDED(GetFontTable(TRUETYPE_TAG('S','i','l','f'), buffer));
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
@ -1022,11 +884,11 @@ gfxFontFamily::SearchAllFontsForChar(GlobalFontMatch *aMatchData)
|
||||
// returns true if other names were found, false otherwise
|
||||
bool
|
||||
gfxFontFamily::ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
|
||||
hb_blob_t *aNameTable,
|
||||
bool useFullName)
|
||||
FallibleTArray<uint8_t>& aNameTable,
|
||||
bool useFullName)
|
||||
{
|
||||
uint32_t dataLength;
|
||||
const char *nameData = hb_blob_get_data(aNameTable, &dataLength);
|
||||
const uint8_t *nameData = aNameTable.Elements();
|
||||
uint32_t dataLength = aNameTable.Length();
|
||||
const gfxFontUtils::NameHeader *nameHeader =
|
||||
reinterpret_cast<const gfxFontUtils::NameHeader*>(nameData);
|
||||
|
||||
@ -1085,18 +947,18 @@ gfxFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList)
|
||||
// read in other family names for the first face in the list
|
||||
uint32_t i, numFonts = mAvailableFonts.Length();
|
||||
const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e');
|
||||
AutoFallibleTArray<uint8_t,8192> buffer;
|
||||
|
||||
for (i = 0; i < numFonts; ++i) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (!fe) {
|
||||
if (!fe)
|
||||
continue;
|
||||
}
|
||||
gfxFontEntry::AutoTable nameTable(fe, kNAME);
|
||||
if (!nameTable) {
|
||||
|
||||
if (fe->GetFontTable(kNAME, buffer) != NS_OK)
|
||||
continue;
|
||||
}
|
||||
|
||||
mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aPlatformFontList,
|
||||
nameTable);
|
||||
buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1110,14 +972,13 @@ gfxFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList)
|
||||
// family names for individual weights (e.g. Hiragino Kaku Gothic Pro W6)
|
||||
for ( ; i < numFonts; i++) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (!fe) {
|
||||
if (!fe)
|
||||
continue;
|
||||
}
|
||||
gfxFontEntry::AutoTable nameTable(fe, kNAME);
|
||||
if (!nameTable) {
|
||||
|
||||
if (fe->GetFontTable(kNAME, buffer) != NS_OK)
|
||||
continue;
|
||||
}
|
||||
ReadOtherFamilyNamesForFace(aPlatformFontList, nameTable);
|
||||
|
||||
ReadOtherFamilyNamesForFace(aPlatformFontList, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1134,49 +995,48 @@ gfxFontFamily::ReadFaceNames(gfxPlatformFontList *aPlatformFontList,
|
||||
|
||||
uint32_t i, numFonts = mAvailableFonts.Length();
|
||||
const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e');
|
||||
AutoFallibleTArray<uint8_t,8192> buffer;
|
||||
nsAutoString fullname, psname;
|
||||
|
||||
bool firstTime = true, readAllFaces = false;
|
||||
for (i = 0; i < numFonts; ++i) {
|
||||
gfxFontEntry *fe = mAvailableFonts[i];
|
||||
if (!fe) {
|
||||
if (!fe)
|
||||
continue;
|
||||
}
|
||||
gfxFontEntry::AutoTable nameTable(fe, kNAME);
|
||||
if (!nameTable) {
|
||||
|
||||
if (fe->GetFontTable(kNAME, buffer) != NS_OK)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aNeedFullnamePostscriptNames) {
|
||||
if (gfxFontUtils::ReadCanonicalName(
|
||||
nameTable, gfxFontUtils::NAME_ID_FULL, fullname) == NS_OK)
|
||||
buffer, gfxFontUtils::NAME_ID_FULL, fullname) == NS_OK)
|
||||
{
|
||||
aPlatformFontList->AddFullname(fe, fullname);
|
||||
}
|
||||
|
||||
if (gfxFontUtils::ReadCanonicalName(
|
||||
nameTable, gfxFontUtils::NAME_ID_POSTSCRIPT, psname) == NS_OK)
|
||||
buffer, gfxFontUtils::NAME_ID_POSTSCRIPT, psname) == NS_OK)
|
||||
{
|
||||
aPlatformFontList->AddPostscriptName(fe, psname);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mOtherFamilyNamesInitialized && (firstTime || readAllFaces)) {
|
||||
bool foundOtherName = ReadOtherFamilyNamesForFace(aPlatformFontList,
|
||||
nameTable);
|
||||
if (!mOtherFamilyNamesInitialized && (firstTime || readAllFaces)) {
|
||||
bool foundOtherName = ReadOtherFamilyNamesForFace(aPlatformFontList,
|
||||
buffer);
|
||||
|
||||
// if the first face has a different name, scan all faces, otherwise
|
||||
// assume the family doesn't have other names
|
||||
if (firstTime && foundOtherName) {
|
||||
mHasOtherFamilyNames = true;
|
||||
readAllFaces = true;
|
||||
}
|
||||
firstTime = false;
|
||||
}
|
||||
// if the first face has a different name, scan all faces, otherwise
|
||||
// assume the family doesn't have other names
|
||||
if (firstTime && foundOtherName) {
|
||||
mHasOtherFamilyNames = true;
|
||||
readAllFaces = true;
|
||||
}
|
||||
firstTime = false;
|
||||
}
|
||||
|
||||
// if not reading in any more names, skip other faces
|
||||
if (!readAllFaces && !aNeedFullnamePostscriptNames) {
|
||||
break;
|
||||
}
|
||||
// if not reading in any more names, skip other faces
|
||||
if (!readAllFaces && !aNeedFullnamePostscriptNames)
|
||||
break;
|
||||
}
|
||||
|
||||
mFaceNamesInitialized = true;
|
||||
@ -1714,6 +1574,26 @@ gfxFont::AgeCacheEntry(CacheHashEntry *aEntry, void *aUserData)
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxFont::GetFontTable(uint32_t aTag) {
|
||||
hb_blob_t *blob;
|
||||
if (mFontEntry->GetExistingFontTable(aTag, &blob))
|
||||
return blob;
|
||||
|
||||
FallibleTArray<uint8_t> buffer;
|
||||
bool haveTable = NS_SUCCEEDED(mFontEntry->GetFontTable(aTag, buffer));
|
||||
|
||||
return mFontEntry->ShareFontTableAndGetBlob(aTag,
|
||||
haveTable ? &buffer : nullptr);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
HBGetTable(hb_face_t *face, hb_tag_t aTag, void *aUserData)
|
||||
{
|
||||
gfxFont* font = static_cast<gfxFont*>(aUserData);
|
||||
return font->GetFontTable(aTag);
|
||||
}
|
||||
|
||||
static bool
|
||||
HasLookupRuleWithGlyphByScript(hb_face_t *aFace, hb_tag_t aTableTag,
|
||||
hb_tag_t aScript, uint16_t aGlyph)
|
||||
@ -1877,7 +1757,7 @@ gfxFont::CheckForFeaturesInvolvingSpace()
|
||||
|
||||
bool result = false;
|
||||
|
||||
hb_face_t *face = GetFontEntry()->GetHBFace();
|
||||
hb_face_t *face = hb_face_create_for_tables(HBGetTable, this, nullptr);
|
||||
|
||||
uint32_t i, len, offset;
|
||||
uint32_t spaceGlyph = GetSpaceGlyph();
|
||||
@ -3412,8 +3292,6 @@ gfxFont::SetupGlyphExtents(gfxContext *aContext, uint32_t aGlyphID, bool aNeedTi
|
||||
// Return FALSE if the gfxFontEntry subclass does not
|
||||
// implement GetFontTable(), or for non-sfnt fonts where tables are
|
||||
// not available.
|
||||
// If this returns TRUE without setting the mIsValid flag, then we -did-
|
||||
// apparently find an sfnt, but it was too broken to be used.
|
||||
bool
|
||||
gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
{
|
||||
@ -3424,21 +3302,16 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
const uint32_t kPostTableTag = TRUETYPE_TAG('p','o','s','t');
|
||||
const uint32_t kOS_2TableTag = TRUETYPE_TAG('O','S','/','2');
|
||||
|
||||
uint32_t len;
|
||||
|
||||
if (mFUnitsConvFactor == 0.0) {
|
||||
// If the conversion factor from FUnits is not yet set,
|
||||
// 'head' table is required; otherwise we cannot read any metrics
|
||||
// because we don't know unitsPerEm
|
||||
gfxFontEntry::AutoTable headTable(mFontEntry, kHeadTableTag);
|
||||
if (!headTable) {
|
||||
return false;
|
||||
}
|
||||
const HeadTable* head =
|
||||
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
|
||||
if (len < sizeof(HeadTable)) {
|
||||
return false;
|
||||
AutoFallibleTArray<uint8_t,sizeof(HeadTable)> headData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kHeadTableTag, headData)) ||
|
||||
headData.Length() < sizeof(HeadTable)) {
|
||||
return false; // no 'head' table -> not an sfnt
|
||||
}
|
||||
HeadTable *head = reinterpret_cast<HeadTable*>(headData.Elements());
|
||||
uint32_t unitsPerEm = head->unitsPerEm;
|
||||
if (!unitsPerEm) {
|
||||
return true; // is an sfnt, but not valid
|
||||
@ -3447,15 +3320,12 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
}
|
||||
|
||||
// 'hhea' table is required to get vertical extents
|
||||
gfxFontEntry::AutoTable hheaTable(mFontEntry, kHheaTableTag);
|
||||
if (!hheaTable) {
|
||||
AutoFallibleTArray<uint8_t,sizeof(HheaTable)> hheaData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kHheaTableTag, hheaData)) ||
|
||||
hheaData.Length() < sizeof(HheaTable)) {
|
||||
return false; // no 'hhea' table -> not an sfnt
|
||||
}
|
||||
const HheaTable* hhea =
|
||||
reinterpret_cast<const HheaTable*>(hb_blob_get_data(hheaTable, &len));
|
||||
if (len < sizeof(HheaTable)) {
|
||||
return false;
|
||||
}
|
||||
HheaTable *hhea = reinterpret_cast<HheaTable*>(hheaData.Elements());
|
||||
|
||||
#define SET_UNSIGNED(field,src) aMetrics.field = uint16_t(src) * mFUnitsConvFactor
|
||||
#define SET_SIGNED(field,src) aMetrics.field = int16_t(src) * mFUnitsConvFactor
|
||||
@ -3466,26 +3336,27 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
SET_SIGNED(externalLeading, hhea->lineGap);
|
||||
|
||||
// 'post' table is required for underline metrics
|
||||
gfxFontEntry::AutoTable postTable(mFontEntry, kPostTableTag);
|
||||
if (!postTable) {
|
||||
AutoFallibleTArray<uint8_t,sizeof(PostTable)> postData;
|
||||
if (NS_FAILED(mFontEntry->GetFontTable(kPostTableTag, postData))) {
|
||||
return true; // no 'post' table -> sfnt is not valid
|
||||
}
|
||||
const PostTable *post =
|
||||
reinterpret_cast<const PostTable*>(hb_blob_get_data(postTable, &len));
|
||||
if (len < offsetof(PostTable, underlineThickness) + sizeof(uint16_t)) {
|
||||
if (postData.Length() <
|
||||
offsetof(PostTable, underlineThickness) + sizeof(uint16_t)) {
|
||||
return true; // bad post table -> sfnt is not valid
|
||||
}
|
||||
PostTable *post = reinterpret_cast<PostTable*>(postData.Elements());
|
||||
|
||||
SET_SIGNED(underlineOffset, post->underlinePosition);
|
||||
SET_UNSIGNED(underlineSize, post->underlineThickness);
|
||||
|
||||
// 'OS/2' table is optional, if not found we'll estimate xHeight
|
||||
// and aveCharWidth by measuring glyphs
|
||||
gfxFontEntry::AutoTable os2Table(mFontEntry, kOS_2TableTag);
|
||||
if (os2Table) {
|
||||
const OS2Table *os2 =
|
||||
reinterpret_cast<const OS2Table*>(hb_blob_get_data(os2Table, &len));
|
||||
if (len >= offsetof(OS2Table, sxHeight) + sizeof(int16_t) &&
|
||||
AutoFallibleTArray<uint8_t,sizeof(OS2Table)> os2data;
|
||||
if (NS_SUCCEEDED(mFontEntry->GetFontTable(kOS_2TableTag, os2data))) {
|
||||
OS2Table *os2 = reinterpret_cast<OS2Table*>(os2data.Elements());
|
||||
|
||||
if (os2data.Length() >= offsetof(OS2Table, sxHeight) +
|
||||
sizeof(int16_t) &&
|
||||
uint16_t(os2->version) >= 2) {
|
||||
// version 2 and later includes the x-height field
|
||||
SET_SIGNED(xHeight, os2->sxHeight);
|
||||
@ -3493,7 +3364,8 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
||||
aMetrics.xHeight = Abs(aMetrics.xHeight);
|
||||
}
|
||||
// this should always be present
|
||||
if (len >= offsetof(OS2Table, yStrikeoutPosition) + sizeof(int16_t)) {
|
||||
if (os2data.Length() >= offsetof(OS2Table, yStrikeoutPosition) +
|
||||
sizeof(int16_t)) {
|
||||
SET_SIGNED(aveCharWidth, os2->xAvgCharWidth);
|
||||
SET_SIGNED(subscriptOffset, os2->ySubscriptYOffset);
|
||||
SET_SIGNED(superscriptOffset, os2->ySuperscriptYOffset);
|
||||
|
@ -29,10 +29,8 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include <algorithm>
|
||||
#include "nsUnicodeProperties.h"
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
typedef struct _cairo_scaled_font cairo_scaled_font_t;
|
||||
typedef struct gr_face gr_face;
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
@ -52,6 +50,8 @@ class gfxTextObjectPaint;
|
||||
|
||||
class nsILanguageAtomService;
|
||||
|
||||
typedef struct hb_blob_t hb_blob_t;
|
||||
|
||||
#define FONT_MAX_SIZE 2000.0
|
||||
|
||||
#define NO_FONT_LANGUAGE_OVERRIDE 0
|
||||
@ -237,17 +237,13 @@ public:
|
||||
mHasSpaceFeaturesKerning(false),
|
||||
mHasSpaceFeaturesNonKerning(false),
|
||||
mHasSpaceFeaturesSubDefault(false),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mUVSOffset(0), mUVSData(nullptr),
|
||||
mUserFontData(nullptr),
|
||||
mSVGGlyphs(nullptr),
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||
mHBFace(nullptr),
|
||||
mGrFace(nullptr),
|
||||
mGrFaceRefCnt(0)
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE)
|
||||
{
|
||||
memset(&mHasSpaceFeaturesSub, 0, sizeof(mHasSpaceFeaturesSub));
|
||||
}
|
||||
@ -326,46 +322,9 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Access to raw font table data (needed for Harfbuzz):
|
||||
// returns a pointer to data owned by the fontEntry or the OS,
|
||||
// which will remain valid until the blob is destroyed.
|
||||
// The data MUST be treated as read-only; we may be getting a
|
||||
// reference to a shared system font cache.
|
||||
//
|
||||
// The default implementation uses CopyFontTable to get the data
|
||||
// into a byte array, and maintains a cache of loaded tables.
|
||||
//
|
||||
// Subclasses should override this if they can provide more efficient
|
||||
// access than copying table data into our own buffers.
|
||||
//
|
||||
// Get blob that encapsulates a specific font table, or NULL if
|
||||
// the table doesn't exist in the font.
|
||||
//
|
||||
// Caller is responsible to call hb_blob_destroy() on the returned blob
|
||||
// (if non-NULL) when no longer required. For transient access to a table,
|
||||
// use of AutoTable (below) is generally preferred.
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
|
||||
// Stack-based utility to return a specified table, automatically releasing
|
||||
// the blob when the AutoTable goes out of scope.
|
||||
class AutoTable {
|
||||
public:
|
||||
AutoTable(gfxFontEntry* aFontEntry, uint32_t aTag)
|
||||
{
|
||||
mBlob = aFontEntry->GetFontTable(aTag);
|
||||
}
|
||||
~AutoTable() {
|
||||
if (mBlob) {
|
||||
hb_blob_destroy(mBlob);
|
||||
}
|
||||
}
|
||||
operator hb_blob_t*() const { return mBlob; }
|
||||
private:
|
||||
hb_blob_t* mBlob;
|
||||
// not implemented:
|
||||
AutoTable(const AutoTable&) MOZ_DELETE;
|
||||
AutoTable& operator=(const AutoTable&) MOZ_DELETE;
|
||||
};
|
||||
virtual nsresult GetFontTable(uint32_t aTableTag, FallibleTArray<uint8_t>& aBuffer) {
|
||||
return NS_ERROR_FAILURE; // all platform subclasses should reimplement this!
|
||||
}
|
||||
|
||||
already_AddRefed<gfxFont> FindOrMakeFont(const gfxFontStyle *aStyle,
|
||||
bool aNeedsBold);
|
||||
@ -388,21 +347,6 @@ public:
|
||||
hb_blob_t *ShareFontTableAndGetBlob(uint32_t aTag,
|
||||
FallibleTArray<uint8_t>* aTable);
|
||||
|
||||
// Shaper face accessors:
|
||||
// NOTE that harfbuzz and graphite handle ownership/lifetime of the face
|
||||
// object in completely different ways.
|
||||
|
||||
// Get HarfBuzz face corresponding to this font file.
|
||||
// Caller must release with hb_face_destroy() when finished with it,
|
||||
// and the font entry will be notified via ForgetHBFace.
|
||||
hb_face_t* GetHBFace();
|
||||
virtual void ForgetHBFace();
|
||||
|
||||
// Get Graphite face corresponding to this font file.
|
||||
// Caller must call gfxFontEntry::ReleaseGrFace when finished with it.
|
||||
gr_face* GetGrFace();
|
||||
virtual void ReleaseGrFace(gr_face* aFace);
|
||||
|
||||
// For memory reporting
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
@ -429,10 +373,6 @@ public:
|
||||
bool mHasSpaceFeaturesKerning : 1;
|
||||
bool mHasSpaceFeaturesNonKerning : 1;
|
||||
bool mHasSpaceFeaturesSubDefault : 1;
|
||||
bool mHasGraphiteTables : 1;
|
||||
bool mCheckedForGraphiteTables : 1;
|
||||
bool mHasCmapTable : 1;
|
||||
bool mGrFaceInitialized : 1;
|
||||
|
||||
// bitvector of substitution space features per script
|
||||
uint32_t mHasSpaceFeaturesSub[(MOZ_NUM_SCRIPT_CODES + 31) / 32];
|
||||
@ -440,6 +380,9 @@ public:
|
||||
uint16_t mWeight;
|
||||
int16_t mStretch;
|
||||
|
||||
bool mHasGraphiteTables;
|
||||
bool mCheckedForGraphiteTables;
|
||||
bool mHasCmapTable;
|
||||
nsRefPtr<gfxCharacterMap> mCharacterMap;
|
||||
uint32_t mUVSOffset;
|
||||
nsAutoArrayPtr<uint8_t> mUVSData;
|
||||
@ -472,17 +415,13 @@ protected:
|
||||
mHasSpaceFeaturesKerning(false),
|
||||
mHasSpaceFeaturesNonKerning(false),
|
||||
mHasSpaceFeaturesSubDefault(false),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mUVSOffset(0), mUVSData(nullptr),
|
||||
mUserFontData(nullptr),
|
||||
mSVGGlyphs(nullptr),
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||
mHBFace(nullptr),
|
||||
mGrFace(nullptr),
|
||||
mGrFaceRefCnt(0)
|
||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE)
|
||||
{ }
|
||||
|
||||
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold) {
|
||||
@ -492,52 +431,8 @@ protected:
|
||||
|
||||
virtual void CheckForGraphiteTables();
|
||||
|
||||
// Copy a font table into aBuffer.
|
||||
// The caller will be responsible for ownership of the data.
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer) {
|
||||
NS_NOTREACHED("forgot to override either GetFontTable or CopyFontTable?");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Shaper-specific face objects, shared by all instantiations of the same
|
||||
// physical font, regardless of size.
|
||||
// Usually, only one of these will actually be created for any given font
|
||||
// entry, depending on the font tables that are present.
|
||||
|
||||
// hb_face_t is refcounted internally, so each shaper that's using it will
|
||||
// bump the ref count when it acquires the face, and "destroy" (release) it
|
||||
// in its destructor. The font entry has only this non-owning reference to
|
||||
// the face; when the face is deleted, it will tell the font entry to forget
|
||||
// it, so that a new face will be created next time it is needed.
|
||||
hb_face_t* mHBFace;
|
||||
|
||||
static hb_blob_t* HBGetTable(hb_face_t *face, uint32_t aTag, void *aUserData);
|
||||
|
||||
// Callback that the hb_face will use to tell us when it is being deleted.
|
||||
static void HBFaceDeletedCallback(void *aUserData);
|
||||
|
||||
// gr_face is -not- refcounted, so it will be owned directly by the font
|
||||
// entry, and we'll keep a count of how many references we've handed out;
|
||||
// each shaper is responsible to call ReleaseGrFace on its entry when
|
||||
// finished with it, so that we know when it can be deleted.
|
||||
gr_face* mGrFace;
|
||||
|
||||
// hashtable to map raw table data ptr back to its owning blob, for use by
|
||||
// graphite table-release callback
|
||||
nsDataHashtable<nsPtrHashKey<const void>,void*>* mGrTableMap;
|
||||
|
||||
// number of current users of this entry's mGrFace
|
||||
nsrefcnt mGrFaceRefCnt;
|
||||
|
||||
static const void* GrGetTable(const void *aAppFaceHandle,
|
||||
unsigned int aName,
|
||||
size_t *aLen);
|
||||
static void GrReleaseTable(const void *aAppFaceHandle,
|
||||
const void *aTableBuffer);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Font table hashtable, to support GetFontTable for harfbuzz.
|
||||
*
|
||||
@ -797,8 +692,8 @@ protected:
|
||||
bool anItalic, int16_t aStretch);
|
||||
|
||||
bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
|
||||
hb_blob_t *aNameTable,
|
||||
bool useFullName = false);
|
||||
FallibleTArray<uint8_t>& aNameTable,
|
||||
bool useFullName = false);
|
||||
|
||||
// set whether this font family is in "bad" underline offset blacklist.
|
||||
void SetBadUnderlineFonts() {
|
||||
@ -1412,6 +1307,21 @@ public:
|
||||
return mFontEntry->HasGraphiteTables();
|
||||
}
|
||||
|
||||
// Access to raw font table data (needed for Harfbuzz):
|
||||
// returns a pointer to data owned by the fontEntry or the OS,
|
||||
// which will remain valid until released.
|
||||
//
|
||||
// Default implementations forward to the font entry,
|
||||
// and maintain a shared table.
|
||||
//
|
||||
// Subclasses should override this if they can provide more efficient
|
||||
// access than getting tables with mFontEntry->GetFontTable() and sharing
|
||||
// them via the entry.
|
||||
//
|
||||
// Get pointer to a specific font table, or NULL if
|
||||
// the table doesn't exist in the font
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
|
||||
// Subclasses may choose to look up glyph ids for characters.
|
||||
// If they do not override this, gfxHarfBuzzShaper will fetch the cmap
|
||||
// table and use that.
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include "nsMemory.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
#include "plbase64.h"
|
||||
#include "prlog.h"
|
||||
|
||||
@ -1217,18 +1215,17 @@ gfxFontUtils::GetFullNameFromSFNT(const uint8_t* aFontData, uint32_t aLength,
|
||||
uint32_t len = dirEntry->length;
|
||||
NS_ENSURE_TRUE(aLength > len && aLength - len >= dirEntry->offset,
|
||||
NS_ERROR_UNEXPECTED);
|
||||
FallibleTArray<uint8_t> nameTable;
|
||||
if (!nameTable.SetLength(len)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
memcpy(nameTable.Elements(), aFontData + dirEntry->offset, len);
|
||||
|
||||
hb_blob_t *nameBlob =
|
||||
hb_blob_create((const char*)aFontData + dirEntry->offset, len,
|
||||
HB_MEMORY_MODE_READONLY, nullptr, nullptr);
|
||||
nsresult rv = GetFullNameFromTable(nameBlob, aFullName);
|
||||
hb_blob_destroy(nameBlob);
|
||||
|
||||
return rv;
|
||||
return GetFullNameFromTable(nameTable, aFullName);
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::GetFullNameFromTable(hb_blob_t *aNameTable,
|
||||
gfxFontUtils::GetFullNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
nsAString& aFullName)
|
||||
{
|
||||
nsAutoString name;
|
||||
@ -1260,7 +1257,7 @@ gfxFontUtils::GetFullNameFromTable(hb_blob_t *aNameTable,
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::GetFamilyNameFromTable(hb_blob_t *aNameTable,
|
||||
gfxFontUtils::GetFamilyNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
nsAString& aFullName)
|
||||
{
|
||||
nsAutoString name;
|
||||
@ -1286,14 +1283,14 @@ enum {
|
||||
};
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
gfxFontUtils::ReadNames(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
int32_t aPlatformID, nsTArray<nsString>& aNames)
|
||||
{
|
||||
return ReadNames(aNameTable, aNameID, LANG_ALL, aPlatformID, aNames);
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::ReadCanonicalName(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
gfxFontUtils::ReadCanonicalName(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
nsString& aName)
|
||||
{
|
||||
nsresult rv;
|
||||
@ -1461,7 +1458,7 @@ gfxFontUtils::GetCharsetForFontName(uint16_t aPlatform, uint16_t aScript, uint16
|
||||
// convert a raw name from the name table to an nsString, if possible;
|
||||
// return value indicates whether conversion succeeded
|
||||
bool
|
||||
gfxFontUtils::DecodeFontName(const char *aNameData, int32_t aByteLen,
|
||||
gfxFontUtils::DecodeFontName(const uint8_t *aNameData, int32_t aByteLen,
|
||||
uint32_t aPlatformCode, uint32_t aScriptCode,
|
||||
uint32_t aLangCode, nsAString& aName)
|
||||
{
|
||||
@ -1511,7 +1508,7 @@ gfxFontUtils::DecodeFontName(const char *aNameData, int32_t aByteLen,
|
||||
}
|
||||
|
||||
int32_t destLength;
|
||||
rv = decoder->GetMaxLength(aNameData, aByteLen, &destLength);
|
||||
rv = decoder->GetMaxLength(reinterpret_cast<const char*>(aNameData), aByteLen, &destLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("decoder->GetMaxLength failed, invalid font name?");
|
||||
return false;
|
||||
@ -1519,7 +1516,7 @@ gfxFontUtils::DecodeFontName(const char *aNameData, int32_t aByteLen,
|
||||
|
||||
// make space for the converted string
|
||||
aName.SetLength(destLength);
|
||||
rv = decoder->Convert(aNameData, &aByteLen,
|
||||
rv = decoder->Convert(reinterpret_cast<const char*>(aNameData), &aByteLen,
|
||||
aName.BeginWriting(), &destLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("decoder->Convert failed, invalid font name?");
|
||||
@ -1531,17 +1528,17 @@ gfxFontUtils::DecodeFontName(const char *aNameData, int32_t aByteLen,
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
gfxFontUtils::ReadNames(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
int32_t aLangID, int32_t aPlatformID,
|
||||
nsTArray<nsString>& aNames)
|
||||
{
|
||||
uint32_t nameTableLen;
|
||||
const char *nameTable = hb_blob_get_data(aNameTable, &nameTableLen);
|
||||
uint32_t nameTableLen = aNameTable.Length();
|
||||
NS_ASSERTION(nameTableLen != 0, "null name table");
|
||||
|
||||
if (!nameTableLen) {
|
||||
if (nameTableLen == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint8_t *nameTable = aNameTable.Elements();
|
||||
|
||||
// -- name table data
|
||||
const NameHeader *nameHeader = reinterpret_cast<const NameHeader*>(nameTable);
|
||||
|
@ -33,8 +33,6 @@
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
typedef struct hb_blob_t hb_blob_t;
|
||||
|
||||
class gfxSparseBitSet {
|
||||
private:
|
||||
enum { BLOCK_SIZE = 32 }; // ==> 256 codepoints per block
|
||||
@ -831,12 +829,12 @@ public:
|
||||
// helper to get fullname from name table, constructing from family+style
|
||||
// if no explicit fullname is present
|
||||
static nsresult
|
||||
GetFullNameFromTable(hb_blob_t *aNameTable,
|
||||
GetFullNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
nsAString& aFullName);
|
||||
|
||||
// helper to get family name from name table
|
||||
static nsresult
|
||||
GetFamilyNameFromTable(hb_blob_t *aNameTable,
|
||||
GetFamilyNameFromTable(FallibleTArray<uint8_t>& aNameTable,
|
||||
nsAString& aFamilyName);
|
||||
|
||||
// create a new name table and build a new font with that name table
|
||||
@ -847,20 +845,20 @@ public:
|
||||
|
||||
// read all names matching aNameID, returning in aNames array
|
||||
static nsresult
|
||||
ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
ReadNames(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
int32_t aPlatformID, nsTArray<nsString>& aNames);
|
||||
|
||||
// reads English or first name matching aNameID, returning in aName
|
||||
// platform based on OS
|
||||
static nsresult
|
||||
ReadCanonicalName(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
ReadCanonicalName(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
nsString& aName);
|
||||
|
||||
// convert a name from the raw name table data into an nsString,
|
||||
// provided we know how; return true if successful, or false
|
||||
// if we can't handle the encoding
|
||||
static bool
|
||||
DecodeFontName(const char *aBuf, int32_t aLength,
|
||||
DecodeFontName(const uint8_t *aBuf, int32_t aLength,
|
||||
uint32_t aPlatformCode, uint32_t aScriptCode,
|
||||
uint32_t aLangCode, nsAString& dest);
|
||||
|
||||
@ -936,7 +934,7 @@ public:
|
||||
|
||||
protected:
|
||||
static nsresult
|
||||
ReadNames(hb_blob_t *aNameTable, uint32_t aNameID,
|
||||
ReadNames(FallibleTArray<uint8_t>& aNameTable, uint32_t aNameID,
|
||||
int32_t aLangID, int32_t aPlatformID, nsTArray<nsString>& aNames);
|
||||
|
||||
// convert opentype name-table platform/encoding/language values to a charset name
|
||||
|
@ -199,7 +199,7 @@ GDIFontEntry::ReadCMAP()
|
||||
nsresult rv;
|
||||
|
||||
AutoFallibleTArray<uint8_t,16384> cmap;
|
||||
rv = CopyFontTable(kCMAP, cmap);
|
||||
rv = GetFontTable(kCMAP, cmap);
|
||||
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
@ -263,8 +263,8 @@ GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold
|
||||
}
|
||||
|
||||
nsresult
|
||||
GDIFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
GDIFontEntry::GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
if (!IsTrueType()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -280,8 +280,8 @@ protected:
|
||||
|
||||
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold);
|
||||
|
||||
virtual nsresult CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
|
||||
virtual nsresult GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer);
|
||||
|
||||
LOGFONTW mLogFont;
|
||||
};
|
||||
|
@ -40,26 +40,69 @@ using namespace mozilla; // for AutoSwap_* types
|
||||
|
||||
gfxGraphiteShaper::gfxGraphiteShaper(gfxFont *aFont)
|
||||
: gfxFontShaper(aFont),
|
||||
mGrFace(mFont->GetFontEntry()->GetGrFace()),
|
||||
mGrFace(nullptr),
|
||||
mGrFont(nullptr)
|
||||
{
|
||||
mTables.Init();
|
||||
mCallbackData.mFont = aFont;
|
||||
mCallbackData.mShaper = this;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
ReleaseTableFunc(const uint32_t& /* aKey */,
|
||||
gfxGraphiteShaper::TableRec& aData,
|
||||
void* /* aUserArg */)
|
||||
{
|
||||
hb_blob_destroy(aData.mBlob);
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
gfxGraphiteShaper::~gfxGraphiteShaper()
|
||||
{
|
||||
if (mGrFont) {
|
||||
gr_font_destroy(mGrFont);
|
||||
}
|
||||
mFont->GetFontEntry()->ReleaseGrFace(mGrFace);
|
||||
if (mGrFace) {
|
||||
gr_face_destroy(mGrFace);
|
||||
}
|
||||
mTables.Enumerate(ReleaseTableFunc, nullptr);
|
||||
}
|
||||
|
||||
/*static*/ float
|
||||
gfxGraphiteShaper::GrGetAdvance(const void* appFontHandle, uint16_t glyphid)
|
||||
static const void*
|
||||
GrGetTable(const void* appFaceHandle, unsigned int name, size_t *len)
|
||||
{
|
||||
const CallbackData *cb =
|
||||
static_cast<const CallbackData*>(appFontHandle);
|
||||
const gfxGraphiteShaper::CallbackData *cb =
|
||||
static_cast<const gfxGraphiteShaper::CallbackData*>(appFaceHandle);
|
||||
return cb->mShaper->GetTable(name, len);
|
||||
}
|
||||
|
||||
const void*
|
||||
gfxGraphiteShaper::GetTable(uint32_t aTag, size_t *aLength)
|
||||
{
|
||||
TableRec tableRec;
|
||||
|
||||
if (!mTables.Get(aTag, &tableRec)) {
|
||||
hb_blob_t *blob = mFont->GetFontTable(aTag);
|
||||
if (blob) {
|
||||
// mFont->GetFontTable() gives us a reference to the blob.
|
||||
// We will destroy (release) it in our destructor.
|
||||
tableRec.mBlob = blob;
|
||||
tableRec.mData = hb_blob_get_data(blob, &tableRec.mLength);
|
||||
mTables.Put(aTag, tableRec);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
*aLength = tableRec.mLength;
|
||||
return tableRec.mData;
|
||||
}
|
||||
|
||||
static float
|
||||
GrGetAdvance(const void* appFontHandle, gr_uint16 glyphid)
|
||||
{
|
||||
const gfxGraphiteShaper::CallbackData *cb =
|
||||
static_cast<const gfxGraphiteShaper::CallbackData*>(appFontHandle);
|
||||
return FixedToFloat(cb->mFont->GetGlyphWidth(cb->mContext, glyphid));
|
||||
}
|
||||
|
||||
@ -109,6 +152,7 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
|
||||
mCallbackData.mContext = aContext;
|
||||
|
||||
if (!mGrFont) {
|
||||
mGrFace = gr_make_face(&mCallbackData, GrGetTable, gr_face_default);
|
||||
if (!mGrFace) {
|
||||
return false;
|
||||
}
|
||||
@ -126,6 +170,8 @@ gfxGraphiteShaper::ShapeText(gfxContext *aContext,
|
||||
}
|
||||
|
||||
if (!mGrFont) {
|
||||
gr_face_destroy(mGrFace);
|
||||
mGrFace = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,22 @@ public:
|
||||
int32_t aScript,
|
||||
gfxShapedText *aShapedText);
|
||||
|
||||
const void* GetTable(uint32_t aTag, size_t *aLength);
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
struct CallbackData {
|
||||
gfxFont *mFont;
|
||||
gfxGraphiteShaper *mShaper;
|
||||
gfxContext *mContext;
|
||||
};
|
||||
|
||||
struct TableRec {
|
||||
hb_blob_t *mBlob;
|
||||
const void *mData;
|
||||
uint32_t mLength;
|
||||
};
|
||||
|
||||
protected:
|
||||
nsresult SetGlyphsFromSegment(gfxContext *aContext,
|
||||
gfxShapedText *aShapedText,
|
||||
@ -37,20 +51,13 @@ protected:
|
||||
const PRUnichar *aText,
|
||||
gr_segment *aSegment);
|
||||
|
||||
static float GrGetAdvance(const void* appFontHandle, uint16_t glyphid);
|
||||
|
||||
gr_face *mGrFace; // owned by the font entry; shaper must call
|
||||
// gfxFontEntry::ReleaseGrFace when finished with it
|
||||
gr_font *mGrFont; // owned by the shaper itself
|
||||
|
||||
struct CallbackData {
|
||||
gfxFont *mFont;
|
||||
gfxGraphiteShaper *mShaper;
|
||||
gfxContext *mContext;
|
||||
};
|
||||
gr_face *mGrFace;
|
||||
gr_font *mGrFont;
|
||||
|
||||
CallbackData mCallbackData;
|
||||
|
||||
nsDataHashtable<nsUint32HashKey,TableRec> mTables;
|
||||
|
||||
// Convert HTML 'lang' (BCP47) to Graphite language code
|
||||
static uint32_t GetGraphiteTagForLang(const nsCString& aLang);
|
||||
static nsTHashtable<nsUint32HashKey> sLanguageTags;
|
||||
|
@ -43,8 +43,7 @@ using namespace mozilla::unicode; // for Unicode property lookup
|
||||
|
||||
gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
|
||||
: gfxFontShaper(aFont),
|
||||
mHBFace(aFont->GetFontEntry()->GetHBFace()),
|
||||
mHBFont(nullptr),
|
||||
mHBFace(nullptr),
|
||||
mKernTable(nullptr),
|
||||
mHmtxTable(nullptr),
|
||||
mNumLongMetrics(0),
|
||||
@ -53,30 +52,63 @@ gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
|
||||
mSubtableOffset(0),
|
||||
mUVSTableOffset(0),
|
||||
mUseFontGetGlyph(aFont->ProvidesGetGlyph()),
|
||||
mUseFontGlyphWidths(false),
|
||||
mInitialized(false)
|
||||
mUseFontGlyphWidths(false)
|
||||
{
|
||||
}
|
||||
|
||||
gfxHarfBuzzShaper::~gfxHarfBuzzShaper()
|
||||
{
|
||||
if (mCmapTable) {
|
||||
hb_blob_destroy(mCmapTable);
|
||||
}
|
||||
if (mHmtxTable) {
|
||||
hb_blob_destroy(mHmtxTable);
|
||||
}
|
||||
if (mKernTable) {
|
||||
hb_blob_destroy(mKernTable);
|
||||
}
|
||||
if (mHBFont) {
|
||||
hb_font_destroy(mHBFont);
|
||||
}
|
||||
if (mHBFace) {
|
||||
hb_face_destroy(mHBFace);
|
||||
}
|
||||
hb_blob_destroy(mCmapTable);
|
||||
hb_blob_destroy(mHmtxTable);
|
||||
hb_blob_destroy(mKernTable);
|
||||
hb_face_destroy(mHBFace);
|
||||
}
|
||||
|
||||
/*
|
||||
* HarfBuzz callback access to font table data
|
||||
*/
|
||||
|
||||
// callback for HarfBuzz to get a font table (in hb_blob_t form)
|
||||
// from the shaper (passed as aUserData)
|
||||
static hb_blob_t *
|
||||
HBGetTable(hb_face_t *face, hb_tag_t aTag, void *aUserData)
|
||||
{
|
||||
gfxHarfBuzzShaper *shaper = static_cast<gfxHarfBuzzShaper*>(aUserData);
|
||||
gfxFont *font = shaper->GetFont();
|
||||
|
||||
// bug 589682 - ignore the GDEF table in buggy fonts (applies to
|
||||
// Italic and BoldItalic faces of Times New Roman)
|
||||
if (aTag == TRUETYPE_TAG('G','D','E','F') &&
|
||||
font->GetFontEntry()->IgnoreGDEF()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// bug 721719 - ignore the GSUB table in buggy fonts (applies to Roboto,
|
||||
// at least on some Android ICS devices; set in gfxFT2FontList.cpp)
|
||||
if (aTag == TRUETYPE_TAG('G','S','U','B') &&
|
||||
font->GetFontEntry()->IgnoreGSUB()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return font->GetFontTable(aTag);
|
||||
}
|
||||
|
||||
/*
|
||||
* HarfBuzz font callback functions; font_data is a ptr to a
|
||||
* FontCallbackData struct
|
||||
*/
|
||||
|
||||
struct FontCallbackData {
|
||||
FontCallbackData(gfxHarfBuzzShaper *aShaper, gfxContext *aContext,
|
||||
bool aKerning)
|
||||
: mShaper(aShaper), mContext(aContext), mKerning(aKerning)
|
||||
{ }
|
||||
|
||||
gfxHarfBuzzShaper *mShaper;
|
||||
gfxContext *mContext;
|
||||
bool mKerning;
|
||||
};
|
||||
|
||||
#define UNICODE_BMP_LIMIT 0x10000
|
||||
|
||||
hb_codepoint_t
|
||||
@ -143,8 +175,8 @@ HBGetGlyph(hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t *glyph,
|
||||
void *user_data)
|
||||
{
|
||||
const gfxHarfBuzzShaper::FontCallbackData *fcd =
|
||||
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
|
||||
const FontCallbackData *fcd =
|
||||
static_cast<const FontCallbackData*>(font_data);
|
||||
*glyph = fcd->mShaper->GetGlyph(unicode, variation_selector);
|
||||
return *glyph != 0;
|
||||
}
|
||||
@ -208,8 +240,8 @@ static hb_position_t
|
||||
HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph, void *user_data)
|
||||
{
|
||||
const gfxHarfBuzzShaper::FontCallbackData *fcd =
|
||||
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
|
||||
const FontCallbackData *fcd =
|
||||
static_cast<const FontCallbackData*>(font_data);
|
||||
return fcd->mShaper->GetGlyphHAdvance(fcd->mContext, glyph);
|
||||
}
|
||||
|
||||
@ -468,7 +500,7 @@ gfxHarfBuzzShaper::GetHKerning(uint16_t aFirstGlyph,
|
||||
}
|
||||
|
||||
if (!mKernTable) {
|
||||
mKernTable = mFont->GetFontEntry()->GetFontTable(TRUETYPE_TAG('k','e','r','n'));
|
||||
mKernTable = mFont->GetFontTable(TRUETYPE_TAG('k','e','r','n'));
|
||||
if (!mKernTable) {
|
||||
mKernTable = hb_blob_get_empty();
|
||||
}
|
||||
@ -612,9 +644,15 @@ HBGetHKerning(hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
|
||||
void *user_data)
|
||||
{
|
||||
const gfxHarfBuzzShaper::FontCallbackData *fcd =
|
||||
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
|
||||
return fcd->mShaper->GetHKerning(first_glyph, second_glyph);
|
||||
const FontCallbackData *fcd =
|
||||
static_cast<const FontCallbackData*>(font_data);
|
||||
|
||||
// return 0 if kerning is explicitly disabled
|
||||
if (fcd->mKerning) {
|
||||
return fcd->mShaper->GetHKerning(first_glyph, second_glyph);
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -821,15 +859,12 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
return false;
|
||||
}
|
||||
|
||||
mCallbackData.mContext = aContext;
|
||||
gfxFontEntry *entry = mFont->GetFontEntry();
|
||||
|
||||
if (!mInitialized) {
|
||||
mInitialized = true;
|
||||
mCallbackData.mShaper = this;
|
||||
if (!mHBFace) {
|
||||
|
||||
mUseFontGlyphWidths = mFont->ProvidesGlyphWidths();
|
||||
|
||||
// set up the harfbuzz face etc the first time we use the font
|
||||
|
||||
if (!sHBFontFuncs) {
|
||||
// static function callback pointers, initialized by the first
|
||||
// harfbuzz shaper used
|
||||
@ -870,9 +905,11 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
mHBFace = hb_face_create_for_tables(HBGetTable, this, nullptr);
|
||||
|
||||
if (!mUseFontGetGlyph) {
|
||||
// get the cmap table and find offset to our subtable
|
||||
mCmapTable = entry->GetFontTable(TRUETYPE_TAG('c','m','a','p'));
|
||||
mCmapTable = mFont->GetFontTable(TRUETYPE_TAG('c','m','a','p'));
|
||||
if (!mCmapTable) {
|
||||
NS_WARNING("failed to load cmap, glyphs will be missing");
|
||||
return false;
|
||||
@ -891,7 +928,8 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
// the hmtx table directly;
|
||||
// read mNumLongMetrics from hhea table without caching its blob,
|
||||
// and preload/cache the hmtx table
|
||||
gfxFontEntry::AutoTable hheaTable(entry, TRUETYPE_TAG('h','h','e','a'));
|
||||
hb_blob_t *hheaTable =
|
||||
mFont->GetFontTable(TRUETYPE_TAG('h','h','e','a'));
|
||||
if (hheaTable) {
|
||||
uint32_t len;
|
||||
const HMetricsHeader* hhea =
|
||||
@ -905,7 +943,7 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
// in that case, we won't be able to use this font
|
||||
// (this method will return FALSE below if mHmtx is null)
|
||||
mHmtxTable =
|
||||
entry->GetFontTable(TRUETYPE_TAG('h','m','t','x'));
|
||||
mFont->GetFontTable(TRUETYPE_TAG('h','m','t','x'));
|
||||
if (hb_blob_get_length(mHmtxTable) <
|
||||
mNumLongMetrics * sizeof(HLongMetric)) {
|
||||
// hmtx table is not large enough for the claimed
|
||||
@ -916,13 +954,8 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
}
|
||||
}
|
||||
}
|
||||
hb_blob_destroy(hheaTable);
|
||||
}
|
||||
|
||||
mHBFont = hb_font_create(mHBFace);
|
||||
hb_font_set_funcs(mHBFont, sHBFontFuncs, &mCallbackData, nullptr);
|
||||
hb_font_set_ppem(mHBFont, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
|
||||
uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point
|
||||
hb_font_set_scale(mHBFont, scale, scale);
|
||||
}
|
||||
|
||||
if ((!mUseFontGetGlyph && mCmapFormat <= 0) ||
|
||||
@ -932,14 +965,24 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
}
|
||||
|
||||
const gfxFontStyle *style = mFont->GetStyle();
|
||||
// kerning is enabled *except* when explicitly disabled (font-kerning: none)
|
||||
FontCallbackData fcd(this, aContext, !mFont->KerningDisabled());
|
||||
hb_font_t *font = hb_font_create(mHBFace);
|
||||
hb_font_set_funcs(font, sHBFontFuncs, &fcd, nullptr);
|
||||
hb_font_set_ppem(font, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
|
||||
uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point
|
||||
hb_font_set_scale(font, scale, scale);
|
||||
|
||||
nsAutoTArray<hb_feature_t,20> features;
|
||||
|
||||
gfxFontEntry *entry = mFont->GetFontEntry();
|
||||
|
||||
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
|
||||
|
||||
if (MergeFontFeatures(style,
|
||||
entry->mFeatureSettings,
|
||||
mFont->GetFontEntry()->mFeatureSettings,
|
||||
aShapedText->DisableLigatures(),
|
||||
entry->FamilyName(),
|
||||
mFont->GetFontEntry()->FamilyName(),
|
||||
mergedFeatures))
|
||||
{
|
||||
// enumerate result and insert into hb_feature array
|
||||
@ -977,7 +1020,7 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
reinterpret_cast<const uint16_t*>(aText),
|
||||
length, 0, length);
|
||||
|
||||
hb_shape(mHBFont, buffer, features.Elements(), features.Length());
|
||||
hb_shape(font, buffer, features.Elements(), features.Length());
|
||||
|
||||
if (isRightToLeft) {
|
||||
hb_buffer_reverse(buffer);
|
||||
@ -988,6 +1031,7 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
|
||||
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to store glyphs into gfxShapedWord");
|
||||
hb_buffer_destroy(buffer);
|
||||
hb_font_destroy(font);
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
@ -18,15 +18,6 @@ public:
|
||||
gfxHarfBuzzShaper(gfxFont *aFont);
|
||||
virtual ~gfxHarfBuzzShaper();
|
||||
|
||||
/*
|
||||
* For HarfBuzz font callback functions, font_data is a ptr to a
|
||||
* FontCallbackData struct
|
||||
*/
|
||||
struct FontCallbackData {
|
||||
gfxHarfBuzzShaper *mShaper;
|
||||
gfxContext *mContext;
|
||||
};
|
||||
|
||||
virtual bool ShapeText(gfxContext *aContext,
|
||||
const PRUnichar *aText,
|
||||
uint32_t aOffset,
|
||||
@ -63,15 +54,9 @@ protected:
|
||||
nsTArray<nsPoint>& aPositions,
|
||||
uint32_t aAppUnitsPerDevUnit);
|
||||
|
||||
// harfbuzz face object: we acquire a reference from the font entry
|
||||
// on shaper creation, and release it in our destructor
|
||||
// harfbuzz face object, created on first use (caches font tables)
|
||||
hb_face_t *mHBFace;
|
||||
|
||||
// size-specific font object, owned by the gfxHarfBuzzShaper
|
||||
hb_font_t *mHBFont;
|
||||
|
||||
FontCallbackData mCallbackData;
|
||||
|
||||
// Following table references etc are declared "mutable" because the
|
||||
// harfbuzz callback functions take a const ptr to the shaper, but
|
||||
// wish to cache tables here to avoid repeatedly looking them up
|
||||
@ -102,8 +87,6 @@ protected:
|
||||
// Whether the font implements GetGlyphWidth, or we should read tables
|
||||
// directly to get ideal widths
|
||||
bool mUseFontGlyphWidths;
|
||||
|
||||
bool mInitialized;
|
||||
};
|
||||
|
||||
#endif /* GFX_HARFBUZZSHAPER_H */
|
||||
|
@ -189,17 +189,13 @@ gfxMacFont::InitMetrics()
|
||||
// return the true value for OpenType/CFF fonts (it normalizes to 1000,
|
||||
// which then leads to metrics errors when we read the 'hmtx' table to
|
||||
// get glyph advances for HarfBuzz, see bug 580863)
|
||||
CFDataRef headData =
|
||||
::CGFontCopyTableForTag(mCGFont, TRUETYPE_TAG('h','e','a','d'));
|
||||
if (headData) {
|
||||
if (size_t(::CFDataGetLength(headData)) >= sizeof(HeadTable)) {
|
||||
const HeadTable *head =
|
||||
reinterpret_cast<const HeadTable*>(::CFDataGetBytePtr(headData));
|
||||
upem = head->unitsPerEm;
|
||||
}
|
||||
::CFRelease(headData);
|
||||
}
|
||||
if (!upem) {
|
||||
const uint32_t kHeadTableTag = TRUETYPE_TAG('h','e','a','d');
|
||||
AutoFallibleTArray<uint8_t,sizeof(HeadTable)> headData;
|
||||
if (NS_SUCCEEDED(mFontEntry->GetFontTable(kHeadTableTag, headData)) &&
|
||||
headData.Length() >= sizeof(HeadTable)) {
|
||||
HeadTable *head = reinterpret_cast<HeadTable*>(headData.Elements());
|
||||
upem = head->unitsPerEm;
|
||||
} else {
|
||||
upem = ::CGFontGetUnitsPerEm(mCGFont);
|
||||
}
|
||||
|
||||
@ -352,6 +348,35 @@ gfxMacFont::GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
gfxMacFont::DestroyBlobFunc(void* aUserData)
|
||||
{
|
||||
::CFRelease((CFDataRef)aUserData);
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxMacFont::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
CFDataRef dataRef = ::CGFontCopyTableForTag(mCGFont, aTag);
|
||||
if (dataRef) {
|
||||
return hb_blob_create((const char*)::CFDataGetBytePtr(dataRef),
|
||||
::CFDataGetLength(dataRef),
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
(void*)dataRef, DestroyBlobFunc);
|
||||
}
|
||||
|
||||
if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
|
||||
// for downloaded fonts, there may be layout tables cached in the entry
|
||||
// even though they're absent from the sanitized platform font
|
||||
hb_blob_t *blob;
|
||||
if (mFontEntry->GetExistingFontTable(aTag, &blob)) {
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to initialize font metrics via platform APIs (CG/CT),
|
||||
// and set mIsValid = TRUE on success.
|
||||
// We ONLY call this for local (platform) fonts that are not sfnt format;
|
||||
|
@ -40,6 +40,10 @@ public:
|
||||
gfxContext *aContextForTightBoundingBox,
|
||||
Spacing *aSpacing);
|
||||
|
||||
// override gfxFont table access function to bypass gfxFontEntry cache,
|
||||
// use CGFontRef API to get direct access to system font data
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag);
|
||||
|
||||
virtual mozilla::TemporaryRef<mozilla::gfx::ScaledFont> GetScaledFont(mozilla::gfx::DrawTarget *aTarget);
|
||||
|
||||
virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
@ -69,6 +73,8 @@ protected:
|
||||
gfxFloat GetCharWidth(CFDataRef aCmap, PRUnichar aUniChar,
|
||||
uint32_t *aGlyphID, gfxFloat aConvFactor);
|
||||
|
||||
static void DestroyBlobFunc(void* aUserData);
|
||||
|
||||
// a weak reference to the CoreGraphics font: this is owned by the
|
||||
// MacOSFontEntry, it is not retained or released by gfxMacFont
|
||||
CGFontRef mCGFont;
|
||||
|
@ -40,9 +40,8 @@ public:
|
||||
|
||||
virtual CGFontRef GetFontRef();
|
||||
|
||||
// override gfxFontEntry table access function to bypass table cache,
|
||||
// use CGFontRef API to get direct access to system font data
|
||||
virtual hb_blob_t *GetFontTable(uint32_t aTag) MOZ_OVERRIDE;
|
||||
virtual nsresult GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer);
|
||||
|
||||
virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
|
||||
FontListSizes* aSizes) const;
|
||||
@ -58,8 +57,6 @@ protected:
|
||||
|
||||
virtual bool HasFontTable(uint32_t aTableTag);
|
||||
|
||||
static void DestroyBlobFunc(void* aUserData);
|
||||
|
||||
CGFontRef mFontRef; // owning reference to the CGFont, released on destruction
|
||||
|
||||
bool mFontRefInitialized;
|
||||
|
@ -201,21 +201,41 @@ static const ScriptRange sComplexScripts[] = {
|
||||
// Thai seems to be "renderable" without AAT morphing tables
|
||||
};
|
||||
|
||||
static void
|
||||
DestroyBlobFunc(void* aUserData)
|
||||
{
|
||||
FallibleTArray<uint8_t>* data = static_cast<FallibleTArray<uint8_t>*>(aUserData);
|
||||
delete data;
|
||||
}
|
||||
|
||||
// This is only used via MacOSFontEntry::ReadCMAP when checking for layout
|
||||
// support; it does not respect the mIgnore* flags on font entries, as those
|
||||
// are not relevant here at present.
|
||||
static hb_blob_t *
|
||||
GetTableForHarfBuzz(hb_face_t *aFace, hb_tag_t aTag, void *aUserData)
|
||||
{
|
||||
gfxFontEntry *fe = static_cast<gfxFontEntry*>(aUserData);
|
||||
FallibleTArray<uint8_t>* table = new FallibleTArray<uint8_t>;
|
||||
nsresult rv = fe->GetFontTable(aTag, *table);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return hb_blob_create((const char*)table->Elements(), table->Length(),
|
||||
HB_MEMORY_MODE_READONLY, table, DestroyBlobFunc);
|
||||
}
|
||||
delete table;
|
||||
return hb_blob_get_empty();
|
||||
}
|
||||
|
||||
static bool
|
||||
SupportsScriptInGSUB(gfxFontEntry* aFontEntry, const hb_tag_t* aScriptTags)
|
||||
{
|
||||
hb_face_t *face = aFontEntry->GetHBFace();
|
||||
if (!face) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hb_face_t *face = hb_face_create_for_tables(GetTableForHarfBuzz,
|
||||
aFontEntry, nullptr);
|
||||
unsigned int index;
|
||||
hb_tag_t chosenScript;
|
||||
bool found =
|
||||
hb_ot_layout_table_choose_script(face, TRUETYPE_TAG('G','S','U','B'),
|
||||
aScriptTags, &index, &chosenScript);
|
||||
hb_face_destroy(face);
|
||||
|
||||
return found && chosenScript != TRUETYPE_TAG('D','F','L','T');
|
||||
}
|
||||
|
||||
@ -230,19 +250,18 @@ MacOSFontEntry::ReadCMAP()
|
||||
nsRefPtr<gfxCharacterMap> charmap = new gfxCharacterMap();
|
||||
|
||||
uint32_t kCMAP = TRUETYPE_TAG('c','m','a','p');
|
||||
nsresult rv;
|
||||
|
||||
AutoTable cmapTable(this, kCMAP);
|
||||
if (!cmapTable) {
|
||||
return NS_OK; // leave it empty
|
||||
}
|
||||
AutoFallibleTArray<uint8_t,16384> cmap;
|
||||
rv = GetFontTable(kCMAP, cmap);
|
||||
|
||||
bool unicodeFont = false, symbolFont = false; // currently ignored
|
||||
|
||||
uint32_t cmapLen;
|
||||
const char* cmapData = hb_blob_get_data(cmapTable, &cmapLen);
|
||||
nsresult rv = gfxFontUtils::ReadCMAP((const uint8_t*)cmapData, cmapLen,
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
*charmap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !HasGraphiteTables()) {
|
||||
// We assume a Graphite font knows what it's doing,
|
||||
@ -376,29 +395,33 @@ MacOSFontEntry::GetFontRef()
|
||||
return mFontRef;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
MacOSFontEntry::DestroyBlobFunc(void* aUserData)
|
||||
nsresult
|
||||
MacOSFontEntry::GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
::CFRelease((CFDataRef)aUserData);
|
||||
}
|
||||
nsAutoreleasePool localPool;
|
||||
|
||||
hb_blob_t *
|
||||
MacOSFontEntry::GetFontTable(uint32_t aTag)
|
||||
{
|
||||
CGFontRef fontRef = GetFontRef();
|
||||
if (!fontRef) {
|
||||
return nullptr;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
CFDataRef dataRef = ::CGFontCopyTableForTag(fontRef, aTag);
|
||||
if (dataRef) {
|
||||
return hb_blob_create((const char*)::CFDataGetBytePtr(dataRef),
|
||||
::CFDataGetLength(dataRef),
|
||||
HB_MEMORY_MODE_READONLY,
|
||||
(void*)dataRef, DestroyBlobFunc);
|
||||
CFDataRef tableData = ::CGFontCopyTableForTag(fontRef, aTableTag);
|
||||
if (!tableData) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
nsresult rval = NS_OK;
|
||||
CFIndex dataLength = ::CFDataGetLength(tableData);
|
||||
if (aBuffer.AppendElements(dataLength)) {
|
||||
::CFDataGetBytes(tableData, ::CFRangeMake(0, dataLength),
|
||||
aBuffer.Elements());
|
||||
} else {
|
||||
rval = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
::CFRelease(tableData);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -617,26 +640,22 @@ gfxSingleFaceMacFontFamily::LocalizedName(nsAString& aLocalizedName)
|
||||
void
|
||||
gfxSingleFaceMacFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformFontList)
|
||||
{
|
||||
if (mOtherFamilyNamesInitialized) {
|
||||
if (mOtherFamilyNamesInitialized)
|
||||
return;
|
||||
}
|
||||
|
||||
gfxFontEntry *fe = mAvailableFonts[0];
|
||||
if (!fe) {
|
||||
if (!fe)
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t kNAME = TRUETYPE_TAG('n','a','m','e');
|
||||
AutoFallibleTArray<uint8_t,8192> buffer;
|
||||
|
||||
gfxFontEntry::AutoTable nameTable(fe, kNAME);
|
||||
if (!nameTable) {
|
||||
if (fe->GetFontTable(kNAME, buffer) != NS_OK)
|
||||
return;
|
||||
}
|
||||
|
||||
mHasOtherFamilyNames = ReadOtherFamilyNamesForFace(aPlatformFontList,
|
||||
nameTable,
|
||||
buffer,
|
||||
true);
|
||||
|
||||
mOtherFamilyNamesInitialized = true;
|
||||
}
|
||||
|
||||
|
@ -315,8 +315,7 @@ public:
|
||||
gfxSystemFcFontEntry(cairo_font_face_t *aFontFace,
|
||||
FcPattern *aFontPattern,
|
||||
const nsAString& aName)
|
||||
: gfxFcFontEntry(aName), mFontFace(aFontFace),
|
||||
mFTFace(nullptr), mFTFaceInitialized(false)
|
||||
: gfxFcFontEntry(aName), mFontFace(aFontFace)
|
||||
{
|
||||
cairo_font_face_reference(mFontFace);
|
||||
cairo_font_face_set_user_data(mFontFace, &sFontEntryKey, this, NULL);
|
||||
@ -337,89 +336,10 @@ public:
|
||||
cairo_font_face_set_user_data(mFontFace, &sFontEntryKey, NULL, NULL);
|
||||
cairo_font_face_destroy(mFontFace);
|
||||
}
|
||||
|
||||
virtual void ForgetHBFace();
|
||||
virtual void ReleaseGrFace(gr_face* aFace);
|
||||
|
||||
protected:
|
||||
virtual nsresult
|
||||
CopyFontTable(uint32_t aTableTag, FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
|
||||
|
||||
void MaybeReleaseFTFace();
|
||||
|
||||
private:
|
||||
cairo_font_face_t *mFontFace;
|
||||
FT_Face mFTFace;
|
||||
bool mFTFaceInitialized;
|
||||
};
|
||||
|
||||
nsresult
|
||||
gfxSystemFcFontEntry::CopyFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
if (!mFTFaceInitialized) {
|
||||
mFTFaceInitialized = true;
|
||||
FcChar8 *filename;
|
||||
if (FcPatternGetString(mPatterns[0], FC_FILE, 0, &filename) != FcResultMatch) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
int index;
|
||||
if (FcPatternGetInteger(mPatterns[0], FC_INDEX, 0, &index) != FcResultMatch) {
|
||||
index = 0; // default to 0 if not found in pattern
|
||||
}
|
||||
if (FT_New_Face(gfxPangoFontGroup::GetFTLibrary(),
|
||||
(const char*)filename, index, &mFTFace) != 0) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mFTFace) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
FT_ULong length = 0;
|
||||
if (FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nullptr, &length) != 0) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
if (!aBuffer.SetLength(length)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, aBuffer.Elements(), &length) != 0) {
|
||||
aBuffer.Clear();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
gfxSystemFcFontEntry::MaybeReleaseFTFace()
|
||||
{
|
||||
// don't release if either HB or Gr face still exists
|
||||
if (mHBFace || mGrFace) {
|
||||
return;
|
||||
}
|
||||
if (mFTFace) {
|
||||
FT_Done_Face(mFTFace);
|
||||
mFTFace = nullptr;
|
||||
}
|
||||
mFTFaceInitialized = false;
|
||||
}
|
||||
|
||||
void
|
||||
gfxSystemFcFontEntry::ForgetHBFace()
|
||||
{
|
||||
gfxFontEntry::ForgetHBFace();
|
||||
MaybeReleaseFTFace();
|
||||
}
|
||||
|
||||
void
|
||||
gfxSystemFcFontEntry::ReleaseGrFace(gr_face* aFace)
|
||||
{
|
||||
gfxFontEntry::ReleaseGrFace(aFace);
|
||||
MaybeReleaseFTFace();
|
||||
}
|
||||
|
||||
// A namespace for @font-face family names in FcPatterns so that fontconfig
|
||||
// aliases do not pick up families from @font-face rules and so that
|
||||
// fontconfig rules can distinguish between web fonts and platform fonts.
|
||||
@ -594,7 +514,8 @@ public:
|
||||
// lifetime of the FontEntry.
|
||||
PangoCoverage *GetPangoCoverage();
|
||||
|
||||
virtual hb_blob_t* GetFontTable(uint32_t aTableTag) MOZ_OVERRIDE;
|
||||
virtual nsresult
|
||||
GetFontTable(uint32_t aTableTag, FallibleTArray<uint8_t>& aBuffer) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
void InitPattern();
|
||||
@ -811,33 +732,27 @@ gfxDownloadedFcFontEntry::GetPangoCoverage()
|
||||
return mPangoCoverage;
|
||||
}
|
||||
|
||||
static int
|
||||
DirEntryCmp(const void* aKey, const void* aItem)
|
||||
nsresult
|
||||
gfxDownloadedFcFontEntry::GetFontTable(uint32_t aTableTag,
|
||||
FallibleTArray<uint8_t>& aBuffer)
|
||||
{
|
||||
int32_t tag = *static_cast<const int32_t*>(aKey);
|
||||
const TableDirEntry* entry = static_cast<const TableDirEntry*>(aItem);
|
||||
return tag - int32_t(entry->tag);
|
||||
}
|
||||
|
||||
hb_blob_t *
|
||||
gfxDownloadedFcFontEntry::GetFontTable(uint32_t aTableTag)
|
||||
{
|
||||
// The entry already owns the (sanitized) sfnt data in mFontData,
|
||||
// so we can just return a blob that "wraps" the appropriate chunk of it.
|
||||
// The blob should not attempt to free its data, as the entire sfnt data
|
||||
// will be freed when the font entry is deleted.
|
||||
const SFNTHeader* header = reinterpret_cast<const SFNTHeader*>(mFontData);
|
||||
const TableDirEntry* dir = reinterpret_cast<const TableDirEntry*>(header + 1);
|
||||
dir = static_cast<const TableDirEntry*>
|
||||
(bsearch(&aTableTag, dir, header->numTables, sizeof(TableDirEntry),
|
||||
DirEntryCmp));
|
||||
if (dir) {
|
||||
return hb_blob_create(reinterpret_cast<const char*>(mFontData) +
|
||||
dir->offset, dir->length,
|
||||
HB_MEMORY_MODE_READONLY, nullptr, nullptr);
|
||||
|
||||
FT_ULong length = 0;
|
||||
FT_Error error = FT_Load_Sfnt_Table(mFace, aTableTag, 0, nullptr, &length);
|
||||
if (error) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
if (!aBuffer.SetLength(length)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
error = FT_Load_Sfnt_Table(mFace, aTableTag, 0, aBuffer.Elements(), &length);
|
||||
if (error) {
|
||||
aBuffer.Clear();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -95,7 +95,6 @@ private:
|
||||
return mSizeAdjustFactor;
|
||||
}
|
||||
|
||||
friend class gfxSystemFcFontEntry;
|
||||
static FT_Library GetFTLibrary();
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,6 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "Element.h"
|
||||
#include "nsSVGUtils.h"
|
||||
#include "harfbuzz/hb.h"
|
||||
|
||||
#define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml")
|
||||
#define UTF8_CHARSET NS_LITERAL_CSTRING("utf-8")
|
||||
@ -73,23 +72,32 @@ const float gfxSVGGlyphs::SVG_UNITS_PER_EM = 1000.0f;
|
||||
|
||||
const gfxRGBA SimpleTextObjectPaint::sZero = gfxRGBA(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
gfxSVGGlyphs::gfxSVGGlyphs(hb_blob_t *aSVGTable, hb_blob_t *aCmapTable)
|
||||
gfxSVGGlyphs::gfxSVGGlyphs(FallibleTArray<uint8_t>& aSVGTable,
|
||||
const FallibleTArray<uint8_t>& aCmapTable)
|
||||
{
|
||||
mSVGData = aSVGTable;
|
||||
mSVGData.SwapElements(aSVGTable);
|
||||
|
||||
const char* svgData = hb_blob_get_data(mSVGData, nullptr);
|
||||
mHeader = reinterpret_cast<const Header*>(svgData);
|
||||
mIndex = reinterpret_cast<const IndexEntry*>(svgData + sizeof(Header));
|
||||
mHeader = reinterpret_cast<Header*>(mSVGData.Elements());
|
||||
UnmangleHeaders();
|
||||
|
||||
mGlyphDocs.Init();
|
||||
mGlyphIdMap.Init();
|
||||
mCmapData = aCmapTable;
|
||||
}
|
||||
|
||||
gfxSVGGlyphs::~gfxSVGGlyphs()
|
||||
void
|
||||
gfxSVGGlyphs::UnmangleHeaders()
|
||||
{
|
||||
hb_blob_destroy(mSVGData);
|
||||
hb_blob_destroy(mCmapData);
|
||||
mHeader->mIndexLength = mozilla::NativeEndian::swapFromBigEndian(mHeader->mIndexLength);
|
||||
|
||||
mIndex = reinterpret_cast<IndexEntry*>(mSVGData.Elements() + sizeof(Header));
|
||||
|
||||
for (uint16_t i = 0; i < mHeader->mIndexLength; i++) {
|
||||
mIndex[i].mStartGlyph = mozilla::NativeEndian::swapFromBigEndian(mIndex[i].mStartGlyph);
|
||||
mIndex[i].mEndGlyph = mozilla::NativeEndian::swapFromBigEndian(mIndex[i].mEndGlyph);
|
||||
mIndex[i].mDocOffset = mozilla::NativeEndian::swapFromBigEndian(mIndex[i].mDocOffset);
|
||||
mIndex[i].mDocLength = mozilla::NativeEndian::swapFromBigEndian(mIndex[i].mDocLength);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -109,8 +117,8 @@ gfxSVGGlyphs::CompareIndexEntries(const void *_key, const void *_entry)
|
||||
const uint32_t key = *(uint32_t*)_key;
|
||||
const IndexEntry *entry = (const IndexEntry*)_entry;
|
||||
|
||||
if (key < uint16_t(entry->mStartGlyph)) return -1;
|
||||
if (key >= uint16_t(entry->mEndGlyph)) return 1;
|
||||
if (key < entry->mStartGlyph) return -1;
|
||||
if (key >= entry->mEndGlyph) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -118,7 +126,7 @@ gfxSVGGlyphsDocument *
|
||||
gfxSVGGlyphs::FindOrCreateGlyphsDocument(uint32_t aGlyphId)
|
||||
{
|
||||
IndexEntry *entry = (IndexEntry*)bsearch(&aGlyphId, mIndex,
|
||||
uint16_t(mHeader->mIndexLength),
|
||||
mHeader->mIndexLength,
|
||||
sizeof(IndexEntry),
|
||||
CompareIndexEntries);
|
||||
if (!entry) {
|
||||
@ -128,8 +136,7 @@ gfxSVGGlyphs::FindOrCreateGlyphsDocument(uint32_t aGlyphId)
|
||||
gfxSVGGlyphsDocument *result = mGlyphDocs.Get(entry->mDocOffset);
|
||||
|
||||
if (!result) {
|
||||
const uint8_t *data = (const uint8_t*)hb_blob_get_data(mSVGData, nullptr);
|
||||
result = new gfxSVGGlyphsDocument(data + entry->mDocOffset,
|
||||
result = new gfxSVGGlyphsDocument(mSVGData.Elements() + entry->mDocOffset,
|
||||
entry->mDocLength, mCmapData);
|
||||
mGlyphDocs.Put(entry->mDocOffset, result);
|
||||
}
|
||||
@ -186,7 +193,8 @@ gfxSVGGlyphsDocument::SetupPresentation()
|
||||
* @param aCmapTable Buffer containing the raw cmap table data
|
||||
*/
|
||||
void
|
||||
gfxSVGGlyphsDocument::FindGlyphElements(Element *aElem, hb_blob_t *aCmapTable)
|
||||
gfxSVGGlyphsDocument::FindGlyphElements(Element *aElem,
|
||||
const FallibleTArray<uint8_t> &aCmapTable)
|
||||
{
|
||||
for (nsIContent *child = aElem->GetLastChild(); child;
|
||||
child = child->GetPreviousSibling()) {
|
||||
@ -262,8 +270,8 @@ gfxSVGGlyphsDocument::GetGlyphElement(uint32_t aGlyphId)
|
||||
return mGlyphIdMap.Get(aGlyphId);
|
||||
}
|
||||
|
||||
gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBufLen,
|
||||
hb_blob_t *aCmapTable)
|
||||
gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(uint8_t *aBuffer, uint32_t aBufLen,
|
||||
const FallibleTArray<uint8_t>& aCmapTable)
|
||||
{
|
||||
mGlyphIdMap.Init();
|
||||
ParseDocument(aBuffer, aBufLen);
|
||||
@ -288,7 +296,7 @@ gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBuf
|
||||
}
|
||||
|
||||
static nsresult
|
||||
CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen,
|
||||
CreateBufferedStream(uint8_t *aBuffer, uint32_t aBufLen,
|
||||
nsCOMPtr<nsIInputStream> &aResult)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
@ -310,7 +318,7 @@ CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen,
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen)
|
||||
gfxSVGGlyphsDocument::ParseDocument(uint8_t *aBuffer, uint32_t aBufLen)
|
||||
{
|
||||
// Mostly pulled from nsDOMParser::ParseFromStream
|
||||
|
||||
@ -404,7 +412,8 @@ gfxSVGGlyphsDocument::InsertGlyphId(Element *aGlyphElement)
|
||||
}
|
||||
|
||||
void
|
||||
gfxSVGGlyphsDocument::InsertGlyphChar(Element *aGlyphElement, hb_blob_t *aCmapTable)
|
||||
gfxSVGGlyphsDocument::InsertGlyphChar(Element *aGlyphElement,
|
||||
const FallibleTArray<uint8_t> &aCmapTable)
|
||||
{
|
||||
nsAutoString glyphChar;
|
||||
if (!aGlyphElement->GetAttr(kNameSpaceID_None, nsGkAtoms::glyphchar, glyphChar)) {
|
||||
@ -413,8 +422,6 @@ gfxSVGGlyphsDocument::InsertGlyphChar(Element *aGlyphElement, hb_blob_t *aCmapTa
|
||||
|
||||
uint32_t varSelector;
|
||||
|
||||
// XXX jfkthame
|
||||
// This will not handle surrogate pairs properly!
|
||||
switch (glyphChar.Length()) {
|
||||
case 0:
|
||||
NS_WARNING("glyphchar is empty");
|
||||
@ -432,9 +439,8 @@ gfxSVGGlyphsDocument::InsertGlyphChar(Element *aGlyphElement, hb_blob_t *aCmapTa
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t len;
|
||||
const uint8_t *data = (const uint8_t*)hb_blob_get_data(aCmapTable, &len);
|
||||
uint32_t glyphId = gfxFontUtils::MapCharToGlyph(data, len,
|
||||
uint32_t glyphId = gfxFontUtils::MapCharToGlyph(aCmapTable.Elements(),
|
||||
aCmapTable.Length(),
|
||||
glyphChar.CharAt(0),
|
||||
varSelector);
|
||||
|
||||
|
@ -65,8 +65,8 @@ class gfxSVGGlyphsDocument
|
||||
typedef gfxFont::DrawMode DrawMode;
|
||||
|
||||
public:
|
||||
gfxSVGGlyphsDocument(const uint8_t *aBuffer, uint32_t aBufLen,
|
||||
hb_blob_t *aCmapTable);
|
||||
gfxSVGGlyphsDocument(uint8_t *aBuffer, uint32_t aBufLen,
|
||||
const FallibleTArray<uint8_t>& aCmapTable);
|
||||
|
||||
Element *GetGlyphElement(uint32_t aGlyphId);
|
||||
|
||||
@ -77,14 +77,16 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
nsresult ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen);
|
||||
nsresult ParseDocument(uint8_t *aBuffer, uint32_t aBufLen);
|
||||
|
||||
nsresult SetupPresentation();
|
||||
|
||||
void FindGlyphElements(Element *aElement, hb_blob_t *aCmapTable);
|
||||
void FindGlyphElements(Element *aElement,
|
||||
const FallibleTArray<uint8_t> &aCmapTable);
|
||||
|
||||
void InsertGlyphId(Element *aGlyphElement);
|
||||
void InsertGlyphChar(Element *aGlyphElement, hb_blob_t *aCmapTable);
|
||||
void InsertGlyphChar(Element *aGlyphElement,
|
||||
const FallibleTArray<uint8_t> &aCmapTable);
|
||||
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<nsIContentViewer> mViewer;
|
||||
@ -111,17 +113,14 @@ public:
|
||||
/**
|
||||
* @param aSVGTable The SVG table from the OpenType font
|
||||
* @param aCmapTable The CMAP table from the OpenType font
|
||||
*
|
||||
* The gfxSVGGlyphs object takes over ownership of the blob references
|
||||
* that are passed in, and will hb_blob_destroy() them when finished;
|
||||
* the caller should -not- destroy these references.
|
||||
*/
|
||||
gfxSVGGlyphs(hb_blob_t *aSVGTable, hb_blob_t *aCmapTable);
|
||||
gfxSVGGlyphs(FallibleTArray<uint8_t>& aSVGTable,
|
||||
const FallibleTArray<uint8_t>& aCmapTable);
|
||||
|
||||
/**
|
||||
* Releases our references to the SVG and cmap tables.
|
||||
* Big- to little-endian conversion for headers
|
||||
*/
|
||||
~gfxSVGGlyphs();
|
||||
void UnmangleHeaders();
|
||||
|
||||
/**
|
||||
* Find the |gfxSVGGlyphsDocument| containing an SVG glyph for |aGlyphId|.
|
||||
@ -158,19 +157,19 @@ private:
|
||||
nsClassHashtable<nsUint32HashKey, gfxSVGGlyphsDocument> mGlyphDocs;
|
||||
nsBaseHashtable<nsUint32HashKey, Element*, Element*> mGlyphIdMap;
|
||||
|
||||
hb_blob_t *mSVGData;
|
||||
hb_blob_t *mCmapData;
|
||||
FallibleTArray<uint8_t> mSVGData;
|
||||
FallibleTArray<uint8_t> mCmapData;
|
||||
|
||||
const struct Header {
|
||||
mozilla::AutoSwap_PRUint16 mVersion;
|
||||
mozilla::AutoSwap_PRUint16 mIndexLength;
|
||||
struct Header {
|
||||
uint16_t mVersion;
|
||||
uint16_t mIndexLength;
|
||||
} *mHeader;
|
||||
|
||||
const struct IndexEntry {
|
||||
mozilla::AutoSwap_PRUint16 mStartGlyph;
|
||||
mozilla::AutoSwap_PRUint16 mEndGlyph;
|
||||
mozilla::AutoSwap_PRUint32 mDocOffset;
|
||||
mozilla::AutoSwap_PRUint32 mDocLength;
|
||||
struct IndexEntry {
|
||||
uint16_t mStartGlyph;
|
||||
uint16_t mEndGlyph;
|
||||
uint32_t mDocOffset;
|
||||
uint32_t mDocLength;
|
||||
} *mIndex;
|
||||
|
||||
static int CompareIndexEntries(const void *_a, const void *_b);
|
||||
|
@ -533,7 +533,6 @@ hb_buffer_set_script
|
||||
hb_buffer_set_unicode_funcs
|
||||
hb_face_create_for_tables
|
||||
hb_face_destroy
|
||||
hb_face_reference
|
||||
hb_font_create
|
||||
hb_font_destroy
|
||||
hb_font_funcs_create
|
||||
|
Loading…
x
Reference in New Issue
Block a user