[4/5] gdiplus: Fix internal font metrics handling. Take 2.
Dmitry Timoshkov
dmitry at baikal.ru
Tue May 8 05:29:56 CDT 2012
Deriving GpFont from GpFontFamily was sent separately to simplify a bit
the patch.
---
dlls/gdiplus/font.c | 454 +++++++++++++++++++++++++---------------
dlls/gdiplus/gdiplus_private.h | 10 +-
dlls/gdiplus/graphics.c | 14 +-
dlls/gdiplus/graphicspath.c | 5 +-
4 files changed, 307 insertions(+), 176 deletions(-)
diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c
index a07333a..bf6a598 100644
--- a/dlls/gdiplus/font.c
+++ b/dlls/gdiplus/font.c
@@ -34,42 +34,121 @@ WINE_DEFAULT_DEBUG_CHANNEL (gdiplus);
#include "gdiplus.h"
#include "gdiplus_private.h"
+/* PANOSE is 10 bytes in size, need to pack the structure properly */
+#include "pshpack2.h"
+typedef struct
+{
+ USHORT version;
+ SHORT xAvgCharWidth;
+ USHORT usWeightClass;
+ USHORT usWidthClass;
+ SHORT fsType;
+ SHORT ySubscriptXSize;
+ SHORT ySubscriptYSize;
+ SHORT ySubscriptXOffset;
+ SHORT ySubscriptYOffset;
+ SHORT ySuperscriptXSize;
+ SHORT ySuperscriptYSize;
+ SHORT ySuperscriptXOffset;
+ SHORT ySuperscriptYOffset;
+ SHORT yStrikeoutSize;
+ SHORT yStrikeoutPosition;
+ SHORT sFamilyClass;
+ PANOSE panose;
+ ULONG ulUnicodeRange1;
+ ULONG ulUnicodeRange2;
+ ULONG ulUnicodeRange3;
+ ULONG ulUnicodeRange4;
+ CHAR achVendID[4];
+ USHORT fsSelection;
+ USHORT usFirstCharIndex;
+ USHORT usLastCharIndex;
+ /* According to the Apple spec, original version didn't have the below fields,
+ * version numbers were taken from the OpenType spec.
+ */
+ /* version 0 (TrueType 1.5) */
+ USHORT sTypoAscender;
+ USHORT sTypoDescender;
+ USHORT sTypoLineGap;
+ USHORT usWinAscent;
+ USHORT usWinDescent;
+ /* version 1 (TrueType 1.66) */
+ ULONG ulCodePageRange1;
+ ULONG ulCodePageRange2;
+ /* version 2 (OpenType 1.2) */
+ SHORT sxHeight;
+ SHORT sCapHeight;
+ USHORT usDefaultChar;
+ USHORT usBreakChar;
+ USHORT usMaxContext;
+} TT_OS2_V2;
+
+typedef struct
+{
+ ULONG Version;
+ SHORT Ascender;
+ SHORT Descender;
+ SHORT LineGap;
+ USHORT advanceWidthMax;
+ SHORT minLeftSideBearing;
+ SHORT minRightSideBearing;
+ SHORT xMaxExtent;
+ SHORT caretSlopeRise;
+ SHORT caretSlopeRun;
+ SHORT caretOffset;
+ SHORT reserved[4];
+ SHORT metricDataFormat;
+ USHORT numberOfHMetrics;
+} TT_HHEA;
+#include "poppack.h"
+
+#ifdef WORDS_BIGENDIAN
+#define GET_BE_WORD(x) (x)
+#define GET_BE_DWORD(x) (x)
+#else
+#define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
+#define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
+#endif
+
+#define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
+ ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
+ ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24))
+#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
+#define MS_HHEA_TAG MS_MAKE_TAG('h','h','e','a')
+
static const REAL mm_per_inch = 25.4;
static const REAL inch_per_point = 1.0/72.0;
static GpFontCollection installedFontCollection = {0};
-static inline REAL get_dpi (void)
-{
- REAL dpi;
- GpGraphics *graphics;
- HDC hdc = GetDC(0);
- GdipCreateFromHDC (hdc, &graphics);
- GdipGetDpiX(graphics, &dpi);
- GdipDeleteGraphics(graphics);
- 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 +175,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, fontFamily->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 +235,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)
@@ -304,7 +349,7 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
{
TRACE("%p %p\n", font, family);
- if (!(font && family))
+ if (!font || !family)
return InvalidParameter;
return GdipCloneFontFamily(font->family, family);
@@ -330,10 +375,10 @@ GpStatus WINGDIPAPI GdipGetFontSize(GpFont *font, REAL *size)
{
TRACE("(%p, %p)\n", font, size);
- if (!(font && size)) return InvalidParameter;
+ 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;
}
@@ -355,18 +400,18 @@ GpStatus WINGDIPAPI GdipGetFontStyle(GpFont *font, INT *style)
{
TRACE("%p %p\n", font, style);
- if (!(font && 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;
@@ -387,10 +432,10 @@ GpStatus WINGDIPAPI GdipGetFontUnit(GpFont *font, Unit *unit)
{
TRACE("(%p, %p)\n", font, unit);
- if (!(font && unit)) return InvalidParameter;
+ 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 +475,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;
}
@@ -479,12 +538,15 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
TRACE("%p %p %p\n", font, graphics, height);
- stat = GdipGetDpiY((GpGraphics*)graphics, &dpi);
-
- if (stat == Ok)
- stat = GdipGetFontHeightGivenDPI(font, dpi, height);
+ if (graphics)
+ {
+ stat = GdipGetDpiY((GpGraphics*)graphics, &dpi);
+ if (stat != Ok) return stat;
+ }
+ else
+ dpi = font->family->dpi;
- return stat;
+ return GdipGetFontHeightGivenDPI(font, dpi, height);
}
/*******************************************************************************
@@ -504,14 +566,26 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
*/
GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi, REAL *height)
{
- REAL font_height;
+ GpStatus stat;
+ INT style;
+ UINT16 line_spacing, em_height;
+ REAL font_height, font_size;
+
+ if (!font || !height) return InvalidParameter;
TRACE("%p (%s), %f, %p\n", font,
- debugstr_w(font->lfw.lfFaceName), dpi, height);
+ debugstr_w(font->family->FamilyName), dpi, height);
- if (!(font && height)) return InvalidParameter;
+ stat = GdipGetFontSize((GpFont *)font, &font_size);
+ if (stat != Ok) return stat;
+ stat = GdipGetFontStyle((GpFont *)font, &style);
+ if (stat != Ok) return stat;
+ stat = GdipGetLineSpacing(font->family, style, &line_spacing);
+ if (stat != Ok) return stat;
+ stat = GdipGetEmHeight(font->family, style, &em_height);
+ if (stat != Ok) return stat;
- font_height = font->line_spacing * (font->emSize / font->height);
+ font_height = (REAL)line_spacing * font_size / (REAL)em_height;
switch (font->unit)
{
@@ -537,7 +611,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;
}
@@ -551,35 +625,84 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf,
const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
{
- if (!ntm || type == RASTER_FONTTYPE)
- {
+ if (type != TRUETYPE_FONTTYPE)
return 1;
- }
*(LOGFONTW *)lParam = *elf;
return 0;
}
-static BOOL find_installed_font(const WCHAR *name, OUTLINETEXTMETRICW *otm)
+struct font_metrics
+{
+ UINT16 em_height, ascent, descent, line_spacing; /* in font units */
+ int dpi;
+};
+
+static BOOL get_font_metrics(HDC hdc, struct font_metrics *fm)
+{
+ OUTLINETEXTMETRICW otm;
+ TT_OS2_V2 tt_os2;
+ TT_HHEA tt_hori;
+ LONG size;
+ UINT16 line_gap;
+
+ otm.otmSize = sizeof(otm);
+ if (!GetOutlineTextMetricsW(hdc, otm.otmSize, &otm)) return FALSE;
+
+ fm->em_height = otm.otmEMSquare;
+ fm->dpi = GetDeviceCaps(hdc, LOGPIXELSY);
+
+ memset(&tt_hori, 0, sizeof(tt_hori));
+ if (GetFontData(hdc, MS_HHEA_TAG, 0, &tt_hori, sizeof(tt_hori)) != GDI_ERROR)
+ {
+ fm->ascent = GET_BE_WORD(tt_hori.Ascender);
+ fm->descent = -GET_BE_WORD(tt_hori.Descender);
+ TRACE("hhea: ascent %d, descent %d\n", fm->ascent, fm->descent);
+ line_gap = GET_BE_WORD(tt_hori.LineGap);
+ fm->line_spacing = fm->ascent + fm->descent + line_gap;
+ TRACE("line_gap %u, line_spacing %u\n", line_gap, fm->line_spacing);
+ if (fm->ascent + fm->descent != 0) return TRUE;
+ }
+
+ size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0);
+ if (size == GDI_ERROR) return FALSE;
+
+ if (size > sizeof(tt_os2)) size = sizeof(tt_os2);
+
+ memset(&tt_os2, 0, sizeof(tt_os2));
+ if (GetFontData(hdc, MS_OS2_TAG, 0, &tt_os2, size) != size) return FALSE;
+
+ fm->ascent = GET_BE_WORD(tt_os2.usWinAscent);
+ fm->descent = GET_BE_WORD(tt_os2.usWinDescent);
+ TRACE("usWinAscent %u, usWinDescent %u\n", fm->ascent, fm->descent);
+ if (fm->ascent + fm->descent == 0)
+ {
+ fm->ascent = GET_BE_WORD(tt_os2.sTypoAscender);
+ fm->descent = GET_BE_WORD(tt_os2.sTypoDescender);
+ TRACE("sTypoAscender %u, sTypoDescender %u\n", fm->ascent, fm->descent);
+ }
+ line_gap = GET_BE_WORD(tt_os2.sTypoLineGap);
+ fm->line_spacing = fm->ascent + fm->descent + line_gap;
+ TRACE("line_gap %u, line_spacing %u\n", line_gap, fm->line_spacing);
+ return TRUE;
+}
+
+static GpStatus find_installed_font(const WCHAR *name, struct font_metrics *fm)
{
LOGFONTW lf;
HDC hdc = CreateCompatibleDC(0);
- BOOL ret = FALSE;
+ GpStatus ret = FontFamilyNotFound;
if(!EnumFontFamiliesW(hdc, name, is_font_installed_proc, (LPARAM)&lf))
{
- HFONT hfont;
+ HFONT hfont, old_font;
- lf.lfHeight = -2048;
hfont = CreateFontIndirectW(&lf);
- hfont = SelectObject(hdc, hfont);
-
- otm->otmSize = sizeof(*otm);
- if (GetOutlineTextMetricsW(hdc, otm->otmSize, otm))
- ret = TRUE;
-
- DeleteObject(SelectObject(hdc, hfont));
+ old_font = SelectObject(hdc, hfont);
+ ret = get_font_metrics(hdc, fm) ? Ok : NotTrueTypeFont;
+ SelectObject(hdc, old_font);
+ DeleteObject(hfont);
}
DeleteDC(hdc);
@@ -610,24 +733,29 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
GpFontCollection *fontCollection,
GpFontFamily **FontFamily)
{
+ GpStatus stat;
GpFontFamily* ffamily;
- OUTLINETEXTMETRICW otm;
+ struct font_metrics fm;
TRACE("%s, %p %p\n", debugstr_w(name), fontCollection, FontFamily);
- if (!(name && FontFamily))
+ if (!name || !FontFamily)
return InvalidParameter;
if (fontCollection)
FIXME("No support for FontCollections yet!\n");
- if (!find_installed_font(name, &otm))
- return FontFamilyNotFound;
+ stat = find_installed_font(name, &fm);
+ if (stat != Ok) return stat;
ffamily = GdipAlloc(sizeof (GpFontFamily));
if (!ffamily) return OutOfMemory;
- ffamily->otm = otm;
lstrcpynW(ffamily->FamilyName, name, LF_FACESIZE);
+ ffamily->em_height = fm.em_height;
+ ffamily->ascent = fm.ascent;
+ ffamily->descent = fm.descent;
+ ffamily->line_spacing = fm.line_spacing;
+ ffamily->dpi = fm.dpi;
*FontFamily = ffamily;
@@ -650,15 +778,15 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
*/
GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily** clonedFontFamily)
{
- if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
+ 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);
@@ -729,10 +857,10 @@ GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily *FontFamily)
GpStatus WINGDIPAPI GdipGetCellAscent(GDIPCONST GpFontFamily *family,
INT style, UINT16* CellAscent)
{
- if (!(family && CellAscent)) return InvalidParameter;
+ if (!family || !CellAscent) return InvalidParameter;
- *CellAscent = family->otm.otmTextMetrics.tmAscent;
- TRACE("%d => %u\n", family->otm.otmTextMetrics.tmHeight, *CellAscent);
+ *CellAscent = family->ascent;
+ TRACE("%s => %u\n", debugstr_w(family->FamilyName), *CellAscent);
return Ok;
}
@@ -742,10 +870,10 @@ GpStatus WINGDIPAPI GdipGetCellDescent(GDIPCONST GpFontFamily *family,
{
TRACE("(%p, %d, %p)\n", family, style, CellDescent);
- if (!(family && CellDescent)) return InvalidParameter;
+ if (!family || !CellDescent) return InvalidParameter;
- *CellDescent = family->otm.otmTextMetrics.tmDescent;
- TRACE("%d => %u\n", family->otm.otmTextMetrics.tmHeight, *CellDescent);
+ *CellDescent = family->descent;
+ TRACE("%s => %u\n", debugstr_w(family->FamilyName), *CellDescent);
return Ok;
}
@@ -766,12 +894,12 @@ GpStatus WINGDIPAPI GdipGetCellDescent(GDIPCONST GpFontFamily *family,
*/
GpStatus WINGDIPAPI GdipGetEmHeight(GDIPCONST GpFontFamily *family, INT style, UINT16* EmHeight)
{
- if (!(family && EmHeight)) return InvalidParameter;
+ if (!family || !EmHeight) return InvalidParameter;
TRACE("%p (%s), %d, %p\n", family, debugstr_w(family->FamilyName), style, EmHeight);
- *EmHeight = family->otm.otmEMSquare;
- TRACE("%d => %u\n", family->otm.otmTextMetrics.tmHeight, *EmHeight);
+ *EmHeight = family->em_height;
+ TRACE("%s => %u\n", debugstr_w(family->FamilyName), *EmHeight);
return Ok;
}
@@ -796,13 +924,13 @@ GpStatus WINGDIPAPI GdipGetLineSpacing(GDIPCONST GpFontFamily *family,
{
TRACE("%p, %d, %p\n", family, style, LineSpacing);
- if (!(family && LineSpacing))
+ if (!family || !LineSpacing)
return InvalidParameter;
if (style) FIXME("ignoring style\n");
- *LineSpacing = family->otm.otmTextMetrics.tmAscent + family->otm.otmTextMetrics.tmDescent + family->otm.otmTextMetrics.tmExternalLeading;
- TRACE("%d => %u\n", family->otm.otmTextMetrics.tmHeight, *LineSpacing);
+ *LineSpacing = family->line_spacing;
+ TRACE("%s => %u\n", debugstr_w(family->FamilyName), *LineSpacing);
return Ok;
}
@@ -829,7 +957,7 @@ GpStatus WINGDIPAPI GdipIsStyleAvailable(GDIPCONST GpFontFamily* family,
TRACE("%p %d %p\n", family, style, IsStyleAvailable);
- if (!(family && IsStyleAvailable))
+ if (!family || !IsStyleAvailable)
return InvalidParameter;
*IsStyleAvailable = FALSE;
@@ -987,7 +1115,7 @@ GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection* fontCollection,
{
FIXME("stub: %p, %s\n", fontCollection, debugstr_w(filename));
- if (!(fontCollection && filename))
+ if (!fontCollection || !filename)
return InvalidParameter;
return NotImplemented;
@@ -1156,7 +1284,7 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyCount(
{
TRACE("%p, %p\n", fontCollection, numFound);
- if (!(fontCollection && numFound))
+ if (!fontCollection || !numFound)
return InvalidParameter;
*numFound = fontCollection->count;
@@ -1175,7 +1303,7 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList(
TRACE("%p, %d, %p, %p\n", fontCollection, numSought, gpfamilies, numFound);
- if (!(fontCollection && gpfamilies && numFound))
+ if (!fontCollection || !gpfamilies || !numFound)
return InvalidParameter;
memset(gpfamilies, 0, sizeof(*gpfamilies) * numSought);
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index 3676358..1adfe09 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;
};
@@ -378,8 +375,9 @@ struct GpFontCollection{
};
struct GpFontFamily{
- OUTLINETEXTMETRICW otm;
WCHAR FamilyName[LF_FACESIZE];
+ UINT16 em_height, ascent, descent, line_spacing; /* in font units */
+ int dpi;
};
/* internal use */
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index a5e3eb2..b674035 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -2136,15 +2136,13 @@ void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font, HFONT *hfont)
rel_height = sqrt((pt[2].Y-pt[0].Y)*(pt[2].Y-pt[0].Y)+
(pt[2].X-pt[0].X)*(pt[2].X-pt[0].X));
- lfw = font->lfw;
- lfw.lfHeight = roundr(-font->pixel_size * rel_height);
+ GdipGetLogFontW((GpFont *)font, graphics, &lfw);
+ lfw.lfHeight = roundr(lfw.lfHeight * rel_height);
unscaled_font = CreateFontIndirectW(&lfw);
SelectObject(hdc, unscaled_font);
GetTextMetricsW(hdc, &textmet);
- lfw = font->lfw;
- lfw.lfHeight = roundr(-font->pixel_size * rel_height);
lfw.lfWidth = roundr(textmet.tmAveCharWidth * rel_width / rel_height);
lfw.lfEscapement = lfw.lfOrientation = roundr((angle / M_PI) * 1800.0);
@@ -4919,6 +4917,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
{
GpStatus stat;
int i;
+ LOGFONTW lfw;
HFONT oldfont;
struct measure_ranges_args args;
HDC hdc, temp_hdc=NULL;
@@ -4926,12 +4925,15 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
TRACE("(%p %s %d %p %s %p %d %p)\n", graphics, debugstr_w(string),
length, font, debugstr_rectf(layoutRect), stringFormat, regionCount, regions);
- if (!(graphics && string && font && layoutRect && stringFormat && regions))
+ if (!graphics || !string || !font || !layoutRect || !stringFormat || !regions)
return InvalidParameter;
if (regionCount < stringFormat->range_count)
return InvalidParameter;
+ stat = GdipGetLogFontW((GpFont *)font, graphics, &lfw);
+ if (stat != Ok) return stat;
+
if(!graphics->hdc)
{
hdc = temp_hdc = CreateCompatibleDC(0);
@@ -4943,7 +4945,7 @@ GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
if (stringFormat->attr)
TRACE("may be ignoring some format flags: attr %x\n", stringFormat->attr);
- oldfont = SelectObject(hdc, CreateFontIndirectW(&font->lfw));
+ oldfont = SelectObject(hdc, CreateFontIndirectW(&lfw));
for (i=0; i<stringFormat->range_count; i++)
{
diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c
index d37512e..5da53b2 100644
--- a/dlls/gdiplus/graphicspath.c
+++ b/dlls/gdiplus/graphicspath.c
@@ -942,6 +942,7 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
{
GpFont *font;
GpStatus status;
+ LOGFONTW lfw;
HANDLE hfont;
HDC dc;
GpPath *backup;
@@ -956,7 +957,9 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
if (status != Ok)
return status;
- hfont = CreateFontIndirectW(&font->lfw);
+ status = GdipGetLogFontW((GpFont *)font, NULL, &lfw);
+ if (status != Ok) return status;
+ hfont = CreateFontIndirectW(&lfw);
if (!hfont)
{
WARN("Failed to create font\n");
--
1.7.10.1
More information about the wine-patches
mailing list