[GDIPLUS]

* Sync with Wine 1.5.19.
[PSDK]
* Update some headers.

svn path=/trunk/; revision=57882
This commit is contained in:
Amine Khaldi 2012-12-11 21:40:15 +00:00
parent 3552b8c127
commit d4f934e3be
15 changed files with 2482 additions and 998 deletions

View file

@ -105,13 +105,7 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
return stat; return stat;
} }
stat = GdipCloneMatrix(src->transform, &dest->transform); dest->transform = src->transform;
if(stat != Ok){
GdipDeletePath(dest->path);
GdipFree(dest);
return stat;
}
/* blending */ /* blending */
count = src->blendcount; count = src->blendcount;
@ -129,7 +123,6 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
if(!dest->blendfac || !dest->blendpos || !dest->surroundcolors || if(!dest->blendfac || !dest->blendpos || !dest->surroundcolors ||
(pcount && (!dest->pblendcolor || !dest->pblendpos))){ (pcount && (!dest->pblendcolor || !dest->pblendpos))){
GdipDeletePath(dest->path); GdipDeletePath(dest->path);
GdipDeleteMatrix(dest->transform);
GdipFree(dest->blendfac); GdipFree(dest->blendfac);
GdipFree(dest->blendpos); GdipFree(dest->blendpos);
GdipFree(dest->surroundcolors); GdipFree(dest->surroundcolors);
@ -211,7 +204,7 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
if (stat == Ok) if (stat == Ok)
{ {
memcpy(new_texture->transform, texture->transform, sizeof(GpMatrix)); new_texture->transform = texture->transform;
*clone = (GpBrush*)new_texture; *clone = (GpBrush*)new_texture;
} }
else else
@ -539,7 +532,6 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect* rect
static GpStatus create_path_gradient(GpPath *path, ARGB centercolor, GpPathGradient **grad) static GpStatus create_path_gradient(GpPath *path, ARGB centercolor, GpPathGradient **grad)
{ {
GpRectF bounds; GpRectF bounds;
GpStatus stat;
if(!path || !grad) if(!path || !grad)
return InvalidParameter; return InvalidParameter;
@ -555,18 +547,12 @@ static GpStatus create_path_gradient(GpPath *path, ARGB centercolor, GpPathGradi
return OutOfMemory; return OutOfMemory;
} }
stat = GdipCreateMatrix(&(*grad)->transform); GdipSetMatrixElements(&(*grad)->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
if (stat != Ok)
{
GdipFree(*grad);
return stat;
}
(*grad)->blendfac = GdipAlloc(sizeof(REAL)); (*grad)->blendfac = GdipAlloc(sizeof(REAL));
(*grad)->blendpos = GdipAlloc(sizeof(REAL)); (*grad)->blendpos = GdipAlloc(sizeof(REAL));
(*grad)->surroundcolors = GdipAlloc(sizeof(ARGB)); (*grad)->surroundcolors = GdipAlloc(sizeof(ARGB));
if(!(*grad)->blendfac || !(*grad)->blendpos || !(*grad)->surroundcolors){ if(!(*grad)->blendfac || !(*grad)->blendpos || !(*grad)->surroundcolors){
GdipDeleteMatrix((*grad)->transform);
GdipFree((*grad)->blendfac); GdipFree((*grad)->blendfac);
GdipFree((*grad)->blendpos); GdipFree((*grad)->blendpos);
GdipFree((*grad)->surroundcolors); GdipFree((*grad)->surroundcolors);
@ -819,9 +805,7 @@ GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
goto exit; goto exit;
} }
if((status = GdipCreateMatrix(&(*texture)->transform)) != Ok){ GdipSetMatrixElements(&(*texture)->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
goto exit;
}
if (imageattr) if (imageattr)
{ {
@ -848,7 +832,6 @@ exit:
{ {
if (*texture) if (*texture)
{ {
GdipDeleteMatrix((*texture)->transform);
GdipDisposeImageAttributes((*texture)->imageattributes); GdipDisposeImageAttributes((*texture)->imageattributes);
GdipFree(*texture); GdipFree(*texture);
*texture = NULL; *texture = NULL;
@ -947,7 +930,6 @@ GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
{ {
case BrushTypePathGradient: case BrushTypePathGradient:
GdipDeletePath(((GpPathGradient*) brush)->path); GdipDeletePath(((GpPathGradient*) brush)->path);
GdipDeleteMatrix(((GpPathGradient*) brush)->transform);
GdipFree(((GpPathGradient*) brush)->blendfac); GdipFree(((GpPathGradient*) brush)->blendfac);
GdipFree(((GpPathGradient*) brush)->blendpos); GdipFree(((GpPathGradient*) brush)->blendpos);
GdipFree(((GpPathGradient*) brush)->surroundcolors); GdipFree(((GpPathGradient*) brush)->surroundcolors);
@ -961,7 +943,6 @@ GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
GdipFree(((GpLineGradient*)brush)->pblendpos); GdipFree(((GpLineGradient*)brush)->pblendpos);
break; break;
case BrushTypeTextureFill: case BrushTypeTextureFill:
GdipDeleteMatrix(((GpTexture*)brush)->transform);
GdipDisposeImage(((GpTexture*)brush)->image); GdipDisposeImage(((GpTexture*)brush)->image);
GdipDisposeImageAttributes(((GpTexture*)brush)->imageattributes); GdipDisposeImageAttributes(((GpTexture*)brush)->imageattributes);
GdipFree(((GpTexture*)brush)->bitmap_bits); GdipFree(((GpTexture*)brush)->bitmap_bits);
@ -1059,8 +1040,8 @@ GpStatus WINGDIPAPI GdipGetPathGradientCenterPointI(GpPathGradient *grad,
ret = GdipGetPathGradientCenterPoint(grad,&ptf); ret = GdipGetPathGradientCenterPoint(grad,&ptf);
if(ret == Ok){ if(ret == Ok){
point->X = roundr(ptf.X); point->X = gdip_round(ptf.X);
point->Y = roundr(ptf.Y); point->Y = gdip_round(ptf.Y);
} }
return ret; return ret;
@ -1158,10 +1139,10 @@ GpStatus WINGDIPAPI GdipGetPathGradientRectI(GpPathGradient *brush, GpRect *rect
stat = GdipGetPathGradientRect(brush, &rectf); stat = GdipGetPathGradientRect(brush, &rectf);
if(stat != Ok) return stat; if(stat != Ok) return stat;
rect->X = roundr(rectf.X); rect->X = gdip_round(rectf.X);
rect->Y = roundr(rectf.Y); rect->Y = gdip_round(rectf.Y);
rect->Width = roundr(rectf.Width); rect->Width = gdip_round(rectf.Width);
rect->Height = roundr(rectf.Height); rect->Height = gdip_round(rectf.Height);
return Ok; return Ok;
} }
@ -1253,7 +1234,7 @@ GpStatus WINGDIPAPI GdipGetTextureTransform(GpTexture *brush, GpMatrix *matrix)
if(!brush || !matrix) if(!brush || !matrix)
return InvalidParameter; return InvalidParameter;
memcpy(matrix, brush->transform, sizeof(GpMatrix)); *matrix = brush->transform;
return Ok; return Ok;
} }
@ -1284,7 +1265,7 @@ GpStatus WINGDIPAPI GdipMultiplyTextureTransform(GpTexture* brush,
if(!brush || !matrix) if(!brush || !matrix)
return InvalidParameter; return InvalidParameter;
return GdipMultiplyMatrix(brush->transform, matrix, order); return GdipMultiplyMatrix(&brush->transform, matrix, order);
} }
/****************************************************************************** /******************************************************************************
@ -1297,7 +1278,7 @@ GpStatus WINGDIPAPI GdipResetTextureTransform(GpTexture* brush)
if(!brush) if(!brush)
return InvalidParameter; return InvalidParameter;
return GdipSetMatrixElements(brush->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); return GdipSetMatrixElements(&brush->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
} }
/****************************************************************************** /******************************************************************************
@ -1311,7 +1292,7 @@ GpStatus WINGDIPAPI GdipScaleTextureTransform(GpTexture* brush,
if(!brush) if(!brush)
return InvalidParameter; return InvalidParameter;
return GdipScaleMatrix(brush->transform, sx, sy, order); return GdipScaleMatrix(&brush->transform, sx, sy, order);
} }
GpStatus WINGDIPAPI GdipSetLineBlend(GpLineGradient *brush, GpStatus WINGDIPAPI GdipSetLineBlend(GpLineGradient *brush,
@ -1785,7 +1766,7 @@ GpStatus WINGDIPAPI GdipSetPathGradientTransform(GpPathGradient *grad,
if (!grad || !matrix) if (!grad || !matrix)
return InvalidParameter; return InvalidParameter;
memcpy(grad->transform, matrix, sizeof(GpMatrix)); grad->transform = *matrix;
return Ok; return Ok;
} }
@ -1798,7 +1779,7 @@ GpStatus WINGDIPAPI GdipGetPathGradientTransform(GpPathGradient *grad,
if (!grad || !matrix) if (!grad || !matrix)
return InvalidParameter; return InvalidParameter;
memcpy(matrix, grad->transform, sizeof(GpMatrix)); *matrix = grad->transform;
return Ok; return Ok;
} }
@ -1811,7 +1792,7 @@ GpStatus WINGDIPAPI GdipMultiplyPathGradientTransform(GpPathGradient *grad,
if (!grad) if (!grad)
return InvalidParameter; return InvalidParameter;
return GdipMultiplyMatrix(grad->transform, matrix, order); return GdipMultiplyMatrix(&grad->transform, matrix, order);
} }
GpStatus WINGDIPAPI GdipResetPathGradientTransform(GpPathGradient *grad) GpStatus WINGDIPAPI GdipResetPathGradientTransform(GpPathGradient *grad)
@ -1821,7 +1802,7 @@ GpStatus WINGDIPAPI GdipResetPathGradientTransform(GpPathGradient *grad)
if (!grad) if (!grad)
return InvalidParameter; return InvalidParameter;
return GdipSetMatrixElements(grad->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); return GdipSetMatrixElements(&grad->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
} }
GpStatus WINGDIPAPI GdipRotatePathGradientTransform(GpPathGradient *grad, GpStatus WINGDIPAPI GdipRotatePathGradientTransform(GpPathGradient *grad,
@ -1832,7 +1813,7 @@ GpStatus WINGDIPAPI GdipRotatePathGradientTransform(GpPathGradient *grad,
if (!grad) if (!grad)
return InvalidParameter; return InvalidParameter;
return GdipRotateMatrix(grad->transform, angle, order); return GdipRotateMatrix(&grad->transform, angle, order);
} }
GpStatus WINGDIPAPI GdipScalePathGradientTransform(GpPathGradient *grad, GpStatus WINGDIPAPI GdipScalePathGradientTransform(GpPathGradient *grad,
@ -1843,7 +1824,7 @@ GpStatus WINGDIPAPI GdipScalePathGradientTransform(GpPathGradient *grad,
if (!grad) if (!grad)
return InvalidParameter; return InvalidParameter;
return GdipScaleMatrix(grad->transform, sx, sy, order); return GdipScaleMatrix(&grad->transform, sx, sy, order);
} }
GpStatus WINGDIPAPI GdipTranslatePathGradientTransform(GpPathGradient *grad, GpStatus WINGDIPAPI GdipTranslatePathGradientTransform(GpPathGradient *grad,
@ -1854,7 +1835,7 @@ GpStatus WINGDIPAPI GdipTranslatePathGradientTransform(GpPathGradient *grad,
if (!grad) if (!grad)
return InvalidParameter; return InvalidParameter;
return GdipTranslateMatrix(grad->transform, dx, dy, order); return GdipTranslateMatrix(&grad->transform, dx, dy, order);
} }
GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb) GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb)
@ -1879,7 +1860,7 @@ GpStatus WINGDIPAPI GdipSetTextureTransform(GpTexture *texture,
if(!texture || !matrix) if(!texture || !matrix)
return InvalidParameter; return InvalidParameter;
memcpy(texture->transform, matrix, sizeof(GpMatrix)); texture->transform = *matrix;
return Ok; return Ok;
} }
@ -1939,7 +1920,7 @@ GpStatus WINGDIPAPI GdipRotateTextureTransform(GpTexture* brush, REAL angle,
if(!brush) if(!brush)
return InvalidParameter; return InvalidParameter;
return GdipRotateMatrix(brush->transform, angle, order); return GdipRotateMatrix(&brush->transform, angle, order);
} }
GpStatus WINGDIPAPI GdipSetLineLinearBlend(GpLineGradient *brush, REAL focus, GpStatus WINGDIPAPI GdipSetLineLinearBlend(GpLineGradient *brush, REAL focus,
@ -2125,7 +2106,7 @@ GpStatus WINGDIPAPI GdipTranslateTextureTransform(GpTexture* brush, REAL dx, REA
if(!brush) if(!brush)
return InvalidParameter; return InvalidParameter;
return GdipTranslateMatrix(brush->transform, dx, dy, order); return GdipTranslateMatrix(&brush->transform, dx, dy, order);
} }
GpStatus WINGDIPAPI GdipGetLineRect(GpLineGradient *brush, GpRectF *rect) GpStatus WINGDIPAPI GdipGetLineRect(GpLineGradient *brush, GpRectF *rect)
@ -2153,10 +2134,10 @@ GpStatus WINGDIPAPI GdipGetLineRectI(GpLineGradient *brush, GpRect *rect)
ret = GdipGetLineRect(brush, &rectF); ret = GdipGetLineRect(brush, &rectF);
if(ret == Ok){ if(ret == Ok){
rect->X = roundr(rectF.X); rect->X = gdip_round(rectF.X);
rect->Y = roundr(rectF.Y); rect->Y = gdip_round(rectF.Y);
rect->Width = roundr(rectF.Width); rect->Width = gdip_round(rectF.Width);
rect->Height = roundr(rectF.Height); rect->Height = gdip_round(rectF.Height);
} }
return ret; return ret;

View file

@ -116,41 +116,10 @@ typedef struct
#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2') #define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
#define MS_HHEA_TAG MS_MAKE_TAG('h','h','e','a') #define MS_HHEA_TAG MS_MAKE_TAG('h','h','e','a')
static const REAL mm_per_inch = 25.4; static GpStatus clone_font_family(const GpFontFamily *, GpFontFamily **);
static const REAL inch_per_point = 1.0/72.0;
static GpFontCollection installedFontCollection = {0}; static GpFontCollection installedFontCollection = {0};
static LONG em_size_to_pixel(REAL em_size, Unit unit, LONG dpi)
{
switch (unit)
{
default:
FIXME("Unhandled unit type: %d\n", unit);
return 0;
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;
}
}
/******************************************************************************* /*******************************************************************************
* GdipCreateFont [GDIPLUS.@] * GdipCreateFont [GDIPLUS.@]
* *
@ -193,7 +162,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL); stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL);
if (stat != Ok) return stat; if (stat != Ok) return stat;
lfw.lfHeight = -em_size_to_pixel(emSize, unit, fontFamily->dpi); lfw.lfHeight = -units_to_pixels(emSize, unit, fontFamily->dpi);
lfw.lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR; lfw.lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR;
lfw.lfItalic = style & FontStyleItalic; lfw.lfItalic = style & FontStyleItalic;
lfw.lfUnderline = style & FontStyleUnderline; lfw.lfUnderline = style & FontStyleUnderline;
@ -216,7 +185,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
(*font)->emSize = emSize; (*font)->emSize = emSize;
(*font)->otm = otm; (*font)->otm = otm;
stat = GdipCloneFontFamily((GpFontFamily *)fontFamily, &(*font)->family); stat = clone_font_family(fontFamily, &(*font)->family);
if (stat != Ok) if (stat != Ok)
{ {
GdipFree(*font); GdipFree(*font);
@ -236,6 +205,7 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
{ {
HFONT hfont, oldfont; HFONT hfont, oldfont;
OUTLINETEXTMETRICW otm; OUTLINETEXTMETRICW otm;
WCHAR facename[LF_FACESIZE];
GpStatus stat; GpStatus stat;
int ret; int ret;
@ -248,6 +218,7 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
oldfont = SelectObject(hdc, hfont); oldfont = SelectObject(hdc, hfont);
otm.otmSize = sizeof(otm); otm.otmSize = sizeof(otm);
ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm); ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
GetTextFaceW(hdc, LF_FACESIZE, facename);
SelectObject(hdc, oldfont); SelectObject(hdc, oldfont);
DeleteObject(hfont); DeleteObject(hfont);
@ -260,7 +231,7 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
(*font)->emSize = otm.otmTextMetrics.tmAscent; (*font)->emSize = otm.otmTextMetrics.tmAscent;
(*font)->otm = otm; (*font)->otm = otm;
stat = GdipCreateFontFamilyFromName(logfont->lfFaceName, NULL, &(*font)->family); stat = GdipCreateFontFamilyFromName(facename, NULL, &(*font)->family);
if (stat != Ok) if (stat != Ok)
{ {
GdipFree(*font); GdipFree(*font);
@ -355,6 +326,11 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
return GdipCloneFontFamily(font->family, family); return GdipCloneFontFamily(font->family, family);
} }
static REAL get_font_size(const GpFont *font)
{
return font->emSize;
}
/****************************************************************************** /******************************************************************************
* GdipGetFontSize [GDIPLUS.@] * GdipGetFontSize [GDIPLUS.@]
* *
@ -377,12 +353,30 @@ GpStatus WINGDIPAPI GdipGetFontSize(GpFont *font, REAL *size)
if (!(font && size)) return InvalidParameter; if (!(font && size)) return InvalidParameter;
*size = font->emSize; *size = get_font_size(font);
TRACE("%s,%d => %f\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *size); TRACE("%s,%d => %f\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *size);
return Ok; return Ok;
} }
static INT get_font_style(const GpFont *font)
{
INT style;
if (font->otm.otmTextMetrics.tmWeight > FW_REGULAR)
style = FontStyleBold;
else
style = FontStyleRegular;
if (font->otm.otmTextMetrics.tmItalic)
style |= FontStyleItalic;
if (font->otm.otmTextMetrics.tmUnderlined)
style |= FontStyleUnderline;
if (font->otm.otmTextMetrics.tmStruckOut)
style |= FontStyleStrikeout;
return style;
}
/******************************************************************************* /*******************************************************************************
* GdipGetFontStyle [GDIPLUS.@] * GdipGetFontStyle [GDIPLUS.@]
* *
@ -403,16 +397,8 @@ GpStatus WINGDIPAPI GdipGetFontStyle(GpFont *font, INT *style)
if (!(font && style)) if (!(font && style))
return InvalidParameter; return InvalidParameter;
if (font->otm.otmTextMetrics.tmWeight > FW_REGULAR) *style = get_font_style(font);
*style = FontStyleBold; TRACE("%s,%d => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *style);
else
*style = FontStyleRegular;
if (font->otm.otmTextMetrics.tmItalic)
*style |= FontStyleItalic;
if (font->otm.otmTextMetrics.tmUnderlined)
*style |= FontStyleUnderline;
if (font->otm.otmTextMetrics.tmStruckOut)
*style |= FontStyleStrikeout;
return Ok; return Ok;
} }
@ -466,31 +452,64 @@ GpStatus WINGDIPAPI GdipGetLogFontA(GpFont *font, GpGraphics *graphics,
/******************************************************************************* /*******************************************************************************
* GdipGetLogFontW [GDIPLUS.@] * GdipGetLogFontW [GDIPLUS.@]
*/ */
GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW *lf)
LOGFONTW *lfw)
{ {
TRACE("(%p, %p, %p)\n", font, graphics, lfw); REAL angle, rel_height, height;
GpMatrix matrix;
GpPointF pt[3];
/* FIXME: use graphics */ TRACE("(%p, %p, %p)\n", font, graphics, lf);
if(!font || !graphics || !lfw)
if (!font || !graphics || !lf)
return InvalidParameter; return InvalidParameter;
lfw->lfHeight = -font->otm.otmTextMetrics.tmAscent; matrix = graphics->worldtrans;
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); if (font->unit == UnitPixel)
{
height = units_to_pixels(font->emSize, graphics->unit, graphics->yres);
if (graphics->unit != UnitDisplay)
GdipScaleMatrix(&matrix, graphics->scale, graphics->scale, MatrixOrderAppend);
}
else
{
if (graphics->unit == UnitDisplay || graphics->unit == UnitPixel)
height = units_to_pixels(font->emSize, font->unit, graphics->xres);
else
height = units_to_pixels(font->emSize, font->unit, graphics->yres);
}
pt[0].X = 0.0;
pt[0].Y = 0.0;
pt[1].X = 1.0;
pt[1].Y = 0.0;
pt[2].X = 0.0;
pt[2].Y = 1.0;
GdipTransformMatrixPoints(&matrix, pt, 3);
angle = -gdiplus_atan2((pt[1].Y - pt[0].Y), (pt[1].X - pt[0].X));
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));
lf->lfHeight = -gdip_round(height * rel_height);
lf->lfWidth = 0;
lf->lfEscapement = lf->lfOrientation = gdip_round((angle / M_PI) * 1800.0);
if (lf->lfEscapement < 0)
{
lf->lfEscapement += 3600;
lf->lfOrientation += 3600;
}
lf->lfWeight = font->otm.otmTextMetrics.tmWeight;
lf->lfItalic = font->otm.otmTextMetrics.tmItalic ? 1 : 0;
lf->lfUnderline = font->otm.otmTextMetrics.tmUnderlined ? 1 : 0;
lf->lfStrikeOut = font->otm.otmTextMetrics.tmStruckOut ? 1 : 0;
lf->lfCharSet = font->otm.otmTextMetrics.tmCharSet;
lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf->lfQuality = DEFAULT_QUALITY;
lf->lfPitchAndFamily = 0;
strcpyW(lf->lfFaceName, font->family->FamilyName);
TRACE("=> %s,%d\n", debugstr_w(lf->lfFaceName), lf->lfHeight);
return Ok; return Ok;
} }
@ -535,18 +554,29 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
{ {
REAL dpi; REAL dpi;
GpStatus stat; GpStatus stat;
REAL font_height;
TRACE("%p %p %p\n", font, graphics, height); TRACE("%p %p %p\n", font, graphics, height);
if (graphics) stat = GdipGetFontHeightGivenDPI(font, font->family->dpi, &font_height);
{ if (stat != Ok) return stat;
stat = GdipGetDpiY((GpGraphics*)graphics, &dpi);
if (stat != Ok) return stat;
}
else
dpi = font->family->dpi;
return GdipGetFontHeightGivenDPI(font, dpi, height); if (!graphics)
{
*height = font_height;
TRACE("%s,%d => %f\n",
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *height);
return Ok;
}
stat = GdipGetDpiY((GpGraphics *)graphics, &dpi);
if (stat != Ok) return stat;
*height = pixels_to_units(font_height, graphics->unit, dpi);
TRACE("%s,%d(unit %d) => %f\n",
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, graphics->unit, *height);
return Ok;
} }
/******************************************************************************* /*******************************************************************************
@ -569,49 +599,24 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
GpStatus stat; GpStatus stat;
INT style; INT style;
UINT16 line_spacing, em_height; UINT16 line_spacing, em_height;
REAL font_height, font_size; REAL font_size;
if (!font || !height) return InvalidParameter; if (!font || !height) return InvalidParameter;
TRACE("%p (%s), %f, %p\n", font, TRACE("%p (%s), %f, %p\n", font,
debugstr_w(font->family->FamilyName), dpi, height); debugstr_w(font->family->FamilyName), dpi, height);
stat = GdipGetFontSize((GpFont *)font, &font_size); font_size = units_to_pixels(get_font_size(font), font->unit, dpi);
if (stat != Ok) return stat; style = get_font_style(font);
stat = GdipGetFontStyle((GpFont *)font, &style);
if (stat != Ok) return stat;
stat = GdipGetLineSpacing(font->family, style, &line_spacing); stat = GdipGetLineSpacing(font->family, style, &line_spacing);
if (stat != Ok) return stat; if (stat != Ok) return stat;
stat = GdipGetEmHeight(font->family, style, &em_height); stat = GdipGetEmHeight(font->family, style, &em_height);
if (stat != Ok) return stat; if (stat != Ok) return stat;
font_height = (REAL)line_spacing * font_size / (REAL)em_height; *height = (REAL)line_spacing * font_size / (REAL)em_height;
switch (font->unit) TRACE("%s,%d => %f\n",
{ debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *height);
case UnitPixel:
case UnitWorld:
*height = font_height;
break;
case UnitPoint:
*height = font_height * dpi * inch_per_point;
break;
case UnitInch:
*height = font_height * dpi;
break;
case UnitDocument:
*height = font_height * (dpi / 300.0);
break;
case UnitMillimeter:
*height = font_height * (dpi / mm_per_inch);
break;
default:
FIXME("Unhandled unit type: %d\n", font->unit);
return NotImplemented;
}
TRACE("%s,%d(unit %d) => %f\n",
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, font->unit, *height);
return Ok; return Ok;
} }
@ -625,7 +630,7 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf, static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf,
const TEXTMETRICW *ntm, DWORD type, LPARAM lParam) const TEXTMETRICW *ntm, DWORD type, LPARAM lParam)
{ {
if (type != TRUETYPE_FONTTYPE) if (type & RASTER_FONTTYPE)
return 1; return 1;
*(LOGFONTW *)lParam = *elf; *(LOGFONTW *)lParam = *elf;
@ -635,6 +640,7 @@ static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf,
struct font_metrics struct font_metrics
{ {
WCHAR facename[LF_FACESIZE];
UINT16 em_height, ascent, descent, line_spacing; /* in font units */ UINT16 em_height, ascent, descent, line_spacing; /* in font units */
int dpi; int dpi;
}; };
@ -650,6 +656,8 @@ static BOOL get_font_metrics(HDC hdc, struct font_metrics *fm)
otm.otmSize = sizeof(otm); otm.otmSize = sizeof(otm);
if (!GetOutlineTextMetricsW(hdc, otm.otmSize, &otm)) return FALSE; if (!GetOutlineTextMetricsW(hdc, otm.otmSize, &otm)) return FALSE;
GetTextFaceW(hdc, LF_FACESIZE, fm->facename);
fm->em_height = otm.otmEMSquare; fm->em_height = otm.otmEMSquare;
fm->dpi = GetDeviceCaps(hdc, LOGPIXELSY); fm->dpi = GetDeviceCaps(hdc, LOGPIXELSY);
@ -750,7 +758,7 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
ffamily = GdipAlloc(sizeof (GpFontFamily)); ffamily = GdipAlloc(sizeof (GpFontFamily));
if (!ffamily) return OutOfMemory; if (!ffamily) return OutOfMemory;
lstrcpynW(ffamily->FamilyName, name, LF_FACESIZE); lstrcpyW(ffamily->FamilyName, fm.facename);
ffamily->em_height = fm.em_height; ffamily->em_height = fm.em_height;
ffamily->ascent = fm.ascent; ffamily->ascent = fm.ascent;
ffamily->descent = fm.descent; ffamily->descent = fm.descent;
@ -764,6 +772,16 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
return Ok; return Ok;
} }
static GpStatus clone_font_family(const GpFontFamily *family, GpFontFamily **clone)
{
*clone = GdipAlloc(sizeof(GpFontFamily));
if (!*clone) return OutOfMemory;
**clone = *family;
return Ok;
}
/******************************************************************************* /*******************************************************************************
* GdipCloneFontFamily [GDIPLUS.@] * GdipCloneFontFamily [GDIPLUS.@]
* *
@ -778,16 +796,15 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
*/ */
GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily** clonedFontFamily) GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily** clonedFontFamily)
{ {
GpStatus status;
if (!(FontFamily && clonedFontFamily)) return InvalidParameter; if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
TRACE("%p (%s), %p\n", FontFamily, TRACE("%p (%s), %p\n", FontFamily,
debugstr_w(FontFamily->FamilyName), clonedFontFamily); debugstr_w(FontFamily->FamilyName), clonedFontFamily);
*clonedFontFamily = GdipAlloc(sizeof(GpFontFamily)); status = clone_font_family(FontFamily, clonedFontFamily);
if (!*clonedFontFamily) return OutOfMemory; if (status != Ok) return status;
**clonedFontFamily = *FontFamily;
lstrcpyW((*clonedFontFamily)->FamilyName, FontFamily->FamilyName);
TRACE("<-- %p\n", *clonedFontFamily); TRACE("<-- %p\n", *clonedFontFamily);

View file

@ -35,6 +35,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
static const REAL mm_per_inch = 25.4;
static const REAL point_per_inch = 72.0;
static Status WINAPI NotificationHook(ULONG_PTR *token) static Status WINAPI NotificationHook(ULONG_PTR *token)
{ {
TRACE("%p\n", token); TRACE("%p\n", token);
@ -207,7 +210,7 @@ static void unstretch_angle(REAL * angle, REAL rad_x, REAL rad_y)
return; return;
stretched = gdiplus_atan2(sin(*angle) / fabs(rad_y), cos(*angle) / fabs(rad_x)); stretched = gdiplus_atan2(sin(*angle) / fabs(rad_y), cos(*angle) / fabs(rad_x));
revs_off = roundr(*angle / (2.0 * M_PI)) - roundr(stretched / (2.0 * M_PI)); revs_off = gdip_round(*angle / (2.0 * M_PI)) - gdip_round(stretched / (2.0 * M_PI));
stretched += ((REAL)revs_off) * M_PI * 2.0; stretched += ((REAL)revs_off) * M_PI * 2.0;
*angle = stretched; *angle = stretched;
} }
@ -318,28 +321,57 @@ GpStatus hresult_to_status(HRESULT res)
} }
/* converts a given unit to its value in pixels */ /* converts a given unit to its value in pixels */
REAL convert_unit(REAL logpixels, GpUnit unit) REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
{ {
switch(unit) switch (unit)
{ {
case UnitInch: case UnitPixel:
return logpixels; case UnitWorld:
case UnitPoint: case UnitDisplay:
return logpixels / 72.0; return units;
case UnitDocument: case UnitPoint:
return logpixels / 300.0; return units * dpi / point_per_inch;
case UnitMillimeter: case UnitInch:
return logpixels / 25.4; return units * dpi;
case UnitWorld: case UnitDocument:
ERR("cannot convert UnitWorld\n"); return units * dpi / 300.0; /* Per MSDN */
return 0.0; case UnitMillimeter:
case UnitPixel: return units * dpi / mm_per_inch;
case UnitDisplay: default:
default: FIXME("Unhandled unit type: %d\n", unit);
return 1.0; return 0;
} }
} }
/* converts value in pixels to a given unit */
REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi)
{
switch (unit)
{
case UnitPixel:
case UnitWorld:
case UnitDisplay:
return pixels;
case UnitPoint:
return pixels * point_per_inch / dpi;
case UnitInch:
return pixels / dpi;
case UnitDocument:
return pixels * 300.0 / dpi;
case UnitMillimeter:
return pixels * mm_per_inch / dpi;
default:
FIXME("Unhandled unit type: %d\n", unit);
return 0;
}
}
REAL units_scale(GpUnit from, GpUnit to, REAL dpi)
{
REAL pixels = units_to_pixels(1.0, from, dpi);
return pixels_to_units(pixels, to, dpi);
}
/* Calculates Bezier points from cardinal spline points. */ /* Calculates Bezier points from cardinal spline points. */
void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1, void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
REAL *y1, REAL *x2, REAL *y2) REAL *y1, REAL *x2, REAL *y2)
@ -362,8 +394,8 @@ void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
REAL tension, REAL *x, REAL *y) REAL tension, REAL *x, REAL *y)
{ {
/* tangent at endpoints is the line from the endpoint to the adjacent point */ /* tangent at endpoints is the line from the endpoint to the adjacent point */
*x = roundr(tension * (xadj - xend) + xend); *x = gdip_round(tension * (xadj - xend) + xend);
*y = roundr(tension * (yadj - yend) + yend); *y = gdip_round(tension * (yadj - yend) + yend);
} }
/* make sure path has enough space for len more points */ /* make sure path has enough space for len more points */

