[WINESYNC] Sync gdiplus to Wine 7abca97

This commit is contained in:
Maj Soklič 2024-04-29 22:50:17 +02:00
parent 68a8619b7b
commit 49389438a3
19 changed files with 2630 additions and 1246 deletions

View file

@ -96,7 +96,7 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
*clone = heap_alloc_zero(sizeof(GpPathGradient));
if (!*clone) return OutOfMemory;
src = (GpPathGradient*) brush,
src = (GpPathGradient*) brush;
dest = (GpPathGradient*) *clone;
memcpy(dest, src, sizeof(GpPathGradient));
@ -226,40 +226,65 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
return Ok;
}
static const char HatchBrushes[][8] = {
{ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }, /* HatchStyleHorizontal */
{ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, /* HatchStyleVertical */
{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, /* HatchStyleForwardDiagonal */
{ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, /* HatchStyleBackwardDiagonal */
{ 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08 }, /* HatchStyleCross */
{ 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }, /* HatchStyleDiagonalCross */
/* The first 8 items per entry are bitmaps for each row of the hatch style.
* The 9th item of the entry is a flag indicating anti-aliasing. */
static const unsigned char HatchBrushes[][9] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, /* HatchStyleHorizontal */
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, /* HatchStyleVertical */
{ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, TRUE }, /* HatchStyleForwardDiagonal */
{ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, TRUE }, /* HatchStyleBackwardDiagonal */
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff }, /* HatchStyleCross */
{ 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81, TRUE }, /* HatchStyleDiagonalCross */
{ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80 }, /* HatchStyle05Percent */
{ 0x00, 0x02, 0x00, 0x88, 0x00, 0x20, 0x00, 0x88 }, /* HatchStyle10Percent */
{ 0x00, 0x22, 0x00, 0xcc, 0x00, 0x22, 0x00, 0xcc }, /* HatchStyle20Percent */
{ 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc }, /* HatchStyle25Percent */
{ 0x00, 0xcc, 0x04, 0xcc, 0x00, 0xcc, 0x40, 0xcc }, /* HatchStyle30Percent */
{ 0x44, 0xcc, 0x22, 0xcc, 0x44, 0xcc, 0x22, 0xcc }, /* HatchStyle40Percent */
{ 0x55, 0xcc, 0x55, 0xcc, 0x55, 0xcc, 0x55, 0xcc }, /* HatchStyle50Percent */
{ 0x55, 0xcd, 0x55, 0xee, 0x55, 0xdc, 0x55, 0xee }, /* HatchStyle60Percent */
{ 0x55, 0xdd, 0x55, 0xff, 0x55, 0xdd, 0x55, 0xff }, /* HatchStyle70Percent */
{ 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff }, /* HatchStyle75Percent */
{ 0x55, 0xff, 0x59, 0xff, 0x55, 0xff, 0x99, 0xff }, /* HatchStyle80Percent */
{ 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xfd, 0xff }, /* HatchStyle90Percent */
{ 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00, 0x80 }, /* HatchStyle10Percent */
{ 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00, 0x88 }, /* HatchStyle20Percent */
{ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88 }, /* HatchStyle25Percent */
{ 0x11, 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa }, /* HatchStyle30Percent */
{ 0x15, 0xaa, 0x55, 0xaa, 0x51, 0xaa, 0x55, 0xaa }, /* HatchStyle40Percent */
{ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }, /* HatchStyle50Percent */
{ 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee }, /* HatchStyle60Percent */
{ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77 }, /* HatchStyle70Percent */
{ 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77 }, /* HatchStyle75Percent */
{ 0xff, 0xfe, 0xff, 0xef, 0xff, 0xfe, 0xff, 0xef }, /* HatchStyle80Percent */
{ 0x7f, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff }, /* HatchStyle90Percent */
{ 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, /* HatchStyleLightDownwardDiagonal */
{ 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 }, /* HatchStyleLightUpwardDiagonal */
{ 0x99, 0x33, 0x66, 0xcc, 0x99, 0x33, 0x66, 0xcc }, /* HatchStyleDarkDownwardDiagonal */
{ 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 }, /* HatchStyleDarkUpwardDiagonal */
{ 0xc1, 0x83, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0 }, /* HatchStyleWideDownwardDiagonal */
{ 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x83, 0xc1 }, /* HatchStyleWideUpwardDiagonal */
{ 0x99, 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33 }, /* HatchStyleDarkUpwardDiagonal */
{ 0x83, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xc1 }, /* HatchStyleWideDownwardDiagonal */
{ 0xc1, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x83 }, /* HatchStyleWideUpwardDiagonal */
{ 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, /* HatchStyleLightVertical */
{ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff }, /* HatchStyleLightHorizontal */
{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, /* HatchStyleNarrowVertical */
{ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, /* HatchStyleNarrowVertical */
{ 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, /* HatchStyleNarrowHorizontal */
{ 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }, /* HatchStyleDarkVertical */
{ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff }, /* HatchStyleDarkHorizontal */
{ 0x00, 0x00, 0x11, 0x22, 0x44, 0x88, 0x00, 0x00 }, /* HatchStyleDashedDownwardDiagonal */
{ 0x00, 0x00, 0x88, 0x44, 0x22, 0x11, 0x00, 0x00 }, /* HatchStyleDashedUpwardDiagonal */
{ 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf0 }, /* HatchStyleDashedHorizontal */
{ 0x08, 0x08, 0x08, 0x08, 0x80, 0x80, 0x80, 0x80 }, /* HatchStyleDashedVertical */
{ 0x04, 0x20, 0x01, 0x10, 0x02, 0x40, 0x08, 0x80 }, /* HatchStyleSmallConfetti */
{ 0x8d, 0x0c, 0xc0, 0xd8, 0x1b, 0x03, 0x30, 0xb1 }, /* HatchStyleLargeConfetti */
{ 0x18, 0x24, 0x42, 0x81, 0x18, 0x24, 0x42, 0x81 }, /* HatchStyleZigZag */
{ 0xc0, 0x25, 0x18, 0x00, 0xc0, 0x25, 0x18, 0x00 }, /* HatchStyleWave */
{ 0x81, 0x42, 0x24, 0x18, 0x08, 0x04, 0x02, 0x01 }, /* HatchStyleDiagonalBrick */
{ 0x08, 0x08, 0x08, 0xff, 0x80, 0x80, 0x80, 0xff }, /* HatchStyleHorizontalBrick */
{ 0x51, 0x22, 0x14, 0x88, 0x45, 0x22, 0x54, 0x88 }, /* HatchStyleWeave */
{ 0xf0, 0xf0, 0xf0, 0xf0, 0x55, 0xaa, 0x55, 0xaa }, /* HatchStylePlaid */
{ 0x80, 0x01, 0x80, 0x00, 0x10, 0x08, 0x10, 0x00 }, /* HatchStyleDivot */
{ 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xaa }, /* HatchStyleDottedGrid */
{ 0x00, 0x22, 0x00, 0x08, 0x00, 0x22, 0x00, 0x80 }, /* HatchStyleDottedDiamond */
{ 0x01, 0x01, 0x02, 0x0c, 0x30, 0x48, 0x84, 0x03 }, /* HatchStyleShingle */
{ 0x99, 0xff, 0x66, 0xff, 0x99, 0xff, 0x66, 0xff }, /* HatchStyleTrellis */
{ 0xf8, 0xf8, 0x98, 0x77, 0x8f, 0x8f, 0x89, 0x77 }, /* HatchStyleSphere */
{ 0x88, 0x88, 0x88, 0xff, 0x88, 0x88, 0x88, 0xff }, /* HatchStyleSmallGrid */
{ 0x99, 0x66, 0x66, 0x99, 0x99, 0x66, 0x66, 0x99 }, /* HatchStyleSmallCheckerBoard */
{ 0x0f, 0x0f, 0x0f, 0x0f, 0xf0, 0xf0, 0xf0, 0xf0 }, /* HatchStyleLargeCheckerBoard */
{ 0x01, 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82 }, /* HatchStyleOutlinedDiamond */
{ 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10 }, /* HatchStyleSolidDiamond */
};
GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result)
GpStatus get_hatch_data(GpHatchStyle hatchstyle, const unsigned char **result)
{
if (hatchstyle < ARRAY_SIZE(HatchBrushes))
{
@ -275,7 +300,7 @@ GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result)
*/
GpStatus WINGDIPAPI GdipCreateHatchBrush(GpHatchStyle hatchstyle, ARGB forecol, ARGB backcol, GpHatch **brush)
{
TRACE("(%d, %d, %d, %p)\n", hatchstyle, forecol, backcol, brush);
TRACE("(%d, %ld, %ld, %p)\n", hatchstyle, forecol, backcol, brush);
if(!brush) return InvalidParameter;
@ -376,7 +401,7 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
GpStatus stat;
GpRectF rect;
TRACE("(%s, %s, %x, %x, %d, %p)\n", debugstr_pointf(startpoint),
TRACE("(%s, %s, %lx, %lx, %d, %p)\n", debugstr_pointf(startpoint),
debugstr_pointf(endpoint), startcolor, endcolor, wrap, line);
if(!line || !startpoint || !endpoint || wrap == WrapModeClamp)
@ -419,7 +444,7 @@ GpStatus WINGDIPAPI GdipCreateLineBrushI(GDIPCONST GpPoint* startpoint,
GpPointF stF;
GpPointF endF;
TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint, endpoint,
TRACE("(%p, %p, %lx, %lx, %d, %p)\n", startpoint, endpoint,
startcolor, endcolor, wrap, line);
if(!startpoint || !endpoint)
@ -439,7 +464,7 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect,
{
float angle;
TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
TRACE("(%s, %lx, %lx, %d, %d, %p)\n", debugstr_rectf(rect), startcolor, endcolor, mode,
wrap, line);
if(!line || !rect)
@ -472,14 +497,10 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectI(GDIPCONST GpRect* rect,
{
GpRectF rectF;
TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
TRACE("(%p, %lx, %lx, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
wrap, line);
rectF.X = (REAL) rect->X;
rectF.Y = (REAL) rect->Y;
rectF.Width = (REAL) rect->Width;
rectF.Height = (REAL) rect->Height;
set_rect(&rectF, rect->X, rect->Y, rect->Width, rect->Height);
return GdipCreateLineBrushFromRect(&rectF, startcolor, endcolor, mode, wrap, line);
}
@ -495,7 +516,7 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF* rect
REAL sin_angle, cos_angle, sin_cos_angle;
GpPointF start, end;
TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
TRACE("(%s, %lx, %lx, %.2f, %d, %d, %p)\n", debugstr_rectf(rect), startcolor, endcolor, angle, isAngleScalable,
wrap, line);
if (!rect || !line || wrap == WrapModeClamp)
@ -594,7 +615,7 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect* rect
ARGB startcolor, ARGB endcolor, REAL angle, BOOL isAngleScalable, GpWrapMode wrap,
GpLineGradient **line)
{
TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
TRACE("(%p, %lx, %lx, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
wrap, line);
return GdipCreateLineBrushFromRectI(rect, startcolor, endcolor, LinearGradientModeForwardDiagonal,
@ -603,7 +624,8 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect* rect
static GpStatus create_path_gradient(GpPath *path, ARGB centercolor, GpPathGradient **grad)
{
GpRectF bounds;
INT i;
REAL sum_x = 0, sum_y = 0;
if(!path || !grad)
return InvalidParameter;
@ -611,8 +633,6 @@ static GpStatus create_path_gradient(GpPath *path, ARGB centercolor, GpPathGradi
if (path->pathdata.Count < 2)
return OutOfMemory;
GdipGetPathWorldBounds(path, &bounds, NULL, NULL);
*grad = heap_alloc_zero(sizeof(GpPathGradient));
if (!*grad)
{
@ -642,9 +662,14 @@ static GpStatus create_path_gradient(GpPath *path, ARGB centercolor, GpPathGradi
(*grad)->centercolor = centercolor;
(*grad)->wrap = WrapModeClamp;
(*grad)->gamma = FALSE;
/* FIXME: this should be set to the "centroid" of the path by default */
(*grad)->center.X = bounds.X + bounds.Width / 2;
(*grad)->center.Y = bounds.Y + bounds.Height / 2;
for (i=0; i<path->pathdata.Count; i++)
{
sum_x += path->pathdata.Points[i].X;
sum_y += path->pathdata.Points[i].Y;
}
(*grad)->center.X = sum_x / path->pathdata.Count;
(*grad)->center.Y = sum_y / path->pathdata.Count;
(*grad)->focus.X = 0.0;
(*grad)->focus.Y = 0.0;
(*grad)->surroundcolors[0] = 0xffffffff;
@ -756,7 +781,7 @@ GpStatus WINGDIPAPI GdipCreatePathGradientFromPath(GDIPCONST GpPath* path,
*/
GpStatus WINGDIPAPI GdipCreateSolidFill(ARGB color, GpSolidFill **sf)
{
TRACE("(%x, %p)\n", color, sf);
TRACE("(%lx, %p)\n", color, sf);
if(!sf) return InvalidParameter;
@ -1656,7 +1681,7 @@ GpStatus WINGDIPAPI GdipGetPathGradientPresetBlendCount(GpPathGradient *brush,
GpStatus WINGDIPAPI GdipSetPathGradientCenterColor(GpPathGradient *grad,
ARGB argb)
{
TRACE("(%p, %x)\n", grad, argb);
TRACE("(%p, %lx)\n", grad, argb);
if(!grad || grad->brush.bt != BrushTypePathGradient)
return InvalidParameter;
@ -1924,7 +1949,7 @@ GpStatus WINGDIPAPI GdipTranslatePathGradientTransform(GpPathGradient *grad,
GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb)
{
TRACE("(%p, %x)\n", sf, argb);
TRACE("(%p, %lx)\n", sf, argb);
if(!sf)
return InvalidParameter;
@ -1969,7 +1994,7 @@ GpStatus WINGDIPAPI GdipSetTextureWrapMode(GpTexture *brush, GpWrapMode wrapmode
GpStatus WINGDIPAPI GdipSetLineColors(GpLineGradient *brush, ARGB color1,
ARGB color2)
{
TRACE("(%p, %x, %x)\n", brush, color1, color2);
TRACE("(%p, %lx, %lx)\n", brush, color1, color2);
if(!brush || brush->brush.bt != BrushTypeLinearGradient)
return InvalidParameter;

View file

@ -25,7 +25,6 @@
#include "winnls.h"
#include "winreg.h"
#include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL (gdiplus);
@ -107,7 +106,7 @@ typedef struct
#define GET_BE_DWORD(x) (x)
#else
#define GET_BE_WORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
#define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)));
#define GET_BE_DWORD(x) MAKELONG(GET_BE_WORD(HIWORD(x)), GET_BE_WORD(LOWORD(x)))
#endif
#define MS_MAKE_TAG(ch0, ch1, ch2, ch3) \
@ -116,10 +115,17 @@ typedef struct
#define MS_OS2_TAG MS_MAKE_TAG('O','S','/','2')
#define MS_HHEA_TAG MS_MAKE_TAG('h','h','e','a')
static GpStatus clone_font_family(const GpFontFamily *, GpFontFamily **);
static GpFontCollection installedFontCollection = {0};
static CRITICAL_SECTION font_cs;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &font_cs,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": font_cs") }
};
static CRITICAL_SECTION font_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
/*******************************************************************************
* GdipCreateFont [GDIPLUS.@]
*
@ -162,7 +168,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
stat = GdipGetFamilyName(fontFamily, lfw.lfFaceName, LANG_NEUTRAL);
if (stat != Ok) return stat;
lfw.lfHeight = -units_to_pixels(emSize, unit, fontFamily->dpi);
lfw.lfHeight = -units_to_pixels(emSize, unit, fontFamily->dpi, FALSE);
lfw.lfWeight = style & FontStyleBold ? FW_BOLD : FW_REGULAR;
lfw.lfItalic = style & FontStyleItalic;
lfw.lfUnderline = style & FontStyleUnderline;
@ -184,13 +190,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
(*font)->unit = unit;
(*font)->emSize = emSize;
(*font)->otm = otm;
stat = clone_font_family(fontFamily, &(*font)->family);
if (stat != Ok)
{
heap_free(*font);
return stat;
}
GdipCloneFontFamily((GpFontFamily*)fontFamily, &(*font)->family);
TRACE("<-- %p\n", *font);
@ -228,7 +228,7 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
if (!*font) return OutOfMemory;
(*font)->unit = UnitWorld;
(*font)->emSize = otm.otmTextMetrics.tmAscent;
(*font)->emSize = otm.otmTextMetrics.tmHeight - otm.otmTextMetrics.tmInternalLeading;
(*font)->otm = otm;
stat = GdipCreateFontFamilyFromName(facename, NULL, &(*font)->family);
@ -354,7 +354,7 @@ GpStatus WINGDIPAPI GdipGetFontSize(GpFont *font, REAL *size)
if (!(font && size)) return InvalidParameter;
*size = get_font_size(font);
TRACE("%s,%d => %f\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *size);
TRACE("%s,%ld => %f\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *size);
return Ok;
}
@ -398,7 +398,7 @@ GpStatus WINGDIPAPI GdipGetFontStyle(GpFont *font, INT *style)
return InvalidParameter;
*style = get_font_style(font);
TRACE("%s,%d => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *style);
TRACE("%s,%ld => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *style);
return Ok;
}
@ -421,7 +421,7 @@ GpStatus WINGDIPAPI GdipGetFontUnit(GpFont *font, Unit *unit)
if (!(font && unit)) return InvalidParameter;
*unit = font->unit;
TRACE("%s,%d => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *unit);
TRACE("%s,%ld => %d\n", debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *unit);
return Ok;
}
@ -467,16 +467,16 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW
if (font->unit == UnitPixel || font->unit == UnitWorld)
{
height = units_to_pixels(font->emSize, graphics->unit, graphics->yres);
height = units_to_pixels(font->emSize, graphics->unit, graphics->yres, graphics->printer_display);
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);
height = units_to_pixels(font->emSize, font->unit, graphics->xres, graphics->printer_display);
else
height = units_to_pixels(font->emSize, font->unit, graphics->yres);
height = units_to_pixels(font->emSize, font->unit, graphics->yres, graphics->printer_display);
}
pt[0].X = 0.0;
@ -507,9 +507,9 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW
lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf->lfQuality = DEFAULT_QUALITY;
lf->lfPitchAndFamily = 0;
strcpyW(lf->lfFaceName, font->family->FamilyName);
lstrcpyW(lf->lfFaceName, font->family->FamilyName);
TRACE("=> %s,%d\n", debugstr_w(lf->lfFaceName), lf->lfHeight);
TRACE("=> %s,%ld\n", debugstr_w(lf->lfFaceName), lf->lfHeight);
return Ok;
}
@ -519,8 +519,6 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW
*/
GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
{
GpStatus stat;
TRACE("(%p, %p)\n", font, cloneFont);
if(!font || !cloneFont)
@ -530,10 +528,7 @@ GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
if(!*cloneFont) return OutOfMemory;
**cloneFont = *font;
stat = GdipCloneFontFamily(font->family, &(*cloneFont)->family);
if (stat != Ok) heap_free(*cloneFont);
return stat;
return Ok;
}
/*******************************************************************************
@ -566,7 +561,7 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
if (!graphics)
{
*height = font_height;
TRACE("%s,%d => %f\n",
TRACE("%s,%ld => %f\n",
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *height);
return Ok;
}
@ -574,9 +569,9 @@ GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
stat = GdipGetDpiY((GpGraphics *)graphics, &dpi);
if (stat != Ok) return stat;
*height = pixels_to_units(font_height, graphics->unit, dpi);
*height = pixels_to_units(font_height, graphics->unit, dpi, graphics->printer_display);
TRACE("%s,%d(unit %d) => %f\n",
TRACE("%s,%ld(unit %d) => %f\n",
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, graphics->unit, *height);
return Ok;
}
@ -608,7 +603,7 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
TRACE("%p (%s), %f, %p\n", font,
debugstr_w(font->family->FamilyName), dpi, height);
font_size = units_to_pixels(get_font_size(font), font->unit, dpi);
font_size = units_to_pixels(get_font_size(font), font->unit, dpi, FALSE);
style = get_font_style(font);
stat = GdipGetLineSpacing(font->family, style, &line_spacing);
if (stat != Ok) return stat;
@ -617,7 +612,7 @@ GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi,
*height = (REAL)line_spacing * font_size / (REAL)em_height;
TRACE("%s,%d => %f\n",
TRACE("%s,%ld => %f\n",
debugstr_w(font->family->FamilyName), font->otm.otmTextMetrics.tmHeight, *height);
return Ok;
@ -700,29 +695,6 @@ static BOOL get_font_metrics(HDC hdc, struct font_metrics *fm)
return TRUE;
}
static GpStatus find_installed_font(const WCHAR *name, struct font_metrics *fm)
{
LOGFONTW lf;
HDC hdc = CreateCompatibleDC(0);
GpStatus ret = FontFamilyNotFound;
if(!EnumFontFamiliesW(hdc, name, is_font_installed_proc, (LPARAM)&lf))
{
HFONT hfont, old_font;
strcpyW(fm->facename, lf.lfFaceName);
hfont = CreateFontIndirectW(&lf);
old_font = SelectObject(hdc, hfont);
ret = get_font_metrics(hdc, fm) ? Ok : NotTrueTypeFont;
SelectObject(hdc, old_font);
DeleteObject(hfont);
}
DeleteDC(hdc);
return ret;
}
/*******************************************************************************
* GdipCreateFontFamilyFromName [GDIPLUS.@]
*
@ -744,48 +716,44 @@ static GpStatus find_installed_font(const WCHAR *name, struct font_metrics *fm)
*/
GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
GpFontCollection *fontCollection,
GpFontFamily **FontFamily)
GpFontCollection *collection,
GpFontFamily **family)
{
GpStatus stat;
GpFontFamily* ffamily;
struct font_metrics fm;
HDC hdc;
LOGFONTW lf;
GpStatus status;
int i;
TRACE("%s, %p %p\n", debugstr_w(name), fontCollection, FontFamily);
TRACE("%s, %p %p\n", debugstr_w(name), collection, family);
if (!(name && FontFamily))
if (!name || !family)
return InvalidParameter;
if (fontCollection)
FIXME("No support for FontCollections yet!\n");
stat = find_installed_font(name, &fm);
if (stat != Ok) return stat;
if (!collection)
{
status = GdipNewInstalledFontCollection(&collection);
if (status != Ok) return status;
}
ffamily = heap_alloc_zero(sizeof (GpFontFamily));
if (!ffamily) return OutOfMemory;
status = FontFamilyNotFound;
lstrcpyW(ffamily->FamilyName, fm.facename);
ffamily->em_height = fm.em_height;
ffamily->ascent = fm.ascent;
ffamily->descent = fm.descent;
ffamily->line_spacing = fm.line_spacing;
ffamily->dpi = fm.dpi;
hdc = CreateCompatibleDC(0);
*FontFamily = ffamily;
if (!EnumFontFamiliesW(hdc, name, is_font_installed_proc, (LPARAM)&lf))
{
for (i = 0; i < collection->count; i++)
{
if (!wcsicmp(lf.lfFaceName, collection->FontFamilies[i]->FamilyName))
{
status = GdipCloneFontFamily(collection->FontFamilies[i], family);
TRACE("<-- %p\n", *family);
break;
}
}
}
TRACE("<-- %p\n", ffamily);
return Ok;
}
static GpStatus clone_font_family(const GpFontFamily *family, GpFontFamily **clone)
{
*clone = heap_alloc_zero(sizeof(GpFontFamily));
if (!*clone) return OutOfMemory;
**clone = *family;
return Ok;
DeleteDC(hdc);
return status;
}
/*******************************************************************************
@ -800,19 +768,17 @@ static GpStatus clone_font_family(const GpFontFamily *family, GpFontFamily **clo
* RETURNS
* SUCCESS: Ok
*/
GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily** clonedFontFamily)
GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily *family, GpFontFamily **clone)
{
GpStatus status;
if (!family || !clone)
return InvalidParameter;
if (!(FontFamily && clonedFontFamily)) return InvalidParameter;
TRACE("%p (%s), %p\n", family, debugstr_w(family->FamilyName), clone);
TRACE("%p (%s), %p\n", FontFamily,
debugstr_w(FontFamily->FamilyName), clonedFontFamily);
*clone = family;
status = clone_font_family(FontFamily, clonedFontFamily);
if (status != Ok) return status;
TRACE("<-- %p\n", *clonedFontFamily);
if (!family->installed)
InterlockedIncrement(&family->ref);
return Ok;
}
@ -832,17 +798,20 @@ GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily* FontFamily, GpFontFamily**
* FAILURE: InvalidParameter if family is NULL
*
* NOTES
* If name is a NULL ptr, then both XP and Vista will crash (so we do as well)
* If name is NULL, XP and Vista crash but not Windows 7+
*/
GpStatus WINGDIPAPI GdipGetFamilyName (GDIPCONST GpFontFamily *family,
WCHAR *name, LANGID language)
{
static int lang_fixme;
TRACE("%p, %p, %d\n", family, name, language);
if (family == NULL)
return InvalidParameter;
TRACE("%p, %p, %d\n", family, name, language);
if (name == NULL)
return Ok;
if (language != LANG_NEUTRAL && !lang_fixme++)
FIXME("No support for handling of multiple languages!\n");
@ -870,9 +839,11 @@ GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily *FontFamily)
{
if (!FontFamily)
return InvalidParameter;
TRACE("Deleting %p (%s)\n", FontFamily, debugstr_w(FontFamily->FamilyName));
heap_free (FontFamily);
if (!FontFamily->installed && !InterlockedDecrement(&FontFamily->ref))
{
heap_free(FontFamily);
}
return Ok;
}
@ -1009,16 +980,14 @@ GpStatus WINGDIPAPI GdipIsStyleAvailable(GDIPCONST GpFontFamily* family,
*/
GpStatus WINGDIPAPI GdipGetGenericFontFamilyMonospace(GpFontFamily **nativeFamily)
{
static const WCHAR CourierNew[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'};
static const WCHAR LiberationMono[] = {'L','i','b','e','r','a','t','i','o','n',' ','M','o','n','o','\0'};
GpStatus stat;
if (nativeFamily == NULL) return InvalidParameter;
stat = GdipCreateFontFamilyFromName(CourierNew, NULL, nativeFamily);
stat = GdipCreateFontFamilyFromName(L"Courier New", NULL, nativeFamily);
if (stat == FontFamilyNotFound)
stat = GdipCreateFontFamilyFromName(LiberationMono, NULL, nativeFamily);
stat = GdipCreateFontFamilyFromName(L"Liberation Mono", NULL, nativeFamily);
if (stat == FontFamilyNotFound)
ERR("Missing 'Courier New' font\n");
@ -1040,18 +1009,16 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilyMonospace(GpFontFamily **nativeFamil
*/
GpStatus WINGDIPAPI GdipGetGenericFontFamilySerif(GpFontFamily **nativeFamily)
{
static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
static const WCHAR LiberationSerif[] = {'L','i','b','e','r','a','t','i','o','n',' ','S','e','r','i','f','\0'};
GpStatus stat;
TRACE("(%p)\n", nativeFamily);
if (nativeFamily == NULL) return InvalidParameter;
stat = GdipCreateFontFamilyFromName(TimesNewRoman, NULL, nativeFamily);
stat = GdipCreateFontFamilyFromName(L"Times New Roman", NULL, nativeFamily);
if (stat == FontFamilyNotFound)
stat = GdipCreateFontFamilyFromName(LiberationSerif, NULL, nativeFamily);
stat = GdipCreateFontFamilyFromName(L"Liberation Serif", NULL, nativeFamily);
if (stat == FontFamilyNotFound)
ERR("Missing 'Times New Roman' font\n");
@ -1074,24 +1041,22 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilySerif(GpFontFamily **nativeFamily)
GpStatus WINGDIPAPI GdipGetGenericFontFamilySansSerif(GpFontFamily **nativeFamily)
{
GpStatus stat;
static const WCHAR MicrosoftSansSerif[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
static const WCHAR Tahoma[] = {'T','a','h','o','m','a','\0'};
TRACE("(%p)\n", nativeFamily);
if (nativeFamily == NULL) return InvalidParameter;
stat = GdipCreateFontFamilyFromName(MicrosoftSansSerif, NULL, nativeFamily);
stat = GdipCreateFontFamilyFromName(L"Microsoft Sans Serif", NULL, nativeFamily);
if (stat == FontFamilyNotFound)
/* FIXME: Microsoft Sans Serif is not installed on Wine. */
stat = GdipCreateFontFamilyFromName(Tahoma, NULL, nativeFamily);
stat = GdipCreateFontFamilyFromName(L"Tahoma", NULL, nativeFamily);
return stat;
}
/*****************************************************************************
* GdipGetGenericFontFamilySansSerif [GDIPLUS.@]
* GdipNewPrivateFontCollection [GDIPLUS.@]
*/
GpStatus WINGDIPAPI GdipNewPrivateFontCollection(GpFontCollection** fontCollection)
{
@ -1124,7 +1089,7 @@ GpStatus WINGDIPAPI GdipDeletePrivateFontCollection(GpFontCollection **fontColle
if (!fontCollection)
return InvalidParameter;
for (i = 0; i < (*fontCollection)->count; i++) heap_free((*fontCollection)->FontFamilies[i]);
for (i = 0; i < (*fontCollection)->count; i++) GdipDeleteFontFamily((*fontCollection)->FontFamilies[i]);
heap_free((*fontCollection)->FontFamilies);
heap_free(*fontCollection);
@ -1185,14 +1150,16 @@ GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection *collection, GDIPCON
#define NAME_ID_FULL_FONT_NAME 4
typedef struct {
USHORT major_version;
USHORT minor_version;
ULONG version;
USHORT tables_no;
USHORT search_range;
USHORT entry_selector;
USHORT range_shift;
} tt_header;
#define TT_HEADER_VERSION_1 0x00010000
#define TT_HEADER_VERSION_CFF 0x4f54544f
typedef struct {
char tag[4]; /* table name */
ULONG check_sum; /* Check sum */
@ -1437,7 +1404,8 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id )
header = (const tt_header*)mem;
count = GET_BE_WORD(header->tables_no);
if (GET_BE_WORD(header->major_version) != 1 || GET_BE_WORD(header->minor_version) != 0)
if (GET_BE_DWORD(header->version) != TT_HEADER_VERSION_1 &&
GET_BE_DWORD(header->version) != TT_HEADER_VERSION_CFF)
return NULL;
pos = sizeof(*header);
@ -1499,6 +1467,7 @@ struct add_font_param
GpFontCollection *collection;
BOOL is_system;
GpStatus stat;
HDC hdc;
};
static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, DWORD type, LPARAM lParam);
@ -1523,16 +1492,15 @@ GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
return OutOfMemory;
font = AddFontMemResourceEx((void*)memory, length, NULL, &count);
TRACE("%s: %p/%u\n", debugstr_w(name), font, count);
TRACE("%s: %p/%lu\n", debugstr_w(name), font, count);
if (!font || !count)
ret = InvalidParameter;
else
{
struct add_font_param param;
HDC hdc;
LOGFONTW lfw;
hdc = CreateCompatibleDC(0);
param.hdc = CreateCompatibleDC(0);
/* Truncate name if necessary, GDI32 can't deal with long names */
if(lstrlenW(name) > LF_FACESIZE - 1)
@ -1544,10 +1512,10 @@ GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
param.collection = fontCollection;
param.is_system = FALSE;
if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)&param, 0))
if (!EnumFontFamiliesExW(param.hdc, &lfw, add_font_proc, (LPARAM)&param, 0))
ret = param.stat;
DeleteDC(hdc);
DeleteDC(param.hdc);
}
heap_free(name);
return ret;
@ -1576,7 +1544,6 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList(
GpFontFamily* gpfamilies[], INT* numFound)
{
INT i;
GpStatus stat=Ok;
TRACE("%p, %d, %p, %p\n", fontCollection, numSought, gpfamilies, numFound);
@ -1585,31 +1552,25 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList(
memset(gpfamilies, 0, sizeof(*gpfamilies) * numSought);
for (i = 0; i < numSought && i < fontCollection->count && stat == Ok; i++)
for (i = 0; i < numSought && i < fontCollection->count; i++)
{
stat = GdipCloneFontFamily(fontCollection->FontFamilies[i], &gpfamilies[i]);
/* caller is responsible for cloning these if it keeps references */
gpfamilies[i] = fontCollection->FontFamilies[i];
}
if (stat == Ok)
*numFound = i;
else
{
int numToFree=i;
for (i=0; i<numToFree; i++)
{
GdipDeleteFontFamily(gpfamilies[i]);
gpfamilies[i] = NULL;
}
}
*numFound = i;
return stat;
return Ok;
}
void free_installed_fonts(void)
{
while (installedFontCollection.count)
GdipDeleteFontFamily(installedFontCollection.FontFamilies[--installedFontCollection.count]);
INT i;
for (i = 0; i < installedFontCollection.count; i++)
heap_free(installedFontCollection.FontFamilies[i]);
heap_free(installedFontCollection.FontFamilies);
installedFontCollection.FontFamilies = NULL;
installedFontCollection.allocated = 0;
}
@ -1619,8 +1580,9 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm,
{
struct add_font_param *param = (struct add_font_param *)lParam;
GpFontCollection *fonts = param->collection;
GpFontFamily* family;
GpStatus stat;
GpFontFamily *family;
HFONT hfont, old_hfont;
struct font_metrics fm;
int i;
param->stat = Ok;
@ -1632,7 +1594,7 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm,
if (lfw->lfFaceName[0] == '@')
return 1;
if (fonts->count && strcmpiW(lfw->lfFaceName, fonts->FontFamilies[fonts->count-1]->FamilyName) == 0)
if (fonts->count && wcsicmp(lfw->lfFaceName, fonts->FontFamilies[fonts->count-1]->FamilyName) == 0)
return 1;
if (fonts->allocated == fonts->count)
@ -1652,25 +1614,52 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm,
fonts->allocated = new_alloc_count;
}
if ((stat = GdipCreateFontFamilyFromName(lfw->lfFaceName, NULL, &family)) != Ok)
family = heap_alloc(sizeof(*family));
if (!family)
{
WARN("Failed to create font family for %s, status %d.\n", debugstr_w(lfw->lfFaceName), stat);
if (param->is_system)
return 1;
param->stat = stat;
param->stat = OutOfMemory;
return 0;
}
/* skip duplicates */
for (i=0; i<fonts->count; i++)
{
if (strcmpiW(family->FamilyName, fonts->FontFamilies[i]->FamilyName) == 0)
if (wcsicmp(lfw->lfFaceName, fonts->FontFamilies[i]->FamilyName) == 0)
{
GdipDeleteFontFamily(family);
heap_free(family);
return 1;
}
}
hfont = CreateFontIndirectW(lfw);
old_hfont = SelectObject(param->hdc, hfont);
if (!get_font_metrics(param->hdc, &fm))
{
SelectObject(param->hdc, old_hfont);
DeleteObject(hfont);
heap_free(family);
param->stat = OutOfMemory;
return 0;
}
SelectObject(param->hdc, old_hfont);
DeleteObject(hfont);
family->em_height = fm.em_height;
family->ascent = fm.ascent;
family->descent = fm.descent;
family->line_spacing = fm.line_spacing;
family->dpi = fm.dpi;
family->installed = param->is_system;
family->ref = 1;
lstrcpyW(family->FamilyName, lfw->lfFaceName);
fonts->FontFamilies[fonts->count++] = family;
return 1;
@ -1684,13 +1673,13 @@ GpStatus WINGDIPAPI GdipNewInstalledFontCollection(
if (!fontCollection)
return InvalidParameter;
EnterCriticalSection( &font_cs );
if (installedFontCollection.count == 0)
{
struct add_font_param param;
HDC hdc;
LOGFONTW lfw;
hdc = CreateCompatibleDC(0);
param.hdc = CreateCompatibleDC(0);
lfw.lfCharSet = DEFAULT_CHARSET;
lfw.lfFaceName[0] = 0;
@ -1698,15 +1687,17 @@ GpStatus WINGDIPAPI GdipNewInstalledFontCollection(
param.collection = &installedFontCollection;
param.is_system = TRUE;
if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)&param, 0))
if (!EnumFontFamiliesExW(param.hdc, &lfw, add_font_proc, (LPARAM)&param, 0))
{
free_installed_fonts();
DeleteDC(hdc);
DeleteDC(param.hdc);
LeaveCriticalSection( &font_cs );
return param.stat;
}
DeleteDC(hdc);
DeleteDC(param.hdc);
}
LeaveCriticalSection( &font_cs );
*fontCollection = &installedFontCollection;

View file

@ -49,7 +49,7 @@ static Status WINAPI NotificationHook(ULONG_PTR *token)
static void WINAPI NotificationUnhook(ULONG_PTR token)
{
TRACE("%ld\n", token);
TRACE("%Id\n", token);
}
/*****************************************************
@ -57,7 +57,7 @@ static void WINAPI NotificationUnhook(ULONG_PTR token)
*/
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
{
TRACE("(%p, %d, %p)\n", hinst, reason, reserved);
TRACE("(%p, %ld, %p)\n", hinst, reason, reserved);
switch(reason)
{
@ -115,7 +115,7 @@ GpStatus WINAPI GdiplusNotificationHook(ULONG_PTR *token)
void WINAPI GdiplusNotificationUnhook(ULONG_PTR token)
{
FIXME("%ld\n", token);
FIXME("%Id\n", token);
NotificationUnhook(token);
}
@ -202,54 +202,54 @@ static void add_arc_part(GpPointF * pt, REAL x1, REAL y1, REAL x2, REAL y2,
* adjusts the angles so that when we stretch the points they will end in the
* right place. This is only complicated because atan and atan2 do not behave
* conveniently. */
static void unstretch_angle(REAL * angle, REAL rad_x, REAL rad_y)
static REAL unstretch_angle(REAL angle, REAL dia_x, REAL dia_y)
{
REAL stretched;
INT revs_off;
*angle = deg2rad(*angle);
if(fabs(cos(angle)) < 0.00001 || fabs(sin(angle)) < 0.00001)
return angle;
if(fabs(cos(*angle)) < 0.00001 || fabs(sin(*angle)) < 0.00001)
return;
stretched = gdiplus_atan2(sin(*angle) / fabs(rad_y), cos(*angle) / fabs(rad_x));
revs_off = gdip_round(*angle / (2.0 * M_PI)) - gdip_round(stretched / (2.0 * M_PI));
stretched = gdiplus_atan2(sin(angle) / fabs(dia_y), cos(angle) / fabs(dia_x));
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;
return stretched;
}
/* Stores the bezier points that correspond to the arc in points. If points is
* null, just return the number of points needed to represent the arc. */
INT arc2polybezier(GpPointF * points, REAL x1, REAL y1, REAL x2, REAL y2,
REAL startAngle, REAL sweepAngle)
INT arc2polybezier(GpPointF * points, REAL left, REAL top, REAL width, REAL height,
REAL start_angle, REAL sweep_angle)
{
INT i;
REAL end_angle, start_angle, endAngle;
REAL partial_end_angle, end_angle;
endAngle = startAngle + sweepAngle;
unstretch_angle(&startAngle, x2 / 2.0, y2 / 2.0);
unstretch_angle(&endAngle, x2 / 2.0, y2 / 2.0);
end_angle = deg2rad(start_angle + sweep_angle);
start_angle = deg2rad(start_angle);
/* start_angle and end_angle are the iterative variables */
start_angle = startAngle;
if (width != height)
{
start_angle = unstretch_angle(start_angle, width, height);
end_angle = unstretch_angle(end_angle, width, height);
}
for(i = 0; i < MAX_ARC_PTS - 1; i += 3){
/* check if we've overshot the end angle */
if( sweepAngle > 0.0 )
if( sweep_angle > 0.0 )
{
if (start_angle >= endAngle) break;
end_angle = min(start_angle + M_PI_2, endAngle);
if (start_angle >= end_angle) break;
partial_end_angle = min(start_angle + M_PI_2, end_angle);
}
else
{
if (start_angle <= endAngle) break;
end_angle = max(start_angle - M_PI_2, endAngle);
if (start_angle <= end_angle) break;
partial_end_angle = max(start_angle - M_PI_2, end_angle);
}
if (points)
add_arc_part(&points[i], x1, y1, x2, y2, start_angle, end_angle, i == 0);
add_arc_part(&points[i], left, top, width, height, start_angle, partial_end_angle, i == 0);
start_angle += M_PI_2 * (sweepAngle < 0.0 ? -1.0 : 1.0);
start_angle = partial_end_angle;
}
if (i == 0) return 0;
@ -324,14 +324,18 @@ GpStatus hresult_to_status(HRESULT res)
}
/* converts a given unit to its value in pixels */
REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi, BOOL printer_display)
{
switch (unit)
{
case UnitPixel:
case UnitWorld:
case UnitDisplay:
return units;
case UnitDisplay:
if (printer_display)
return units * dpi / 100.0;
else
return units;
case UnitPoint:
return units * dpi / point_per_inch;
case UnitInch:
@ -347,14 +351,18 @@ REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
}
/* converts value in pixels to a given unit */
REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi)
REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi, BOOL printer_display)
{
switch (unit)
{
case UnitPixel:
case UnitWorld:
case UnitDisplay:
return pixels;
case UnitDisplay:
if (printer_display)
return pixels * 100.0 / dpi;
else
return pixels;
case UnitPoint:
return pixels * point_per_inch / dpi;
case UnitInch:
@ -369,10 +377,10 @@ REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi)
}
}
REAL units_scale(GpUnit from, GpUnit to, REAL dpi)
REAL units_scale(GpUnit from, GpUnit to, REAL dpi, BOOL printer_display)
{
REAL pixels = units_to_pixels(1.0, from, dpi);
return pixels_to_units(pixels, to, dpi);
REAL pixels = units_to_pixels(1.0, from, dpi, printer_display);
return pixels_to_units(pixels, to, dpi, printer_display);
}
/* Calculates Bezier points from cardinal spline points. */

View file

@ -18,6 +18,15 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define WINE_FILEDESCRIPTION_STR "Wine gdiplus"
#define WINE_FILENAME_STR "gdiplus.dll"
#define WINE_FILEVERSION 6,1,7601,17514
#define WINE_FILEVERSION_STR "6.1.7601.17514"
#define WINE_PRODUCTVERSION 6,1,7601,17514
#define WINE_PRODUCTVERSION_STR "6.1.7601.17514"
#include "wine/wine_common_ver.rc"
/* @makedep: gdiplus.manifest */
WINE_MANIFEST 24 gdiplus.manifest

View file

@ -100,7 +100,7 @@
100 stdcall GdipCreateMatrix3I(ptr ptr ptr)
101 stdcall GdipCreateMatrix(ptr)
102 stdcall GdipCreateMetafileFromEmf(ptr long ptr)
103 stdcall GdipCreateMetafileFromFile(ptr ptr)
103 stdcall GdipCreateMetafileFromFile(wstr ptr)
104 stdcall GdipCreateMetafileFromStream(ptr ptr)
105 stdcall GdipCreateMetafileFromWmf(ptr long ptr ptr)
106 stdcall GdipCreateMetafileFromWmfFile(wstr ptr ptr)
@ -200,8 +200,8 @@
200 stub GdipEnumerateMetafileSrcRectDestPointI
201 stdcall GdipEnumerateMetafileSrcRectDestPoints(ptr ptr ptr long ptr long ptr ptr ptr)
202 stub GdipEnumerateMetafileSrcRectDestPointsI
203 stub GdipEnumerateMetafileSrcRectDestRect
204 stub GdipEnumerateMetafileSrcRectDestRectI
203 stdcall GdipEnumerateMetafileSrcRectDestRect(ptr ptr ptr ptr long ptr ptr ptr)
204 stdcall GdipEnumerateMetafileSrcRectDestRectI(ptr ptr ptr ptr long ptr ptr ptr)
205 stdcall GdipFillClosedCurve2(ptr ptr ptr long float long)
206 stdcall GdipFillClosedCurve2I(ptr ptr ptr long float long)
207 stdcall GdipFillClosedCurve(ptr ptr ptr long)
@ -298,7 +298,7 @@
298 stdcall GdipGetLogFontA(ptr ptr ptr)
299 stdcall GdipGetLogFontW(ptr ptr ptr)
300 stdcall GdipGetMatrixElements(ptr ptr)
301 stub GdipGetMetafileDownLevelRasterizationLimit
301 stdcall GdipGetMetafileDownLevelRasterizationLimit(ptr ptr)
302 stdcall GdipGetMetafileHeaderFromEmf(ptr ptr)
303 stdcall GdipGetMetafileHeaderFromFile(wstr ptr)
304 stdcall GdipGetMetafileHeaderFromMetafile(ptr ptr)
@ -451,7 +451,7 @@
451 stdcall GdipRecordMetafileFileNameI(wstr long long ptr long wstr ptr)
452 stdcall GdipRecordMetafileI(long long ptr long wstr ptr)
453 stdcall GdipRecordMetafileStream(ptr long long ptr long wstr ptr)
454 stub GdipRecordMetafileStreamI
454 stdcall GdipRecordMetafileStreamI(ptr long long ptr long wstr ptr)
455 stdcall GdipReleaseDC(ptr ptr)
456 stdcall GdipRemovePropertyItem(ptr long)
457 stdcall GdipResetClip(ptr)
@ -472,7 +472,7 @@
472 stdcall GdipRotateTextureTransform(ptr float long)
473 stdcall GdipRotateWorldTransform(ptr float long)
474 stdcall GdipSaveAdd(ptr ptr)
475 stub GdipSaveAddImage
475 stdcall GdipSaveAddImage(ptr ptr ptr)
476 stdcall GdipSaveGraphics(ptr ptr)
477 stdcall GdipSaveImageToFile(ptr wstr ptr ptr)
478 stdcall GdipSaveImageToStream(ptr ptr ptr ptr)
@ -506,7 +506,7 @@
506 stdcall GdipSetImageAttributesGamma(ptr long long float)
507 stdcall GdipSetImageAttributesNoOp(ptr long long)
508 stdcall GdipSetImageAttributesOutputChannel(ptr long long long)
509 stdcall GdipSetImageAttributesOutputChannelColorProfile(ptr long long ptr)
509 stdcall GdipSetImageAttributesOutputChannelColorProfile(ptr long long wstr)
510 stdcall GdipSetImageAttributesRemapTable(ptr long long long ptr)
511 stdcall GdipSetImageAttributesThreshold(ptr long long float)
512 stdcall GdipSetImageAttributesToIdentity(ptr long)
@ -624,7 +624,7 @@
624 stdcall GdipImageSetAbort(ptr ptr)
625 stdcall GdipGraphicsSetAbort(ptr ptr)
626 stub GdipDrawImageFX
627 stdcall GdipConvertToEmfPlus(ptr ptr ptr long ptr ptr)
628 stdcall GdipConvertToEmfPlusToFile(ptr ptr ptr ptr long ptr ptr)
627 stdcall GdipConvertToEmfPlus(ptr ptr ptr long wstr ptr)
628 stdcall GdipConvertToEmfPlusToFile(ptr ptr ptr wstr long wstr ptr)
629 stub GdipConvertToEmfPlusToStream
630 stub GdipPlayTSClientRecord

View file

@ -57,9 +57,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 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 REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi, BOOL printer_display) DECLSPEC_HIDDEN;
extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi, BOOL printer_display) DECLSPEC_HIDDEN;
extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi, BOOL printer_display) DECLSPEC_HIDDEN;
#define WineCoordinateSpaceGdiDevice ((GpCoordinateSpace)4)
@ -72,6 +72,7 @@ extern GpStatus gdip_transform_points(GpGraphics *graphics, GpCoordinateSpace ds
extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN;
extern GpStatus encode_image_png(GpImage *image, IStream* stream, GDIPCONST EncoderParameters* params) DECLSPEC_HIDDEN;
extern GpStatus terminate_encoder_wic(GpImage *image) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc) DECLSPEC_HIDDEN;
@ -103,7 +104,23 @@ extern GpStatus METAFILE_DrawImagePointsRect(GpMetafile* metafile, GpImage *imag
extern GpStatus METAFILE_AddSimpleProperty(GpMetafile *metafile, SHORT prop, SHORT val) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_DrawPath(GpMetafile *metafile, GpPen *pen, GpPath *path) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_FillPath(GpMetafile *metafile, GpBrush *brush, GpPath *path) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_DrawDriverString(GpMetafile *metafile, GDIPCONST UINT16 *text, INT length,
GDIPCONST GpFont *font, GDIPCONST GpStringFormat *format, GDIPCONST GpBrush *brush,
GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_FillRegion(GpMetafile* metafile, GpBrush* brush,
GpRegion* region) DECLSPEC_HIDDEN;
extern void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_DrawEllipse(GpMetafile *metafile, GpPen *pen, GpRectF *rect) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_FillEllipse(GpMetafile *metafile, GpBrush *brush, GpRectF *rect) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_DrawRectangles(GpMetafile *metafile, GpPen *pen, const GpRectF *rects, INT count) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_FillPie(GpMetafile *metafile, GpBrush *brush, const GpRectF *rect,
REAL startAngle, REAL sweepAngle) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_DrawArc(GpMetafile *metafile, GpPen *pen, const GpRectF *rect,
REAL startAngle, REAL sweepAngle) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_OffsetClip(GpMetafile *metafile, REAL dx, REAL dy) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_ResetClip(GpMetafile *metafile) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetClipPath(GpMetafile *metafile, GpPath *path, CombineMode mode) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_SetRenderingOrigin(GpMetafile *metafile, INT x, INT y) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN;
@ -122,7 +139,7 @@ extern GpStatus trace_path(GpGraphics *graphics, GpPath *path) DECLSPEC_HIDDEN;
typedef struct region_element region_element;
extern void delete_element(region_element *element) DECLSPEC_HIDDEN;
extern GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result) DECLSPEC_HIDDEN;
extern GpStatus get_hatch_data(GpHatchStyle hatchstyle, const unsigned char **result) DECLSPEC_HIDDEN;
static inline INT gdip_round(REAL x)
{
@ -190,8 +207,8 @@ extern void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height,
BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride) DECLSPEC_HIDDEN;
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, ColorPalette *palette) DECLSPEC_HIDDEN;
INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, ColorPalette *dst_palette,
INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *src_palette) DECLSPEC_HIDDEN;
extern PixelFormat apply_image_attributes(const GpImageAttributes *attributes, LPBYTE data,
UINT width, UINT height, INT stride, ColorAdjustType type, PixelFormat fmt) DECLSPEC_HIDDEN;
@ -225,6 +242,7 @@ struct GpGraphics{
HWND hwnd;
BOOL owndc;
BOOL alpha_hdc;
BOOL printer_display;
GpImage *image;
ImageType image_type;
SmoothingMode smoothing;
@ -346,6 +364,7 @@ struct GpAdjustableArrowCap{
struct GpImage{
IWICBitmapDecoder *decoder;
IWICBitmapEncoder *encoder;
ImageType type;
GUID format;
UINT flags;
@ -405,6 +424,10 @@ struct GpMetafile{
BOOL auto_frame; /* If true, determine the frame automatically */
GpPointF auto_frame_min, auto_frame_max;
DWORD next_object_id;
UINT limit_dpi;
BOOL printer_display;
REAL logical_dpix;
REAL logical_dpiy;
/* playback */
GpGraphics *playback_graphics;
@ -413,7 +436,6 @@ struct GpMetafile{
GpRectF src_rect;
HANDLETABLE *handle_table;
int handle_count;
XFORM gdiworldtransform;
GpMatrix *world_transform;
GpUnit page_unit;
REAL page_scale;
@ -521,6 +543,8 @@ struct GpFontFamily{
WCHAR FamilyName[LF_FACESIZE];
UINT16 em_height, ascent, descent, line_spacing; /* in font units */
int dpi;
BOOL installed;
LONG ref;
};
/* internal use */
@ -602,4 +626,12 @@ static inline void image_unlock(GpImage *image, BOOL unlock)
if (unlock) image->busy = 0;
}
static inline void set_rect(GpRectF *rect, REAL x, REAL y, REAL width, REAL height)
{
rect->X = x;
rect->Y = y;
rect->Width = width;
rect->Height = height;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -166,6 +166,52 @@ static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, R
return TRUE;
}
/* GdipAddPath* helper
*
* Several GdipAddPath functions are expected to add onto an open figure.
* So if the first point being added is an exact match to the last point
* of the existing line, that point should not be added.
*
* Parameters:
* path : path to which points should be added
* points : array of points to add
* count : number of points to add (at least 1)
* type : type of the points being added
*
* Return value:
* OutOfMemory : out of memory, could not lengthen path
* Ok : success
*/
static GpStatus extend_current_figure(GpPath *path, GDIPCONST PointF *points, INT count, BYTE type)
{
INT insert_index = path->pathdata.Count;
BYTE first_point_type = (path->newfigure ? PathPointTypeStart : PathPointTypeLine);
if(!path->newfigure &&
path->pathdata.Points[insert_index-1].X == points[0].X &&
path->pathdata.Points[insert_index-1].Y == points[0].Y)
{
points++;
count--;
first_point_type = type;
}
if(!count)
return Ok;
if(!lengthen_path(path, count))
return OutOfMemory;
memcpy(path->pathdata.Points + insert_index, points, sizeof(GpPointF)*count);
path->pathdata.Types[insert_index] = first_point_type;
memset(path->pathdata.Types + insert_index + 1, type, count - 1);
path->newfigure = FALSE;
path->pathdata.Count += count;
return Ok;
}
/*******************************************************************************
* GdipAddPathArc [GDIPLUS.1]
*
@ -195,7 +241,9 @@ static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, R
GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x1, REAL y1, REAL x2,
REAL y2, REAL startAngle, REAL sweepAngle)
{
INT count, old_count, i;
GpPointF *points;
GpStatus status;
INT count;
TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
path, x1, y1, x2, y2, startAngle, sweepAngle);
@ -204,26 +252,19 @@ GpStatus WINGDIPAPI GdipAddPathArc(GpPath *path, REAL x1, REAL y1, REAL x2,
return InvalidParameter;
count = arc2polybezier(NULL, x1, y1, x2, y2, startAngle, sweepAngle);
if(count == 0)
return Ok;
if(!lengthen_path(path, count))
points = heap_alloc_zero(sizeof(GpPointF)*count);
if(!points)
return OutOfMemory;
old_count = path->pathdata.Count;
arc2polybezier(&path->pathdata.Points[old_count], x1, y1, x2, y2,
startAngle, sweepAngle);
arc2polybezier(points, x1, y1, x2, y2, startAngle, sweepAngle);
for(i = 0; i < count; i++){
path->pathdata.Types[old_count + i] = PathPointTypeBezier;
}
status = extend_current_figure(path, points, count, PathPointTypeBezier);
path->pathdata.Types[old_count] =
(path->newfigure ? PathPointTypeStart : PathPointTypeLine);
path->newfigure = FALSE;
path->pathdata.Count += count;
return Ok;
heap_free(points);
return status;
}
/*******************************************************************************
@ -243,7 +284,7 @@ GpStatus WINGDIPAPI GdipAddPathArcI(GpPath *path, INT x1, INT y1, INT x2,
GpStatus WINGDIPAPI GdipAddPathBezier(GpPath *path, REAL x1, REAL y1, REAL x2,
REAL y2, REAL x3, REAL y3, REAL x4, REAL y4)
{
INT old_count;
PointF points[4];
TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
path, x1, y1, x2, y2, x3, y3, x4, y4);
@ -251,30 +292,16 @@ GpStatus WINGDIPAPI GdipAddPathBezier(GpPath *path, REAL x1, REAL y1, REAL x2,
if(!path)
return InvalidParameter;
if(!lengthen_path(path, 4))
return OutOfMemory;
points[0].X = x1;
points[0].Y = y1;
points[1].X = x2;
points[1].Y = y2;
points[2].X = x3;
points[2].Y = y3;
points[3].X = x4;
points[3].Y = y4;
old_count = path->pathdata.Count;
path->pathdata.Points[old_count].X = x1;
path->pathdata.Points[old_count].Y = y1;
path->pathdata.Points[old_count + 1].X = x2;
path->pathdata.Points[old_count + 1].Y = y2;
path->pathdata.Points[old_count + 2].X = x3;
path->pathdata.Points[old_count + 2].Y = y3;
path->pathdata.Points[old_count + 3].X = x4;
path->pathdata.Points[old_count + 3].Y = y4;
path->pathdata.Types[old_count] =
(path->newfigure ? PathPointTypeStart : PathPointTypeLine);
path->pathdata.Types[old_count + 1] = PathPointTypeBezier;
path->pathdata.Types[old_count + 2] = PathPointTypeBezier;
path->pathdata.Types[old_count + 3] = PathPointTypeBezier;
path->newfigure = FALSE;
path->pathdata.Count += 4;
return Ok;
return extend_current_figure(path, points, 4, PathPointTypeBezier);
}
GpStatus WINGDIPAPI GdipAddPathBezierI(GpPath *path, INT x1, INT y1, INT x2,
@ -290,30 +317,12 @@ GpStatus WINGDIPAPI GdipAddPathBezierI(GpPath *path, INT x1, INT y1, INT x2,
GpStatus WINGDIPAPI GdipAddPathBeziers(GpPath *path, GDIPCONST GpPointF *points,
INT count)
{
INT i, old_count;
TRACE("(%p, %p, %d)\n", path, points, count);
if(!path || !points || ((count - 1) % 3))
return InvalidParameter;
if(!lengthen_path(path, count))
return OutOfMemory;
old_count = path->pathdata.Count;
for(i = 0; i < count; i++){
path->pathdata.Points[old_count + i].X = points[i].X;
path->pathdata.Points[old_count + i].Y = points[i].Y;
path->pathdata.Types[old_count + i] = PathPointTypeBezier;
}
path->pathdata.Types[old_count] =
(path->newfigure ? PathPointTypeStart : PathPointTypeLine);
path->newfigure = FALSE;
path->pathdata.Count += count;
return Ok;
return extend_current_figure(path, points, count, PathPointTypeBezier);
}
GpStatus WINGDIPAPI GdipAddPathBeziersI(GpPath *path, GDIPCONST GpPoint *points,
@ -415,7 +424,7 @@ GpStatus WINGDIPAPI GdipAddPathClosedCurve2(GpPath *path, GDIPCONST GpPointF *po
pt[len_pt-1].X = pt[0].X;
pt[len_pt-1].Y = pt[0].Y;
stat = GdipAddPathBeziers(path, pt, len_pt);
stat = extend_current_figure(path, pt, len_pt, PathPointTypeBezier);
/* close figure */
if(stat == Ok){
@ -523,7 +532,7 @@ GpStatus WINGDIPAPI GdipAddPathCurve2(GpPath *path, GDIPCONST GpPointF *points,
pt[len_pt-1].X = points[count-1].X;
pt[len_pt-1].Y = points[count-1].Y;
stat = GdipAddPathBeziers(path, pt, len_pt);
stat = extend_current_figure(path, pt, len_pt, PathPointTypeBezier);
heap_free(pt);
@ -623,32 +632,12 @@ GpStatus WINGDIPAPI GdipAddPathEllipseI(GpPath *path, INT x, INT y, INT width,
GpStatus WINGDIPAPI GdipAddPathLine2(GpPath *path, GDIPCONST GpPointF *points,
INT count)
{
INT i, old_count;
TRACE("(%p, %p, %d)\n", path, points, count);
if(!path || !points)
if(!path || !points || count < 1)
return InvalidParameter;
if(!lengthen_path(path, count))
return OutOfMemory;
old_count = path->pathdata.Count;
for(i = 0; i < count; i++){
path->pathdata.Points[old_count + i].X = points[i].X;
path->pathdata.Points[old_count + i].Y = points[i].Y;
path->pathdata.Types[old_count + i] = PathPointTypeLine;
}
if(path->newfigure){
path->pathdata.Types[old_count] = PathPointTypeStart;
path->newfigure = FALSE;
}
path->pathdata.Count += count;
return Ok;
return extend_current_figure(path, points, count, PathPointTypeLine);
}
GpStatus WINGDIPAPI GdipAddPathLine2I(GpPath *path, GDIPCONST GpPoint *points, INT count)
@ -703,31 +692,19 @@ GpStatus WINGDIPAPI GdipAddPathLine2I(GpPath *path, GDIPCONST GpPoint *points, I
*/
GpStatus WINGDIPAPI GdipAddPathLine(GpPath *path, REAL x1, REAL y1, REAL x2, REAL y2)
{
INT old_count;
PointF points[2];
TRACE("(%p, %.2f, %.2f, %.2f, %.2f)\n", path, x1, y1, x2, y2);
if(!path)
return InvalidParameter;
if(!lengthen_path(path, 2))
return OutOfMemory;
points[0].X = x1;
points[0].Y = y1;
points[1].X = x2;
points[1].Y = y2;
old_count = path->pathdata.Count;
path->pathdata.Points[old_count].X = x1;
path->pathdata.Points[old_count].Y = y1;
path->pathdata.Points[old_count + 1].X = x2;
path->pathdata.Points[old_count + 1].Y = y2;
path->pathdata.Types[old_count] =
(path->newfigure ? PathPointTypeStart : PathPointTypeLine);
path->pathdata.Types[old_count + 1] = PathPointTypeLine;
path->newfigure = FALSE;
path->pathdata.Count += 2;
return Ok;
return extend_current_figure(path, points, 2, PathPointTypeLine);
}
/*************************************************************************
@ -1088,13 +1065,13 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
heap_free(backup);
return status;
}
if (format && format->line_align == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height)
if (format->line_align == StringAlignmentCenter && layoutRect->Y + args.maxY < layoutRect->Height)
{
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->line_align == StringAlignmentFar) {
} else if (format->line_align == StringAlignmentFar) {
float inc = layoutRect->Height + layoutRect->Y - args.maxY;
for (i = backup->pathdata.Count; i < path->pathdata.Count; ++i)
path->pathdata.Points[i].Y += inc;
@ -1103,19 +1080,16 @@ GpStatus WINGDIPAPI GdipAddPathString(GpPath* path, GDIPCONST WCHAR* string, INT
return status;
}
GpStatus WINGDIPAPI GdipAddPathStringI(GpPath* path, GDIPCONST WCHAR* string, INT length, GDIPCONST GpFontFamily* family, INT style, REAL emSize, GDIPCONST Rect* layoutRect, GDIPCONST GpStringFormat* format)
GpStatus WINGDIPAPI GdipAddPathStringI(GpPath* path, GDIPCONST WCHAR* string, INT length, GDIPCONST GpFontFamily* family,
INT style, REAL emSize, GDIPCONST Rect* layoutRect, GDIPCONST GpStringFormat* format)
{
if (layoutRect)
{
RectF layoutRectF = {
(REAL)layoutRect->X,
(REAL)layoutRect->Y,
(REAL)layoutRect->Width,
(REAL)layoutRect->Height
};
return GdipAddPathString(path, string, length, family, style, emSize, &layoutRectF, format);
}
return InvalidParameter;
RectF rect;
if (!layoutRect)
return InvalidParameter;
set_rect(&rect, layoutRect->X, layoutRect->Y, layoutRect->Width, layoutRect->Height);
return GdipAddPathString(path, string, length, family, style, emSize, &rect, format);
}
/*************************************************************************
@ -1213,14 +1187,37 @@ GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
GpStatus WINGDIPAPI GdipCreatePath2(GDIPCONST GpPointF* points,
GDIPCONST BYTE* types, INT count, GpFillMode fill, GpPath **path)
{
int i;
TRACE("(%p, %p, %d, %d, %p)\n", points, types, count, fill, path);
if(!path)
if(!points || !types || !path)
return InvalidParameter;
if(count <= 0) {
*path = NULL;
return OutOfMemory;
}
*path = heap_alloc_zero(sizeof(GpPath));
if(!*path) return OutOfMemory;
if(count > 1 && (types[count-1] & PathPointTypePathTypeMask) == PathPointTypeStart)
count = 0;
for(i = 1; i < count; i++) {
if((types[i] & PathPointTypePathTypeMask) == PathPointTypeBezier) {
if(i+2 < count &&
(types[i+1] & PathPointTypePathTypeMask) == PathPointTypeBezier &&
(types[i+2] & PathPointTypePathTypeMask) == PathPointTypeBezier)
i += 2;
else {
count = 0;
break;
}
}
}
(*path)->pathdata.Points = heap_alloc_zero(count * sizeof(PointF));
(*path)->pathdata.Types = heap_alloc_zero(count);
@ -1233,6 +1230,8 @@ GpStatus WINGDIPAPI GdipCreatePath2(GDIPCONST GpPointF* points,
memcpy((*path)->pathdata.Points, points, count * sizeof(PointF));
memcpy((*path)->pathdata.Types, types, count);
if(count > 0)
(*path)->pathdata.Types[0] = PathPointTypeStart;
(*path)->pathdata.Count = count;
(*path)->datalen = count;
@ -1804,12 +1803,12 @@ GpStatus WINGDIPAPI GdipWarpPath(GpPath *path, GpMatrix* matrix,
}
static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint,
GpPen *pen, int right_side, path_list_node_t **last_point)
REAL pen_width, int right_side, path_list_node_t **last_point)
{
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 distance = pen_width / 2.0;
REAL bevel_dx, bevel_dy;
if (segment_length == 0.0)
@ -1835,7 +1834,7 @@ static void add_bevel_point(const GpPointF *endpoint, const GpPointF *nextpoint,
}
static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *p3,
GpPen* pen, path_list_node_t **last_point)
GpPen* pen, REAL pen_width, path_list_node_t **last_point)
{
switch (pen->join)
{
@ -1843,7 +1842,7 @@ static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *
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 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;
@ -1870,14 +1869,14 @@ static void widen_joint(const GpPointF *p1, const GpPointF *p2, const GpPointF *
/* else fall-through */
default:
case LineJoinBevel:
add_bevel_point(p2, p1, pen, 1, last_point);
add_bevel_point(p2, p3, pen, 0, last_point);
add_bevel_point(p2, p1, pen_width, 1, last_point);
add_bevel_point(p2, p3, pen_width, 0, last_point);
break;
}
}
static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
GpPen *pen, GpLineCap cap, GpCustomLineCap *custom, int add_first_points,
REAL pen_width, GpLineCap cap, GpCustomLineCap *custom, int add_first_points,
int add_last_point, path_list_node_t **last_point)
{
switch (cap)
@ -1885,16 +1884,16 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
default:
case LineCapFlat:
if (add_first_points)
add_bevel_point(endpoint, nextpoint, pen, 1, last_point);
add_bevel_point(endpoint, nextpoint, pen_width, 1, last_point);
if (add_last_point)
add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
add_bevel_point(endpoint, nextpoint, pen_width, 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 distance = pen_width / 2.0;
REAL bevel_dx, bevel_dy;
REAL extend_dx, extend_dy;
@ -1919,7 +1918,7 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
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 distance = pen_width / 2.0;
REAL dx, dy, dx2, dy2;
const REAL control_point_distance = 0.5522847498307935; /* 4/3 * (sqrt(2) - 1) */
@ -1955,6 +1954,8 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
*last_point = add_path_list_node(*last_point, endpoint->X - dy,
endpoint->Y + dx, PathPointTypeBezier);
}
else if (add_last_point)
add_bevel_point(endpoint, nextpoint, pen_width, 0, last_point);
break;
}
case LineCapTriangle:
@ -1962,79 +1963,193 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
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 distance = pen_width / 2.0;
REAL dx, dy;
dx = distance * segment_dx / segment_length;
dy = distance * segment_dy / segment_length;
if (add_first_points) {
add_bevel_point(endpoint, nextpoint, pen, 1, last_point);
add_bevel_point(endpoint, nextpoint, pen_width, 1, last_point);
*last_point = add_path_list_node(*last_point, endpoint->X - dx,
endpoint->Y - dy, PathPointTypeLine);
}
if (add_last_point)
add_bevel_point(endpoint, nextpoint, pen, 0, last_point);
if (add_first_points || add_last_point)
add_bevel_point(endpoint, nextpoint, pen_width, 0, last_point);
break;
}
}
}
static void widen_open_figure(const GpPointF *points, GpPen *pen, int start, int end,
GpLineCap start_cap, GpCustomLineCap *start_custom, GpLineCap end_cap,
GpCustomLineCap *end_custom, path_list_node_t **last_point)
static void add_anchor(const GpPointF *endpoint, const GpPointF *nextpoint,
REAL pen_width, GpLineCap cap, GpCustomLineCap *custom, path_list_node_t **last_point)
{
switch (cap)
{
default:
case LineCapNoAnchor:
return;
case LineCapSquareAnchor:
{
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 / sqrtf(2.0);
REAL par_dx, par_dy;
REAL perp_dx, perp_dy;
par_dx = -distance * segment_dx / segment_length;
par_dy = -distance * segment_dy / segment_length;
perp_dx = -distance * segment_dy / segment_length;
perp_dy = distance * segment_dx / segment_length;
*last_point = add_path_list_node(*last_point, endpoint->X - par_dx - perp_dx,
endpoint->Y - par_dy - perp_dy, PathPointTypeStart);
*last_point = add_path_list_node(*last_point, endpoint->X - par_dx + perp_dx,
endpoint->Y - par_dy + perp_dy, PathPointTypeLine);
*last_point = add_path_list_node(*last_point, endpoint->X + par_dx + perp_dx,
endpoint->Y + par_dy + perp_dy, PathPointTypeLine);
*last_point = add_path_list_node(*last_point, endpoint->X + par_dx - perp_dx,
endpoint->Y + par_dy - perp_dy, PathPointTypeLine);
break;
}
case LineCapRoundAnchor:
{
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 dx, dy, dx2, dy2;
const REAL control_point_distance = 0.55228475; /* 4/3 * (sqrt(2) - 1) */
dx = -pen_width * segment_dx / segment_length;
dy = -pen_width * segment_dy / segment_length;
dx2 = dx * control_point_distance;
dy2 = dy * control_point_distance;
/* starting point */
*last_point = add_path_list_node(*last_point, endpoint->X + dy,
endpoint->Y - dx, PathPointTypeStart);
/* first 90-degree arc */
*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);
*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);
/* third 90-degree arc */
*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);
*last_point = add_path_list_node(*last_point, endpoint->X - dx,
endpoint->Y - dy, PathPointTypeBezier);
/* fourth 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;
}
case LineCapDiamondAnchor:
{
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 par_dx, par_dy;
REAL perp_dx, perp_dy;
par_dx = -pen_width * segment_dx / segment_length;
par_dy = -pen_width * segment_dy / segment_length;
perp_dx = -pen_width * segment_dy / segment_length;
perp_dy = pen_width * segment_dx / segment_length;
*last_point = add_path_list_node(*last_point, endpoint->X + par_dx,
endpoint->Y + par_dy, PathPointTypeStart);
*last_point = add_path_list_node(*last_point, endpoint->X - perp_dx,
endpoint->Y - perp_dy, PathPointTypeLine);
*last_point = add_path_list_node(*last_point, endpoint->X - par_dx,
endpoint->Y - par_dy, PathPointTypeLine);
*last_point = add_path_list_node(*last_point, endpoint->X + perp_dx,
endpoint->Y + perp_dy, PathPointTypeLine);
break;
}
}
(*last_point)->type |= PathPointTypeCloseSubpath;
}
static void widen_open_figure(const GpPointF *points, int start, int end,
GpPen *pen, REAL pen_width, GpLineCap start_cap, GpCustomLineCap *start_custom,
GpLineCap end_cap, GpCustomLineCap *end_custom, path_list_node_t **last_point)
{
int i;
path_list_node_t *prev_point;
if (end <= start)
if (end <= start || pen_width == 0.0)
return;
prev_point = *last_point;
widen_cap(&points[start], &points[start+1],
pen, start_cap, start_custom, FALSE, TRUE, last_point);
pen_width, start_cap, start_custom, FALSE, TRUE, last_point);
for (i=start+1; i<end; i++)
widen_joint(&points[i-1], &points[i],
&points[i+1], pen, last_point);
widen_joint(&points[i-1], &points[i], &points[i+1],
pen, pen_width, last_point);
widen_cap(&points[end], &points[end-1],
pen, end_cap, end_custom, TRUE, TRUE, last_point);
pen_width, end_cap, end_custom, TRUE, TRUE, last_point);
for (i=end-1; i>start; i--)
widen_joint(&points[i+1], &points[i],
&points[i-1], pen, last_point);
widen_joint(&points[i+1], &points[i], &points[i-1],
pen, pen_width, last_point);
widen_cap(&points[start], &points[start+1],
pen, start_cap, start_custom, TRUE, FALSE, last_point);
pen_width, start_cap, start_custom, TRUE, FALSE, last_point);
prev_point->next->type = PathPointTypeStart;
(*last_point)->type |= PathPointTypeCloseSubpath;
}
static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end,
path_list_node_t **last_point)
static void widen_closed_figure(GpPath *path, int start, int end,
GpPen *pen, REAL pen_width, path_list_node_t **last_point)
{
int i;
path_list_node_t *prev_point;
if (end <= start)
if (end <= start || pen_width == 0.0)
return;
/* left outline */
prev_point = *last_point;
widen_joint(&path->pathdata.Points[end], &path->pathdata.Points[start],
&path->pathdata.Points[start+1], pen, last_point);
&path->pathdata.Points[start+1], pen, pen_width, last_point);
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);
&path->pathdata.Points[i+1], pen, pen_width, last_point);
widen_joint(&path->pathdata.Points[end-1], &path->pathdata.Points[end],
&path->pathdata.Points[start], pen, last_point);
&path->pathdata.Points[start], pen, pen_width, last_point);
prev_point->next->type = PathPointTypeStart;
(*last_point)->type |= PathPointTypeCloseSubpath;
@ -2043,21 +2158,21 @@ static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end,
prev_point = *last_point;
widen_joint(&path->pathdata.Points[start], &path->pathdata.Points[end],
&path->pathdata.Points[end-1], pen, last_point);
&path->pathdata.Points[end-1], pen, pen_width, last_point);
for (i=end-1; i>start; 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, pen_width, last_point);
widen_joint(&path->pathdata.Points[start+1], &path->pathdata.Points[start],
&path->pathdata.Points[end], pen, last_point);
&path->pathdata.Points[end], pen, pen_width, last_point);
prev_point->next->type = PathPointTypeStart;
(*last_point)->type |= PathPointTypeCloseSubpath;
}
static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end,
int closed, path_list_node_t **last_point)
static void widen_dashed_figure(GpPath *path, int start, int end, int closed,
GpPen *pen, REAL pen_width, path_list_node_t **last_point)
{
int i, j;
REAL dash_pos=0.0;
@ -2074,7 +2189,7 @@ static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end,
int draw_start_cap=0;
static const REAL dash_dot_dot[6] = { 3.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
if (end <= start)
if (end <= start || pen_width == 0.0)
return;
switch (pen->dash)
@ -2151,7 +2266,7 @@ static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end,
tmp_points[num_tmp_points].X = path->pathdata.Points[i].X + segment_dx * segment_pos / segment_length;
tmp_points[num_tmp_points].Y = path->pathdata.Points[i].Y + segment_dy * segment_pos / segment_length;
widen_open_figure(tmp_points, pen, 0, num_tmp_points,
widen_open_figure(tmp_points, 0, num_tmp_points, pen, pen_width,
draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart,
LineCapFlat, NULL, last_point);
draw_start_cap = 0;
@ -2185,7 +2300,7 @@ static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end,
if (dash_index % 2 == 0 && num_tmp_points != 0)
{
/* last dash overflows last segment */
widen_open_figure(tmp_points, pen, 0, num_tmp_points-1,
widen_open_figure(tmp_points, 0, num_tmp_points-1, pen, pen_width,
draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart,
closed ? LineCapFlat : pen->endcap, pen->customend, last_point);
}
@ -2201,7 +2316,6 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
GpStatus status;
path_list_node_t *points=NULL, *last_point=NULL;
int i, subpath_start=0, new_length;
BYTE type;
TRACE("(%p,%p,%p,%0.2f)\n", path, pen, matrix, flatness);
@ -2221,12 +2335,16 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
if (status == Ok)
{
REAL anchor_pen_width = max(pen->width, 2.0);
REAL pen_width = (pen->unit == UnitWorld) ? max(pen->width, 1.0) : pen->width;
BYTE *types = flat_path->pathdata.Types;
last_point = points;
if (pen->endcap > LineCapTriangle)
if (pen->endcap > LineCapDiamondAnchor)
FIXME("unimplemented end cap %x\n", pen->endcap);
if (pen->startcap > LineCapTriangle)
if (pen->startcap > LineCapDiamondAnchor)
FIXME("unimplemented start cap %x\n", pen->startcap);
if (pen->dashcap != DashCapFlat)
@ -2240,25 +2358,46 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
for (i=0; i < flat_path->pathdata.Count; i++)
{
type = flat_path->pathdata.Types[i];
if ((type&PathPointTypePathTypeMask) == PathPointTypeStart)
if ((types[i]&PathPointTypePathTypeMask) == PathPointTypeStart)
subpath_start = i;
if ((type&PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath)
if ((types[i]&PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath)
{
if (pen->dash != DashStyleSolid)
widen_dashed_figure(flat_path, pen, subpath_start, i, 1, &last_point);
widen_dashed_figure(flat_path, subpath_start, i, 1, pen, pen_width, &last_point);
else
widen_closed_figure(flat_path, pen, subpath_start, i, &last_point);
widen_closed_figure(flat_path, subpath_start, i, pen, pen_width, &last_point);
}
else if (i == flat_path->pathdata.Count-1 ||
(flat_path->pathdata.Types[i+1]&PathPointTypePathTypeMask) == PathPointTypeStart)
(types[i+1]&PathPointTypePathTypeMask) == PathPointTypeStart)
{
if (pen->dash != DashStyleSolid)
widen_dashed_figure(flat_path, pen, subpath_start, i, 0, &last_point);
widen_dashed_figure(flat_path, subpath_start, i, 0, pen, pen_width, &last_point);
else
widen_open_figure(flat_path->pathdata.Points, pen, subpath_start, i, pen->startcap, pen->customstart, pen->endcap, pen->customend, &last_point);
widen_open_figure(flat_path->pathdata.Points, subpath_start, i, pen, pen_width, pen->startcap, pen->customstart, pen->endcap, pen->customend, &last_point);
}
}
for (i=0; i < flat_path->pathdata.Count; i++)
{
if ((types[i]&PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath)
continue;
if ((types[i]&PathPointTypePathTypeMask) == PathPointTypeStart)
subpath_start = i;
if (i == flat_path->pathdata.Count-1 ||
(types[i+1]&PathPointTypePathTypeMask) == PathPointTypeStart)
{
if (pen->startcap & LineCapAnchorMask)
add_anchor(&flat_path->pathdata.Points[subpath_start],
&flat_path->pathdata.Points[subpath_start+1],
anchor_pen_width, pen->startcap, pen->customstart, &last_point);
if (pen->endcap & LineCapAnchorMask)
add_anchor(&flat_path->pathdata.Points[i],
&flat_path->pathdata.Points[i-1],
anchor_pen_width, pen->endcap, pen->customend, &last_point);
}
}
@ -2405,12 +2544,8 @@ GpStatus WINGDIPAPI GdipAddPathRectanglesI(GpPath *path, GDIPCONST GpRect *rects
rectsF = heap_alloc_zero(sizeof(GpRectF)*count);
for(i = 0;i < count;i++){
rectsF[i].X = (REAL)rects[i].X;
rectsF[i].Y = (REAL)rects[i].Y;
rectsF[i].Width = (REAL)rects[i].Width;
rectsF[i].Height = (REAL)rects[i].Height;
}
for(i = 0;i < count;i++)
set_rect(&rectsF[i], rects[i].X, rects[i].Y, rects[i].Width, rects[i].Height);
retstat = GdipAddPathRectangles(path, rectsF, count);
heap_free(rectsF);

File diff suppressed because it is too large Load diff

View file

@ -129,7 +129,7 @@ GpStatus WINGDIPAPI GdipGetImageAttributesAdjustedPalette(GpImageAttributes *ima
GpStatus WINGDIPAPI GdipSetImageAttributesColorKeys(GpImageAttributes *imageattr,
ColorAdjustType type, BOOL enableFlag, ARGB colorLow, ARGB colorHigh)
{
TRACE("(%p,%u,%i,%08x,%08x)\n", imageattr, type, enableFlag, colorLow, colorHigh);
TRACE("(%p,%u,%i,%08lx,%08lx)\n", imageattr, type, enableFlag, colorLow, colorHigh);
if(!imageattr || type >= ColorAdjustTypeCount)
return InvalidParameter;
@ -176,7 +176,7 @@ GpStatus WINGDIPAPI GdipSetImageAttributesColorMatrix(GpImageAttributes *imageat
GpStatus WINGDIPAPI GdipSetImageAttributesWrapMode(GpImageAttributes *imageAttr,
WrapMode wrap, ARGB argb, BOOL clamp)
{
TRACE("(%p,%u,%08x,%i)\n", imageAttr, wrap, argb, clamp);
TRACE("(%p,%u,%08lx,%i)\n", imageAttr, wrap, argb, clamp);
if(!imageAttr || wrap > WrapModeClamp)
return InvalidParameter;

View file

@ -86,7 +86,8 @@ GpStatus WINGDIPAPI GdipCreateMatrix3(GDIPCONST GpRectF *rect,
GDIPCONST GpPointF *pt, GpMatrix **matrix)
{
REAL m11, m12, m21, m22, dx, dy;
TRACE("(%p, %p, %p)\n", rect, pt, matrix);
TRACE("(%s, %p, %p)\n", debugstr_rectf(rect), pt, matrix);
if(!matrix || !pt)
return InvalidParameter;
@ -110,10 +111,7 @@ GpStatus WINGDIPAPI GdipCreateMatrix3I(GDIPCONST GpRect *rect, GDIPCONST GpPoint
TRACE("(%p, %p, %p)\n", rect, pt, matrix);
rectF.X = (REAL)rect->X;
rectF.Y = (REAL)rect->Y;
rectF.Width = (REAL)rect->Width;
rectF.Height = (REAL)rect->Height;
set_rect(&rectF, rect->X, rect->Y, rect->Width, rect->Height);
for (i = 0; i < 3; i++) {
ptF[i].X = (REAL)pt[i].X;

File diff suppressed because it is too large Load diff

View file

@ -139,7 +139,7 @@ GpStatus WINGDIPAPI GdipCreatePen1(ARGB color, REAL width, GpUnit unit,
GpBrush *brush;
GpStatus status;
TRACE("(%x, %.2f, %d, %p)\n", color, width, unit, pen);
TRACE("(%lx, %.2f, %d, %p)\n", color, width, unit, pen);
GdipCreateSolidFill(color, (GpSolidFill **)(&brush));
status = GdipCreatePen2(brush, width, unit, pen);
@ -512,7 +512,7 @@ GpStatus WINGDIPAPI GdipSetPenBrushFill(GpPen *pen, GpBrush *brush)
GpStatus WINGDIPAPI GdipSetPenColor(GpPen *pen, ARGB argb)
{
TRACE("(%p, %x)\n", pen, argb);
TRACE("(%p, %lx)\n", pen, argb);
if(!pen)
return InvalidParameter;
@ -598,13 +598,10 @@ GpStatus WINGDIPAPI GdipSetPenDashArray(GpPen *pen, GDIPCONST REAL *dash,
for(i = 0; i < count; i++){
sum += dash[i];
if(dash[i] < 0.0)
if(dash[i] <= 0.0)
return InvalidParameter;
}
if(sum == 0.0 && count)
return InvalidParameter;
heap_free(pen->dashes);
pen->dashes = NULL;

View file

@ -332,11 +332,7 @@ GpStatus WINGDIPAPI GdipCombineRegionRectI(GpRegion *region,
if (!rect)
return InvalidParameter;
rectf.X = (REAL)rect->X;
rectf.Y = (REAL)rect->Y;
rectf.Height = (REAL)rect->Height;
rectf.Width = (REAL)rect->Width;
set_rect(&rectf, rect->X, rect->Y, rect->Width, rect->Height);
return GdipCombineRegionRect(region, &rectf, mode);
}
@ -461,7 +457,7 @@ GpStatus WINGDIPAPI GdipCreateRegionRect(GDIPCONST GpRectF *rect,
{
GpStatus stat;
TRACE("%p, %p\n", rect, region);
TRACE("%s, %p\n", debugstr_rectf(rect), region);
if (!(rect && region))
return InvalidParameter;
@ -492,11 +488,7 @@ GpStatus WINGDIPAPI GdipCreateRegionRectI(GDIPCONST GpRect *rect,
TRACE("%p, %p\n", rect, region);
rectf.X = (REAL)rect->X;
rectf.Y = (REAL)rect->Y;
rectf.Width = (REAL)rect->Width;
rectf.Height = (REAL)rect->Height;
set_rect(&rectf, rect->X, rect->Y, rect->Width, rect->Height);
return GdipCreateRegionRect(&rectf, region);
}
@ -780,7 +772,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
type = buffer_read(mbuf, sizeof(*type));
if (!type) return Ok;
TRACE("type %#x\n", *type);
TRACE("type %#lx\n", *type);
node->type = *type;
@ -852,7 +844,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
}
if (!VALID_MAGIC(path_header->magic))
{
ERR("invalid path header magic %#x\n", path_header->magic);
ERR("invalid path header magic %#lx\n", path_header->magic);
return InvalidParameter;
}
@ -874,7 +866,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
path->pathdata.Count = path_header->count;
if (path_header->flags & ~FLAGS_INTPATH)
FIXME("unhandled path flags %#x\n", path_header->flags);
FIXME("unhandled path flags %#lx\n", path_header->flags);
if (path_header->flags & FLAGS_INTPATH)
{
@ -884,7 +876,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
pt = buffer_read(mbuf, sizeof(*pt) * path_header->count);
if (!pt)
{
ERR("failed to read packed %u path points\n", path_header->count);
ERR("failed to read packed %lu path points\n", path_header->count);
return InvalidParameter;
}
@ -901,7 +893,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
ptf = buffer_read(mbuf, sizeof(*ptf) * path_header->count);
if (!ptf)
{
ERR("failed to read %u path points\n", path_header->count);
ERR("failed to read %lu path points\n", path_header->count);
return InvalidParameter;
}
memcpy(path->pathdata.Points, ptf, sizeof(*ptf) * path_header->count);
@ -910,7 +902,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
types = buffer_read(mbuf, path_header->count);
if (!types)
{
ERR("failed to read %u path types\n", path_header->count);
ERR("failed to read %lu path types\n", path_header->count);
return InvalidParameter;
}
memcpy(path->pathdata.Types, types, path_header->count);
@ -918,7 +910,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
{
if (!buffer_read(mbuf, 4 - (path_header->count & 3)))
{
ERR("failed to read rounding %u bytes\n", 4 - (path_header->count & 3));
ERR("failed to read rounding %lu bytes\n", 4 - (path_header->count & 3));
return InvalidParameter;
}
}
@ -933,7 +925,7 @@ static GpStatus read_element(struct memory_buffer *mbuf, GpRegion *region, regio
return Ok;
default:
FIXME("element type %#x is not supported\n", *type);
FIXME("element type %#lx is not supported\n", *type);
break;
}
@ -1182,7 +1174,7 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
return Ok;
}
default:
FIXME("GdipGetRegionHRgn unimplemented for region type=%x\n", element->type);
FIXME("GdipGetRegionHRgn unimplemented for region type=%lx\n", element->type);
*hrgn = NULL;
return NotImplemented;
}

View file

@ -72,7 +72,7 @@ dll/win32/dwmapi # Synced to Wine-8.14
dll/win32/faultrep # Synced to WineStaging-4.18
dll/win32/fontsub # Synced to WineStaging-2.9
dll/win32/fusion # Synced to WineStaging-4.18
dll/win32/gdiplus # Synced to WineStaging-4.0
dll/win32/gdiplus # Synced to Wine 7abca9742a9410447636e0222e36d214449c90dd
dll/win32/hhctrl.ocx # Synced to WineStaging-4.18
dll/win32/hlink # Synced to WineStaging-4.18
dll/win32/hnetcfg # Synced to WineStaging-4.18

View file

@ -346,6 +346,45 @@ enum ImageFlags
ImageFlagsCaching = 0x00020000
};
enum EncoderParameterValueType {
EncoderParameterValueTypeByte = 1,
EncoderParameterValueTypeASCII = 2,
EncoderParameterValueTypeShort = 3,
EncoderParameterValueTypeLong = 4,
EncoderParameterValueTypeRational = 5,
EncoderParameterValueTypeLongRange = 6,
EncoderParameterValueTypeUndefined = 7,
EncoderParameterValueTypeRationalRange = 8,
EncoderParameterValueTypePointer = 9
};
enum EncoderValue {
EncoderValueColorTypeCMYK = 0,
EncoderValueColorTypeYCCK = 1,
EncoderValueCompressionLZW = 2,
EncoderValueCompressionCCITT3 = 3,
EncoderValueCompressionCCITT4 = 4,
EncoderValueCompressionRle = 5,
EncoderValueCompressionNone = 6,
EncoderValueScanMethodInterlaced = 7,
EncoderValueScanMethodNonInterlaced = 8,
EncoderValueVersionGif87 = 9,
EncoderValueVersionGif89 = 10,
EncoderValueRenderProgressive = 11,
EncoderValueRenderNonProgressive = 12,
EncoderValueTransformRotate90 = 13,
EncoderValueTransformRotate180 = 14,
EncoderValueTransformRotate270 = 15,
EncoderValueTransformFlipHorizontal = 16,
EncoderValueTransformFlipVertical = 17,
EncoderValueMultiFrame = 18,
EncoderValueLastFrame = 19,
EncoderValueFlush = 20,
EncoderValueFrameDimensionTime = 21,
EncoderValueFrameDimensionResolution = 22,
EncoderValueFrameDimensionPage = 23
};
enum CombineMode
{
CombineModeReplace,

View file

@ -611,6 +611,8 @@ extern "C"
GpStatus WINGDIPAPI
GdipSaveAdd(GpImage *, GDIPCONST EncoderParameters *);
GpStatus WINGDIPAPI
GdipSaveAddImage(GpImage*,GpImage*,GDIPCONST EncoderParameters*);
GpStatus WINGDIPAPI
GdipSaveGraphics(GpGraphics *, GraphicsState *);
GpStatus WINGDIPAPI
GdipScaleWorldTransform(GpGraphics *, REAL, REAL, GpMatrixOrder);

View file

@ -35,6 +35,8 @@ DEFINE_GUID(FrameDimensionTime, 0x6aedbd6d, 0x3fb5, 0x418a, 0x83, 0xa6, 0x7f, 0x
DEFINE_GUID(FrameDimensionPage, 0x7462dc86, 0x6180, 0x4c7e, 0x8e, 0x3f, 0xee, 0x73, 0x33, 0xa7, 0xa4, 0x83);
DEFINE_GUID(FrameDimensionResolution, 0x84236f7b, 0x3bd3, 0x428f, 0x8d, 0xab, 0x4e, 0xa1, 0x43, 0x9c, 0xa3, 0x15);
DEFINE_GUID(EncoderSaveFlag, 0x292266fc, 0xac40, 0x47bf, 0x8c, 0xfc, 0xa8, 0x5b, 0x89, 0xa6, 0x55, 0xde);
enum ImageLockMode
{
ImageLockModeRead = 1,

View file

@ -0,0 +1,5 @@
directories:
dlls/gdiplus: dll/win32/gdiplus
files: null
tags:
wine: 7abca9742a9410447636e0222e36d214449c90dd