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

View file

@ -116,41 +116,10 @@ typedef struct
#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 GpStatus clone_font_family(const GpFontFamily *, GpFontFamily **);
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.@]
*
@ -193,7 +162,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL);
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.lfItalic = style & FontStyleItalic;
lfw.lfUnderline = style & FontStyleUnderline;
@ -216,7 +185,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
(*font)->emSize = emSize;
(*font)->otm = otm;
stat = GdipCloneFontFamily((GpFontFamily *)fontFamily, &(*font)->family);
stat = clone_font_family(fontFamily, &(*font)->family);
if (stat != Ok)
{
GdipFree(*font);
@ -236,6 +205,7 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
{
HFONT hfont, oldfont;
OUTLINETEXTMETRICW otm;
WCHAR facename[LF_FACESIZE];
GpStatus stat;
int ret;
@ -248,6 +218,7 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
oldfont = SelectObject(hdc, hfont);
otm.otmSize = sizeof(otm);
ret = GetOutlineTextMetricsW(hdc, otm.otmSize, &otm);
GetTextFaceW(hdc, LF_FACESIZE, facename);
SelectObject(hdc, oldfont);
DeleteObject(hfont);
@ -260,7 +231,7 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
(*font)->emSize = otm.otmTextMetrics.tmAscent;
(*font)->otm = otm;
stat = GdipCreateFontFamilyFromName(logfont->lfFaceName, NULL, &(*font)->family);
stat = GdipCreateFontFamilyFromName(facename, NULL, &(*font)->family);
if (stat != Ok)
{
GdipFree(*font);
@ -355,6 +326,11 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
return GdipCloneFontFamily(font->family, family);
}
static REAL get_font_size(const GpFont *font)
{
return font->emSize;
}
/******************************************************************************
* GdipGetFontSize [GDIPLUS.@]
*
@ -377,12 +353,30 @@ GpStatus WINGDIPAPI GdipGetFontSize(GpFont *font, REAL *size)
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);
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.@]
*
@ -403,16 +397,8 @@ GpStatus WINGDIPAPI GdipGetFontStyle(GpFont *font, INT *style)
if (!(font && style))
return InvalidParameter;
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;
*style = get_font_style(font);
TRACE("%s,%d => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *style);
return Ok;
}
@ -466,31 +452,64 @@ GpStatus WINGDIPAPI GdipGetLogFontA(GpFont *font, GpGraphics *graphics,
/*******************************************************************************
* GdipGetLogFontW [GDIPLUS.@]
*/
GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics,
LOGFONTW *lfw)
GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW *lf)
{
TRACE("(%p, %p, %p)\n", font, graphics, lfw);
REAL angle, rel_height, height;
GpMatrix matrix;
GpPointF pt[3];
/* FIXME: use graphics */
if(!font || !graphics || !lfw)
TRACE("(%p, %p, %p)\n", font, graphics, lf);
if (!font || !graphics || !lf)
return InvalidParameter;
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);
matrix = graphics->worldtrans;
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;
}
@ -535,18 +554,29 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
{
REAL dpi;
GpStatus stat;
REAL font_height;
TRACE("%p %p %p\n", font, graphics, height);
if (graphics)
{
stat = GdipGetDpiY((GpGraphics*)graphics, &dpi);
if (stat != Ok) return stat;
}
else
dpi = font->family->dpi;
stat = GdipGetFontHeightGivenDPI(font, font->family->dpi, &font_height);
if (stat != Ok) return stat;
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;
INT style;
UINT16 line_spacing, em_height;
REAL font_height, font_size;
REAL font_size;
if (!font || !height) return InvalidParameter;
TRACE("%p (%s), %f, %p\n", font,
debugstr_w(font->family->FamilyName), dpi, height);
stat = GdipGetFontSize((GpFont *)font, &font_size);
if (stat != Ok) return stat;
stat = GdipGetFontStyle((GpFont *)font, &style);
if (stat != Ok) return stat;
font_size = units_to_pixels(get_font_size(font), font->unit, dpi);
style = get_font_style(font);
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 = (REAL)line_spacing * font_size / (REAL)em_height;
*height = (REAL)line_spacing * font_size / (REAL)em_height;
switch (font->unit)
{
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);
TRACE("%s,%d => %f\n",
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *height);
return Ok;
}
@ -625,7 +630,7 @@ 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 (type != TRUETYPE_FONTTYPE)
if (type & RASTER_FONTTYPE)
return 1;
*(LOGFONTW *)lParam = *elf;
@ -635,6 +640,7 @@ static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf,
struct font_metrics
{
WCHAR facename[LF_FACESIZE];
UINT16 em_height, ascent, descent, line_spacing; /* in font units */
int dpi;
};
@ -650,6 +656,8 @@ static BOOL get_font_metrics(HDC hdc, struct font_metrics *fm)
otm.otmSize = sizeof(otm);
if (!GetOutlineTextMetricsW(hdc, otm.otmSize, &otm)) return FALSE;
GetTextFaceW(hdc, LF_FACESIZE, fm->facename);
fm->em_height = otm.otmEMSquare;
fm->dpi = GetDeviceCaps(hdc, LOGPIXELSY);
@ -750,7 +758,7 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
ffamily = GdipAlloc(sizeof (GpFontFamily));
if (!ffamily) return OutOfMemory;
lstrcpynW(ffamily->FamilyName, name, LF_FACESIZE);
lstrcpyW(ffamily->FamilyName, fm.facename);
ffamily->em_height = fm.em_height;
ffamily->ascent = fm.ascent;
ffamily->descent = fm.descent;
@ -764,6 +772,16 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
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.@]
*
@ -778,16 +796,15 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
*/
GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily** clonedFontFamily)
{
GpStatus status;
if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
TRACE("%p (%s), %p\n", FontFamily,
debugstr_w(FontFamily->FamilyName), clonedFontFamily);
*clonedFontFamily = GdipAlloc(sizeof(GpFontFamily));
if (!*clonedFontFamily) return OutOfMemory;
**clonedFontFamily = *FontFamily;
lstrcpyW((*clonedFontFamily)->FamilyName, FontFamily->FamilyName);
status = clone_font_family(FontFamily, clonedFontFamily);
if (status != Ok) return status;
TRACE("<-- %p\n", *clonedFontFamily);

View file

@ -35,6 +35,9 @@
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)
{
TRACE("%p\n", token);
@ -207,7 +210,7 @@ static void unstretch_angle(REAL * angle, REAL rad_x, REAL rad_y)
return;
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;
*angle = stretched;
}
@ -318,28 +321,57 @@ GpStatus hresult_to_status(HRESULT res)
}
/* 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:
return logpixels;
case UnitPoint:
return logpixels / 72.0;
case UnitDocument:
return logpixels / 300.0;
case UnitMillimeter:
return logpixels / 25.4;
case UnitWorld:
ERR("cannot convert UnitWorld\n");
return 0.0;
case UnitPixel:
case UnitDisplay:
default:
return 1.0;
case UnitPixel:
case UnitWorld:
case UnitDisplay:
return units;
case UnitPoint:
return units * dpi / point_per_inch;
case UnitInch:
return units * dpi;
case UnitDocument:
return units * dpi / 300.0; /* Per MSDN */
case UnitMillimeter:
return units * dpi / mm_per_inch;
default:
FIXME("Unhandled unit type: %d\n", unit);
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. */
void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
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)
{
/* tangent at endpoints is the line from the endpoint to the adjacent point */
*x = roundr(tension * (xadj - xend) + xend);
*y = roundr(tension * (yadj - yend) + yend);
*x = gdip_round(tension * (xadj - xend) + xend);
*y = gdip_round(tension * (yadj - yend) + yend);
}
/* make sure path has enough space for len more points */