View file

@ -471,10 +471,10 @@
471 stdcall GdipRotatePenTransform(ptr float long) 471 stdcall GdipRotatePenTransform(ptr float long)
472 stdcall GdipRotateTextureTransform(ptr float long) 472 stdcall GdipRotateTextureTransform(ptr float long)
473 stdcall GdipRotateWorldTransform(ptr float long) 473 stdcall GdipRotateWorldTransform(ptr float long)
474 stub GdipSaveAdd 474 stdcall GdipSaveAdd(ptr ptr)
475 stub GdipSaveAddImage 475 stub GdipSaveAddImage
476 stdcall GdipSaveGraphics(ptr ptr) 476 stdcall GdipSaveGraphics(ptr ptr)
477 stdcall GdipSaveImageToFile(ptr ptr ptr ptr) 477 stdcall GdipSaveImageToFile(ptr wstr ptr ptr)
478 stdcall GdipSaveImageToStream(ptr ptr ptr ptr) 478 stdcall GdipSaveImageToStream(ptr ptr ptr ptr)
479 stdcall GdipScaleLineTransform(ptr float float long) 479 stdcall GdipScaleLineTransform(ptr float float long)
480 stdcall GdipScaleMatrix(ptr float float long) 480 stdcall GdipScaleMatrix(ptr float float long)

