mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1120101 - Calculate vertical glyph origin based on 'vmtx' table in TrueType fonts. r=jdaggett
This commit is contained in:
parent
22e73356e6
commit
eb9c988460
@ -41,6 +41,8 @@ gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
|
||||
mHmtxTable(nullptr),
|
||||
mVmtxTable(nullptr),
|
||||
mVORGTable(nullptr),
|
||||
mLocaTable(nullptr),
|
||||
mGlyfTable(nullptr),
|
||||
mCmapTable(nullptr),
|
||||
mCmapFormat(-1),
|
||||
mSubtableOffset(0),
|
||||
@ -50,7 +52,8 @@ gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
|
||||
mUseFontGetGlyph(aFont->ProvidesGetGlyph()),
|
||||
mUseFontGlyphWidths(false),
|
||||
mInitialized(false),
|
||||
mVerticalInitialized(false)
|
||||
mVerticalInitialized(false),
|
||||
mLocaLongOffsets(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -65,6 +68,18 @@ gfxHarfBuzzShaper::~gfxHarfBuzzShaper()
|
||||
if (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) {
|
||||
hb_font_destroy(mHBFont);
|
||||
}
|
||||
@ -330,6 +345,72 @@ gfxHarfBuzzShaper::GetGlyphVOrigin(hb_codepoint_t aGlyph,
|
||||
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?
|
||||
|
||||
gfxFontEntry::AutoTable hheaTable(GetFont()->GetFontEntry(),
|
||||
@ -1144,6 +1225,20 @@ gfxHarfBuzzShaper::InitializeVertical()
|
||||
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;
|
||||
|
@ -130,6 +130,10 @@ protected:
|
||||
// For vertical fonts, cached vmtx and VORG table, if present.
|
||||
mutable hb_blob_t *mVmtxTable;
|
||||
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.
|
||||
// This comes from GetFontTablePtr; if it is non-null, our destructor
|
||||
@ -157,6 +161,7 @@ protected:
|
||||
|
||||
bool mInitialized;
|
||||
bool mVerticalInitialized;
|
||||
bool mLocaLongOffsets;
|
||||
};
|
||||
|
||||
#endif /* GFX_HARFBUZZSHAPER_H */
|
||||
|
Loading…
Reference in New Issue
Block a user