GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
{
+ TRACE("(%p, %p)\n", brush, clone);
+
if(!brush || !clone)
return InvalidParameter;
{
COLORREF col = ARGB2COLORREF(startcolor);
+ TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint, endpoint,
+ startcolor, endcolor, wrap, line);
+
if(!line || !startpoint || !endpoint || wrap == WrapModeClamp)
return InvalidParameter;
GpPointF stF;
GpPointF endF;
+ TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint, endpoint,
+ startcolor, endcolor, wrap, line);
+
if(!startpoint || !endpoint)
return InvalidParameter;
{
GpPointF start, end;
+ TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
+ wrap, line);
+
if(!line || !rect)
return InvalidParameter;
{
GpRectF rectF;
+ TRACE("(%p, %x, %x, %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;
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,
+ wrap, line);
+
return GdipCreateLineBrushFromRect(rect, startcolor, endcolor, LinearGradientModeForwardDiagonal,
wrap, line);
}
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,
+ wrap, line);
+
return GdipCreateLineBrushFromRectI(rect, startcolor, endcolor, LinearGradientModeForwardDiagonal,
wrap, line);
}
{
COLORREF col = ARGB2COLORREF(0xffffffff);
+ TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
+
if(!points || !grad)
return InvalidParameter;
GpStatus ret;
INT i;
+ TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
+
if(!points || !grad)
return InvalidParameter;
{
COLORREF col = ARGB2COLORREF(0xffffffff);
+ TRACE("(%p, %p)\n", path, grad);
+
if(!path || !grad)
return InvalidParameter;
{
COLORREF col = ARGB2COLORREF(color);
+ TRACE("(%x, %p)\n", color, sf);
+
if(!sf) return InvalidParameter;
*sf = GdipAlloc(sizeof(GpSolidFill));
return Ok;
}
+/*******************************************************************************
+ * GdipCreateTexture [GDIPLUS.@]
+ *
+ * PARAMS
+ * image [I] image to use
+ * wrapmode [I] optional
+ * texture [O] pointer to the resulting texturebrush
+ *
+ * RETURNS
+ * SUCCESS: Ok
+ * FAILURE: element of GpStatus
+ */
+GpStatus WINGDIPAPI GdipCreateTexture(GpImage *image, GpWrapMode wrapmode,
+ GpTexture **texture)
+{
+ UINT width, height;
+ GpImageAttributes attributes;
+ GpStatus stat;
+
+ TRACE("%p, %d %p\n", image, wrapmode, texture);
+
+ if (!(image && texture))
+ return InvalidParameter;
+
+ stat = GdipGetImageWidth(image, &width);
+ if (stat != Ok) return stat;
+ stat = GdipGetImageHeight(image, &height);
+ if (stat != Ok) return stat;
+ attributes.wrap = wrapmode;
+
+ return GdipCreateTextureIA(image, &attributes, 0, 0, width, height,
+ texture);
+}
+
+GpStatus WINGDIPAPI GdipCreateTexture2(GpImage *image, GpWrapMode wrapmode,
+ REAL x, REAL y, REAL width, REAL height, GpTexture **texture)
+{
+ GpImageAttributes attributes;
+
+ TRACE("%p %d %f %f %f %f %p\n", image, wrapmode,
+ x, y, width, height, texture);
+
+ attributes.wrap = wrapmode;
+ return GdipCreateTextureIA(image, &attributes, x, y, width, height,
+ texture);
+}
+
/* FIXME: imageattr ignored */
GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
GDIPCONST GpImageAttributes *imageattr, REAL x, REAL y, REAL width,
BOOL bm_is_selected;
BYTE *dibits, *buff, *textbits;
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image, imageattr, x, y, width, height,
+ texture);
+
if(!image || !texture || x < 0.0 || y < 0.0 || width < 0.0 || height < 0.0)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCreateTextureIAI(GpImage *image, GDIPCONST GpImageAttributes *imageattr,
INT x, INT y, INT width, INT height, GpTexture **texture)
{
+ TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image, imageattr, x, y, width, height,
+ texture);
+
return GdipCreateTextureIA(image,imageattr,(REAL)x,(REAL)y,(REAL)width,(REAL)height,texture);
}
+GpStatus WINGDIPAPI GdipCreateTexture2I(GpImage *image, GpWrapMode wrapmode,
+ INT x, INT y, INT width, INT height, GpTexture **texture)
+{
+ GpImageAttributes imageattr;
+
+ TRACE("%p %d %d %d %d %d %p\n", image, wrapmode, x, y, width, height,
+ texture);
+
+ imageattr.wrap = wrapmode;
+
+ return GdipCreateTextureIA(image, &imageattr, x, y, width, height, texture);
+}
+
GpStatus WINGDIPAPI GdipGetBrushType(GpBrush *brush, GpBrushType *type)
{
+ TRACE("(%p, %p)\n", brush, type);
+
if(!brush || !type) return InvalidParameter;
*type = brush->bt;
GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
{
+ TRACE("(%p)\n", brush);
+
if(!brush) return InvalidParameter;
switch(brush->bt)
GpStatus WINGDIPAPI GdipGetLineGammaCorrection(GpLineGradient *line,
BOOL *usinggamma)
{
- if(!line)
+ TRACE("(%p, %p)\n", line, usinggamma);
+
+ if(!line || !usinggamma)
return InvalidParameter;
*usinggamma = line->gamma;
GpStatus WINGDIPAPI GdipGetLineWrapMode(GpLineGradient *brush, GpWrapMode *wrapmode)
{
+ TRACE("(%p, %p)\n", brush, wrapmode);
+
if(!brush || !wrapmode)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathGradientBlend(GpPathGradient *brush, REAL *blend,
REAL *positions, INT count)
{
+ TRACE("(%p, %p, %p, %d)\n", brush, blend, positions, count);
+
if(!brush || !blend || !positions || count <= 0)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathGradientBlendCount(GpPathGradient *brush, INT *count)
{
+ TRACE("(%p, %p)\n", brush, count);
+
if(!brush || !count)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathGradientCenterPoint(GpPathGradient *grad,
GpPointF *point)
{
+ TRACE("(%p, %p)\n", grad, point);
+
if(!grad || !point)
return InvalidParameter;
GpStatus ret;
GpPointF ptf;
+ TRACE("(%p, %p)\n", grad, point);
+
if(!point)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathGradientFocusScales(GpPathGradient *grad,
REAL *x, REAL *y)
{
+ TRACE("(%p, %p, %p)\n", grad, x, y);
+
if(!grad || !x || !y)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathGradientGammaCorrection(GpPathGradient *grad,
BOOL *gamma)
{
+ TRACE("(%p, %p)\n", grad, gamma);
+
if(!grad || !gamma)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathGradientPointCount(GpPathGradient *grad,
INT *count)
{
+ TRACE("(%p, %p)\n", grad, count);
+
if(!grad || !count)
return InvalidParameter;
GpPath* path;
GpStatus stat;
+ TRACE("(%p, %p)\n", brush, rect);
+
if(!brush || !rect)
return InvalidParameter;
GpRectF rectf;
GpStatus stat;
+ TRACE("(%p, %p)\n", brush, rect);
+
if(!brush || !rect)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathGradientWrapMode(GpPathGradient *brush,
GpWrapMode *wrapmode)
{
+ TRACE("(%p, %p)\n", brush, wrapmode);
+
if(!brush || !wrapmode)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetSolidFillColor(GpSolidFill *sf, ARGB *argb)
{
+ TRACE("(%p, %p)\n", sf, argb);
+
if(!sf || !argb)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetLineGammaCorrection(GpLineGradient *line,
BOOL usegamma)
{
+ TRACE("(%p, %d)\n", line, usegamma);
+
if(!line)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetLineWrapMode(GpLineGradient *line,
GpWrapMode wrap)
{
+ TRACE("(%p, %d)\n", line, wrap);
+
if(!line || wrap == WrapModeClamp)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetPathGradientCenterColor(GpPathGradient *grad,
ARGB argb)
{
+ TRACE("(%p, %x)\n", grad, argb);
+
if(!grad)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetPathGradientCenterPoint(GpPathGradient *grad,
GpPointF *point)
{
+ TRACE("(%p, %p)\n", grad, point);
+
if(!grad || !point)
return InvalidParameter;
{
GpPointF ptf;
+ TRACE("(%p, %p)\n", grad, point);
+
if(!point)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetPathGradientFocusScales(GpPathGradient *grad,
REAL x, REAL y)
{
+ TRACE("(%p, %.2f, %.2f)\n", grad, x, y);
+
if(!grad)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetPathGradientGammaCorrection(GpPathGradient *grad,
BOOL gamma)
{
+ TRACE("(%p, %d)\n", grad, gamma);
+
if(!grad)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetPathGradientWrapMode(GpPathGradient *grad,
GpWrapMode wrap)
{
+ TRACE("(%p, %d)\n", grad, wrap);
+
if(!grad)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb)
{
+ TRACE("(%p, %x)\n", sf, argb);
+
if(!sf)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetLineColors(GpLineGradient *brush, ARGB color1,
ARGB color2)
{
+ TRACE("(%p, %x, %x)\n", brush, color1, color2);
+
if(!brush)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetLineColors(GpLineGradient *brush, ARGB *colors)
{
+ TRACE("(%p, %p)\n", brush, colors);
+
if(!brush || !colors)
return InvalidParameter;
return NotImplemented;
}
+GpStatus WINGDIPAPI GdipTranslateLineTransform(GpLineGradient* brush,
+ REAL dx, REAL dy, GpMatrixOrder order)
+{
+ FIXME("stub: %p %f %f %d\n", brush, dx, dy, order);
+
+ return NotImplemented;
+}
+
GpStatus WINGDIPAPI GdipGetLineRect(GpLineGradient *brush, GpRectF *rect)
{
+ TRACE("(%p, %p)\n", brush, rect);
+
if(!brush || !rect)
return InvalidParameter;
GpRectF rectF;
GpStatus ret;
+ TRACE("(%p, %p)\n", brush, rect);
+
if(!rect)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCloneCustomLineCap(GpCustomLineCap* from,
GpCustomLineCap** to)
{
+ TRACE("(%p, %p)\n", from, to);
+
if(!from || !to)
return InvalidParameter;
GpStatus WINGDIPAPI GdipDeleteCustomLineCap(GpCustomLineCap *customCap)
{
+ TRACE("(%p)\n", customCap);
+
if(!customCap)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetCustomLineCapStrokeJoin(GpCustomLineCap* customCap,
GpLineJoin* lineJoin)
{
+ TRACE("(%p, %p)\n", customCap, lineJoin);
+
if(!customCap || !lineJoin)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetCustomLineCapWidthScale(GpCustomLineCap* custom,
REAL* widthScale)
{
+ TRACE("(%p, %p)\n", custom, widthScale);
+
if(!custom || !widthScale)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetCustomLineCapBaseInset(GpCustomLineCap* custom,
REAL* inset)
{
+ TRACE("(%p, %p)\n", custom, inset);
+
if(!custom || !inset)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetCustomLineCapStrokeJoin(GpCustomLineCap* custom,
GpLineJoin join)
{
+ TRACE("(%p, %d)\n", custom, join);
+
if(!custom)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetCustomLineCapBaseCap(GpCustomLineCap *customCap, GpLineCap *baseCap)
{
+ TRACE("(%p, %p)\n", customCap, baseCap);
+
if(!customCap || !baseCap)
return InvalidParameter;
return Ok;
}
+
+GpStatus WINGDIPAPI GdipCreateAdjustableArrowCap(REAL height, REAL width, BOOL fill,
+ GpAdjustableArrowCap **cap)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipGetAdjustableArrowCapFillState(GpAdjustableArrowCap* cap, BOOL* fill)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipGetAdjustableArrowCapHeight(GpAdjustableArrowCap* cap, REAL* height)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipGetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap* cap, REAL* middle)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipGetAdjustableArrowCapWidth(GpAdjustableArrowCap* cap, REAL* width)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipSetAdjustableArrowCapFillState(GpAdjustableArrowCap* cap, BOOL fill)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipSetAdjustableArrowCapHeight(GpAdjustableArrowCap* cap, REAL height)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipSetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap* cap, REAL middle)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipSetAdjustableArrowCapWidth(GpAdjustableArrowCap* cap, REAL width)
+{
+ static int calls;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
HFONT hfont, oldfont;
TEXTMETRICW textmet;
+ TRACE("(%p, %p, %p)\n", hdc, logfont, font);
+
if(!logfont || !font)
return InvalidParameter;
+ if (logfont->lfFaceName[0] == 0)
+ return NotTrueTypeFont;
+
*font = GdipAlloc(sizeof(GpFont));
if(!*font) return OutOfMemory;
{
LOGFONTW lfw;
+ TRACE("(%p, %p, %p)\n", hdc, lfa, font);
+
if(!lfa || !font)
return InvalidParameter;
*/
GpStatus WINGDIPAPI GdipDeleteFont(GpFont* font)
{
+ TRACE("(%p)\n", font);
+
if(!font)
return InvalidParameter;
HFONT hfont;
LOGFONTW lfw;
+ TRACE("(%p, %p)\n", hdc, font);
+
if(!font)
return InvalidParameter;
return GdipCreateFontFromLogfontW(hdc, &lfw, font);
}
+/*******************************************************************************
+ * GdipGetFamily [GDIPLUS.@]
+ *
+ * Returns the FontFamily for the specified Font
+ *
+ * PARAMS
+ * font [I] Font to request from
+ * family [O] Resulting FontFamily object
+ *
+ * RETURNS
+ * SUCCESS: Ok
+ * FAILURE: An element of GpStatus
+ */
+GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
+{
+ TRACE("%p %p\n", font, family);
+
+ if (!(font && family))
+ return InvalidParameter;
+
+ return GdipCreateFontFamilyFromName(font->lfw.lfFaceName, NULL, family);
+}
+
/******************************************************************************
* GdipGetFontSize [GDIPLUS.@]
*
*/
GpStatus WINGDIPAPI GdipGetFontSize(GpFont *font, REAL *size)
{
+ TRACE("(%p, %p)\n", font, size);
+
if (!(font && size)) return InvalidParameter;
*size = font->emSize;
return Ok;
}
+/*******************************************************************************
+ * GdipGetFontStyle [GDIPLUS.@]
+ *
+ * Gets the font's style, returned in bitwise OR of FontStyle enumeration
+ *
+ * PARAMS
+ * font [I] font to request from
+ * style [O] resulting pointer to a FontStyle enumeration
+ *
+ * RETURNS
+ * SUCCESS: Ok
+ * FAILURE: InvalidParameter
+ */
+GpStatus WINGDIPAPI GdipGetFontStyle(GpFont *font, INT *style)
+{
+ TRACE("%p %p\n", font, style);
+
+ if (!(font && style))
+ return InvalidParameter;
+
+ if (font->lfw.lfWeight > 400)
+ *style = FontStyleBold;
+ else
+ *style = 0;
+ if (font->lfw.lfItalic)
+ *style |= FontStyleItalic;
+ if (font->lfw.lfUnderline)
+ *style |= FontStyleUnderline;
+ if (font->lfw.lfStrikeOut)
+ *style |= FontStyleStrikeout;
+
+ return Ok;
+}
+
/*******************************************************************************
* GdipGetFontUnit [GDIPLUS.@]
*
*/
GpStatus WINGDIPAPI GdipGetFontUnit(GpFont *font, Unit *unit)
{
+ TRACE("(%p, %p)\n", font, unit);
+
if (!(font && unit)) return InvalidParameter;
*unit = font->unit;
GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics,
LOGFONTW *lfw)
{
+ TRACE("(%p, %p, %p)\n", font, graphics, lfw);
+
/* FIXME: use graphics */
if(!font || !graphics || !lfw)
return InvalidParameter;
*/
GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont)
{
+ TRACE("(%p, %p)\n", font, cloneFont);
+
if(!font || !cloneFont)
return InvalidParameter;
return Ok;
}
+/*******************************************************************************
+ * GdipGetFontHeight [GDIPLUS.@]
+ * PARAMS
+ * font [I] Font to retrieve height from
+ * graphics [I] The current graphics context
+ * height [O] Resulting height
+ * RETURNS
+ * SUCCESS: Ok
+ * FAILURE: Another element of GpStatus
+ *
+ * NOTES
+ * Forwards to GdipGetFontHeightGivenDPI
+ */
+GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont *font,
+ GDIPCONST GpGraphics *graphics, REAL *height)
+{
+ REAL dpi;
+
+ TRACE("%p %p %p\n", font, graphics, height);
+
+ dpi = GetDeviceCaps(graphics->hdc, LOGPIXELSY);
+
+ return GdipGetFontHeightGivenDPI(font, dpi, height);
+}
+
/*******************************************************************************
* GdipGetFontHeightGivenDPI [GDIPLUS.@]
* PARAMS
*/
GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont *font, REAL dpi, REAL *height)
{
+ TRACE("%p (%s), %f, %p\n", font,
+ debugstr_w(font->lfw.lfFaceName), dpi, height);
+
if (!(font && height)) return InvalidParameter;
- FIXME("%p (%s), %f, %p\n", font,
- debugstr_w(font->lfw.lfFaceName), dpi, height);
+ switch (font->unit)
+ {
+ case UnitPixel:
+ *height = font->emSize;
+ break;
+ default:
+ FIXME("Unhandled unit type: %d\n", font->unit);
+ return NotImplemented;
+ }
- return NotImplemented;
+ return Ok;
}
/***********************************************************************
GpStatus WINGDIPAPI GdipGetCellDescent(GDIPCONST GpFontFamily *family,
INT style, UINT16* CellDescent)
{
+ TRACE("(%p, %d, %p)\n", family, style, CellDescent);
+
if (!(family && CellDescent)) return InvalidParameter;
*CellDescent = family->tmw.tmDescent;
{
static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'};
+ TRACE("(%p)\n", nativeFamily);
+
if (nativeFamily == NULL) return InvalidParameter;
return GdipCreateFontFamilyFromName(TimesNewRoman, NULL, nativeFamily);
* affect anything */
static const WCHAR MSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'};
+ TRACE("(%p)\n", nativeFamily);
+
if (nativeFamily == NULL) return InvalidParameter;
return GdipCreateFontFamilyFromName(MSSansSerif, NULL, nativeFamily);
*x = roundr(tension * (xadj - xend) + xend);
*y = roundr(tension * (yadj - yend) + yend);
}
+
+/* make sure path has enough space for len more points */
+BOOL lengthen_path(GpPath *path, INT len)
+{
+ /* initial allocation */
+ if(path->datalen == 0){
+ path->datalen = len * 2;
+
+ path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF));
+ if(!path->pathdata.Points) return FALSE;
+
+ path->pathdata.Types = GdipAlloc(path->datalen);
+ if(!path->pathdata.Types){
+ GdipFree(path->pathdata.Points);
+ return FALSE;
+ }
+ }
+ /* reallocation, double size of arrays */
+ else if(path->datalen - path->pathdata.Count < len){
+ while(path->datalen - path->pathdata.Count < len)
+ path->datalen *= 2;
+
+ path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0,
+ path->pathdata.Points, path->datalen * sizeof(PointF));
+ if(!path->pathdata.Points) return FALSE;
+
+ path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0,
+ path->pathdata.Types, path->datalen);
+ if(!path->pathdata.Types) return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* recursive deletion of GpRegion nodes */
+inline void delete_element(region_element* element)
+{
+ switch(element->type)
+ {
+ case RegionDataRect:
+ break;
+ case RegionDataPath:
+ GdipDeletePath(element->elementdata.pathdata.path);
+ break;
+ case RegionDataEmptyRect:
+ case RegionDataInfiniteRect:
+ break;
+ default:
+ delete_element(element->elementdata.combine.left);
+ delete_element(element->elementdata.combine.right);
+ GdipFree(element->elementdata.combine.left);
+ GdipFree(element->elementdata.combine.right);
+ break;
+ }
+}
@ stdcall GdipAddPathLine(ptr long long long long)
@ stdcall GdipAddPathLineI(ptr long long long long)
@ stdcall GdipAddPathPath(ptr ptr long)
-@ stub GdipAddPathPie
-@ stub GdipAddPathPieI
+@ stdcall GdipAddPathPie(ptr long long long long long long)
+@ stdcall GdipAddPathPieI(ptr long long long long long long)
@ stdcall GdipAddPathPolygon(ptr ptr long)
@ stdcall GdipAddPathPolygonI(ptr ptr long)
@ stdcall GdipAddPathRectangle(ptr long long long long)
@ stdcall GdipConvertToEmfPlus(ptr ptr ptr long ptr ptr)
@ stub GdipConvertToEmfPlusToFile
@ stub GdipConvertToEmfPlusToStream
-@ stub GdipCreateAdjustableArrowCap
+@ stdcall GdipCreateAdjustableArrowCap(long long long ptr)
@ stub GdipCreateBitmapFromDirectDrawSurface
@ stdcall GdipCreateBitmapFromFile(wstr ptr)
@ stdcall GdipCreateBitmapFromFileICM(wstr ptr)
@ stdcall GdipCreateSolidFill(long ptr)
@ stdcall GdipCreateStreamOnFile(ptr long ptr)
@ stdcall GdipCreateStringFormat(long long ptr)
-@ stub GdipCreateTexture2
-@ stub GdipCreateTexture2I
-@ stub GdipCreateTexture
+@ stdcall GdipCreateTexture2(ptr long long long long long ptr)
+@ stdcall GdipCreateTexture2I(ptr long long long long long ptr)
+@ stdcall GdipCreateTexture(ptr long ptr)
@ stdcall GdipCreateTextureIA(ptr ptr long long long long ptr)
@ stdcall GdipCreateTextureIAI(ptr ptr long long long long ptr)
@ stdcall GdipDeleteBrush(ptr)
@ stub GdipEnumerateMetafileSrcRectDestPointsI
@ stub GdipEnumerateMetafileSrcRectDestRect
@ stub GdipEnumerateMetafileSrcRectDestRectI
-@ stub GdipFillClosedCurve2
-@ stub GdipFillClosedCurve2I
+@ stdcall GdipFillClosedCurve2(ptr ptr ptr long long long)
+@ stdcall GdipFillClosedCurve2I(ptr ptr ptr long long long)
@ stub GdipFillClosedCurve
@ stub GdipFillClosedCurveI
@ stdcall GdipFillEllipse(ptr ptr long long long long)
@ stdcall GdipFillRegion(ptr ptr ptr)
@ stdcall GdipFindFirstImageItem(ptr ptr)
@ stub GdipFindNextImageItem
-@ stub GdipFlattenPath
+@ stdcall GdipFlattenPath(ptr ptr long)
@ stdcall GdipFlush(ptr long)
@ stdcall GdipFree(ptr)
-@ stub GdipGetAdjustableArrowCapFillState
-@ stub GdipGetAdjustableArrowCapHeight
-@ stub GdipGetAdjustableArrowCapMiddleInset
-@ stub GdipGetAdjustableArrowCapWidth
+@ stdcall GdipGetAdjustableArrowCapFillState(ptr ptr)
+@ stdcall GdipGetAdjustableArrowCapHeight(ptr ptr)
+@ stdcall GdipGetAdjustableArrowCapMiddleInset(ptr ptr)
+@ stdcall GdipGetAdjustableArrowCapWidth(ptr ptr)
@ stub GdipGetAllPropertyItems
@ stdcall GdipGetBrushType(ptr ptr)
@ stdcall GdipGetCellAscent(ptr long ptr)
@ stdcall GdipGetEmHeight(ptr long ptr)
@ stub GdipGetEncoderParameterList
@ stub GdipGetEncoderParameterListSize
-@ stub GdipGetFamily
+@ stdcall GdipGetFamily(ptr ptr)
@ stdcall GdipGetFamilyName(ptr ptr long)
@ stdcall GdipGetFontCollectionFamilyCount(ptr ptr)
@ stdcall GdipGetFontCollectionFamilyList(ptr long ptr ptr)
-@ stub GdipGetFontHeight
+@ stdcall GdipGetFontHeight(ptr ptr ptr)
@ stdcall GdipGetFontHeightGivenDPI(ptr long ptr)
@ stdcall GdipGetFontSize(ptr ptr)
-@ stub GdipGetFontStyle
+@ stdcall GdipGetFontStyle(ptr ptr)
@ stdcall GdipGetFontUnit(ptr ptr)
@ stdcall GdipGetGenericFontFamilyMonospace(ptr)
@ stdcall GdipGetGenericFontFamilySansSerif(ptr)
@ stub GdipGetVisibleClipBounds
@ stub GdipGetVisibleClipBoundsI
@ stdcall GdipGetWorldTransform(ptr ptr)
-@ stub GdipGraphicsClear
+@ stdcall GdipGraphicsClear(ptr long)
@ stub GdipGraphicsSetAbort
@ stub GdipImageForceValidation
@ stdcall GdipImageGetFrameCount(ptr ptr ptr)
@ stub GdipImageSetAbort
@ stub GdipInitializePalette
@ stdcall GdipInvertMatrix(ptr)
-@ stub GdipIsClipEmpty
+@ stdcall GdipIsClipEmpty(ptr ptr)
@ stdcall GdipIsEmptyRegion(ptr ptr ptr)
@ stdcall GdipIsEqualRegion(ptr ptr ptr ptr)
@ stdcall GdipIsInfiniteRegion(ptr ptr ptr)
@ stdcall GdipPathIterGetCount(ptr ptr)
@ stdcall GdipPathIterGetSubpathCount(ptr ptr)
@ stdcall GdipPathIterHasCurve(ptr ptr)
-@ stub GdipPathIterIsValid
+@ stdcall GdipPathIterIsValid(ptr ptr)
@ stdcall GdipPathIterNextMarker(ptr ptr ptr ptr)
-@ stub GdipPathIterNextMarkerPath
-@ stub GdipPathIterNextPathType
+@ stdcall GdipPathIterNextMarkerPath(ptr ptr ptr)
+@ stdcall GdipPathIterNextPathType(ptr ptr ptr ptr ptr)
@ stdcall GdipPathIterNextSubpath(ptr ptr ptr ptr ptr)
-@ stub GdipPathIterNextSubpathPath
+@ stdcall GdipPathIterNextSubpathPath(ptr ptr ptr ptr)
@ stdcall GdipPathIterRewind(ptr)
@ stub GdipPlayMetafileRecord
@ stub GdipPlayTSClientRecord
@ stub GdipRecordMetafileStreamI
@ stdcall GdipReleaseDC(ptr ptr)
@ stdcall GdipRemovePropertyItem(ptr long)
-@ stub GdipResetClip
+@ stdcall GdipResetClip(ptr)
@ stub GdipResetImageAttributes
@ stub GdipResetLineTransform
@ stub GdipResetPageTransform
@ stub GdipResetPathGradientTransform
@ stub GdipResetPenTransform
@ stub GdipResetTextureTransform
-@ stub GdipResetWorldTransform
+@ stdcall GdipResetWorldTransform(ptr)
@ stdcall GdipRestoreGraphics(ptr long)
-@ stub GdipReversePath
+@ stdcall GdipReversePath(ptr)
@ stub GdipRotateLineTransform
@ stdcall GdipRotateMatrix(ptr long long)
@ stub GdipRotatePathGradientTransform
@ stub GdipScalePenTransform
@ stub GdipScaleTextureTransform
@ stdcall GdipScaleWorldTransform(ptr long long long)
-@ stub GdipSetAdjustableArrowCapFillState
-@ stub GdipSetAdjustableArrowCapHeight
-@ stub GdipSetAdjustableArrowCapMiddleInset
-@ stub GdipSetAdjustableArrowCapWidth
+@ stdcall GdipSetAdjustableArrowCapFillState(ptr long)
+@ stdcall GdipSetAdjustableArrowCapHeight(ptr long)
+@ stdcall GdipSetAdjustableArrowCapMiddleInset(ptr long)
+@ stdcall GdipSetAdjustableArrowCapWidth(ptr long)
@ stub GdipSetClipGraphics
@ stub GdipSetClipHrgn
@ stub GdipSetClipPath
@ stdcall GdipTransformRegion(ptr ptr)
@ stub GdipTranslateClip
@ stub GdipTranslateClipI
-@ stub GdipTranslateLineTransform
+@ stdcall GdipTranslateLineTransform(ptr long long long)
@ stdcall GdipTranslateMatrix(ptr long long long)
@ stub GdipTranslatePathGradientTransform
@ stub GdipTranslatePenTransform
extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
REAL tension, REAL *x, REAL *y);
+extern BOOL lengthen_path(GpPath *path, INT len);
+
+typedef struct region_element region_element;
+extern inline void delete_element(region_element *element);
+
static inline INT roundr(REAL x)
{
return (INT) floor(x + 0.5);
GpUnit unit; /* page unit */
REAL scale; /* page scale */
GpMatrix * worldtrans; /* world transform */
+ BOOL busy; /* hdc handle obtained by GdipGetDC */
+ GpRegion *clip;
};
struct GpBrush{
REAL scale;
};
+struct GpAdustableArrowCap{
+ GpCustomLineCap cap;
+};
+
struct GpImage{
IPicture* picture;
ImageType type;
WCHAR FamilyName[LF_FACESIZE];
};
-typedef struct region_element
+/* internal use */
+typedef enum RegionType
+{
+ RegionDataRect = 0x10000000,
+ RegionDataPath = 0x10000001,
+ RegionDataEmptyRect = 0x10000002,
+ RegionDataInfiniteRect = 0x10000003,
+} RegionType;
+
+struct region_element
{
DWORD type; /* Rectangle, Path, SpecialRectangle, or CombineMode */
union
struct region_element *right; /* what *left was combined with */
} combine;
} elementdata;
-} region_element;
+};
struct GpRegion{
struct
GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
{
+ TRACE("(%p, %p)\n", hdc, graphics);
+
return GdipCreateFromHDC2(hdc, NULL, graphics);
}
{
GpStatus retval;
+ TRACE("(%p, %p, %p)\n", hdc, hDevice, graphics);
+
if(hDevice != NULL) {
FIXME("Don't know how to hadle parameter hDevice\n");
return NotImplemented;
return retval;
}
+ if((retval = GdipCreateRegion(&(*graphics)->clip)) != Ok){
+ GdipFree((*graphics)->worldtrans);
+ GdipFree(*graphics);
+ return retval;
+ }
+
(*graphics)->hdc = hdc;
- (*graphics)->hwnd = NULL;
+ (*graphics)->hwnd = WindowFromDC(hdc);
(*graphics)->smoothing = SmoothingModeDefault;
(*graphics)->compqual = CompositingQualityDefault;
(*graphics)->interpolation = InterpolationModeDefault;
(*graphics)->compmode = CompositingModeSourceOver;
(*graphics)->unit = UnitDisplay;
(*graphics)->scale = 1.0;
+ (*graphics)->busy = FALSE;
return Ok;
}
{
GpStatus ret;
+ TRACE("(%p, %p)\n", hwnd, graphics);
+
if((ret = GdipCreateFromHDC(GetDC(hwnd), graphics)) != Ok)
return ret;
/* FIXME: no icm handling */
GpStatus WINGDIPAPI GdipCreateFromHWNDICM(HWND hwnd, GpGraphics **graphics)
{
+ TRACE("(%p, %p)\n", hwnd, graphics);
+
return GdipCreateFromHWND(hwnd, graphics);
}
HENHMETAFILE hemf;
GpStatus retval = GenericError;
+ TRACE("(%p, %d, %p, %p)\n", hwmf, delete, placeable, metafile);
+
if(!hwmf || !metafile || !placeable)
return InvalidParameter;
DWORD dwMode;
HRESULT ret;
+ TRACE("(%s, %u, %p)\n", debugstr_w(filename), access, stream);
+
if(!stream || !filename)
return InvalidParameter;
GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
{
+ TRACE("(%p)\n", graphics);
+
if(!graphics) return InvalidParameter;
+ if(graphics->busy) return ObjectBusy;
+
if(graphics->hwnd)
ReleaseDC(graphics->hwnd, graphics->hdc);
+ GdipDeleteRegion(graphics->clip);
GdipDeleteMatrix(graphics->worldtrans);
- HeapFree(GetProcessHeap(), 0, graphics);
+ GdipFree(graphics);
return Ok;
}
GpPointF points[MAX_ARC_PTS];
GpStatus retval;
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y,
+ width, height, startAngle, sweepAngle);
+
if(!graphics || !pen || width <= 0 || height <= 0)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
num_pts = arc2polybezier(points, x, y, width, height, startAngle, sweepAngle);
save_state = prepare_dc(graphics, pen);
GpStatus WINGDIPAPI GdipDrawArcI(GpGraphics *graphics, GpPen *pen, INT x,
INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
{
+ TRACE("(%p, %p, %d, %d, %d, %d, %.2f, %.2f)\n", graphics, pen, x, y,
+ width, height, startAngle, sweepAngle);
+
return GdipDrawArc(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height,startAngle,sweepAngle);
}
GpPointF pt[4];
GpStatus retval;
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x1, y1,
+ x2, y2, x3, y3, x4, y4);
+
if(!graphics || !pen)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
pt[0].X = x1;
pt[0].Y = y1;
pt[1].X = x2;
GpPointF pt[4];
GpStatus retval;
+ TRACE("(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d)\n", graphics, pen, x1, y1,
+ x2, y2, x3, y3, x4, y4);
+
if(!graphics || !pen)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
pt[0].X = x1;
pt[0].Y = y1;
pt[1].X = x2;
INT i;
GpStatus ret;
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
if(!graphics || !pen || !points || (count <= 0))
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
for(i = 0; i < floor(count / 4); i++){
ret = GdipDrawBezier(graphics, pen,
points[4*i].X, points[4*i].Y,
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
if(!graphics || !pen || !points || (count <= 0))
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
pts = GdipAlloc(sizeof(GpPointF) * count);
if(!pts)
return OutOfMemory;
GpStatus WINGDIPAPI GdipDrawClosedCurve(GpGraphics *graphics, GpPen *pen,
GDIPCONST GpPointF *points, INT count)
{
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
return GdipDrawClosedCurve2(graphics, pen, points, count, 1.0);
}
GpStatus WINGDIPAPI GdipDrawClosedCurveI(GpGraphics *graphics, GpPen *pen,
GDIPCONST GpPoint *points, INT count)
{
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
return GdipDrawClosedCurve2I(graphics, pen, points, count, 1.0);
}
GpStatus WINGDIPAPI GdipDrawClosedCurve2(GpGraphics *graphics, GpPen *pen,
GDIPCONST GpPointF *points, INT count, REAL tension)
{
- GpPointF *ptf;
+ GpPath *path;
GpStatus stat;
+ TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension);
+
if(!graphics || !pen || !points || count <= 0)
return InvalidParameter;
- /* make a full points copy.. */
- ptf = GdipAlloc(sizeof(GpPointF)*(count+1));
- if(!ptf)
- return OutOfMemory;
- memcpy(ptf, points, sizeof(GpPointF)*count);
+ if(graphics->busy)
+ return ObjectBusy;
- /* ..and add a first point as a last one */
- ptf[count] = ptf[0];
+ if((stat = GdipCreatePath(FillModeAlternate, &path)) != Ok)
+ return stat;
- stat = GdipDrawCurve2(graphics, pen, ptf, count + 1, tension);
+ stat = GdipAddPathClosedCurve2(path, points, count, tension);
+ if(stat != Ok){
+ GdipDeletePath(path);
+ return stat;
+ }
- GdipFree(ptf);
+ stat = GdipDrawPath(graphics, pen, path);
+
+ GdipDeletePath(path);
return stat;
}
GpStatus stat;
INT i;
+ TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension);
+
if(!points || count <= 0)
return InvalidParameter;
GpStatus WINGDIPAPI GdipDrawCurve(GpGraphics *graphics, GpPen *pen,
GDIPCONST GpPointF *points, INT count)
{
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
return GdipDrawCurve2(graphics,pen,points,count,1.0);
}
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
if(!points || count <= 0)
return InvalidParameter;
REAL x1, x2, y1, y2;
GpStatus retval;
+ TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension);
+
if(!graphics || !pen)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
pt = GdipAlloc(len_pt * sizeof(GpPointF));
tension = tension * TENSION_CONST;
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %p, %d, %.2f)\n", graphics, pen, points, count, tension);
+
if(!points || count <= 0)
return InvalidParameter;
GpPointF ptf[2];
POINT pti[2];
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y, width, height);
+
if(!graphics || !pen)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf[0].X = x;
ptf[0].Y = y;
ptf[1].X = x + width;
GpStatus WINGDIPAPI GdipDrawEllipseI(GpGraphics *graphics, GpPen *pen, INT x,
INT y, INT width, INT height)
{
+ TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, pen, x, y, width, height);
+
return GdipDrawEllipse(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
}
GpStatus WINGDIPAPI GdipDrawImage(GpGraphics *graphics, GpImage *image, REAL x, REAL y)
{
+ TRACE("(%p, %p, %.2f, %.2f)\n", graphics, image, x, y);
+
/* IPicture::Render uses LONG coords */
return GdipDrawImageI(graphics,image,roundr(x),roundr(y));
}
{
UINT width, height, srcw, srch;
+ TRACE("(%p, %p, %d, %d)\n", graphics, image, x, y);
+
if(!graphics || !image)
return InvalidParameter;
POINT pti[3];
REAL dx, dy;
- TRACE("%p %p %p %d %f %f %f %f %d %p %p %p\n", graphics, image, points, count,
- srcx, srcy, srcwidth, srcheight, srcUnit, imageAttributes, callback,
+ TRACE("(%p, %p, %p, %d, %f, %f, %f, %f, %d, %p, %p, %p)\n", graphics, image, points,
+ count, srcx, srcy, srcwidth, srcheight, srcUnit, imageAttributes, callback,
callbackData);
if(!graphics || !image || !points || count != 3)
GpPointF pointsF[3];
INT i;
+ TRACE("(%p, %p, %p, %d, %d, %d, %d, %d, %d, %p, %p, %p)\n", graphics, image, points, count,
+ srcx, srcy, srcwidth, srcheight, srcUnit, imageAttributes, callback,
+ callbackData);
+
if(!points || count!=3)
return InvalidParameter;
{
GpPointF points[3];
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p, %p, %p)\n",
+ graphics, image, dstx, dsty, dstwidth, dstheight, srcx, srcy,
+ srcwidth, srcheight, srcUnit, imageattr, callback, callbackData);
+
points[0].X = dstx;
points[0].Y = dsty;
points[1].X = dstx + dstwidth;
GDIPCONST GpImageAttributes* imageAttributes, DrawImageAbort callback,
VOID * callbackData)
{
- GpPointF points[3];
+ GpPointF points[3];
+
+ TRACE("(%p, %p, %d, %d, %d, %d, %d, %d, %d, %d, %d, %p, %p, %p)\n",
+ graphics, image, dstx, dsty, dstwidth, dstheight, srcx, srcy,
+ srcwidth, srcheight, srcUnit, imageAttributes, callback, callbackData);
points[0].X = dstx;
points[0].Y = dsty;
GpUnit unit;
GpStatus ret;
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, image, x, y, width, height);
+
if(!graphics || !image)
return InvalidParameter;
GpStatus WINGDIPAPI GdipDrawImageRectI(GpGraphics *graphics, GpImage *image,
INT x, INT y, INT width, INT height)
{
+ TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, image, x, y, width, height);
+
return GdipDrawImageRect(graphics, image, (REAL)x, (REAL)y, (REAL)width, (REAL)height);
}
GpPointF pt[2];
GpStatus retval;
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x1, y1, x2, y2);
+
if(!pen || !graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
pt[0].X = x1;
pt[0].Y = y1;
pt[1].X = x2;
GpPointF pt[2];
GpStatus retval;
+ TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, pen, x1, y1, x2, y2);
+
if(!pen || !graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
pt[0].X = (REAL)x1;
pt[0].Y = (REAL)y1;
pt[1].X = (REAL)x2;
INT save_state;
GpStatus retval;
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
if(!pen || !graphics || (count < 2))
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
save_state = prepare_dc(graphics, pen);
retval = draw_polyline(graphics, pen, points, count, TRUE);
GpPointF *ptf = NULL;
int i;
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
if(!pen || !graphics || (count < 2))
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf = GdipAlloc(count * sizeof(GpPointF));
if(!ptf) return OutOfMemory;
INT save_state;
GpStatus retval;
+ TRACE("(%p, %p, %p)\n", graphics, pen, path);
+
if(!pen || !graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
save_state = prepare_dc(graphics, pen);
retval = draw_poly(graphics, pen, path->pathdata.Points,
{
INT save_state;
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y,
+ width, height, startAngle, sweepAngle);
+
if(!graphics || !pen)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
save_state = prepare_dc(graphics, pen);
SelectObject(graphics->hdc, GetStockObject(NULL_BRUSH));
GpStatus WINGDIPAPI GdipDrawPieI(GpGraphics *graphics, GpPen *pen, INT x,
INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
{
+ TRACE("(%p, %p, %d, %d, %d, %d, %.2f, %.2f)\n", graphics, pen, x, y,
+ width, height, startAngle, sweepAngle);
+
return GdipDrawPie(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height,startAngle,sweepAngle);
}
GpPointF ptf[4];
POINT pti[4];
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x, y, width, height);
+
if(!pen || !graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf[0].X = x;
ptf[0].Y = y;
ptf[1].X = x + width;
GpStatus WINGDIPAPI GdipDrawRectangleI(GpGraphics *graphics, GpPen *pen, INT x,
INT y, INT width, INT height)
{
+ TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, pen, x, y, width, height);
+
return GdipDrawRectangle(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
}
POINT *pti;
INT save_state, i;
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, rects, count);
+
if(!graphics || !pen || !rects || count < 1)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf = GdipAlloc(4 * count * sizeof(GpPointF));
pti = GdipAlloc(4 * count * sizeof(POINT));
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, rects, count);
+
if(!rects || count<=0)
return InvalidParameter;
return Ok;
}
+GpStatus WINGDIPAPI GdipFillClosedCurve2(GpGraphics *graphics, GpBrush *brush,
+ GDIPCONST GpPointF *points, INT count, REAL tension, GpFillMode fill)
+{
+ GpPath *path;
+ GpStatus stat;
+
+ TRACE("(%p, %p, %p, %d, %.2f, %d)\n", graphics, brush, points,
+ count, tension, fill);
+
+ if(!graphics || !brush || !points)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
+ stat = GdipCreatePath(fill, &path);
+ if(stat != Ok)
+ return stat;
+
+ stat = GdipAddPathClosedCurve2(path, points, count, tension);
+ if(stat != Ok){
+ GdipDeletePath(path);
+ return stat;
+ }
+
+ stat = GdipFillPath(graphics, brush, path);
+ if(stat != Ok){
+ GdipDeletePath(path);
+ return stat;
+ }
+
+ GdipDeletePath(path);
+
+ return Ok;
+}
+
+GpStatus WINGDIPAPI GdipFillClosedCurve2I(GpGraphics *graphics, GpBrush *brush,
+ GDIPCONST GpPoint *points, INT count, REAL tension, GpFillMode fill)
+{
+ GpPointF *ptf;
+ GpStatus stat;
+ INT i;
+
+ TRACE("(%p, %p, %p, %d, %.2f, %d)\n", graphics, brush, points,
+ count, tension, fill);
+
+ if(!points || count <= 0)
+ return InvalidParameter;
+
+ ptf = GdipAlloc(sizeof(GpPointF)*count);
+ if(!ptf)
+ return OutOfMemory;
+
+ for(i = 0;i < count;i++){
+ ptf[i].X = (REAL)points[i].X;
+ ptf[i].Y = (REAL)points[i].Y;
+ }
+
+ stat = GdipFillClosedCurve2(graphics, brush, ptf, count, tension, fill);
+
+ GdipFree(ptf);
+
+ return stat;
+}
+
GpStatus WINGDIPAPI GdipFillEllipse(GpGraphics *graphics, GpBrush *brush, REAL x,
REAL y, REAL width, REAL height)
{
GpPointF ptf[2];
POINT pti[2];
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, brush, x, y, width, height);
+
if(!graphics || !brush)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf[0].X = x;
ptf[0].Y = y;
ptf[1].X = x + width;
GpStatus WINGDIPAPI GdipFillEllipseI(GpGraphics *graphics, GpBrush *brush, INT x,
INT y, INT width, INT height)
{
+ TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, brush, x, y, width, height);
+
return GdipFillEllipse(graphics,brush,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
}
INT save_state;
GpStatus retval;
+ TRACE("(%p, %p, %p)\n", graphics, brush, path);
+
if(!brush || !graphics || !path)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
save_state = SaveDC(graphics->hdc);
EndPath(graphics->hdc);
SelectObject(graphics->hdc, brush->gdibrush);
{
INT save_state;
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
+ graphics, brush, x, y, width, height, startAngle, sweepAngle);
+
if(!graphics || !brush)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
save_state = SaveDC(graphics->hdc);
EndPath(graphics->hdc);
SelectObject(graphics->hdc, brush->gdibrush);
GpStatus WINGDIPAPI GdipFillPieI(GpGraphics *graphics, GpBrush *brush, INT x,
INT y, INT width, INT height, REAL startAngle, REAL sweepAngle)
{
+ TRACE("(%p, %p, %d, %d, %d, %d, %.2f, %.2f)\n",
+ graphics, brush, x, y, width, height, startAngle, sweepAngle);
+
return GdipFillPie(graphics,brush,(REAL)x,(REAL)y,(REAL)width,(REAL)height,startAngle,sweepAngle);
}
POINT *pti = NULL;
GpStatus retval = Ok;
+ TRACE("(%p, %p, %p, %d, %d)\n", graphics, brush, points, count, fillMode);
+
if(!graphics || !brush || !points || !count)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf = GdipAlloc(count * sizeof(GpPointF));
pti = GdipAlloc(count * sizeof(POINT));
if(!ptf || !pti){
POINT *pti = NULL;
GpStatus retval = Ok;
+ TRACE("(%p, %p, %p, %d, %d)\n", graphics, brush, points, count, fillMode);
+
if(!graphics || !brush || !points || !count)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf = GdipAlloc(count * sizeof(GpPointF));
pti = GdipAlloc(count * sizeof(POINT));
if(!ptf || !pti){
GpStatus WINGDIPAPI GdipFillPolygon2(GpGraphics *graphics, GpBrush *brush,
GDIPCONST GpPointF *points, INT count)
{
+ TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
+
return GdipFillPolygon(graphics, brush, points, count, FillModeAlternate);
}
GpStatus WINGDIPAPI GdipFillPolygon2I(GpGraphics *graphics, GpBrush *brush,
GDIPCONST GpPoint *points, INT count)
{
+ TRACE("(%p, %p, %p, %d)\n", graphics, brush, points, count);
+
return GdipFillPolygonI(graphics, brush, points, count, FillModeAlternate);
}
GpPointF ptf[4];
POINT pti[4];
+ TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, brush, x, y, width, height);
+
if(!graphics || !brush)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf[0].X = x;
ptf[0].Y = y;
ptf[1].X = x + width;
GpPointF ptf[4];
POINT pti[4];
+ TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, brush, x, y, width, height);
+
if(!graphics || !brush)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
ptf[0].X = x;
ptf[0].Y = y;
ptf[1].X = x + width;
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %p, %d)\n", graphics, brush, rects, count);
+
if(!rects)
return InvalidParameter;
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %p, %d)\n", graphics, brush, rects, count);
+
if(!rects || count <= 0)
return InvalidParameter;
if (!(graphics && brush && region))
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
FIXME("(%p, %p, %p): stub\n", graphics, brush, region);
return NotImplemented;
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
if(!(calls++))
FIXME("not implemented\n");
GpStatus WINGDIPAPI GdipGetCompositingMode(GpGraphics *graphics,
CompositingMode *mode)
{
+ TRACE("(%p, %p)\n", graphics, mode);
+
if(!graphics || !mode)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*mode = graphics->compmode;
return Ok;
GpStatus WINGDIPAPI GdipGetCompositingQuality(GpGraphics *graphics,
CompositingQuality *quality)
{
+ TRACE("(%p, %p)\n", graphics, quality);
+
if(!graphics || !quality)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*quality = graphics->compqual;
return Ok;
GpStatus WINGDIPAPI GdipGetInterpolationMode(GpGraphics *graphics,
InterpolationMode *mode)
{
+ TRACE("(%p, %p)\n", graphics, mode);
+
if(!graphics || !mode)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*mode = graphics->interpolation;
return Ok;
GpStatus WINGDIPAPI GdipGetPageScale(GpGraphics *graphics, REAL *scale)
{
+ TRACE("(%p, %p)\n", graphics, scale);
+
if(!graphics || !scale)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*scale = graphics->scale;
return Ok;
GpStatus WINGDIPAPI GdipGetPageUnit(GpGraphics *graphics, GpUnit *unit)
{
+ TRACE("(%p, %p)\n", graphics, unit);
+
if(!graphics || !unit)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*unit = graphics->unit;
return Ok;
GpStatus WINGDIPAPI GdipGetPixelOffsetMode(GpGraphics *graphics, PixelOffsetMode
*mode)
{
+ TRACE("(%p, %p)\n", graphics, mode);
+
if(!graphics || !mode)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*mode = graphics->pixeloffset;
return Ok;
/* FIXME: Smoothing mode is not used anywhere except the getter/setter. */
GpStatus WINGDIPAPI GdipGetSmoothingMode(GpGraphics *graphics, SmoothingMode *mode)
{
+ TRACE("(%p, %p)\n", graphics, mode);
+
if(!graphics || !mode)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*mode = graphics->smoothing;
return Ok;
GpStatus WINGDIPAPI GdipGetTextRenderingHint(GpGraphics *graphics,
TextRenderingHint *hint)
{
+ TRACE("(%p, %p)\n", graphics, hint);
+
if(!graphics || !hint)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*hint = graphics->texthint;
return Ok;
GpStatus WINGDIPAPI GdipGetWorldTransform(GpGraphics *graphics, GpMatrix *matrix)
{
+ TRACE("(%p, %p)\n", graphics, matrix);
+
if(!graphics || !matrix)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*matrix = *graphics->worldtrans;
return Ok;
}
+GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics *graphics, ARGB color)
+{
+ GpSolidFill *brush;
+ GpStatus stat;
+ RECT rect;
+
+ TRACE("(%p, %x)\n", graphics, color);
+
+ if(!graphics)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
+ if((stat = GdipCreateSolidFill(color, &brush)) != Ok)
+ return stat;
+
+ if(graphics->hwnd){
+ if(!GetWindowRect(graphics->hwnd, &rect)){
+ GdipDeleteBrush((GpBrush*)brush);
+ return GenericError;
+ }
+
+ GdipFillRectangle(graphics, (GpBrush*)brush, 0.0, 0.0, (REAL)(rect.right - rect.left),
+ (REAL)(rect.bottom - rect.top));
+ }
+ else
+ GdipFillRectangle(graphics, (GpBrush*)brush, 0.0, 0.0, (REAL)GetDeviceCaps(graphics->hdc, HORZRES),
+ (REAL)GetDeviceCaps(graphics->hdc, VERTRES));
+
+ GdipDeleteBrush((GpBrush*)brush);
+
+ return Ok;
+}
+
+GpStatus WINGDIPAPI GdipIsClipEmpty(GpGraphics *graphics, BOOL *res)
+{
+ TRACE("(%p, %p)\n", graphics, res);
+
+ if(!graphics || !res)
+ return InvalidParameter;
+
+ return GdipIsEmptyRegion(graphics->clip, graphics, res);
+}
+
GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics* graphics,
GDIPCONST WCHAR* string, INT length, GDIPCONST GpFont* font,
GDIPCONST RectF* layoutRect, GDIPCONST GpStringFormat *stringFormat,
return Ok;
}
+GpStatus WINGDIPAPI GdipResetClip(GpGraphics *graphics)
+{
+ TRACE("(%p)\n", graphics);
+
+ if(!graphics)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
+ return GdipSetInfinite(graphics->clip);
+}
+
+GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics *graphics)
+{
+ TRACE("(%p)\n", graphics);
+
+ if(!graphics)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
+ graphics->worldtrans->matrix[0] = 1.0;
+ graphics->worldtrans->matrix[1] = 0.0;
+ graphics->worldtrans->matrix[2] = 0.0;
+ graphics->worldtrans->matrix[3] = 1.0;
+ graphics->worldtrans->matrix[4] = 0.0;
+ graphics->worldtrans->matrix[5] = 0.0;
+
+ return Ok;
+}
+
GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics *graphics, GraphicsState state)
{
static int calls;
GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics *graphics, REAL angle,
GpMatrixOrder order)
{
+ TRACE("(%p, %.2f, %d)\n", graphics, angle, order);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
return GdipRotateMatrix(graphics->worldtrans, angle, order);
}
GpStatus WINGDIPAPI GdipScaleWorldTransform(GpGraphics *graphics, REAL sx,
REAL sy, GpMatrixOrder order)
{
+ TRACE("(%p, %.2f, %.2f, %d)\n", graphics, sx, sy, order);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
return GdipScaleMatrix(graphics->worldtrans, sx, sy, order);
}
GpStatus WINGDIPAPI GdipSetCompositingMode(GpGraphics *graphics,
CompositingMode mode)
{
+ TRACE("(%p, %d)\n", graphics, mode);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
graphics->compmode = mode;
return Ok;
GpStatus WINGDIPAPI GdipSetCompositingQuality(GpGraphics *graphics,
CompositingQuality quality)
{
+ TRACE("(%p, %d)\n", graphics, quality);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
graphics->compqual = quality;
return Ok;
GpStatus WINGDIPAPI GdipSetInterpolationMode(GpGraphics *graphics,
InterpolationMode mode)
{
+ TRACE("(%p, %d)\n", graphics, mode);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
graphics->interpolation = mode;
return Ok;
GpStatus WINGDIPAPI GdipSetPageScale(GpGraphics *graphics, REAL scale)
{
+ TRACE("(%p, %.2f)\n", graphics, scale);
+
if(!graphics || (scale <= 0.0))
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
graphics->scale = scale;
return Ok;
GpStatus WINGDIPAPI GdipSetPageUnit(GpGraphics *graphics, GpUnit unit)
{
- if(!graphics || (unit == UnitWorld))
+ TRACE("(%p, %d)\n", graphics, unit);
+
+ if(!graphics)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
+ if(unit == UnitWorld)
return InvalidParameter;
graphics->unit = unit;
GpStatus WINGDIPAPI GdipSetPixelOffsetMode(GpGraphics *graphics, PixelOffsetMode
mode)
{
+ TRACE("(%p, %d)\n", graphics, mode);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
graphics->pixeloffset = mode;
return Ok;
GpStatus WINGDIPAPI GdipSetSmoothingMode(GpGraphics *graphics, SmoothingMode mode)
{
+ TRACE("(%p, %d)\n", graphics, mode);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
graphics->smoothing = mode;
return Ok;
GpStatus WINGDIPAPI GdipSetTextRenderingHint(GpGraphics *graphics,
TextRenderingHint hint)
{
+ TRACE("(%p, %d)\n", graphics, hint);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
graphics->texthint = hint;
return Ok;
GpStatus WINGDIPAPI GdipSetWorldTransform(GpGraphics *graphics, GpMatrix *matrix)
{
+ TRACE("(%p, %p)\n", graphics, matrix);
+
if(!graphics || !matrix)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
GdipDeleteMatrix(graphics->worldtrans);
return GdipCloneMatrix(matrix, &graphics->worldtrans);
}
GpStatus WINGDIPAPI GdipTranslateWorldTransform(GpGraphics *graphics, REAL dx,
REAL dy, GpMatrixOrder order)
{
+ TRACE("(%p, %.2f, %.2f, %d)\n", graphics, dx, dy, order);
+
if(!graphics)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
return GdipTranslateMatrix(graphics->worldtrans, dx, dy, order);
}
{
static int calls;
+ if(!graphics)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
if(!(calls++))
FIXME("not implemented\n");
}
GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region,
- CombineMode combineMode)
+ CombineMode mode)
{
- static int calls;
+ TRACE("(%p, %p, %d)\n", graphics, region, mode);
- if(!(calls++))
- FIXME("not implemented\n");
+ if(!graphics || !region)
+ return InvalidParameter;
- return NotImplemented;
+ if(graphics->busy)
+ return ObjectBusy;
+
+ return GdipCombineRegionRegion(graphics->clip, region, mode);
}
-GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpGraphics *graphics,
+GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpMetafile *metafile,
UINT limitDpi)
{
static int calls;
INT save_state;
POINT *pti;
+ TRACE("(%p, %p, %d)\n", graphics, points, count);
+
if(!graphics || !pen || count<=0)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
pti = GdipAlloc(sizeof(POINT) * count);
save_state = prepare_dc(graphics, pen);
GpPointF *ptf;
INT i;
+ TRACE("(%p, %p, %p, %d)\n", graphics, pen, points, count);
+
if(count<=0) return InvalidParameter;
ptf = GdipAlloc(sizeof(GpPointF) * count);
GpStatus WINGDIPAPI GdipGetDpiX(GpGraphics *graphics, REAL* dpi)
{
+ TRACE("(%p, %p)\n", graphics, dpi);
+
if(!graphics || !dpi)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*dpi = (REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSX);
return Ok;
GpStatus WINGDIPAPI GdipGetDpiY(GpGraphics *graphics, REAL* dpi)
{
+ TRACE("(%p, %p)\n", graphics, dpi);
+
if(!graphics || !dpi)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
*dpi = (REAL)GetDeviceCaps(graphics->hdc, LOGPIXELSY);
return Ok;
GpMatrix m;
GpStatus ret;
+ TRACE("(%p, %p, %d)\n", graphics, matrix, order);
+
if(!graphics || !matrix)
return InvalidParameter;
+ if(graphics->busy)
+ return ObjectBusy;
+
m = *(graphics->worldtrans);
ret = GdipMultiplyMatrix(&m, (GpMatrix*)matrix, order);
GpStatus WINGDIPAPI GdipGetDC(GpGraphics *graphics, HDC *hdc)
{
- FIXME("(%p, %p): stub\n", graphics, hdc);
+ TRACE("(%p, %p)\n", graphics, hdc);
- *hdc = NULL;
- return NotImplemented;
+ if(!graphics || !hdc)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
+ *hdc = graphics->hdc;
+ graphics->busy = TRUE;
+
+ return Ok;
}
GpStatus WINGDIPAPI GdipReleaseDC(GpGraphics *graphics, HDC hdc)
{
- FIXME("(%p, %p): stub\n", graphics, hdc);
+ TRACE("(%p, %p)\n", graphics, hdc);
- return NotImplemented;
+ if(!graphics)
+ return InvalidParameter;
+
+ if(graphics->hdc != hdc || !(graphics->busy))
+ return InvalidParameter;
+
+ graphics->busy = FALSE;
+
+ return Ok;
}
GpStatus WINGDIPAPI GdipGetClip(GpGraphics *graphics, GpRegion *region)
{
- FIXME("(%p, %p): stub\n", graphics, region);
+ GpRegion *clip;
+ GpStatus status;
+
+ TRACE("(%p, %p)\n", graphics, region);
+
+ if(!graphics || !region)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
+ if((status = GdipCloneRegion(graphics->clip, &clip)) != Ok)
+ return status;
+
+ /* free everything except root node and header */
+ delete_element(®ion->node);
+ memcpy(region, clip, sizeof(GpRegion));
- return NotImplemented;
+ return Ok;
}
GpStatus WINGDIPAPI GdipTransformPoints(GpGraphics *graphics, GpCoordinateSpace dst_space,
GpCoordinateSpace src_space, GpPointF *points, INT count)
{
+ if(!graphics || !points || count <= 0)
+ return InvalidParameter;
+
+ if(graphics->busy)
+ return ObjectBusy;
+
FIXME("(%p, %d, %d, %p, %d): stub\n", graphics, dst_space, src_space, points, count);
return NotImplemented;
WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
-/* make sure path has enough space for len more points */
-static BOOL lengthen_path(GpPath *path, INT len)
+typedef struct path_list_node_t path_list_node_t;
+struct path_list_node_t {
+ GpPointF pt;
+ BYTE type; /* PathPointTypeStart or PathPointTypeLine */
+ path_list_node_t *next;
+};
+
+/* init list */
+static BOOL init_path_list(path_list_node_t **node, REAL x, REAL y)
{
- /* initial allocation */
- if(path->datalen == 0){
- path->datalen = len * 2;
+ *node = GdipAlloc(sizeof(path_list_node_t));
+ if(!*node)
+ return FALSE;
- path->pathdata.Points = GdipAlloc(path->datalen * sizeof(PointF));
- if(!path->pathdata.Points) return FALSE;
+ (*node)->pt.X = x;
+ (*node)->pt.Y = y;
+ (*node)->type = PathPointTypeStart;
+ (*node)->next = NULL;
- path->pathdata.Types = GdipAlloc(path->datalen);
- if(!path->pathdata.Types){
- GdipFree(path->pathdata.Points);
- return FALSE;
- }
+ return TRUE;
+}
+
+/* free all nodes including argument */
+static void free_path_list(path_list_node_t *node)
+{
+ path_list_node_t *n = node;
+
+ while(n){
+ n = n->next;
+ GdipFree(node);
+ node = n;
}
- /* reallocation, double size of arrays */
- else if(path->datalen - path->pathdata.Count < len){
- while(path->datalen - path->pathdata.Count < len)
- path->datalen *= 2;
-
- path->pathdata.Points = HeapReAlloc(GetProcessHeap(), 0,
- path->pathdata.Points, path->datalen * sizeof(PointF));
- if(!path->pathdata.Points) return FALSE;
-
- path->pathdata.Types = HeapReAlloc(GetProcessHeap(), 0,
- path->pathdata.Types, path->datalen);
- if(!path->pathdata.Types) return FALSE;
+}
+
+/* Add a node after 'node' */
+/*
+ * Returns
+ * pointer on success
+ * NULL on allocation problems
+ */
+static path_list_node_t* add_path_list_node(path_list_node_t *node, REAL x, REAL y, BOOL type)
+{
+ path_list_node_t *new;
+
+ new = GdipAlloc(sizeof(path_list_node_t));
+ if(!new)
+ return NULL;
+
+ new->pt.X = x;
+ new->pt.Y = y;
+ new->type = type;
+ new->next = node->next;
+ node->next = new;
+
+ return new;
+}
+
+/* returns element count */
+static INT path_list_count(path_list_node_t *node)
+{
+ INT count = 1;
+
+ while((node = node->next))
+ ++count;
+
+ return count;
+}
+
+/* GdipFlattenPath helper */
+/*
+ * Used to recursively flatten single Bezier curve
+ * Parameters:
+ * - start : pointer to start point node;
+ * - (x2, y2): first control point;
+ * - (x3, y3): second control point;
+ * - end : pointer to end point node
+ * - flatness: admissible error of linear approximation.
+ *
+ * Return value:
+ * TRUE : success
+ * FALSE: out of memory
+ *
+ * TODO: used quality criteria should be revised to match native as
+ * closer as possible.
+ */
+static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, REAL y3,
+ path_list_node_t *end, REAL flatness)
+{
+ /* this 5 middle points with start/end define to half-curves */
+ GpPointF mp[5];
+ GpPointF pt, pt_st;
+ path_list_node_t *node;
+
+ /* calculate bezier curve middle points == new control points */
+ mp[0].X = (start->pt.X + x2) / 2.0;
+ mp[0].Y = (start->pt.Y + y2) / 2.0;
+ /* middle point between control points */
+ pt.X = (x2 + x3) / 2.0;
+ pt.Y = (y2 + y3) / 2.0;
+ mp[1].X = (mp[0].X + pt.X) / 2.0;
+ mp[1].Y = (mp[0].Y + pt.Y) / 2.0;
+ mp[4].X = (end->pt.X + x3) / 2.0;
+ mp[4].Y = (end->pt.Y + y3) / 2.0;
+ mp[3].X = (mp[4].X + pt.X) / 2.0;
+ mp[3].Y = (mp[4].Y + pt.Y) / 2.0;
+
+ mp[2].X = (mp[1].X + mp[3].X) / 2.0;
+ mp[2].Y = (mp[1].Y + mp[3].Y) / 2.0;
+
+ pt = end->pt;
+ pt_st = start->pt;
+ /* check flatness as a half of distance between middle point and a linearized path */
+ if(fabs(((pt.Y - pt_st.Y)*mp[2].X + (pt_st.X - pt.X)*mp[2].Y +
+ (pt_st.Y*pt.X - pt_st.X*pt.Y))) <=
+ (0.5 * flatness*sqrt((powf(pt.Y - pt_st.Y, 2.0) + powf(pt_st.X - pt.X, 2.0))))){
+ return TRUE;
}
+ else
+ /* add a middle point */
+ if(!(node = add_path_list_node(start, mp[2].X, mp[2].Y, PathPointTypeLine)))
+ return FALSE;
+
+ /* do the same with halfs */
+ flatten_bezier(start, mp[0].X, mp[0].Y, mp[1].X, mp[1].Y, node, flatness);
+ flatten_bezier(node, mp[3].X, mp[3].Y, mp[4].X, mp[4].Y, end, flatness);
return TRUE;
}
{
INT count, old_count, i;
+ TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
+ path, x1, y1, x2, y2, startAngle, sweepAngle);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipAddPathArcI(GpPath *path, INT x1, INT y1, INT x2,
INT y2, REAL startAngle, REAL sweepAngle)
{
+ TRACE("(%p, %d, %d, %d, %d, %.2f, %.2f)\n",
+ path, x1, y1, x2, y2, startAngle, sweepAngle);
+
return GdipAddPathArc(path,(REAL)x1,(REAL)y1,(REAL)x2,(REAL)y2,startAngle,sweepAngle);
}
{
INT old_count;
+ TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
+ path, x1, y1, x2, y2, x3, y3, x4, y4);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipAddPathBezierI(GpPath *path, INT x1, INT y1, INT x2,
INT y2, INT x3, INT y3, INT x4, INT y4)
{
+ TRACE("(%p, %d, %d, %d, %d, %d, %d, %d, %d)\n",
+ path, x1, y1, x2, y2, x3, y3, x4, y4);
+
return GdipAddPathBezier(path,(REAL)x1,(REAL)y1,(REAL)x2,(REAL)y2,(REAL)x3,(REAL)y3,
(REAL)x4,(REAL)y4);
}
{
INT i, old_count;
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(!path || !points || ((count - 1) % 3))
return InvalidParameter;
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(!points || ((count - 1) % 3))
return InvalidParameter;
GpStatus WINGDIPAPI GdipAddPathClosedCurve(GpPath *path, GDIPCONST GpPointF *points,
INT count)
{
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
return GdipAddPathClosedCurve2(path, points, count, 1.0);
}
GpStatus WINGDIPAPI GdipAddPathClosedCurveI(GpPath *path, GDIPCONST GpPoint *points,
INT count)
{
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
return GdipAddPathClosedCurve2I(path, points, count, 1.0);
}
REAL x1, x2, y1, y2;
GpStatus stat;
+ TRACE("(%p, %p, %d, %.2f)\n", path, points, count, tension);
+
if(!path || !points || count <= 1)
return InvalidParameter;
INT i;
GpStatus stat;
+ TRACE("(%p, %p, %d, %.2f)\n", path, points, count, tension);
+
if(!path || !points || count <= 1)
return InvalidParameter;
GpStatus WINGDIPAPI GdipAddPathCurve(GpPath *path, GDIPCONST GpPointF *points, INT count)
{
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(!path || !points || count <= 1)
return InvalidParameter;
- return GdipAddPathCurve2(path, points, count, 1.0);
+ return GdipAddPathCurve2(path, points, count, 1.0);
}
GpStatus WINGDIPAPI GdipAddPathCurveI(GpPath *path, GDIPCONST GpPoint *points, INT count)
{
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(!path || !points || count <= 1)
return InvalidParameter;
- return GdipAddPathCurve2I(path, points, count, 1.0);
+ return GdipAddPathCurve2I(path, points, count, 1.0);
}
GpStatus WINGDIPAPI GdipAddPathCurve2(GpPath *path, GDIPCONST GpPointF *points, INT count,
REAL x1, x2, y1, y2;
GpStatus stat;
+ TRACE("(%p, %p, %d, %.2f)\n", path, points, count, tension);
+
if(!path || !points || count <= 1)
return InvalidParameter;
INT i;
GpStatus stat;
+ TRACE("(%p, %p, %d, %.2f)\n", path, points, count, tension);
+
if(!path || !points || count <= 1)
return InvalidParameter;
{
INT old_count, numpts;
+ TRACE("(%p, %.2f, %.2f, %.2f, %.2f)\n", path, x, y, width, height);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipAddPathEllipseI(GpPath *path, INT x, INT y, INT width,
INT height)
{
+ TRACE("(%p, %d, %d, %d, %d)\n", path, x, y, width, height);
+
return GdipAddPathEllipse(path,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
}
{
INT i, old_count;
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(!path || !points)
return InvalidParameter;
INT i;
GpStatus stat;
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(count <= 0)
return InvalidParameter;
{
INT old_count;
+ TRACE("(%p, %.2f, %.2f, %.2f, %.2f)\n", path, x1, y1, x2, y2);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipAddPathLineI(GpPath *path, INT x1, INT y1, INT x2, INT y2)
{
+ TRACE("(%p, %d, %d, %d, %d)\n", path, x1, y1, x2, y2);
+
return GdipAddPathLine(path, (REAL)x1, (REAL)y1, (REAL)x2, (REAL)y2);
}
{
INT old_count, count;
+ TRACE("(%p, %p, %d)\n", path, addingPath, connect);
+
if(!path || !addingPath)
return InvalidParameter;
return Ok;
}
+GpStatus WINGDIPAPI GdipAddPathPie(GpPath *path, REAL x, REAL y, REAL width, REAL height,
+ REAL startAngle, REAL sweepAngle)
+{
+ GpPointF *ptf;
+ GpStatus status;
+ INT i, count;
+
+ TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n",
+ path, x, y, width, height, startAngle, sweepAngle);
+
+ if(!path)
+ return InvalidParameter;
+
+ count = arc2polybezier(NULL, x, y, width, height, startAngle, sweepAngle);
+
+ if(count == 0)
+ return Ok;
+
+ ptf = GdipAlloc(sizeof(GpPointF)*count);
+ if(!ptf)
+ return OutOfMemory;
+
+ arc2polybezier(ptf, x, y, width, height, startAngle, sweepAngle);
+
+ status = GdipAddPathLine(path, (width - x)/2, (height - y)/2, ptf[0].X, ptf[0].Y);
+ if(status != Ok){
+ GdipFree(ptf);
+ return status;
+ }
+ /* one spline is already added as a line endpoint */
+ if(!lengthen_path(path, count - 1)){
+ GdipFree(ptf);
+ return OutOfMemory;
+ }
+
+ memcpy(&(path->pathdata.Points[path->pathdata.Count]), &(ptf[1]),sizeof(GpPointF)*(count-1));
+ for(i = 0; i < count-1; i++)
+ path->pathdata.Types[path->pathdata.Count+i] = PathPointTypeBezier;
+
+ path->pathdata.Count += count-1;
+
+ GdipClosePathFigure(path);
+
+ GdipFree(ptf);
+
+ return status;
+}
+
+GpStatus WINGDIPAPI GdipAddPathPieI(GpPath *path, INT x, INT y, INT width, INT height,
+ REAL startAngle, REAL sweepAngle)
+{
+ TRACE("(%p, %d, %d, %d, %d, %.2f, %.2f)\n",
+ path, x, y, width, height, startAngle, sweepAngle);
+
+ return GdipAddPathPieI(path, (REAL)x, (REAL)y, (REAL)width, (REAL)height, startAngle, sweepAngle);
+}
+
GpStatus WINGDIPAPI GdipAddPathPolygon(GpPath *path, GDIPCONST GpPointF *points, INT count)
{
INT old_count;
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(!path || !points || count < 3)
return InvalidParameter;
GpStatus status;
INT i;
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(!points || count < 3)
return InvalidParameter;
GpStatus WINGDIPAPI GdipClonePath(GpPath* path, GpPath **clone)
{
+ TRACE("(%p, %p)\n", path, clone);
+
if(!path || !clone)
return InvalidParameter;
GpStatus WINGDIPAPI GdipClosePathFigure(GpPath* path)
{
+ TRACE("(%p)\n", path);
+
if(!path)
return InvalidParameter;
{
INT i;
+ TRACE("(%p)\n", path);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCreatePath(GpFillMode fill, GpPath **path)
{
+ TRACE("(%d, %p)\n", fill, path);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCreatePath2(GDIPCONST GpPointF* points,
GDIPCONST BYTE* types, INT count, GpFillMode fill, GpPath **path)
{
+ TRACE("(%p, %p, %d, %d, %p)\n", points, types, count, fill, path);
+
if(!path)
return InvalidParameter;
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %d, %d, %p)\n", points, types, count, fill, path);
+
ptF = GdipAlloc(sizeof(GpPointF)*count);
for(i = 0;i < count; i++){
GpStatus WINGDIPAPI GdipDeletePath(GpPath *path)
{
+ TRACE("(%p)\n", path);
+
if(!path)
return InvalidParameter;
return Ok;
}
+GpStatus WINGDIPAPI GdipFlattenPath(GpPath *path, GpMatrix* matrix, REAL flatness)
+{
+ path_list_node_t *list, *node;
+ GpPointF pt;
+ INT i = 1;
+ INT startidx = 0;
+
+ TRACE("(%p, %p, %.2f)\n", path, matrix, flatness);
+
+ if(!path)
+ return InvalidParameter;
+
+ if(matrix){
+ WARN("transformation not supported yet!\n");
+ return NotImplemented;
+ }
+
+ if(path->pathdata.Count == 0)
+ return Ok;
+
+ pt = path->pathdata.Points[0];
+ if(!init_path_list(&list, pt.X, pt.Y))
+ return OutOfMemory;
+
+ node = list;
+
+ while(i < path->pathdata.Count){
+
+ BYTE type = path->pathdata.Types[i] & PathPointTypePathTypeMask;
+ path_list_node_t *start;
+
+ pt = path->pathdata.Points[i];
+
+ /* save last start point index */
+ if(type == PathPointTypeStart)
+ startidx = i;
+
+ /* always add line points and start points */
+ if((type == PathPointTypeStart) || (type == PathPointTypeLine)){
+ type = (path->pathdata.Types[i] & ~PathPointTypeBezier) | PathPointTypeLine;
+ if(!add_path_list_node(node, pt.X, pt.Y, type))
+ goto memout;
+
+ node = node->next;
+ continue;
+ }
+
+ /* Bezier curve always stored as 4 points */
+ if((path->pathdata.Types[i-1] & PathPointTypePathTypeMask) != PathPointTypeStart){
+ type = (path->pathdata.Types[i] & ~PathPointTypeBezier) | PathPointTypeLine;
+ if(!add_path_list_node(node, pt.X, pt.Y, type))
+ goto memout;
+
+ node = node->next;
+ }
+
+ /* test for closed figure */
+ if(path->pathdata.Types[i+1] & PathPointTypeCloseSubpath){
+ pt = path->pathdata.Points[startidx];
+ ++i;
+ }
+ else
+ {
+ i += 2;
+ pt = path->pathdata.Points[i];
+ };
+
+ start = node;
+ /* add Bezier end point */
+ type = (path->pathdata.Types[i] & ~PathPointTypeBezier) | PathPointTypeLine;
+ if(!add_path_list_node(node, pt.X, pt.Y, type))
+ goto memout;
+ node = node->next;
+
+ /* flatten curve */
+ if(!flatten_bezier(start, path->pathdata.Points[i-2].X, path->pathdata.Points[i-2].Y,
+ path->pathdata.Points[i-1].X, path->pathdata.Points[i-1].Y,
+ node, flatness))
+ goto memout;
+
+ ++i;
+ }/* while */
+
+ /* store path data back */
+ i = path_list_count(list);
+ if(!lengthen_path(path, i))
+ goto memout;
+ path->pathdata.Count = i;
+
+ node = list;
+ for(i = 0; i < path->pathdata.Count; i++){
+ path->pathdata.Points[i] = node->pt;
+ path->pathdata.Types[i] = node->type;
+ node = node->next;
+ }
+
+ free_path_list(list);
+ return Ok;
+
+memout:
+ free_path_list(list);
+ return OutOfMemory;
+}
+
GpStatus WINGDIPAPI GdipGetPathData(GpPath *path, GpPathData* pathData)
{
+ TRACE("(%p, %p)\n", path, pathData);
+
if(!path || !pathData)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathFillMode(GpPath *path, GpFillMode *fillmode)
{
+ TRACE("(%p, %p)\n", path, fillmode);
+
if(!path || !fillmode)
return InvalidParameter;
{
INT count;
+ TRACE("(%p, %p)\n", path, lastPoint);
+
if(!path || !lastPoint)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathPoints(GpPath *path, GpPointF* points, INT count)
{
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(!path)
return InvalidParameter;
GpPointF *ptf;
INT i;
+ TRACE("(%p, %p, %d)\n", path, points, count);
+
if(count <= 0)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetPathTypes(GpPath *path, BYTE* types, INT count)
{
+ TRACE("(%p, %p, %d)\n", path, types, count);
+
if(!path)
return InvalidParameter;
INT count, i;
REAL path_width = 1.0, width, height, temp, low_x, low_y, high_x, high_y;
+ TRACE("(%p, %p, %p, %p)\n", path, bounds, matrix, pen);
+
/* Matrix and pen can be null. */
if(!path || !bounds)
return InvalidParameter;
GpStatus ret;
GpRectF boundsF;
+ TRACE("(%p, %p, %p, %p)\n", path, bounds, matrix, pen);
+
ret = GdipGetPathWorldBounds(path,&boundsF,matrix,pen);
if(ret == Ok){
GpStatus WINGDIPAPI GdipGetPointCount(GpPath *path, INT *count)
{
+ TRACE("(%p, %p)\n", path, count);
+
if(!path)
return InvalidParameter;
return Ok;
}
+GpStatus WINGDIPAPI GdipReversePath(GpPath* path)
+{
+ INT i, count;
+ INT start = 0; /* position in reversed path */
+ GpPathData revpath;
+
+ TRACE("(%p)\n", path);
+
+ if(!path)
+ return InvalidParameter;
+
+ count = path->pathdata.Count;
+
+ if(count == 0) return Ok;
+
+ revpath.Points = GdipAlloc(sizeof(GpPointF)*count);
+ revpath.Types = GdipAlloc(sizeof(BYTE)*count);
+ revpath.Count = count;
+ if(!revpath.Points || !revpath.Types){
+ GdipFree(revpath.Points);
+ GdipFree(revpath.Types);
+ return OutOfMemory;
+ }
+
+ for(i = 0; i < count; i++){
+
+ /* find next start point */
+ if(path->pathdata.Types[count-i-1] == PathPointTypeStart){
+ INT j;
+ for(j = start; j <= i; j++){
+ revpath.Points[j] = path->pathdata.Points[count-j-1];
+ revpath.Types[j] = path->pathdata.Types[count-j-1];
+ }
+ /* mark start point */
+ revpath.Types[start] = PathPointTypeStart;
+ /* set 'figure' endpoint type */
+ if(i-start > 1){
+ revpath.Types[i] = path->pathdata.Types[count-start-1] & ~PathPointTypePathTypeMask;
+ revpath.Types[i] |= revpath.Types[i-1];
+ }
+ else
+ revpath.Types[i] = path->pathdata.Types[start];
+
+ start = i+1;
+ }
+ }
+
+ memcpy(path->pathdata.Points, revpath.Points, sizeof(GpPointF)*count);
+ memcpy(path->pathdata.Types, revpath.Types, sizeof(BYTE)*count);
+
+ GdipFree(revpath.Points);
+ GdipFree(revpath.Types);
+
+ return Ok;
+}
+
GpStatus WINGDIPAPI GdipIsOutlineVisiblePathPointI(GpPath* path, INT x, INT y,
GpPen *pen, GpGraphics *graphics, BOOL *result)
{
+ TRACE("(%p, %d, %d, %p, %p, %p)\n", path, x, y, pen, graphics, result);
+
return GdipIsOutlineVisiblePathPoint(path, x, y, pen, graphics, result);
}
GpStatus WINGDIPAPI GdipIsVisiblePathPointI(GpPath* path, INT x, INT y, GpGraphics *graphics, BOOL *result)
{
+ TRACE("(%p, %d, %d, %p, %p)\n", path, x, y, graphics, result);
+
return GdipIsVisiblePathPoint(path, x, y, graphics, result);
}
GpStatus WINGDIPAPI GdipStartPathFigure(GpPath *path)
{
+ TRACE("(%p)\n", path);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipResetPath(GpPath *path)
{
+ TRACE("(%p)\n", path);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetPathFillMode(GpPath *path, GpFillMode fill)
{
+ TRACE("(%p, %d)\n", path, fill);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipTransformPath(GpPath *path, GpMatrix *matrix)
{
+ TRACE("(%p, %p)\n", path, matrix);
+
if(!path)
return InvalidParameter;
GpStatus retstat;
BOOL old_new;
+ TRACE("(%p, %.2f, %.2f, %.2f, %.2f)\n", path, x, y, width, height);
+
if(!path || width < 0.0 || height < 0.0)
return InvalidParameter;
GpStatus WINGDIPAPI GdipAddPathRectangleI(GpPath *path, INT x, INT y,
INT width, INT height)
{
+ TRACE("(%p, %d, %d, %d, %d)\n", path, x, y, width, height);
+
return GdipAddPathRectangle(path,(REAL)x,(REAL)y,(REAL)width,(REAL)height);
}
GpStatus retstat;
INT i;
+ TRACE("(%p, %p, %d)\n", path, rects, count);
+
/* count == 0 - verified condition */
if(!path || !rects || count == 0)
return InvalidParameter;
GpStatus retstat;
INT i;
+ TRACE("(%p, %p, %d)\n", path, rects, count);
+
if(!rects || count == 0)
return InvalidParameter;
{
INT count;
+ TRACE("(%p)\n", path);
+
if(!path)
return InvalidParameter;
INT count;
INT i;
+ TRACE("(%p)\n", path);
+
if(!path)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
{
- if (!(image && cloneImage)) return InvalidParameter;
+ IStream* stream;
+ HRESULT hr;
+ INT size;
- FIXME("stub: %p, %p\n", image, cloneImage);
+ TRACE("%p, %p\n", image, cloneImage);
- return NotImplemented;
+ if (!image || !cloneImage)
+ return InvalidParameter;
+
+ hr = CreateStreamOnHGlobal(0, TRUE, &stream);
+ if (FAILED(hr))
+ return GenericError;
+
+ *cloneImage = GdipAlloc(sizeof(GpImage));
+ if (!*cloneImage)
+ {
+ IStream_Release(stream);
+ return OutOfMemory;
+ }
+ (*cloneImage)->type = image->type;
+ (*cloneImage)->flags = image->flags;
+
+ hr = IPicture_SaveAsFile(image->picture, stream, FALSE, &size);
+ if(FAILED(hr))
+ {
+ WARN("Failed to save image on stream\n");
+ goto out;
+ }
+
+ hr = OleLoadPicture(stream, size, FALSE, &IID_IPicture,
+ (LPVOID*) &(*cloneImage)->picture);
+ if (FAILED(hr))
+ {
+ WARN("Failed to load image from stream\n");
+ goto out;
+ }
+
+ IStream_Release(stream);
+ return Ok;
+out:
+ IStream_Release(stream);
+ GdipFree(*cloneImage);
+ *cloneImage = NULL;
+ return GenericError;
}
GpStatus WINGDIPAPI GdipCreateBitmapFromFile(GDIPCONST WCHAR* filename,
GpStatus WINGDIPAPI GdipCloneImageAttributes(GDIPCONST GpImageAttributes *imageattr,
GpImageAttributes **cloneImageattr)
{
+ TRACE("(%p, %p)\n", imageattr, cloneImageattr);
+
if(!imageattr || !cloneImageattr)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCreateImageAttributes(GpImageAttributes **imageattr)
{
+ TRACE("(%p)\n", imageattr);
+
if(!imageattr)
return InvalidParameter;
GpStatus WINGDIPAPI GdipDisposeImageAttributes(GpImageAttributes *imageattr)
{
+ TRACE("(%p)\n", imageattr);
+
if(!imageattr)
return InvalidParameter;
#include "gdiplus.h"
#include "gdiplus_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
/* Multiplies two matrices of the form
*
GpStatus WINGDIPAPI GdipCreateMatrix2(REAL m11, REAL m12, REAL m21, REAL m22,
REAL dx, REAL dy, GpMatrix **matrix)
{
+ TRACE("(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p)\n", m11, m12, m21, m22, dx, dy, matrix);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCreateMatrix3(GDIPCONST GpRectF *rect,
GDIPCONST GpPointF *pt, GpMatrix **matrix)
{
+ TRACE("(%p, %p, %p)\n", rect, pt, matrix);
+
if(!matrix)
return InvalidParameter;
GpRectF rectF;
GpPointF ptF;
+ TRACE("(%p, %p, %p)\n", rect, pt, matrix);
+
rectF.X = (REAL)rect->X;
rectF.Y = (REAL)rect->Y;
rectF.Width = (REAL)rect->Width;
GpStatus WINGDIPAPI GdipCloneMatrix(GpMatrix *matrix, GpMatrix **clone)
{
+ TRACE("(%p, %p)\n", matrix, clone);
+
if(!matrix || !clone)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix **matrix)
{
+ TRACE("(%p)\n", matrix);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipDeleteMatrix(GpMatrix *matrix)
{
+ TRACE("(%p)\n", matrix);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetMatrixElements(GDIPCONST GpMatrix *matrix,
REAL *out)
{
+ TRACE("(%p, %p)\n", matrix, out);
+
if(!matrix || !out)
return InvalidParameter;
REAL det;
BOOL invertible;
+ TRACE("(%p)\n", matrix);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix *matrix, BOOL *result)
{
+ TRACE("(%p, %p)\n", matrix, result);
+
if(!matrix || !result)
return InvalidParameter;
GpStatus WINGDIPAPI GdipMultiplyMatrix(GpMatrix *matrix, GpMatrix* matrix2,
GpMatrixOrder order)
{
+ TRACE("(%p, %p, %d)\n", matrix, matrix2, order);
+
if(!matrix || !matrix2)
return InvalidParameter;
{
REAL cos_theta, sin_theta, rotate[6];
+ TRACE("(%p, %.2f, %d)\n", matrix, angle, order);
+
if(!matrix)
return InvalidParameter;
{
REAL scale[6];
+ TRACE("(%p, %.2f, %.2f, %d)\n", matrix, scaleX, scaleY, order);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetMatrixElements(GpMatrix *matrix, REAL m11, REAL m12,
REAL m21, REAL m22, REAL dx, REAL dy)
{
+ TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", matrix, m11, m12,
+ m21, m22, dx, dy);
+
if(!matrix)
return InvalidParameter;
{
REAL shear[6];
+ TRACE("(%p, %.2f, %.2f, %d)\n", matrix, shearX, shearY, order);
+
if(!matrix)
return InvalidParameter;
REAL x, y;
INT i;
+ TRACE("(%p, %p, %d)\n", matrix, pts, count);
+
if(!matrix || !pts || count <= 0)
return InvalidParameter;
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %d)\n", matrix, pts, count);
+
if(count <= 0)
return InvalidParameter;
{
REAL translate[6];
+ TRACE("(%p, %.2f, %.2f, %d)\n", matrix, offsetX, offsetY, order);
+
if(!matrix)
return InvalidParameter;
REAL x, y;
INT i;
+ TRACE("(%p, %p, %d)\n", matrix, pts, count);
+
if(!matrix || !pts || count <= 0)
return InvalidParameter;
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %d)\n", matrix, pts, count);
+
if(count <= 0)
return InvalidParameter;
GpStatus WINGDIPAPI GdipIsMatrixEqual(GDIPCONST GpMatrix *matrix, GDIPCONST GpMatrix *matrix2,
BOOL *result)
{
+ TRACE("(%p, %p, %p)\n", matrix, matrix2, result);
+
if(!matrix || !matrix2 || !result)
return InvalidParameter;
/* based on single array member of GpMatrix */
GpStatus ret;
BOOL isIdentity;
+ TRACE("(%p, %p)\n", matrix, result);
+
if(!matrix || !result)
return InvalidParameter;
/*
* Copyright (C) 2007 Google (Evan Stade)
+ * Copyright (C) 2008 Nikolay Sivov <bunglehead at gmail dot com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "gdiplus.h"
#include "gdiplus_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
GpStatus WINGDIPAPI GdipCreatePathIter(GpPathIterator **iterator, GpPath* path)
{
INT size;
+ TRACE("(%p, %p)\n", iterator, path);
+
if(!iterator)
return InvalidParameter;
GpStatus WINGDIPAPI GdipDeletePathIter(GpPathIterator *iter)
{
+ TRACE("(%p)\n", iter);
+
if(!iter)
return InvalidParameter;
GpStatus WINGDIPAPI GdipPathIterCopyData(GpPathIterator* iterator,
INT* resultCount, GpPointF* points, BYTE* types, INT startIndex, INT endIndex)
{
+ TRACE("(%p, %p, %p, %p, %d, %d)\n", iterator, resultCount, points, types,
+ startIndex, endIndex);
+
if(!iterator || !types || !points)
return InvalidParameter;
{
INT i;
+ TRACE("(%p, %p)\n", iterator, hasCurve);
+
if(!iterator)
return InvalidParameter;
{
INT i;
+ TRACE("(%p, %p)\n", iterator, count);
+
if(!iterator || !count)
return InvalidParameter;
{
INT i;
+ TRACE("(%p, %p, %p, %p)\n", iterator, resultCount, startIndex, endIndex);
+
if(!iterator || !startIndex || !endIndex)
return InvalidParameter;
return Ok;
}
+GpStatus WINGDIPAPI GdipPathIterNextMarkerPath(GpPathIterator* iterator, INT* result,
+ GpPath* path)
+{
+ INT start, end;
+
+ TRACE("(%p, %p, %p)\n", iterator, result, path);
+
+ if(!iterator || !result)
+ return InvalidParameter;
+
+ GdipPathIterNextMarker(iterator, result, &start, &end);
+ /* return path */
+ if(((*result) > 0) && path){
+ GdipResetPath(path);
+
+ if(!lengthen_path(path, *result))
+ return OutOfMemory;
+
+ memcpy(path->pathdata.Points, &(iterator->pathdata.Points[start]), sizeof(GpPointF)*(*result));
+ memcpy(path->pathdata.Types, &(iterator->pathdata.Types[start]), sizeof(BYTE)*(*result));
+ path->pathdata.Count = *result;
+ }
+
+ return Ok;
+}
+
GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator* iterator,
INT *resultCount, INT* startIndex, INT* endIndex, BOOL* isClosed)
{
INT i, count;
+ TRACE("(%p, %p, %p, %p, %p)\n", iterator, resultCount, startIndex,
+ endIndex, isClosed);
+
if(!iterator || !startIndex || !endIndex || !isClosed || !resultCount)
return InvalidParameter;
count = iterator->pathdata.Count;
/* iterator created with NULL path */
- if(count == 0)
+ if(count == 0){
+ *resultCount = 0;
return Ok;
+ }
if(iterator->subpath_pos == count){
*startIndex = *endIndex = *resultCount = 0;
}
GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator *iterator)
{
+ TRACE("(%p)\n", iterator);
+
if(!iterator)
return InvalidParameter;
GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator* iterator, INT* count)
{
+ TRACE("(%p, %p)\n", iterator, count);
+
if(!iterator || !count)
return InvalidParameter;
GpStatus WINGDIPAPI GdipPathIterEnumerate(GpPathIterator* iterator, INT* resultCount,
GpPointF *points, BYTE *types, INT count)
{
+ TRACE("(%p, %p, %p, %p, %d)\n", iterator, resultCount, points, types, count);
+
if((count < 0) || !resultCount)
return InvalidParameter;
return GdipPathIterCopyData(iterator, resultCount, points, types, 0, count-1);
}
+
+GpStatus WINGDIPAPI GdipPathIterIsValid(GpPathIterator* iterator, BOOL* valid)
+{
+ TRACE("(%p, %p)\n", iterator, valid);
+
+ if(!iterator || !valid)
+ return InvalidParameter;
+
+ *valid = TRUE;
+
+ return Ok;
+}
+
+GpStatus WINGDIPAPI GdipPathIterNextPathType(GpPathIterator* iter, INT* result,
+ BYTE* type, INT* start, INT* end)
+{
+ FIXME("(%p, %p, %p, %p, %p) stub\n", iter, result, type, start, end);
+
+ if(!iter || !result || !type || !start || !end)
+ return InvalidParameter;
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator* iter, INT* result,
+ GpPath* path, BOOL* closed)
+{
+ INT start, end;
+
+ TRACE("(%p, %p, %p, %p)\n", iter, result, path, closed);
+
+ if(!iter || !result || !closed)
+ return InvalidParameter;
+
+ GdipPathIterNextSubpath(iter, result, &start, &end, closed);
+ /* return path */
+ if(((*result) > 0) && path){
+ GdipResetPath(path);
+
+ if(!lengthen_path(path, *result))
+ return OutOfMemory;
+
+ memcpy(path->pathdata.Points, &(iter->pathdata.Points[start]), sizeof(GpPointF)*(*result));
+ memcpy(path->pathdata.Types, &(iter->pathdata.Types[start]), sizeof(BYTE)*(*result));
+ path->pathdata.Count = *result;
+ }
+
+ return Ok;
+}
*
*/
-typedef enum RegionType
-{
- RegionDataRect = 0x10000000,
- RegionDataPath = 0x10000001,
- RegionDataEmptyRect = 0x10000002,
- RegionDataInfiniteRect = 0x10000003,
-} RegionType;
+#define FLAGS_NOFLAGS 0x0
+#define FLAGS_INTPATH 0x4000
/* Header size as far as header->size is concerned. This doesn't include
* header->size or header->checksum
*/
static const INT sizeheader_size = sizeof(DWORD) * 2;
+typedef struct packed_point
+{
+ short X;
+ short Y;
+} packed_point;
+
+/* Everything is measured in DWORDS; round up if there's a remainder */
+static inline INT get_pathtypes_size(const GpPath* path)
+{
+ INT needed = path->pathdata.Count / sizeof(DWORD);
+
+ if (path->pathdata.Count % sizeof(DWORD) > 0)
+ needed++;
+
+ return needed * sizeof(DWORD);
+}
+
static inline INT get_element_size(const region_element* element)
{
INT needed = sizeof(DWORD); /* DWORD for the type */
return Ok;
}
-static inline void delete_element(region_element* element)
+static inline GpStatus clone_element(const region_element* element,
+ region_element** element2)
{
- switch(element->type)
+ GpStatus stat;
+
+ /* root node is allocated with GpRegion */
+ if(!*element2){
+ *element2 = GdipAlloc(sizeof(region_element));
+ if (!*element2)
+ return OutOfMemory;
+ }
+
+ (*element2)->type = element->type;
+
+ switch (element->type)
{
case RegionDataRect:
- break;
- case RegionDataPath:
- GdipDeletePath(element->elementdata.pathdata.path);
+ (*element2)->elementdata.rect = element->elementdata.rect;
break;
case RegionDataEmptyRect:
case RegionDataInfiniteRect:
break;
+ case RegionDataPath:
+ (*element2)->elementdata.pathdata.pathheader = element->elementdata.pathdata.pathheader;
+ stat = GdipClonePath(element->elementdata.pathdata.path,
+ &(*element2)->elementdata.pathdata.path);
+ if (stat != Ok) goto clone_out;
+ break;
default:
- delete_element(element->elementdata.combine.left);
- delete_element(element->elementdata.combine.right);
- GdipFree(element->elementdata.combine.left);
- GdipFree(element->elementdata.combine.right);
+ (*element2)->elementdata.combine.left = NULL;
+ (*element2)->elementdata.combine.right = NULL;
+
+ stat = clone_element(element->elementdata.combine.left,
+ &(*element2)->elementdata.combine.left);
+ if (stat != Ok) goto clone_out;
+ stat = clone_element(element->elementdata.combine.right,
+ &(*element2)->elementdata.combine.right);
+ if (stat != Ok) goto clone_out;
break;
}
+
+ return Ok;
+
+clone_out:
+ delete_element(*element2);
+ *element2 = NULL;
+ return stat;
+}
+
+/* Common code for CombineRegion*
+ * All the caller has to do is get its format into an element
+ */
+static inline void fuse_region(GpRegion* region, region_element* left,
+ region_element* right, const CombineMode mode)
+{
+ region->node.type = mode;
+ region->node.elementdata.combine.left = left;
+ region->node.elementdata.combine.right = right;
+
+ region->header.size = sizeheader_size + get_element_size(®ion->node);
+ region->header.num_children += 2;
}
/*****************************************************************************
* GdipCloneRegion [GDIPLUS.@]
+ *
+ * Creates a deep copy of the region
+ *
+ * PARAMS
+ * region [I] source region
+ * clone [O] resulting clone
+ *
+ * RETURNS
+ * SUCCESS: Ok
+ * FAILURE: InvalidParameter or OutOfMemory
*/
GpStatus WINGDIPAPI GdipCloneRegion(GpRegion *region, GpRegion **clone)
{
- FIXME("(%p %p): stub\n", region, clone);
+ region_element *element;
- *clone = NULL;
- return NotImplemented;
+ TRACE("%p %p\n", region, clone);
+
+ if (!(region && clone))
+ return InvalidParameter;
+
+ *clone = GdipAlloc(sizeof(GpRegion));
+ if (!*clone)
+ return OutOfMemory;
+ element = &(*clone)->node;
+
+ (*clone)->header = region->header;
+ return clone_element(®ion->node, &element);
}
+/*****************************************************************************
+ * GdipCombineRegionPath [GDIPLUS.@]
+ */
GpStatus WINGDIPAPI GdipCombineRegionPath(GpRegion *region, GpPath *path, CombineMode mode)
{
- FIXME("(%p %p %d): stub\n", region, path, mode);
- return NotImplemented;
+ GpRegion *path_region;
+ region_element *left, *right = NULL;
+ GpStatus stat;
+
+ TRACE("%p %p %d\n", region, path, mode);
+
+ if (!(region && path))
+ return InvalidParameter;
+
+ stat = GdipCreateRegionPath(path, &path_region);
+ if (stat != Ok)
+ return stat;
+
+ /* simply replace region data */
+ if(mode == CombineModeReplace){
+ delete_element(®ion->node);
+ memcpy(region, path_region, sizeof(GpRegion));
+ return Ok;
+ }
+
+ left = GdipAlloc(sizeof(region_element));
+ if (!left)
+ goto out;
+ *left = region->node;
+
+ stat = clone_element(&path_region->node, &right);
+ if (stat != Ok)
+ goto out;
+
+ fuse_region(region, left, right, mode);
+
+ GdipDeleteRegion(path_region);
+ return Ok;
+
+out:
+ GdipFree(left);
+ delete_element(right);
+ GdipDeleteRegion(path_region);
+ return stat;
}
-GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region, GDIPCONST GpRectF *rect,
- CombineMode mode)
+/*****************************************************************************
+ * GdipCombineRegionRect [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipCombineRegionRect(GpRegion *region,
+ GDIPCONST GpRectF *rect, CombineMode mode)
{
- FIXME("(%p %p %d): stub\n", region, rect, mode);
- return NotImplemented;
+ GpRegion *rect_region;
+ region_element *left, *right = NULL;
+ GpStatus stat;
+
+ TRACE("%p %p %d\n", region, rect, mode);
+
+ if (!(region && rect))
+ return InvalidParameter;
+
+ stat = GdipCreateRegionRect(rect, &rect_region);
+ if (stat != Ok)
+ return stat;
+
+ /* simply replace region data */
+ if(mode == CombineModeReplace){
+ delete_element(®ion->node);
+ memcpy(region, rect_region, sizeof(GpRegion));
+ return Ok;
+ }
+
+ left = GdipAlloc(sizeof(region_element));
+ if (!left)
+ goto out;
+ memcpy(left, ®ion->node, sizeof(region_element));
+
+ stat = clone_element(&rect_region->node, &right);
+ if (stat != Ok)
+ goto out;
+
+ fuse_region(region, left, right, mode);
+
+ GdipDeleteRegion(rect_region);
+ return Ok;
+
+out:
+ GdipFree(left);
+ delete_element(right);
+ GdipDeleteRegion(rect_region);
+ return stat;
}
-GpStatus WINGDIPAPI GdipCombineRegionRectI(GpRegion *region, GDIPCONST GpRect *rect,
- CombineMode mode)
+/*****************************************************************************
+ * GdipCombineRegionRectI [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipCombineRegionRectI(GpRegion *region,
+ GDIPCONST GpRect *rect, CombineMode mode)
{
- FIXME("(%p %p %d): stub\n", region, rect, mode);
- return NotImplemented;
+ GpRectF rectf;
+
+ TRACE("%p %p %d\n", region, rect, mode);
+
+ if (!rect)
+ return InvalidParameter;
+
+ rectf.X = (REAL)rect->X;
+ rectf.Y = (REAL)rect->Y;
+ rectf.Height = (REAL)rect->Height;
+ rectf.Width = (REAL)rect->Width;
+
+ return GdipCombineRegionRect(region, &rectf, mode);
}
-GpStatus WINGDIPAPI GdipCombineRegionRegion(GpRegion *region1, GpRegion *region2,
- CombineMode mode)
+GpStatus WINGDIPAPI GdipCombineRegionRegion(GpRegion *region1,
+ GpRegion *region2, CombineMode mode)
{
- FIXME("(%p %p %d): stub\n", region1, region2, mode);
- return NotImplemented;
+ region_element *left, *right = NULL;
+ GpStatus stat;
+ GpRegion *reg2copy;
+
+ TRACE("%p %p %d\n", region1, region2, mode);
+
+ if(!(region1 && region2))
+ return InvalidParameter;
+
+ /* simply replace region data */
+ if(mode == CombineModeReplace){
+ stat = GdipCloneRegion(region2, ®2copy);
+ if(stat != Ok) return stat;
+
+ delete_element(®ion1->node);
+ memcpy(region1, reg2copy, sizeof(GpRegion));
+ return Ok;
+ }
+
+ left = GdipAlloc(sizeof(region_element));
+ if (!left)
+ return OutOfMemory;
+
+ *left = region1->node;
+ stat = clone_element(®ion2->node, &right);
+ if (stat != Ok)
+ {
+ GdipFree(left);
+ delete_element(right);
+ return OutOfMemory;
+ }
+
+ fuse_region(region1, left, right, mode);
+ region1->header.num_children += region2->header.num_children;
+
+ return Ok;
}
+/*****************************************************************************
+ * GdipCreateRegion [GDIPLUS.@]
+ */
GpStatus WINGDIPAPI GdipCreateRegion(GpRegion **region)
{
+ TRACE("%p\n", region);
+
if(!region)
return InvalidParameter;
- TRACE("%p\n", region);
-
*region = GdipAlloc(sizeof(GpRegion));
if(!*region)
return OutOfMemory;
return init_region(*region, RegionDataInfiniteRect);
}
+/*****************************************************************************
+ * GdipCreateRegionPath [GDIPLUS.@]
+ *
+ * Creates a GpRegion from a GpPath
+ *
+ * PARAMS
+ * path [I] path to base the region on
+ * region [O] pointer to the newly allocated region
+ *
+ * RETURNS
+ * SUCCESS: Ok
+ * FAILURE: InvalidParameter
+ *
+ * NOTES
+ * If a path has no floating point points, its points will be stored as shorts
+ * (INTPATH)
+ *
+ * If a path is empty, it is considered to be an INTPATH
+ */
GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
{
- FIXME("(%p, %p): stub\n", path, region);
+ region_element* element;
+ GpPoint *pointsi;
+ GpPointF *pointsf;
- *region = NULL;
- return NotImplemented;
+ GpStatus stat;
+ DWORD flags = FLAGS_INTPATH;
+ INT count, i;
+
+ TRACE("%p, %p\n", path, region);
+
+ if (!(path && region))
+ return InvalidParameter;
+
+ *region = GdipAlloc(sizeof(GpRegion));
+ if(!*region)
+ return OutOfMemory;
+ stat = init_region(*region, RegionDataPath);
+ if (stat != Ok)
+ {
+ GdipDeleteRegion(*region);
+ return stat;
+ }
+ element = &(*region)->node;
+ count = path->pathdata.Count;
+
+ /* Test to see if the path is an Integer path */
+ if (count)
+ {
+ pointsi = GdipAlloc(sizeof(GpPoint) * count);
+ pointsf = GdipAlloc(sizeof(GpPointF) * count);
+ if (!(pointsi && pointsf))
+ {
+ GdipFree(pointsi);
+ GdipFree(pointsf);
+ GdipDeleteRegion(*region);
+ return OutOfMemory;
+ }
+
+ stat = GdipGetPathPointsI(path, pointsi, count);
+ if (stat != Ok)
+ {
+ GdipDeleteRegion(*region);
+ return stat;
+ }
+ stat = GdipGetPathPoints(path, pointsf, count);
+ if (stat != Ok)
+ {
+ GdipDeleteRegion(*region);
+ return stat;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (!(pointsi[i].X == pointsf[i].X &&
+ pointsi[i].Y == pointsf[i].Y ))
+ {
+ flags = FLAGS_NOFLAGS;
+ break;
+ }
+ }
+ GdipFree(pointsi);
+ GdipFree(pointsf);
+ }
+
+ stat = GdipClonePath(path, &element->elementdata.pathdata.path);
+ if (stat != Ok)
+ {
+ GdipDeleteRegion(*region);
+ return stat;
+ }
+
+ /* 3 for headers, once again size doesn't count itself */
+ element->elementdata.pathdata.pathheader.size = ((sizeof(DWORD) * 3));
+ switch(flags)
+ {
+ /* Floats, sent out as floats */
+ case FLAGS_NOFLAGS:
+ element->elementdata.pathdata.pathheader.size +=
+ (sizeof(DWORD) * count * 2);
+ break;
+ /* INTs, sent out as packed shorts */
+ case FLAGS_INTPATH:
+ element->elementdata.pathdata.pathheader.size +=
+ (sizeof(DWORD) * count);
+ break;
+ default:
+ FIXME("Unhandled flags (%08x). Expect wrong results.\n", flags);
+ }
+ element->elementdata.pathdata.pathheader.size += get_pathtypes_size(path);
+ element->elementdata.pathdata.pathheader.magic = VERSION_MAGIC;
+ element->elementdata.pathdata.pathheader.count = count;
+ element->elementdata.pathdata.pathheader.flags = flags;
+ (*region)->header.size = sizeheader_size + get_element_size(element);
+
+ return Ok;
}
-GpStatus WINGDIPAPI GdipCreateRegionRect(GDIPCONST GpRectF *rect, GpRegion **region)
+/*****************************************************************************
+ * GdipCreateRegionRect [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipCreateRegionRect(GDIPCONST GpRectF *rect,
+ GpRegion **region)
{
- FIXME("(%p, %p): stub\n", rect, region);
+ GpStatus stat;
- *region = NULL;
- return NotImplemented;
+ TRACE("%p, %p\n", rect, region);
+
+ if (!(rect && region))
+ return InvalidParameter;
+
+ *region = GdipAlloc(sizeof(GpRegion));
+ stat = init_region(*region, RegionDataRect);
+ if(stat != Ok)
+ {
+ GdipDeleteRegion(*region);
+ return stat;
+ }
+
+ (*region)->node.elementdata.rect.X = rect->X;
+ (*region)->node.elementdata.rect.Y = rect->Y;
+ (*region)->node.elementdata.rect.Width = rect->Width;
+ (*region)->node.elementdata.rect.Height = rect->Height;
+
+ return Ok;
}
-GpStatus WINGDIPAPI GdipCreateRegionRectI(GDIPCONST GpRect *rect, GpRegion **region)
+GpStatus WINGDIPAPI GdipCreateRegionRectI(GDIPCONST GpRect *rect,
+ GpRegion **region)
{
- FIXME("(%p, %p): stub\n", rect, region);
+ GpRectF rectf;
- *region = NULL;
- return NotImplemented;
+ 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;
+
+ return GdipCreateRegionRect(&rectf, region);
}
GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRegion **region)
return NotImplemented;
}
-GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, UINT *needed)
+static inline void write_dword(DWORD* location, INT* offset, const DWORD write)
{
- FIXME("(%p, %p, %d, %p): stub\n", region, buffer, size, needed);
+ location[*offset] = write;
+ (*offset)++;
+}
- return NotImplemented;
+static inline void write_float(DWORD* location, INT* offset, const FLOAT write)
+{
+ ((FLOAT*)location)[*offset] = write;
+ (*offset)++;
}
-GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
+static inline void write_packed_point(DWORD* location, INT* offset,
+ const GpPointF* write)
{
- if (!(region && needed))
+ packed_point point;
+
+ point.X = write->X;
+ point.Y = write->Y;
+ memcpy(location + *offset, &point, sizeof(packed_point));
+ (*offset)++;
+}
+
+static inline void write_path_types(DWORD* location, INT* offset,
+ const GpPath* path)
+{
+ memcpy(location + *offset, path->pathdata.Types, path->pathdata.Count);
+
+ /* The unwritten parts of the DWORD (if any) must be cleared */
+ if (path->pathdata.Count % sizeof(DWORD))
+ ZeroMemory(((BYTE*)location) + (*offset * sizeof(DWORD)) +
+ path->pathdata.Count,
+ sizeof(DWORD) - path->pathdata.Count % sizeof(DWORD));
+ *offset += (get_pathtypes_size(path) / sizeof(DWORD));
+}
+
+static void write_element(const region_element* element, DWORD *buffer,
+ INT* filled)
+{
+ write_dword(buffer, filled, element->type);
+ switch (element->type)
+ {
+ case CombineModeReplace:
+ case CombineModeIntersect:
+ case CombineModeUnion:
+ case CombineModeXor:
+ case CombineModeExclude:
+ case CombineModeComplement:
+ write_element(element->elementdata.combine.left, buffer, filled);
+ write_element(element->elementdata.combine.right, buffer, filled);
+ break;
+ case RegionDataRect:
+ write_float(buffer, filled, element->elementdata.rect.X);
+ write_float(buffer, filled, element->elementdata.rect.Y);
+ write_float(buffer, filled, element->elementdata.rect.Width);
+ write_float(buffer, filled, element->elementdata.rect.Height);
+ break;
+ case RegionDataPath:
+ {
+ INT i;
+ const GpPath* path = element->elementdata.pathdata.path;
+
+ memcpy(buffer + *filled, &element->elementdata.pathdata.pathheader,
+ sizeof(element->elementdata.pathdata.pathheader));
+ *filled += sizeof(element->elementdata.pathdata.pathheader) / sizeof(DWORD);
+ switch (element->elementdata.pathdata.pathheader.flags)
+ {
+ case FLAGS_NOFLAGS:
+ for (i = 0; i < path->pathdata.Count; i++)
+ {
+ write_float(buffer, filled, path->pathdata.Points[i].X);
+ write_float(buffer, filled, path->pathdata.Points[i].Y);
+ }
+ break;
+ case FLAGS_INTPATH:
+ for (i = 0; i < path->pathdata.Count; i++)
+ {
+ write_packed_point(buffer, filled,
+ &path->pathdata.Points[i]);
+ }
+ }
+ write_path_types(buffer, filled, path);
+ break;
+ }
+ case RegionDataEmptyRect:
+ case RegionDataInfiniteRect:
+ break;
+ }
+}
+
+/*****************************************************************************
+ * GdipGetRegionData [GDIPLUS.@]
+ *
+ * Returns the header, followed by combining ops and region elements.
+ *
+ * PARAMS
+ * region [I] region to retrieve from
+ * buffer [O] buffer to hold the resulting data
+ * size [I] size of the buffer
+ * needed [O] (optional) how much data was written
+ *
+ * RETURNS
+ * SUCCESS: Ok
+ * FAILURE: InvalidParamter
+ *
+ * NOTES
+ * The header contains the size, a checksum, a version string, and the number
+ * of children. The size does not count itself or the checksum.
+ * Version is always something like 0xdbc01001 or 0xdbc01002
+ *
+ * An element is a RECT, or PATH; Combining ops are stored as their
+ * CombineMode value. Special regions (infinite, empty) emit just their
+ * op-code; GpRectFs emit their code followed by their points; GpPaths emit
+ * their code followed by a second header for the path followed by the actual
+ * path data. Followed by the flags for each point. The pathheader contains
+ * the size of the data to follow, a version number again, followed by a count
+ * of how many points, and any special flags which may apply. 0x4000 means its
+ * a path of shorts instead of FLOAT.
+ *
+ * Combining Ops are stored in reverse order from when they were constructed;
+ * the output is a tree where the left side combining area is always taken
+ * first.
+ */
+GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
+ UINT *needed)
+{
+ INT filled = 0;
+
+ TRACE("%p, %p, %d, %p\n", region, buffer, size, needed);
+
+ if (!(region && buffer && size))
return InvalidParameter;
+ memcpy(buffer, ®ion->header, sizeof(region->header));
+ filled += sizeof(region->header) / sizeof(DWORD);
+ /* With few exceptions, everything written is DWORD aligned,
+ * so use that as our base */
+ write_element(®ion->node, (DWORD*)buffer, &filled);
+
+ if (needed)
+ *needed = filled * sizeof(DWORD);
+
+ return Ok;
+}
+
+/*****************************************************************************
+ * GdipGetRegionDataSize [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
+{
TRACE("%p, %p\n", region, needed);
+ if (!(region && needed))
+ return InvalidParameter;
+
/* header.size doesn't count header.size and header.checksum */
*needed = region->header.size + sizeof(DWORD) * 2;
GpStatus WINGDIPAPI GdipIsEmptyRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
{
- FIXME("(%p, %p, %p): stub\n", region, graphics, res);
+ TRACE("(%p, %p, %p)\n", region, graphics, res);
- return NotImplemented;
+ if(!region || !graphics || !res)
+ return InvalidParameter;
+
+ *res = (region->node.type == RegionDataEmptyRect);
+
+ return Ok;
}
GpStatus WINGDIPAPI GdipIsEqualRegion(GpRegion *region, GpRegion *region2, GpGraphics *graphics,
return NotImplemented;
}
+/*****************************************************************************
+ * GdipIsInfiniteRegion [GDIPLUS.@]
+ */
GpStatus WINGDIPAPI GdipIsInfiniteRegion(GpRegion *region, GpGraphics *graphics, BOOL *res)
{
- FIXME("(%p, %p, %p): stub\n", region, graphics, res);
+ /* I think graphics is ignored here */
+ TRACE("(%p, %p, %p)\n", region, graphics, res);
- return NotImplemented;
+ if(!region || !graphics || !res)
+ return InvalidParameter;
+
+ *res = (region->node.type == RegionDataInfiniteRect);
+
+ return Ok;
}
+/*****************************************************************************
+ * GdipSetEmpty [GDIPLUS.@]
+ */
GpStatus WINGDIPAPI GdipSetEmpty(GpRegion *region)
{
GpStatus stat;
{
GpStatus stat;
+ TRACE("%p\n", region);
+
if (!region)
return InvalidParameter;
- TRACE("%p\n", region);
-
delete_element(®ion->node);
stat = init_region(region, RegionDataInfiniteRect);
GpStatus WINGDIPAPI GdipDrawCurveI(GpGraphics*,GpPen*,GDIPCONST GpPoint*,INT);
GpStatus WINGDIPAPI GdipDrawCurve2(GpGraphics*,GpPen*,GDIPCONST GpPointF*,INT,REAL);
GpStatus WINGDIPAPI GdipDrawCurve2I(GpGraphics*,GpPen*,GDIPCONST GpPoint*,INT,REAL);
+GpStatus WINGDIPAPI GdipDrawEllipse(GpGraphics*,GpPen*,REAL,REAL,REAL,REAL);
+GpStatus WINGDIPAPI GdipDrawEllipseI(GpGraphics*,GpPen*,INT,INT,INT,INT);
GpStatus WINGDIPAPI GdipDrawImage(GpGraphics*,GpImage*,REAL,REAL);
GpStatus WINGDIPAPI GdipDrawImageI(GpGraphics*,GpImage*,INT,INT);
GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics*,GpImage*,
GpStatus WINGDIPAPI GdipDrawString(GpGraphics*,GDIPCONST WCHAR*,INT,
GDIPCONST GpFont*,GDIPCONST RectF*, GDIPCONST GpStringFormat*,
GDIPCONST GpBrush*);
+
+GpStatus WINGDIPAPI GdipFillClosedCurve2(GpGraphics*,GpBrush*,GDIPCONST GpPointF*,INT,
+ REAL,GpFillMode);
+GpStatus WINGDIPAPI GdipFillClosedCurve2I(GpGraphics*,GpBrush*,GDIPCONST GpPoint*,INT,
+ REAL,GpFillMode);
GpStatus WINGDIPAPI GdipFillEllipse(GpGraphics*,GpBrush*,REAL,REAL,REAL,REAL);
GpStatus WINGDIPAPI GdipFillEllipseI(GpGraphics*,GpBrush*,INT,INT,INT,INT);
GpStatus WINGDIPAPI GdipFillPath(GpGraphics*,GpBrush*,GpPath*);
GpStatus WINGDIPAPI GdipFillRectanglesI(GpGraphics*,GpBrush*,GDIPCONST GpRect*,INT);
GpStatus WINGDIPAPI GdipGetCompositingMode(GpGraphics*,CompositingMode*);
GpStatus WINGDIPAPI GdipGetClip(GpGraphics*,GpRegion*);
+GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics*,GpRegion*,CombineMode);
+GpStatus WINGDIPAPI GdipResetClip(GpGraphics*);
+GpStatus WINGDIPAPI GdipIsClipEmpty(GpGraphics*, BOOL*);
GpStatus WINGDIPAPI GdipGetCompositingQuality(GpGraphics*,CompositingQuality*);
GpStatus WINGDIPAPI GdipGetDC(GpGraphics*,HDC*);
GpStatus WINGDIPAPI GdipGetImageDimension(GpImage*,REAL*,REAL*);
GpStatus WINGDIPAPI GdipGetSmoothingMode(GpGraphics*,SmoothingMode*);
GpStatus WINGDIPAPI GdipGetTextRenderingHint(GpGraphics*,TextRenderingHint*);
GpStatus WINGDIPAPI GdipGetWorldTransform(GpGraphics*,GpMatrix*);
+GpStatus WINGDIPAPI GdipGraphicsClear(GpGraphics*,ARGB);
GpStatus WINGDIPAPI GdipMeasureString(GpGraphics*,GDIPCONST WCHAR*,INT,
GDIPCONST GpFont*,GDIPCONST RectF*,GDIPCONST GpStringFormat*,RectF*,INT*,INT*);
GpStatus WINGDIPAPI GdipMeasureCharacterRanges(GpGraphics*, GDIPCONST WCHAR*,
GpRegion**);
GpStatus WINGDIPAPI GdipReleaseDC(GpGraphics*,HDC);
+GpStatus WINGDIPAPI GdipResetWorldTransform(GpGraphics*);
GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics*,GraphicsState);
GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics*,REAL,GpMatrixOrder);
GpStatus WINGDIPAPI GdipSaveGraphics(GpGraphics*,GraphicsState*);
GpStatus WINGDIPAPI GdipAddPathLine2I(GpPath*,GDIPCONST GpPoint*,INT);
GpStatus WINGDIPAPI GdipAddPathLineI(GpPath*,INT,INT,INT,INT);
GpStatus WINGDIPAPI GdipAddPathPath(GpPath*,GDIPCONST GpPath*,BOOL);
+GpStatus WINGDIPAPI GdipAddPathPie(GpPath*,REAL,REAL,REAL,REAL,REAL,REAL);
+GpStatus WINGDIPAPI GdipAddPathPieI(GpPath*,INT,INT,INT,INT,REAL,REAL);
GpStatus WINGDIPAPI GdipAddPathPolygon(GpPath*,GDIPCONST GpPointF*,INT);
GpStatus WINGDIPAPI GdipAddPathPolygonI(GpPath*,GDIPCONST GpPoint*,INT);
GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath*,REAL,REAL,REAL,REAL);
GpFillMode,GpPath**);
GpStatus WINGDIPAPI GdipCreatePath2I(GDIPCONST GpPoint*,GDIPCONST BYTE*,INT,GpFillMode,GpPath**);
GpStatus WINGDIPAPI GdipDeletePath(GpPath*);
+GpStatus WINGDIPAPI GdipFlattenPath(GpPath*,GpMatrix*,REAL);
GpStatus WINGDIPAPI GdipGetPathData(GpPath*,GpPathData*);
GpStatus WINGDIPAPI GdipGetPathFillMode(GpPath*,GpFillMode*);
GpStatus WINGDIPAPI GdipGetPathLastPoint(GpPath*,GpPointF*);
GpStatus WINGDIPAPI GdipIsVisiblePathPoint(GpPath*,REAL,REAL,GpGraphics*,BOOL*);
GpStatus WINGDIPAPI GdipIsVisiblePathPointI(GpPath*,INT,INT,GpGraphics*,BOOL*);
GpStatus WINGDIPAPI GdipResetPath(GpPath*);
+GpStatus WINGDIPAPI GdipReversePath(GpPath*);
GpStatus WINGDIPAPI GdipSetPathFillMode(GpPath*,GpFillMode);
GpStatus WINGDIPAPI GdipStartPathFigure(GpPath*);
GpStatus WINGDIPAPI GdipTransformPath(GpPath*,GpMatrix*);
GpStatus WINGDIPAPI GdipPathIterCopyData(GpPathIterator*,INT*,GpPointF*,BYTE*,
INT,INT);
GpStatus WINGDIPAPI GdipPathIterNextMarker(GpPathIterator*,INT*,INT*,INT*);
+GpStatus WINGDIPAPI GdipPathIterNextMarkerPath(GpPathIterator*,INT*,GpPath*);
+GpStatus WINGDIPAPI GdipPathIterNextPathType(GpPathIterator*,INT*,BYTE*,INT*,INT*);
GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator*,INT*,INT*,INT*,BOOL*);
+GpStatus WINGDIPAPI GdipPathIterNextSubpathPath(GpPathIterator*,INT*,GpPath*,BOOL*);
GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator*);
GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator*,INT*);
GpStatus WINGDIPAPI GdipPathIterGetSubpathCount(GpPathIterator*,INT*);
GpStatus WINGDIPAPI GdipPathIterEnumerate(GpPathIterator*,INT*,GpPointF*,BYTE*,INT);
GpStatus WINGDIPAPI GdipPathIterHasCurve(GpPathIterator*,BOOL*);
+GpStatus WINGDIPAPI GdipPathIterIsValid(GpPathIterator*,BOOL*);
GpStatus WINGDIPAPI GdipCloneCustomLineCap(GpCustomLineCap*,GpCustomLineCap**);
GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath*,GpPath*,GpLineCap,REAL,
GpStatus WINGDIPAPI GdipDeleteFont(GpFont*);
GpStatus WINGDIPAPI GdipGetLogFontW(GpFont*,GpGraphics*,LOGFONTW*);
GpStatus WINGDIPAPI GdipCloneFont(GpFont*,GpFont**);
+GpStatus WINGDIPAPI GdipGetFamily(GpFont*, GpFontFamily**);
GpStatus WINGDIPAPI GdipGetFontUnit(GpFont*, Unit*);
GpStatus WINGDIPAPI GdipGetFontSize(GpFont*, REAL*);
+GpStatus WINGDIPAPI GdipGetFontStyle(GpFont*, INT*);
+GpStatus WINGDIPAPI GdipGetFontHeight(GDIPCONST GpFont*, GDIPCONST GpGraphics*,
+ REAL*);
GpStatus WINGDIPAPI GdipGetFontHeightGivenDPI(GDIPCONST GpFont*, REAL, REAL*);
GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR*,
GpStatus WINGDIPAPI GdipTranslateRegionI(GpRegion *, INT, INT);
GpStatus WINGDIPAPI GdipFlush(GpGraphics*, GpFlushIntention);
+GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpMetafile*,UINT);
+GpStatus WINGDIPAPI GdipSetClipRectI(GpGraphics*,INT,INT,INT,INT,CombineMode);
+GpStatus WINGDIPAPI GdipFillRegion(GpGraphics*,GpBrush*,GpRegion*);
+
+GpStatus WINGDIPAPI GdipCreateAdjustableArrowCap(REAL,REAL,BOOL,GpAdjustableArrowCap**);
+GpStatus WINGDIPAPI GdipGetAdjustableArrowCapFillState(GpAdjustableArrowCap*,BOOL*);
+GpStatus WINGDIPAPI GdipGetAdjustableArrowCapHeight(GpAdjustableArrowCap*,REAL*);
+GpStatus WINGDIPAPI GdipGetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap*,REAL*);
+GpStatus WINGDIPAPI GdipGetAdjustableArrowCapWidth(GpAdjustableArrowCap*,REAL*);
+GpStatus WINGDIPAPI GdipSetAdjustableArrowCapFillState(GpAdjustableArrowCap*,BOOL);
+GpStatus WINGDIPAPI GdipSetAdjustableArrowCapHeight(GpAdjustableArrowCap*,REAL);
+GpStatus WINGDIPAPI GdipSetAdjustableArrowCapMiddleInset(GpAdjustableArrowCap*,REAL);
+GpStatus WINGDIPAPI GdipSetAdjustableArrowCapWidth(GpAdjustableArrowCap*,REAL);
#ifdef __cplusplus
}
class GpMatrix {};
class GpPathIterator {};
class GpCustomLineCap {};
+class GpAdjustableArrowCap : public GpCustomLineCap {};
class GpImage {};
class GpMetafile : public GpImage {};
class GpImageAttributes {};
typedef struct GpMatrix GpMatrix;
typedef struct GpPathIterator GpPathIterator;
typedef struct GpCustomLineCap GpCustomLineCap;
+typedef struct GpAdjustableArrowCap GpAdjustableArrowCap;
typedef struct GpImage GpImage;
typedef struct GpMetafile GpMetafile;
typedef struct GpImageAttributes GpImageAttributes;