View file

@ -29,6 +29,7 @@
#include "objbase.h" #include "objbase.h"
#include "ocidl.h" #include "ocidl.h"
#include "wincodecsdk.h"
#include "wine/list.h" #include "wine/list.h"
#include "gdiplus.h" #include "gdiplus.h"
@ -47,7 +48,9 @@ extern INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2,
REAL startAngle, REAL sweepAngle) DECLSPEC_HIDDEN; REAL startAngle, REAL sweepAngle) DECLSPEC_HIDDEN;
extern REAL gdiplus_atan2(REAL dy, REAL dx) DECLSPEC_HIDDEN; extern REAL gdiplus_atan2(REAL dy, REAL dx) DECLSPEC_HIDDEN;
extern GpStatus hresult_to_status(HRESULT res) DECLSPEC_HIDDEN; extern GpStatus hresult_to_status(HRESULT res) DECLSPEC_HIDDEN;
extern REAL convert_unit(REAL logpixels, GpUnit unit) DECLSPEC_HIDDEN; extern REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN;
extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN;
extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi) DECLSPEC_HIDDEN;
extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN; extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN;
@ -55,6 +58,7 @@ extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **r
extern GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN;
extern MetafileType METAFILE_GetEmfType(HENHMETAFILE hemf) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1, extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN; REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN;
@ -63,8 +67,6 @@ extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
extern void free_installed_fonts(void) DECLSPEC_HIDDEN; extern void free_installed_fonts(void) DECLSPEC_HIDDEN;
extern void get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font, HFONT *hfont) DECLSPEC_HIDDEN;
extern BOOL lengthen_path(GpPath *path, INT len) DECLSPEC_HIDDEN; extern BOOL lengthen_path(GpPath *path, INT len) DECLSPEC_HIDDEN;
extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN; extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN;
@ -74,7 +76,7 @@ extern void delete_element(region_element *element) DECLSPEC_HIDDEN;
extern GpStatus get_hatch_data(HatchStyle hatchstyle, const char **result) DECLSPEC_HIDDEN; extern GpStatus get_hatch_data(HatchStyle hatchstyle, const char **result) DECLSPEC_HIDDEN;
static inline INT roundr(REAL x) static inline INT gdip_round(REAL x)
{ {
return (INT) floorf(x + 0.5); return (INT) floorf(x + 0.5);
} }
@ -121,7 +123,11 @@ extern void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height,
extern GpStatus convert_pixels(INT width, INT height, extern GpStatus convert_pixels(INT width, INT height,
INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, INT dst_stride, BYTE *dst_bits, PixelFormat dst_format,
INT src_stride, const BYTE *src_bits, PixelFormat src_format, ARGB *src_palette) DECLSPEC_HIDDEN; INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *palette) DECLSPEC_HIDDEN;
struct GpMatrix{
REAL matrix[6];
};
struct GpPen{ struct GpPen{
UINT style; UINT style;
@ -146,6 +152,7 @@ struct GpGraphics{
HDC hdc; HDC hdc;
HWND hwnd; HWND hwnd;
BOOL owndc; BOOL owndc;
BOOL alpha_hdc;
GpImage *image; GpImage *image;
SmoothingMode smoothing; SmoothingMode smoothing;
CompositingQuality compqual; CompositingQuality compqual;
@ -155,7 +162,8 @@ struct GpGraphics{
TextRenderingHint texthint; TextRenderingHint texthint;
GpUnit unit; /* page unit */ GpUnit unit; /* page unit */
REAL scale; /* page scale */ REAL scale; /* page scale */
GpMatrix * worldtrans; /* world transform */ REAL xres, yres;
GpMatrix worldtrans; /* world transform */
BOOL busy; /* hdc handle obtained by GdipGetDC */ BOOL busy; /* hdc handle obtained by GdipGetDC */
GpRegion *clip; GpRegion *clip;
UINT textcontrast; /* not used yet. get/set only */ UINT textcontrast; /* not used yet. get/set only */
@ -202,7 +210,7 @@ struct GpPathGradient{
ARGB* pblendcolor; /* preset blend colors */ ARGB* pblendcolor; /* preset blend colors */
REAL* pblendpos; /* preset blend positions */ REAL* pblendpos; /* preset blend positions */
INT pblendcount; INT pblendcount;
GpMatrix *transform; GpMatrix transform;
}; };
struct GpLineGradient{ struct GpLineGradient{
@ -224,7 +232,7 @@ struct GpLineGradient{
struct GpTexture{ struct GpTexture{
GpBrush brush; GpBrush brush;
GpMatrix *transform; GpMatrix transform;
GpImage *image; GpImage *image;
GpImageAttributes *imageattributes; GpImageAttributes *imageattributes;
BYTE *bitmap_bits; /* image bits converted to ARGB and run through imageattributes */ BYTE *bitmap_bits; /* image bits converted to ARGB and run through imageattributes */
@ -237,10 +245,6 @@ struct GpPath{
INT datalen; /* size of the arrays in pathdata */ INT datalen; /* size of the arrays in pathdata */
}; };
struct GpMatrix{
REAL matrix[6];
};
struct GpPathIterator{ struct GpPathIterator{
GpPathData pathdata; GpPathData pathdata;
INT subpath_pos; /* for NextSubpath methods */ INT subpath_pos; /* for NextSubpath methods */
@ -262,14 +266,13 @@ struct GpAdustableArrowCap{
}; };
struct GpImage{ struct GpImage{
IPicture* picture; IPicture *picture;
IStream *stream; /* source stream */
ImageType type; ImageType type;
GUID format; GUID format;
UINT flags; UINT flags;
UINT palette_flags; UINT frame_count, current_frame;
UINT palette_count; ColorPalette *palette;
UINT palette_size;
ARGB *palette_entries;
REAL xres, yres; REAL xres, yres;
}; };
@ -279,6 +282,7 @@ struct GpMetafile{
GpUnit unit; GpUnit unit;
MetafileType metafile_type; MetafileType metafile_type;
HENHMETAFILE hemf; HENHMETAFILE hemf;
int preserve_hemf; /* if true, hemf belongs to the app and should not be deleted */
/* recording */ /* recording */
HDC record_dc; HDC record_dc;
@ -309,6 +313,9 @@ struct GpBitmap{
INT stride; /* stride of bits if this is a DIB */ INT stride; /* stride of bits if this is a DIB */
BYTE *own_bits; /* image bits that need to be freed with this object */ BYTE *own_bits; /* image bits that need to be freed with this object */
INT lockx, locky; /* X and Y coordinates of the rect when a bitmap is locked for writing. */ INT lockx, locky; /* X and Y coordinates of the rect when a bitmap is locked for writing. */
IWICMetadataReader *metadata_reader; /* NULL if there is no metadata */
UINT prop_count;
PropertyItem *prop_item; /* cached image properties */
}; };
struct GpCachedBitmap{ struct GpCachedBitmap{
@ -366,6 +373,7 @@ struct GpStringFormat{
REAL *tabs; REAL *tabs;
CharacterRange *character_ranges; CharacterRange *character_ranges;
INT range_count; INT range_count;
BOOL generic_typographic;
}; };
struct GpFontCollection{ struct GpFontCollection{
@ -436,4 +444,6 @@ GpStatus gdip_format_string(HDC hdc,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format, GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
gdip_format_string_callback callback, void *user_data) DECLSPEC_HIDDEN; gdip_format_string_callback callback, void *user_data) DECLSPEC_HIDDEN;
void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN;
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -155,7 +155,7 @@ static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, R
if(!(node = add_path_list_node(start, mp[2].X, mp[2].Y, PathPointTypeLine))) if(!(node = add_path_list_node(start, mp[2].X, mp[2].Y, PathPointTypeLine)))
return FALSE; return FALSE;
/* do the same with halfs */ /* do the same with halves */
flatten_bezier(start, mp[0].X, mp[0].Y, mp[1].X, mp[1].Y, node, flatness); flatten_bezier(start, mp[0].X, mp[0].Y, mp[1].X, mp[1].Y, node, flatness);
flatten_bezier(node, mp[3].X, mp[3].Y, mp[4].X, mp[4].Y, end, flatness); flatten_bezier(node, mp[3].X, mp[3].Y, mp[4].X, mp[4].Y, end, flatness);
@ -840,7 +840,9 @@ static float fromfixedpoint(const FIXED v)
struct format_string_args struct format_string_args
{ {
GpPath *path; GpPath *path;
UINT maxY; float maxY;
float scale;
float ascent;
}; };
static GpStatus format_string_callback(HDC dc, static GpStatus format_string_callback(HDC dc,
@ -853,20 +855,22 @@ static GpStatus format_string_callback(HDC dc,
struct format_string_args *args = priv; struct format_string_args *args = priv;
GpPath *path = args->path; GpPath *path = args->path;
GpStatus status = Ok; GpStatus status = Ok;
float x = bounds->X; float x = rect->X + (bounds->X - rect->X) * args->scale;
float y = bounds->Y; float y = rect->Y + (bounds->Y - rect->Y) * args->scale;
int i; int i;
if (underlined_index_count) if (underlined_index_count)
FIXME("hotkey underlines not drawn yet\n"); FIXME("hotkey underlines not drawn yet\n");
if (y + bounds->Height * args->scale > args->maxY)
args->maxY = y + bounds->Height * args->scale;
for (i = index; i < length; ++i) for (i = index; i < length; ++i)
{ {
GLYPHMETRICS gm; GLYPHMETRICS gm;
TTPOLYGONHEADER *ph = NULL; TTPOLYGONHEADER *ph = NULL;
char *start; char *start;
DWORD len, ofs = 0; DWORD len, ofs = 0;
UINT bb_end;
len = GetGlyphOutlineW(dc, string[i], GGO_BEZIER, &gm, 0, NULL, &identity); len = GetGlyphOutlineW(dc, string[i], GGO_BEZIER, &gm, 0, NULL, &identity);
if (len == GDI_ERROR) if (len == GDI_ERROR)
{ {
@ -881,9 +885,6 @@ static GpStatus format_string_callback(HDC dc,
break; break;
} }
GetGlyphOutlineW(dc, string[i], GGO_BEZIER, &gm, len, start, &identity); GetGlyphOutlineW(dc, string[i], GGO_BEZIER, &gm, len, start, &identity);
bb_end = gm.gmBlackBoxY + gm.gmptGlyphOrigin.y;
if (bb_end + y > args->maxY)
args->maxY = bb_end + y;
ofs = 0; ofs = 0;
while (ofs < len) while (ofs < len)
@ -891,8 +892,8 @@ static GpStatus format_string_callback(HDC dc,
DWORD ofs_start = ofs; DWORD ofs_start = ofs;
ph = (TTPOLYGONHEADER*)&start[ofs]; ph = (TTPOLYGONHEADER*)&start[ofs];
path->pathdata.Types[path->pathdata.Count] = PathPointTypeStart; path->pathdata.Types[path->pathdata.Count] = PathPointTypeStart;
path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(ph->pfxStart.x); path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(ph->pfxStart.x) * args->scale;
path->pathdata.Points[path->pathdata.Count++].Y = y + bb_end - fromfixedpoint(ph->pfxStart.y); path->pathdata.Points[path->pathdata.Count++].Y = y + args->ascent - fromfixedpoint(ph->pfxStart.y) * args->scale;
TRACE("Starting at count %i with pos %f, %f)\n", path->pathdata.Count, x, y); TRACE("Starting at count %i with pos %f, %f)\n", path->pathdata.Count, x, y);
ofs += sizeof(*ph); ofs += sizeof(*ph);
while (ofs - ofs_start < ph->cb) while (ofs - ofs_start < ph->cb)
@ -907,16 +908,16 @@ static GpStatus format_string_callback(HDC dc,
for (j = 0; j < curve->cpfx; ++j) for (j = 0; j < curve->cpfx; ++j)
{ {
path->pathdata.Types[path->pathdata.Count] = PathPointTypeLine; path->pathdata.Types[path->pathdata.Count] = PathPointTypeLine;
path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(curve->apfx[j].x); path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(curve->apfx[j].x) * args->scale;
path->pathdata.Points[path->pathdata.Count++].Y = y + bb_end - fromfixedpoint(curve->apfx[j].y); path->pathdata.Points[path->pathdata.Count++].Y = y + args->ascent - fromfixedpoint(curve->apfx[j].y) * args->scale;
} }
break; break;
case TT_PRIM_CSPLINE: case TT_PRIM_CSPLINE:
for (j = 0; j < curve->cpfx; ++j) for (j = 0; j < curve->cpfx; ++j)
{ {
path->pathdata.Types[path->pathdata.Count] = PathPointTypeBezier; path->pathdata.Types[path->pathdata.Count] = PathPointTypeBezier;
path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(curve->apfx[j].x); path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(curve->apfx[j].x) * args->scale;
path->pathdata.Points[path->pathdata.Count++].Y = y + bb_end - fromfixedpoint(curve->apfx[j].y); path->pathdata.Points[path->pathdata.Count++].Y = y + args->ascent - fromfixedpoint(curve->apfx[j].y) * args->scale;
} }
break; break;
default: default:
@ -927,8 +928,8 @@ static GpStatus format_string_callback(HDC dc,
path->pathdata.Types[path->pathdata.Count - 1] |= PathPointTypeCloseSubpath; path->pathdata.Types[path->pathdata.Count - 1] |= PathPointTypeCloseSubpath;
} }
path->newfigure = TRUE; path->newfigure = TRUE;
x += gm.gmCellIncX; x += gm.gmCellIncX * args->scale;
y += gm.gmCellIncY; y += gm.gmCellIncY * args->scale;
GdipFree(ph); GdipFree(ph);
if (status != Ok) if (status != Ok)
@ -945,39 +946,70 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
LOGFONTW lfw; LOGFONTW lfw;
HANDLE hfont; HANDLE hfont;
HDC dc; HDC dc;
GpGraphics *graphics;
GpPath *backup; GpPath *backup;
struct format_string_args args; struct format_string_args args;
int i; int i;
UINT16 native_height;
RectF scaled_layout_rect;
TEXTMETRICW textmetric;
FIXME("(%p, %s, %d, %p, %d, %f, %p, %p): stub\n", path, debugstr_w(string), length, family, style, emSize, layoutRect, format); TRACE("(%p, %s, %d, %p, %d, %f, %p, %p)\n", path, debugstr_w(string), length, family, style, emSize, layoutRect, format);
if (!path || !string || !family || !emSize || !layoutRect || !format) if (!path || !string || !family || !emSize || !layoutRect || !format)
return InvalidParameter; return InvalidParameter;
status = GdipCreateFont(family, emSize, style, UnitPixel, &font); status = GdipGetEmHeight(family, style, &native_height);
if (status != Ok) if (status != Ok)
return status; return status;
status = GdipGetLogFontW((GpFont *)font, NULL, &lfw); scaled_layout_rect.X = layoutRect->X;
if (status != Ok) return status; scaled_layout_rect.Y = layoutRect->Y;
scaled_layout_rect.Width = layoutRect->Width * native_height / emSize;
scaled_layout_rect.Height = layoutRect->Height * native_height / emSize;
if ((status = GdipClonePath(path, &backup)) != Ok)
return status;
dc = CreateCompatibleDC(0);
status = GdipCreateFromHDC(dc, &graphics);
if (status != Ok)
{
DeleteDC(dc);
GdipDeletePath(backup);
return status;
}
status = GdipCreateFont(family, native_height, style, UnitPixel, &font);
if (status != Ok)
{
GdipDeleteGraphics(graphics);
DeleteDC(dc);
GdipDeletePath(backup);
return status;
}
get_log_fontW(font, graphics, &lfw);
GdipDeleteFont(font);
GdipDeleteGraphics(graphics);
hfont = CreateFontIndirectW(&lfw); hfont = CreateFontIndirectW(&lfw);
if (!hfont) if (!hfont)
{ {
WARN("Failed to create font\n"); WARN("Failed to create font\n");
DeleteDC(dc);
GdipDeletePath(backup);
return GenericError; return GenericError;
} }
if ((status = GdipClonePath(path, &backup)) != Ok)
{
DeleteObject(hfont);
return status;
}
dc = CreateCompatibleDC(0);
SelectObject(dc, hfont); SelectObject(dc, hfont);
GetTextMetricsW(dc, &textmetric);
args.path = path; args.path = path;
args.maxY = 0; args.maxY = 0;
status = gdip_format_string(dc, string, length, NULL, layoutRect, format, format_string_callback, &args); args.scale = emSize / native_height;
args.ascent = textmetric.tmAscent * args.scale;
status = gdip_format_string(dc, string, length, NULL, &scaled_layout_rect, format, format_string_callback, &args);
DeleteDC(dc); DeleteDC(dc);
DeleteObject(hfont); DeleteObject(hfont);
@ -992,12 +1024,12 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
} }
if (format && format->vertalign == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height) if (format && format->vertalign == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height)
{ {
float inc = layoutRect->Height - args.maxY - layoutRect->Y; float inc = layoutRect->Height + layoutRect->Y - args.maxY;
inc /= 2; inc /= 2;
for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i) for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i)
path->pathdata.Points[i].Y += inc; path->pathdata.Points[i].Y += inc;
} else if (format && format->vertalign == StringAlignmentFar) { } else if (format && format->vertalign == StringAlignmentFar) {
float inc = layoutRect->Height - args.maxY - layoutRect->Y; float inc = layoutRect->Height + layoutRect->Y - args.maxY;
for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i) for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i)
path->pathdata.Points[i].Y += inc; path->pathdata.Points[i].Y += inc;
} }
@ -1035,9 +1067,9 @@ GpStatus WINGDIPAPI GdipClonePath(GpPath* path, GpPath **clone)
(*clone)->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF)); (*clone)->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF));
(*clone)->pathdata.Types = GdipAlloc(path->datalen); (*clone)->pathdata.Types = GdipAlloc(path->datalen);
if(!(*clone)->pathdata.Points || !(*clone)->pathdata.Types){ if(!(*clone)->pathdata.Points || !(*clone)->pathdata.Types){
GdipFree(*clone);
GdipFree((*clone)->pathdata.Points); GdipFree((*clone)->pathdata.Points);
GdipFree((*clone)->pathdata.Types); GdipFree((*clone)->pathdata.Types);
GdipFree(*clone);
return OutOfMemory; return OutOfMemory;
} }
@ -1173,20 +1205,22 @@ GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix* matrix, REAL flatnes
GpPointF pt; GpPointF pt;
INT i = 1; INT i = 1;
INT startidx = 0; INT startidx = 0;
GpStatus stat;
TRACE("(%p, %p, %.2f)\n", path, matrix, flatness); TRACE("(%p, %p, %.2f)\n", path, matrix, flatness);
if(!path) if(!path)
return InvalidParameter; return InvalidParameter;
if(matrix){
WARN("transformation not supported yet!\n");
return NotImplemented;
}
if(path->pathdata.Count == 0) if(path->pathdata.Count == 0)
return Ok; return Ok;
if(matrix){
stat = GdipTransformPath(path, matrix);
if (stat != Ok)
return stat;
}
pt = path->pathdata.Points[0]; pt = path->pathdata.Points[0];
if(!init_path_list(&list, pt.X, pt.Y)) if(!init_path_list(&list, pt.X, pt.Y))
return OutOfMemory; return OutOfMemory;
@ -1339,8 +1373,8 @@ GpStatus WINGDIPAPI GdipGetPathPointsI(GpPath *path, GpPoint* points, INT count)
ret = GdipGetPathPoints(path,ptf,count); ret = GdipGetPathPoints(path,ptf,count);
if(ret == Ok) if(ret == Ok)
for(i = 0;i < count;i++){ for(i = 0;i < count;i++){
points[i].X = roundr(ptf[i].X); points[i].X = gdip_round(ptf[i].X);
points[i].Y = roundr(ptf[i].Y); points[i].Y = gdip_round(ptf[i].Y);
}; };
GdipFree(ptf); GdipFree(ptf);
@ -1460,10 +1494,10 @@ GpStatus WINGDIPAPI GdipGetPathWorldBoundsI(GpPath* path, GpRect* bounds,
ret = GdipGetPathWorldBounds(path,&boundsF,matrix,pen); ret = GdipGetPathWorldBounds(path,&boundsF,matrix,pen);
if(ret == Ok){ if(ret == Ok){
bounds->X = roundr(boundsF.X); bounds->X = gdip_round(boundsF.X);
bounds->Y = roundr(boundsF.Y); bounds->Y = gdip_round(boundsF.Y);
bounds->Width = roundr(boundsF.Width); bounds->Width = gdip_round(boundsF.Width);
bounds->Height = roundr(boundsF.Height); bounds->Height = gdip_round(boundsF.Height);
} }
return ret; return ret;
@ -1589,7 +1623,7 @@ GpStatus WINGDIPAPI GdipIsVisiblePathPoint(GpPath* path, REAL x, REAL y, GpGraph
return status; return status;
} }
*result = PtInRegion(hrgn, roundr(x), roundr(y)); *result = PtInRegion(hrgn, gdip_round(x), gdip_round(y));
DeleteObject(hrgn); DeleteObject(hrgn);
GdipDeleteRegion(region); GdipDeleteRegion(region);
@ -1688,6 +1722,35 @@ static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *
{ {
switch (pen->join) switch (pen->join)
{ {
case LineJoinMiter:
case LineJoinMiterClipped:
if ((p2->X - p1->X) * (p3->Y - p1->Y) > (p2->Y - p1->Y) * (p3->X - p1->X))
{
float distance = pen->width/2.0;
float length_0 = sqrtf((p2->X-p1->X)*(p2->X-p1->X)+(p2->Y-p1->Y)*(p2->Y-p1->Y));
float length_1 = sqrtf((p3->X-p2->X)*(p3->X-p2->X)+(p3->Y-p2->Y)*(p3->Y-p2->Y));
float dx0 = distance * (p2->X - p1->X) / length_0;
float dy0 = distance * (p2->Y - p1->Y) / length_0;
float dx1 = distance * (p3->X - p2->X) / length_1;
float dy1 = distance * (p3->Y - p2->Y) / length_1;
float det = (dy0*dx1 - dx0*dy1);
float dx = (dx0*dx1*(dx0-dx1) + dy0*dy0*dx1 - dy1*dy1*dx0)/det;
float dy = (dy0*dy1*(dy0-dy1) + dx0*dx0*dy1 - dx1*dx1*dy0)/det;
if (dx*dx + dy*dy < pen->miterlimit*pen->miterlimit * distance*distance)
{
*last_point = add_path_list_node(*last_point, p2->X + dx,
p2->Y + dy, PathPointTypeLine);
break;
}
else if (pen->join == LineJoinMiter)
{
static int once;
if (!once++)
FIXME("should add a clipped corner\n");
}
/* else fall-through */
}
/* else fall-through */
default: default:
case LineJoinBevel: case LineJoinBevel:
add_bevel_point(p2, p1, pen, 1, last_point); add_bevel_point(p2, p1, pen, 1, last_point);
@ -1709,6 +1772,74 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
if (add_last_point) if (add_last_point)
add_bevel_point(endpoint, nextpoint, pen, 0, last_point); add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
break; break;
case LineCapSquare:
{
REAL segment_dy = nextpoint->Y-endpoint->Y;
REAL segment_dx = nextpoint->X-endpoint->X;
REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
REAL distance = pen->width/2.0;
REAL bevel_dx, bevel_dy;
REAL extend_dx, extend_dy;
extend_dx = -distance * segment_dx / segment_length;
extend_dy = -distance * segment_dy / segment_length;
bevel_dx = -distance * segment_dy / segment_length;
bevel_dy = distance * segment_dx / segment_length;
if (add_first_points)
*last_point = add_path_list_node(*last_point, endpoint->X + extend_dx + bevel_dx,
endpoint->Y + extend_dy + bevel_dy, PathPointTypeLine);
if (add_last_point)
*last_point = add_path_list_node(*last_point, endpoint->X + extend_dx - bevel_dx,
endpoint->Y + extend_dy - bevel_dy, PathPointTypeLine);
break;
}
case LineCapRound:
{
REAL segment_dy = nextpoint->Y-endpoint->Y;
REAL segment_dx = nextpoint->X-endpoint->X;
REAL segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
REAL distance = pen->width/2.0;
REAL dx, dy, dx2, dy2;
const REAL control_point_distance = 0.5522847498307935; /* 4/3 * (sqrt(2) - 1) */
if (add_first_points)
{
dx = -distance * segment_dx / segment_length;
dy = -distance * segment_dy / segment_length;
dx2 = dx * control_point_distance;
dy2 = dy * control_point_distance;
/* first 90-degree arc */
*last_point = add_path_list_node(*last_point, endpoint->X + dy,
endpoint->Y - dx, PathPointTypeLine);
*last_point = add_path_list_node(*last_point, endpoint->X + dy + dx2,
endpoint->Y - dx + dy2, PathPointTypeBezier);
*last_point = add_path_list_node(*last_point, endpoint->X + dx + dy2,
endpoint->Y + dy - dx2, PathPointTypeBezier);
/* midpoint */
*last_point = add_path_list_node(*last_point, endpoint->X + dx,
endpoint->Y + dy, PathPointTypeBezier);
/* second 90-degree arc */
*last_point = add_path_list_node(*last_point, endpoint->X + dx - dy2,
endpoint->Y + dy + dx2, PathPointTypeBezier);
*last_point = add_path_list_node(*last_point, endpoint->X - dy + dx2,
endpoint->Y + dx + dy2, PathPointTypeBezier);
*last_point = add_path_list_node(*last_point, endpoint->X - dy,
endpoint->Y + dx, PathPointTypeBezier);
}
break;
}
} }
} }
@ -1716,15 +1847,16 @@ static void widen_open_figure(GpPath *path, GpPen *pen, int start, int end,
path_list_node_t **last_point) path_list_node_t **last_point)
{ {
int i; int i;
path_list_node_t *prev_point;
if (end <= start) if (end <= start)
return; return;
prev_point = *last_point;
widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1], widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
pen, pen->startcap, pen->customstart, FALSE, TRUE, last_point); pen, pen->startcap, pen->customstart, FALSE, TRUE, last_point);
(*last_point)->type = PathPointTypeStart;
for (i=start+1; i<end; i++) for (i=start+1; i<end; i++)
widen_joint(&path->pathdata.Points[i-1], &path->pathdata.Points[i], widen_joint(&path->pathdata.Points[i-1], &path->pathdata.Points[i],
&path->pathdata.Points[i+1], pen, last_point); &path->pathdata.Points[i+1], pen, last_point);
@ -1739,6 +1871,7 @@ static void widen_open_figure(GpPath *path, GpPen *pen, int start, int end,
widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1], widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
pen, pen->startcap, pen->customstart, TRUE, FALSE, last_point); pen, pen->startcap, pen->customstart, TRUE, FALSE, last_point);
prev_point->next->type = PathPointTypeStart;
(*last_point)->type |= PathPointTypeCloseSubpath; (*last_point)->type |= PathPointTypeCloseSubpath;
} }
@ -1813,16 +1946,16 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
{ {
last_point = points; last_point = points;
if (pen->endcap != LineCapFlat) if (pen->endcap > LineCapRound)
FIXME("unimplemented end cap %x\n", pen->endcap); FIXME("unimplemented end cap %x\n", pen->endcap);
if (pen->startcap != LineCapFlat) if (pen->startcap > LineCapRound)
FIXME("unimplemented start cap %x\n", pen->startcap); FIXME("unimplemented start cap %x\n", pen->startcap);
if (pen->dashcap != DashCapFlat) if (pen->dashcap != DashCapFlat)
FIXME("unimplemented dash cap %d\n", pen->dashcap); FIXME("unimplemented dash cap %d\n", pen->dashcap);
if (pen->join != LineJoinBevel) if (pen->join == LineJoinRound)
FIXME("unimplemented line join %d\n", pen->join); FIXME("unimplemented line join %d\n", pen->join);
if (pen->dash != DashStyleSolid) if (pen->dash != DashStyleSolid)

File diff suppressed because it is too large Load diff

View file

@ -393,8 +393,8 @@ GpStatus WINGDIPAPI GdipTransformMatrixPointsI(GpMatrix *matrix, GpPoint *pts, I
if(ret == Ok) if(ret == Ok)
for(i = 0; i < count; i++){ for(i = 0; i < count; i++){
pts[i].X = roundr(ptsF[i].X); pts[i].X = gdip_round(ptsF[i].X);
pts[i].Y = roundr(ptsF[i].Y); pts[i].Y = gdip_round(ptsF[i].Y);
} }
GdipFree(ptsF); GdipFree(ptsF);
@ -474,8 +474,8 @@ GpStatus WINGDIPAPI GdipVectorTransformMatrixPointsI(GpMatrix *matrix, GpPoint *
/* store back */ /* store back */
if(ret == Ok) if(ret == Ok)
for(i = 0; i < count; i++){ for(i = 0; i < count; i++){
pts[i].X = roundr(ptsF[i].X); pts[i].X = gdip_round(ptsF[i].X);
pts[i].Y = roundr(ptsF[i].Y); pts[i].Y = gdip_round(ptsF[i].Y);
} }
GdipFree(ptsF); GdipFree(ptsF);

View file

@ -232,10 +232,7 @@ GpStatus WINGDIPAPI GdipRecordMetafile(HDC hdc, EmfType type, GDIPCONST GpRectF
(*metafile)->image.type = ImageTypeMetafile; (*metafile)->image.type = ImageTypeMetafile;
(*metafile)->image.picture = NULL; (*metafile)->image.picture = NULL;
(*metafile)->image.flags = ImageFlagsNone; (*metafile)->image.flags = ImageFlagsNone;
(*metafile)->image.palette_flags = 0; (*metafile)->image.palette = NULL;
(*metafile)->image.palette_count = 0;
(*metafile)->image.palette_size = 0;
(*metafile)->image.palette_entries = NULL;
(*metafile)->bounds = *frameRect; (*metafile)->bounds = *frameRect;
(*metafile)->unit = frameUnit; (*metafile)->unit = frameUnit;
(*metafile)->metafile_type = type; (*metafile)->metafile_type = type;
@ -551,3 +548,41 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
return stat; return stat;
} }
static int CALLBACK get_metafile_type_proc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR,
int nObj, LPARAM lpData)
{
MetafileType *result = (MetafileType*)lpData;
if (lpEMFR->iType == EMR_GDICOMMENT)
{
const EMRGDICOMMENT *comment = (const EMRGDICOMMENT*)lpEMFR;
if (comment->cbData >= 4 && memcmp(comment->Data, "EMF+", 4) == 0)
{
const EmfPlusRecordHeader *header = (const EmfPlusRecordHeader*)&comment->Data[4];
if (4 + sizeof(EmfPlusRecordHeader) <= comment->cbData &&
header->Type == EmfPlusRecordTypeHeader)
{
if ((header->Flags & 1) == 1)
*result = MetafileTypeEmfPlusDual;
else
*result = MetafileTypeEmfPlusOnly;
}
}
else
*result = MetafileTypeEmf;
}
else
*result = MetafileTypeEmf;
return FALSE;
}
MetafileType METAFILE_GetEmfType(HENHMETAFILE hemf)
{
MetafileType result = MetafileTypeInvalid;
EnumEnhMetaFile(NULL, hemf, get_metafile_type_proc, &result, NULL);
return result;
}

View file

@ -151,15 +151,15 @@ static inline GpStatus clone_element(const region_element* element,
{ {
case RegionDataRect: case RegionDataRect:
(*element2)->elementdata.rect = element->elementdata.rect; (*element2)->elementdata.rect = element->elementdata.rect;
break; return Ok;
case RegionDataEmptyRect: case RegionDataEmptyRect:
case RegionDataInfiniteRect: case RegionDataInfiniteRect:
break; return Ok;
case RegionDataPath: case RegionDataPath:
(*element2)->elementdata.pathdata.pathheader = element->elementdata.pathdata.pathheader; (*element2)->elementdata.pathdata.pathheader = element->elementdata.pathdata.pathheader;
stat = GdipClonePath(element->elementdata.pathdata.path, stat = GdipClonePath(element->elementdata.pathdata.path,
&(*element2)->elementdata.pathdata.path); &(*element2)->elementdata.pathdata.path);
if (stat != Ok) goto clone_out; if (stat == Ok) return Ok;
break; break;
default: default:
(*element2)->elementdata.combine.left = NULL; (*element2)->elementdata.combine.left = NULL;
@ -167,16 +167,15 @@ static inline GpStatus clone_element(const region_element* element,
stat = clone_element(element->elementdata.combine.left, stat = clone_element(element->elementdata.combine.left,
&(*element2)->elementdata.combine.left); &(*element2)->elementdata.combine.left);
if (stat != Ok) goto clone_out; if (stat == Ok)
stat = clone_element(element->elementdata.combine.right, {
&(*element2)->elementdata.combine.right); stat = clone_element(element->elementdata.combine.right,
if (stat != Ok) goto clone_out; &(*element2)->elementdata.combine.right);
if (stat == Ok) return Ok;
}
break; break;
} }
return Ok;
clone_out:
delete_element(*element2); delete_element(*element2);
*element2 = NULL; *element2 = NULL;
return stat; return stat;
@ -254,20 +253,20 @@ GpStatus WINGDIPAPI GdipCombineRegionPath(GpRegion *region, GpPath *path, Combin
} }
left = GdipAlloc(sizeof(region_element)); left = GdipAlloc(sizeof(region_element));
if (!left) if (left)
goto out; {
*left = region->node; *left = region->node;
stat = clone_element(&path_region->node, &right);
if (stat == Ok)
{
fuse_region(region, left, right, mode);
GdipDeleteRegion(path_region);
return Ok;
}
}
else
stat = OutOfMemory;
stat = clone_element(&path_region->node, &right);
if (stat != Ok)
goto out;
fuse_region(region, left, right, mode);
GdipDeleteRegion(path_region);
return Ok;
out:
GdipFree(left); GdipFree(left);
GdipDeleteRegion(path_region); GdipDeleteRegion(path_region);
return stat; return stat;
@ -301,20 +300,20 @@ GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region,
} }
left = GdipAlloc(sizeof(region_element)); left = GdipAlloc(sizeof(region_element));
if (!left) if (left)
goto out; {
memcpy(left, &region->node, sizeof(region_element)); memcpy(left, &region->node, sizeof(region_element));
stat = clone_element(&rect_region->node, &right);
if (stat == Ok)
{
fuse_region(region, left, right, mode);
GdipDeleteRegion(rect_region);
return Ok;
}
}
else
stat = OutOfMemory;
stat = clone_element(&rect_region->node, &right);
if (stat != Ok)
goto out;
fuse_region(region, left, right, mode);
GdipDeleteRegion(rect_region);
return Ok;
out:
GdipFree(left); GdipFree(left);
GdipDeleteRegion(rect_region); GdipDeleteRegion(rect_region);
return stat; return stat;
@ -399,6 +398,8 @@ GpStatus WINGDIPAPI GdipCreateRegion(GpRegion **region)
if(!*region) if(!*region)
return OutOfMemory; return OutOfMemory;
TRACE("=> %p\n", *region);
return init_region(*region, RegionDataInfiniteRect); return init_region(*region, RegionDataInfiniteRect);
} }
@ -680,6 +681,7 @@ GpStatus WINGDIPAPI GdipGetRegionBounds(GpRegion *region, GpGraphics *graphics,
if(!hrgn){ if(!hrgn){
rect->X = rect->Y = -(REAL)(1 << 22); rect->X = rect->Y = -(REAL)(1 << 22);
rect->Width = rect->Height = (REAL)(1 << 23); rect->Width = rect->Height = (REAL)(1 << 23);
TRACE("%p => infinite\n", region);
return Ok; return Ok;
} }
@ -688,6 +690,7 @@ GpStatus WINGDIPAPI GdipGetRegionBounds(GpRegion *region, GpGraphics *graphics,
rect->Y = r.top; rect->Y = r.top;
rect->Width = r.right - r.left; rect->Width = r.right - r.left;
rect->Height = r.bottom - r.top; rect->Height = r.bottom - r.top;
TRACE("%p => %s\n", region, debugstr_rectf(rect));
} }
else else
status = GenericError; status = GenericError;
@ -712,10 +715,10 @@ GpStatus WINGDIPAPI GdipGetRegionBoundsI(GpRegion *region, GpGraphics *graphics,
status = GdipGetRegionBounds(region, graphics, &rectf); status = GdipGetRegionBounds(region, graphics, &rectf);
if(status == Ok){ if(status == Ok){
rect->X = roundr(rectf.X); rect->X = gdip_round(rectf.X);
rect->Y = roundr(rectf.X); rect->Y = gdip_round(rectf.X);
rect->Width = roundr(rectf.Width); rect->Width = gdip_round(rectf.Width);
rect->Height = roundr(rectf.Height); rect->Height = gdip_round(rectf.Height);
} }
return status; return status;
@ -1080,12 +1083,19 @@ GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *region, GpGraphics *graphics, HR
GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *region, GpGraphics *graphics, BOOL *res) GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
{ {
GpStatus status;
GpRectF rect;
TRACE("(%p, %p, %p)\n", region, graphics, res); TRACE("(%p, %p, %p)\n", region, graphics, res);
if(!region || !graphics || !res) if(!region || !graphics || !res)
return InvalidParameter; return InvalidParameter;
*res = (region->node.type == RegionDataEmptyRect); status = GdipGetRegionBounds(region, graphics, &rect);
if (status != Ok) return status;
*res = rect.Width == 0.0 && rect.Height == 0.0;
TRACE("=> %d\n", *res);
return Ok; return Ok;
} }
@ -1210,7 +1220,7 @@ GpStatus WINGDIPAPI GdipIsVisibleRegionPoint(GpRegion* region, REAL x, REAL y, G
return Ok; return Ok;
} }
*res = PtInRegion(hrgn, roundr(x), roundr(y)); *res = PtInRegion(hrgn, gdip_round(x), gdip_round(y));
DeleteObject(hrgn); DeleteObject(hrgn);

