Basic support for vector FON.

This change gives vector FON fonts slightly better support than bitmap 
FON fonts which we already have some support for. 

This also fixes the calculation of the y component of advances for 
bitmap and vector FON glyphs.



git-svn-id: http://skia.googlecode.com/svn/trunk@13150 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bungeman@google.com 2014-01-23 15:22:42 +00:00
parent fed2ab6483
commit 4732df6941

View File

@ -152,6 +152,10 @@ static inline FIXED SkScalarToFIXED(SkScalar x) {
return SkFixedToFIXED(SkScalarToFixed(x));
}
static inline SkScalar SkFIXEDToScalar(FIXED x) {
return SkFixedToScalar(SkFIXEDToFixed(x));
}
static unsigned calculateGlyphCount(HDC hdc, const LOGFONT& lf) {
TEXTMETRIC textMetric;
if (0 == GetTextMetrics(hdc, &textMetric)) {
@ -583,7 +587,7 @@ private:
*/
SkMatrix fG_inv;
enum Type {
kTrueType_Type, kBitmap_Type,
kTrueType_Type, kBitmap_Type, kLine_Type
} fType;
TEXTMETRIC fTM;
};
@ -717,21 +721,24 @@ SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
fTM.tmPitchAndFamily = TMPF_TRUETYPE;
}
}
// Used a logfont on a memory context, should never get a device font.
// Therefore all TMPF_DEVICE will be PostScript fonts.
// If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE must be set,
// otherwise we have a vector FON, which we don't support.
// This was determined by testing with Type1 PFM/PFB and OpenTypeCFF OTF,
// as well as looking at Wine bugs and sources.
SkASSERT(!(fTM.tmPitchAndFamily & TMPF_VECTOR) ||
(fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)));
XFORM xform;
if (fTM.tmPitchAndFamily & TMPF_VECTOR) {
// Truetype or PostScript.
// Stroked FON also gets here (TMPF_VECTOR), but we don't handle it.
fType = SkScalerContext_GDI::kTrueType_Type;
// Used a logfont on a memory context, should never get a device font.
// Therefore all TMPF_DEVICE will be PostScript fonts.
// If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE means that
// we have an outline font. Otherwise we have a vector FON, which is
// scalable, but not an outline font.
// This was determined by testing with Type1 PFM/PFB and
// OpenTypeCFF OTF, as well as looking at Wine bugs and sources.
if (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)) {
// Truetype or PostScript.
fType = SkScalerContext_GDI::kTrueType_Type;
} else {
// Stroked FON.
fType = SkScalerContext_GDI::kLine_Type;
}
// fPost2x2 is column-major, left handed (y down).
// XFORM 2x2 is row-major, left handed (y down).
@ -833,8 +840,8 @@ uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar utf32) {
*
* When GGI_MARK_NONEXISTING_GLYPHS is not specified and a character does not map to a
* glyph, then the 'default character's glyph is returned instead. The 'default character'
* is available in fTM.tmDefaultChar. FON fonts have adefault character, and there exists a
* usDefaultChar in the 'OS/2' table, version 2 and later. If there is no
* is available in fTM.tmDefaultChar. FON fonts have a default character, and there exists
* a usDefaultChar in the 'OS/2' table, version 2 and later. If there is no
* 'default character' specified by the font, then often the first character found is used.
*
* When GGI_MARK_NONEXISTING_GLYPHS is specified and a character does not map to a glyph,
@ -845,7 +852,11 @@ uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar utf32) {
DWORD result = GetGlyphIndicesW(fDDC, utf16, 1, &index, GGI_MARK_NONEXISTING_GLYPHS);
if (result == GDI_ERROR
|| 0xFFFF == index
|| (0x1F == index && fType == SkScalerContext_GDI::kBitmap_Type /*&& winVer < Vista */))
|| (0x1F == index &&
(fType == SkScalerContext_GDI::kBitmap_Type ||
fType == SkScalerContext_GDI::kLine_Type)
/*&& winVer < Vista */)
)
{
index = 0;
}
@ -885,7 +896,7 @@ void SkScalerContext_GDI::generateAdvance(SkGlyph* glyph) {
void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
SkASSERT(fDDC);
if (fType == SkScalerContext_GDI::kBitmap_Type) {
if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
SIZE size;
WORD glyphs = glyph->getGlyphID(0);
if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
@ -896,12 +907,30 @@ void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
glyph->fHeight = SkToS16(size.cy);
glyph->fTop = SkToS16(-fTM.tmAscent);
// Bitmap FON cannot underhang, but vector FON may.
// There appears no means of determining underhang of vector FON.
glyph->fLeft = SkToS16(0);
glyph->fAdvanceX = SkIntToFixed(glyph->fWidth);
glyph->fAdvanceY = 0;
// Vector FON will transform nicely, but bitmap FON do not.
if (fType == SkScalerContext_GDI::kLine_Type) {
SkRect bounds = SkRect::MakeXYWH(glyph->fLeft, glyph->fTop,
glyph->fWidth, glyph->fHeight);
SkMatrix m;
m.setAll(SkFIXEDToScalar(fMat22.eM11), -SkFIXEDToScalar(fMat22.eM21), 0,
-SkFIXEDToScalar(fMat22.eM12), SkFIXEDToScalar(fMat22.eM22), 0,
0, 0, SkScalarToPersp(SK_Scalar1));
m.mapRect(&bounds);
bounds.roundOut();
glyph->fLeft = SkScalarTruncToInt(bounds.fLeft);
glyph->fTop = SkScalarTruncToInt(bounds.fTop);
glyph->fWidth = SkScalarTruncToInt(bounds.width());
glyph->fHeight = SkScalarTruncToInt(bounds.height());
}
// Apply matrix to advance.
glyph->fAdvanceY = SkFixedMul(SkFIXEDToFixed(fMat22.eM21), glyph->fAdvanceX);
glyph->fAdvanceY = SkFixedMul(-SkFIXEDToFixed(fMat22.eM12), glyph->fAdvanceX);
glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvanceX);
return;
@ -988,7 +1017,7 @@ void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint:
SkASSERT(fDDC);
#ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
if (fType == SkScalerContext_GDI::kBitmap_Type) {
if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
#endif
if (mx) {
mx->fTop = SkIntToScalar(-fTM.tmAscent);