[3/5] gdiplus: Use OUTLINETEXTMETRIC instead of LOGFONT to store GpFont metrics. Take 2.
Dmitry Timoshkov
dmitry at baikal.ru
Fri May 11 05:20:31 CDT 2012
---
dlls/gdiplus/font.c | 201 +++++++++++++++++++---------------------
dlls/gdiplus/gdiplus_private.h | 7 +-
2 files changed, 96 insertions(+), 112 deletions(-)
diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c
index 5b57ec6..b08323e 100644
--- a/dlls/gdiplus/font.c
+++ b/dlls/gdiplus/font.c
@@ -39,37 +39,44 @@ static const REAL inch_per_point = 1.0/72.0;
static GpFontCollection installedFontCollection = {0};
-static inline REAL get_dpi (void)
+static inline LONG get_dpi(void)
{
- REAL dpi;
- GpGraphics *graphics;
+ LONG dpi;
HDC hdc = GetDC(0);
- GdipCreateFromHDC (hdc, &graphics);
- GdipGetDpiX(graphics, &dpi);
- GdipDeleteGraphics(graphics);
+ dpi = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC (0, hdc);
return dpi;
}
-static inline REAL point_to_pixel (REAL point)
-{
- return point * get_dpi() * inch_per_point;
-}
-
-static inline REAL inch_to_pixel (REAL inch)
-{
- return inch * get_dpi();
-}
-
-static inline REAL document_to_pixel (REAL doc)
+static LONG em_size_to_pixel(REAL em_size, Unit unit, LONG dpi)
{
- return doc * (get_dpi() / 300.0); /* Per MSDN */
-}
+ switch (unit)
+ {
+ default:
+ FIXME("Unhandled unit type: %d\n", unit);
+ return 0;
-static inline REAL mm_to_pixel (REAL mm)
-{
- return mm * (get_dpi() / mm_per_inch);
+ case UnitPixel:
+ case UnitWorld:
+ /* FIXME: Figure out when World != Pixel */
+ return em_size;
+ case UnitDisplay:
+ FIXME("Unknown behavior for UnitDisplay! Please report!\n");
+ /* FIXME: Figure out how this works...
+ * MSDN says that if "DISPLAY" is a monitor, then pixel should be
+ * used. That's not what I got. Tests on Windows revealed no output,
+ * and the tests in tests/font crash windows */
+ return 0;
+ case UnitPoint:
+ return em_size * dpi * inch_per_point;
+ case UnitInch:
+ return em_size * dpi;
+ case UnitDocument:
+ return em_size * dpi / 300.0; /* Per MSDN */
+ case UnitMillimeter:
+ return em_size * dpi / mm_per_inch;
+ }
}
/*******************************************************************************
@@ -96,68 +103,46 @@ static inline REAL mm_to_pixel (REAL mm)
GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
REAL emSize, INT style, Unit unit, GpFont **font)
{
- WCHAR facename[LF_FACESIZE];
- LOGFONTW* lfw;
- const OUTLINETEXTMETRICW *otm;
+ HFONT hfont;
+ OUTLINETEXTMETRICW otm;
+ LOGFONTW lfw;
+ HDC hdc;
GpStatus stat;
+ int ret;
- if (!fontFamily || !font)
+ if (!fontFamily || !font || emSize < 0.0)
return InvalidParameter;
TRACE("%p (%s), %f, %d, %d, %p\n", fontFamily,
debugstr_w(fontFamily->FamilyName), emSize, style, unit, font);
- stat = GdipGetFamilyName (fontFamily, facename, 0);
- if (stat != Ok) return stat;
- *font = GdipAlloc(sizeof(GpFont));
-
- otm = &fontFamily->otm;
- lfw = &((*font)->lfw);
- ZeroMemory(&(*lfw), sizeof(*lfw));
+ memset(&lfw, 0, sizeof(lfw));
- lfw->lfWeight = otm->otmTextMetrics.tmWeight;
- lfw->lfItalic = otm->otmTextMetrics.tmItalic;
- lfw->lfUnderline = otm->otmTextMetrics.tmUnderlined;
- lfw->lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
- lfw->lfCharSet = otm->otmTextMetrics.tmCharSet;
- lfw->lfPitchAndFamily = otm->otmTextMetrics.tmPitchAndFamily;
- lstrcpynW(lfw->lfFaceName, facename, LF_FACESIZE);
+ stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL);
+ if (stat != Ok) return stat;
- switch (unit)
- {
- case UnitWorld:
- /* FIXME: Figure out when World != Pixel */
- (*font)->pixel_size = emSize; break;
- case UnitDisplay:
- FIXME("Unknown behavior for UnitDisplay! Please report!\n");
- /* FIXME: Figure out how this works...
- * MSDN says that if "DISPLAY" is a monitor, then pixel should be
- * used. That's not what I got. Tests on Windows revealed no output,
- * and the tests in tests/font crash windows */
- (*font)->pixel_size = 0; break;
- case UnitPixel:
- (*font)->pixel_size = emSize; break;
- case UnitPoint:
- (*font)->pixel_size = point_to_pixel(emSize); break;
- case UnitInch:
- (*font)->pixel_size = inch_to_pixel(emSize); break;
- case UnitDocument:
- (*font)->pixel_size = document_to_pixel(emSize); break;
- case UnitMillimeter:
- (*font)->pixel_size = mm_to_pixel(emSize); break;
- }
+ lfw.lfHeight = -em_size_to_pixel(emSize, unit, get_dpi());
+ lfw.lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR;
+ lfw.lfItalic = style & FontStyleItalic;
+ lfw.lfUnderline = style & FontStyleUnderline;
+ lfw.lfStrikeOut = style & FontStyleStrikeout;
+
+ hfont = CreateFontIndirectW(&lfw);
+ hdc = CreateCompatibleDC(0);
+ SelectObject(hdc, hfont);
+ otm.otmSize = sizeof(otm);
+ ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
+ DeleteDC(hdc);
+ DeleteObject(hfont);
- lfw->lfHeight = (*font)->pixel_size * -1;
+ if (!ret) return NotTrueTypeFont;
- lfw->lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR;
- lfw->lfItalic = style & FontStyleItalic;
- lfw->lfUnderline = style & FontStyleUnderline;
- lfw->lfStrikeOut = style & FontStyleStrikeout;
+ *font = GdipAlloc(sizeof(GpFont));
+ if (!*font) return OutOfMemory;
(*font)->unit = unit;
(*font)->emSize = emSize;
- (*font)->height = otm->otmEMSquare;
- (*font)->line_spacing = otm->otmTextMetrics.tmAscent + otm->otmTextMetrics.tmDescent + otm->otmTextMetrics.tmExternalLeading;
+ (*font)->otm = otm;
stat = GdipCloneFontFamily((GpFontFamily *)fontFamily, &(*font)->family);
if (stat != Ok)
@@ -178,42 +163,30 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
GDIPCONST LOGFONTW *logfont, GpFont **font)
{
HFONT hfont, oldfont;
- TEXTMETRICW textmet;
+ OUTLINETEXTMETRICW otm;
GpStatus stat;
+ int ret;
TRACE("(%p, %p, %p)\n", hdc, logfont, font);
- if(!logfont || !font)
+ if (!hdc || !logfont || !font)
return InvalidParameter;
- if (logfont->lfFaceName[0] == 0)
- return NotTrueTypeFont;
-
- *font = GdipAlloc(sizeof(GpFont));
- if(!*font) return OutOfMemory;
-
- memcpy((*font)->lfw.lfFaceName, logfont->lfFaceName, LF_FACESIZE *
- sizeof(WCHAR));
- (*font)->lfw.lfHeight = logfont->lfHeight;
- (*font)->lfw.lfItalic = logfont->lfItalic;
- (*font)->lfw.lfUnderline = logfont->lfUnderline;
- (*font)->lfw.lfStrikeOut = logfont->lfStrikeOut;
-
- hfont = CreateFontIndirectW(&(*font)->lfw);
+ hfont = CreateFontIndirectW(logfont);
oldfont = SelectObject(hdc, hfont);
- GetTextMetricsW(hdc, &textmet);
+ otm.otmSize = sizeof(otm);
+ ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
+ SelectObject(hdc, oldfont);
+ DeleteObject(hfont);
- (*font)->lfw.lfHeight = -(textmet.tmHeight-textmet.tmInternalLeading);
- (*font)->lfw.lfWeight = textmet.tmWeight;
- (*font)->lfw.lfCharSet = textmet.tmCharSet;
+ if (!ret) return NotTrueTypeFont;
- (*font)->pixel_size = (*font)->emSize = textmet.tmHeight;
- (*font)->unit = UnitPixel;
- (*font)->height = 1; /* FIXME: need NEWTEXTMETRIC.ntmSizeEM here */
- (*font)->line_spacing = textmet.tmAscent + textmet.tmDescent + textmet.tmExternalLeading;
+ *font = GdipAlloc(sizeof(GpFont));
+ if (!*font) return OutOfMemory;
- SelectObject(hdc, oldfont);
- DeleteObject(hfont);
+ (*font)->unit = UnitWorld;
+ (*font)->emSize = otm.otmTextMetrics.tmAscent;
+ (*font)->otm = otm;
stat = GdipCreateFontFamilyFromName(logfont->lfFaceName, NULL, &(*font)->family);
if (stat != Ok)
@@ -333,7 +306,7 @@ GpStatus WINGDIPAPI GdipGetFontSize(GpFont *font, REAL *size)
if (!(font && size)) return InvalidParameter;
*size = font->emSize;
- TRACE("%s,%d => %f\n", debugstr_w(font->lfw.lfFaceName), font->lfw.lfHeight, *size);
+ TRACE("%s,%d => %f\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *size);
return Ok;
}
@@ -358,15 +331,15 @@ GpStatus WINGDIPAPI GdipGetFontStyle(GpFont *font, INT *style)
if (!(font && style))
return InvalidParameter;
- if (font->lfw.lfWeight > FW_REGULAR)
+ if (font->otm.otmTextMetrics.tmWeight > FW_REGULAR)
*style = FontStyleBold;
else
*style = FontStyleRegular;
- if (font->lfw.lfItalic)
+ if (font->otm.otmTextMetrics.tmItalic)
*style |= FontStyleItalic;
- if (font->lfw.lfUnderline)
+ if (font->otm.otmTextMetrics.tmUnderlined)
*style |= FontStyleUnderline;
- if (font->lfw.lfStrikeOut)
+ if (font->otm.otmTextMetrics.tmStruckOut)
*style |= FontStyleStrikeout;
return Ok;
@@ -390,7 +363,7 @@ GpStatus WINGDIPAPI GdipGetFontUnit(GpFont *font, Unit *unit)
if (!(font && unit)) return InvalidParameter;
*unit = font->unit;
- TRACE("%s,%d => %d\n", debugstr_w(font->lfw.lfFaceName), font->lfw.lfHeight, *unit);
+ TRACE("%s,%d => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *unit);
return Ok;
}
@@ -430,8 +403,22 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics,
if(!font || !graphics || !lfw)
return InvalidParameter;
- *lfw = font->lfw;
- TRACE("=> %s,%d\n", debugstr_w(font->lfw.lfFaceName), font->lfw.lfHeight);
+ lfw->lfHeight = -font->otm.otmTextMetrics.tmAscent;
+ lfw->lfWidth = 0;
+ lfw->lfEscapement = 0;
+ lfw->lfOrientation = 0;
+ lfw->lfWeight = font->otm.otmTextMetrics.tmWeight;
+ lfw->lfItalic = font->otm.otmTextMetrics.tmItalic ? 1 : 0;
+ lfw->lfUnderline = font->otm.otmTextMetrics.tmUnderlined ? 1 : 0;
+ lfw->lfStrikeOut = font->otm.otmTextMetrics.tmStruckOut ? 1 : 0;
+ lfw->lfCharSet = font->otm.otmTextMetrics.tmCharSet;
+ lfw->lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lfw->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lfw->lfQuality = DEFAULT_QUALITY;
+ lfw->lfPitchAndFamily = 0;
+ strcpyW(lfw->lfFaceName, font->family->FamilyName);
+
+ TRACE("=> %s,%d\n", debugstr_w(lfw->lfFaceName), lfw->lfHeight);
return Ok;
}
@@ -549,7 +536,7 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
}
TRACE("%s,%d(unit %d) => %f\n",
- debugstr_w(font->lfw.lfFaceName), font->lfw.lfHeight, font->unit, *height);
+ debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, font->unit, *height);
return Ok;
}
@@ -664,13 +651,13 @@ GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily**
{
if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
- TRACE("stub: %p (%s), %p\n", FontFamily,
+ TRACE("%p (%s), %p\n", FontFamily,
debugstr_w(FontFamily->FamilyName), clonedFontFamily);
*clonedFontFamily = GdipAlloc(sizeof(GpFontFamily));
if (!*clonedFontFamily) return OutOfMemory;
- (*clonedFontFamily)->otm = FontFamily->otm;
+ **clonedFontFamily = *FontFamily;
lstrcpyW((*clonedFontFamily)->FamilyName, FontFamily->FamilyName);
TRACE("<-- %p\n", *clonedFontFamily);
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 3676358..5267d74 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -347,11 +347,8 @@ struct GpImageAttributes{
struct GpFont{
GpFontFamily *family;
- LOGFONTW lfw;
- REAL emSize;
- REAL pixel_size;
- UINT height;
- LONG line_spacing;
+ OUTLINETEXTMETRICW otm;
+ REAL emSize; /* in font units */
Unit unit;
};
--
1.7.10.1
More information about the wine-patches
mailing list