View file

@ -50,6 +50,7 @@ GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang,
(*format)->digitsub = StringDigitSubstituteUser; (*format)->digitsub = StringDigitSubstituteUser;
(*format)->character_ranges = NULL; (*format)->character_ranges = NULL;
(*format)->range_count = 0; (*format)->range_count = 0;
(*format)->generic_typographic = FALSE;
/* tabstops */ /* tabstops */
(*format)->tabcount = 0; (*format)->tabcount = 0;
(*format)->firsttab = 0.0; (*format)->firsttab = 0.0;
@ -386,6 +387,9 @@ GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **forma
(*format)->hkprefix = HotkeyPrefixNone; (*format)->hkprefix = HotkeyPrefixNone;
(*format)->align = StringAlignmentNear; (*format)->align = StringAlignmentNear;
(*format)->vertalign = StringAlignmentNear; (*format)->vertalign = StringAlignmentNear;
(*format)->generic_typographic = TRUE;
TRACE("%p => %p\n", format, *format);
return Ok; return Ok;
} }

View file

@ -299,13 +299,6 @@ enum HotkeyPrefix
HotkeyPrefixHide = 2 HotkeyPrefixHide = 2
}; };
enum PaletteFlags
{
PaletteFlagsHasAlpha = 1,
PaletteFlagsGrayScale = 2,
PaletteFlagsHalftone = 4
};
enum ImageCodecFlags enum ImageCodecFlags
{ {
ImageCodecFlagsEncoder = 1, ImageCodecFlagsEncoder = 1,

View file

@ -364,6 +364,9 @@ typedef struct PropertyItem
#define PropertyTagFrameDelay 0x5100 #define PropertyTagFrameDelay 0x5100
#define PropertyTagLoopCount 0x5101 #define PropertyTagLoopCount 0x5101
#define PropertyTagGlobalPalette 0x5102
#define PropertyTagIndexBackground 0x5103
#define PropertyTagIndexTransparent 0x5104
#define PropertyTagPixelUnit 0x5110 #define PropertyTagPixelUnit 0x5110
#define PropertyTagPixelPerUnitX 0x5111 #define PropertyTagPixelPerUnitX 0x5111

View file

@ -46,7 +46,40 @@ typedef INT PixelFormat;
#define PixelFormat48bppRGB (12 | (48 << 8) | PixelFormatExtended) #define PixelFormat48bppRGB (12 | (48 << 8) | PixelFormatExtended)
#define PixelFormat64bppARGB (13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | PixelFormatExtended) #define PixelFormat64bppARGB (13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | PixelFormatExtended)
#define PixelFormat64bppPARGB (14 | (64 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatExtended) #define PixelFormat64bppPARGB (14 | (64 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatExtended)
#define PixelFormatMax 15 #define PixelFormat32bppCMYK (15 | (32 << 8))
#define PixelFormatMax 16
static inline BOOL IsIndexedPixelFormat(PixelFormat format)
{
return (format & PixelFormatIndexed) != 0;
}
static inline BOOL IsAlphaPixelFormat(PixelFormat format)
{
return (format & PixelFormatAlpha) != 0;
}
static inline BOOL IsCanonicalPixelFormat(PixelFormat format)
{
return (format & PixelFormatCanonical) != 0;
}
static inline BOOL IsExtendedPixelFormat(PixelFormat format)
{
return (format & PixelFormatExtended) != 0;
}
static inline UINT GetPixelFormatSize(PixelFormat format)
{
return (format >> 8) & 0xff;
}
enum PaletteFlags
{
PaletteFlagsHasAlpha = 1,
PaletteFlagsGrayScale = 2,
PaletteFlagsHalftone = 4
};
#ifdef __cplusplus #ifdef __cplusplus