View file

@ -471,10 +471,10 @@
471 stdcall GdipRotatePenTransform(ptr float long)
472 stdcall GdipRotateTextureTransform(ptr float long)
473 stdcall GdipRotateWorldTransform(ptr float long)
474 stub GdipSaveAdd
474 stdcall GdipSaveAdd(ptr ptr)
475 stub GdipSaveAddImage
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)
479 stdcall GdipScaleLineTransform(ptr float float long)
480 stdcall GdipScaleMatrix(ptr float float long)

View file

@ -29,6 +29,7 @@
#include "objbase.h"
#include "ocidl.h"
#include "wincodecsdk.h"
#include "wine/list.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;
extern REAL gdiplus_atan2(REAL dy, REAL dx) 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;
@ -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_ReleaseDC(GpMetafile* metafile, HDC hdc) 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,
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 get_font_hfont(GpGraphics *graphics, GDIPCONST GpFont *font, HFONT *hfont) DECLSPEC_HIDDEN;
extern BOOL lengthen_path(GpPath *path, INT len) 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;
static inline INT roundr(REAL x)
static inline INT gdip_round(REAL x)
{
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,
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{
UINT style;
@ -146,6 +152,7 @@ struct GpGraphics{
HDC hdc;
HWND hwnd;
BOOL owndc;
BOOL alpha_hdc;
GpImage *image;
SmoothingMode smoothing;
CompositingQuality compqual;
@ -155,7 +162,8 @@ struct GpGraphics{
TextRenderingHint texthint;
GpUnit unit; /* page unit */
REAL scale; /* page scale */
GpMatrix * worldtrans; /* world transform */
REAL xres, yres;
GpMatrix worldtrans; /* world transform */
BOOL busy; /* hdc handle obtained by GdipGetDC */
GpRegion *clip;
UINT textcontrast; /* not used yet. get/set only */
@ -202,7 +210,7 @@ struct GpPathGradient{
ARGB* pblendcolor; /* preset blend colors */
REAL* pblendpos; /* preset blend positions */
INT pblendcount;
GpMatrix *transform;
GpMatrix transform;
};
struct GpLineGradient{
@ -224,7 +232,7 @@ struct GpLineGradient{
struct GpTexture{
GpBrush brush;
GpMatrix *transform;
GpMatrix transform;
GpImage *image;
GpImageAttributes *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 */
};
struct GpMatrix{
REAL matrix[6];
};
struct GpPathIterator{
GpPathData pathdata;
INT subpath_pos; /* for NextSubpath methods */
@ -262,14 +266,13 @@ struct GpAdustableArrowCap{
};
struct GpImage{
IPicture* picture;
IPicture *picture;
IStream *stream; /* source stream */
ImageType type;
GUID format;
UINT flags;
UINT palette_flags;
UINT palette_count;
UINT palette_size;
ARGB *palette_entries;
UINT frame_count, current_frame;
ColorPalette *palette;
REAL xres, yres;
};
@ -279,6 +282,7 @@ struct GpMetafile{
GpUnit unit;
MetafileType metafile_type;
HENHMETAFILE hemf;
int preserve_hemf; /* if true, hemf belongs to the app and should not be deleted */
/* recording */
HDC record_dc;
@ -309,6 +313,9 @@ struct GpBitmap{
INT stride; /* stride of bits if this is a DIB */
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. */
IWICMetadataReader *metadata_reader; /* NULL if there is no metadata */
UINT prop_count;
PropertyItem *prop_item; /* cached image properties */
};
struct GpCachedBitmap{
@ -366,6 +373,7 @@ struct GpStringFormat{
REAL *tabs;
CharacterRange *character_ranges;
INT range_count;
BOOL generic_typographic;
};
struct GpFontCollection{
@ -436,4 +444,6 @@ GpStatus gdip_format_string(HDC hdc,
GDIPCONST RectF *rect, GDIPCONST GpStringFormat *format,
gdip_format_string_callback callback, void *user_data) DECLSPEC_HIDDEN;
void get_log_fontW(const GpFont *, GpGraphics *, LOGFONTW *) DECLSPEC_HIDDEN;
#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)))
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(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
{
GpPath *path;
UINT maxY;
float maxY;
float scale;
float ascent;
};
static GpStatus format_string_callback(HDC dc,
@ -853,20 +855,22 @@ static GpStatus format_string_callback(HDC dc,
struct format_string_args *args = priv;
GpPath *path = args->path;
GpStatus status = Ok;
float x = bounds->X;
float y = bounds->Y;
float x = rect->X + (bounds->X - rect->X) * args->scale;
float y = rect->Y + (bounds->Y - rect->Y) * args->scale;
int i;
if (underlined_index_count)
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)
{
GLYPHMETRICS gm;
TTPOLYGONHEADER *ph = NULL;
char *start;
DWORD len, ofs = 0;
UINT bb_end;
len = GetGlyphOutlineW(dc, string[i], GGO_BEZIER, &gm, 0, NULL, &identity);
if (len == GDI_ERROR)
{
@ -881,9 +885,6 @@ static GpStatus format_string_callback(HDC dc,
break;
}
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;
while (ofs < len)
@ -891,8 +892,8 @@ static GpStatus format_string_callback(HDC dc,
DWORD ofs_start = ofs;
ph = (TTPOLYGONHEADER*)&start[ofs];
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++].Y = y + bb_end - fromfixedpoint(ph->pfxStart.y);
path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(ph->pfxStart.x) * args->scale;
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);
ofs += sizeof(*ph);
while (ofs - ofs_start < ph->cb)
@ -907,16 +908,16 @@ static GpStatus format_string_callback(HDC dc,
for (j = 0; j < curve->cpfx; ++j)
{
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++].Y = y + bb_end - fromfixedpoint(curve->apfx[j].y);
path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(curve->apfx[j].x) * args->scale;
path->pathdata.Points[path->pathdata.Count++].Y = y + args->ascent - fromfixedpoint(curve->apfx[j].y) * args->scale;
}
break;
case TT_PRIM_CSPLINE:
for (j = 0; j < curve->cpfx; ++j)
{
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++].Y = y + bb_end - fromfixedpoint(curve->apfx[j].y);
path->pathdata.Points[path->pathdata.Count].X = x + fromfixedpoint(curve->apfx[j].x) * args->scale;
path->pathdata.Points[path->pathdata.Count++].Y = y + args->ascent - fromfixedpoint(curve->apfx[j].y) * args->scale;
}
break;
default:
@ -927,8 +928,8 @@ static GpStatus format_string_callback(HDC dc,
path->pathdata.Types[path->pathdata.Count - 1] |= PathPointTypeCloseSubpath;
}
path->newfigure = TRUE;
x += gm.gmCellIncX;
y += gm.gmCellIncY;
x += gm.gmCellIncX * args->scale;
y += gm.gmCellIncY * args->scale;
GdipFree(ph);
if (status != Ok)
@ -945,39 +946,70 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
LOGFONTW lfw;
HANDLE hfont;
HDC dc;
GpGraphics *graphics;
GpPath *backup;
struct format_string_args args;
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)
return InvalidParameter;
status = GdipCreateFont(family, emSize, style, UnitPixel, &font);
status = GdipGetEmHeight(family, style, &native_height);
if (status != Ok)
return status;
status = GdipGetLogFontW((GpFont *)font, NULL, &lfw);
if (status != Ok) return status;
scaled_layout_rect.X = layoutRect->X;
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);
if (!hfont)
{
WARN("Failed to create font\n");
DeleteDC(dc);
GdipDeletePath(backup);
return GenericError;
}
if ((status = GdipClonePath(path, &backup)) != Ok)
{
DeleteObject(hfont);
return status;
}
dc = CreateCompatibleDC(0);
SelectObject(dc, hfont);
GetTextMetricsW(dc, &textmetric);
args.path = path;
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);
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)
{
float inc = layoutRect->Height - args.maxY - layoutRect->Y;
float inc = layoutRect->Height + layoutRect->Y - args.maxY;
inc /= 2;
for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i)
path->pathdata.Points[i].Y += inc;
} 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)
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.Types = GdipAlloc(path->datalen);
if(!(*clone)->pathdata.Points || !(*clone)->pathdata.Types){
GdipFree(*clone);
GdipFree((*clone)->pathdata.Points);
GdipFree((*clone)->pathdata.Types);
GdipFree(*clone);
return OutOfMemory;
}
@ -1173,20 +1205,22 @@ GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix* matrix, REAL flatnes
GpPointF pt;
INT i = 1;
INT startidx = 0;
GpStatus stat;
TRACE("(%p, %p, %.2f)\n", path, matrix, flatness);
if(!path)
return InvalidParameter;
if(matrix){
WARN("transformation not supported yet!\n");
return NotImplemented;
}
if(path->pathdata.Count == 0)
return Ok;
if(matrix){
stat = GdipTransformPath(path, matrix);
if (stat != Ok)
return stat;
}
pt = path->pathdata.Points[0];
if(!init_path_list(&list, pt.X, pt.Y))
return OutOfMemory;
@ -1339,8 +1373,8 @@ GpStatus WINGDIPAPI GdipGetPathPointsI(GpPath *path, GpPoint* points, INT count)
ret = GdipGetPathPoints(path,ptf,count);
if(ret == Ok)
for(i = 0;i < count;i++){
points[i].X = roundr(ptf[i].X);
points[i].Y = roundr(ptf[i].Y);
points[i].X = gdip_round(ptf[i].X);
points[i].Y = gdip_round(ptf[i].Y);
};
GdipFree(ptf);
@ -1460,10 +1494,10 @@ GpStatus WINGDIPAPI GdipGetPathWorldBoundsI(GpPath* path, GpRect* bounds,
ret = GdipGetPathWorldBounds(path,&boundsF,matrix,pen);
if(ret == Ok){
bounds->X = roundr(boundsF.X);
bounds->Y = roundr(boundsF.Y);
bounds->Width = roundr(boundsF.Width);
bounds->Height = roundr(boundsF.Height);
bounds->X = gdip_round(boundsF.X);
bounds->Y = gdip_round(boundsF.Y);
bounds->Width = gdip_round(boundsF.Width);
bounds->Height = gdip_round(boundsF.Height);
}
return ret;
@ -1589,7 +1623,7 @@ GpStatus WINGDIPAPI GdipIsVisiblePathPoint(GpPath* path, REAL x, REAL y, GpGraph
return status;
}
*result = PtInRegion(hrgn, roundr(x), roundr(y));
*result = PtInRegion(hrgn, gdip_round(x), gdip_round(y));
DeleteObject(hrgn);
GdipDeleteRegion(region);
@ -1688,6 +1722,35 @@ static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *
{
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:
case LineJoinBevel:
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)
add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
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)
{
int i;
path_list_node_t *prev_point;
if (end <= start)
return;
prev_point = *last_point;
widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
pen, pen->startcap, pen->customstart, FALSE, TRUE, last_point);
(*last_point)->type = PathPointTypeStart;
for (i=start+1; i<end; i++)
widen_joint(&path->pathdata.Points[i-1], &path->pathdata.Points[i],
&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],
pen, pen->startcap, pen->customstart, TRUE, FALSE, last_point);
prev_point->next->type = PathPointTypeStart;
(*last_point)->type |= PathPointTypeCloseSubpath;
}
@ -1813,16 +1946,16 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
{
last_point = points;
if (pen->endcap != LineCapFlat)
if (pen->endcap > LineCapRound)
FIXME("unimplemented end cap %x\n", pen->endcap);
if (pen->startcap != LineCapFlat)
if (pen->startcap > LineCapRound)
FIXME("unimplemented start cap %x\n", pen->startcap);
if (pen->dashcap != DashCapFlat)
FIXME("unimplemented dash cap %d\n", pen->dashcap);
if (pen->join != LineJoinBevel)
if (pen->join == LineJoinRound)
FIXME("unimplemented line join %d\n", pen->join);
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)
for(i = 0; i < count; i++){
pts[i].X = roundr(ptsF[i].X);
pts[i].Y = roundr(ptsF[i].Y);
pts[i].X = gdip_round(ptsF[i].X);
pts[i].Y = gdip_round(ptsF[i].Y);
}
GdipFree(ptsF);
@ -474,8 +474,8 @@ GpStatus WINGDIPAPI GdipVectorTransformMatrixPointsI(GpMatrix *matrix, GpPoint *
/* store back */
if(ret == Ok)
for(i = 0; i < count; i++){
pts[i].X = roundr(ptsF[i].X);
pts[i].Y = roundr(ptsF[i].Y);
pts[i].X = gdip_round(ptsF[i].X);
pts[i].Y = gdip_round(ptsF[i].Y);
}
GdipFree(ptsF);

View file

@ -232,10 +232,7 @@ GpStatus WINGDIPAPI GdipRecordMetafile(HDC hdc, EmfType type, GDIPCONST GpRectF
(*metafile)->image.type = ImageTypeMetafile;
(*metafile)->image.picture = NULL;
(*metafile)->image.flags = ImageFlagsNone;
(*metafile)->image.palette_flags = 0;
(*metafile)->image.palette_count = 0;
(*metafile)->image.palette_size = 0;
(*metafile)->image.palette_entries = NULL;
(*metafile)->image.palette = NULL;
(*metafile)->bounds = *frameRect;
(*metafile)->unit = frameUnit;
(*metafile)->metafile_type = type;
@ -551,3 +548,41 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
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:
(*element2)->elementdata.rect = element->elementdata.rect;
break;
return Ok;
case RegionDataEmptyRect:
case RegionDataInfiniteRect:
break;
return Ok;
case RegionDataPath:
(*element2)->elementdata.pathdata.pathheader = element->elementdata.pathdata.pathheader;
stat = GdipClonePath(element->elementdata.pathdata.path,
&(*element2)->elementdata.pathdata.path);
if (stat != Ok) goto clone_out;
if (stat == Ok) return Ok;
break;
default:
(*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,
&(*element2)->elementdata.combine.left);
if (stat != Ok) goto clone_out;
stat = clone_element(element->elementdata.combine.right,
&(*element2)->elementdata.combine.right);
if (stat != Ok) goto clone_out;
if (stat == Ok)
{
stat = clone_element(element->elementdata.combine.right,
&(*element2)->elementdata.combine.right);
if (stat == Ok) return Ok;
}
break;
}
return Ok;
clone_out:
delete_element(*element2);
*element2 = NULL;
return stat;
@ -254,20 +253,20 @@ GpStatus WINGDIPAPI GdipCombineRegionPath(GpRegion *region, GpPath *path, Combin
}
left = GdipAlloc(sizeof(region_element));
if (!left)
goto out;
*left = region->node;
if (left)
{
*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);
GdipDeleteRegion(path_region);
return stat;
@ -301,20 +300,20 @@ GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region,
}
left = GdipAlloc(sizeof(region_element));
if (!left)
goto out;
memcpy(left, &region->node, sizeof(region_element));
if (left)
{
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);
GdipDeleteRegion(rect_region);
return stat;
@ -399,6 +398,8 @@ GpStatus WINGDIPAPI GdipCreateRegion(GpRegion **region)
if(!*region)
return OutOfMemory;
TRACE("=> %p\n", *region);
return init_region(*region, RegionDataInfiniteRect);
}
@ -680,6 +681,7 @@ GpStatus WINGDIPAPI GdipGetRegionBounds(GpRegion *region, GpGraphics *graphics,
if(!hrgn){
rect->X = rect->Y = -(REAL)(1 << 22);
rect->Width = rect->Height = (REAL)(1 << 23);
TRACE("%p => infinite\n", region);
return Ok;
}
@ -688,6 +690,7 @@ GpStatus WINGDIPAPI GdipGetRegionBounds(GpRegion *region, GpGraphics *graphics,
rect->Y = r.top;
rect->Width = r.right - r.left;
rect->Height = r.bottom - r.top;
TRACE("%p => %s\n", region, debugstr_rectf(rect));
}
else
status = GenericError;
@ -712,10 +715,10 @@ GpStatus WINGDIPAPI GdipGetRegionBoundsI(GpRegion *region, GpGraphics *graphics,
status = GdipGetRegionBounds(region, graphics, &rectf);
if(status == Ok){
rect->X = roundr(rectf.X);
rect->Y = roundr(rectf.X);
rect->Width = roundr(rectf.Width);
rect->Height = roundr(rectf.Height);
rect->X = gdip_round(rectf.X);
rect->Y = gdip_round(rectf.X);
rect->Width = gdip_round(rectf.Width);
rect->Height = gdip_round(rectf.Height);
}
return status;
@ -1080,12 +1083,19 @@ GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *region, GpGraphics *graphics, HR
GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
{
GpStatus status;
GpRectF rect;
TRACE("(%p, %p, %p)\n", region, graphics, res);
if(!region || !graphics || !res)
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;
}
@ -1210,7 +1220,7 @@ GpStatus WINGDIPAPI GdipIsVisibleRegionPoint(GpRegion* region, REAL x, REAL y, G
return Ok;
}
*res = PtInRegion(hrgn, roundr(x), roundr(y));
*res = PtInRegion(hrgn, gdip_round(x), gdip_round(y));
DeleteObject(hrgn);

View file

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

View file

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

View file

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

View file

@ -46,7 +46,40 @@ typedef INT PixelFormat;
#define PixelFormat48bppRGB (12 | (48 << 8) | PixelFormatExtended)
#define PixelFormat64bppARGB (13 | (64 << 8) | PixelFormatAlpha | PixelFormatCanonical | 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