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:
parent
9a5c47f4ef
commit
f149169352
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user