[GDIPLUS] Sync with Wine Staging 3.9. CORE-14656

This commit is contained in:
Amine Khaldi 2018-05-27 04:10:39 +01:00
parent 4b8fbca3f7
commit 6619d0261f
11 changed files with 253 additions and 100 deletions

View file

@ -261,7 +261,7 @@ static const char HatchBrushes[][8] = {
GpStatus get_hatch_data(GpHatchStyle hatchstyle, const char **result)
{
if (hatchstyle < sizeof(HatchBrushes) / sizeof(HatchBrushes[0]))
if (hatchstyle < ARRAY_SIZE(HatchBrushes))
{
*result = HatchBrushes[hatchstyle];
return Ok;
@ -1715,6 +1715,18 @@ GpStatus WINGDIPAPI GdipSetPathGradientGammaCorrection(GpPathGradient *grad,
return Ok;
}
GpStatus WINGDIPAPI GdipSetPathGradientPath(GpPathGradient *grad, GDIPCONST GpPath *path)
{
static int calls;
TRACE("(%p, %p)\n", grad, path);
if (!(calls++))
FIXME("not implemented\n");
return NotImplemented;
}
GpStatus WINGDIPAPI GdipSetPathGradientSigmaBlend(GpPathGradient *grad,
REAL focus, REAL scale)
{

View file

@ -17,6 +17,7 @@
*/
#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
@ -38,11 +39,20 @@ GpStatus WINGDIPAPI GdipCloneCustomLineCap(GpCustomLineCap* from,
if(!from || !to)
return InvalidParameter;
*to = heap_alloc_zero(sizeof(GpCustomLineCap));
if(!*to) return OutOfMemory;
if (from->type == CustomLineCapTypeDefault)
*to = heap_alloc_zero(sizeof(GpCustomLineCap));
else
*to = heap_alloc_zero(sizeof(GpAdjustableArrowCap));
memcpy(*to, from, sizeof(GpCustomLineCap));
if (!*to)
return OutOfMemory;
if (from->type == CustomLineCapTypeDefault)
**to = *from;
else
*(GpAdjustableArrowCap *)*to = *(GpAdjustableArrowCap *)from;
/* Duplicate path data */
(*to)->pathdata.Points = heap_alloc_zero(from->pathdata.Count * sizeof(PointF));
(*to)->pathdata.Types = heap_alloc_zero(from->pathdata.Count);
@ -62,12 +72,44 @@ GpStatus WINGDIPAPI GdipCloneCustomLineCap(GpCustomLineCap* from,
return Ok;
}
static GpStatus init_custom_linecap(GpCustomLineCap *cap, GpPathData *pathdata, BOOL fill, GpLineCap basecap,
REAL base_inset)
{
cap->fill = fill;
cap->pathdata.Points = heap_alloc_zero(pathdata->Count * sizeof(PointF));
cap->pathdata.Types = heap_alloc_zero(pathdata->Count);
if ((!cap->pathdata.Types || !cap->pathdata.Points) && pathdata->Count)
{
heap_free(cap->pathdata.Points);
heap_free(cap->pathdata.Types);
cap->pathdata.Points = NULL;
cap->pathdata.Types = NULL;
return OutOfMemory;
}
if (pathdata->Points)
memcpy(cap->pathdata.Points, pathdata->Points, pathdata->Count * sizeof(PointF));
if (pathdata->Types)
memcpy(cap->pathdata.Types, pathdata->Types, pathdata->Count);
cap->pathdata.Count = pathdata->Count;
cap->inset = base_inset;
cap->cap = basecap;
cap->join = LineJoinMiter;
cap->scale = 1.0;
return Ok;
}
/* FIXME: Sometimes when fillPath is non-null and stroke path is null, the native
* version of this function returns NotImplemented. I cannot figure out why. */
GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath* fillPath, GpPath* strokePath,
GpLineCap baseCap, REAL baseInset, GpCustomLineCap **customCap)
{
GpPathData *pathdata;
GpStatus stat;
TRACE("%p %p %d %f %p\n", fillPath, strokePath, baseCap, baseInset, customCap);
@ -77,37 +119,18 @@ GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath* fillPath, GpPath* strokePath
*customCap = heap_alloc_zero(sizeof(GpCustomLineCap));
if(!*customCap) return OutOfMemory;
(*customCap)->type = CustomLineCapTypeDefault;
if(strokePath){
(*customCap)->fill = FALSE;
if (strokePath)
pathdata = &strokePath->pathdata;
}
else{
(*customCap)->fill = TRUE;
else
pathdata = &fillPath->pathdata;
}
(*customCap)->pathdata.Points = heap_alloc_zero(pathdata->Count * sizeof(PointF));
(*customCap)->pathdata.Types = heap_alloc_zero(pathdata->Count);
if((!(*customCap)->pathdata.Types || !(*customCap)->pathdata.Points) &&
pathdata->Count){
heap_free((*customCap)->pathdata.Points);
heap_free((*customCap)->pathdata.Types);
stat = init_custom_linecap(*customCap, pathdata, fillPath != NULL, baseCap, baseInset);
if (stat != Ok)
{
heap_free(*customCap);
return OutOfMemory;
return stat;
}
memcpy((*customCap)->pathdata.Points, pathdata->Points, pathdata->Count
* sizeof(PointF));
memcpy((*customCap)->pathdata.Types, pathdata->Types, pathdata->Count);
(*customCap)->pathdata.Count = pathdata->Count;
(*customCap)->inset = baseInset;
(*customCap)->cap = baseCap;
(*customCap)->join = LineJoinMiter;
(*customCap)->scale = 1.0;
TRACE("<-- %p\n", *customCap);
return Ok;
@ -257,111 +280,175 @@ GpStatus WINGDIPAPI GdipGetCustomLineCapType(GpCustomLineCap *customCap, CustomL
return Ok;
}
static void arrowcap_update_path(GpAdjustableArrowCap *cap)
{
static const BYTE types_filled[] =
{
PathPointTypeStart, PathPointTypeLine, PathPointTypeLine, PathPointTypeLine | PathPointTypeCloseSubpath
};
static const BYTE types_unfilled[] =
{
PathPointTypeStart, PathPointTypeLine, PathPointTypeLine
};
GpPointF *points;
assert(cap->cap.pathdata.Count == 3 || cap->cap.pathdata.Count == 4);
points = cap->cap.pathdata.Points;
if (cap->cap.fill)
{
memcpy(cap->cap.pathdata.Types, types_filled, sizeof(types_filled));
cap->cap.pathdata.Count = 4;
points[0].X = -cap->width / 2.0;
points[0].Y = -cap->height;
points[1].X = 0.0;
points[1].Y = 0.0;
points[2].X = cap->width / 2.0;
points[2].Y = -cap->height;
points[3].X = 0.0;
points[3].Y = -cap->height - cap->middle_inset;
}
else
{
memcpy(cap->cap.pathdata.Types, types_unfilled, sizeof(types_unfilled));
cap->cap.pathdata.Count = 3;
points[0].X = -cap->width / 4.0;
points[0].Y = -cap->height / 2.0;
points[1].X = 0.0;
points[1].Y = 0.0;
points[2].X = cap->width / 4.0;
points[2].Y = -cap->height / 2.0;
}
if (cap->width == 0.0)
cap->cap.inset = 0.0;
else
cap->cap.inset = cap->height / cap->width;
}
GpStatus WINGDIPAPI GdipCreateAdjustableArrowCap(REAL height, REAL width, BOOL fill,
GpAdjustableArrowCap **cap)
{
static int calls;
GpPathData pathdata;
GpStatus stat;
TRACE("(%0.2f,%0.2f,%i,%p)\n", height, width, fill, cap);
if(!(calls++))
FIXME("not implemented\n");
if (!cap)
return InvalidParameter;
return NotImplemented;
*cap = heap_alloc_zero(sizeof(**cap));
if (!*cap)
return OutOfMemory;
/* We'll need 4 points at most. */
pathdata.Count = 4;
pathdata.Points = NULL;
pathdata.Types = NULL;
stat = init_custom_linecap(&(*cap)->cap, &pathdata, fill, LineCapTriangle, width != 0.0 ? height / width : 0.0);
if (stat != Ok)
{
heap_free(*cap);
return stat;
}
(*cap)->cap.type = CustomLineCapTypeAdjustableArrow;
(*cap)->height = height;
(*cap)->width = width;
(*cap)->middle_inset = 0.0;
arrowcap_update_path(*cap);
return Ok;
}
GpStatus WINGDIPAPI GdipGetAdjustableArrowCapFillState(GpAdjustableArrowCap* cap, BOOL* fill)
{
static int calls;
TRACE("(%p,%p)\n", cap, fill);
if(!(calls++))
FIXME("not implemented\n");
if (!cap || !fill)
return InvalidParameter;
return NotImplemented;
*fill = cap->cap.fill;
return Ok;
}
GpStatus WINGDIPAPI GdipGetAdjustableArrowCapHeight(GpAdjustableArrowCap* cap, REAL* height)
{
static int calls;
TRACE("(%p,%p)\n", cap, height);
if(!(calls++))
FIXME("not implemented\n");
if (!cap || !height)
return InvalidParameter;
return NotImplemented;
*height = cap->height;
return Ok;
}
GpStatus WINGDIPAPI GdipGetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap* cap, REAL* middle)
{
static int calls;
TRACE("(%p,%p)\n", cap, middle);
if(!(calls++))
FIXME("not implemented\n");
if (!cap || !middle)
return InvalidParameter;
return NotImplemented;
*middle = cap->middle_inset;
return Ok;
}
GpStatus WINGDIPAPI GdipGetAdjustableArrowCapWidth(GpAdjustableArrowCap* cap, REAL* width)
{
static int calls;
TRACE("(%p,%p)\n", cap, width);
if(!(calls++))
FIXME("not implemented\n");
if (!cap || !width)
return InvalidParameter;
return NotImplemented;
*width = cap->width;
return Ok;
}
GpStatus WINGDIPAPI GdipSetAdjustableArrowCapFillState(GpAdjustableArrowCap* cap, BOOL fill)
{
static int calls;
TRACE("(%p,%i)\n", cap, fill);
if(!(calls++))
FIXME("not implemented\n");
if (!cap)
return InvalidParameter;
return NotImplemented;
cap->cap.fill = fill;
arrowcap_update_path(cap);
return Ok;
}
GpStatus WINGDIPAPI GdipSetAdjustableArrowCapHeight(GpAdjustableArrowCap* cap, REAL height)
{
static int calls;
TRACE("(%p,%0.2f)\n", cap, height);
if(!(calls++))
FIXME("not implemented\n");
if (!cap)
return InvalidParameter;
return NotImplemented;
cap->height = height;
arrowcap_update_path(cap);
return Ok;
}
GpStatus WINGDIPAPI GdipSetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap* cap, REAL middle)
{
static int calls;
TRACE("(%p,%0.2f)\n", cap, middle);
if(!(calls++))
FIXME("not implemented\n");
if (!cap)
return InvalidParameter;
return NotImplemented;
cap->middle_inset = middle;
arrowcap_update_path(cap);
return Ok;
}
GpStatus WINGDIPAPI GdipSetAdjustableArrowCapWidth(GpAdjustableArrowCap* cap, REAL width)
{
static int calls;
TRACE("(%p,%0.2f)\n", cap, width);
if(!(calls++))
FIXME("not implemented\n");
if (!cap)
return InvalidParameter;
return NotImplemented;
cap->width = width;
arrowcap_update_path(cap);
return Ok;
}

View file

@ -1367,7 +1367,7 @@ static int match_name_table_language( const tt_name_record *name, LANGID lang )
case TT_PLATFORM_MACINTOSH:
if (!IsValidCodePage( get_mac_code_page( name ))) return 0;
name_lang = GET_BE_WORD(name->language_id);
if (name_lang >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
if (name_lang >= ARRAY_SIZE(mac_langid_table)) return 0;
name_lang = mac_langid_table[name_lang];
break;
case TT_PLATFORM_APPLE_UNICODE:
@ -1377,7 +1377,7 @@ static int match_name_table_language( const tt_name_record *name, LANGID lang )
case TT_APPLE_ID_ISO_10646:
case TT_APPLE_ID_UNICODE_2_0:
name_lang = GET_BE_WORD(name->language_id);
if (name_lang >= sizeof(mac_langid_table)/sizeof(mac_langid_table[0])) return 0;
if (name_lang >= ARRAY_SIZE(mac_langid_table)) return 0;
name_lang = mac_langid_table[name_lang];
break;
default:

View file

@ -534,7 +534,7 @@
534 stdcall GdipSetPathGradientFocusScales(ptr float float)
535 stdcall GdipSetPathGradientGammaCorrection(ptr long)
536 stdcall GdipSetPathGradientLinearBlend(ptr float float)
537 stub GdipSetPathGradientPath
537 stdcall GdipSetPathGradientPath(ptr ptr)
538 stdcall GdipSetPathGradientPresetBlend(ptr ptr ptr long)
539 stdcall GdipSetPathGradientSigmaBlend(ptr float float)
540 stdcall GdipSetPathGradientSurroundColorsWithCount(ptr ptr ptr)

View file

@ -35,6 +35,8 @@
#include "gdiplus.h"
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
#define GP_DEFAULT_PENSTYLE (PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | PS_JOIN_MITER)
#define MAX_ARC_PTS (13)
#define MAX_DASHLEN (16) /* this is a limitation of gdi */
@ -341,6 +343,9 @@ struct GpCustomLineCap{
struct GpAdjustableArrowCap{
GpCustomLineCap cap;
REAL middle_inset;
REAL height;
REAL width;
};
struct GpImage{

View file

@ -353,15 +353,20 @@ static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn)
GpRegion *rgn;
GpMatrix transform;
GpStatus stat;
BOOL identity;
stat = get_graphics_transform(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceDevice, &transform);
if (stat == Ok)
stat = GdipIsMatrixIdentity(&transform, &identity);
if (stat == Ok)
stat = GdipCloneRegion(graphics->clip, &rgn);
if (stat == Ok)
{
stat = GdipTransformRegion(rgn, &transform);
if (!identity)
stat = GdipTransformRegion(rgn, &transform);
if (stat == Ok)
stat = GdipGetRegionHRgn(rgn, NULL, hrgn);
@ -1695,9 +1700,9 @@ static void draw_cap(GpGraphics *graphics, COLORREF color, GpLineCap cap, REAL s
ptf[3].X = x2 - dbig;
ptf[2].X = x2 + dsmall;
gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, ptf, 3);
gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, ptf, 4);
round_points(pt, ptf, 3);
round_points(pt, ptf, 4);
Polygon(graphics->hdc, pt, 4);
@ -1735,9 +1740,9 @@ static void draw_cap(GpGraphics *graphics, COLORREF color, GpLineCap cap, REAL s
ptf[1].X = x2 + dx;
ptf[1].Y = y2 + dy;
gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, ptf, 3);
gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, ptf, 2);
round_points(pt, ptf, 3);
round_points(pt, ptf, 2);
Ellipse(graphics->hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y);
@ -1781,9 +1786,9 @@ static void draw_cap(GpGraphics *graphics, COLORREF color, GpLineCap cap, REAL s
ptf[3].X = x2 + dx;
ptf[3].Y = y2 + dy;
gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, ptf, 3);
gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, ptf, 4);
round_points(pt, ptf, 3);
round_points(pt, ptf, 4);
Pie(graphics->hdc, pt[0].x, pt[0].y, pt[1].x, pt[1].y, pt[2].x,
pt[2].y, pt[3].x, pt[3].y);
@ -1793,6 +1798,13 @@ static void draw_cap(GpGraphics *graphics, COLORREF color, GpLineCap cap, REAL s
if(!custom)
break;
if (custom->type == CustomLineCapTypeAdjustableArrow)
{
GpAdjustableArrowCap *arrow = (GpAdjustableArrowCap *)custom;
if (arrow->cap.fill && arrow->height <= 0.0)
break;
}
count = custom->pathdata.Count;
custptf = heap_alloc_zero(count * sizeof(PointF));
custpt = heap_alloc_zero(count * sizeof(POINT));
@ -1810,9 +1822,9 @@ static void draw_cap(GpGraphics *graphics, COLORREF color, GpLineCap cap, REAL s
GdipTranslateMatrix(&matrix, x2, y2, MatrixOrderAppend);
GdipTransformMatrixPoints(&matrix, custptf, count);
gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, ptf, 3);
gdip_transform_points(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceWorld, custptf, count);
round_points(pt, ptf, 3);
round_points(custpt, custptf, count);
for(i = 0; i < count; i++)
tp[i] = convert_path_point_type(custom->pathdata.Types[i]);
@ -6469,9 +6481,12 @@ GpStatus WINGDIPAPI GdipSetClipRect(GpGraphics *graphics, REAL x, REAL y,
if (status == Ok)
{
GpMatrix world_to_device;
BOOL identity;
get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
status = GdipTransformRegion(region, &world_to_device);
status = GdipIsMatrixIdentity(&world_to_device, &identity);
if (status == Ok && !identity)
status = GdipTransformRegion(region, &world_to_device);
if (status == Ok)
status = GdipCombineRegionRegion(graphics->clip, region, mode);
@ -6520,9 +6535,12 @@ GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region,
if (status == Ok)
{
GpMatrix world_to_device;
BOOL identity;
get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
status = GdipTransformRegion(clip, &world_to_device);
status = GdipIsMatrixIdentity(&world_to_device, &identity);
if (status == Ok && !identity)
status = GdipTransformRegion(clip, &world_to_device);
if (status == Ok)
status = GdipCombineRegionRegion(graphics->clip, clip, mode);

View file

@ -2560,7 +2560,7 @@ static UINT vt_to_itemtype(UINT vt)
{ VT_BLOB, PropertyTagTypeUndefined }
};
UINT i;
for (i = 0; i < sizeof(vt2type)/sizeof(vt2type[0]); i++)
for (i = 0; i < ARRAY_SIZE(vt2type); i++)
{
if (vt2type[i].vt == vt) return vt2type[i].type;
}
@ -3460,10 +3460,10 @@ static void png_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UI
{
if (name.vt == VT_LPSTR)
{
for (j=0; j<sizeof(keywords)/sizeof(keywords[0]); j++)
for (j = 0; j < ARRAY_SIZE(keywords); j++)
if (!strcmp(keywords[j].name, name.u.pszVal))
break;
if (j < sizeof(keywords)/sizeof(keywords[0]) && !keywords[j].seen)
if (j < ARRAY_SIZE(keywords) && !keywords[j].seen)
{
keywords[j].seen = TRUE;
item = create_prop(keywords[j].propid, &value);
@ -4586,7 +4586,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream,
encode_image_func encode_image;
int i;
TRACE("%p %p %s %p\n", image, stream, wine_dbgstr_guid(clsid), params);
TRACE("%p, %p, %s, %p\n", image, stream, wine_dbgstr_guid(clsid), params);
if(!image || !stream)
return InvalidParameter;

View file

@ -606,7 +606,7 @@ void METAFILE_Free(GpMetafile *metafile)
if (metafile->record_stream)
IStream_Release(metafile->record_stream);
for (i = 0; i < sizeof(metafile->objtable)/sizeof(metafile->objtable[0]); i++)
for (i = 0; i < ARRAY_SIZE(metafile->objtable); i++)
metafile_free_object_table_entry(metafile, i);
}

View file

@ -460,17 +460,12 @@ GpStatus WINGDIPAPI GdipGetPenTransform(GpPen *pen, GpMatrix *matrix)
GpStatus WINGDIPAPI GdipTranslatePenTransform(GpPen *pen, REAL dx, REAL dy, GpMatrixOrder order)
{
static int calls;
TRACE("(%p,%0.2f,%0.2f,%u)\n", pen, dx, dy, order);
if(!pen)
return InvalidParameter;
if(!(calls++))
FIXME("not implemented\n");
return NotImplemented;
return GdipTranslateMatrix(&pen->transform, dx, dy, order);
}
GpStatus WINGDIPAPI GdipScalePenTransform(GpPen *pen, REAL sx, REAL sy, GpMatrixOrder order)

View file

@ -1398,10 +1398,46 @@ static GpStatus transform_region_element(region_element* element, GpMatrix *matr
return Ok;
case RegionDataRect:
{
/* We can't transform a rectangle, so convert it to a path. */
GpRegion *new_region;
GpPath *path;
if (matrix->matrix[1] == 0.0 && matrix->matrix[2] == 0.0)
{
GpPointF points[2];
points[0].X = element->elementdata.rect.X;
points[0].Y = element->elementdata.rect.Y;
points[1].X = element->elementdata.rect.X + element->elementdata.rect.Width;
points[1].Y = element->elementdata.rect.Y + element->elementdata.rect.Height;
stat = GdipTransformMatrixPoints(matrix, points, 2);
if (stat != Ok)
return stat;
if (points[0].X > points[1].X)
{
REAL temp;
temp = points[0].X;
points[0].X = points[1].X;
points[1].X = temp;
}
if (points[0].Y > points[1].Y)
{
REAL temp;
temp = points[0].Y;
points[0].Y = points[1].Y;
points[1].Y = temp;
}
element->elementdata.rect.X = points[0].X;
element->elementdata.rect.Y = points[0].Y;
element->elementdata.rect.Width = points[1].X - points[0].X;
element->elementdata.rect.Height = points[1].Y - points[0].Y;
return Ok;
}
/* We can't rotate/shear a rectangle, so convert it to a path. */
stat = GdipCreatePath(FillModeAlternate, &path);
if (stat == Ok)
{

View file

@ -68,7 +68,7 @@ reactos/dll/win32/dciman32 # Synced to WineStaging-3.3
reactos/dll/win32/faultrep # Synced to WineStaging-2.9
reactos/dll/win32/fontsub # Synced to WineStaging-2.9
reactos/dll/win32/fusion # Synced to WineStaging-3.3
reactos/dll/win32/gdiplus # Synced to WineStaging-3.3
reactos/dll/win32/gdiplus # Synced to WineStaging-3.9
reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-3.3
reactos/dll/win32/hlink # Synced to WineStaging-3.3
reactos/dll/win32/hnetcfg # Synced to WineStaging-3.3