Author: akhaldi Date: Sat Jul 23 21:33:40 2016 New Revision: 71986 URL: http://svn.reactos.org/svn/reactos?rev=71986&view=rev Log: [GDI32] Sync EMFDRV_PolyPolylinegon() with Wine Staging 1.9.14. CORE-11521
Modified: trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/enhmetafiledrv.h trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/graphics.c Modified: trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/enhmetafiledrv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/enhmetafiledrv.h?rev=71986&r1=71985&r2=71986&view=diff ============================================================================== --- trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/enhmetafiledrv.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/enhmetafiledrv.h [iso-8859-1] Sat Jul 23 21:33:40 2016 @@ -42,8 +42,13 @@ HDC ref_dc; /* Reference device */ HDC screen_dc; /* Screen DC if no reference device specified */ INT restoring; /* RestoreDC counter */ + BOOL path; } EMFDRV_PDEVICE; +static inline EMFDRV_PDEVICE *get_emf_physdev( PHYSDEV dev ) +{ + return CONTAINING_RECORD( dev, EMFDRV_PDEVICE, dev ); +} extern BOOL EMFDRV_WriteRecord( PHYSDEV dev, EMR *emr ) DECLSPEC_HIDDEN; extern void EMFDRV_UpdateBBox( PHYSDEV dev, RECTL *rect ) DECLSPEC_HIDDEN; Modified: trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/graphics.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/graphics.c?rev=71986&r1=71985&r2=71986&view=diff ============================================================================== --- trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/graphics.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/graphics.c [iso-8859-1] Sat Jul 23 21:33:40 2016 @@ -33,6 +33,69 @@ WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); +static const RECTL empty_bounds = { 0, 0, -1, -1 }; + +/* determine if we can use 16-bit points to store all the input points */ +static BOOL can_use_short_points( const POINT *pts, UINT count ) +{ + UINT i; + + for (i = 0; i < count; i++) + if (((pts[i].x + 0x8000) & ~0xffff) || ((pts[i].y + 0x8000) & ~0xffff)) + return FALSE; + return TRUE; +} + +/* store points in either long or short format; return a pointer to the end of the stored data */ +static void *store_points( POINTL *dest, const POINT *pts, UINT count, BOOL short_points ) +{ + if (short_points) + { + UINT i; + POINTS *dest_short = (POINTS *)dest; + + for (i = 0; i < count; i++) + { + dest_short[i].x = pts[i].x; + dest_short[i].y = pts[i].y; + } + return dest_short + count; + } + else + { + memcpy( dest, pts, count * sizeof(*dest) ); + return dest + count; + } +} + +/* compute the bounds of an array of points, optionally including the current position */ +static void get_points_bounds( RECTL *bounds, const POINT *pts, UINT count, HDC hdc ) +{ + UINT i; + + if (hdc) + { + POINT cur_pt; + GetCurrentPositionEx( hdc, &cur_pt ); + bounds->left = bounds->right = cur_pt.x; + bounds->top = bounds->bottom = cur_pt.y; + } + else if (count) + { + bounds->left = bounds->right = pts[0].x; + bounds->top = bounds->bottom = pts[0].y; + } + else *bounds = empty_bounds; + + for (i = 0; i < count; i++) + { + bounds->left = min( bounds->left, pts[i].x ); + bounds->right = max( bounds->right, pts[i].x ); + bounds->top = min( bounds->top, pts[i].y ); + bounds->bottom = max( bounds->bottom, pts[i].y ); + } +} + /********************************************************************** * EMFDRV_MoveTo */ @@ -481,42 +544,50 @@ EMFDRV_PolyPolylinegon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys, DWORD iType) { + EMFDRV_PDEVICE *physDev = get_emf_physdev( dev ); EMRPOLYPOLYLINE *emr; DWORD cptl = 0, poly, size; - INT point; - RECTL bounds; - const POINT *pts; - BOOL ret; - - bounds.left = bounds.right = pt[0].x; - bounds.top = bounds.bottom = pt[0].y; - - pts = pt; + BOOL ret, use_small_emr, bounds_valid = TRUE; + for(poly = 0; poly < polys; poly++) { cptl += counts[poly]; - for(point = 0; point < counts[poly]; point++) { - if(bounds.left > pts->x) bounds.left = pts->x; - else if(bounds.right < pts->x) bounds.right = pts->x; - if(bounds.top > pts->y) bounds.top = pts->y; - else if(bounds.bottom < pts->y) bounds.bottom = pts->y; - pts++; - } - } - - size = sizeof(EMRPOLYPOLYLINE) + (polys - 1) * sizeof(DWORD) + - (cptl - 1) * sizeof(POINTL); + if(counts[poly] < 2) bounds_valid = FALSE; + } + if(!cptl) bounds_valid = FALSE; + use_small_emr = can_use_short_points( pt, cptl ); + + size = FIELD_OFFSET(EMRPOLYPOLYLINE, aPolyCounts[polys]); + if(use_small_emr) + size += cptl * sizeof(POINTS); + else + size += cptl * sizeof(POINTL); emr = HeapAlloc( GetProcessHeap(), 0, size ); emr->emr.iType = iType; + if(use_small_emr) emr->emr.iType += EMR_POLYPOLYLINE16 - EMR_POLYPOLYLINE; + emr->emr.nSize = size; - emr->rclBounds = bounds; + if(bounds_valid && !physDev->path) + get_points_bounds( &emr->rclBounds, pt, cptl, 0 ); + else + emr->rclBounds = empty_bounds; emr->nPolys = polys; emr->cptl = cptl; - memcpy(emr->aPolyCounts, counts, polys * sizeof(DWORD)); - memcpy(emr->aPolyCounts + polys, pt, cptl * sizeof(POINTL)); + + if(polys) + { + memcpy( emr->aPolyCounts, counts, polys * sizeof(DWORD) ); + store_points( (POINTL *)(emr->aPolyCounts + polys), pt, cptl, use_small_emr ); + } + ret = EMFDRV_WriteRecord( dev, &emr->emr ); - if(ret) + if(ret && !bounds_valid) + { + ret = FALSE; + SetLastError( ERROR_INVALID_PARAMETER ); + } + if(ret && !physDev->path) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret;