mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 06:35:42 +00:00
[GDIPLUS]
* Sync with Wine 1.7.17. CORE-8080 svn path=/trunk/; revision=62888
This commit is contained in:
parent
cceb6b9f47
commit
86c5b8463d
11 changed files with 1075 additions and 590 deletions
|
@ -756,8 +756,6 @@ GpStatus WINGDIPAPI GdipCreateTexture2(GpImage *image, GpWrapMode wrapmode,
|
|||
|
||||
/******************************************************************************
|
||||
* GdipCreateTextureIA [GDIPLUS.@]
|
||||
*
|
||||
* FIXME: imageattr ignored
|
||||
*/
|
||||
GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
|
||||
GDIPCONST GpImageAttributes *imageattr, REAL x, REAL y, REAL width,
|
||||
|
@ -855,6 +853,7 @@ GpStatus WINGDIPAPI GdipCreateTexture2I(GpImage *image, GpWrapMode wrapmode,
|
|||
imageattr->wrap = wrapmode;
|
||||
|
||||
stat = GdipCreateTextureIA(image, imageattr, x, y, width, height, texture);
|
||||
GdipDisposeImageAttributes(imageattr);
|
||||
}
|
||||
|
||||
return stat;
|
||||
|
|
|
@ -1112,15 +1112,39 @@ GpStatus WINGDIPAPI GdipDeletePrivateFontCollection(GpFontCollection **fontColle
|
|||
/*****************************************************************************
|
||||
* GdipPrivateAddFontFile [GDIPLUS.@]
|
||||
*/
|
||||
GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection* fontCollection,
|
||||
GDIPCONST WCHAR* filename)
|
||||
GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection *collection, GDIPCONST WCHAR *name)
|
||||
{
|
||||
FIXME("stub: %p, %s\n", fontCollection, debugstr_w(filename));
|
||||
HANDLE file, mapping;
|
||||
LARGE_INTEGER size;
|
||||
void *mem;
|
||||
GpStatus status;
|
||||
|
||||
if (!(fontCollection && filename))
|
||||
TRACE("%p, %s\n", collection, debugstr_w(name));
|
||||
|
||||
if (!collection || !name) return InvalidParameter;
|
||||
|
||||
file = CreateFileW(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE) return InvalidParameter;
|
||||
|
||||
if (!GetFileSizeEx(file, &size) || size.u.HighPart)
|
||||
{
|
||||
CloseHandle(file);
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
return NotImplemented;
|
||||
mapping = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
CloseHandle(file);
|
||||
if (!mapping) return InvalidParameter;
|
||||
|
||||
mem = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
|
||||
CloseHandle(mapping);
|
||||
if (!mem) return InvalidParameter;
|
||||
|
||||
/* GdipPrivateAddMemoryFont creates a copy of the memory block */
|
||||
status = GdipPrivateAddMemoryFont(collection, mem, size.u.LowPart);
|
||||
UnmapViewOfFile(mem);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#define TT_PLATFORM_APPLE_UNICODE 0
|
||||
|
|
|
@ -357,7 +357,7 @@ REAL units_scale(GpUnit from, GpUnit to, REAL dpi)
|
|||
}
|
||||
|
||||
/* Calculates Bezier points from cardinal spline points. */
|
||||
void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
|
||||
void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
|
||||
REAL *y1, REAL *x2, REAL *y2)
|
||||
{
|
||||
REAL xdiff, ydiff;
|
||||
|
@ -442,7 +442,7 @@ void delete_element(region_element* element)
|
|||
case RegionDataRect:
|
||||
break;
|
||||
case RegionDataPath:
|
||||
GdipDeletePath(element->elementdata.pathdata.path);
|
||||
GdipDeletePath(element->elementdata.path);
|
||||
break;
|
||||
case RegionDataEmptyRect:
|
||||
case RegionDataInfiniteRect:
|
||||
|
@ -456,13 +456,13 @@ void delete_element(region_element* element)
|
|||
}
|
||||
}
|
||||
|
||||
const char *debugstr_rectf(CONST RectF* rc)
|
||||
const char *debugstr_rectf(const RectF* rc)
|
||||
{
|
||||
if (!rc) return "(null)";
|
||||
return wine_dbg_sprintf("(%0.2f,%0.2f,%0.2f,%0.2f)", rc->X, rc->Y, rc->Width, rc->Height);
|
||||
}
|
||||
|
||||
const char *debugstr_pointf(CONST PointF* pt)
|
||||
const char *debugstr_pointf(const PointF* pt)
|
||||
{
|
||||
if (!pt) return "(null)";
|
||||
return wine_dbg_sprintf("(%0.2f,%0.2f)", pt->X, pt->Y);
|
||||
|
|
|
@ -65,10 +65,12 @@ extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLS
|
|||
extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result) DECLSPEC_HIDDEN;
|
||||
extern GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc) DECLSPEC_HIDDEN;
|
||||
extern GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc) DECLSPEC_HIDDEN;
|
||||
extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
|
||||
GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN;
|
||||
extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN;
|
||||
extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN;
|
||||
extern MetafileType METAFILE_GetEmfType(HENHMETAFILE hemf) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void calc_curve_bezier(CONST GpPointF *pts, REAL tension, REAL *x1,
|
||||
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1,
|
||||
REAL *y1, REAL *x2, REAL *y2) DECLSPEC_HIDDEN;
|
||||
extern void calc_curve_bezier_endp(REAL xend, REAL yend, REAL xadj, REAL yadj,
|
||||
REAL tension, REAL *x, REAL *y) DECLSPEC_HIDDEN;
|
||||
|
@ -122,9 +124,9 @@ static inline ARGB color_over(ARGB bg, ARGB fg)
|
|||
return (a<<24)|(r<<16)|(g<<8)|b;
|
||||
}
|
||||
|
||||
extern const char *debugstr_rectf(CONST RectF* rc) DECLSPEC_HIDDEN;
|
||||
extern const char *debugstr_rectf(const RectF* rc) DECLSPEC_HIDDEN;
|
||||
|
||||
extern const char *debugstr_pointf(CONST PointF* pt) DECLSPEC_HIDDEN;
|
||||
extern const char *debugstr_pointf(const PointF* pt) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height,
|
||||
BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride) DECLSPEC_HIDDEN;
|
||||
|
@ -304,8 +306,12 @@ struct GpMetafile{
|
|||
GpGraphics *playback_graphics;
|
||||
HDC playback_dc;
|
||||
GpPointF playback_points[3];
|
||||
GpRectF src_rect;
|
||||
HANDLETABLE *handle_table;
|
||||
int handle_count;
|
||||
GpMatrix *world_transform;
|
||||
GpUnit page_unit;
|
||||
REAL page_scale;
|
||||
};
|
||||
|
||||
struct GpBitmap{
|
||||
|
@ -412,17 +418,7 @@ struct region_element
|
|||
union
|
||||
{
|
||||
GpRectF rect;
|
||||
struct
|
||||
{
|
||||
GpPath* path;
|
||||
struct
|
||||
{
|
||||
DWORD size;
|
||||
DWORD magic;
|
||||
DWORD count;
|
||||
DWORD flags;
|
||||
} pathheader;
|
||||
} pathdata;
|
||||
GpPath *path;
|
||||
struct
|
||||
{
|
||||
struct region_element *left; /* the original region */
|
||||
|
@ -432,13 +428,7 @@ struct region_element
|
|||
};
|
||||
|
||||
struct GpRegion{
|
||||
struct
|
||||
{
|
||||
DWORD size;
|
||||
DWORD checksum;
|
||||
DWORD magic;
|
||||
DWORD num_children;
|
||||
} header;
|
||||
DWORD num_children;
|
||||
region_element node;
|
||||
};
|
||||
|
||||
|
|
|
@ -617,7 +617,7 @@ static ARGB transform_color(ARGB color, const ColorMatrix *matrix)
|
|||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
static int color_is_gray(ARGB color)
|
||||
static BOOL color_is_gray(ARGB color)
|
||||
{
|
||||
unsigned char r, g, b;
|
||||
|
||||
|
@ -940,12 +940,12 @@ static REAL intersect_line_scanline(const GpPointF *p1, const GpPointF *p2, REAL
|
|||
return (p1->X - p2->X) * (p2->Y - y) / (p2->Y - p1->Y) + p2->X;
|
||||
}
|
||||
|
||||
static INT brush_can_fill_path(GpBrush *brush)
|
||||
static BOOL brush_can_fill_path(GpBrush *brush)
|
||||
{
|
||||
switch (brush->bt)
|
||||
{
|
||||
case BrushTypeSolidColor:
|
||||
return 1;
|
||||
return TRUE;
|
||||
case BrushTypeHatchFill:
|
||||
{
|
||||
GpHatch *hatch = (GpHatch*)brush;
|
||||
|
@ -956,7 +956,7 @@ static INT brush_can_fill_path(GpBrush *brush)
|
|||
case BrushTypeTextureFill:
|
||||
/* Gdi32 isn't much help with these, so we should use brush_fill_pixels instead. */
|
||||
default:
|
||||
return 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1008,7 +1008,7 @@ static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
|
|||
}
|
||||
}
|
||||
|
||||
static INT brush_can_fill_pixels(GpBrush *brush)
|
||||
static BOOL brush_can_fill_pixels(GpBrush *brush)
|
||||
{
|
||||
switch (brush->bt)
|
||||
{
|
||||
|
@ -1017,9 +1017,9 @@ static INT brush_can_fill_pixels(GpBrush *brush)
|
|||
case BrushTypeLinearGradient:
|
||||
case BrushTypeTextureFill:
|
||||
case BrushTypePathGradient:
|
||||
return 1;
|
||||
return TRUE;
|
||||
default:
|
||||
return 0;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1239,7 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
|
|||
INT min_y, max_y, min_x, max_x;
|
||||
INT x, y;
|
||||
ARGB outer_color;
|
||||
static int transform_fixme_once;
|
||||
static BOOL transform_fixme_once;
|
||||
|
||||
if (fill->focus.X != 0.0 || fill->focus.Y != 0.0)
|
||||
{
|
||||
|
@ -1276,7 +1276,7 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
|
|||
if (!is_identity)
|
||||
{
|
||||
FIXME("path gradient transform not implemented\n");
|
||||
transform_fixme_once = 1;
|
||||
transform_fixme_once = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1310,7 +1310,7 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
|
|||
for (i=0; i<flat_path->pathdata.Count; i++)
|
||||
{
|
||||
int start_center_line=0, end_center_line=0;
|
||||
int seen_start=0, seen_end=0, seen_center=0;
|
||||
BOOL seen_start = FALSE, seen_end = FALSE, seen_center = FALSE;
|
||||
REAL center_distance;
|
||||
ARGB start_color, end_color;
|
||||
REAL dy, dx;
|
||||
|
@ -1370,17 +1370,17 @@ static GpStatus brush_fill_pixels(GpGraphics *graphics, GpBrush *brush,
|
|||
|
||||
if (!seen_start && yf >= start_point.Y)
|
||||
{
|
||||
seen_start = 1;
|
||||
seen_start = TRUE;
|
||||
start_center_line ^= 1;
|
||||
}
|
||||
if (!seen_end && yf >= end_point.Y)
|
||||
{
|
||||
seen_end = 1;
|
||||
seen_end = TRUE;
|
||||
end_center_line ^= 1;
|
||||
}
|
||||
if (!seen_center && yf >= center_point.Y)
|
||||
{
|
||||
seen_center = 1;
|
||||
seen_center = TRUE;
|
||||
start_center_line ^= 1;
|
||||
end_center_line ^= 1;
|
||||
}
|
||||
|
@ -2243,120 +2243,6 @@ GpStatus WINGDIPAPI GdipCreateFromHWNDICM(HWND hwnd, GpGraphics **graphics)
|
|||
return GdipCreateFromHWND(hwnd, graphics);
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromEmf(HENHMETAFILE hemf, BOOL delete,
|
||||
GpMetafile **metafile)
|
||||
{
|
||||
ENHMETAHEADER header;
|
||||
MetafileType metafile_type;
|
||||
|
||||
TRACE("(%p,%i,%p)\n", hemf, delete, metafile);
|
||||
|
||||
if(!hemf || !metafile)
|
||||
return InvalidParameter;
|
||||
|
||||
if (GetEnhMetaFileHeader(hemf, sizeof(header), &header) == 0)
|
||||
return GenericError;
|
||||
|
||||
metafile_type = METAFILE_GetEmfType(hemf);
|
||||
|
||||
if (metafile_type == MetafileTypeInvalid)
|
||||
return GenericError;
|
||||
|
||||
*metafile = GdipAlloc(sizeof(GpMetafile));
|
||||
if (!*metafile)
|
||||
return OutOfMemory;
|
||||
|
||||
(*metafile)->image.type = ImageTypeMetafile;
|
||||
(*metafile)->image.format = ImageFormatEMF;
|
||||
(*metafile)->image.frame_count = 1;
|
||||
(*metafile)->image.xres = (REAL)header.szlDevice.cx;
|
||||
(*metafile)->image.yres = (REAL)header.szlDevice.cy;
|
||||
(*metafile)->bounds.X = (REAL)header.rclBounds.left;
|
||||
(*metafile)->bounds.Y = (REAL)header.rclBounds.top;
|
||||
(*metafile)->bounds.Width = (REAL)(header.rclBounds.right - header.rclBounds.left);
|
||||
(*metafile)->bounds.Height = (REAL)(header.rclBounds.bottom - header.rclBounds.top);
|
||||
(*metafile)->unit = UnitPixel;
|
||||
(*metafile)->metafile_type = metafile_type;
|
||||
(*metafile)->hemf = hemf;
|
||||
(*metafile)->preserve_hemf = !delete;
|
||||
|
||||
TRACE("<-- %p\n", *metafile);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete,
|
||||
GDIPCONST WmfPlaceableFileHeader * placeable, GpMetafile **metafile)
|
||||
{
|
||||
UINT read;
|
||||
BYTE *copy;
|
||||
HENHMETAFILE hemf;
|
||||
GpStatus retval = Ok;
|
||||
|
||||
TRACE("(%p, %d, %p, %p)\n", hwmf, delete, placeable, metafile);
|
||||
|
||||
if(!hwmf || !metafile || !placeable)
|
||||
return InvalidParameter;
|
||||
|
||||
*metafile = NULL;
|
||||
read = GetMetaFileBitsEx(hwmf, 0, NULL);
|
||||
if(!read)
|
||||
return GenericError;
|
||||
copy = GdipAlloc(read);
|
||||
GetMetaFileBitsEx(hwmf, read, copy);
|
||||
|
||||
hemf = SetWinMetaFileBits(read, copy, NULL, NULL);
|
||||
GdipFree(copy);
|
||||
|
||||
/* FIXME: We should store and use hwmf instead of converting to hemf */
|
||||
retval = GdipCreateMetafileFromEmf(hemf, TRUE, metafile);
|
||||
|
||||
if (retval == Ok)
|
||||
{
|
||||
(*metafile)->image.xres = (REAL)placeable->Inch;
|
||||
(*metafile)->image.yres = (REAL)placeable->Inch;
|
||||
(*metafile)->bounds.X = ((REAL)placeable->BoundingBox.Left) / ((REAL)placeable->Inch);
|
||||
(*metafile)->bounds.Y = ((REAL)placeable->BoundingBox.Top) / ((REAL)placeable->Inch);
|
||||
(*metafile)->bounds.Width = (REAL)(placeable->BoundingBox.Right -
|
||||
placeable->BoundingBox.Left);
|
||||
(*metafile)->bounds.Height = (REAL)(placeable->BoundingBox.Bottom -
|
||||
placeable->BoundingBox.Top);
|
||||
(*metafile)->metafile_type = MetafileTypeWmfPlaceable;
|
||||
(*metafile)->image.format = ImageFormatWMF;
|
||||
|
||||
if (delete) DeleteMetaFile(hwmf);
|
||||
}
|
||||
else
|
||||
DeleteEnhMetaFile(hemf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromWmfFile(GDIPCONST WCHAR *file,
|
||||
GDIPCONST WmfPlaceableFileHeader * placeable, GpMetafile **metafile)
|
||||
{
|
||||
HMETAFILE hmf = GetMetaFileW(file);
|
||||
|
||||
TRACE("(%s, %p, %p)\n", debugstr_w(file), placeable, metafile);
|
||||
|
||||
if(!hmf) return InvalidParameter;
|
||||
|
||||
return GdipCreateMetafileFromWmf(hmf, TRUE, placeable, metafile);
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromFile(GDIPCONST WCHAR *file,
|
||||
GpMetafile **metafile)
|
||||
{
|
||||
FIXME("(%p, %p): stub\n", file, metafile);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromStream(IStream *stream,
|
||||
GpMetafile **metafile)
|
||||
{
|
||||
FIXME("(%p, %p): stub\n", stream, metafile);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateStreamOnFile(GDIPCONST WCHAR * filename,
|
||||
UINT access, IStream **stream)
|
||||
{
|
||||
|
@ -2405,6 +2291,12 @@ GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
|
|||
}
|
||||
|
||||
GdipDeleteRegion(graphics->clip);
|
||||
|
||||
/* Native returns ObjectBusy on the second free, instead of crashing as we'd
|
||||
* do otherwise, but we can't have that in the test suite because it means
|
||||
* accessing freed memory. */
|
||||
graphics->busy = TRUE;
|
||||
|
||||
GdipFree(graphics);
|
||||
|
||||
return Ok;
|
||||
|
@ -2885,9 +2777,33 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
debugstr_pointf(&points[2]));
|
||||
|
||||
memcpy(ptf, points, 3 * sizeof(GpPointF));
|
||||
|
||||
/* Ensure source width/height is positive */
|
||||
if (srcwidth < 0)
|
||||
{
|
||||
GpPointF tmp = ptf[1];
|
||||
srcx = srcx + srcwidth;
|
||||
srcwidth = -srcwidth;
|
||||
ptf[2].X = ptf[2].X + ptf[1].X - ptf[0].X;
|
||||
ptf[2].Y = ptf[2].Y + ptf[1].Y - ptf[0].Y;
|
||||
ptf[1] = ptf[0];
|
||||
ptf[0] = tmp;
|
||||
}
|
||||
|
||||
if (srcheight < 0)
|
||||
{
|
||||
GpPointF tmp = ptf[2];
|
||||
srcy = srcy + srcheight;
|
||||
srcheight = -srcheight;
|
||||
ptf[1].X = ptf[1].X + ptf[2].X - ptf[0].X;
|
||||
ptf[1].Y = ptf[1].Y + ptf[2].Y - ptf[0].Y;
|
||||
ptf[2] = ptf[0];
|
||||
ptf[0] = tmp;
|
||||
}
|
||||
|
||||
ptf[3].X = ptf[2].X + ptf[1].X - ptf[0].X;
|
||||
ptf[3].Y = ptf[2].Y + ptf[1].Y - ptf[0].Y;
|
||||
if (!srcwidth || !srcheight || ptf[3].X == ptf[0].X || ptf[3].Y == ptf[0].Y)
|
||||
if (!srcwidth || !srcheight || (ptf[3].X == ptf[0].X && ptf[3].Y == ptf[0].Y))
|
||||
return Ok;
|
||||
transform_and_round_points(graphics, pti, ptf, 4);
|
||||
|
||||
|
@ -2919,7 +2835,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
else if (image->type == ImageTypeBitmap)
|
||||
{
|
||||
GpBitmap* bitmap = (GpBitmap*)image;
|
||||
int use_software=0;
|
||||
BOOL use_software = FALSE;
|
||||
|
||||
TRACE("graphics: %.2fx%.2f dpi, fmt %#x, scale %f, image: %.2fx%.2f dpi, fmt %#x, color %08x\n",
|
||||
graphics->xres, graphics->yres,
|
||||
|
@ -2933,11 +2849,12 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
ptf[1].X - ptf[0].X != srcwidth || ptf[2].Y - ptf[0].Y != srcheight ||
|
||||
srcx < 0 || srcy < 0 ||
|
||||
srcx + srcwidth > bitmap->width || srcy + srcheight > bitmap->height)
|
||||
use_software = 1;
|
||||
use_software = TRUE;
|
||||
|
||||
if (use_software)
|
||||
{
|
||||
RECT dst_area;
|
||||
GpRectF graphics_bounds;
|
||||
GpRect src_area;
|
||||
int i, x, y, src_stride, dst_stride;
|
||||
GpMatrix dst_to_src;
|
||||
|
@ -2963,8 +2880,18 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
if (dst_area.bottom < pti[i].y) dst_area.bottom = pti[i].y;
|
||||
}
|
||||
|
||||
stat = get_graphics_bounds(graphics, &graphics_bounds);
|
||||
if (stat != Ok) return stat;
|
||||
|
||||
if (graphics_bounds.X > dst_area.left) dst_area.left = floorf(graphics_bounds.X);
|
||||
if (graphics_bounds.Y > dst_area.top) dst_area.top = floorf(graphics_bounds.Y);
|
||||
if (graphics_bounds.X + graphics_bounds.Width < dst_area.right) dst_area.right = ceilf(graphics_bounds.X + graphics_bounds.Width);
|
||||
if (graphics_bounds.Y + graphics_bounds.Height < dst_area.bottom) dst_area.bottom = ceilf(graphics_bounds.Y + graphics_bounds.Height);
|
||||
|
||||
TRACE("dst_area: %s\n", wine_dbgstr_rect(&dst_area));
|
||||
|
||||
if (IsRectEmpty(&dst_area)) return Ok;
|
||||
|
||||
m11 = (ptf[1].X - ptf[0].X) / srcwidth;
|
||||
m21 = (ptf[2].X - ptf[0].X) / srcheight;
|
||||
mdx = ptf[0].X - m11 * srcx - m21 * srcy;
|
||||
|
@ -3010,8 +2937,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
|
||||
if (stat != Ok)
|
||||
{
|
||||
if (src_data != dst_data)
|
||||
GdipFree(src_data);
|
||||
GdipFree(src_data);
|
||||
GdipFree(dst_data);
|
||||
return stat;
|
||||
}
|
||||
|
@ -3060,7 +2986,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
else
|
||||
{
|
||||
HDC hdc;
|
||||
int temp_hdc=0, temp_bitmap=0;
|
||||
BOOL temp_hdc = FALSE, temp_bitmap = FALSE;
|
||||
HBITMAP hbitmap, old_hbm=NULL;
|
||||
|
||||
if (!(bitmap->format == PixelFormat16bppRGB555 ||
|
||||
|
@ -3074,8 +3000,8 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
|
||||
/* we can't draw a bitmap of this format directly */
|
||||
hdc = CreateCompatibleDC(0);
|
||||
temp_hdc = 1;
|
||||
temp_bitmap = 1;
|
||||
temp_hdc = TRUE;
|
||||
temp_bitmap = TRUE;
|
||||
|
||||
bih.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bih.biWidth = bitmap->width;
|
||||
|
@ -3109,7 +3035,7 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
|
|||
else
|
||||
{
|
||||
GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
|
||||
temp_bitmap = 1;
|
||||
temp_bitmap = TRUE;
|
||||
}
|
||||
|
||||
hdc = bitmap->hdc;
|
||||
|
@ -3338,6 +3264,7 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
|
|||
{
|
||||
INT save_state;
|
||||
GpStatus retval;
|
||||
HRGN hrgn=NULL;
|
||||
|
||||
TRACE("(%p, %p, %p)\n", graphics, pen, path);
|
||||
|
||||
|
@ -3355,10 +3282,20 @@ GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path)
|
|||
|
||||
save_state = prepare_dc(graphics, pen);
|
||||
|
||||
retval = get_clip_hrgn(graphics, &hrgn);
|
||||
|
||||
if (retval != Ok)
|
||||
goto end;
|
||||
|
||||
if (hrgn)
|
||||
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
|
||||
|
||||
retval = draw_poly(graphics, pen, path->pathdata.Points,
|
||||
path->pathdata.Types, path->pathdata.Count, TRUE);
|
||||
|
||||
end:
|
||||
restore_dc(graphics, save_state);
|
||||
DeleteObject(hrgn);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -3603,6 +3540,7 @@ static GpStatus GDI32_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath
|
|||
{
|
||||
INT save_state;
|
||||
GpStatus retval;
|
||||
HRGN hrgn=NULL;
|
||||
|
||||
if(!graphics->hdc || !brush_can_fill_path(brush))
|
||||
return NotImplemented;
|
||||
|
@ -3612,6 +3550,14 @@ static GpStatus GDI32_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath
|
|||
SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE
|
||||
: WINDING));
|
||||
|
||||
retval = get_clip_hrgn(graphics, &hrgn);
|
||||
|
||||
if (retval != Ok)
|
||||
goto end;
|
||||
|
||||
if (hrgn)
|
||||
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
|
||||
|
||||
BeginPath(graphics->hdc);
|
||||
retval = draw_poly(graphics, NULL, path->pathdata.Points,
|
||||
path->pathdata.Types, path->pathdata.Count, FALSE);
|
||||
|
@ -3626,6 +3572,7 @@ static GpStatus GDI32_GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath
|
|||
|
||||
end:
|
||||
RestoreDC(graphics->hdc, save_state);
|
||||
DeleteObject(hrgn);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -3795,38 +3742,31 @@ GpStatus WINGDIPAPI GdipFillPolygon2I(GpGraphics *graphics, GpBrush *brush,
|
|||
GpStatus WINGDIPAPI GdipFillRectangle(GpGraphics *graphics, GpBrush *brush,
|
||||
REAL x, REAL y, REAL width, REAL height)
|
||||
{
|
||||
GpStatus stat;
|
||||
GpPath *path;
|
||||
GpRectF rect;
|
||||
|
||||
TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, brush, x, y, width, height);
|
||||
|
||||
if(!graphics || !brush)
|
||||
return InvalidParameter;
|
||||
rect.X = x;
|
||||
rect.Y = y;
|
||||
rect.Width = width;
|
||||
rect.Height = height;
|
||||
|
||||
if(graphics->busy)
|
||||
return ObjectBusy;
|
||||
|
||||
stat = GdipCreatePath(FillModeAlternate, &path);
|
||||
|
||||
if (stat == Ok)
|
||||
{
|
||||
stat = GdipAddPathRectangle(path, x, y, width, height);
|
||||
|
||||
if (stat == Ok)
|
||||
stat = GdipFillPath(graphics, brush, path);
|
||||
|
||||
GdipDeletePath(path);
|
||||
}
|
||||
|
||||
return stat;
|
||||
return GdipFillRectangles(graphics, brush, &rect, 1);
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipFillRectangleI(GpGraphics *graphics, GpBrush *brush,
|
||||
INT x, INT y, INT width, INT height)
|
||||
{
|
||||
GpRectF rect;
|
||||
|
||||
TRACE("(%p, %p, %d, %d, %d, %d)\n", graphics, brush, x, y, width, height);
|
||||
|
||||
return GdipFillRectangle(graphics, brush, x, y, width, height);
|
||||
rect.X = (REAL)x;
|
||||
rect.Y = (REAL)y;
|
||||
rect.Width = (REAL)width;
|
||||
rect.Height = (REAL)height;
|
||||
|
||||
return GdipFillRectangles(graphics, brush, &rect, 1);
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipFillRectangles(GpGraphics *graphics, GpBrush *brush, GDIPCONST GpRectF *rects,
|
||||
|
@ -3837,9 +3777,16 @@ GpStatus WINGDIPAPI GdipFillRectangles(GpGraphics *graphics, GpBrush *brush, GDI
|
|||
|
||||
TRACE("(%p, %p, %p, %d)\n", graphics, brush, rects, count);
|
||||
|
||||
if(!rects)
|
||||
if(!graphics || !brush || !rects || count <= 0)
|
||||
return InvalidParameter;
|
||||
|
||||
if (graphics->image && graphics->image->type == ImageTypeMetafile)
|
||||
{
|
||||
status = METAFILE_FillRectangles((GpMetafile*)graphics->image, brush, rects, count);
|
||||
/* FIXME: Add gdi32 drawing. */
|
||||
return status;
|
||||
}
|
||||
|
||||
status = GdipCreatePath(FillModeAlternate, &path);
|
||||
if (status != Ok) return status;
|
||||
|
||||
|
@ -4440,13 +4387,25 @@ GpStatus gdip_format_string(HDC hdc,
|
|||
INT *hotkeyprefix_offsets=NULL;
|
||||
INT hotkeyprefix_count=0;
|
||||
INT hotkeyprefix_pos=0, hotkeyprefix_end_pos=0;
|
||||
int seen_prefix=0;
|
||||
BOOL seen_prefix = FALSE;
|
||||
GpStringFormat *dyn_format=NULL;
|
||||
|
||||
if(length == -1) length = lstrlenW(string);
|
||||
|
||||
stringdup = GdipAlloc((length + 1) * sizeof(WCHAR));
|
||||
if(!stringdup) return OutOfMemory;
|
||||
|
||||
if (!format)
|
||||
{
|
||||
stat = GdipStringFormatGetGenericDefault(&dyn_format);
|
||||
if (stat != Ok)
|
||||
{
|
||||
GdipFree(stringdup);
|
||||
return stat;
|
||||
}
|
||||
format = dyn_format;
|
||||
}
|
||||
|
||||
nwidth = rect->Width;
|
||||
nheight = rect->Height;
|
||||
if (ignore_empty_clip)
|
||||
|
@ -4455,10 +4414,7 @@ GpStatus gdip_format_string(HDC hdc,
|
|||
if (!nheight) nheight = INT_MAX;
|
||||
}
|
||||
|
||||
if (format)
|
||||
hkprefix = format->hkprefix;
|
||||
else
|
||||
hkprefix = HotkeyPrefixNone;
|
||||
hkprefix = format->hkprefix;
|
||||
|
||||
if (hkprefix == HotkeyPrefixShow)
|
||||
{
|
||||
|
@ -4487,11 +4443,11 @@ GpStatus gdip_format_string(HDC hdc,
|
|||
hotkeyprefix_offsets[hotkeyprefix_count++] = j;
|
||||
else if (!seen_prefix && hkprefix != HotkeyPrefixNone && string[i] == '&')
|
||||
{
|
||||
seen_prefix = 1;
|
||||
seen_prefix = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
seen_prefix = 0;
|
||||
seen_prefix = FALSE;
|
||||
|
||||
stringdup[j] = string[i];
|
||||
j++;
|
||||
|
@ -4499,8 +4455,7 @@ GpStatus gdip_format_string(HDC hdc,
|
|||
|
||||
length = j;
|
||||
|
||||
if (format) halign = format->align;
|
||||
else halign = StringAlignmentNear;
|
||||
halign = format->align;
|
||||
|
||||
while(sum < length){
|
||||
GetTextExtentExPointW(hdc, stringdup + sum, length - sum,
|
||||
|
@ -4547,7 +4502,11 @@ GpStatus gdip_format_string(HDC hdc,
|
|||
bounds.Width = size.cx;
|
||||
|
||||
if(height + size.cy > nheight)
|
||||
{
|
||||
if (format->attr & StringFormatFlagsLineLimit)
|
||||
break;
|
||||
bounds.Height = nheight - (height + size.cy);
|
||||
}
|
||||
else
|
||||
bounds.Height = size.cy;
|
||||
|
||||
|
@ -4589,13 +4548,13 @@ GpStatus gdip_format_string(HDC hdc,
|
|||
break;
|
||||
|
||||
/* Stop if this was a linewrap (but not if it was a linebreak). */
|
||||
if ((lret == fitcpy) && format &&
|
||||
(format->attr & (StringFormatFlagsNoWrap | StringFormatFlagsLineLimit)))
|
||||
if ((lret == fitcpy) && (format->attr & StringFormatFlagsNoWrap))
|
||||
break;
|
||||
}
|
||||
|
||||
GdipFree(stringdup);
|
||||
GdipFree(hotkeyprefix_offsets);
|
||||
GdipDeleteStringFormat(dyn_format);
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
@ -5239,6 +5198,8 @@ GpStatus WINGDIPAPI GdipSetInterpolationMode(GpGraphics *graphics,
|
|||
|
||||
GpStatus WINGDIPAPI GdipSetPageScale(GpGraphics *graphics, REAL scale)
|
||||
{
|
||||
GpStatus stat;
|
||||
|
||||
TRACE("(%p, %.2f)\n", graphics, scale);
|
||||
|
||||
if(!graphics || (scale <= 0.0))
|
||||
|
@ -5247,6 +5208,13 @@ GpStatus WINGDIPAPI GdipSetPageScale(GpGraphics *graphics, REAL scale)
|
|||
if(graphics->busy)
|
||||
return ObjectBusy;
|
||||
|
||||
if (graphics->image && graphics->image->type == ImageTypeMetafile)
|
||||
{
|
||||
stat = METAFILE_SetPageTransform((GpMetafile*)graphics->image, graphics->unit, scale);
|
||||
if (stat != Ok)
|
||||
return stat;
|
||||
}
|
||||
|
||||
graphics->scale = scale;
|
||||
|
||||
return Ok;
|
||||
|
@ -5254,6 +5222,8 @@ GpStatus WINGDIPAPI GdipSetPageScale(GpGraphics *graphics, REAL scale)
|
|||
|
||||
GpStatus WINGDIPAPI GdipSetPageUnit(GpGraphics *graphics, GpUnit unit)
|
||||
{
|
||||
GpStatus stat;
|
||||
|
||||
TRACE("(%p, %d)\n", graphics, unit);
|
||||
|
||||
if(!graphics)
|
||||
|
@ -5265,6 +5235,13 @@ GpStatus WINGDIPAPI GdipSetPageUnit(GpGraphics *graphics, GpUnit unit)
|
|||
if(unit == UnitWorld)
|
||||
return InvalidParameter;
|
||||
|
||||
if (graphics->image && graphics->image->type == ImageTypeMetafile)
|
||||
{
|
||||
stat = METAFILE_SetPageTransform((GpMetafile*)graphics->image, unit, graphics->scale);
|
||||
if (stat != Ok)
|
||||
return stat;
|
||||
}
|
||||
|
||||
graphics->unit = unit;
|
||||
|
||||
return Ok;
|
||||
|
@ -5528,19 +5505,6 @@ GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region,
|
|||
return status;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpMetafile *metafile,
|
||||
UINT limitDpi)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%p,%u)\n", metafile, limitDpi);
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipDrawPolygon(GpGraphics *graphics,GpPen *pen,GDIPCONST GpPointF *points,
|
||||
INT count)
|
||||
{
|
||||
|
@ -6204,15 +6168,18 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
|
|||
if (glyphsize > max_glyphsize)
|
||||
max_glyphsize = glyphsize;
|
||||
|
||||
left = pti[i].x + glyphmetrics.gmptGlyphOrigin.x;
|
||||
top = pti[i].y - glyphmetrics.gmptGlyphOrigin.y;
|
||||
right = pti[i].x + glyphmetrics.gmptGlyphOrigin.x + glyphmetrics.gmBlackBoxX;
|
||||
bottom = pti[i].y - glyphmetrics.gmptGlyphOrigin.y + glyphmetrics.gmBlackBoxY;
|
||||
if (glyphsize != 0)
|
||||
{
|
||||
left = pti[i].x + glyphmetrics.gmptGlyphOrigin.x;
|
||||
top = pti[i].y - glyphmetrics.gmptGlyphOrigin.y;
|
||||
right = pti[i].x + glyphmetrics.gmptGlyphOrigin.x + glyphmetrics.gmBlackBoxX;
|
||||
bottom = pti[i].y - glyphmetrics.gmptGlyphOrigin.y + glyphmetrics.gmBlackBoxY;
|
||||
|
||||
if (left < min_x) min_x = left;
|
||||
if (top < min_y) min_y = top;
|
||||
if (right > max_x) max_x = right;
|
||||
if (bottom > max_y) max_y = bottom;
|
||||
if (left < min_x) min_x = left;
|
||||
if (top < min_y) min_y = top;
|
||||
if (right > max_x) max_x = right;
|
||||
if (bottom > max_y) max_y = bottom;
|
||||
}
|
||||
|
||||
if (i+1 < length && (flags & DriverStringOptionsRealizedAdvance) == DriverStringOptionsRealizedAdvance)
|
||||
{
|
||||
|
@ -6221,6 +6188,10 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
|
|||
}
|
||||
}
|
||||
|
||||
if (max_glyphsize == 0)
|
||||
/* Nothing to draw. */
|
||||
return Ok;
|
||||
|
||||
glyph_mask = GdipAlloc(max_glyphsize);
|
||||
text_mask = GdipAlloc((max_x - min_x) * (max_y - min_y));
|
||||
text_mask_stride = max_x - min_x;
|
||||
|
@ -6238,11 +6209,15 @@ static GpStatus SOFTWARE_GdipDrawDriverString(GpGraphics *graphics, GDIPCONST UI
|
|||
/* Generate a mask for the text */
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
DWORD ret;
|
||||
int left, top, stride;
|
||||
|
||||
GetGlyphOutlineW(hdc, text[i], ggo_flags,
|
||||
ret = GetGlyphOutlineW(hdc, text[i], ggo_flags,
|
||||
&glyphmetrics, max_glyphsize, glyph_mask, &identity);
|
||||
|
||||
if (ret == GDI_ERROR || ret == 0)
|
||||
continue; /* empty glyph */
|
||||
|
||||
left = pti[i].x + glyphmetrics.gmptGlyphOrigin.x;
|
||||
top = pti[i].y - glyphmetrics.gmptGlyphOrigin.y;
|
||||
stride = (glyphmetrics.gmBlackBoxX + 3) & (~3);
|
||||
|
|
|
@ -854,7 +854,7 @@ static GpStatus format_string_callback(HDC dc,
|
|||
for (i = index; i < length; ++i)
|
||||
{
|
||||
GLYPHMETRICS gm;
|
||||
TTPOLYGONHEADER *ph = NULL;
|
||||
TTPOLYGONHEADER *ph = NULL, *origph;
|
||||
char *start;
|
||||
DWORD len, ofs = 0;
|
||||
len = GetGlyphOutlineW(dc, string[i], GGO_BEZIER, &gm, 0, NULL, &identity);
|
||||
|
@ -863,7 +863,7 @@ static GpStatus format_string_callback(HDC dc,
|
|||
status = GenericError;
|
||||
break;
|
||||
}
|
||||
ph = GdipAlloc(len);
|
||||
origph = ph = GdipAlloc(len);
|
||||
start = (char *)ph;
|
||||
if (!ph || !lengthen_path(path, len / sizeof(POINTFX)))
|
||||
{
|
||||
|
@ -917,7 +917,7 @@ static GpStatus format_string_callback(HDC dc,
|
|||
x += gm.gmCellIncX * args->scale;
|
||||
y += gm.gmCellIncY * args->scale;
|
||||
|
||||
GdipFree(ph);
|
||||
GdipFree(origph);
|
||||
if (status != Ok)
|
||||
break;
|
||||
}
|
||||
|
@ -1837,8 +1837,9 @@ static void widen_cap(const GpPointF *endpoint, const GpPointF *nextpoint,
|
|||
}
|
||||
}
|
||||
|
||||
static void widen_open_figure(GpPath *path, GpPen *pen, int start, int end,
|
||||
path_list_node_t **last_point)
|
||||
static void widen_open_figure(const GpPointF *points, GpPen *pen, int start, int end,
|
||||
GpLineCap start_cap, GpCustomLineCap *start_custom, GpLineCap end_cap,
|
||||
GpCustomLineCap *end_custom, path_list_node_t **last_point)
|
||||
{
|
||||
int i;
|
||||
path_list_node_t *prev_point;
|
||||
|
@ -1848,22 +1849,22 @@ static void widen_open_figure(GpPath *path, GpPen *pen, int start, int end,
|
|||
|
||||
prev_point = *last_point;
|
||||
|
||||
widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
|
||||
pen, pen->startcap, pen->customstart, FALSE, TRUE, last_point);
|
||||
widen_cap(&points[start], &points[start+1],
|
||||
pen, start_cap, start_custom, FALSE, TRUE, last_point);
|
||||
|
||||
for (i=start+1; i<end; i++)
|
||||
widen_joint(&path->pathdata.Points[i-1], &path->pathdata.Points[i],
|
||||
&path->pathdata.Points[i+1], pen, last_point);
|
||||
widen_joint(&points[i-1], &points[i],
|
||||
&points[i+1], pen, last_point);
|
||||
|
||||
widen_cap(&path->pathdata.Points[end], &path->pathdata.Points[end-1],
|
||||
pen, pen->endcap, pen->customend, TRUE, TRUE, last_point);
|
||||
widen_cap(&points[end], &points[end-1],
|
||||
pen, end_cap, end_custom, TRUE, TRUE, last_point);
|
||||
|
||||
for (i=end-1; i>start; i--)
|
||||
widen_joint(&path->pathdata.Points[i+1], &path->pathdata.Points[i],
|
||||
&path->pathdata.Points[i-1], pen, last_point);
|
||||
widen_joint(&points[i+1], &points[i],
|
||||
&points[i-1], pen, last_point);
|
||||
|
||||
widen_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1],
|
||||
pen, pen->startcap, pen->customstart, TRUE, FALSE, last_point);
|
||||
widen_cap(&points[start], &points[start+1],
|
||||
pen, start_cap, start_custom, TRUE, FALSE, last_point);
|
||||
|
||||
prev_point->next->type = PathPointTypeStart;
|
||||
(*last_point)->type |= PathPointTypeCloseSubpath;
|
||||
|
@ -1911,6 +1912,134 @@ static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end,
|
|||
(*last_point)->type |= PathPointTypeCloseSubpath;
|
||||
}
|
||||
|
||||
static void widen_dashed_figure(GpPath *path, GpPen *pen, int start, int end,
|
||||
int closed, path_list_node_t **last_point)
|
||||
{
|
||||
int i, j;
|
||||
REAL dash_pos=0.0;
|
||||
int dash_index=0;
|
||||
const REAL *dash_pattern;
|
||||
int dash_count;
|
||||
GpPointF *tmp_points;
|
||||
REAL segment_dy;
|
||||
REAL segment_dx;
|
||||
REAL segment_length;
|
||||
REAL segment_pos;
|
||||
int num_tmp_points=0;
|
||||
int draw_start_cap=0;
|
||||
static const REAL dash_dot_dot[6] = { 3.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
|
||||
|
||||
if (end <= start)
|
||||
return;
|
||||
|
||||
switch (pen->dash)
|
||||
{
|
||||
case DashStyleDash:
|
||||
default:
|
||||
dash_pattern = dash_dot_dot;
|
||||
dash_count = 2;
|
||||
break;
|
||||
case DashStyleDot:
|
||||
dash_pattern = &dash_dot_dot[2];
|
||||
dash_count = 2;
|
||||
break;
|
||||
case DashStyleDashDot:
|
||||
dash_pattern = dash_dot_dot;
|
||||
dash_count = 4;
|
||||
break;
|
||||
case DashStyleDashDotDot:
|
||||
dash_pattern = dash_dot_dot;
|
||||
dash_count = 6;
|
||||
break;
|
||||
case DashStyleCustom:
|
||||
dash_pattern = pen->dashes;
|
||||
dash_count = pen->numdashes;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp_points = GdipAlloc((end - start + 2) * sizeof(GpPoint));
|
||||
if (!tmp_points) return; /* FIXME */
|
||||
|
||||
if (!closed)
|
||||
draw_start_cap = 1;
|
||||
|
||||
for (j=start; j <= end; j++)
|
||||
{
|
||||
if (j == start)
|
||||
{
|
||||
if (closed)
|
||||
i = end;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
i = j-1;
|
||||
|
||||
segment_dy = path->pathdata.Points[j].Y - path->pathdata.Points[i].Y;
|
||||
segment_dx = path->pathdata.Points[j].X - path->pathdata.Points[i].X;
|
||||
segment_length = sqrtf(segment_dy*segment_dy + segment_dx*segment_dx);
|
||||
segment_pos = 0.0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (dash_pos == 0.0)
|
||||
{
|
||||
if ((dash_index % 2) == 0)
|
||||
{
|
||||
/* start dash */
|
||||
num_tmp_points = 1;
|
||||
tmp_points[0].X = path->pathdata.Points[i].X + segment_dx * segment_pos / segment_length;
|
||||
tmp_points[0].Y = path->pathdata.Points[i].Y + segment_dy * segment_pos / segment_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* end dash */
|
||||
tmp_points[num_tmp_points].X = path->pathdata.Points[i].X + segment_dx * segment_pos / segment_length;
|
||||
tmp_points[num_tmp_points].Y = path->pathdata.Points[i].Y + segment_dy * segment_pos / segment_length;
|
||||
|
||||
widen_open_figure(tmp_points, pen, 0, num_tmp_points,
|
||||
draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart,
|
||||
LineCapFlat, NULL, last_point);
|
||||
draw_start_cap = 0;
|
||||
num_tmp_points = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dash_pattern[dash_index] - dash_pos > segment_length - segment_pos)
|
||||
{
|
||||
/* advance to next segment */
|
||||
if ((dash_index % 2) == 0)
|
||||
{
|
||||
tmp_points[num_tmp_points] = path->pathdata.Points[j];
|
||||
num_tmp_points++;
|
||||
}
|
||||
dash_pos += segment_length - segment_pos;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* advance to next dash in pattern */
|
||||
segment_pos += dash_pattern[dash_index] - dash_pos;
|
||||
dash_pos = 0.0;
|
||||
if (++dash_index == dash_count)
|
||||
dash_index = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dash_index % 2 == 0 && num_tmp_points != 0)
|
||||
{
|
||||
/* last dash overflows last segment */
|
||||
tmp_points[num_tmp_points] = path->pathdata.Points[end];
|
||||
widen_open_figure(tmp_points, pen, 0, num_tmp_points,
|
||||
draw_start_cap ? pen->startcap : LineCapFlat, pen->customstart,
|
||||
closed ? LineCapFlat : pen->endcap, pen->customend, last_point);
|
||||
}
|
||||
|
||||
GdipFree(tmp_points);
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
|
||||
REAL flatness)
|
||||
{
|
||||
|
@ -1952,9 +2081,6 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
|
|||
if (pen->join == LineJoinRound)
|
||||
FIXME("unimplemented line join %d\n", pen->join);
|
||||
|
||||
if (pen->dash != DashStyleSolid)
|
||||
FIXME("unimplemented dash style %d\n", pen->dash);
|
||||
|
||||
if (pen->align != PenAlignmentCenter)
|
||||
FIXME("unimplemented pen alignment %d\n", pen->align);
|
||||
|
||||
|
@ -1967,12 +2093,18 @@ GpStatus WINGDIPAPI GdipWidenPath(GpPath *path, GpPen *pen, GpMatrix *matrix,
|
|||
|
||||
if ((type&PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath)
|
||||
{
|
||||
widen_closed_figure(flat_path, pen, subpath_start, i, &last_point);
|
||||
if (pen->dash != DashStyleSolid)
|
||||
widen_dashed_figure(flat_path, pen, subpath_start, i, 1, &last_point);
|
||||
else
|
||||
widen_closed_figure(flat_path, pen, subpath_start, i, &last_point);
|
||||
}
|
||||
else if (i == flat_path->pathdata.Count-1 ||
|
||||
(flat_path->pathdata.Types[i+1]&PathPointTypePathTypeMask) == PathPointTypeStart)
|
||||
{
|
||||
widen_open_figure(flat_path, pen, subpath_start, i, &last_point);
|
||||
if (pen->dash != DashStyleSolid)
|
||||
widen_dashed_figure(flat_path, pen, subpath_start, i, 0, &last_point);
|
||||
else
|
||||
widen_open_figure(flat_path->pathdata.Points, pen, subpath_start, i, pen->startcap, pen->customstart, pen->endcap, pen->customend, &last_point);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1105,12 +1105,12 @@ GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap* bitmap, GDIPCONST GpRect* rect,
|
|||
|
||||
if (flags & ImageLockModeRead)
|
||||
{
|
||||
static int fixme=0;
|
||||
static BOOL fixme = FALSE;
|
||||
|
||||
if (!fixme && (PIXELFORMATBPP(bitmap->format) * act_rect.X) % 8 != 0)
|
||||
{
|
||||
FIXME("Cannot copy rows that don't start at a whole byte.\n");
|
||||
fixme = 1;
|
||||
fixme = TRUE;
|
||||
}
|
||||
|
||||
stat = convert_pixels(act_rect.Width, act_rect.Height,
|
||||
|
@ -1152,7 +1152,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
|
|||
BitmapData* lockeddata)
|
||||
{
|
||||
GpStatus stat;
|
||||
static int fixme=0;
|
||||
static BOOL fixme = FALSE;
|
||||
|
||||
TRACE("(%p,%p)\n", bitmap, lockeddata);
|
||||
|
||||
|
@ -1182,7 +1182,7 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
|
|||
if (!fixme && (PIXELFORMATBPP(bitmap->format) * bitmap->lockx) % 8 != 0)
|
||||
{
|
||||
FIXME("Cannot copy rows that don't start at a whole byte.\n");
|
||||
fixme = 1;
|
||||
fixme = TRUE;
|
||||
}
|
||||
|
||||
stat = convert_pixels(lockeddata->Width, lockeddata->Height,
|
||||
|
@ -1207,9 +1207,6 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
|
|||
GpStatus WINGDIPAPI GdipCloneBitmapArea(REAL x, REAL y, REAL width, REAL height,
|
||||
PixelFormat format, GpBitmap* srcBitmap, GpBitmap** dstBitmap)
|
||||
{
|
||||
BitmapData lockeddata_src, lockeddata_dst;
|
||||
int i;
|
||||
UINT row_size;
|
||||
Rect area;
|
||||
GpStatus stat;
|
||||
|
||||
|
@ -1231,39 +1228,41 @@ GpStatus WINGDIPAPI GdipCloneBitmapArea(REAL x, REAL y, REAL width, REAL height,
|
|||
area.Width = gdip_round(width);
|
||||
area.Height = gdip_round(height);
|
||||
|
||||
stat = GdipBitmapLockBits(srcBitmap, &area, ImageLockModeRead, format,
|
||||
&lockeddata_src);
|
||||
if (stat != Ok) return stat;
|
||||
|
||||
stat = GdipCreateBitmapFromScan0(lockeddata_src.Width, lockeddata_src.Height,
|
||||
0, lockeddata_src.PixelFormat, NULL, dstBitmap);
|
||||
stat = GdipCreateBitmapFromScan0(area.Width, area.Height, 0, format, NULL, dstBitmap);
|
||||
if (stat == Ok)
|
||||
{
|
||||
stat = GdipBitmapLockBits(*dstBitmap, NULL, ImageLockModeWrite,
|
||||
lockeddata_src.PixelFormat, &lockeddata_dst);
|
||||
stat = convert_pixels(area.Width, area.Height, (*dstBitmap)->stride, (*dstBitmap)->bits, (*dstBitmap)->format,
|
||||
srcBitmap->stride,
|
||||
srcBitmap->bits + srcBitmap->stride * area.Y + PIXELFORMATBPP(srcBitmap->format) * area.X / 8,
|
||||
srcBitmap->format, srcBitmap->image.palette);
|
||||
|
||||
if (stat == Ok)
|
||||
if (stat == Ok && srcBitmap->image.palette)
|
||||
{
|
||||
/* copy the image data */
|
||||
row_size = (lockeddata_src.Width * PIXELFORMATBPP(lockeddata_src.PixelFormat) +7)/8;
|
||||
for (i=0; i<lockeddata_src.Height; i++)
|
||||
memcpy((BYTE*)lockeddata_dst.Scan0+lockeddata_dst.Stride*i,
|
||||
(BYTE*)lockeddata_src.Scan0+lockeddata_src.Stride*i,
|
||||
row_size);
|
||||
ColorPalette *src_palette, *dst_palette;
|
||||
|
||||
GdipBitmapUnlockBits(*dstBitmap, &lockeddata_dst);
|
||||
src_palette = srcBitmap->image.palette;
|
||||
|
||||
dst_palette = GdipAlloc(sizeof(UINT) * 2 + sizeof(ARGB) * src_palette->Count);
|
||||
|
||||
if (dst_palette)
|
||||
{
|
||||
dst_palette->Flags = src_palette->Flags;
|
||||
dst_palette->Count = src_palette->Count;
|
||||
memcpy(dst_palette->Entries, src_palette->Entries, sizeof(ARGB) * src_palette->Count);
|
||||
|
||||
GdipFree((*dstBitmap)->image.palette);
|
||||
(*dstBitmap)->image.palette = dst_palette;
|
||||
}
|
||||
else
|
||||
stat = OutOfMemory;
|
||||
}
|
||||
|
||||
if (stat != Ok)
|
||||
GdipDisposeImage((GpImage*)*dstBitmap);
|
||||
}
|
||||
|
||||
GdipBitmapUnlockBits(srcBitmap, &lockeddata_src);
|
||||
|
||||
if (stat != Ok)
|
||||
{
|
||||
*dstBitmap = NULL;
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
@ -1318,47 +1317,10 @@ GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
|
|||
}
|
||||
else if (image->type == ImageTypeBitmap)
|
||||
{
|
||||
GpBitmap *bitmap = (GpBitmap*)image;
|
||||
BitmapData lockeddata_src, lockeddata_dst;
|
||||
int i;
|
||||
UINT row_size;
|
||||
GpBitmap *bitmap = (GpBitmap *)image;
|
||||
|
||||
stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format,
|
||||
&lockeddata_src);
|
||||
if (stat != Ok) return stat;
|
||||
|
||||
stat = GdipCreateBitmapFromScan0(lockeddata_src.Width, lockeddata_src.Height,
|
||||
0, lockeddata_src.PixelFormat, NULL, (GpBitmap**)cloneImage);
|
||||
if (stat == Ok)
|
||||
{
|
||||
stat = GdipBitmapLockBits((GpBitmap*)*cloneImage, NULL, ImageLockModeWrite,
|
||||
lockeddata_src.PixelFormat, &lockeddata_dst);
|
||||
|
||||
if (stat == Ok)
|
||||
{
|
||||
/* copy the image data */
|
||||
row_size = (lockeddata_src.Width * PIXELFORMATBPP(lockeddata_src.PixelFormat) +7)/8;
|
||||
for (i=0; i<lockeddata_src.Height; i++)
|
||||
memcpy((BYTE*)lockeddata_dst.Scan0+lockeddata_dst.Stride*i,
|
||||
(BYTE*)lockeddata_src.Scan0+lockeddata_src.Stride*i,
|
||||
row_size);
|
||||
|
||||
GdipBitmapUnlockBits((GpBitmap*)*cloneImage, &lockeddata_dst);
|
||||
}
|
||||
|
||||
if (stat != Ok)
|
||||
GdipDisposeImage(*cloneImage);
|
||||
}
|
||||
|
||||
GdipBitmapUnlockBits(bitmap, &lockeddata_src);
|
||||
|
||||
if (stat != Ok)
|
||||
{
|
||||
*cloneImage = NULL;
|
||||
}
|
||||
else memcpy(&(*cloneImage)->format, &image->format, sizeof(GUID));
|
||||
|
||||
return stat;
|
||||
return GdipCloneBitmapAreaI(0, 0, bitmap->width, bitmap->height,
|
||||
bitmap->format, bitmap, (GpBitmap **)cloneImage);
|
||||
}
|
||||
else if (image->type == ImageTypeMetafile && ((GpMetafile*)image)->hemf)
|
||||
{
|
||||
|
@ -1557,27 +1519,6 @@ GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap,
|
|||
return stat;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipConvertToEmfPlus(const GpGraphics* ref,
|
||||
GpMetafile* metafile, BOOL* succ, EmfType emfType,
|
||||
const WCHAR* description, GpMetafile** out_metafile)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%p,%p,%p,%u,%s,%p)\n", ref, metafile, succ, emfType,
|
||||
debugstr_w(description), out_metafile);
|
||||
|
||||
if(!ref || !metafile || !out_metafile)
|
||||
return InvalidParameter;
|
||||
|
||||
*succ = FALSE;
|
||||
*out_metafile = NULL;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT width, INT height,
|
||||
GpGraphics* target, GpBitmap** bitmap)
|
||||
{
|
||||
|
@ -1799,7 +1740,6 @@ static GpStatus get_screen_resolution(REAL *xres, REAL *yres)
|
|||
GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
||||
PixelFormat format, BYTE* scan0, GpBitmap** bitmap)
|
||||
{
|
||||
BITMAPINFO* pbmi;
|
||||
HBITMAP hbitmap=NULL;
|
||||
INT row_size, dib_stride;
|
||||
BYTE *bits=NULL, *own_bits=NULL;
|
||||
|
@ -1829,9 +1769,8 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
|||
|
||||
if (format & PixelFormatGDI && !(format & (PixelFormatAlpha|PixelFormatIndexed)) && !scan0)
|
||||
{
|
||||
pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
||||
if (!pbmi)
|
||||
return OutOfMemory;
|
||||
char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
|
||||
BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
|
||||
|
||||
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
pbmi->bmiHeader.biWidth = width;
|
||||
|
@ -1848,8 +1787,6 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
|
|||
|
||||
hbitmap = CreateDIBSection(0, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
|
||||
|
||||
GdipFree(pbmi);
|
||||
|
||||
if (!hbitmap) return GenericError;
|
||||
|
||||
stride = dib_stride;
|
||||
|
@ -2072,13 +2009,6 @@ GpStatus WINGDIPAPI GdipDrawCachedBitmap(GpGraphics *graphics,
|
|||
return GdipDrawImage(graphics, cachedbmp->image, (REAL)x, (REAL)y);
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipEmfToWmfBits(HENHMETAFILE hemf, UINT cbData16,
|
||||
LPBYTE pData16, INT iMapMode, INT eFlags)
|
||||
{
|
||||
FIXME("(%p, %d, %p, %d, %d): stub\n", hemf, cbData16, pData16, iMapMode, eFlags);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
/* Internal utility function: Replace the image data of dst with that of src,
|
||||
* and free src. */
|
||||
static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
|
||||
|
@ -2423,76 +2353,6 @@ GpStatus WINGDIPAPI GdipGetImageWidth(GpImage *image, UINT *width)
|
|||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetMetafileHeaderFromMetafile(GpMetafile * metafile,
|
||||
MetafileHeader * header)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%p, %p)\n", metafile, header);
|
||||
|
||||
if(!metafile || !header)
|
||||
return InvalidParameter;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
memset(header, 0, sizeof(MetafileHeader));
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetMetafileHeaderFromEmf(HENHMETAFILE hEmf,
|
||||
MetafileHeader *header)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
if(!hEmf || !header)
|
||||
return InvalidParameter;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
memset(header, 0, sizeof(MetafileHeader));
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetMetafileHeaderFromFile(GDIPCONST WCHAR *filename,
|
||||
MetafileHeader *header)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%s,%p)\n", debugstr_w(filename), header);
|
||||
|
||||
if(!filename || !header)
|
||||
return InvalidParameter;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
memset(header, 0, sizeof(MetafileHeader));
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetMetafileHeaderFromStream(IStream *stream,
|
||||
MetafileHeader *header)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%p,%p)\n", stream, header);
|
||||
|
||||
if(!stream || !header)
|
||||
return InvalidParameter;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
memset(header, 0, sizeof(MetafileHeader));
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetPropertyCount(GpImage *image, UINT *num)
|
||||
{
|
||||
TRACE("(%p, %p)\n", image, num);
|
||||
|
@ -3989,6 +3849,7 @@ static GpStatus encode_image_WIC(GpImage *image, IStream* stream,
|
|||
HRESULT hr;
|
||||
UINT width, height;
|
||||
PixelFormat gdipformat=0;
|
||||
const WICPixelFormatGUID *desired_wicformat;
|
||||
WICPixelFormatGUID wicformat;
|
||||
GpRect rc;
|
||||
BitmapData lockeddata;
|
||||
|
@ -4041,20 +3902,40 @@ static GpStatus encode_image_WIC(GpImage *image, IStream* stream,
|
|||
{
|
||||
if (pixel_formats[i].gdip_format == bitmap->format)
|
||||
{
|
||||
memcpy(&wicformat, pixel_formats[i].wic_format, sizeof(GUID));
|
||||
desired_wicformat = pixel_formats[i].wic_format;
|
||||
gdipformat = bitmap->format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!gdipformat)
|
||||
{
|
||||
memcpy(&wicformat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
|
||||
desired_wicformat = &GUID_WICPixelFormat32bppBGRA;
|
||||
gdipformat = PixelFormat32bppARGB;
|
||||
}
|
||||
|
||||
memcpy(&wicformat, desired_wicformat, sizeof(GUID));
|
||||
hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &wicformat);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && !IsEqualGUID(desired_wicformat, &wicformat))
|
||||
{
|
||||
/* Encoder doesn't support this bitmap's format. */
|
||||
gdipformat = 0;
|
||||
for (i=0; pixel_formats[i].wic_format; i++)
|
||||
{
|
||||
if (IsEqualGUID(&wicformat, pixel_formats[i].wic_format))
|
||||
{
|
||||
gdipformat = pixel_formats[i].gdip_format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!gdipformat)
|
||||
{
|
||||
ERR("Cannot support encoder format %s\n", debugstr_guid(&wicformat));
|
||||
hr = E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
stat = GdipBitmapLockBits(bitmap, &rc, ImageLockModeRead, gdipformat,
|
||||
|
@ -4652,28 +4533,21 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi
|
|||
if (retval == Ok)
|
||||
{
|
||||
HDC hdc;
|
||||
BITMAPINFO *pbmi;
|
||||
char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
|
||||
BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
|
||||
INT src_height;
|
||||
|
||||
hdc = CreateCompatibleDC(NULL);
|
||||
pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
|
||||
|
||||
if (pbmi)
|
||||
{
|
||||
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
pbmi->bmiHeader.biBitCount = 0;
|
||||
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
pbmi->bmiHeader.biBitCount = 0;
|
||||
|
||||
GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
|
||||
GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
|
||||
|
||||
src_height = abs(pbmi->bmiHeader.biHeight);
|
||||
pbmi->bmiHeader.biHeight = -src_height;
|
||||
src_height = abs(pbmi->bmiHeader.biHeight);
|
||||
pbmi->bmiHeader.biHeight = -src_height;
|
||||
|
||||
GetDIBits(hdc, hbm, 0, src_height, lockeddata.Scan0, pbmi, DIB_RGB_COLORS);
|
||||
|
||||
GdipFree(pbmi);
|
||||
}
|
||||
else
|
||||
retval = OutOfMemory;
|
||||
GetDIBits(hdc, hbm, 0, src_height, lockeddata.Scan0, pbmi, DIB_RGB_COLORS);
|
||||
|
||||
DeleteDC(hdc);
|
||||
|
||||
|
@ -4781,27 +4655,6 @@ GpStatus WINGDIPAPI GdipTestControl(GpTestControlEnum control, void *param)
|
|||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipRecordMetafileFileName(GDIPCONST WCHAR* fileName,
|
||||
HDC hdc, EmfType type, GDIPCONST GpRectF *pFrameRect,
|
||||
MetafileFrameUnit frameUnit, GDIPCONST WCHAR *desc,
|
||||
GpMetafile **metafile)
|
||||
{
|
||||
FIXME("%s %p %d %p %d %s %p stub!\n", debugstr_w(fileName), hdc, type, pFrameRect,
|
||||
frameUnit, debugstr_w(desc), metafile);
|
||||
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipRecordMetafileFileNameI(GDIPCONST WCHAR* fileName, HDC hdc, EmfType type,
|
||||
GDIPCONST GpRect *pFrameRect, MetafileFrameUnit frameUnit,
|
||||
GDIPCONST WCHAR *desc, GpMetafile **metafile)
|
||||
{
|
||||
FIXME("%s %p %d %p %d %s %p stub!\n", debugstr_w(fileName), hdc, type, pFrameRect,
|
||||
frameUnit, debugstr_w(desc), metafile);
|
||||
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipImageForceValidation(GpImage *image)
|
||||
{
|
||||
TRACE("%p\n", image);
|
||||
|
@ -4866,7 +4719,7 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
|
|||
GpBitmap *new_bitmap;
|
||||
GpBitmap *bitmap;
|
||||
int bpp, bytesperpixel;
|
||||
int rotate_90, flip_x, flip_y;
|
||||
BOOL rotate_90, flip_x, flip_y;
|
||||
int src_x_offset, src_y_offset;
|
||||
LPBYTE src_origin;
|
||||
UINT x, y, width, height;
|
||||
|
@ -4975,16 +4828,3 @@ GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
|
|||
|
||||
return stat;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* GdipConvertToEmfPlusToFile [GDIPLUS.@]
|
||||
*/
|
||||
|
||||
GpStatus WINGDIPAPI GdipConvertToEmfPlusToFile(const GpGraphics* refGraphics,
|
||||
GpMetafile* metafile, BOOL* conversionSuccess,
|
||||
const WCHAR* filename, EmfType emfType,
|
||||
const WCHAR* description, GpMetafile** out_metafile)
|
||||
{
|
||||
FIXME("stub: %p, %p, %p, %p, %u, %p, %p\n", refGraphics, metafile, conversionSuccess, filename, emfType, description, out_metafile);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,27 @@ typedef struct EmfPlusHeader
|
|||
DWORD LogicalDpiY;
|
||||
} EmfPlusHeader;
|
||||
|
||||
typedef struct EmfPlusFillRects
|
||||
{
|
||||
EmfPlusRecordHeader Header;
|
||||
DWORD BrushID;
|
||||
DWORD Count;
|
||||
} EmfPlusFillRects;
|
||||
|
||||
typedef struct EmfPlusSetPageTransform
|
||||
{
|
||||
EmfPlusRecordHeader Header;
|
||||
REAL PageScale;
|
||||
} EmfPlusSetPageTransform;
|
||||
|
||||
typedef struct EmfPlusRect
|
||||
{
|
||||
SHORT X;
|
||||
SHORT Y;
|
||||
SHORT Width;
|
||||
SHORT Height;
|
||||
} EmfPlusRect;
|
||||
|
||||
static GpStatus METAFILE_AllocateRecord(GpMetafile *metafile, DWORD size, void **result)
|
||||
{
|
||||
DWORD size_needed;
|
||||
|
@ -211,6 +232,8 @@ GpStatus WINGDIPAPI GdipRecordMetafile(HDC hdc, EmfType type, GDIPCONST GpRectF
|
|||
(*metafile)->image.picture = NULL;
|
||||
(*metafile)->image.flags = ImageFlagsNone;
|
||||
(*metafile)->image.palette = NULL;
|
||||
(*metafile)->image.xres = 72.0;
|
||||
(*metafile)->image.yres = 72.0;
|
||||
(*metafile)->bounds = *frameRect;
|
||||
(*metafile)->unit = frameUnit;
|
||||
(*metafile)->metafile_type = type;
|
||||
|
@ -267,7 +290,11 @@ GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result)
|
|||
stat = graphics_from_image((GpImage*)metafile, &metafile->record_graphics);
|
||||
|
||||
if (stat == Ok)
|
||||
{
|
||||
*result = metafile->record_graphics;
|
||||
metafile->record_graphics->xres = 96.0;
|
||||
metafile->record_graphics->yres = 96.0;
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
@ -294,6 +321,108 @@ GpStatus METAFILE_GetDC(GpMetafile* metafile, HDC *hdc)
|
|||
return Ok;
|
||||
}
|
||||
|
||||
static BOOL is_integer_rect(const GpRectF *rect)
|
||||
{
|
||||
SHORT x, y, width, height;
|
||||
x = rect->X;
|
||||
y = rect->Y;
|
||||
width = rect->Width;
|
||||
height = rect->Height;
|
||||
if (rect->X != (REAL)x || rect->Y != (REAL)y ||
|
||||
rect->Width != (REAL)width || rect->Height != (REAL)height)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush,
|
||||
GDIPCONST GpRectF* rects, INT count)
|
||||
{
|
||||
if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
|
||||
{
|
||||
EmfPlusFillRects *record;
|
||||
GpStatus stat;
|
||||
BOOL integer_rects = TRUE;
|
||||
int i;
|
||||
DWORD brushid;
|
||||
int flags = 0;
|
||||
|
||||
if (brush->bt == BrushTypeSolidColor)
|
||||
{
|
||||
flags |= 0x8000;
|
||||
brushid = ((GpSolidFill*)brush)->color;
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("brush serialization not implemented\n");
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
if (!is_integer_rect(&rects[i]))
|
||||
{
|
||||
integer_rects = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (integer_rects)
|
||||
flags |= 0x4000;
|
||||
|
||||
stat = METAFILE_AllocateRecord(metafile,
|
||||
sizeof(EmfPlusFillRects) + count * (integer_rects ? sizeof(EmfPlusRect) : sizeof(GpRectF)),
|
||||
(void**)&record);
|
||||
if (stat != Ok)
|
||||
return stat;
|
||||
|
||||
record->Header.Type = EmfPlusRecordTypeFillRects;
|
||||
record->Header.Flags = flags;
|
||||
record->BrushID = brushid;
|
||||
record->Count = count;
|
||||
|
||||
if (integer_rects)
|
||||
{
|
||||
EmfPlusRect *record_rects = (EmfPlusRect*)(record+1);
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
record_rects[i].X = (SHORT)rects[i].X;
|
||||
record_rects[i].Y = (SHORT)rects[i].Y;
|
||||
record_rects[i].Width = (SHORT)rects[i].Width;
|
||||
record_rects[i].Height = (SHORT)rects[i].Height;
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(record+1, rects, sizeof(GpRectF) * count);
|
||||
|
||||
METAFILE_WriteRecords(metafile);
|
||||
}
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale)
|
||||
{
|
||||
if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual)
|
||||
{
|
||||
EmfPlusSetPageTransform *record;
|
||||
GpStatus stat;
|
||||
|
||||
stat = METAFILE_AllocateRecord(metafile,
|
||||
sizeof(EmfPlusSetPageTransform),
|
||||
(void**)&record);
|
||||
if (stat != Ok)
|
||||
return stat;
|
||||
|
||||
record->Header.Type = EmfPlusRecordTypeSetPageTransform;
|
||||
record->Header.Flags = unit;
|
||||
record->PageScale = scale;
|
||||
|
||||
METAFILE_WriteRecords(metafile);
|
||||
}
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus METAFILE_ReleaseDC(GpMetafile* metafile, HDC hdc)
|
||||
{
|
||||
if (hdc != metafile->record_dc)
|
||||
|
@ -368,9 +497,40 @@ static void METAFILE_PlaybackReleaseDC(GpMetafile *metafile)
|
|||
}
|
||||
}
|
||||
|
||||
static GpStatus METAFILE_PlaybackUpdateWorldTransform(GpMetafile *metafile)
|
||||
{
|
||||
GpMatrix *real_transform;
|
||||
GpStatus stat;
|
||||
|
||||
stat = GdipCreateMatrix3(&metafile->src_rect, metafile->playback_points, &real_transform);
|
||||
|
||||
if (stat == Ok)
|
||||
{
|
||||
REAL scale = units_to_pixels(1.0, metafile->page_unit, 96.0);
|
||||
|
||||
if (metafile->page_unit != UnitDisplay)
|
||||
scale *= metafile->page_scale;
|
||||
|
||||
stat = GdipScaleMatrix(real_transform, scale, scale, MatrixOrderPrepend);
|
||||
|
||||
if (stat == Ok)
|
||||
stat = GdipMultiplyMatrix(real_transform, metafile->world_transform, MatrixOrderPrepend);
|
||||
|
||||
if (stat == Ok)
|
||||
stat = GdipSetWorldTransform(metafile->playback_graphics, real_transform);
|
||||
|
||||
GdipDeleteMatrix(real_transform);
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
|
||||
EmfPlusRecordType recordType, UINT flags, UINT dataSize, GDIPCONST BYTE *data)
|
||||
{
|
||||
GpStatus stat;
|
||||
GpMetafile *real_metafile = (GpMetafile*)metafile;
|
||||
|
||||
TRACE("(%p,%x,%x,%d,%p)\n", metafile, recordType, flags, dataSize, data);
|
||||
|
||||
if (!metafile || (dataSize && !data) || !metafile->playback_graphics)
|
||||
|
@ -402,6 +562,8 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
|
|||
}
|
||||
else
|
||||
{
|
||||
EmfPlusRecordHeader *header = (EmfPlusRecordHeader*)(data)-1;
|
||||
|
||||
METAFILE_PlaybackReleaseDC((GpMetafile*)metafile);
|
||||
|
||||
switch(recordType)
|
||||
|
@ -412,6 +574,85 @@ GpStatus WINGDIPAPI GdipPlayMetafileRecord(GDIPCONST GpMetafile *metafile,
|
|||
case EmfPlusRecordTypeGetDC:
|
||||
METAFILE_PlaybackGetDC((GpMetafile*)metafile);
|
||||
break;
|
||||
case EmfPlusRecordTypeFillRects:
|
||||
{
|
||||
EmfPlusFillRects *record = (EmfPlusFillRects*)header;
|
||||
GpBrush *brush, *temp_brush=NULL;
|
||||
GpRectF *rects, *temp_rects=NULL;
|
||||
|
||||
if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusFillRects))
|
||||
return InvalidParameter;
|
||||
|
||||
if (flags & 0x4000)
|
||||
{
|
||||
if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusFillRects) + sizeof(EmfPlusRect) * record->Count)
|
||||
return InvalidParameter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusFillRects) + sizeof(GpRectF) * record->Count)
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
if (flags & 0x8000)
|
||||
{
|
||||
stat = GdipCreateSolidFill((ARGB)record->BrushID, (GpSolidFill**)&temp_brush);
|
||||
brush = temp_brush;
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("brush deserialization not implemented\n");
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
if (stat == Ok)
|
||||
{
|
||||
if (flags & 0x4000)
|
||||
{
|
||||
EmfPlusRect *int_rects = (EmfPlusRect*)(record+1);
|
||||
int i;
|
||||
|
||||
rects = temp_rects = GdipAlloc(sizeof(GpRectF) * record->Count);
|
||||
if (rects)
|
||||
{
|
||||
for (i=0; i<record->Count; i++)
|
||||
{
|
||||
rects[i].X = int_rects[i].X;
|
||||
rects[i].Y = int_rects[i].Y;
|
||||
rects[i].Width = int_rects[i].Width;
|
||||
rects[i].Height = int_rects[i].Height;
|
||||
}
|
||||
}
|
||||
else
|
||||
stat = OutOfMemory;
|
||||
}
|
||||
else
|
||||
rects = (GpRectF*)(record+1);
|
||||
}
|
||||
|
||||
if (stat == Ok)
|
||||
{
|
||||
stat = GdipFillRectangles(metafile->playback_graphics, brush, rects, record->Count);
|
||||
}
|
||||
|
||||
GdipDeleteBrush(temp_brush);
|
||||
GdipFree(temp_rects);
|
||||
|
||||
return stat;
|
||||
}
|
||||
case EmfPlusRecordTypeSetPageTransform:
|
||||
{
|
||||
EmfPlusSetPageTransform *record = (EmfPlusSetPageTransform*)header;
|
||||
GpUnit unit = (GpUnit)flags;
|
||||
|
||||
if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusSetPageTransform))
|
||||
return InvalidParameter;
|
||||
|
||||
real_metafile->page_unit = unit;
|
||||
real_metafile->page_scale = record->PageScale;
|
||||
|
||||
return METAFILE_PlaybackUpdateWorldTransform(real_metafile);
|
||||
}
|
||||
default:
|
||||
FIXME("Not implemented for record type %x\n", recordType);
|
||||
return NotImplemented;
|
||||
|
@ -486,6 +727,7 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
|
|||
struct enum_metafile_data data;
|
||||
GpStatus stat;
|
||||
GpMetafile *real_metafile = (GpMetafile*)metafile; /* whoever made this const was joking */
|
||||
GraphicsContainer state;
|
||||
|
||||
TRACE("(%p,%p,%p,%i,%p,%i,%p,%p,%p)\n", graphics, metafile,
|
||||
destPoints, count, srcRect, srcUnit, callback, callbackData,
|
||||
|
@ -510,19 +752,46 @@ GpStatus WINGDIPAPI GdipEnumerateMetafileSrcRectDestPoints(GpGraphics *graphics,
|
|||
|
||||
real_metafile->playback_graphics = graphics;
|
||||
real_metafile->playback_dc = NULL;
|
||||
real_metafile->src_rect = *srcRect;
|
||||
|
||||
memcpy(real_metafile->playback_points, destPoints, sizeof(PointF) * 3);
|
||||
stat = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, real_metafile->playback_points, 3);
|
||||
|
||||
if (stat == Ok && (metafile->metafile_type == MetafileTypeEmf ||
|
||||
metafile->metafile_type == MetafileTypeWmfPlaceable ||
|
||||
metafile->metafile_type == MetafileTypeWmf))
|
||||
stat = METAFILE_PlaybackGetDC((GpMetafile*)metafile);
|
||||
if (stat == Ok)
|
||||
stat = GdipBeginContainer2(graphics, &state);
|
||||
|
||||
if (stat == Ok)
|
||||
EnumEnhMetaFile(0, metafile->hemf, enum_metafile_proc, &data, NULL);
|
||||
{
|
||||
stat = GdipSetPageScale(graphics, 1.0);
|
||||
|
||||
METAFILE_PlaybackReleaseDC((GpMetafile*)metafile);
|
||||
if (stat == Ok)
|
||||
stat = GdipSetPageUnit(graphics, UnitPixel);
|
||||
|
||||
if (stat == Ok)
|
||||
stat = GdipCreateMatrix(&real_metafile->world_transform);
|
||||
|
||||
if (stat == Ok)
|
||||
{
|
||||
real_metafile->page_unit = UnitDisplay;
|
||||
real_metafile->page_scale = 1.0;
|
||||
stat = METAFILE_PlaybackUpdateWorldTransform(real_metafile);
|
||||
}
|
||||
|
||||
if (stat == Ok && (metafile->metafile_type == MetafileTypeEmf ||
|
||||
metafile->metafile_type == MetafileTypeWmfPlaceable ||
|
||||
metafile->metafile_type == MetafileTypeWmf))
|
||||
stat = METAFILE_PlaybackGetDC(real_metafile);
|
||||
|
||||
if (stat == Ok)
|
||||
EnumEnhMetaFile(0, metafile->hemf, enum_metafile_proc, &data, NULL);
|
||||
|
||||
METAFILE_PlaybackReleaseDC(real_metafile);
|
||||
|
||||
GdipDeleteMatrix(real_metafile->world_transform);
|
||||
real_metafile->world_transform = NULL;
|
||||
|
||||
GdipEndContainer(graphics, state);
|
||||
}
|
||||
|
||||
real_metafile->playback_graphics = NULL;
|
||||
|
||||
|
@ -623,9 +892,268 @@ static int CALLBACK get_metafile_type_proc(HDC hDC, HANDLETABLE *lpHTable, const
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
MetafileType METAFILE_GetEmfType(HENHMETAFILE hemf)
|
||||
static MetafileType METAFILE_GetEmfType(HENHMETAFILE hemf)
|
||||
{
|
||||
MetafileType result = MetafileTypeInvalid;
|
||||
EnumEnhMetaFile(NULL, hemf, get_metafile_type_proc, &result, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetMetafileHeaderFromMetafile(GpMetafile * metafile,
|
||||
MetafileHeader * header)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%p, %p)\n", metafile, header);
|
||||
|
||||
if(!metafile || !header)
|
||||
return InvalidParameter;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
memset(header, 0, sizeof(MetafileHeader));
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetMetafileHeaderFromEmf(HENHMETAFILE hEmf,
|
||||
MetafileHeader *header)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
if(!hEmf || !header)
|
||||
return InvalidParameter;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
memset(header, 0, sizeof(MetafileHeader));
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetMetafileHeaderFromFile(GDIPCONST WCHAR *filename,
|
||||
MetafileHeader *header)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%s,%p)\n", debugstr_w(filename), header);
|
||||
|
||||
if(!filename || !header)
|
||||
return InvalidParameter;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
memset(header, 0, sizeof(MetafileHeader));
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipGetMetafileHeaderFromStream(IStream *stream,
|
||||
MetafileHeader *header)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%p,%p)\n", stream, header);
|
||||
|
||||
if(!stream || !header)
|
||||
return InvalidParameter;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
memset(header, 0, sizeof(MetafileHeader));
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromEmf(HENHMETAFILE hemf, BOOL delete,
|
||||
GpMetafile **metafile)
|
||||
{
|
||||
ENHMETAHEADER header;
|
||||
MetafileType metafile_type;
|
||||
|
||||
TRACE("(%p,%i,%p)\n", hemf, delete, metafile);
|
||||
|
||||
if(!hemf || !metafile)
|
||||
return InvalidParameter;
|
||||
|
||||
if (GetEnhMetaFileHeader(hemf, sizeof(header), &header) == 0)
|
||||
return GenericError;
|
||||
|
||||
metafile_type = METAFILE_GetEmfType(hemf);
|
||||
|
||||
if (metafile_type == MetafileTypeInvalid)
|
||||
return GenericError;
|
||||
|
||||
*metafile = GdipAlloc(sizeof(GpMetafile));
|
||||
if (!*metafile)
|
||||
return OutOfMemory;
|
||||
|
||||
(*metafile)->image.type = ImageTypeMetafile;
|
||||
(*metafile)->image.format = ImageFormatEMF;
|
||||
(*metafile)->image.frame_count = 1;
|
||||
(*metafile)->image.xres = (REAL)header.szlDevice.cx;
|
||||
(*metafile)->image.yres = (REAL)header.szlDevice.cy;
|
||||
(*metafile)->bounds.X = (REAL)header.rclBounds.left;
|
||||
(*metafile)->bounds.Y = (REAL)header.rclBounds.top;
|
||||
(*metafile)->bounds.Width = (REAL)(header.rclBounds.right - header.rclBounds.left);
|
||||
(*metafile)->bounds.Height = (REAL)(header.rclBounds.bottom - header.rclBounds.top);
|
||||
(*metafile)->unit = UnitPixel;
|
||||
(*metafile)->metafile_type = metafile_type;
|
||||
(*metafile)->hemf = hemf;
|
||||
(*metafile)->preserve_hemf = !delete;
|
||||
|
||||
TRACE("<-- %p\n", *metafile);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete,
|
||||
GDIPCONST WmfPlaceableFileHeader * placeable, GpMetafile **metafile)
|
||||
{
|
||||
UINT read;
|
||||
BYTE *copy;
|
||||
HENHMETAFILE hemf;
|
||||
GpStatus retval = Ok;
|
||||
|
||||
TRACE("(%p, %d, %p, %p)\n", hwmf, delete, placeable, metafile);
|
||||
|
||||
if(!hwmf || !metafile || !placeable)
|
||||
return InvalidParameter;
|
||||
|
||||
*metafile = NULL;
|
||||
read = GetMetaFileBitsEx(hwmf, 0, NULL);
|
||||
if(!read)
|
||||
return GenericError;
|
||||
copy = GdipAlloc(read);
|
||||
GetMetaFileBitsEx(hwmf, read, copy);
|
||||
|
||||
hemf = SetWinMetaFileBits(read, copy, NULL, NULL);
|
||||
GdipFree(copy);
|
||||
|
||||
/* FIXME: We should store and use hwmf instead of converting to hemf */
|
||||
retval = GdipCreateMetafileFromEmf(hemf, TRUE, metafile);
|
||||
|
||||
if (retval == Ok)
|
||||
{
|
||||
(*metafile)->image.xres = (REAL)placeable->Inch;
|
||||
(*metafile)->image.yres = (REAL)placeable->Inch;
|
||||
(*metafile)->bounds.X = ((REAL)placeable->BoundingBox.Left) / ((REAL)placeable->Inch);
|
||||
(*metafile)->bounds.Y = ((REAL)placeable->BoundingBox.Top) / ((REAL)placeable->Inch);
|
||||
(*metafile)->bounds.Width = (REAL)(placeable->BoundingBox.Right -
|
||||
placeable->BoundingBox.Left);
|
||||
(*metafile)->bounds.Height = (REAL)(placeable->BoundingBox.Bottom -
|
||||
placeable->BoundingBox.Top);
|
||||
(*metafile)->metafile_type = MetafileTypeWmfPlaceable;
|
||||
(*metafile)->image.format = ImageFormatWMF;
|
||||
|
||||
if (delete) DeleteMetaFile(hwmf);
|
||||
}
|
||||
else
|
||||
DeleteEnhMetaFile(hemf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromWmfFile(GDIPCONST WCHAR *file,
|
||||
GDIPCONST WmfPlaceableFileHeader * placeable, GpMetafile **metafile)
|
||||
{
|
||||
HMETAFILE hmf = GetMetaFileW(file);
|
||||
|
||||
TRACE("(%s, %p, %p)\n", debugstr_w(file), placeable, metafile);
|
||||
|
||||
if(!hmf) return InvalidParameter;
|
||||
|
||||
return GdipCreateMetafileFromWmf(hmf, TRUE, placeable, metafile);
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromFile(GDIPCONST WCHAR *file,
|
||||
GpMetafile **metafile)
|
||||
{
|
||||
FIXME("(%p, %p): stub\n", file, metafile);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipCreateMetafileFromStream(IStream *stream,
|
||||
GpMetafile **metafile)
|
||||
{
|
||||
FIXME("(%p, %p): stub\n", stream, metafile);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipSetMetafileDownLevelRasterizationLimit(GpMetafile *metafile,
|
||||
UINT limitDpi)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%p,%u)\n", metafile, limitDpi);
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipConvertToEmfPlus(const GpGraphics* ref,
|
||||
GpMetafile* metafile, BOOL* succ, EmfType emfType,
|
||||
const WCHAR* description, GpMetafile** out_metafile)
|
||||
{
|
||||
static int calls;
|
||||
|
||||
TRACE("(%p,%p,%p,%u,%s,%p)\n", ref, metafile, succ, emfType,
|
||||
debugstr_w(description), out_metafile);
|
||||
|
||||
if(!ref || !metafile || !out_metafile)
|
||||
return InvalidParameter;
|
||||
|
||||
*succ = FALSE;
|
||||
*out_metafile = NULL;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipEmfToWmfBits(HENHMETAFILE hemf, UINT cbData16,
|
||||
LPBYTE pData16, INT iMapMode, INT eFlags)
|
||||
{
|
||||
FIXME("(%p, %d, %p, %d, %d): stub\n", hemf, cbData16, pData16, iMapMode, eFlags);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipRecordMetafileFileName(GDIPCONST WCHAR* fileName,
|
||||
HDC hdc, EmfType type, GDIPCONST GpRectF *pFrameRect,
|
||||
MetafileFrameUnit frameUnit, GDIPCONST WCHAR *desc,
|
||||
GpMetafile **metafile)
|
||||
{
|
||||
FIXME("%s %p %d %p %d %s %p stub!\n", debugstr_w(fileName), hdc, type, pFrameRect,
|
||||
frameUnit, debugstr_w(desc), metafile);
|
||||
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipRecordMetafileFileNameI(GDIPCONST WCHAR* fileName, HDC hdc, EmfType type,
|
||||
GDIPCONST GpRect *pFrameRect, MetafileFrameUnit frameUnit,
|
||||
GDIPCONST WCHAR *desc, GpMetafile **metafile)
|
||||
{
|
||||
FIXME("%s %p %d %p %d %s %p stub!\n", debugstr_w(fileName), hdc, type, pFrameRect,
|
||||
frameUnit, debugstr_w(desc), metafile);
|
||||
|
||||
return NotImplemented;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* GdipConvertToEmfPlusToFile [GDIPLUS.@]
|
||||
*/
|
||||
|
||||
GpStatus WINGDIPAPI GdipConvertToEmfPlusToFile(const GpGraphics* refGraphics,
|
||||
GpMetafile* metafile, BOOL* conversionSuccess,
|
||||
const WCHAR* filename, EmfType emfType,
|
||||
const WCHAR* description, GpMetafile** out_metafile)
|
||||
{
|
||||
FIXME("stub: %p, %p, %p, %p, %u, %p, %p\n", refGraphics, metafile, conversionSuccess, filename, emfType, description, out_metafile);
|
||||
return NotImplemented;
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator* iterator,
|
|||
|
||||
if(iterator->subpath_pos == count){
|
||||
*startIndex = *endIndex = *resultCount = 0;
|
||||
*isClosed = 1;
|
||||
*isClosed = TRUE;
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,24 @@ typedef struct packed_point
|
|||
short Y;
|
||||
} packed_point;
|
||||
|
||||
/* Test to see if the path could be stored as an array of shorts */
|
||||
static BOOL is_integer_path(const GpPath *path)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!path->pathdata.Count) return FALSE;
|
||||
|
||||
for (i = 0; i < path->pathdata.Count; i++)
|
||||
{
|
||||
short x, y;
|
||||
x = gdip_round(path->pathdata.Points[i].X);
|
||||
y = gdip_round(path->pathdata.Points[i].Y);
|
||||
if (path->pathdata.Points[i].X != (REAL)x || path->pathdata.Points[i].Y != (REAL)y)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Everything is measured in DWORDS; round up if there's a remainder */
|
||||
static inline INT get_pathtypes_size(const GpPath* path)
|
||||
{
|
||||
|
@ -94,9 +112,20 @@ static inline INT get_element_size(const region_element* element)
|
|||
case RegionDataRect:
|
||||
return needed + sizeof(GpRect);
|
||||
case RegionDataPath:
|
||||
needed += element->elementdata.pathdata.pathheader.size;
|
||||
needed += sizeof(DWORD); /* Extra DWORD for pathheader.size */
|
||||
return needed;
|
||||
{
|
||||
const GpPath *path = element->elementdata.path;
|
||||
DWORD flags = is_integer_path(path) ? FLAGS_INTPATH : FLAGS_NOFLAGS;
|
||||
/* 3 for headers, once again size doesn't count itself */
|
||||
needed += sizeof(DWORD) * 3;
|
||||
if (flags & FLAGS_INTPATH)
|
||||
needed += 2 * sizeof(SHORT) * path->pathdata.Count;
|
||||
else
|
||||
needed += 2 * sizeof(FLOAT) * path->pathdata.Count;
|
||||
|
||||
needed += get_pathtypes_size(path);
|
||||
needed += sizeof(DWORD); /* Extra DWORD for pathheader.size */
|
||||
return needed;
|
||||
}
|
||||
case RegionDataEmptyRect:
|
||||
case RegionDataInfiniteRect:
|
||||
return needed;
|
||||
|
@ -112,11 +141,8 @@ static inline INT get_element_size(const region_element* element)
|
|||
/* Does not check parameters, caller must do that */
|
||||
static inline GpStatus init_region(GpRegion* region, const RegionType type)
|
||||
{
|
||||
region->node.type = type;
|
||||
region->header.checksum = 0xdeadbeef;
|
||||
region->header.magic = VERSION_MAGIC;
|
||||
region->header.num_children = 0;
|
||||
region->header.size = sizeheader_size + get_element_size(®ion->node);
|
||||
region->node.type = type;
|
||||
region->num_children = 0;
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
@ -144,9 +170,7 @@ static inline GpStatus clone_element(const region_element* element,
|
|||
case RegionDataInfiniteRect:
|
||||
return Ok;
|
||||
case RegionDataPath:
|
||||
(*element2)->elementdata.pathdata.pathheader = element->elementdata.pathdata.pathheader;
|
||||
stat = GdipClonePath(element->elementdata.pathdata.path,
|
||||
&(*element2)->elementdata.pathdata.path);
|
||||
stat = GdipClonePath(element->elementdata.path, &(*element2)->elementdata.path);
|
||||
if (stat == Ok) return Ok;
|
||||
break;
|
||||
default:
|
||||
|
@ -178,9 +202,7 @@ static inline void fuse_region(GpRegion* region, region_element* left,
|
|||
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;
|
||||
region->num_children += 2;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -210,7 +232,7 @@ GpStatus WINGDIPAPI GdipCloneRegion(GpRegion *region, GpRegion **clone)
|
|||
return OutOfMemory;
|
||||
element = &(*clone)->node;
|
||||
|
||||
(*clone)->header = region->header;
|
||||
(*clone)->num_children = region->num_children;
|
||||
return clone_element(®ion->node, &element);
|
||||
}
|
||||
|
||||
|
@ -367,7 +389,7 @@ GpStatus WINGDIPAPI GdipCombineRegionRegion(GpRegion *region1,
|
|||
}
|
||||
|
||||
fuse_region(region1, left, right, mode);
|
||||
region1->header.num_children += region2->header.num_children;
|
||||
region1->num_children += region2->num_children;
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
@ -413,12 +435,7 @@ GpStatus WINGDIPAPI GdipCreateRegion(GpRegion **region)
|
|||
GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region)
|
||||
{
|
||||
region_element* element;
|
||||
GpPoint *pointsi;
|
||||
GpPointF *pointsf;
|
||||
|
||||
GpStatus stat;
|
||||
DWORD flags = FLAGS_INTPATH;
|
||||
INT count, i;
|
||||
|
||||
TRACE("%p, %p\n", path, region);
|
||||
|
||||
|
@ -435,77 +452,14 @@ GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **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);
|
||||
stat = GdipClonePath(path, &element->elementdata.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;
|
||||
}
|
||||
|
||||
|
@ -727,25 +681,24 @@ static inline void write_float(DWORD* location, INT* offset, const FLOAT write)
|
|||
static inline void write_packed_point(DWORD* location, INT* offset,
|
||||
const GpPointF* write)
|
||||
{
|
||||
packed_point point;
|
||||
|
||||
point.X = write->X;
|
||||
point.Y = write->Y;
|
||||
memcpy(location + *offset, &point, sizeof(packed_point));
|
||||
packed_point *point = (packed_point *)(location + *offset);
|
||||
point->X = gdip_round(write->X);
|
||||
point->Y = gdip_round(write->Y);
|
||||
(*offset)++;
|
||||
}
|
||||
|
||||
static inline void write_path_types(DWORD* location, INT* offset,
|
||||
const GpPath* path)
|
||||
{
|
||||
INT rounded_size = get_pathtypes_size(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))
|
||||
if (rounded_size - path->pathdata.Count)
|
||||
ZeroMemory(((BYTE*)location) + (*offset * sizeof(DWORD)) +
|
||||
path->pathdata.Count,
|
||||
sizeof(DWORD) - path->pathdata.Count % sizeof(DWORD));
|
||||
*offset += (get_pathtypes_size(path) / sizeof(DWORD));
|
||||
path->pathdata.Count, rounded_size - path->pathdata.Count);
|
||||
*offset += rounded_size / sizeof(DWORD);
|
||||
}
|
||||
|
||||
static void write_element(const region_element* element, DWORD *buffer,
|
||||
|
@ -772,12 +725,31 @@ static void write_element(const region_element* element, DWORD *buffer,
|
|||
case RegionDataPath:
|
||||
{
|
||||
INT i;
|
||||
const GpPath* path = element->elementdata.pathdata.path;
|
||||
const GpPath* path = element->elementdata.path;
|
||||
struct _pathheader
|
||||
{
|
||||
DWORD size;
|
||||
DWORD magic;
|
||||
DWORD count;
|
||||
DWORD flags;
|
||||
} *pathheader;
|
||||
|
||||
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)
|
||||
pathheader = (struct _pathheader *)(buffer + *filled);
|
||||
|
||||
pathheader->flags = is_integer_path(path) ? FLAGS_INTPATH : FLAGS_NOFLAGS;
|
||||
/* 3 for headers, once again size doesn't count itself */
|
||||
pathheader->size = sizeof(DWORD) * 3;
|
||||
if (pathheader->flags & FLAGS_INTPATH)
|
||||
pathheader->size += 2 * sizeof(SHORT) * path->pathdata.Count;
|
||||
else
|
||||
pathheader->size += 2 * sizeof(FLOAT) * path->pathdata.Count;
|
||||
pathheader->size += get_pathtypes_size(path);
|
||||
pathheader->magic = VERSION_MAGIC;
|
||||
pathheader->count = path->pathdata.Count;
|
||||
|
||||
*filled += 4;
|
||||
|
||||
switch (pathheader->flags & FLAGS_INTPATH)
|
||||
{
|
||||
case FLAGS_NOFLAGS:
|
||||
for (i = 0; i < path->pathdata.Count; i++)
|
||||
|
@ -792,6 +764,7 @@ static void write_element(const region_element* element, DWORD *buffer,
|
|||
write_packed_point(buffer, filled,
|
||||
&path->pathdata.Points[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
write_path_types(buffer, filled, path);
|
||||
break;
|
||||
|
@ -838,15 +811,36 @@ static void write_element(const region_element* element, DWORD *buffer,
|
|||
GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
|
||||
UINT *needed)
|
||||
{
|
||||
struct _region_header
|
||||
{
|
||||
DWORD size;
|
||||
DWORD checksum;
|
||||
DWORD magic;
|
||||
DWORD num_children;
|
||||
} *region_header;
|
||||
INT filled = 0;
|
||||
UINT required;
|
||||
GpStatus status;
|
||||
|
||||
TRACE("%p, %p, %d, %p\n", region, buffer, size, needed);
|
||||
|
||||
if (!(region && buffer && size))
|
||||
if (!region || !buffer || !size)
|
||||
return InvalidParameter;
|
||||
|
||||
memcpy(buffer, ®ion->header, sizeof(region->header));
|
||||
filled += sizeof(region->header) / sizeof(DWORD);
|
||||
status = GdipGetRegionDataSize(region, &required);
|
||||
if (status != Ok) return status;
|
||||
if (size < required)
|
||||
{
|
||||
if (needed) *needed = size;
|
||||
return InsufficientBuffer;
|
||||
}
|
||||
|
||||
region_header = (struct _region_header *)buffer;
|
||||
region_header->size = sizeheader_size + get_element_size(®ion->node);
|
||||
region_header->checksum = 0;
|
||||
region_header->magic = VERSION_MAGIC;
|
||||
region_header->num_children = region->num_children;
|
||||
filled += 4;
|
||||
/* With few exceptions, everything written is DWORD aligned,
|
||||
* so use that as our base */
|
||||
write_element(®ion->node, (DWORD*)buffer, &filled);
|
||||
|
@ -868,7 +862,7 @@ GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
|
|||
return InvalidParameter;
|
||||
|
||||
/* header.size doesn't count header.size and header.checksum */
|
||||
*needed = region->header.size + sizeof(DWORD) * 2;
|
||||
*needed = sizeof(DWORD) * 2 + sizeheader_size + get_element_size(®ion->node);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
@ -938,7 +932,7 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
|
|||
*hrgn = CreateRectRgn(0, 0, 0, 0);
|
||||
return *hrgn ? Ok : OutOfMemory;
|
||||
case RegionDataPath:
|
||||
return get_path_hrgn(element->elementdata.pathdata.path, graphics, hrgn);
|
||||
return get_path_hrgn(element->elementdata.path, graphics, hrgn);
|
||||
case RegionDataRect:
|
||||
{
|
||||
GpPath* path;
|
||||
|
@ -982,8 +976,8 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
|
|||
case CombineModeIntersect:
|
||||
return get_region_hrgn(element->elementdata.combine.right, graphics, hrgn);
|
||||
case CombineModeXor: case CombineModeExclude:
|
||||
FIXME("cannot exclude from an infinite region\n");
|
||||
/* fall-through */
|
||||
left = CreateRectRgn(-4194304, -4194304, 4194304, 4194304);
|
||||
break;
|
||||
case CombineModeUnion: case CombineModeComplement:
|
||||
*hrgn = NULL;
|
||||
return Ok;
|
||||
|
@ -1007,8 +1001,8 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap
|
|||
*hrgn = left;
|
||||
return Ok;
|
||||
case CombineModeXor: case CombineModeComplement:
|
||||
FIXME("cannot exclude from an infinite region\n");
|
||||
/* fall-through */
|
||||
right = CreateRectRgn(-4194304, -4194304, 4194304, 4194304);
|
||||
break;
|
||||
case CombineModeUnion: case CombineModeExclude:
|
||||
DeleteObject(left);
|
||||
*hrgn = NULL;
|
||||
|
@ -1291,16 +1285,19 @@ static GpStatus transform_region_element(region_element* element, GpMatrix *matr
|
|||
{
|
||||
/* Steal the element from the created region. */
|
||||
memcpy(element, &new_region->node, sizeof(region_element));
|
||||
HeapFree(GetProcessHeap(), 0, new_region);
|
||||
GdipFree(new_region);
|
||||
}
|
||||
else
|
||||
return stat;
|
||||
}
|
||||
/* Fall-through to do the actual conversion. */
|
||||
case RegionDataPath:
|
||||
if (!element->elementdata.path->pathdata.Count)
|
||||
return Ok;
|
||||
|
||||
stat = GdipTransformMatrixPoints(matrix,
|
||||
element->elementdata.pathdata.path->pathdata.Points,
|
||||
element->elementdata.pathdata.path->pathdata.Count);
|
||||
element->elementdata.path->pathdata.Points,
|
||||
element->elementdata.path->pathdata.Count);
|
||||
return stat;
|
||||
default:
|
||||
stat = transform_region_element(element->elementdata.combine.left, matrix);
|
||||
|
@ -1335,9 +1332,9 @@ static void translate_region_element(region_element* element, REAL dx, REAL dy)
|
|||
element->elementdata.rect.Y += dy;
|
||||
return;
|
||||
case RegionDataPath:
|
||||
for(i = 0; i < element->elementdata.pathdata.path->pathdata.Count; i++){
|
||||
element->elementdata.pathdata.path->pathdata.Points[i].X += dx;
|
||||
element->elementdata.pathdata.path->pathdata.Points[i].Y += dy;
|
||||
for(i = 0; i < element->elementdata.path->pathdata.Count; i++){
|
||||
element->elementdata.path->pathdata.Points[i].X += dx;
|
||||
element->elementdata.path->pathdata.Points[i].Y += dy;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
|
|
|
@ -74,7 +74,7 @@ reactos/dll/win32/dciman32 # Synced to Wine-1.7.1
|
|||
reactos/dll/win32/dwmapi # Synced to Wine-1.7.17
|
||||
reactos/dll/win32/faultrep # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/fusion # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/gdiplus # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/gdiplus # Synced to Wine-1.7.17
|
||||
reactos/dll/win32/hhctrl.ocx # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/hlink # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/hnetcfg # Synced to Wine-1.7.1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue