Correct advances for 'monospace' fonts in PDF.

FT_IS_FIXED_WIDTH, kCTFontMonoSpaceTrait, and TMPF_FIXED_PITCH
are style bits, they do not imply that all advances are the same.

BUG=skia:5537
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2162023002

Review-Url: https://codereview.chromium.org/2162023002
This commit is contained in:
bungeman 2016-07-22 11:19:24 -07:00 committed by Commit bot
parent 9a5c47f4ef
commit f149169352
3 changed files with 80 additions and 127 deletions

View File

@ -482,21 +482,17 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
info->fLastGlyphID = face->num_glyphs - 1;
info->fEmSize = 1000;
bool cid = false;
const char* fontType = FT_Get_X11_Font_Format(face);
if (strcmp(fontType, "Type 1") == 0) {
info->fType = SkAdvancedTypefaceMetrics::kType1_Font;
} else if (strcmp(fontType, "CID Type 1") == 0) {
info->fType = SkAdvancedTypefaceMetrics::kType1CID_Font;
cid = true;
} else if (strcmp(fontType, "CFF") == 0) {
info->fType = SkAdvancedTypefaceMetrics::kCFF_Font;
} else if (strcmp(fontType, "TrueType") == 0) {
info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
cid = true;
TT_Header* ttHeader;
if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face,
ft_sfnt_head)) != nullptr) {
if ((ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head)) != nullptr) {
info->fEmSize = ttHeader->Units_Per_EM;
}
} else {
@ -504,19 +500,19 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
}
info->fStyle = 0;
if (FT_IS_FIXED_WIDTH(face))
if (FT_IS_FIXED_WIDTH(face)) {
info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
if (face->style_flags & FT_STYLE_FLAG_ITALIC)
}
if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
}
PS_FontInfoRec ps_info;
TT_Postscript* tt_info;
if (FT_Get_PS_Font_Info(face, &ps_info) == 0) {
info->fItalicAngle = ps_info.italic_angle;
} else if ((tt_info =
(TT_Postscript*)FT_Get_Sfnt_Table(face,
ft_sfnt_post)) != nullptr) {
info->fItalicAngle = SkFixedToScalar(tt_info->italicAngle);
PS_FontInfoRec psFontInfo;
TT_Postscript* postTable;
if (FT_Get_PS_Font_Info(face, &psFontInfo) == 0) {
info->fItalicAngle = psFontInfo.italic_angle;
} else if ((postTable = (TT_Postscript*)FT_Get_Sfnt_Table(face, ft_sfnt_post)) != nullptr) {
info->fItalicAngle = SkFixedToScalar(postTable->italicAngle);
} else {
info->fItalicAngle = 0;
}
@ -540,20 +536,22 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
}
}
TT_PCLT* pclt_info;
TT_OS2* os2_table;
if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != nullptr) {
info->fCapHeight = pclt_info->CapHeight;
uint8_t serif_style = pclt_info->SerifStyle & 0x3F;
if (serif_style >= 2 && serif_style <= 6)
TT_PCLT* pcltTable;
TT_OS2* os2Table;
if ((pcltTable = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != nullptr) {
info->fCapHeight = pcltTable->CapHeight;
uint8_t serif_style = pcltTable->SerifStyle & 0x3F;
if (2 <= serif_style && serif_style <= 6) {
info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
else if (serif_style >= 9 && serif_style <= 12)
} else if (9 <= serif_style && serif_style <= 12) {
info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
} else if (((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != nullptr) &&
}
} else if (((os2Table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != nullptr) &&
// sCapHeight is available only when version 2 or later.
os2_table->version != 0xFFFF &&
os2_table->version >= 2) {
info->fCapHeight = os2_table->sCapHeight;
os2Table->version != 0xFFFF &&
os2Table->version >= 2)
{
info->fCapHeight = os2Table->sCapHeight;
} else {
// Figure out a good guess for CapHeight: average the height of M and X.
FT_BBox m_bbox, x_bbox;
@ -561,8 +559,7 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
got_m = GetLetterCBox(face, 'M', &m_bbox);
got_x = GetLetterCBox(face, 'X', &x_bbox);
if (got_m && got_x) {
info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax -
x_bbox.yMin) / 2;
info->fCapHeight = ((m_bbox.yMax - m_bbox.yMin) + (x_bbox.yMax - x_bbox.yMin)) / 2;
} else if (got_m && !got_x) {
info->fCapHeight = m_bbox.yMax - m_bbox.yMin;
} else if (!got_m && got_x) {
@ -581,62 +578,33 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
}
if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
if (FT_IS_FIXED_WIDTH(face)) {
SkAdvancedTypefaceMetrics::WidthRange range(0);
int16_t advance = face->max_advance_width;
range.fAdvance.append(1, &advance);
SkAdvancedTypefaceMetrics::FinishRange(
&range, 0, SkAdvancedTypefaceMetrics::WidthRange::kDefault);
info->fGlyphWidths.emplace_back(std::move(range));
} else if (!cid) {
SkAdvancedTypefaceMetrics::WidthRange range(0);
// So as to not blow out the stack, get advances in batches.
for (int gID = 0; gID < face->num_glyphs; gID += 128) {
FT_Fixed advances[128];
int advanceCount = 128;
if (gID + advanceCount > face->num_glyphs) {
advanceCount = face->num_glyphs - gID;
info->setGlyphWidths(
face->num_glyphs,
glyphIDs,
glyphIDsCount,
SkAdvancedTypefaceMetrics::GetAdvance([face](int gId, int16_t* data) {
FT_Fixed advance = 0;
if (FT_Get_Advances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
return false;
}
FT_Get_Advances(face, gID, advanceCount, FT_LOAD_NO_SCALE, advances);
for (int i = 0; i < advanceCount; i++) {
int16_t advance = advances[i];
range.fAdvance.append(1, &advance);
}
}
SkAdvancedTypefaceMetrics::FinishRange(
&range, face->num_glyphs - 1,
SkAdvancedTypefaceMetrics::WidthRange::kRange);
info->fGlyphWidths.emplace_back(std::move(range));
} else {
info->setGlyphWidths(
face->num_glyphs,
glyphIDs,
glyphIDsCount,
SkAdvancedTypefaceMetrics::GetAdvance([face](int gId, int16_t* data) {
FT_Fixed advance = 0;
if (FT_Get_Advances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
return false;
}
SkASSERT(data);
*data = advance;
return true;
})
);
}
SkASSERT(data);
*data = advance;
return true;
})
);
}
if (perGlyphInfo & kVAdvance_PerGlyphInfo &&
FT_HAS_VERTICAL(face)) {
if (perGlyphInfo & kVAdvance_PerGlyphInfo && FT_HAS_VERTICAL(face)) {
SkASSERT(false); // Not implemented yet.
}
if (perGlyphInfo & kGlyphNames_PerGlyphInfo &&
info->fType == SkAdvancedTypefaceMetrics::kType1_Font) {
info->fType == SkAdvancedTypefaceMetrics::kType1_Font)
{
// Postscript fonts may contain more than 255 glyphs, so we end up
// using multiple font descriptions with a glyph ordering. Record
// the name of each glyph.
info->fGlyphNames.reset(
new SkAutoTArray<SkString>(face->num_glyphs));
info->fGlyphNames.reset(new SkAutoTArray<SkString>(face->num_glyphs));
for (int gID = 0; gID < face->num_glyphs; gID++) {
char glyphName[128]; // PS limit for names is 127 bytes.
FT_Get_Glyph_Name(face, gID, glyphName, 128);
@ -645,8 +613,9 @@ SkAdvancedTypefaceMetrics* SkTypeface_FreeType::onGetAdvancedTypefaceMetrics(
}
if (perGlyphInfo & kToUnicode_PerGlyphInfo &&
info->fType != SkAdvancedTypefaceMetrics::kType1_Font &&
face->num_charmaps) {
info->fType != SkAdvancedTypefaceMetrics::kType1_Font &&
face->num_charmaps)
{
populate_glyph_to_unicode(face, &(info->fGlyphToUnicode));
}

View File

@ -1610,29 +1610,21 @@ SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics(
}
if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
SkAdvancedTypefaceMetrics::WidthRange range(0);
range.fAdvance.append(1, &min_width);
SkAdvancedTypefaceMetrics::FinishRange(
&range, 0, SkAdvancedTypefaceMetrics::WidthRange::kDefault);
info->fGlyphWidths.emplace_back(std::move(range));
} else {
CTFontRef borrowedCTFont = ctFont.get();
info->setGlyphWidths(
SkToInt(glyphCount),
glyphIDs,
glyphIDsCount,
SkAdvancedTypefaceMetrics::GetAdvance([borrowedCTFont](int gId, int16_t* data) {
CGSize advance;
advance.width = 0;
CGGlyph glyph = gId;
CTFontGetAdvancesForGlyphs(borrowedCTFont, kCTFontHorizontalOrientation,
&glyph, &advance, 1);
*data = sk_float_round2int(advance.width);
return true;
})
);
}
CTFontRef borrowedCTFont = ctFont.get();
info->setGlyphWidths(
SkToInt(glyphCount),
glyphIDs,
glyphIDsCount,
SkAdvancedTypefaceMetrics::GetAdvance([borrowedCTFont](int gId, int16_t* data) {
CGSize advance;
advance.width = 0;
CGGlyph glyph = gId;
CTFontGetAdvancesForGlyphs(borrowedCTFont, kCTFontHorizontalOrientation,
&glyph, &advance, 1);
*data = sk_float_round2int(advance.width);
return true;
})
);
}
return info;
}

View File

@ -1818,34 +1818,26 @@ SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics(
}
if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
SkAdvancedTypefaceMetrics::WidthRange range(0);
range.fAdvance.append(1, &min_width);
SkAdvancedTypefaceMetrics::FinishRange(
&range, 0, SkAdvancedTypefaceMetrics::WidthRange::kDefault);
info->fGlyphWidths.emplace_back(std::move(range));
} else {
info->setGlyphWidths(
glyphCount,
glyphIDs,
glyphIDsCount,
SkAdvancedTypefaceMetrics::GetAdvance([hdc](int gId, int16_t* advance) {
// Initialize the MAT2 structure to
// the identify transformation matrix.
static const MAT2 mat2 = {
SkScalarToFIXED(1), SkScalarToFIXED(0),
SkScalarToFIXED(0), SkScalarToFIXED(1)};
int flags = GGO_METRICS | GGO_GLYPH_INDEX;
GLYPHMETRICS gm;
if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, nullptr, &mat2)) {
return false;
}
SkASSERT(advance);
*advance = gm.gmCellIncX;
return true;
})
);
}
info->setGlyphWidths(
glyphCount,
glyphIDs,
glyphIDsCount,
SkAdvancedTypefaceMetrics::GetAdvance([hdc](int gId, int16_t* advance) {
// Initialize the MAT2 structure to
// the identify transformation matrix.
static const MAT2 mat2 = {
SkScalarToFIXED(1), SkScalarToFIXED(0),
SkScalarToFIXED(0), SkScalarToFIXED(1)};
int flags = GGO_METRICS | GGO_GLYPH_INDEX;
GLYPHMETRICS gm;
if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, nullptr, &mat2)) {
return false;
}
SkASSERT(advance);
*advance = gm.gmCellIncX;
return true;
})
);
}
Error: