Author: akhaldi Date: Tue Apr 22 15:42:03 2014 New Revision: 62888
URL: http://svn.reactos.org/svn/reactos?rev=62888&view=rev Log: [GDIPLUS] * Sync with Wine 1.7.17. CORE-8080
Modified: trunk/reactos/dll/win32/gdiplus/brush.c trunk/reactos/dll/win32/gdiplus/font.c trunk/reactos/dll/win32/gdiplus/gdiplus.c trunk/reactos/dll/win32/gdiplus/gdiplus_private.h trunk/reactos/dll/win32/gdiplus/graphics.c trunk/reactos/dll/win32/gdiplus/graphicspath.c trunk/reactos/dll/win32/gdiplus/image.c trunk/reactos/dll/win32/gdiplus/metafile.c trunk/reactos/dll/win32/gdiplus/pathiterator.c trunk/reactos/dll/win32/gdiplus/region.c trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/dll/win32/gdiplus/brush.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/brush.c?r... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/brush.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/brush.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -756,8 +756,6 @@
/****************************************************************************** * GdipCreateTextureIA [GDIPLUS.@] - * - * FIXME: imageattr ignored */ GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image, GDIPCONST GpImageAttributes *imageattr, REAL x, REAL y, REAL width, @@ -855,6 +853,7 @@ imageattr->wrap = wrapmode;
stat = GdipCreateTextureIA(image, imageattr, x, y, width, height, texture); + GdipDisposeImageAttributes(imageattr); }
return stat;
Modified: trunk/reactos/dll/win32/gdiplus/font.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/font.c?re... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/font.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/font.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -1112,15 +1112,39 @@ /***************************************************************************** * GdipPrivateAddFontFile [GDIPLUS.@] */ -GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection* fontCollection, - GDIPCONST WCHAR* filename) -{ - FIXME("stub: %p, %s\n", fontCollection, debugstr_w(filename)); - - if (!(fontCollection && filename)) - return InvalidParameter; - - return NotImplemented; +GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection *collection, GDIPCONST WCHAR *name) +{ + HANDLE file, mapping; + LARGE_INTEGER size; + void *mem; + GpStatus status; + + 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; + } + + 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
Modified: trunk/reactos/dll/win32/gdiplus/gdiplus.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/gdiplus.c... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/gdiplus.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/gdiplus.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -357,7 +357,7 @@ }
/* 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 @@ case RegionDataRect: break; case RegionDataPath: - GdipDeletePath(element->elementdata.pathdata.path); + GdipDeletePath(element->elementdata.path); break; case RegionDataEmptyRect: case RegionDataInfiniteRect: @@ -456,13 +456,13 @@ } }
-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);
Modified: trunk/reactos/dll/win32/gdiplus/gdiplus_private.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/gdiplus_p... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/gdiplus_private.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/gdiplus_private.h [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -65,10 +65,12 @@ 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 @@ return (a<<24)|(r<<16)|(g<<8)|b; }
-extern const char *debugstr_rectf(CONST RectF* rc) DECLSPEC_HIDDEN; - -extern const char *debugstr_pointf(CONST PointF* pt) DECLSPEC_HIDDEN; +extern const char *debugstr_rectf(const RectF* rc) 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 @@ 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 @@ 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 GpRegion{ - struct - { - DWORD size; - DWORD checksum; - DWORD magic; - DWORD num_children; - } header; + DWORD num_children; region_element node; };
Modified: trunk/reactos/dll/win32/gdiplus/graphics.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/graphics.... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/graphics.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/graphics.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -617,7 +617,7 @@ 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 @@ 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 @@ 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 INT brush_can_fill_pixels(GpBrush *brush) +static BOOL brush_can_fill_pixels(GpBrush *brush) { switch (brush->bt) { @@ -1017,9 +1017,9 @@ case BrushTypeLinearGradient: case BrushTypeTextureFill: case BrushTypePathGradient: - return 1; + return TRUE; default: - return 0; + return FALSE; } }
@@ -1239,7 +1239,7 @@ 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 @@ if (!is_identity) { FIXME("path gradient transform not implemented\n"); - transform_fixme_once = 1; + transform_fixme_once = TRUE; } }
@@ -1310,7 +1310,7 @@ 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 @@
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 @@ 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 @@ }
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 @@ 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 @@ 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 @@ 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,7 +2880,17 @@ 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; @@ -3010,8 +2937,7 @@
if (stat != Ok) { - if (src_data != dst_data) - GdipFree(src_data); + GdipFree(src_data); GdipFree(dst_data); return stat; } @@ -3060,7 +2986,7 @@ 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 @@
/* 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 @@ else { GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0); - temp_bitmap = 1; + temp_bitmap = TRUE; }
hdc = bitmap->hdc; @@ -3338,6 +3264,7 @@ { INT save_state; GpStatus retval; + HRGN hrgn=NULL;
TRACE("(%p, %p, %p)\n", graphics, pen, path);
@@ -3355,10 +3282,20 @@
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 @@ { INT save_state; GpStatus retval; + HRGN hrgn=NULL;
if(!graphics->hdc || !brush_can_fill_path(brush)) return NotImplemented; @@ -3612,6 +3550,14 @@ 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 @@
end: RestoreDC(graphics->hdc, save_state); + DeleteObject(hrgn);
return retval; } @@ -3795,38 +3742,31 @@ 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; - - 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; + rect.X = x; + rect.Y = y; + rect.Width = width; + rect.Height = height; + + 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,8 +3777,15 @@
TRACE("(%p, %p, %p, %d)\n", graphics, brush, rects, count);
- if(!rects) - return InvalidParameter; + 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,12 +4387,24 @@ 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; @@ -4455,10 +4414,7 @@ if (!nheight) nheight = INT_MAX; }
- if (format) - hkprefix = format->hkprefix; - else - hkprefix = HotkeyPrefixNone; + hkprefix = format->hkprefix;
if (hkprefix == HotkeyPrefixShow) { @@ -4487,11 +4443,11 @@ 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 @@
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 @@ 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 @@ 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 GdipSetPageScale(GpGraphics *graphics, REAL scale) { + GpStatus stat; + TRACE("(%p, %.2f)\n", graphics, scale);
if(!graphics || (scale <= 0.0)) @@ -5247,6 +5208,13 @@ 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 GdipSetPageUnit(GpGraphics *graphics, GpUnit unit) { + GpStatus stat; + TRACE("(%p, %d)\n", graphics, unit);
if(!graphics) @@ -5264,6 +5234,13 @@
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;
@@ -5526,19 +5503,6 @@ GdipDeleteRegion(clip); } 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, @@ -6204,15 +6168,18 @@ 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 (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 (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 (i+1 < length && (flags & DriverStringOptionsRealizedAdvance) == DriverStringOptionsRealizedAdvance) { @@ -6220,6 +6187,10 @@ pti[i+1].y = pti[i].y + glyphmetrics.gmCellIncY; } } + + 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)); @@ -6238,10 +6209,14 @@ /* 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;
Modified: trunk/reactos/dll/win32/gdiplus/graphicspath.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/graphicsp... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/graphicspath.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/graphicspath.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -854,7 +854,7 @@ 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 @@ 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 @@ 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_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,67 +1849,195 @@
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(&points[i-1], &points[i], + &points[i+1], pen, 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(&points[i+1], &points[i], + &points[i-1], pen, 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; +} + +static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end, + path_list_node_t **last_point) +{ + int i; + path_list_node_t *prev_point; + + if (end <= start+1) + return; + + /* left outline */ + prev_point = *last_point; + + widen_joint(&path->pathdata.Points[end], &path->pathdata.Points[start], + &path->pathdata.Points[start+1], pen, last_point);
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_cap(&path->pathdata.Points[end], &path->pathdata.Points[end-1], - pen, pen->endcap, pen->customend, TRUE, TRUE, last_point); + widen_joint(&path->pathdata.Points[end-1], &path->pathdata.Points[end], + &path->pathdata.Points[start], pen, last_point); + + prev_point->next->type = PathPointTypeStart; + (*last_point)->type |= PathPointTypeCloseSubpath; + + /* right outline */ + prev_point = *last_point; + + widen_joint(&path->pathdata.Points[start], &path->pathdata.Points[end], + &path->pathdata.Points[end-1], pen, 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_cap(&path->pathdata.Points[start], &path->pathdata.Points[start+1], - pen, pen->startcap, pen->customstart, TRUE, FALSE, last_point); + widen_joint(&path->pathdata.Points[start+1], &path->pathdata.Points[start], + &path->pathdata.Points[end], pen, last_point);
prev_point->next->type = PathPointTypeStart; (*last_point)->type |= PathPointTypeCloseSubpath; }
-static void widen_closed_figure(GpPath *path, GpPen *pen, int start, int end, - path_list_node_t **last_point) -{ - int i; - path_list_node_t *prev_point; - - if (end <= start+1) +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;
- /* left outline */ - prev_point = *last_point; - - widen_joint(&path->pathdata.Points[end], &path->pathdata.Points[start], - &path->pathdata.Points[start+1], pen, 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(&path->pathdata.Points[end-1], &path->pathdata.Points[end], - &path->pathdata.Points[start], pen, last_point); - - prev_point->next->type = PathPointTypeStart; - (*last_point)->type |= PathPointTypeCloseSubpath; - - /* right outline */ - prev_point = *last_point; - - widen_joint(&path->pathdata.Points[start], &path->pathdata.Points[end], - &path->pathdata.Points[end-1], pen, 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(&path->pathdata.Points[start+1], &path->pathdata.Points[start], - &path->pathdata.Points[end], pen, last_point); - - prev_point->next->type = PathPointTypeStart; - (*last_point)->type |= PathPointTypeCloseSubpath; + 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, @@ -1952,9 +2081,6 @@ 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 @@
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); } }
Modified: trunk/reactos/dll/win32/gdiplus/image.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/image.c?r... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/image.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/image.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -1105,12 +1105,12 @@
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 @@ BitmapData* lockeddata) { GpStatus stat; - static int fixme=0; + static BOOL fixme = FALSE;
TRACE("(%p,%p)\n", bitmap, lockeddata);
@@ -1182,7 +1182,7 @@ 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 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 @@ 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); - - 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(*dstBitmap, &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 && srcBitmap->image.palette) + { + ColorPalette *src_palette, *dst_palette; + + 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 @@ } else if (image->type == ImageTypeBitmap) { - GpBitmap *bitmap = (GpBitmap*)image; - BitmapData lockeddata_src, lockeddata_dst; - int i; - UINT row_size; - - 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; + GpBitmap *bitmap = (GpBitmap *)image; + + 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 @@ 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 @@ 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 @@
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; @@ -1847,8 +1786,6 @@ pbmi->bmiHeader.biClrImportant = 0;
hbitmap = CreateDIBSection(0, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); - - GdipFree(pbmi);
if (!hbitmap) return GenericError;
@@ -2070,13 +2007,6 @@ return InvalidParameter;
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, @@ -2419,76 +2349,6 @@ *width = ipicture_pixel_width(image->picture);
TRACE("returning %d\n", *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; } @@ -3989,6 +3849,7 @@ HRESULT hr; UINT width, height; PixelFormat gdipformat=0; + const WICPixelFormatGUID *desired_wicformat; WICPixelFormatGUID wicformat; GpRect rc; BitmapData lockeddata; @@ -4041,18 +3902,38 @@ { 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)) @@ -4652,28 +4533,21 @@ 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; - - GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS); - - 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; + + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + pbmi->bmiHeader.biBitCount = 0; + + GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS); + + src_height = abs(pbmi->bmiHeader.biHeight); + pbmi->bmiHeader.biHeight = -src_height; + + GetDIBits(hdc, hbm, 0, src_height, lockeddata.Scan0, pbmi, DIB_RGB_COLORS);
DeleteDC(hdc);
@@ -4779,27 +4653,6 @@ }
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) @@ -4866,7 +4719,7 @@ 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 @@
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; -}
Modified: trunk/reactos/dll/win32/gdiplus/metafile.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/metafile.... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/metafile.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/metafile.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -34,6 +34,27 @@ DWORD LogicalDpiX; 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) { @@ -211,6 +232,8 @@ (*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 @@ 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; } @@ -290,6 +317,108 @@ }
*hdc = metafile->record_dc; + + 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; } @@ -368,9 +497,40 @@ } }
+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 @@ } else { + EmfPlusRecordHeader *header = (EmfPlusRecordHeader*)(data)-1; + METAFILE_PlaybackReleaseDC((GpMetafile*)metafile);
switch(recordType) @@ -412,6 +574,85 @@ 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 @@ 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 @@
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) - EnumEnhMetaFile(0, metafile->hemf, enum_metafile_proc, &data, NULL); - - METAFILE_PlaybackReleaseDC((GpMetafile*)metafile); + stat = GdipBeginContainer2(graphics, &state); + + if (stat == Ok) + { + stat = GdipSetPageScale(graphics, 1.0); + + 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 @@ 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; +}
Modified: trunk/reactos/dll/win32/gdiplus/pathiterator.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/pathitera... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/pathiterator.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/pathiterator.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -205,7 +205,7 @@
if(iterator->subpath_pos == count){ *startIndex = *endIndex = *resultCount = 0; - *isClosed = 1; + *isClosed = TRUE; return Ok; }
Modified: trunk/reactos/dll/win32/gdiplus/region.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/region.c?... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/region.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/region.c [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -75,6 +75,24 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ }
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 GdipCreateRegionPath(GpPath *path, GpRegion **region) { region_element* element; - GpPoint *pointsi; - GpPointF *pointsf; - - GpStatus stat; - DWORD flags = FLAGS_INTPATH; - INT count, i; + GpStatus stat;
TRACE("%p, %p\n", path, region);
@@ -435,76 +452,13 @@ 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_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 @@ 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) + const GpPath* path = element->elementdata.path; + struct _pathheader + { + DWORD size; + DWORD magic; + DWORD count; + DWORD flags; + } *pathheader; + + 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 @@ write_packed_point(buffer, filled, &path->pathdata.Points[i]); } + break; } write_path_types(buffer, filled, path); break; @@ -838,15 +811,36 @@ 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)) - return InvalidParameter; - - memcpy(buffer, ®ion->header, sizeof(region->header)); - filled += sizeof(region->header) / sizeof(DWORD); + if (!region || !buffer || !size) + return InvalidParameter; + + 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 @@ 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 @@ *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 @@ 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 @@ *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 @@ { /* 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 @@ 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:
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=6... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Tue Apr 22 15:42:03 2014 @@ -74,7 +74,7 @@ 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