/*********************************************************************** * EMFDRV_Rectangle */ BOOL EMFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom) { EMRRECTANGLE emr; INT temp; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; TRACE("%d,%d - %d,%d\n", left, top, right, bottom); if(left == right || top == bottom) return FALSE; if(left > right) {temp = left; left = right; right = temp;} if(top > bottom) {temp = top; top = bottom; bottom = temp;} if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) { right--; bottom--; } emr.emr.iType = EMR_RECTANGLE; emr.emr.nSize = sizeof(emr); emr.rclBox.left = left; emr.rclBox.top = top; emr.rclBox.right = right; emr.rclBox.bottom = bottom; EMFDRV_UpdateBBox( dev, &emr.rclBox ); return EMFDRV_WriteRecord( dev, &emr.emr ); }
/********************************************************************** * EMFDRV_Polylinegon * * Helper for EMFDRV_Poly{line|gon} */ static BOOL EMFDRV_Polylinegon( PHYSDEV dev, const POINT* pt, INT count, DWORD iType ) { EMFDRV_PDEVICE *physDev = get_emf_physdev( dev ); DC *dc = get_physdev_dc( dev ); EMRPOLYLINE *emr; DWORD size; BOOL ret, use_small_emr = can_use_short_points( pt, count ); size = use_small_emr ? offsetof( EMRPOLYLINE16, apts[count] ) : offsetof( EMRPOLYLINE, aptl[count] ); emr = HeapAlloc( GetProcessHeap(), 0, size ); emr->emr.iType = use_small_emr ? iType + EMR_POLYLINE16 - EMR_POLYLINE : iType; emr->emr.nSize = size; emr->cptl = count; store_points( emr->aptl, pt, count, use_small_emr ); if (!physDev->path) get_points_bounds( &emr->rclBounds, pt, count, (iType == EMR_POLYBEZIERTO || iType == EMR_POLYLINETO) ? dc : 0 ); else emr->rclBounds = empty_bounds; ret = EMFDRV_WriteRecord( dev, &emr->emr ); if (ret && !physDev->path) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
/*********************************************************************** * EMFDRV_LineTo */ BOOL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y ) { EMFDRV_PDEVICE *physDev = get_emf_physdev( dev ); DC *dc = get_physdev_dc( dev ); POINT pt; EMRLINETO emr; RECTL bounds; emr.emr.iType = EMR_LINETO; emr.emr.nSize = sizeof(emr); emr.ptl.x = x; emr.ptl.y = y; if(!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; pt = dc->cur_pos; bounds.left = min(x, pt.x); bounds.top = min(y, pt.y); bounds.right = max(x, pt.x); bounds.bottom = max(y, pt.y); if(!physDev->path) EMFDRV_UpdateBBox( dev, &bounds ); return TRUE; }
/*********************************************************************** * EMFDRV_Ellipse */ BOOL EMFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) { EMFDRV_PDEVICE *physDev = get_emf_physdev( dev ); DC *dc = get_physdev_dc( dev ); EMRELLIPSE emr; INT temp; TRACE("%d,%d - %d,%d\n", left, top, right, bottom); if(left == right || top == bottom) return FALSE; if(left > right) {temp = left; left = right; right = temp;} if(top > bottom) {temp = top; top = bottom; bottom = temp;} if(dc->GraphicsMode == GM_COMPATIBLE) { right--; bottom--; } emr.emr.iType = EMR_ELLIPSE; emr.emr.nSize = sizeof(emr); emr.rclBox.left = left; emr.rclBox.top = top; emr.rclBox.right = right; emr.rclBox.bottom = bottom; if(!physDev->path) EMFDRV_UpdateBBox( dev, &emr.rclBox ); return EMFDRV_WriteRecord( dev, &emr.emr ); }
/*********************************************************************** * EMFDRV_RoundRect */ BOOL EMFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT ell_width, INT ell_height ) { EMRROUNDRECT emr; INT temp; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; if(left == right || top == bottom) return FALSE; if(left > right) {temp = left; left = right; right = temp;} if(top > bottom) {temp = top; top = bottom; bottom = temp;} if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) { right--; bottom--; } emr.emr.iType = EMR_ROUNDRECT; emr.emr.nSize = sizeof(emr); emr.rclBox.left = left; emr.rclBox.top = top; emr.rclBox.right = right; emr.rclBox.bottom = bottom; emr.szlCorner.cx = ell_width; emr.szlCorner.cy = ell_height; EMFDRV_UpdateBBox( dev, &emr.rclBox ); return EMFDRV_WriteRecord( dev, &emr.emr ); }
/*********************************************************************** * EMFDRV_LineTo */ BOOL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y ) { POINT pt; EMRLINETO emr; RECTL bounds; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; emr.emr.iType = EMR_LINETO; emr.emr.nSize = sizeof(emr); emr.ptl.x = x; emr.ptl.y = y; if(!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; GetCurrentPositionEx(physDev->hdc, &pt); bounds.left = min(x, pt.x); bounds.top = min(y, pt.y); bounds.right = max(x, pt.x); bounds.bottom = max(y, pt.y); EMFDRV_UpdateBBox( dev, &bounds ); return TRUE; }
/********************************************************************* * EMFDRV_FrameRgn */ BOOL EMFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT width, INT height ) { EMRFRAMERGN *emr; DWORD size, rgnsize, index; BOOL ret; index = EMFDRV_CreateBrushIndirect( dev, hbrush ); if(!index) return FALSE; rgnsize = GetRegionData( hrgn, 0, NULL ); size = rgnsize + offsetof(EMRFRAMERGN,RgnData); emr = HeapAlloc( GetProcessHeap(), 0, size ); GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData ); emr->emr.iType = EMR_FRAMERGN; emr->emr.nSize = size; emr->rclBounds.left = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left; emr->rclBounds.top = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top; emr->rclBounds.right = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1; emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1; emr->cbRgnData = rgnsize; emr->ihBrush = index; emr->szlStroke.cx = width; emr->szlStroke.cy = height; ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
/********************************************************************** * EMFDRV_PolyDraw */ BOOL EMFDRV_PolyDraw( PHYSDEV dev, const POINT *pts, const BYTE *types, DWORD count ) { EMFDRV_PDEVICE *physDev = get_emf_physdev( dev ); EMRPOLYDRAW *emr; BOOL ret; BYTE *types_dest; BOOL use_small_emr = can_use_short_points( pts, count ); DWORD size; size = use_small_emr ? offsetof( EMRPOLYDRAW16, apts[count] ) : offsetof( EMRPOLYDRAW, aptl[count] ); size += (count + 3) & ~3; if (!(emr = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE; emr->emr.iType = use_small_emr ? EMR_POLYDRAW16 : EMR_POLYDRAW; emr->emr.nSize = size; emr->cptl = count; types_dest = store_points( emr->aptl, pts, count, use_small_emr ); memcpy( types_dest, types, count ); if (count & 3) memset( types_dest + count, 0, 4 - (count & 3) ); if (!physDev->path) get_points_bounds( &emr->rclBounds, pts, count, 0 ); else emr->rclBounds = empty_bounds; ret = EMFDRV_WriteRecord( dev, &emr->emr ); if (ret && !physDev->path) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
/********************************************************************* * EMFDRV_PaintInvertRgn * * Helper for EMFDRV_{Paint|Invert}Rgn */ static BOOL EMFDRV_PaintInvertRgn( PHYSDEV dev, HRGN hrgn, DWORD iType ) { EMRINVERTRGN *emr; DWORD size, rgnsize; BOOL ret; rgnsize = GetRegionData( hrgn, 0, NULL ); size = rgnsize + offsetof(EMRINVERTRGN,RgnData); emr = HeapAlloc( GetProcessHeap(), 0, size ); GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData ); emr->emr.iType = iType; emr->emr.nSize = size; emr->rclBounds.left = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left; emr->rclBounds.top = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top; emr->rclBounds.right = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1; emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1; emr->cbRgnData = rgnsize; ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
INT EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits, BITMAPINFO *info, UINT wUsage, DWORD dwRop ) { EMRSTRETCHDIBITS *emr; BOOL ret; UINT bmi_size, emr_size; /* calculate the size of the colour table */ bmi_size = get_dib_info_size(info, wUsage); emr_size = sizeof (EMRSTRETCHDIBITS) + bmi_size + info->bmiHeader.biSizeImage; emr = HeapAlloc(GetProcessHeap(), 0, emr_size ); if (!emr) return 0; /* write a bitmap info header (with colours) to the record */ memcpy( &emr[1], info, bmi_size); /* write bitmap bits to the record */ memcpy ( ( (BYTE *) (&emr[1]) ) + bmi_size, bits, info->bmiHeader.biSizeImage); /* fill in the EMR header at the front of our piece of memory */ emr->emr.iType = EMR_STRETCHDIBITS; emr->emr.nSize = emr_size; emr->xDest = xDst; emr->yDest = yDst; emr->cxDest = widthDst; emr->cyDest = heightDst; emr->dwRop = dwRop; emr->xSrc = xSrc; /* FIXME: only save the piece of the bitmap needed */ emr->ySrc = ySrc; emr->iUsageSrc = wUsage; emr->offBmiSrc = sizeof (EMRSTRETCHDIBITS); emr->cbBmiSrc = bmi_size; emr->offBitsSrc = emr->offBmiSrc + bmi_size; emr->cbBitsSrc = info->bmiHeader.biSizeImage; emr->cxSrc = widthSrc; emr->cySrc = heightSrc; emr->rclBounds.left = xDst; emr->rclBounds.top = yDst; emr->rclBounds.right = xDst + widthDst; emr->rclBounds.bottom = yDst + heightDst; /* save the record we just created */ ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree(GetProcessHeap(), 0, emr); return ret ? heightSrc : GDI_ERROR; }
/********************************************************************** * EMFDRV_PolyPolylinegon * * Helper for EMFDRV_PolyPoly{line|gon} */ static BOOL 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; BOOL ret, use_small_emr, bounds_valid = TRUE; for(poly = 0; poly < polys; poly++) { cptl += counts[poly]; 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; if(bounds_valid && !physDev->path) get_points_bounds( &emr->rclBounds, pt, cptl, 0 ); else emr->rclBounds = empty_bounds; emr->nPolys = polys; emr->cptl = cptl; 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 && !bounds_valid) { ret = FALSE; SetLastError( ERROR_INVALID_PARAMETER ); } if(ret && !physDev->path) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
/********************************************************************** * EMFDRV_GradientFill */ BOOL EMFDRV_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert, void *grad_array, ULONG ngrad, ULONG mode ) { EMRGRADIENTFILL *emr; ULONG i, pt, size, num_pts = ngrad * (mode == GRADIENT_FILL_TRIANGLE ? 3 : 2); const ULONG *pts = (const ULONG *)grad_array; BOOL ret; size = FIELD_OFFSET(EMRGRADIENTFILL, Ver[nvert]) + num_pts * sizeof(pts[0]); emr = HeapAlloc( GetProcessHeap(), 0, size ); if (!emr) return FALSE; for (i = 0; i < num_pts; i++) { pt = pts[i]; if (i == 0) { emr->rclBounds.left = emr->rclBounds.right = vert_array[pt].x; emr->rclBounds.top = emr->rclBounds.bottom = vert_array[pt].y; } else { if (vert_array[pt].x < emr->rclBounds.left) emr->rclBounds.left = vert_array[pt].x; else if (vert_array[pt].x > emr->rclBounds.right) emr->rclBounds.right = vert_array[pt].x; if (vert_array[pt].y < emr->rclBounds.top) emr->rclBounds.top = vert_array[pt].y; else if (vert_array[pt].y > emr->rclBounds.bottom) emr->rclBounds.bottom = vert_array[pt].y; } } emr->rclBounds.right--; emr->rclBounds.bottom--; emr->emr.iType = EMR_GRADIENTFILL; emr->emr.nSize = size; emr->nVer = nvert; emr->nTri = ngrad; emr->ulMode = mode; memcpy( emr->Ver, vert_array, nvert * sizeof(vert_array[0]) ); memcpy( emr->Ver + nvert, pts, num_pts * sizeof(pts[0]) ); EMFDRV_UpdateBBox( dev, &emr->rclBounds ); ret = EMFDRV_WriteRecord( dev, &emr->emr ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
/********************************************************************** * EMFDRV_Polylinegon16 * * Helper for EMFDRV_Poly{line|gon} * * This is not a legacy function! * We are using SHORT integers to save space. */ static BOOL EMFDRV_Polylinegon16( PHYSDEV dev, const POINT* pt, INT count, DWORD iType ) { EMRPOLYLINE16 *emr; DWORD size; INT i; BOOL ret; /* check whether all points fit in the SHORT int POINT structure */ for(i = 0; i < count; i++) { if( ((pt[i].x+0x8000) & ~0xffff ) || ((pt[i].y+0x8000) & ~0xffff ) ) return FALSE; } size = sizeof(EMRPOLYLINE16) + sizeof(POINTS) * (count - 1); emr = HeapAlloc( GetProcessHeap(), 0, size ); emr->emr.iType = iType; emr->emr.nSize = size; emr->rclBounds.left = emr->rclBounds.right = pt[0].x; emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y; for(i = 1; i < count; i++) { if(pt[i].x < emr->rclBounds.left) emr->rclBounds.left = pt[i].x; else if(pt[i].x > emr->rclBounds.right) emr->rclBounds.right = pt[i].x; if(pt[i].y < emr->rclBounds.top) emr->rclBounds.top = pt[i].y; else if(pt[i].y > emr->rclBounds.bottom) emr->rclBounds.bottom = pt[i].y; } emr->cpts = count; for(i = 0; i < count; i++ ) { emr->apts[i].x = pt[i].x; emr->apts[i].y = pt[i].y; } ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
INT CDECL EMFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD width, DWORD height, INT xSrc, INT ySrc, UINT startscan, UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT wUsage ) { EMRSETDIBITSTODEVICE* pEMR; DWORD size, bmiSize, bitsSize; bmiSize = bitmap_info_size(info, wUsage); bitsSize = DIB_GetDIBImageBytes( info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount ); size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + bitsSize; pEMR = HeapAlloc(GetProcessHeap(), 0, size); if (!pEMR) return 0; pEMR->emr.iType = EMR_SETDIBITSTODEVICE; pEMR->emr.nSize = size; pEMR->rclBounds.left = xDst; pEMR->rclBounds.top = yDst; pEMR->rclBounds.right = xDst + width - 1; pEMR->rclBounds.bottom = yDst + height - 1; pEMR->xDest = xDst; pEMR->yDest = yDst; pEMR->xSrc = xSrc; pEMR->ySrc = ySrc; pEMR->cxSrc = width; pEMR->cySrc = height; pEMR->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE); pEMR->cbBmiSrc = bmiSize; pEMR->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize; pEMR->cbBitsSrc = bitsSize; pEMR->iUsageSrc = wUsage; pEMR->iStartScan = startscan; pEMR->cScans = lines; memcpy((BYTE*)pEMR + pEMR->offBmiSrc, info, bmiSize); memcpy((BYTE*)pEMR + pEMR->offBitsSrc, bits, bitsSize); if (EMFDRV_WriteRecord(dev, (EMR*)pEMR)) EMFDRV_UpdateBBox(dev, &(pEMR->rclBounds)); HeapFree( GetProcessHeap(), 0, pEMR); return lines; }
/********************************************************************** * EMFDRV_PolyPolylinegon * * Helper for EMFDRV_PolyPoly{line|gon} */ static BOOL EMFDRV_PolyPolylinegon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys, DWORD iType) { 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; 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); emr = HeapAlloc( GetProcessHeap(), 0, size ); emr->emr.iType = iType; emr->emr.nSize = size; emr->rclBounds = bounds; emr->nPolys = polys; emr->cptl = cptl; memcpy(emr->aPolyCounts, counts, polys * sizeof(DWORD)); memcpy(emr->aPolyCounts + polys, pt, cptl * sizeof(POINTL)); ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
/*********************************************************************** * EMFDRV_SetPixel */ COLORREF EMFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) { EMRSETPIXELV emr; emr.emr.iType = EMR_SETPIXELV; emr.emr.nSize = sizeof(emr); emr.ptlPixel.x = x; emr.ptlPixel.y = y; emr.crColor = color; if (EMFDRV_WriteRecord( dev, &emr.emr )) { RECTL bounds; bounds.left = bounds.right = x; bounds.top = bounds.bottom = y; EMFDRV_UpdateBBox( dev, &bounds ); return color; } return -1; }
/* helper for path stroke and fill functions */ static BOOL emfdrv_stroke_and_fill_path( PHYSDEV dev, INT type ) { EMRSTROKEANDFILLPATH emr; struct gdi_path *path; POINT *points; BYTE *flags; emr.emr.iType = type; emr.emr.nSize = sizeof(emr); if ((path = get_gdi_flat_path( dev->hdc, NULL ))) { int count = get_gdi_path_data( path, &points, &flags ); get_points_bounds( &emr.rclBounds, points, count, 0 ); free_gdi_path( path ); } else emr.rclBounds = empty_bounds; if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; if (!path) return FALSE; EMFDRV_UpdateBBox( dev, &emr.rclBounds ); return TRUE; }
BOOL CDECL EMFDRV_PatBlt( PHYSDEV dev, INT left, INT top, INT width, INT height, DWORD rop ) { EMRBITBLT emr; BOOL ret; emr.emr.iType = EMR_BITBLT; emr.emr.nSize = sizeof(emr); emr.rclBounds.left = left; emr.rclBounds.top = top; emr.rclBounds.right = left + width - 1; emr.rclBounds.bottom = top + height - 1; emr.xDest = left; emr.yDest = top; emr.cxDest = width; emr.cyDest = height; emr.dwRop = rop; emr.xSrc = 0; emr.ySrc = 0; emr.xformSrc.eM11 = 1.0; emr.xformSrc.eM12 = 0.0; emr.xformSrc.eM21 = 0.0; emr.xformSrc.eM22 = 1.0; emr.xformSrc.eDx = 0.0; emr.xformSrc.eDy = 0.0; emr.crBkColorSrc = 0; emr.iUsageSrc = 0; emr.offBmiSrc = 0; emr.cbBmiSrc = 0; emr.offBitsSrc = 0; emr.cbBitsSrc = 0; ret = EMFDRV_WriteRecord( dev, &emr.emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr.rclBounds ); return ret; }
/********************************************************************** * EMFDRV_Polylinegon * * Helper for EMFDRV_Poly{line|gon} */ static BOOL EMFDRV_Polylinegon( PHYSDEV dev, const POINT* pt, INT count, DWORD iType ) { EMRPOLYLINE *emr; DWORD size; INT i; BOOL ret; size = sizeof(EMRPOLYLINE) + sizeof(POINTL) * (count - 1); emr = HeapAlloc( GetProcessHeap(), 0, size ); emr->emr.iType = iType; emr->emr.nSize = size; emr->rclBounds.left = emr->rclBounds.right = pt[0].x; emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y; for(i = 1; i < count; i++) { if(pt[i].x < emr->rclBounds.left) emr->rclBounds.left = pt[i].x; else if(pt[i].x > emr->rclBounds.right) emr->rclBounds.right = pt[i].x; if(pt[i].y < emr->rclBounds.top) emr->rclBounds.top = pt[i].y; else if(pt[i].y > emr->rclBounds.bottom) emr->rclBounds.bottom = pt[i].y; } emr->cptl = count; memcpy(emr->aptl, pt, count * sizeof(POINTL)); ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }
BOOL EMFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) { EMRBITBLT emr; BOOL ret; emr.emr.iType = EMR_BITBLT; emr.emr.nSize = sizeof(emr); emr.rclBounds.left = dst->log_x; emr.rclBounds.top = dst->log_y; emr.rclBounds.right = dst->log_x + dst->log_width - 1; emr.rclBounds.bottom = dst->log_y + dst->log_height - 1; emr.xDest = dst->log_x; emr.yDest = dst->log_y; emr.cxDest = dst->log_width; emr.cyDest = dst->log_height; emr.dwRop = rop; emr.xSrc = 0; emr.ySrc = 0; emr.xformSrc.eM11 = 1.0; emr.xformSrc.eM12 = 0.0; emr.xformSrc.eM21 = 0.0; emr.xformSrc.eM22 = 1.0; emr.xformSrc.eDx = 0.0; emr.xformSrc.eDy = 0.0; emr.crBkColorSrc = 0; emr.iUsageSrc = 0; emr.offBmiSrc = 0; emr.cbBmiSrc = 0; emr.offBitsSrc = 0; emr.cbBitsSrc = 0; ret = EMFDRV_WriteRecord( dev, &emr.emr ); if(ret) EMFDRV_UpdateBBox( dev, &emr.rclBounds ); return ret; }
static BOOL EMFDRV_BitBlockTransfer( PHYSDEV devDst, INT xDst, INT yDst, INT widthDst, INT heightDst, PHYSDEV devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop, DWORD emrType) { BOOL ret; PEMRBITBLT pEMR; UINT emrSize; UINT bmiSize; UINT bitsSize; UINT size; BITMAP BM; WORD nBPP; LPBITMAPINFOHEADER lpBmiH; EMFDRV_PDEVICE* physDevSrc = (EMFDRV_PDEVICE*)devSrc; HBITMAP hBitmap = GetCurrentObject(physDevSrc->hdc, OBJ_BITMAP); if (emrType == EMR_BITBLT) emrSize = sizeof(EMRBITBLT); else if (emrType == EMR_STRETCHBLT) emrSize = sizeof(EMRSTRETCHBLT); else return FALSE; if(sizeof(BITMAP) != GetObjectW(hBitmap, sizeof(BITMAP), &BM)) return FALSE; nBPP = BM.bmPlanes * BM.bmBitsPixel; if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */ bitsSize = DIB_GetDIBWidthBytes(BM.bmWidth, nBPP) * BM.bmHeight; bmiSize = sizeof(BITMAPINFOHEADER) + (nBPP <= 8 ? 1 << nBPP : 0) * sizeof(RGBQUAD); size = emrSize + bmiSize + bitsSize; pEMR = HeapAlloc(GetProcessHeap(), 0, size); if (!pEMR) return FALSE; /* Initialize EMR */ pEMR->emr.iType = emrType; pEMR->emr.nSize = size; pEMR->rclBounds.left = xDst; pEMR->rclBounds.top = yDst; pEMR->rclBounds.right = xDst + widthDst - 1; pEMR->rclBounds.bottom = yDst + heightDst - 1; pEMR->xDest = xDst; pEMR->yDest = yDst; pEMR->cxDest = widthDst; pEMR->cyDest = heightDst; pEMR->dwRop = rop; pEMR->xSrc = xSrc; pEMR->ySrc = ySrc; pEMR->xformSrc.eM11 = 1.0; /** FIXME: */ pEMR->xformSrc.eM12 = 0.0; /** Setting default */ pEMR->xformSrc.eM21 = 0.0; /** value. */ pEMR->xformSrc.eM22 = 1.0; /** Where should we */ pEMR->xformSrc.eDx = 0.0; /** get that info */ pEMR->xformSrc.eDy = 0.0; /** ???? */ pEMR->crBkColorSrc = GetBkColor(physDevSrc->hdc); pEMR->iUsageSrc = DIB_RGB_COLORS; pEMR->offBmiSrc = emrSize; pEMR->cbBmiSrc = bmiSize; pEMR->offBitsSrc = emrSize + bmiSize; pEMR->cbBitsSrc = bitsSize; if (emrType == EMR_STRETCHBLT) { PEMRSTRETCHBLT pEMRStretch = (PEMRSTRETCHBLT)pEMR; pEMRStretch->cxSrc = widthSrc; pEMRStretch->cySrc = heightSrc; } /* Initialize BITMAPINFO structure */ lpBmiH = (LPBITMAPINFOHEADER)((BYTE*)pEMR + pEMR->offBmiSrc); lpBmiH->biSize = sizeof(BITMAPINFOHEADER); lpBmiH->biWidth = BM.bmWidth; lpBmiH->biHeight = BM.bmHeight; lpBmiH->biPlanes = BM.bmPlanes; lpBmiH->biBitCount = nBPP; /* Assume the bitmap isn't compressed and set the BI_RGB flag. */ lpBmiH->biCompression = BI_RGB; lpBmiH->biSizeImage = bitsSize; lpBmiH->biYPelsPerMeter = /* 1 meter = 39.37 inch */ MulDiv(GetDeviceCaps(physDevSrc->hdc,LOGPIXELSX),3937,100); lpBmiH->biXPelsPerMeter = MulDiv(GetDeviceCaps(physDevSrc->hdc,LOGPIXELSY),3937,100); lpBmiH->biClrUsed = nBPP <= 8 ? 1 << nBPP : 0; /* Set biClrImportant to 0, indicating that all of the device colors are important. */ lpBmiH->biClrImportant = 0; /* Initialize bitmap bits */ if (GetDIBits(physDevSrc->hdc, hBitmap, 0, (UINT)lpBmiH->biHeight, (BYTE*)pEMR + pEMR->offBitsSrc, (LPBITMAPINFO)lpBmiH, DIB_RGB_COLORS)) { ret = EMFDRV_WriteRecord(devDst, (EMR*)pEMR); if (ret) EMFDRV_UpdateBBox(devDst, &(pEMR->rclBounds)); } else ret = FALSE; HeapFree( GetProcessHeap(), 0, pEMR); return ret; }
BOOL EMFDRV_StretchBlt( PHYSDEV devDst, struct bitblt_coords *dst, PHYSDEV devSrc, struct bitblt_coords *src, DWORD rop ) { BOOL ret; PEMRBITBLT pEMR; UINT emrSize; UINT bmiSize; UINT bitsSize; UINT size; BITMAP BM; WORD nBPP = 0; LPBITMAPINFOHEADER lpBmiH; HBITMAP hBitmap = NULL; DWORD emrType; if (devSrc->funcs == devDst->funcs) return FALSE; /* can't use a metafile DC as source */ if (src->log_width == dst->log_width && src->log_height == dst->log_height) { emrType = EMR_BITBLT; emrSize = sizeof(EMRBITBLT); } else { emrType = EMR_STRETCHBLT; emrSize = sizeof(EMRSTRETCHBLT); } hBitmap = GetCurrentObject(devSrc->hdc, OBJ_BITMAP); if(sizeof(BITMAP) != GetObjectW(hBitmap, sizeof(BITMAP), &BM)) return FALSE; nBPP = BM.bmPlanes * BM.bmBitsPixel; if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */ bitsSize = get_dib_stride( BM.bmWidth, nBPP ) * BM.bmHeight; bmiSize = sizeof(BITMAPINFOHEADER) + (nBPP <= 8 ? 1 << nBPP : 0) * sizeof(RGBQUAD); size = emrSize + bmiSize + bitsSize; pEMR = HeapAlloc(GetProcessHeap(), 0, size); if (!pEMR) return FALSE; /* Initialize EMR */ pEMR->emr.iType = emrType; pEMR->emr.nSize = size; pEMR->rclBounds.left = dst->log_x; pEMR->rclBounds.top = dst->log_y; pEMR->rclBounds.right = dst->log_x + dst->log_width - 1; pEMR->rclBounds.bottom = dst->log_y + dst->log_height - 1; pEMR->xDest = dst->log_x; pEMR->yDest = dst->log_y; pEMR->cxDest = dst->log_width; pEMR->cyDest = dst->log_height; pEMR->dwRop = rop; pEMR->xSrc = src->log_x; pEMR->ySrc = src->log_y; GetTransform(devSrc->hdc, 0x204, &pEMR->xformSrc); pEMR->crBkColorSrc = GetBkColor(devSrc->hdc); pEMR->iUsageSrc = DIB_RGB_COLORS; pEMR->offBmiSrc = emrSize; pEMR->offBitsSrc = emrSize + bmiSize; pEMR->cbBmiSrc = bmiSize; pEMR->cbBitsSrc = bitsSize; if (emrType == EMR_STRETCHBLT) { PEMRSTRETCHBLT pEMRStretch = (PEMRSTRETCHBLT)pEMR; pEMRStretch->cxSrc = src->log_width; pEMRStretch->cySrc = src->log_height; } /* Initialize BITMAPINFO structure */ lpBmiH = (LPBITMAPINFOHEADER)((BYTE*)pEMR + pEMR->offBmiSrc); lpBmiH->biSize = sizeof(BITMAPINFOHEADER); lpBmiH->biWidth = BM.bmWidth; lpBmiH->biHeight = BM.bmHeight; lpBmiH->biPlanes = BM.bmPlanes; lpBmiH->biBitCount = nBPP; /* Assume the bitmap isn't compressed and set the BI_RGB flag. */ lpBmiH->biCompression = BI_RGB; lpBmiH->biSizeImage = bitsSize; lpBmiH->biYPelsPerMeter = 0; lpBmiH->biXPelsPerMeter = 0; lpBmiH->biClrUsed = nBPP <= 8 ? 1 << nBPP : 0; /* Set biClrImportant to 0, indicating that all of the device colors are important. */ lpBmiH->biClrImportant = 0; /* Initialize bitmap bits */ if (GetDIBits(devSrc->hdc, hBitmap, 0, (UINT)lpBmiH->biHeight, (BYTE*)pEMR + pEMR->offBitsSrc, (LPBITMAPINFO)lpBmiH, DIB_RGB_COLORS)) { ret = EMFDRV_WriteRecord(devDst, (EMR*)pEMR); if (ret) EMFDRV_UpdateBBox(devDst, &(pEMR->rclBounds)); } else ret = FALSE; HeapFree( GetProcessHeap(), 0, pEMR); return ret; }
/********************************************************************** * EMFDRV_ExtTextOut */ BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx ) { EMREXTTEXTOUTW *pemr; DWORD nSize; BOOL ret; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev; int textHeight = 0; int textWidth = 0; const UINT textAlign = GetTextAlign(physDev->hdc); nSize = sizeof(*pemr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT); TRACE("%s %s count %d nSize = %ld\n", debugstr_wn(str, count), wine_dbgstr_rect(lprect), count, nSize); pemr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSize); pemr->emr.iType = EMR_EXTTEXTOUTW; pemr->emr.nSize = nSize; pemr->iGraphicsMode = GetGraphicsMode(physDev->hdc); pemr->exScale = pemr->eyScale = 1.0; /* FIXME */ pemr->emrtext.ptlReference.x = x; pemr->emrtext.ptlReference.y = y; pemr->emrtext.nChars = count; pemr->emrtext.offString = sizeof(*pemr); memcpy((char*)pemr + pemr->emrtext.offString, str, count * sizeof(WCHAR)); pemr->emrtext.fOptions = flags; if(!lprect) { pemr->emrtext.rcl.left = pemr->emrtext.rcl.top = 0; pemr->emrtext.rcl.right = pemr->emrtext.rcl.bottom = -1; } else { pemr->emrtext.rcl.left = lprect->left; pemr->emrtext.rcl.top = lprect->top; pemr->emrtext.rcl.right = lprect->right; pemr->emrtext.rcl.bottom = lprect->bottom; } pemr->emrtext.offDx = pemr->emrtext.offString + ((count+1) & ~1) * sizeof(WCHAR); if(lpDx) { UINT i; SIZE strSize; memcpy((char*)pemr + pemr->emrtext.offDx, lpDx, count * sizeof(INT)); for (i = 0; i < count; i++) { textWidth += lpDx[i]; } GetTextExtentPoint32W(physDev->hdc, str, count, &strSize); textHeight = strSize.cy; } else { UINT i; INT *dx = (INT *)((char*)pemr + pemr->emrtext.offDx); SIZE charSize; for (i = 0; i < count; i++) { GetTextExtentPoint32W(physDev->hdc, str + i, 1, &charSize); dx[i] = charSize.cx; textWidth += charSize.cx; textHeight = max(textHeight, charSize.cy); } } switch (textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER)) { case TA_CENTER: { pemr->rclBounds.left = x - (textWidth / 2) - 1; pemr->rclBounds.right = x + (textWidth / 2) + 1; break; } case TA_RIGHT: { pemr->rclBounds.left = x - textWidth - 1; pemr->rclBounds.right = x; break; } default: { /* TA_LEFT */ pemr->rclBounds.left = x; pemr->rclBounds.right = x + textWidth + 1; } } switch (textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE)) { case TA_BASELINE: { TEXTMETRICW tm; GetTextMetricsW(physDev->hdc, &tm); /* Play safe here... it's better to have a bounding box */ /* that is too big than too small. */ pemr->rclBounds.top = y - textHeight - 1; pemr->rclBounds.bottom = y + tm.tmDescent + 1; break; } case TA_BOTTOM: { pemr->rclBounds.top = y - textHeight - 1; pemr->rclBounds.bottom = y; break; } default: { /* TA_TOP */ pemr->rclBounds.top = y; pemr->rclBounds.bottom = y + textHeight + 1; } } ret = EMFDRV_WriteRecord( dev, &pemr->emr ); if(ret) EMFDRV_UpdateBBox( dev, &pemr->rclBounds ); HeapFree( GetProcessHeap(), 0, pemr ); return ret; }
/********************************************************************** * EMFDRV_ExtTextOut */ BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx ) { EMFDRV_PDEVICE *physDev = get_emf_physdev( dev ); DC *dc = get_physdev_dc( dev ); EMREXTTEXTOUTW *pemr; DWORD nSize; BOOL ret; int textHeight = 0; int textWidth = 0; const UINT textAlign = dc->textAlign; const INT graphicsMode = dc->GraphicsMode; FLOAT exScale, eyScale; nSize = sizeof(*pemr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT); TRACE("%s %s count %d nSize = %d\n", debugstr_wn(str, count), wine_dbgstr_rect(lprect), count, nSize); pemr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSize); if (graphicsMode == GM_COMPATIBLE) { const INT horzSize = GetDeviceCaps( dev->hdc, HORZSIZE ); const INT horzRes = GetDeviceCaps( dev->hdc, HORZRES ); const INT vertSize = GetDeviceCaps( dev->hdc, VERTSIZE ); const INT vertRes = GetDeviceCaps( dev->hdc, VERTRES ); SIZE wndext, vportext; GetViewportExtEx( dev->hdc, &vportext ); GetWindowExtEx( dev->hdc, &wndext ); exScale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) / ((FLOAT)wndext.cx / (FLOAT)vportext.cx); eyScale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) / ((FLOAT)wndext.cy / (FLOAT)vportext.cy); } else { exScale = 0.0; eyScale = 0.0; } pemr->emr.iType = EMR_EXTTEXTOUTW; pemr->emr.nSize = nSize; pemr->iGraphicsMode = graphicsMode; pemr->exScale = exScale; pemr->eyScale = eyScale; pemr->emrtext.ptlReference.x = x; pemr->emrtext.ptlReference.y = y; pemr->emrtext.nChars = count; pemr->emrtext.offString = sizeof(*pemr); memcpy((char*)pemr + pemr->emrtext.offString, str, count * sizeof(WCHAR)); pemr->emrtext.fOptions = flags; if(!lprect) { pemr->emrtext.rcl.left = pemr->emrtext.rcl.top = 0; pemr->emrtext.rcl.right = pemr->emrtext.rcl.bottom = -1; } else { pemr->emrtext.rcl.left = lprect->left; pemr->emrtext.rcl.top = lprect->top; pemr->emrtext.rcl.right = lprect->right; pemr->emrtext.rcl.bottom = lprect->bottom; } pemr->emrtext.offDx = pemr->emrtext.offString + ((count+1) & ~1) * sizeof(WCHAR); if(lpDx) { UINT i; SIZE strSize; memcpy((char*)pemr + pemr->emrtext.offDx, lpDx, count * sizeof(INT)); for (i = 0; i < count; i++) { textWidth += lpDx[i]; } if (GetTextExtentPoint32W( dev->hdc, str, count, &strSize )) textHeight = strSize.cy; } else { UINT i; INT *dx = (INT *)((char*)pemr + pemr->emrtext.offDx); SIZE charSize; for (i = 0; i < count; i++) { if (GetTextExtentPoint32W( dev->hdc, str + i, 1, &charSize )) { dx[i] = charSize.cx; textWidth += charSize.cx; textHeight = max(textHeight, charSize.cy); } } } if (physDev->path) { pemr->rclBounds.left = pemr->rclBounds.top = 0; pemr->rclBounds.right = pemr->rclBounds.bottom = -1; goto no_bounds; } /* FIXME: handle font escapement */ switch (textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER)) { case TA_CENTER: { pemr->rclBounds.left = x - (textWidth / 2) - 1; pemr->rclBounds.right = x + (textWidth / 2) + 1; break; } case TA_RIGHT: { pemr->rclBounds.left = x - textWidth - 1; pemr->rclBounds.right = x; break; } default: { /* TA_LEFT */ pemr->rclBounds.left = x; pemr->rclBounds.right = x + textWidth + 1; } } switch (textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE)) { case TA_BASELINE: { TEXTMETRICW tm; if (!GetTextMetricsW( dev->hdc, &tm )) tm.tmDescent = 0; /* Play safe here... it's better to have a bounding box */ /* that is too big than too small. */ pemr->rclBounds.top = y - textHeight - 1; pemr->rclBounds.bottom = y + tm.tmDescent + 1; break; } case TA_BOTTOM: { pemr->rclBounds.top = y - textHeight - 1; pemr->rclBounds.bottom = y; break; } default: { /* TA_TOP */ pemr->rclBounds.top = y; pemr->rclBounds.bottom = y + textHeight + 1; } } EMFDRV_UpdateBBox( dev, &pemr->rclBounds ); no_bounds: ret = EMFDRV_WriteRecord( dev, &pemr->emr ); HeapFree( GetProcessHeap(), 0, pemr ); return ret; }
/*********************************************************************** * EMFDRV_ArcChordPie */ static BOOL EMFDRV_ArcChordPie( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend, DWORD iType ) { INT temp, xCentre, yCentre, i; double angleStart, angleEnd; double xinterStart, yinterStart, xinterEnd, yinterEnd; EMRARC emr; RECTL bounds; EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; if(left == right || top == bottom) return FALSE; if(left > right) {temp = left; left = right; right = temp;} if(top > bottom) {temp = top; top = bottom; bottom = temp;} if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) { right--; bottom--; } emr.emr.iType = iType; emr.emr.nSize = sizeof(emr); emr.rclBox.left = left; emr.rclBox.top = top; emr.rclBox.right = right; emr.rclBox.bottom = bottom; emr.ptlStart.x = xstart; emr.ptlStart.y = ystart; emr.ptlEnd.x = xend; emr.ptlEnd.x = yend; /* Now calculate the BBox */ xCentre = (left + right + 1) / 2; yCentre = (top + bottom + 1) / 2; xstart -= xCentre; ystart -= yCentre; xend -= xCentre; yend -= yCentre; /* invert y co-ords to get angle anti-clockwise from x-axis */ angleStart = atan2( -(double)ystart, (double)xstart); angleEnd = atan2( -(double)yend, (double)xend); /* These are the intercepts of the start/end lines with the arc */ xinterStart = (right - left + 1)/2 * cos(angleStart) + xCentre; yinterStart = -(bottom - top + 1)/2 * sin(angleStart) + yCentre; xinterEnd = (right - left + 1)/2 * cos(angleEnd) + xCentre; yinterEnd = -(bottom - top + 1)/2 * sin(angleEnd) + yCentre; if(angleStart < 0) angleStart += 2 * M_PI; if(angleEnd < 0) angleEnd += 2 * M_PI; if(angleEnd < angleStart) angleEnd += 2 * M_PI; bounds.left = min(xinterStart, xinterEnd); bounds.top = min(yinterStart, yinterEnd); bounds.right = max(xinterStart, xinterEnd); bounds.bottom = max(yinterStart, yinterEnd); for(i = 0; i <= 8; i++) { if(i * M_PI / 2 < angleStart) /* loop until we're past start */ continue; if(i * M_PI / 2 > angleEnd) /* if we're past end we're finished */ break; /* the arc touches the rectangle at the start of quadrant i, so adjust BBox to reflect this. */ switch(i % 4) { case 0: bounds.right = right; break; case 1: bounds.top = top; break; case 2: bounds.left = left; break; case 3: bounds.bottom = bottom; break; } } /* If we're drawing a pie then make sure we include the centre */ if(iType == EMR_PIE) { if(bounds.left > xCentre) bounds.left = xCentre; else if(bounds.right < xCentre) bounds.right = xCentre; if(bounds.top > yCentre) bounds.top = yCentre; else if(bounds.bottom < yCentre) bounds.right = yCentre; } if(!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; EMFDRV_UpdateBBox( dev, &bounds ); return TRUE; }
/********************************************************************** * EMFDRV_PolyPolylinegon * * Helper for EMFDRV_PolyPoly{line|gon} */ static BOOL EMFDRV_PolyPolylinegon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys, DWORD iType) { EMRPOLYPOLYLINE *emr; DWORD cptl = 0, poly, size, i; INT point; const RECTL empty = {0, 0, -1, -1}; RECTL bounds = empty; const POINT *pts; BOOL ret, use_small_emr = TRUE, bounds_valid = TRUE; pts = pt; for(poly = 0; poly < polys; poly++) { cptl += counts[poly]; if(counts[poly] < 2) bounds_valid = FALSE; for(point = 0; point < counts[poly]; point++) { /* check whether all points fit in the SHORT int POINT structure */ if( ((pts->x+0x8000) & ~0xffff ) || ((pts->y+0x8000) & ~0xffff ) ) use_small_emr = FALSE; if(pts == pt) { bounds.left = bounds.right = pts->x; bounds.top = bounds.bottom = pts->y; } else { 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++; } } if(!cptl) bounds_valid = FALSE; 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; if(bounds_valid) emr->rclBounds = bounds; else emr->rclBounds = empty; emr->nPolys = polys; emr->cptl = cptl; if(polys) { memcpy( emr->aPolyCounts, counts, polys * sizeof(DWORD) ); if(cptl) { if(use_small_emr) { POINTS *out_pts = (POINTS *)(emr->aPolyCounts + polys); for(i = 0; i < cptl; i++ ) { out_pts[i].x = pt[i].x; out_pts[i].y = pt[i].y; } } else memcpy( emr->aPolyCounts + polys, pt, cptl * sizeof(POINTL) ); } } ret = EMFDRV_WriteRecord( dev, &emr->emr ); if(ret && !bounds_valid) { ret = FALSE; SetLastError( ERROR_INVALID_PARAMETER ); } if(ret) EMFDRV_UpdateBBox( dev, &emr->rclBounds ); HeapFree( GetProcessHeap(), 0, emr ); return ret; }