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)) {
*/
SkMatrix fG_inv;
enum Type {
- kTrueType_Type, kBitmap_Type,
+ kTrueType_Type, kBitmap_Type, kLine_Type
} fType;
TEXTMETRIC fTM;
};
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).
*
* 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,
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;
}
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)) {
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;
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);