Author: akhaldi Date: Thu Nov 17 22:35:44 2016 New Revision: 73270
URL: http://svn.reactos.org/svn/reactos?rev=73270&view=rev Log: [GDIPLUS] Sync with Wine Staging 1.9.23. CORE-12409
Modified: trunk/reactos/dll/win32/gdiplus/brush.c trunk/reactos/dll/win32/gdiplus/gdiplus.spec 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/imageattributes.c trunk/reactos/dll/win32/gdiplus/matrix.c trunk/reactos/dll/win32/gdiplus/metafile.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] Thu Nov 17 22:35:44 2016 @@ -441,25 +441,42 @@ { GpStatus stat; LinearGradientMode mode; - REAL width, height, exofs, eyofs; + REAL exofs, eyofs; REAL sin_angle, cos_angle, sin_cos_angle;
TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable, wrap, line);
- sin_angle = sinf(deg2rad(angle)); - cos_angle = cosf(deg2rad(angle)); + if (!rect || !rect->Width || !rect->Height) + return InvalidParameter; + + angle = fmodf(angle, 360); + if (angle < 0) + angle += 360; + + if (isAngleScalable) + { + float add_angle = 0; + + while(angle >= 90) { + angle -= 180; + add_angle += M_PI; + } + + if (angle != 90 && angle != -90) + angle = atan((rect->Width / rect->Height) * tan(deg2rad(angle))); + else + angle = deg2rad(angle); + angle += add_angle; + } + else + { + angle = deg2rad(angle); + } + + sin_angle = sinf(angle); + cos_angle = cosf(angle); sin_cos_angle = sin_angle * cos_angle; - - if (isAngleScalable) - { - width = height = 1.0; - } - else - { - width = rect->Width; - height = rect->Height; - }
if (sin_cos_angle >= 0) mode = LinearGradientModeForwardDiagonal; @@ -472,19 +489,13 @@ { if (sin_cos_angle >= 0) { - exofs = width * sin_cos_angle + height * cos_angle * cos_angle; - eyofs = width * sin_angle * sin_angle + height * sin_cos_angle; + exofs = rect->Height * sin_cos_angle + rect->Width * cos_angle * cos_angle; + eyofs = rect->Height * sin_angle * sin_angle + rect->Width * sin_cos_angle; } else { - exofs = width * sin_angle * sin_angle + height * sin_cos_angle; - eyofs = -width * sin_cos_angle + height * sin_angle * sin_angle; - } - - if (isAngleScalable) - { - exofs = exofs * rect->Width; - eyofs = eyofs * rect->Height; + exofs = rect->Width * sin_angle * sin_angle + rect->Height * sin_cos_angle; + eyofs = -rect->Width * sin_cos_angle + rect->Height * sin_angle * sin_angle; }
if (sin_angle >= 0)
Modified: trunk/reactos/dll/win32/gdiplus/gdiplus.spec URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/gdiplus.s... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/gdiplus.spec [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/gdiplus.spec [iso-8859-1] Thu Nov 17 22:35:44 2016 @@ -615,11 +615,11 @@ 615 stub GdipGetEffectParameterSize 616 stub GdipGetEffectParameters 617 stdcall GdipSetEffectParameters(ptr ptr long) -618 stub GdipInitializePalette +618 stdcall GdipInitializePalette(ptr long long long ptr) 619 stdcall GdipBitmapCreateApplyEffect(ptr long ptr ptr ptr ptr long ptr ptr) 620 stdcall GdipBitmapApplyEffect(ptr ptr ptr long ptr ptr) -621 stub GdipBitmapGetHistogram -622 stub GdipBitmapGetHistogramSize +621 stdcall GdipBitmapGetHistogram(ptr long long ptr ptr ptr ptr) +622 stdcall GdipBitmapGetHistogramSize(long ptr) 623 stdcall GdipBitmapConvertFormat(ptr long long long ptr float) 624 stdcall GdipImageSetAbort(ptr ptr) 625 stub GdipGraphicsSetAbort
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] Thu Nov 17 22:35:44 2016 @@ -89,6 +89,9 @@ extern REAL pixels_to_units(REAL pixels, GpUnit unit, REAL dpi) DECLSPEC_HIDDEN; extern REAL units_scale(GpUnit from, GpUnit to, REAL dpi) DECLSPEC_HIDDEN;
+extern GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, + GpCoordinateSpace src_space, GpMatrix *matrix) DECLSPEC_HIDDEN; + extern GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN;
extern GpStatus METAFILE_GetGraphicsContext(GpMetafile* metafile, GpGraphics **result) DECLSPEC_HIDDEN; @@ -97,9 +100,21 @@ extern GpStatus METAFILE_GraphicsClear(GpMetafile* metafile, ARGB color) DECLSPEC_HIDDEN; extern GpStatus METAFILE_FillRectangles(GpMetafile* metafile, GpBrush* brush, GDIPCONST GpRectF* rects, INT count) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_SetClipRect(GpMetafile* metafile, + REAL x, REAL y, REAL width, REAL height, CombineMode mode) DECLSPEC_HIDDEN; extern GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* matrix, MatrixOrder order) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_RotateWorldTransform(GpMetafile* metafile, REAL angle, MatrixOrder order) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_TranslateWorldTransform(GpMetafile* metafile, REAL dx, REAL dy, MatrixOrder order) DECLSPEC_HIDDEN; extern GpStatus METAFILE_ResetWorldTransform(GpMetafile* metafile) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_BeginContainer(GpMetafile* metafile, GDIPCONST GpRectF *dstrect, + GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_BeginContainerNoParams(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_EndContainer(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_SaveGraphics(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; +extern GpStatus METAFILE_RestoreGraphics(GpMetafile* metafile, DWORD StackIndex) DECLSPEC_HIDDEN; extern GpStatus METAFILE_GraphicsDeleted(GpMetafile* metafile) DECLSPEC_HIDDEN;
extern void calc_curve_bezier(const GpPointF *pts, REAL tension, REAL *x1, @@ -367,10 +382,13 @@ GpRectF src_rect; HANDLETABLE *handle_table; int handle_count; + XFORM gdiworldtransform; GpMatrix *world_transform; GpUnit page_unit; REAL page_scale; GpRegion *base_clip; /* clip region in device space for all metafile output */ + GpRegion *clip; /* clip region within the metafile */ + struct list containers; };
struct GpBitmap{
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] Thu Nov 17 22:35:44 2016 @@ -47,9 +47,6 @@ GDIPCONST GpBrush *brush, GDIPCONST PointF *positions, INT flags, GDIPCONST GpMatrix *matrix);
-static GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, - GpCoordinateSpace src_space, GpMatrix *matrix); - /* Converts from gdiplus path point type to gdi path point type. */ static BYTE convert_path_point_type(BYTE type) { @@ -1920,9 +1917,15 @@ return result; }
+typedef enum GraphicsContainerType { + BEGIN_CONTAINER, + SAVE_GRAPHICS +} GraphicsContainerType; + typedef struct _GraphicsContainerItem { struct list entry; GraphicsContainer contid; + GraphicsContainerType type;
SmoothingMode smoothing; CompositingQuality compqual; @@ -1939,7 +1942,7 @@ } GraphicsContainerItem;
static GpStatus init_container(GraphicsContainerItem** container, - GDIPCONST GpGraphics* graphics){ + GDIPCONST GpGraphics* graphics, GraphicsContainerType type){ GpStatus sts;
*container = heap_alloc_zero(sizeof(GraphicsContainerItem)); @@ -1947,6 +1950,7 @@ return OutOfMemory;
(*container)->contid = graphics->contid + 1; + (*container)->type = type;
(*container)->smoothing = graphics->smoothing; (*container)->compqual = graphics->compqual; @@ -3075,6 +3079,8 @@ HDC hdc; BOOL temp_hdc = FALSE, temp_bitmap = FALSE; HBITMAP hbitmap, old_hbm=NULL; + HRGN hrgn; + INT save_state;
if (!(bitmap->format == PixelFormat16bppRGB555 || bitmap->format == PixelFormat24bppRGB || @@ -3135,6 +3141,16 @@ old_hbm = SelectObject(hdc, hbitmap); }
+ save_state = SaveDC(graphics->hdc); + + stat = get_clip_hrgn(graphics, &hrgn); + + if (stat == Ok && hrgn) + { + ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); + DeleteObject(hrgn); + } + if (bitmap->format & (PixelFormatAlpha|PixelFormatPAlpha)) { gdi_alpha_blend(graphics, pti[0].x, pti[0].y, pti[1].x - pti[0].x, pti[2].y - pti[0].y, @@ -3146,6 +3162,8 @@ hdc, srcx, srcy, srcwidth, srcheight, SRCCOPY); }
+ RestoreDC(graphics->hdc, save_state); + if (temp_hdc) { SelectObject(hdc, old_hbm); @@ -3284,6 +3302,12 @@
TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f)\n", graphics, pen, x1, y1, x2, y2);
+ if (!pen) + return InvalidParameter; + + if (pen->unit == UnitPixel && pen->width <= 0.0) + return Ok; + pt[0].X = x1; pt[0].Y = y1; pt[1].X = x2; @@ -3347,26 +3371,12 @@ return retval; }
-GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) +GpStatus GDI32_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) { INT save_state; GpStatus retval; HRGN hrgn=NULL;
- TRACE("(%p, %p, %p)\n", graphics, pen, path); - - if(!pen || !graphics) - return InvalidParameter; - - if(graphics->busy) - return ObjectBusy; - - if (!graphics->hdc) - { - FIXME("graphics object has no HDC\n"); - return Ok; - } - save_state = prepare_dc(graphics, pen);
retval = get_clip_hrgn(graphics, &hrgn); @@ -3383,6 +3393,398 @@ end: restore_dc(graphics, save_state); DeleteObject(hrgn); + + return retval; +} + +GpStatus SOFTWARE_GdipDrawThinPath(GpGraphics *graphics, GpPen *pen, GpPath *path) +{ + GpStatus stat; + GpPath* flat_path; + GpMatrix* transform; + GpRectF gp_bound_rect; + GpRect gp_output_area; + RECT output_area; + INT output_height, output_width; + DWORD *output_bits, *brush_bits=NULL; + int i; + static const BYTE static_dash_pattern[] = {1,1,1,0,1,0,1,0}; + const BYTE *dash_pattern; + INT dash_pattern_size; + BYTE *dyn_dash_pattern = NULL; + + stat = GdipClonePath(path, &flat_path); + + if (stat != Ok) + return stat; + + stat = GdipCreateMatrix(&transform); + + if (stat == Ok) + { + stat = get_graphics_transform(graphics, CoordinateSpaceDevice, + CoordinateSpaceWorld, transform); + + if (stat == Ok) + stat = GdipFlattenPath(flat_path, transform, 1.0); + + GdipDeleteMatrix(transform); + } + + /* estimate the output size in pixels, can be larger than necessary */ + if (stat == Ok) + { + output_area.left = floorf(flat_path->pathdata.Points[0].X); + output_area.right = ceilf(flat_path->pathdata.Points[0].X); + output_area.top = floorf(flat_path->pathdata.Points[0].Y); + output_area.bottom = ceilf(flat_path->pathdata.Points[0].Y); + + for (i=1; i<flat_path->pathdata.Count; i++) + { + REAL x, y; + x = flat_path->pathdata.Points[i].X; + y = flat_path->pathdata.Points[i].Y; + + if (floorf(x) < output_area.left) output_area.left = floorf(x); + if (floorf(y) < output_area.top) output_area.top = floorf(y); + if (ceilf(x) > output_area.right) output_area.right = ceilf(x); + if (ceilf(y) > output_area.bottom) output_area.bottom = ceilf(y); + } + + stat = get_graphics_bounds(graphics, &gp_bound_rect); + } + + if (stat == Ok) + { + output_area.left = max(output_area.left, floorf(gp_bound_rect.X)); + output_area.top = max(output_area.top, floorf(gp_bound_rect.Y)); + output_area.right = min(output_area.right, ceilf(gp_bound_rect.X + gp_bound_rect.Width)); + output_area.bottom = min(output_area.bottom, ceilf(gp_bound_rect.Y + gp_bound_rect.Height)); + + output_width = output_area.right - output_area.left + 1; + output_height = output_area.bottom - output_area.top + 1; + + if (output_width <= 0 || output_height <= 0) + { + GdipDeletePath(flat_path); + return Ok; + } + + gp_output_area.X = output_area.left; + gp_output_area.Y = output_area.top; + gp_output_area.Width = output_width; + gp_output_area.Height = output_height; + + output_bits = heap_alloc_zero(output_width * output_height * sizeof(DWORD)); + if (!output_bits) + stat = OutOfMemory; + } + + if (stat == Ok) + { + if (pen->brush->bt != BrushTypeSolidColor) + { + /* allocate and draw brush output */ + brush_bits = heap_alloc_zero(output_width * output_height * sizeof(DWORD)); + + if (brush_bits) + { + stat = brush_fill_pixels(graphics, pen->brush, brush_bits, + &gp_output_area, output_width); + } + else + stat = OutOfMemory; + } + + if (stat == Ok) + { + /* convert dash pattern to bool array */ + switch (pen->dash) + { + case DashStyleCustom: + { + dash_pattern_size = 0; + + for (i=0; i < pen->numdashes; i++) + dash_pattern_size += gdip_round(pen->dashes[i]); + + if (dash_pattern_size != 0) + { + dash_pattern = dyn_dash_pattern = heap_alloc(dash_pattern_size); + + if (dyn_dash_pattern) + { + int j=0; + for (i=0; i < pen->numdashes; i++) + { + int k; + for (k=0; k < gdip_round(pen->dashes[i]); k++) + dyn_dash_pattern[j++] = (i&1)^1; + } + } + else + stat = OutOfMemory; + + break; + } + /* else fall through */ + } + case DashStyleSolid: + default: + dash_pattern = static_dash_pattern; + dash_pattern_size = 1; + break; + case DashStyleDash: + dash_pattern = static_dash_pattern; + dash_pattern_size = 4; + break; + case DashStyleDot: + dash_pattern = &static_dash_pattern[4]; + dash_pattern_size = 2; + break; + case DashStyleDashDot: + dash_pattern = static_dash_pattern; + dash_pattern_size = 6; + break; + case DashStyleDashDotDot: + dash_pattern = static_dash_pattern; + dash_pattern_size = 8; + break; + } + } + + if (stat == Ok) + { + /* trace path */ + GpPointF subpath_start = flat_path->pathdata.Points[0]; + INT prev_x = INT_MAX, prev_y = INT_MAX; + int dash_pos = dash_pattern_size - 1; + + for (i=0; i < flat_path->pathdata.Count; i++) + { + BYTE type, type2; + GpPointF start_point, end_point; + GpPoint start_pointi, end_pointi; + + type = flat_path->pathdata.Types[i]; + if (i+1 < flat_path->pathdata.Count) + type2 = flat_path->pathdata.Types[i+1]; + else + type2 = PathPointTypeStart; + + start_point = flat_path->pathdata.Points[i]; + + if ((type & PathPointTypePathTypeMask) == PathPointTypeStart) + subpath_start = start_point; + + if ((type & PathPointTypeCloseSubpath) == PathPointTypeCloseSubpath) + end_point = subpath_start; + else if ((type2 & PathPointTypePathTypeMask) == PathPointTypeStart) + continue; + else + end_point = flat_path->pathdata.Points[i+1]; + + start_pointi.X = floorf(start_point.X); + start_pointi.Y = floorf(start_point.Y); + end_pointi.X = floorf(end_point.X); + end_pointi.Y = floorf(end_point.Y); + + /* draw line segment */ + if (abs(start_pointi.Y - end_pointi.Y) > abs(start_pointi.X - end_pointi.X)) + { + INT x, y, start_y, end_y, step; + + if (start_pointi.Y < end_pointi.Y) + { + step = 1; + start_y = ceilf(start_point.Y) - output_area.top; + end_y = end_pointi.Y - output_area.top; + } + else + { + step = -1; + start_y = start_point.Y - output_area.top; + end_y = ceilf(end_point.Y) - output_area.top; + } + + for (y=start_y; y != (end_y+step); y+=step) + { + x = gdip_round( start_point.X + + (end_point.X - start_point.X) * (y + output_area.top - start_point.Y) / (end_point.Y - start_point.Y) ) + - output_area.left; + + if (x == prev_x && y == prev_y) + continue; + + prev_x = x; + prev_y = y; + dash_pos = (dash_pos + 1 == dash_pattern_size) ? 0 : dash_pos + 1; + + if (!dash_pattern[dash_pos]) + continue; + + if (x < 0 || x >= output_width || y < 0 || y >= output_height) + continue; + + if (brush_bits) + output_bits[x + y*output_width] = brush_bits[x + y*output_width]; + else + output_bits[x + y*output_width] = ((GpSolidFill*)pen->brush)->color; + } + } + else + { + INT x, y, start_x, end_x, step; + + if (start_pointi.X < end_pointi.X) + { + step = 1; + start_x = ceilf(start_point.X) - output_area.left; + end_x = end_pointi.X - output_area.left; + } + else + { + step = -1; + start_x = start_point.X - output_area.left; + end_x = ceilf(end_point.X) - output_area.left; + } + + for (x=start_x; x != (end_x+step); x+=step) + { + y = gdip_round( start_point.Y + + (end_point.Y - start_point.Y) * (x + output_area.left - start_point.X) / (end_point.X - start_point.X) ) + - output_area.top; + + if (x == prev_x && y == prev_y) + continue; + + prev_x = x; + prev_y = y; + dash_pos = (dash_pos + 1 == dash_pattern_size) ? 0 : dash_pos + 1; + + if (!dash_pattern[dash_pos]) + continue; + + if (x < 0 || x >= output_width || y < 0 || y >= output_height) + continue; + + if (brush_bits) + output_bits[x + y*output_width] = brush_bits[x + y*output_width]; + else + output_bits[x + y*output_width] = ((GpSolidFill*)pen->brush)->color; + } + } + } + } + + /* draw output image */ + if (stat == Ok) + { + stat = alpha_blend_pixels(graphics, output_area.left, output_area.top, + (BYTE*)output_bits, output_width, output_height, output_width * 4, + PixelFormat32bppARGB); + } + + heap_free(brush_bits); + heap_free(dyn_dash_pattern); + heap_free(output_bits); + } + + GdipDeletePath(flat_path); + + return stat; +} + +GpStatus SOFTWARE_GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) +{ + GpStatus stat; + GpPath *wide_path; + GpMatrix *transform=NULL; + + /* Check if the final pen thickness in pixels is too thin. */ + if (pen->unit == UnitPixel) + { + if (pen->width < 1.415) + return SOFTWARE_GdipDrawThinPath(graphics, pen, path); + } + else + { + GpPointF points[3] = {{0,0}, {1,0}, {0,1}}; + + points[1].X = pen->width; + points[2].Y = pen->width; + + stat = GdipTransformPoints(graphics, CoordinateSpaceDevice, + CoordinateSpaceWorld, points, 3); + + if (stat != Ok) + return stat; + + if (((points[1].X-points[0].X)*(points[1].X-points[0].X) + + (points[1].Y-points[0].Y)*(points[1].Y-points[0].Y) < 2.0001) && + ((points[2].X-points[0].X)*(points[2].X-points[0].X) + + (points[2].Y-points[0].Y)*(points[2].Y-points[0].Y) < 2.0001)) + return SOFTWARE_GdipDrawThinPath(graphics, pen, path); + } + + stat = GdipClonePath(path, &wide_path); + + if (stat != Ok) + return stat; + + if (pen->unit == UnitPixel) + { + /* We have to transform this to device coordinates to get the widths right. */ + stat = GdipCreateMatrix(&transform); + + if (stat == Ok) + stat = get_graphics_transform(graphics, CoordinateSpaceDevice, + CoordinateSpaceWorld, transform); + } + + if (stat == Ok) + stat = GdipWidenPath(wide_path, pen, transform, 1.0); + + if (pen->unit == UnitPixel) + { + /* Transform the path back to world coordinates */ + if (stat == Ok) + stat = GdipInvertMatrix(transform); + + if (stat == Ok) + stat = GdipTransformPath(wide_path, transform); + } + + /* Actually draw the path */ + if (stat == Ok) + stat = GdipFillPath(graphics, pen->brush, wide_path); + + GdipDeleteMatrix(transform); + + GdipDeletePath(wide_path); + + return stat; +} + +GpStatus WINGDIPAPI GdipDrawPath(GpGraphics *graphics, GpPen *pen, GpPath *path) +{ + GpStatus retval; + + TRACE("(%p, %p, %p)\n", graphics, pen, path); + + if(!pen || !graphics) + return InvalidParameter; + + if(graphics->busy) + return ObjectBusy; + + if (path->pathdata.Count == 0) + return Ok; + + if (!graphics->hdc) + retval = SOFTWARE_GdipDrawPath(graphics, pen, path); + else + retval = GDI32_GdipDrawPath(graphics, pen, path);
return retval; } @@ -3934,6 +4336,23 @@
ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND);
+ DeleteObject(hrgn); + + hrgn = NULL; + status = get_clip_hrgn(graphics, &hrgn); + + if (status != Ok) + { + RestoreDC(graphics->hdc, save_state); + return status; + } + + if (hrgn) + { + ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); + DeleteObject(hrgn); + } + if (GetClipBox(graphics->hdc, &rc) != NULLREGION) { BeginPath(graphics->hdc); @@ -3945,7 +4364,6 @@
RestoreDC(graphics->hdc, save_state);
- DeleteObject(hrgn);
return Ok; } @@ -5128,14 +5546,11 @@ return GdipSetMatrixElements(&graphics->worldtrans, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); }
-GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics *graphics, GraphicsState state) -{ - return GdipEndContainer(graphics, state); -} - GpStatus WINGDIPAPI GdipRotateWorldTransform(GpGraphics *graphics, REAL angle, GpMatrixOrder order) { + GpStatus stat; + TRACE("(%p, %.2f, %d)\n", graphics, angle, order);
if(!graphics) @@ -5144,45 +5559,119 @@ if(graphics->busy) return ObjectBusy;
+ if (graphics->image && graphics->image->type == ImageTypeMetafile) { + stat = METAFILE_RotateWorldTransform((GpMetafile*)graphics->image, angle, order); + + if (stat != Ok) + return stat; + } + return GdipRotateMatrix(&graphics->worldtrans, angle, order); }
+static GpStatus begin_container(GpGraphics *graphics, + GraphicsContainerType type, GraphicsContainer *state) +{ + GraphicsContainerItem *container; + GpStatus sts; + + if(!graphics || !state) + return InvalidParameter; + + sts = init_container(&container, graphics, type); + if(sts != Ok) + return sts; + + list_add_head(&graphics->containers, &container->entry); + *state = graphics->contid = container->contid; + + if (graphics->image && graphics->image->type == ImageTypeMetafile) { + if (type == BEGIN_CONTAINER) + METAFILE_BeginContainerNoParams((GpMetafile*)graphics->image, container->contid); + else + METAFILE_SaveGraphics((GpMetafile*)graphics->image, container->contid); + } + + return Ok; +} + GpStatus WINGDIPAPI GdipSaveGraphics(GpGraphics *graphics, GraphicsState *state) { - return GdipBeginContainer2(graphics, state); + TRACE("(%p, %p)\n", graphics, state); + return begin_container(graphics, SAVE_GRAPHICS, state); }
GpStatus WINGDIPAPI GdipBeginContainer2(GpGraphics *graphics, GraphicsContainer *state) { + TRACE("(%p, %p)\n", graphics, state); + return begin_container(graphics, BEGIN_CONTAINER, state); +} + +GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics, GDIPCONST GpRectF *dstrect, GDIPCONST GpRectF *srcrect, GpUnit unit, GraphicsContainer *state) +{ GraphicsContainerItem *container; - GpStatus sts; - - TRACE("(%p, %p)\n", graphics, state); - - if(!graphics || !state) - return InvalidParameter; - - sts = init_container(&container, graphics); - if(sts != Ok) - return sts; + GpMatrix transform; + GpStatus stat; + GpRectF scaled_srcrect; + REAL scale_x, scale_y; + + TRACE("(%p, %s, %s, %d, %p)\n", graphics, debugstr_rectf(dstrect), debugstr_rectf(srcrect), unit, state); + + if(!graphics || !dstrect || !srcrect || unit < UnitPixel || unit > UnitMillimeter || !state) + return InvalidParameter; + + stat = init_container(&container, graphics, BEGIN_CONTAINER); + if(stat != Ok) + return stat;
list_add_head(&graphics->containers, &container->entry); *state = graphics->contid = container->contid;
+ scale_x = units_to_pixels(1.0, unit, graphics->xres); + scale_y = units_to_pixels(1.0, unit, graphics->yres); + + scaled_srcrect.X = scale_x * srcrect->X; + scaled_srcrect.Y = scale_y * srcrect->Y; + scaled_srcrect.Width = scale_x * srcrect->Width; + scaled_srcrect.Height = scale_y * srcrect->Height; + + transform.matrix[0] = dstrect->Width / scaled_srcrect.Width; + transform.matrix[1] = 0.0; + transform.matrix[2] = 0.0; + transform.matrix[3] = dstrect->Height / scaled_srcrect.Height; + transform.matrix[4] = dstrect->X - scaled_srcrect.X; + transform.matrix[5] = dstrect->Y - scaled_srcrect.Y; + + GdipMultiplyMatrix(&graphics->worldtrans, &transform, MatrixOrderPrepend); + + if (graphics->image && graphics->image->type == ImageTypeMetafile) { + METAFILE_BeginContainer((GpMetafile*)graphics->image, dstrect, srcrect, unit, container->contid); + } + return Ok; }
-GpStatus WINGDIPAPI GdipBeginContainer(GpGraphics *graphics, GDIPCONST GpRectF *dstrect, GDIPCONST GpRectF *srcrect, GpUnit unit, GraphicsContainer *state) -{ - FIXME("(%p, %p, %p, %d, %p): stub\n", graphics, dstrect, srcrect, unit, state); - return NotImplemented; -} - GpStatus WINGDIPAPI GdipBeginContainerI(GpGraphics *graphics, GDIPCONST GpRect *dstrect, GDIPCONST GpRect *srcrect, GpUnit unit, GraphicsContainer *state) { - FIXME("(%p, %p, %p, %d, %p): stub\n", graphics, dstrect, srcrect, unit, state); - return NotImplemented; + GpRectF dstrectf, srcrectf; + + TRACE("(%p, %p, %p, %d, %p)\n", graphics, dstrect, srcrect, unit, state); + + if (!dstrect || !srcrect) + return InvalidParameter; + + dstrectf.X = dstrect->X; + dstrectf.Y = dstrect->Y; + dstrectf.Width = dstrect->Width; + dstrectf.Height = dstrect->Height; + + srcrectf.X = srcrect->X; + srcrectf.Y = srcrect->Y; + srcrectf.Width = srcrect->Width; + srcrectf.Height = srcrect->Height; + + return GdipBeginContainer(graphics, &dstrectf, &srcrectf, unit, state); }
GpStatus WINGDIPAPI GdipComment(GpGraphics *graphics, UINT sizeData, GDIPCONST BYTE *data) @@ -5191,18 +5680,17 @@ return NotImplemented; }
-GpStatus WINGDIPAPI GdipEndContainer(GpGraphics *graphics, GraphicsContainer state) +static GpStatus end_container(GpGraphics *graphics, GraphicsContainerType type, + GraphicsContainer state) { GpStatus sts; GraphicsContainerItem *container, *container2;
- TRACE("(%p, %x)\n", graphics, state); - if(!graphics) return InvalidParameter;
LIST_FOR_EACH_ENTRY(container, &graphics->containers, GraphicsContainerItem, entry){ - if(container->contid == state) + if(container->contid == state && container->type == type) break; }
@@ -5225,7 +5713,26 @@ list_remove(&container->entry); delete_container(container);
+ if (graphics->image && graphics->image->type == ImageTypeMetafile) { + if (type == BEGIN_CONTAINER) + METAFILE_EndContainer((GpMetafile*)graphics->image, state); + else + METAFILE_RestoreGraphics((GpMetafile*)graphics->image, state); + } + return Ok; +} + +GpStatus WINGDIPAPI GdipEndContainer(GpGraphics *graphics, GraphicsContainer state) +{ + TRACE("(%p, %x)\n", graphics, state); + return end_container(graphics, BEGIN_CONTAINER, state); +} + +GpStatus WINGDIPAPI GdipRestoreGraphics(GpGraphics *graphics, GraphicsState state) +{ + TRACE("(%p, %x)\n", graphics, state); + return end_container(graphics, SAVE_GRAPHICS, state); }
GpStatus WINGDIPAPI GdipScaleWorldTransform(GpGraphics *graphics, REAL sx, @@ -5459,6 +5966,8 @@
GpStatus WINGDIPAPI GdipSetWorldTransform(GpGraphics *graphics, GpMatrix *matrix) { + GpStatus stat; + TRACE("(%p, %p)\n", graphics, matrix);
if(!graphics || !matrix) @@ -5471,6 +5980,13 @@ matrix->matrix[0], matrix->matrix[1], matrix->matrix[2], matrix->matrix[3], matrix->matrix[4], matrix->matrix[5]);
+ if (graphics->image && graphics->image->type == ImageTypeMetafile) { + stat = METAFILE_SetWorldTransform((GpMetafile*)graphics->image, matrix); + + if (stat != Ok) + return stat; + } + graphics->worldtrans = *matrix;
return Ok; @@ -5479,6 +5995,8 @@ GpStatus WINGDIPAPI GdipTranslateWorldTransform(GpGraphics *graphics, REAL dx, REAL dy, GpMatrixOrder order) { + GpStatus stat; + TRACE("(%p, %.2f, %.2f, %d)\n", graphics, dx, dy, order);
if(!graphics) @@ -5486,6 +6004,13 @@
if(graphics->busy) return ObjectBusy; + + if (graphics->image && graphics->image->type == ImageTypeMetafile) { + stat = METAFILE_TranslateWorldTransform((GpMetafile*)graphics->image, dx, dy, order); + + if (stat != Ok) + return stat; + }
return GdipTranslateMatrix(&graphics->worldtrans, dx, dy, order); } @@ -5561,6 +6086,13 @@
if(graphics->busy) return ObjectBusy; + + if (graphics->image && graphics->image->type == ImageTypeMetafile) + { + status = METAFILE_SetClipRect((GpMetafile*)graphics->image, x, y, width, height, mode); + if (status != Ok) + return status; + }
rect.X = x; rect.Y = y; @@ -5628,8 +6160,8 @@ GpStatus WINGDIPAPI GdipDrawPolygon(GpGraphics *graphics,GpPen *pen,GDIPCONST GpPointF *points, INT count) { - INT save_state; - POINT *pti; + GpStatus status; + GpPath* path;
TRACE("(%p, %p, %d)\n", graphics, points, count);
@@ -5639,24 +6171,16 @@ if(graphics->busy) return ObjectBusy;
- if (!graphics->hdc) - { - FIXME("graphics object has no HDC\n"); - return Ok; - } - - pti = heap_alloc_zero(sizeof(POINT) * count); - - save_state = prepare_dc(graphics, pen); - SelectObject(graphics->hdc, GetStockObject(NULL_BRUSH)); - - transform_and_round_points(graphics, pti, (GpPointF*)points, count); - Polygon(graphics->hdc, pti, count); - - restore_dc(graphics, save_state); - heap_free(pti); - - return Ok; + status = GdipCreatePath(FillModeAlternate, &path); + if (status != Ok) return status; + + status = GdipAddPathPolygon(path, points, count); + if (status == Ok) + status = GdipDrawPath(graphics, pen, path); + + GdipDeletePath(path); + + return status; }
GpStatus WINGDIPAPI GdipDrawPolygonI(GpGraphics *graphics,GpPen *pen,GDIPCONST GpPoint *points, @@ -5723,6 +6247,13 @@
if(graphics->busy) return ObjectBusy; + + if (graphics->image && graphics->image->type == ImageTypeMetafile) { + ret = METAFILE_MultiplyWorldTransform((GpMetafile*)graphics->image, matrix, order); + + if (ret != Ok) + return ret; + }
m = graphics->worldtrans;
@@ -5896,7 +6427,7 @@ return Ok; }
-static GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, +GpStatus get_graphics_transform(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpMatrix *matrix) { GpStatus stat = Ok; @@ -6176,6 +6707,8 @@ GpPointF pt; HFONT hfont; UINT eto_flags=0; + GpStatus status; + HRGN hrgn;
if (flags & unsupported_flags) FIXME("Ignoring flags %x\n", flags & unsupported_flags); @@ -6186,6 +6719,14 @@ save_state = SaveDC(graphics->hdc); SetBkMode(graphics->hdc, TRANSPARENT); SetTextColor(graphics->hdc, get_gdi_brush_color(brush)); + + status = get_clip_hrgn(graphics, &hrgn); + + if (status == Ok && hrgn) + { + ExtSelectClipRgn(graphics->hdc, hrgn, RGN_AND); + DeleteObject(hrgn); + }
pt = positions[0]; GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &pt, 1);
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] Thu Nov 17 22:35:44 2016 @@ -1567,17 +1567,49 @@ GpStatus WINGDIPAPI GdipIsOutlineVisiblePathPoint(GpPath* path, REAL x, REAL y, GpPen *pen, GpGraphics *graphics, BOOL *result) { - static int calls; + GpStatus stat; + GpPath *wide_path; + GpMatrix *transform = NULL;
TRACE("(%p,%0.2f,%0.2f,%p,%p,%p)\n", path, x, y, pen, graphics, result);
if(!path || !pen) return InvalidParameter;
- if(!(calls++)) - FIXME("not implemented\n"); - - return NotImplemented; + stat = GdipClonePath(path, &wide_path); + + if (stat != Ok) + return stat; + + if (pen->unit == UnitPixel && graphics != NULL) + { + stat = GdipCreateMatrix(&transform); + + if (stat == Ok) + stat = get_graphics_transform(graphics, CoordinateSpaceDevice, + CoordinateSpaceWorld, transform); + } + + if (stat == Ok) + stat = GdipWidenPath(wide_path, pen, transform, 1.0); + + if (pen->unit == UnitPixel && graphics != NULL) + { + if (stat == Ok) + stat = GdipInvertMatrix(transform); + + if (stat == Ok) + stat = GdipTransformPath(wide_path, transform); + } + + if (stat == Ok) + stat = GdipIsVisiblePathPoint(wide_path, x, y, graphics, result); + + GdipDeleteMatrix(transform); + + GdipDeletePath(wide_path); + + return stat; }
GpStatus WINGDIPAPI GdipIsVisiblePathPointI(GpPath* path, INT x, INT y, GpGraphics *graphics, BOOL *result) @@ -1874,7 +1906,7 @@ int i; path_list_node_t *prev_point;
- if (end <= start+1) + if (end <= start) return;
/* left outline */
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] Thu Nov 17 22:35:44 2016 @@ -26,6 +26,7 @@ HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory**);
#define PIXELFORMATBPP(x) ((x) ? ((x) >> 8) & 255 : 24) +#define WMF_PLACEABLE_KEY 0x9ac6cdd7
static const struct { @@ -2138,6 +2139,10 @@ srcRect->Height = (REAL) ((GpBitmap*)image)->height; *srcUnit = UnitPixel; } + else{ + WARN("GpImage with no image data\n"); + return InvalidParameter; + }
TRACE("returning (%f, %f) (%f, %f) unit type %d\n", srcRect->X, srcRect->Y, srcRect->Width, srcRect->Height, *srcUnit); @@ -2160,6 +2165,10 @@ else if(image->type == ImageTypeBitmap){ *height = ((GpBitmap*)image)->height; *width = ((GpBitmap*)image)->width; + } + else{ + WARN("GpImage with no image data\n"); + return InvalidParameter; }
TRACE("returning (%f, %f)\n", *height, *width); @@ -2215,6 +2224,11 @@ *height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit, image->yres); else if(image->type == ImageTypeBitmap) *height = ((GpBitmap*)image)->height; + else + { + WARN("GpImage with no image data\n"); + return InvalidParameter; + }
TRACE("returning %d\n", *height);
@@ -2313,6 +2327,11 @@ *width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit, image->xres); else if(image->type == ImageTypeBitmap) *width = ((GpBitmap*)image)->width; + else + { + WARN("GpImage with no image data\n"); + return InvalidParameter; + }
TRACE("returning %d\n", *width);
@@ -3981,29 +4000,25 @@
static GpStatus load_wmf(IStream *stream, GpMetafile **metafile) { - GpStatus status = GenericError; + WmfPlaceableFileHeader pfh; + BOOL is_placeable = FALSE; + LARGE_INTEGER seek; + GpStatus status; + METAHEADER mh; + HMETAFILE hmf; HRESULT hr; UINT size; - LARGE_INTEGER pos; - WmfPlaceableFileHeader pfh; - BOOL is_placeable = FALSE; - METAHEADER mh; - HMETAFILE hmf; void *buf; - - pos.QuadPart = 0; - IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
hr = IStream_Read(stream, &mh, sizeof(mh), &size); if (hr != S_OK || size != sizeof(mh)) return GenericError;
- if (mh.mtType == 0xcdd7 && mh.mtHeaderSize == 0x9ac6) - { - is_placeable = TRUE; - - pos.QuadPart = 0; - IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + if (((WmfPlaceableFileHeader *)&mh)->Key == WMF_PLACEABLE_KEY) + { + seek.QuadPart = 0; + hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) return hresult_to_status(hr);
hr = IStream_Read(stream, &pfh, sizeof(pfh), &size); if (hr != S_OK || size != sizeof(pfh)) @@ -4012,82 +4027,112 @@ hr = IStream_Read(stream, &mh, sizeof(mh), &size); if (hr != S_OK || size != sizeof(mh)) return GenericError; - } - - pos.QuadPart = is_placeable ? sizeof(pfh) : 0; - IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + + is_placeable = TRUE; + } + + seek.QuadPart = is_placeable ? sizeof(pfh) : 0; + hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) return hresult_to_status(hr);
buf = heap_alloc(mh.mtSize * 2); if (!buf) return OutOfMemory;
hr = IStream_Read(stream, buf, mh.mtSize * 2, &size); - if (hr == S_OK && size == mh.mtSize * 2) - { - hmf = SetMetaFileBitsEx(mh.mtSize * 2, buf); - if (hmf) - { - status = GdipCreateMetafileFromWmf(hmf, TRUE, is_placeable ? &pfh : NULL, metafile); - if (status != Ok) - DeleteMetaFile(hmf); - } - } - + if (hr != S_OK || size != mh.mtSize * 2) + { + heap_free(buf); + return GenericError; + } + + hmf = SetMetaFileBitsEx(mh.mtSize * 2, buf); heap_free(buf); + if (!hmf) + return GenericError; + + status = GdipCreateMetafileFromWmf(hmf, TRUE, is_placeable ? &pfh : NULL, metafile); + if (status != Ok) + DeleteMetaFile(hmf); return status; }
+static GpStatus decode_image_wmf(IStream *stream, GpImage **image) +{ + GpMetafile *metafile; + GpStatus status; + + TRACE("%p %p\n", stream, image); + + if (!stream || !image) + return InvalidParameter; + + status = load_wmf(stream, &metafile); + if (status != Ok) + { + TRACE("Could not load metafile\n"); + return status; + } + + *image = (GpImage *)metafile; + TRACE("<-- %p\n", *image); + + return Ok; +} + static GpStatus load_emf(IStream *stream, GpMetafile **metafile) { - GpStatus status = GenericError; + LARGE_INTEGER seek; + ENHMETAHEADER emh; + HENHMETAFILE hemf; + GpStatus status; HRESULT hr; UINT size; - LARGE_INTEGER pos; - ENHMETAHEADER emh; - HENHMETAFILE hemf; void *buf; - - pos.QuadPart = 0; - IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
hr = IStream_Read(stream, &emh, sizeof(emh), &size); if (hr != S_OK || size != sizeof(emh) || emh.dSignature != ENHMETA_SIGNATURE) return GenericError;
- pos.QuadPart = 0; - IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + seek.QuadPart = 0; + hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL); + if (FAILED(hr)) return hresult_to_status(hr);
buf = heap_alloc(emh.nBytes); if (!buf) return OutOfMemory;
hr = IStream_Read(stream, buf, emh.nBytes, &size); - if (hr == S_OK && size == emh.nBytes) - { - hemf = SetEnhMetaFileBits(emh.nBytes, buf); - if (hemf) - { - status = GdipCreateMetafileFromEmf(hemf, FALSE, metafile); - if (status != Ok) - DeleteEnhMetaFile(hemf); - } - } - + if (hr != S_OK || size != emh.nBytes) + { + heap_free(buf); + return GenericError; + } + + hemf = SetEnhMetaFileBits(emh.nBytes, buf); heap_free(buf); + if (!hemf) + return GenericError; + + status = GdipCreateMetafileFromEmf(hemf, TRUE, metafile); + if (status != Ok) + DeleteEnhMetaFile(hemf); return status; }
-static GpStatus decode_image_metafile(IStream *stream, GpImage **image) +static GpStatus decode_image_emf(IStream *stream, GpImage **image) { GpMetafile *metafile; + GpStatus status;
TRACE("%p %p\n", stream, image);
- if(!stream || !image) - return InvalidParameter; - - if (load_emf(stream, &metafile) != Ok && load_wmf(stream, &metafile) != Ok) + if (!stream || !image) + return InvalidParameter; + + status = load_emf(stream, &metafile); + if (status != Ok) { TRACE("Could not load metafile\n"); - return GenericError; + return status; }
*image = (GpImage *)metafile; @@ -4487,7 +4532,7 @@ static GpStatus encode_image_gif(GpImage *image, IStream* stream, GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) { - return encode_image_wic(image, stream, &CLSID_WICGifEncoder, params); + return encode_image_wic(image, stream, &GUID_ContainerFormatGif, params); }
/***************************************************************************** @@ -4500,7 +4545,7 @@ encode_image_func encode_image; int i;
- TRACE("%p %p %p %p\n", image, stream, clsid, params); + TRACE("%p %p %s %p\n", image, stream, wine_dbgstr_guid(clsid), params);
if(!image || !stream) return InvalidParameter; @@ -4748,7 +4793,7 @@ /* SigMask */ emf_sig_mask, }, NULL, - decode_image_metafile, + decode_image_emf, NULL }, { @@ -4768,7 +4813,7 @@ /* SigMask */ wmf_sig_mask, }, NULL, - decode_image_metafile, + decode_image_wmf, NULL }, { @@ -5348,8 +5393,15 @@ */ GpStatus WINGDIPAPI GdipImageSetAbort(GpImage *image, GdiplusAbort *pabort) { - FIXME("(%p, %p): stub\n", image, pabort); - return NotImplemented; + TRACE("(%p, %p)\n", image, pabort); + + if (!image) + return InvalidParameter; + + if (pabort) + FIXME("Abort callback is not supported.\n"); + + return Ok; }
/***************************************************************************** @@ -5361,3 +5413,248 @@ FIXME("(%p, 0x%08x, %d, %d, %p, %f): stub\n", bitmap, format, dithertype, palettetype, palette, alphathreshold); return NotImplemented; } + +static void set_histogram_point_argb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + ch0[ color >> 24 ]++; + ch1[(color >> 16) & 0xff]++; + ch2[(color >> 8) & 0xff]++; + ch3[ color & 0xff]++; +} + +static void set_histogram_point_pargb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + BYTE alpha = color >> 24; + + ch0[alpha]++; + ch1[(((color >> 16) & 0xff) * alpha) / 0xff]++; + ch2[(((color >> 8) & 0xff) * alpha) / 0xff]++; + ch3[(( color & 0xff) * alpha) / 0xff]++; +} + +static void set_histogram_point_rgb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + ch0[(color >> 16) & 0xff]++; + ch1[(color >> 8) & 0xff]++; + ch2[ color & 0xff]++; +} + +static void set_histogram_point_gray(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + ch0[(76 * ((color >> 16) & 0xff) + 150 * ((color >> 8) & 0xff) + 29 * (color & 0xff)) / 0xff]++; +} + +static void set_histogram_point_b(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + ch0[color & 0xff]++; +} + +static void set_histogram_point_g(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + ch0[(color >> 8) & 0xff]++; +} + +static void set_histogram_point_r(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + ch0[(color >> 16) & 0xff]++; +} + +static void set_histogram_point_a(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + ch0[(color >> 24) & 0xff]++; +} + +/***************************************************************************** + * GdipBitmapGetHistogram [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipBitmapGetHistogram(GpBitmap *bitmap, HistogramFormat format, UINT num_of_entries, + UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) +{ + static void (* const set_histogram_point[])(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) = + { + set_histogram_point_argb, + set_histogram_point_pargb, + set_histogram_point_rgb, + set_histogram_point_gray, + set_histogram_point_b, + set_histogram_point_g, + set_histogram_point_r, + set_histogram_point_a, + }; + UINT width, height, x, y; + + TRACE("(%p, %d, %u, %p, %p, %p, %p)\n", bitmap, format, num_of_entries, + ch0, ch1, ch2, ch3); + + if (!bitmap || num_of_entries != 256) + return InvalidParameter; + + /* Make sure passed channel pointers match requested format */ + switch (format) + { + case HistogramFormatARGB: + case HistogramFormatPARGB: + if (!ch0 || !ch1 || !ch2 || !ch3) + return InvalidParameter; + memset(ch0, 0, num_of_entries * sizeof(UINT)); + memset(ch1, 0, num_of_entries * sizeof(UINT)); + memset(ch2, 0, num_of_entries * sizeof(UINT)); + memset(ch3, 0, num_of_entries * sizeof(UINT)); + break; + case HistogramFormatRGB: + if (!ch0 || !ch1 || !ch2 || ch3) + return InvalidParameter; + memset(ch0, 0, num_of_entries * sizeof(UINT)); + memset(ch1, 0, num_of_entries * sizeof(UINT)); + memset(ch2, 0, num_of_entries * sizeof(UINT)); + break; + case HistogramFormatGray: + case HistogramFormatB: + case HistogramFormatG: + case HistogramFormatR: + case HistogramFormatA: + if (!ch0 || ch1 || ch2 || ch3) + return InvalidParameter; + memset(ch0, 0, num_of_entries * sizeof(UINT)); + break; + default: + WARN("Invalid histogram format requested, %d\n", format); + return InvalidParameter; + } + + GdipGetImageWidth(&bitmap->image, &width); + GdipGetImageHeight(&bitmap->image, &height); + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + { + ARGB color; + + GdipBitmapGetPixel(bitmap, x, y, &color); + set_histogram_point[format](color, ch0, ch1, ch2, ch3); + } + + return Ok; +} + +/***************************************************************************** + * GdipBitmapGetHistogramSize [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipBitmapGetHistogramSize(HistogramFormat format, UINT *num_of_entries) +{ + TRACE("(%d, %p)\n", format, num_of_entries); + + if (!num_of_entries) + return InvalidParameter; + + *num_of_entries = 256; + return Ok; +} + +static GpStatus create_optimal_palette(ColorPalette *palette, INT desired, + BOOL transparent, GpBitmap *bitmap) +{ + GpStatus status; + BitmapData data; + HRESULT hr; + IWICImagingFactory *factory; + IWICPalette *wic_palette; + + if (!bitmap) return InvalidParameter; + if (palette->Count < desired) return GenericError; + + status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data); + if (status != Ok) return status; + + hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory); + if (hr != S_OK) + { + GdipBitmapUnlockBits(bitmap, &data); + return hresult_to_status(hr); + } + + hr = IWICImagingFactory_CreatePalette(factory, &wic_palette); + if (hr == S_OK) + { + IWICBitmap *bitmap; + + /* PixelFormat24bppRGB actually stores the bitmap bits as BGR. */ + hr = IWICImagingFactory_CreateBitmapFromMemory(factory, data.Width, data.Height, + &GUID_WICPixelFormat24bppBGR, data.Stride, data.Stride * data.Width, data.Scan0, &bitmap); + if (hr == S_OK) + { + hr = IWICPalette_InitializeFromBitmap(wic_palette, (IWICBitmapSource *)bitmap, desired, transparent); + if (hr == S_OK) + { + palette->Flags = 0; + IWICPalette_GetColorCount(wic_palette, &palette->Count); + IWICPalette_GetColors(wic_palette, palette->Count, palette->Entries, &palette->Count); + } + + IWICBitmap_Release(bitmap); + } + + IWICPalette_Release(wic_palette); + } + + IWICImagingFactory_Release(factory); + GdipBitmapUnlockBits(bitmap, &data); + + return hresult_to_status(hr); +} + +/***************************************************************************** + * GdipInitializePalette [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipInitializePalette(ColorPalette *palette, + PaletteType type, INT desired, BOOL transparent, GpBitmap *bitmap) +{ + TRACE("(%p,%d,%d,%d,%p)\n", palette, type, desired, transparent, bitmap); + + if (!palette) return InvalidParameter; + + switch (type) + { + case PaletteTypeCustom: + return Ok; + + case PaletteTypeOptimal: + return create_optimal_palette(palette, desired, transparent, bitmap); + + /* WIC palette type enumeration matches these gdiplus enums */ + case PaletteTypeFixedBW: + case PaletteTypeFixedHalftone8: + case PaletteTypeFixedHalftone27: + case PaletteTypeFixedHalftone64: + case PaletteTypeFixedHalftone125: + case PaletteTypeFixedHalftone216: + case PaletteTypeFixedHalftone252: + case PaletteTypeFixedHalftone256: + { + ColorPalette *wic_palette; + GpStatus status = Ok; + + wic_palette = get_palette(NULL, type); + if (!wic_palette) return OutOfMemory; + + if (palette->Count >= wic_palette->Count) + { + palette->Flags = wic_palette->Flags; + palette->Count = wic_palette->Count; + memcpy(palette->Entries, wic_palette->Entries, wic_palette->Count * sizeof(wic_palette->Entries[0])); + } + else + status = GenericError; + + heap_free(wic_palette); + + return status; + } + + default: + FIXME("unknown palette type %d\n", type); + break; + } + + return InvalidParameter; +}
Modified: trunk/reactos/dll/win32/gdiplus/imageattributes.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/imageattr... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/imageattributes.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/imageattributes.c [iso-8859-1] Thu Nov 17 22:35:44 2016 @@ -21,17 +21,51 @@ GpStatus WINGDIPAPI GdipCloneImageAttributes(GDIPCONST GpImageAttributes *imageattr, GpImageAttributes **cloneImageattr) { - GpStatus stat; + GpStatus stat = Ok; + struct color_remap_table remap_tables[ColorAdjustTypeCount] = {{0}}; + int i;
TRACE("(%p, %p)\n", imageattr, cloneImageattr);
if(!imageattr || !cloneImageattr) return InvalidParameter;
- stat = GdipCreateImageAttributes(cloneImageattr); + for (i=0; i<ColorAdjustTypeCount; i++) + { + if (imageattr->colorremaptables[i].enabled) + { + remap_tables[i].enabled = TRUE; + remap_tables[i].mapsize = imageattr->colorremaptables[i].mapsize; + remap_tables[i].colormap = heap_alloc(sizeof(ColorMap) * remap_tables[i].mapsize); + + if (remap_tables[i].colormap) + { + memcpy(remap_tables[i].colormap, imageattr->colorremaptables[i].colormap, + sizeof(ColorMap) * remap_tables[i].mapsize); + } + else + { + stat = OutOfMemory; + break; + } + } + }
if (stat == Ok) + stat = GdipCreateImageAttributes(cloneImageattr); + + if (stat == Ok) + { **cloneImageattr = *imageattr; + + memcpy((*cloneImageattr)->colorremaptables, remap_tables, sizeof(remap_tables)); + } + + if (stat != Ok) + { + for (i=0; i<ColorAdjustTypeCount; i++) + heap_free(remap_tables[i].colormap); + }
return stat; }
Modified: trunk/reactos/dll/win32/gdiplus/matrix.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/matrix.c?... ============================================================================== --- trunk/reactos/dll/win32/gdiplus/matrix.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/gdiplus/matrix.c [iso-8859-1] Thu Nov 17 22:35:44 2016 @@ -484,23 +484,17 @@
GpStatus WINGDIPAPI GdipIsMatrixIdentity(GDIPCONST GpMatrix *matrix, BOOL *result) { - GpMatrix *e; - GpStatus ret; - BOOL isIdentity; + static const GpMatrix identity = + { + { 1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0 } + };
TRACE("(%p, %p)\n", matrix, result);
if(!matrix || !result) return InvalidParameter;
- ret = GdipCreateMatrix(&e); - if(ret != Ok) return ret; - - ret = GdipIsMatrixEqual(matrix, e, &isIdentity); - if(ret == Ok) - *result = isIdentity; - - heap_free(e); - - return ret; -} + return GdipIsMatrixEqual(matrix, &identity, result); +}
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] Thu Nov 17 22:35:44 2016 @@ -48,6 +48,12 @@ DWORD Count; } EmfPlusFillRects;
+typedef struct EmfPlusSetClipRect +{ + EmfPlusRecordHeader Header; + GpRectF ClipRect; +} EmfPlusSetClipRect; + typedef struct EmfPlusSetPageTransform { EmfPlusRecordHeader Header; @@ -62,12 +68,69 @@ SHORT Height; } EmfPlusRect;
+typedef struct EmfPlusSetWorldTransform +{ + EmfPlusRecordHeader Header; + REAL MatrixData[6]; +} EmfPlusSetWorldTransform; + typedef struct EmfPlusScaleWorldTransform { EmfPlusRecordHeader Header; REAL Sx; REAL Sy; } EmfPlusScaleWorldTransform; + +typedef struct EmfPlusMultiplyWorldTransform +{ + EmfPlusRecordHeader Header; + REAL MatrixData[6]; +} EmfPlusMultiplyWorldTransform; + +typedef struct EmfPlusRotateWorldTransform +{ + EmfPlusRecordHeader Header; + REAL Angle; +} EmfPlusRotateWorldTransform; + +typedef struct EmfPlusTranslateWorldTransform +{ + EmfPlusRecordHeader Header; + REAL dx; + REAL dy; +} EmfPlusTranslateWorldTransform; + +typedef struct EmfPlusBeginContainer +{ + EmfPlusRecordHeader Header; + GpRectF DestRect; + GpRectF SrcRect; + DWORD StackIndex; +} EmfPlusBeginContainer; + +typedef struct EmfPlusContainerRecord +{ + EmfPlusRecordHeader Header; + DWORD StackIndex; +} EmfPlusContainerRecord; + +enum container_type +{ + BEGIN_CONTAINER, + SAVE_GRAPHICS +}; + +typedef struct container +{ + struct list entry; + DWORD id; + enum container_type type; + GraphicsContainer state; + GpMatrix world_transform; + GpUnit page_unit; + REAL page_scale; + GpRegion *clip; +} container;
static GpStatus METAFILE_AllocateRecord(GpMetafile *metafile, DWORD size, void **result) { @@ -260,6 +323,7 @@ (*metafile)->comment_data_size = 0; (*metafile)->comment_data_length = 0; (*metafile)->hemf = NULL; + list_init(&(*metafile)->containers);
if (!frameRect) { @@ -516,6 +580,32 @@ return Ok; }
+GpStatus METAFILE_SetClipRect(GpMetafile* metafile, REAL x, REAL y, REAL width, REAL height, CombineMode mode) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusSetClipRect *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusSetClipRect), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeSetClipRect; + record->Header.Flags = (mode & 0xf) << 8; + record->ClipRect.X = x; + record->ClipRect.Y = y; + record->ClipRect.Width = width; + record->ClipRect.Height = height; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + GpStatus METAFILE_SetPageTransform(GpMetafile* metafile, GpUnit unit, REAL scale) { if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) @@ -539,6 +629,29 @@ return Ok; }
+GpStatus METAFILE_SetWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* transform) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusSetWorldTransform *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusSetWorldTransform), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeSetWorldTransform; + record->Header.Flags = 0; + memcpy(record->MatrixData, transform->matrix, sizeof(record->MatrixData)); + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + GpStatus METAFILE_ScaleWorldTransform(GpMetafile* metafile, REAL sx, REAL sy, MatrixOrder order) { if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) @@ -553,9 +666,79 @@ return stat;
record->Header.Type = EmfPlusRecordTypeScaleWorldTransform; - record->Header.Flags = (order == MatrixOrderAppend ? 4 : 0); + record->Header.Flags = (order == MatrixOrderAppend ? 0x2000 : 0); record->Sx = sx; record->Sy = sy; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + +GpStatus METAFILE_MultiplyWorldTransform(GpMetafile* metafile, GDIPCONST GpMatrix* matrix, MatrixOrder order) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusMultiplyWorldTransform *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusMultiplyWorldTransform), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeMultiplyWorldTransform; + record->Header.Flags = (order == MatrixOrderAppend ? 0x2000 : 0); + memcpy(record->MatrixData, matrix->matrix, sizeof(record->MatrixData)); + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + +GpStatus METAFILE_RotateWorldTransform(GpMetafile* metafile, REAL angle, MatrixOrder order) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusRotateWorldTransform *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusRotateWorldTransform), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeRotateWorldTransform; + record->Header.Flags = (order == MatrixOrderAppend ? 0x2000 : 0); + record->Angle = angle; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + +GpStatus METAFILE_TranslateWorldTransform(GpMetafile* metafile, REAL dx, REAL dy, MatrixOrder order) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusTranslateWorldTransform *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusTranslateWorldTransform), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeTranslateWorldTransform; + record->Header.Flags = (order == MatrixOrderAppend ? 0x2000 : 0); + record->dx = dx; + record->dy = dy;
METAFILE_WriteRecords(metafile); } @@ -578,6 +761,122 @@
record->Type = EmfPlusRecordTypeResetWorldTransform; record->Flags = 0; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + +GpStatus METAFILE_BeginContainer(GpMetafile* metafile, GDIPCONST GpRectF *dstrect, + GDIPCONST GpRectF *srcrect, GpUnit unit, DWORD StackIndex) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusBeginContainer *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, sizeof(*record), (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeBeginContainer; + record->Header.Flags = unit & 0xff; + record->DestRect = *dstrect; + record->SrcRect = *srcrect; + record->StackIndex = StackIndex; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + +GpStatus METAFILE_BeginContainerNoParams(GpMetafile* metafile, DWORD StackIndex) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusContainerRecord *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusContainerRecord), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeBeginContainerNoParams; + record->Header.Flags = 0; + record->StackIndex = StackIndex; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + +GpStatus METAFILE_EndContainer(GpMetafile* metafile, DWORD StackIndex) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusContainerRecord *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusContainerRecord), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeEndContainer; + record->Header.Flags = 0; + record->StackIndex = StackIndex; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + +GpStatus METAFILE_SaveGraphics(GpMetafile* metafile, DWORD StackIndex) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusContainerRecord *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusContainerRecord), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeSave; + record->Header.Flags = 0; + record->StackIndex = StackIndex; + + METAFILE_WriteRecords(metafile); + } + + return Ok; +} + +GpStatus METAFILE_RestoreGraphics(GpMetafile* metafile, DWORD StackIndex) +{ + if (metafile->metafile_type == MetafileTypeEmfPlusOnly || metafile->metafile_type == MetafileTypeEmfPlusDual) + { + EmfPlusContainerRecord *record; + GpStatus stat; + + stat = METAFILE_AllocateRecord(metafile, + sizeof(EmfPlusContainerRecord), + (void**)&record); + if (stat != Ok) + return stat; + + record->Header.Type = EmfPlusRecordTypeRestore; + record->Header.Flags = 0; + record->StackIndex = StackIndex;
METAFILE_WriteRecords(metafile); } @@ -719,6 +1018,36 @@ return Ok; }
+static void METAFILE_GetFinalGdiTransform(const GpMetafile *metafile, XFORM *result) +{ + const GpRectF *rect; + const GpPointF *pt; + + /* This transforms metafile device space to output points. */ + rect = &metafile->src_rect; + pt = metafile->playback_points; + result->eM11 = (pt[1].X - pt[0].X) / rect->Width; + result->eM21 = (pt[2].X - pt[0].X) / rect->Height; + result->eDx = pt[0].X - result->eM11 * rect->X - result->eM21 * rect->Y; + result->eM12 = (pt[1].Y - pt[0].Y) / rect->Width; + result->eM22 = (pt[2].Y - pt[0].Y) / rect->Height; + result->eDy = pt[0].Y - result->eM12 * rect->X - result->eM22 * rect->Y; +} + +static GpStatus METAFILE_PlaybackUpdateGdiTransform(GpMetafile *metafile) +{ + XFORM combined, final; + + METAFILE_GetFinalGdiTransform(metafile, &final); + + CombineTransform(&combined, &metafile->gdiworldtransform, &final); + + SetGraphicsMode(metafile->playback_dc, GM_ADVANCED); + SetWorldTransform(metafile->playback_dc, &combined); + + return Ok; +} + static GpStatus METAFILE_PlaybackGetDC(GpMetafile *metafile) { GpStatus stat = Ok; @@ -727,20 +1056,10 @@
if (stat == Ok) { - /* The result of GdipGetDC always expects device co-ordinates, but the - * device co-ordinates of the source metafile do not correspond to - * device co-ordinates of the destination. Therefore, we set up the DC - * so that the metafile's bounds map to the destination points where we - * are drawing this metafile. */ - SetMapMode(metafile->playback_dc, MM_ANISOTROPIC); - - SetWindowOrgEx(metafile->playback_dc, metafile->bounds.X, metafile->bounds.Y, NULL); - SetWindowExtEx(metafile->playback_dc, metafile->bounds.Width, metafile->bounds.Height, NULL); - - SetViewportOrgEx(metafile->playback_dc, metafile->playback_points[0].X, metafile->playback_points[0].Y, NULL); - SetViewportExtEx(metafile->playback_dc, - metafile->playback_points[1].X - metafile->playback_points[0].X, - metafile->playback_points[2].Y - metafile->playback_points[0].Y, NULL); + static const XFORM identity = {1, 0, 0, 1, 0, 0}; + + metafile->gdiworldtransform = identity; + METAFILE_PlaybackUpdateGdiTransform(metafile); }
return stat; @@ -757,7 +1076,11 @@
static GpStatus METAFILE_PlaybackUpdateClip(GpMetafile *metafile) { - return GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->base_clip, CombineModeReplace); + GpStatus stat; + stat = GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->base_clip, CombineModeReplace); + if (stat == Ok) + stat = GdipCombineRegionRegion(metafile->playback_graphics->clip, metafile->clip, CombineModeIntersect); + return stat; }
static GpStatus METAFILE_PlaybackUpdateWorldTransform(GpMetafile *metafile) @@ -805,6 +1128,53 @@ if (metafile->playback_dc) { ENHMETARECORD *record; + + switch (recordType) + { + case EMR_SETMAPMODE: + case EMR_SAVEDC: + case EMR_RESTOREDC: + case EMR_SETWINDOWORGEX: + case EMR_SETWINDOWEXTEX: + case EMR_SETVIEWPORTORGEX: + case EMR_SETVIEWPORTEXTEX: + case EMR_SCALEVIEWPORTEXTEX: + case EMR_SCALEWINDOWEXTEX: + case EMR_MODIFYWORLDTRANSFORM: + FIXME("not implemented for record type %x\n", recordType); + break; + case EMR_SETWORLDTRANSFORM: + { + const XFORM* xform = (void*)data; + real_metafile->gdiworldtransform = *xform; + METAFILE_PlaybackUpdateGdiTransform(real_metafile); + break; + } + case EMR_EXTSELECTCLIPRGN: + { + DWORD rgndatasize = *(DWORD*)data; + DWORD mode = *(DWORD*)(data + 4); + const RGNDATA *rgndata = (const RGNDATA*)(data + 8); + HRGN hrgn = NULL; + + if (dataSize > 8) + { + XFORM final; + + METAFILE_GetFinalGdiTransform(metafile, &final); + + hrgn = ExtCreateRegion(&final, rgndatasize, rgndata); + } + + ExtSelectClipRgn(metafile->playback_dc, hrgn, mode); + + DeleteObject(hrgn); + + return Ok; + } + default: + break; + }
record = heap_alloc_zero(dataSize + 8);
@@ -909,6 +1279,32 @@
return stat; } + case EmfPlusRecordTypeSetClipRect: + { + EmfPlusSetClipRect *record = (EmfPlusSetClipRect*)header; + CombineMode mode = (CombineMode)((flags >> 8) & 0xf); + GpRegion *region; + GpMatrix world_to_device; + + if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(*record)) + return InvalidParameter; + + stat = GdipCreateRegionRect(&record->ClipRect, ®ion); + + if (stat == Ok) + { + get_graphics_transform(real_metafile->playback_graphics, + CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device); + + GdipTransformRegion(region, &world_to_device); + + GdipCombineRegionRegion(real_metafile->clip, region, mode); + + GdipDeleteRegion(region); + } + + return METAFILE_PlaybackUpdateClip(real_metafile); + } case EmfPlusRecordTypeSetPageTransform: { EmfPlusSetPageTransform *record = (EmfPlusSetPageTransform*)header; @@ -922,10 +1318,21 @@
return METAFILE_PlaybackUpdateWorldTransform(real_metafile); } + case EmfPlusRecordTypeSetWorldTransform: + { + EmfPlusSetWorldTransform *record = (EmfPlusSetWorldTransform*)header; + + if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusSetWorldTransform)) + return InvalidParameter; + + memcpy(real_metafile->world_transform->matrix, record->MatrixData, sizeof(record->MatrixData)); + + return METAFILE_PlaybackUpdateWorldTransform(real_metafile); + } case EmfPlusRecordTypeScaleWorldTransform: { EmfPlusScaleWorldTransform *record = (EmfPlusScaleWorldTransform*)header; - MatrixOrder order = (flags & 0x4) ? MatrixOrderAppend : MatrixOrderPrepend; + MatrixOrder order = (flags & 0x2000) ? MatrixOrderAppend : MatrixOrderPrepend;
if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusScaleWorldTransform)) return InvalidParameter; @@ -934,11 +1341,199 @@
return METAFILE_PlaybackUpdateWorldTransform(real_metafile); } + case EmfPlusRecordTypeMultiplyWorldTransform: + { + EmfPlusMultiplyWorldTransform *record = (EmfPlusMultiplyWorldTransform*)header; + MatrixOrder order = (flags & 0x2000) ? MatrixOrderAppend : MatrixOrderPrepend; + GpMatrix matrix; + + if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusMultiplyWorldTransform)) + return InvalidParameter; + + memcpy(matrix.matrix, record->MatrixData, sizeof(matrix.matrix)); + + GdipMultiplyMatrix(real_metafile->world_transform, &matrix, order); + + return METAFILE_PlaybackUpdateWorldTransform(real_metafile); + } + case EmfPlusRecordTypeRotateWorldTransform: + { + EmfPlusRotateWorldTransform *record = (EmfPlusRotateWorldTransform*)header; + MatrixOrder order = (flags & 0x2000) ? MatrixOrderAppend : MatrixOrderPrepend; + + if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusRotateWorldTransform)) + return InvalidParameter; + + GdipRotateMatrix(real_metafile->world_transform, record->Angle, order); + + return METAFILE_PlaybackUpdateWorldTransform(real_metafile); + } + case EmfPlusRecordTypeTranslateWorldTransform: + { + EmfPlusTranslateWorldTransform *record = (EmfPlusTranslateWorldTransform*)header; + MatrixOrder order = (flags & 0x2000) ? MatrixOrderAppend : MatrixOrderPrepend; + + if (dataSize + sizeof(EmfPlusRecordHeader) < sizeof(EmfPlusTranslateWorldTransform)) + return InvalidParameter; + + GdipTranslateMatrix(real_metafile->world_transform, record->dx, record->dy, order); + + return METAFILE_PlaybackUpdateWorldTransform(real_metafile); + } case EmfPlusRecordTypeResetWorldTransform: { GdipSetMatrixElements(real_metafile->world_transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
return METAFILE_PlaybackUpdateWorldTransform(real_metafile); + } + case EmfPlusRecordTypeBeginContainer: + { + EmfPlusBeginContainer *record = (EmfPlusBeginContainer*)header; + container* cont; + GpUnit unit; + REAL scale_x, scale_y; + GpRectF scaled_srcrect; + GpMatrix transform; + + cont = heap_alloc_zero(sizeof(*cont)); + if (!cont) + return OutOfMemory; + + stat = GdipCloneRegion(metafile->clip, &cont->clip); + if (stat != Ok) + { + heap_free(cont); + return stat; + } + + stat = GdipBeginContainer2(metafile->playback_graphics, &cont->state); + + if (stat != Ok) + { + GdipDeleteRegion(cont->clip); + heap_free(cont); + return stat; + } + + cont->id = record->StackIndex; + cont->type = BEGIN_CONTAINER; + cont->world_transform = *metafile->world_transform; + cont->page_unit = metafile->page_unit; + cont->page_scale = metafile->page_scale; + list_add_head(&real_metafile->containers, &cont->entry); + + unit = record->Header.Flags & 0xff; + + scale_x = units_to_pixels(1.0, unit, metafile->image.xres); + scale_y = units_to_pixels(1.0, unit, metafile->image.yres); + + scaled_srcrect.X = scale_x * record->SrcRect.X; + scaled_srcrect.Y = scale_y * record->SrcRect.Y; + scaled_srcrect.Width = scale_x * record->SrcRect.Width; + scaled_srcrect.Height = scale_y * record->SrcRect.Height; + + transform.matrix[0] = record->DestRect.Width / scaled_srcrect.Width; + transform.matrix[1] = 0.0; + transform.matrix[2] = 0.0; + transform.matrix[3] = record->DestRect.Height / scaled_srcrect.Height; + transform.matrix[4] = record->DestRect.X - scaled_srcrect.X; + transform.matrix[5] = record->DestRect.Y - scaled_srcrect.Y; + + GdipMultiplyMatrix(real_metafile->world_transform, &transform, MatrixOrderPrepend); + + return METAFILE_PlaybackUpdateWorldTransform(real_metafile); + } + case EmfPlusRecordTypeBeginContainerNoParams: + case EmfPlusRecordTypeSave: + { + EmfPlusContainerRecord *record = (EmfPlusContainerRecord*)header; + container* cont; + + cont = heap_alloc_zero(sizeof(*cont)); + if (!cont) + return OutOfMemory; + + stat = GdipCloneRegion(metafile->clip, &cont->clip); + if (stat != Ok) + { + heap_free(cont); + return stat; + } + + if (recordType == EmfPlusRecordTypeBeginContainerNoParams) + stat = GdipBeginContainer2(metafile->playback_graphics, &cont->state); + else + stat = GdipSaveGraphics(metafile->playback_graphics, &cont->state); + + if (stat != Ok) + { + GdipDeleteRegion(cont->clip); + heap_free(cont); + return stat; + } + + cont->id = record->StackIndex; + if (recordType == EmfPlusRecordTypeBeginContainerNoParams) + cont->type = BEGIN_CONTAINER; + else + cont->type = SAVE_GRAPHICS; + cont->world_transform = *metafile->world_transform; + cont->page_unit = metafile->page_unit; + cont->page_scale = metafile->page_scale; + list_add_head(&real_metafile->containers, &cont->entry); + + break; + } + case EmfPlusRecordTypeEndContainer: + case EmfPlusRecordTypeRestore: + { + EmfPlusContainerRecord *record = (EmfPlusContainerRecord*)header; + container* cont; + enum container_type type; + BOOL found=FALSE; + + if (recordType == EmfPlusRecordTypeEndContainer) + type = BEGIN_CONTAINER; + else + type = SAVE_GRAPHICS; + + LIST_FOR_EACH_ENTRY(cont, &real_metafile->containers, container, entry) + { + if (cont->id == record->StackIndex && cont->type == type) + { + found = TRUE; + break; + } + } + + if (found) + { + container* cont2; + + /* pop any newer items on the stack */ + while ((cont2 = LIST_ENTRY(list_head(&real_metafile->containers), container, entry)) != cont) + { + list_remove(&cont2->entry); + GdipDeleteRegion(cont2->clip); + heap_free(cont2); + } + + if (type == BEGIN_CONTAINER) + GdipEndContainer(real_metafile->playback_graphics, cont->state); + else + GdipRestoreGraphics(real_metafile->playback_graphics, cont->state); + + *real_metafile->world_transform = cont->world_transform; + real_metafile->page_unit = cont->page_unit; + real_metafile->page_scale = cont->page_scale; + GdipCombineRegionRegion(real_metafile->clip, cont->clip, CombineModeReplace); + + list_remove(&cont->entry); + GdipDeleteRegion(cont->clip); + heap_free(cont); + } + + break; } default: FIXME("Not implemented for record type %x\n", recordType); @@ -1063,6 +1658,9 @@
if (stat == Ok) stat = GdipGetClip(graphics, real_metafile->base_clip); + + if (stat == Ok) + stat = GdipCreateRegion(&real_metafile->clip);
if (stat == Ok) stat = GdipCreatePath(FillModeAlternate, &dst_path); @@ -1118,6 +1716,17 @@ GdipDeleteRegion(real_metafile->base_clip); real_metafile->base_clip = NULL;
+ GdipDeleteRegion(real_metafile->clip); + real_metafile->clip = NULL; + + while (list_head(&real_metafile->containers)) + { + container* cont = LIST_ENTRY(list_head(&real_metafile->containers), container, entry); + list_remove(&cont->entry); + GdipDeleteRegion(cont->clip); + heap_free(cont); + } + GdipEndContainer(graphics, state); }
@@ -1199,17 +1808,22 @@ if(!metafile || !header) return InvalidParameter;
- if (!metafile->hemf) - return InvalidParameter; - - status = GdipGetMetafileHeaderFromEmf(metafile->hemf, header); - if (status != Ok) return status; + if (metafile->hemf) + { + status = GdipGetMetafileHeaderFromEmf(metafile->hemf, header); + if (status != Ok) return status; + } + else + { + memset(header, 0, sizeof(*header)); + header->Version = 0xdbc01002; + }
header->Type = metafile->metafile_type; header->DpiX = metafile->image.xres; header->DpiY = metafile->image.yres; - header->Width = metafile->bounds.Width; - header->Height = metafile->bounds.Height; + header->Width = gdip_round(metafile->bounds.Width); + header->Height = gdip_round(metafile->bounds.Height);
return Ok; } @@ -1390,6 +2004,7 @@ (*metafile)->metafile_type = header.Type; (*metafile)->hemf = hemf; (*metafile)->preserve_hemf = !delete; + list_init(&(*metafile)->containers);
TRACE("<-- %p\n", *metafile);
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=7... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Thu Nov 17 22:35:44 2016 @@ -68,7 +68,7 @@ reactos/dll/win32/faultrep # Synced to WineStaging-1.9.11 reactos/dll/win32/fontsub # Synced to WineStaging-1.9.13 reactos/dll/win32/fusion # Synced to WineStaging-1.9.23 -reactos/dll/win32/gdiplus # Synced to WineStaging-1.9.16 +reactos/dll/win32/gdiplus # Synced to WineStaging-1.9.23 reactos/dll/win32/hhctrl.ocx # Synced to WineStaging-1.9.16 reactos/dll/win32/hlink # Synced to WineStaging-1.9.16 reactos/dll/win32/hnetcfg # Synced to WineStaging-1.9.16