Bug 1120101 - Calculate vertical glyph origin based on 'vmtx' table in TrueType fonts. r=jdaggett

This commit is contained in:
Jonathan Kew 2015-01-15 11:07:26 +00:00
parent 22e73356e6
commit eb9c988460
2 changed files with 101 additions and 1 deletions

View File

@ -41,6 +41,8 @@ gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
mHmtxTable(nullptr), mHmtxTable(nullptr),
mVmtxTable(nullptr), mVmtxTable(nullptr),
mVORGTable(nullptr), mVORGTable(nullptr),
mLocaTable(nullptr),
mGlyfTable(nullptr),
mCmapTable(nullptr), mCmapTable(nullptr),
mCmapFormat(-1), mCmapFormat(-1),
mSubtableOffset(0), mSubtableOffset(0),
@ -50,7 +52,8 @@ gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
mUseFontGetGlyph(aFont->ProvidesGetGlyph()), mUseFontGetGlyph(aFont->ProvidesGetGlyph()),
mUseFontGlyphWidths(false), mUseFontGlyphWidths(false),
mInitialized(false), mInitialized(false),
mVerticalInitialized(false) mVerticalInitialized(false),
mLocaLongOffsets(false)
{ {
} }
@ -65,6 +68,18 @@ gfxHarfBuzzShaper::~gfxHarfBuzzShaper()
if (mKernTable) { if (mKernTable) {
hb_blob_destroy(mKernTable); hb_blob_destroy(mKernTable);
} }
if (mVmtxTable) {
hb_blob_destroy(mVmtxTable);
}
if (mVORGTable) {
hb_blob_destroy(mVORGTable);
}
if (mLocaTable) {
hb_blob_destroy(mLocaTable);
}
if (mGlyfTable) {
hb_blob_destroy(mGlyfTable);
}
if (mHBFont) { if (mHBFont) {
hb_font_destroy(mHBFont); hb_font_destroy(mHBFont);
} }
@ -330,6 +345,72 @@ gfxHarfBuzzShaper::GetGlyphVOrigin(hb_codepoint_t aGlyph,
return; return;
} }
if (mVmtxTable) {
if (mLocaTable && mGlyfTable) {
// TrueType outlines: use glyph bbox + top sidebearing
uint32_t offset; // offset of glyph record in the 'glyf' table
uint32_t len;
const char* data = hb_blob_get_data(mLocaTable, &len);
if (mLocaLongOffsets) {
if ((aGlyph + 1) * sizeof(AutoSwap_PRUint32) > len) {
*aY = 0;
return;
}
const AutoSwap_PRUint32* offsets =
reinterpret_cast<const AutoSwap_PRUint32*>(data);
offset = offsets[aGlyph];
if (offset == offsets[aGlyph + 1]) {
// empty glyph
*aY = 0;
return;
}
} else {
if ((aGlyph + 1) * sizeof(AutoSwap_PRUint16) > len) {
*aY = 0;
return;
}
const AutoSwap_PRUint16* offsets =
reinterpret_cast<const AutoSwap_PRUint16*>(data);
offset = uint16_t(offsets[aGlyph]);
if (offset == uint16_t(offsets[aGlyph + 1])) {
// empty glyph
*aY = 0;
return;
}
offset *= 2;
}
struct Glyf { // we only need the bounding-box at the beginning
// of the glyph record, not the actual outline data
AutoSwap_PRInt16 numberOfContours;
AutoSwap_PRInt16 xMin;
AutoSwap_PRInt16 yMin;
AutoSwap_PRInt16 xMax;
AutoSwap_PRInt16 yMax;
};
data = hb_blob_get_data(mGlyfTable, &len);
if (offset + sizeof(Glyf) > len) {
*aY = 0;
return;
}
const Glyf* glyf = reinterpret_cast<const Glyf*>(data + offset);
if (aGlyph >= uint32_t(mNumLongVMetrics)) {
aGlyph = mNumLongVMetrics - 1;
}
const GlyphMetrics* metrics =
reinterpret_cast<const GlyphMetrics*>
(hb_blob_get_data(mVmtxTable, nullptr));
*aY = -FloatToFixed(mFont->FUnitsToDevUnitsFactor() *
(int16_t(metrics->metrics[aGlyph].lsb) +
int16_t(glyf->yMax)));
return;
} else {
// XXX TODO: CFF outlines - need to get glyph extents.
// For now, fall through to default code below.
}
}
// XXX should we consider using OS/2 sTypo* metrics if available? // XXX should we consider using OS/2 sTypo* metrics if available?
gfxFontEntry::AutoTable hheaTable(GetFont()->GetFontEntry(), gfxFontEntry::AutoTable hheaTable(GetFont()->GetFontEntry(),
@ -1144,6 +1225,20 @@ gfxHarfBuzzShaper::InitializeVertical()
mVORGTable = nullptr; mVORGTable = nullptr;
} }
} }
} else if (mVmtxTable) {
// Otherwise, try to load loca and glyf tables so that we can read
// bounding boxes (needed to support vertical glyph origin).
uint32_t len;
gfxFontEntry::AutoTable headTable(entry,
TRUETYPE_TAG('h','e','a','d'));
const HeadTable* head =
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable,
&len));
if (len >= sizeof(HeadTable)) {
mLocaLongOffsets = int16_t(head->indexToLocFormat) > 0;
mLocaTable = entry->GetFontTable(TRUETYPE_TAG('l','o','c','a'));
mGlyfTable = entry->GetFontTable(TRUETYPE_TAG('g','l','y','f'));
}
} }
return true; return true;

View File

@ -130,6 +130,10 @@ protected:
// For vertical fonts, cached vmtx and VORG table, if present. // For vertical fonts, cached vmtx and VORG table, if present.
mutable hb_blob_t *mVmtxTable; mutable hb_blob_t *mVmtxTable;
mutable hb_blob_t *mVORGTable; mutable hb_blob_t *mVORGTable;
// And for vertical TrueType (not CFF) fonts that have vmtx,
// we also use loca and glyf to get glyph bounding boxes.
mutable hb_blob_t *mLocaTable;
mutable hb_blob_t *mGlyfTable;
// Cached pointer to cmap subtable to be used for char-to-glyph mapping. // Cached pointer to cmap subtable to be used for char-to-glyph mapping.
// This comes from GetFontTablePtr; if it is non-null, our destructor // This comes from GetFontTablePtr; if it is non-null, our destructor
@ -157,6 +161,7 @@ protected:
bool mInitialized; bool mInitialized;
bool mVerticalInitialized; bool mVerticalInitialized;
bool mLocaLongOffsets;
}; };
#endif /* GFX_HARFBUZZSHAPER_H */ #endif /* GFX_HARFBUZZSHAPER_H */