Backout changeset 0a6d36fc3749 for conflicting with the backout of bug 549861.

This commit is contained in:
Ms2ger 2013-05-19 20:22:17 +02:00
parent 713151feb2
commit 63c2282db0
29 changed files with 727 additions and 830 deletions

View File

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

View File

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

View File

@ -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()
{

View File

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

View File

@ -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)
{

View File

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

View File

@ -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) {

View File

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

View File

@ -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)
{

View File

@ -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()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
}
/*

View File

@ -95,7 +95,6 @@ private:
return mSizeAdjustFactor;
}
friend class gfxSystemFcFontEntry;
static FT_Library GetFTLibrary();
};

View File

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

View File

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

View File

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