gdiplus: Use OUTLINETEXTMETRIC instead of LOGFONT to store GpFont metrics.
This commit is contained in:
parent
915cd7b5b2
commit
c626528a91
|
@ -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)
|
||||
static LONG em_size_to_pixel(REAL em_size, Unit unit, LONG dpi)
|
||||
{
|
||||
return point * get_dpi() * inch_per_point;
|
||||
}
|
||||
switch (unit)
|
||||
{
|
||||
default:
|
||||
FIXME("Unhandled unit type: %d\n", unit);
|
||||
return 0;
|
||||
|
||||
static inline REAL inch_to_pixel (REAL inch)
|
||||
{
|
||||
return inch * get_dpi();
|
||||
}
|
||||
|
||||
static inline REAL document_to_pixel (REAL doc)
|
||||
{
|
||||
return doc * (get_dpi() / 300.0); /* Per MSDN */
|
||||
}
|
||||
|
||||
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);
|
||||
memset(&lfw, 0, sizeof(lfw));
|
||||
|
||||
stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL);
|
||||
if (stat != Ok) return stat;
|
||||
|
||||
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);
|
||||
|
||||
if (!ret) return NotTrueTypeFont;
|
||||
|
||||
*font = GdipAlloc(sizeof(GpFont));
|
||||
|
||||
otm = &fontFamily->otm;
|
||||
lfw = &((*font)->lfw);
|
||||
ZeroMemory(&(*lfw), 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);
|
||||
|
||||
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 = (*font)->pixel_size * -1;
|
||||
|
||||
lfw->lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR;
|
||||
lfw->lfItalic = style & FontStyleItalic;
|
||||
lfw->lfUnderline = style & FontStyleUnderline;
|
||||
lfw->lfStrikeOut = style & FontStyleStrikeout;
|
||||
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,43 +163,31 @@ 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);
|
||||
|
||||
(*font)->lfw.lfHeight = -(textmet.tmHeight-textmet.tmInternalLeading);
|
||||
(*font)->lfw.lfWeight = textmet.tmWeight;
|
||||
(*font)->lfw.lfCharSet = textmet.tmCharSet;
|
||||
|
||||
(*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;
|
||||
|
||||
otm.otmSize = sizeof(otm);
|
||||
ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
|
||||
SelectObject(hdc, oldfont);
|
||||
DeleteObject(hfont);
|
||||
|
||||
if (!ret) return NotTrueTypeFont;
|
||||
|
||||
*font = GdipAlloc(sizeof(GpFont));
|
||||
if (!*font) return OutOfMemory;
|
||||
|
||||
(*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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue