wininet: Don't change the verb if the server response is HTTP_STATUS_REDIRECT_KEEP_VERB.
[wine] / dlls / gdi32 / painting.c
index 3e84f60..22cc50c 100644 (file)
 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
 
 
+/***********************************************************************
+ *           null driver fallback implementations
+ */
+
+BOOL CDECL nulldrv_AngleArc( PHYSDEV dev, INT x, INT y, DWORD radius, FLOAT start, FLOAT sweep )
+{
+    INT x1 = GDI_ROUND( x + cos( start * M_PI / 180 ) * radius );
+    INT y1 = GDI_ROUND( y - sin( start * M_PI / 180 ) * radius );
+    INT x2 = GDI_ROUND( x + cos( (start + sweep) * M_PI / 180) * radius );
+    INT y2 = GDI_ROUND( y - sin( (start + sweep) * M_PI / 180) * radius );
+    INT arcdir = SetArcDirection( dev->hdc, sweep >= 0 ? AD_COUNTERCLOCKWISE : AD_CLOCKWISE );
+    BOOL ret = ArcTo( dev->hdc, x - radius, y - radius, x + radius, y + radius, x1, y1, x2, y2 );
+    SetArcDirection( dev->hdc, arcdir );
+    return ret;
+}
+
+BOOL CDECL nulldrv_ArcTo( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
+                          INT xstart, INT ystart, INT xend, INT yend )
+{
+    INT width = abs( right - left );
+    INT height = abs( bottom - top );
+    double xradius = width / 2.0;
+    double yradius = height / 2.0;
+    double xcenter = right > left ? left + xradius : right + xradius;
+    double ycenter = bottom > top ? top + yradius : bottom + yradius;
+    double angle;
+
+    if (!height || !width) return FALSE;
+    /* draw a line from the current position to the starting point of the arc, then draw the arc */
+    angle = atan2( (ystart - ycenter) / height, (xstart - xcenter) / width );
+    LineTo( dev->hdc, GDI_ROUND( xcenter + cos(angle) * xradius ),
+            GDI_ROUND( ycenter + sin(angle) * yradius ));
+    return Arc( dev->hdc, left, top, right, bottom, xstart, ystart, xend, yend );
+}
+
+BOOL CDECL nulldrv_FillRgn( PHYSDEV dev, HRGN rgn, HBRUSH brush )
+{
+    BOOL ret = FALSE;
+    HBRUSH prev;
+
+    if ((prev = SelectObject( dev->hdc, brush )))
+    {
+        ret = PaintRgn( dev->hdc, rgn );
+        SelectObject( dev->hdc, prev );
+    }
+    return ret;
+}
+
+BOOL CDECL nulldrv_FrameRgn( PHYSDEV dev, HRGN rgn, HBRUSH brush, INT width, INT height )
+{
+    BOOL ret = FALSE;
+    HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
+
+    if (tmp)
+    {
+        if (REGION_FrameRgn( tmp, rgn, width, height )) ret = FillRgn( dev->hdc, tmp, brush );
+        DeleteObject( tmp );
+    }
+    return ret;
+}
+
+BOOL CDECL nulldrv_InvertRgn( PHYSDEV dev, HRGN rgn )
+{
+    HBRUSH prev_brush = SelectObject( dev->hdc, GetStockObject(BLACK_BRUSH) );
+    INT prev_rop = SetROP2( dev->hdc, R2_NOT );
+    BOOL ret = PaintRgn( dev->hdc, rgn );
+    SelectObject( dev->hdc, prev_brush );
+    SetROP2( dev->hdc, prev_rop );
+    return ret;
+}
+
+BOOL CDECL nulldrv_PolyBezier( PHYSDEV dev, const POINT *points, DWORD count )
+{
+    BOOL ret = FALSE;
+    POINT *pts;
+    INT n;
+
+    if ((pts = GDI_Bezier( points, count, &n )))
+    {
+        ret = Polyline( dev->hdc, pts, n );
+        HeapFree( GetProcessHeap(), 0, pts );
+    }
+    return ret;
+}
+
+BOOL CDECL nulldrv_PolyBezierTo( PHYSDEV dev, const POINT *points, DWORD count )
+{
+    BOOL ret = FALSE;
+    POINT *pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINT) * (count + 1) );
+
+    if (pts)
+    {
+        GetCurrentPositionEx( dev->hdc, &pts[0] );
+        memcpy( pts + 1, points, sizeof(POINT) * count );
+        ret = PolyBezier( dev->hdc, pts, count + 1 );
+        HeapFree( GetProcessHeap(), 0, pts );
+    }
+    return ret;
+}
+
+BOOL CDECL nulldrv_PolyDraw( PHYSDEV dev, const POINT *points, const BYTE *types, DWORD count )
+{
+    POINT *line_pts = NULL, *bzr_pts = NULL, bzr[4];
+    INT i, num_pts, num_bzr_pts, space, size;
+
+    /* check for valid point types */
+    for (i = 0; i < count; i++)
+    {
+        switch (types[i])
+        {
+        case PT_MOVETO:
+        case PT_LINETO | PT_CLOSEFIGURE:
+        case PT_LINETO:
+            break;
+        case PT_BEZIERTO:
+            if((i + 2 < count) && (types[i + 1] == PT_BEZIERTO) &&
+               ((types[i + 2] & ~PT_CLOSEFIGURE) == PT_BEZIERTO))
+            {
+                i += 2;
+                break;
+            }
+        default:
+            return FALSE;
+        }
+    }
+
+    space = count + 300;
+    line_pts = HeapAlloc( GetProcessHeap(), 0, space * sizeof(POINT) );
+    num_pts = 1;
+
+    GetCurrentPositionEx( dev->hdc, &line_pts[0] );
+    for (i = 0; i < count; i++)
+    {
+        switch (types[i])
+        {
+        case PT_MOVETO:
+            if (num_pts >= 2) Polyline( dev->hdc, line_pts, num_pts );
+            num_pts = 0;
+            line_pts[num_pts++] = points[i];
+            break;
+        case PT_LINETO:
+        case (PT_LINETO | PT_CLOSEFIGURE):
+            line_pts[num_pts++] = points[i];
+            break;
+        case PT_BEZIERTO:
+            bzr[0].x = line_pts[num_pts - 1].x;
+            bzr[0].y = line_pts[num_pts - 1].y;
+            memcpy( &bzr[1], &points[i], 3 * sizeof(POINT) );
+
+            if ((bzr_pts = GDI_Bezier( bzr, 4, &num_bzr_pts )))
+            {
+                size = num_pts + (count - i) + num_bzr_pts;
+                if (space < size)
+                {
+                    space = size * 2;
+                    line_pts = HeapReAlloc( GetProcessHeap(), 0, line_pts, space * sizeof(POINT) );
+                }
+                memcpy( &line_pts[num_pts], &bzr_pts[1], (num_bzr_pts - 1) * sizeof(POINT) );
+                num_pts += num_bzr_pts - 1;
+                HeapFree( GetProcessHeap(), 0, bzr_pts );
+            }
+            i += 2;
+            break;
+        }
+        if (types[i] & PT_CLOSEFIGURE) line_pts[num_pts++] = line_pts[0];
+    }
+
+    if (num_pts >= 2) Polyline( dev->hdc, line_pts, num_pts );
+    MoveToEx( dev->hdc, line_pts[num_pts - 1].x, line_pts[num_pts - 1].y, NULL );
+    HeapFree( GetProcessHeap(), 0, line_pts );
+    return TRUE;
+}
+
+BOOL CDECL nulldrv_PolylineTo( PHYSDEV dev, const POINT *points, INT count )
+{
+    BOOL ret = FALSE;
+    POINT *pts;
+
+    if (!count) return FALSE;
+    if ((pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINT) * (count + 1) )))
+    {
+        GetCurrentPositionEx( dev->hdc, &pts[0] );
+        memcpy( pts + 1, points, sizeof(POINT) * count );
+        ret = Polyline( dev->hdc, pts, count + 1 );
+        HeapFree( GetProcessHeap(), 0, pts );
+    }
+    return ret;
+}
+
 /***********************************************************************
  *           LineTo    (GDI32.@)
  */
 BOOL WINAPI LineTo( HDC hdc, INT x, INT y )
 {
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
     BOOL ret;
 
     if(!dc) return FALSE;
 
+    update_dc( dc );
     if(PATH_IsPathOpen(dc->path))
         ret = PATH_LineTo(dc, x, y);
     else
-        ret = dc->funcs->pLineTo && dc->funcs->pLineTo(dc->physDev,x,y);
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pLineTo );
+        ret = physdev->funcs->pLineTo( physdev, x, y );
+    }
     if(ret) {
         dc->CursPosX = x;
         dc->CursPosY = y;
     }
-    GDI_ReleaseObj( hdc );
+    release_dc_ptr( dc );
     return ret;
 }
 
@@ -66,7 +259,7 @@ BOOL WINAPI LineTo( HDC hdc, INT x, INT y )
 BOOL WINAPI MoveToEx( HDC hdc, INT x, INT y, LPPOINT pt )
 {
     BOOL ret = TRUE;
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = get_dc_ptr( hdc );
 
     if(!dc) return FALSE;
 
@@ -78,8 +271,12 @@ BOOL WINAPI MoveToEx( HDC hdc, INT x, INT y, LPPOINT pt )
     dc->CursPosY = y;
 
     if(PATH_IsPathOpen(dc->path)) ret = PATH_MoveTo(dc);
-    else if (dc->funcs->pMoveTo) ret = dc->funcs->pMoveTo(dc->physDev,x,y);
-    GDI_ReleaseObj( hdc );
+    else
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pMoveTo );
+        ret = physdev->funcs->pMoveTo( physdev, x, y );
+    }
+    release_dc_ptr( dc );
     return ret;
 }
 
@@ -92,14 +289,19 @@ BOOL WINAPI Arc( HDC hdc, INT left, INT top, INT right,
                      INT xend, INT yend )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
-    if(PATH_IsPathOpen(dc->path))
+        update_dc( dc );
+        if(PATH_IsPathOpen(dc->path))
             ret = PATH_Arc(dc, left, top, right, bottom, xstart, ystart, xend, yend,0);
-        else if (dc->funcs->pArc)
-            ret = dc->funcs->pArc(dc->physDev,left,top,right,bottom,xstart,ystart,xend,yend);
-        GDI_ReleaseObj( hdc );
+        else
+        {
+            PHYSDEV physdev = GET_DC_PHYSDEV( dc, pArc );
+            ret = physdev->funcs->pArc( physdev, left, top, right, bottom, xstart, ystart, xend, yend );
+        }
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -121,21 +323,16 @@ BOOL WINAPI ArcTo( HDC hdc,
         ycenter = bottom > top ? top+yradius : bottom+yradius,
         angle;
     BOOL result;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
     if(!dc) return FALSE;
 
+    update_dc( dc );
     if(PATH_IsPathOpen(dc->path))
         result = PATH_Arc(dc,left,top,right,bottom,xstart,ystart,xend,yend,-1);
-    else if(dc->funcs->pArcTo)
-        result = dc->funcs->pArcTo( dc->physDev, left, top, right, bottom,
-                                 xstart, ystart, xend, yend );
-    else /* We'll draw a line from the current position to the starting point of the arc, then draw the arc */
+    else
     {
-        angle = atan2(((ystart-ycenter)/height),
-                      ((xstart-xcenter)/width));
-        LineTo(hdc, GDI_ROUND(xcenter+(cos(angle)*xradius)),
-               GDI_ROUND(ycenter+(sin(angle)*yradius)));
-        result = Arc(hdc, left, top, right, bottom, xstart, ystart, xend, yend);
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pArcTo );
+        result = physdev->funcs->pArcTo( physdev, left, top, right, bottom, xstart, ystart, xend, yend );
     }
     if (result) {
         angle = atan2(((yend-ycenter)/height),
@@ -143,7 +340,7 @@ BOOL WINAPI ArcTo( HDC hdc,
         dc->CursPosX = GDI_ROUND(xcenter+(cos(angle)*xradius));
         dc->CursPosY = GDI_ROUND(ycenter+(sin(angle)*yradius));
     }
-    GDI_ReleaseObj( hdc );
+    release_dc_ptr( dc );
     return result;
 }
 
@@ -156,15 +353,18 @@ BOOL WINAPI Pie( HDC hdc, INT left, INT top,
                      INT xend, INT yend )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
     if (!dc) return FALSE;
 
+    update_dc( dc );
     if(PATH_IsPathOpen(dc->path))
         ret = PATH_Arc(dc,left,top,right,bottom,xstart,ystart,xend,yend,2);
-    else if(dc->funcs->pPie)
-        ret = dc->funcs->pPie(dc->physDev,left,top,right,bottom,xstart,ystart,xend,yend);
-
-    GDI_ReleaseObj( hdc );
+    else
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPie );
+        ret = physdev->funcs->pPie( physdev, left, top, right, bottom, xstart, ystart, xend, yend );
+    }
+    release_dc_ptr( dc );
     return ret;
 }
 
@@ -177,15 +377,18 @@ BOOL WINAPI Chord( HDC hdc, INT left, INT top,
                        INT xend, INT yend )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
     if (!dc) return FALSE;
 
+    update_dc( dc );
     if(PATH_IsPathOpen(dc->path))
        ret = PATH_Arc(dc,left,top,right,bottom,xstart,ystart,xend,yend,1);
-    else if(dc->funcs->pChord)
-        ret = dc->funcs->pChord(dc->physDev,left,top,right,bottom,xstart,ystart,xend,yend);
-
-    GDI_ReleaseObj( hdc );
+    else
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pChord );
+        ret = physdev->funcs->pChord( physdev, left, top, right, bottom, xstart, ystart, xend, yend );
+    }
+    release_dc_ptr( dc );
     return ret;
 }
 
@@ -197,15 +400,19 @@ BOOL WINAPI Ellipse( HDC hdc, INT left, INT top,
                          INT right, INT bottom )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
     if (!dc) return FALSE;
 
+    update_dc( dc );
     if(PATH_IsPathOpen(dc->path))
        ret = PATH_Ellipse(dc,left,top,right,bottom);
-    else if (dc->funcs->pEllipse)
-        ret = dc->funcs->pEllipse(dc->physDev,left,top,right,bottom);
+    else
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEllipse );
+        ret = physdev->funcs->pEllipse( physdev, left, top, right, bottom );
+    }
 
-    GDI_ReleaseObj( hdc );
+    release_dc_ptr( dc );
     return ret;
 }
 
@@ -217,14 +424,19 @@ BOOL WINAPI Rectangle( HDC hdc, INT left, INT top,
                            INT right, INT bottom )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
-    if(PATH_IsPathOpen(dc->path))
+        update_dc( dc );
+        if(PATH_IsPathOpen(dc->path))
             ret = PATH_Rectangle(dc, left, top, right, bottom);
-        else if (dc->funcs->pRectangle)
-            ret = dc->funcs->pRectangle(dc->physDev,left,top,right,bottom);
-        GDI_ReleaseObj( hdc );
+        else
+        {
+            PHYSDEV physdev = GET_DC_PHYSDEV( dc, pRectangle );
+            ret = physdev->funcs->pRectangle( physdev, left, top, right, bottom );
+        }
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -237,15 +449,19 @@ BOOL WINAPI RoundRect( HDC hdc, INT left, INT top, INT right,
                            INT bottom, INT ell_width, INT ell_height )
 {
     BOOL ret = FALSE;
-    DC *dc = DC_GetDCUpdate( hdc );
+    DC *dc = get_dc_ptr( hdc );
 
     if (dc)
     {
+        update_dc( dc );
         if(PATH_IsPathOpen(dc->path))
            ret = PATH_RoundRect(dc,left,top,right,bottom,ell_width,ell_height);
-        else if (dc->funcs->pRoundRect)
-            ret = dc->funcs->pRoundRect(dc->physDev,left,top,right,bottom,ell_width,ell_height);
-        GDI_ReleaseObj( hdc );
+        else
+        {
+            PHYSDEV physdev = GET_DC_PHYSDEV( dc, pRoundRect );
+            ret = physdev->funcs->pRoundRect( physdev, left, top, right, bottom, ell_width, ell_height );
+        }
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -256,11 +472,14 @@ BOOL WINAPI RoundRect( HDC hdc, INT left, INT top, INT right,
 COLORREF WINAPI SetPixel( HDC hdc, INT x, INT y, COLORREF color )
 {
     COLORREF ret = 0;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
-        if (dc->funcs->pSetPixel) ret = dc->funcs->pSetPixel(dc->physDev,x,y,color);
-        GDI_ReleaseObj( hdc );
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetPixel );
+        update_dc( dc );
+        ret = physdev->funcs->pSetPixel( physdev, x, y, color );
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -271,15 +490,15 @@ COLORREF WINAPI SetPixel( HDC hdc, INT x, INT y, COLORREF color )
 BOOL WINAPI SetPixelV( HDC hdc, INT x, INT y, COLORREF color )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
-        if (dc->funcs->pSetPixel)
-        {
-            dc->funcs->pSetPixel(dc->physDev,x,y,color);
-            ret = TRUE;
-        }
-        GDI_ReleaseObj( hdc );
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetPixel );
+        update_dc( dc );
+        physdev->funcs->pSetPixel( physdev, x, y, color );
+        ret = TRUE;
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -290,16 +509,18 @@ BOOL WINAPI SetPixelV( HDC hdc, INT x, INT y, COLORREF color )
 COLORREF WINAPI GetPixel( HDC hdc, INT x, INT y )
 {
     COLORREF ret = CLR_INVALID;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
 
     if (dc)
     {
-    /* FIXME: should this be in the graphics driver? */
+        update_dc( dc );
+        /* FIXME: should this be in the graphics driver? */
         if (PtVisible( hdc, x, y ))
         {
-            if (dc->funcs->pGetPixel) ret = dc->funcs->pGetPixel(dc->physDev,x,y);
+            PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetPixel );
+            ret = physdev->funcs->pGetPixel( physdev, x, y );
         }
-        GDI_ReleaseObj( hdc );
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -320,16 +541,16 @@ COLORREF WINAPI GetPixel( HDC hdc, INT x, INT y )
 INT WINAPI ChoosePixelFormat( HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd )
 {
     INT ret = 0;
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = get_dc_ptr( hdc );
 
     TRACE("(%p,%p)\n",hdc,ppfd);
 
-    if (!dc) return 0;
-
-    if (!dc->funcs->pChoosePixelFormat) FIXME(" :stub\n");
-    else ret = dc->funcs->pChoosePixelFormat(dc->physDev,ppfd);
-
-    GDI_ReleaseObj( hdc );
+    if (dc)
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pChoosePixelFormat );
+        ret = physdev->funcs->pChoosePixelFormat( physdev, ppfd );
+        release_dc_ptr( dc );
+    }
     return ret;
 }
 
@@ -351,16 +572,17 @@ BOOL WINAPI SetPixelFormat( HDC hdc, INT iPixelFormat,
                             const PIXELFORMATDESCRIPTOR *ppfd)
 {
     INT bRet = FALSE;
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = get_dc_ptr( hdc );
 
     TRACE("(%p,%d,%p)\n",hdc,iPixelFormat,ppfd);
 
-    if (!dc) return 0;
-
-    if (!dc->funcs->pSetPixelFormat) FIXME(" :stub\n");
-    else bRet = dc->funcs->pSetPixelFormat(dc->physDev,iPixelFormat,ppfd);
-
-    GDI_ReleaseObj( hdc );
+    if (dc)
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetPixelFormat );
+        update_dc( dc );
+        bRet = physdev->funcs->pSetPixelFormat( physdev, iPixelFormat, ppfd );
+        release_dc_ptr( dc );
+    }
     return bRet;
 }
 
@@ -379,16 +601,17 @@ BOOL WINAPI SetPixelFormat( HDC hdc, INT iPixelFormat,
 INT WINAPI GetPixelFormat( HDC hdc )
 {
     INT ret = 0;
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = get_dc_ptr( hdc );
 
     TRACE("(%p)\n",hdc);
 
-    if (!dc) return 0;
-
-    if (!dc->funcs->pGetPixelFormat) FIXME(" :stub\n");
-    else ret = dc->funcs->pGetPixelFormat(dc->physDev);
-
-    GDI_ReleaseObj( hdc );
+    if (dc)
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetPixelFormat );
+        update_dc( dc );
+        ret = physdev->funcs->pGetPixelFormat( physdev );
+        release_dc_ptr( dc );
+    }
     return ret;
 }
 
@@ -411,22 +634,17 @@ INT WINAPI DescribePixelFormat( HDC hdc, INT iPixelFormat, UINT nBytes,
                                 LPPIXELFORMATDESCRIPTOR ppfd )
 {
     INT ret = 0;
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = get_dc_ptr( hdc );
 
     TRACE("(%p,%d,%d,%p): stub\n",hdc,iPixelFormat,nBytes,ppfd);
 
-    if (!dc) return 0;
-
-    if (!dc->funcs->pDescribePixelFormat)
+    if (dc)
     {
-        FIXME(" :stub\n");
-        ppfd->nSize = nBytes;
-        ppfd->nVersion = 1;
-       ret = 3;
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pDescribePixelFormat );
+        update_dc( dc );
+        ret = physdev->funcs->pDescribePixelFormat( physdev, iPixelFormat, nBytes, ppfd );
+        release_dc_ptr( dc );
     }
-    else ret = dc->funcs->pDescribePixelFormat(dc->physDev,iPixelFormat,nBytes,ppfd);
-
-    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -445,20 +663,17 @@ INT WINAPI DescribePixelFormat( HDC hdc, INT iPixelFormat, UINT nBytes,
 BOOL WINAPI SwapBuffers( HDC hdc )
 {
     INT bRet = FALSE;
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = get_dc_ptr( hdc );
 
     TRACE("(%p)\n",hdc);
 
-    if (!dc) return TRUE;
-
-    if (!dc->funcs->pSwapBuffers)
+    if (dc)
     {
-        FIXME(" :stub\n");
-       bRet = TRUE;
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSwapBuffers );
+        update_dc( dc );
+        bRet = physdev->funcs->pSwapBuffers( physdev );
+        release_dc_ptr( dc );
     }
-    else bRet = dc->funcs->pSwapBuffers(dc->physDev);
-
-    GDI_ReleaseObj( hdc );
     return bRet;
 }
 
@@ -469,11 +684,14 @@ BOOL WINAPI SwapBuffers( HDC hdc )
 BOOL WINAPI PaintRgn( HDC hdc, HRGN hrgn )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
-        if (dc->funcs->pPaintRgn) ret = dc->funcs->pPaintRgn(dc->physDev,hrgn);
-        GDI_ReleaseObj( hdc );
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPaintRgn );
+        update_dc( dc );
+        ret = physdev->funcs->pPaintRgn( physdev, hrgn );
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -485,18 +703,15 @@ BOOL WINAPI PaintRgn( HDC hdc, HRGN hrgn )
 BOOL WINAPI FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
 {
     BOOL retval = FALSE;
-    HBRUSH prevBrush;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
 
-    if (!dc) return FALSE;
-    if(dc->funcs->pFillRgn)
-        retval = dc->funcs->pFillRgn(dc->physDev, hrgn, hbrush);
-    else if ((prevBrush = SelectObject( hdc, hbrush )))
+    if (dc)
     {
-    retval = PaintRgn( hdc, hrgn );
-    SelectObject( hdc, prevBrush );
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pFillRgn );
+        update_dc( dc );
+        retval = physdev->funcs->pFillRgn( physdev, hrgn, hbrush );
+        release_dc_ptr( dc );
     }
-    GDI_ReleaseObj( hdc );
     return retval;
 }
 
@@ -508,25 +723,15 @@ BOOL WINAPI FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush,
                           INT nWidth, INT nHeight )
 {
     BOOL ret = FALSE;
-    DC *dc = DC_GetDCUpdate( hdc );
+    DC *dc = get_dc_ptr( hdc );
 
-    if (!dc) return FALSE;
-    if(dc->funcs->pFrameRgn)
-        ret = dc->funcs->pFrameRgn( dc->physDev, hrgn, hbrush, nWidth, nHeight );
-    else
+    if (dc)
     {
-        HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
-        if (tmp)
-        {
-            if (REGION_FrameRgn( tmp, hrgn, nWidth, nHeight ))
-            {
-                FillRgn( hdc, tmp, hbrush );
-                ret = TRUE;
-            }
-            DeleteObject( tmp );
-        }
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pFrameRgn );
+        update_dc( dc );
+        ret = physdev->funcs->pFrameRgn( physdev, hrgn, hbrush, nWidth, nHeight );
+        release_dc_ptr( dc );
     }
-    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -536,24 +741,17 @@ BOOL WINAPI FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush,
  */
 BOOL WINAPI InvertRgn( HDC hdc, HRGN hrgn )
 {
-    HBRUSH prevBrush;
-    INT prevROP;
-    BOOL retval;
-    DC *dc = DC_GetDCUpdate( hdc );
-    if (!dc) return FALSE;
+    BOOL ret = FALSE;
+    DC *dc = get_dc_ptr( hdc );
 
-    if(dc->funcs->pInvertRgn)
-        retval = dc->funcs->pInvertRgn( dc->physDev, hrgn );
-    else
+    if (dc)
     {
-    prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
-    prevROP = SetROP2( hdc, R2_NOT );
-    retval = PaintRgn( hdc, hrgn );
-    SelectObject( hdc, prevBrush );
-    SetROP2( hdc, prevROP );
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pInvertRgn );
+        update_dc( dc );
+        ret = physdev->funcs->pInvertRgn( physdev, hrgn );
+        release_dc_ptr( dc );
     }
-    GDI_ReleaseObj( hdc );
-    return retval;
+    return ret;
 }
 
 
@@ -563,12 +761,18 @@ BOOL WINAPI InvertRgn( HDC hdc, HRGN hrgn )
 BOOL WINAPI Polyline( HDC hdc, const POINT* pt, INT count )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
+        update_dc( dc );
         if (PATH_IsPathOpen(dc->path)) ret = PATH_Polyline(dc, pt, count);
-        else if (dc->funcs->pPolyline) ret = dc->funcs->pPolyline(dc->physDev,pt,count);
-        GDI_ReleaseObj( hdc );
+        else
+        {
+            PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPolyline );
+            ret = physdev->funcs->pPolyline( physdev, pt, count );
+        }
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -578,34 +782,24 @@ BOOL WINAPI Polyline( HDC hdc, const POINT* pt, INT count )
  */
 BOOL WINAPI PolylineTo( HDC hdc, const POINT* pt, DWORD cCount )
 {
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
     BOOL ret = FALSE;
 
     if(!dc) return FALSE;
 
-    if(PATH_IsPathOpen(dc->path))
-        ret = PATH_PolylineTo(dc, pt, cCount);
-
-    else if(dc->funcs->pPolylineTo)
-        ret = dc->funcs->pPolylineTo(dc->physDev, pt, cCount);
-
-    else { /* do it using Polyline */
-        POINT *pts = HeapAlloc( GetProcessHeap(), 0,
-                               sizeof(POINT) * (cCount + 1) );
-       if (pts)
-        {
-       pts[0].x = dc->CursPosX;
-       pts[0].y = dc->CursPosY;
-       memcpy( pts + 1, pt, sizeof(POINT) * cCount );
-       ret = Polyline( hdc, pts, cCount + 1 );
-       HeapFree( GetProcessHeap(), 0, pts );
-    }
+    update_dc( dc );
+    if(PATH_IsPathOpen(dc->path)) ret = PATH_PolylineTo(dc, pt, cCount);
+    else
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPolylineTo );
+        ret = physdev->funcs->pPolylineTo( physdev, pt, cCount );
     }
-    if(ret) {
+    if (ret && cCount)
+    {
         dc->CursPosX = pt[cCount-1].x;
        dc->CursPosY = pt[cCount-1].y;
     }
-    GDI_ReleaseObj( hdc );
+    release_dc_ptr( dc );
     return ret;
 }
 
@@ -616,12 +810,18 @@ BOOL WINAPI PolylineTo( HDC hdc, const POINT* pt, DWORD cCount )
 BOOL WINAPI Polygon( HDC hdc, const POINT* pt, INT count )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
+        update_dc( dc );
         if (PATH_IsPathOpen(dc->path)) ret = PATH_Polygon(dc, pt, count);
-        else if (dc->funcs->pPolygon) ret = dc->funcs->pPolygon(dc->physDev,pt,count);
-        GDI_ReleaseObj( hdc );
+        else
+        {
+            PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPolygon );
+            ret = physdev->funcs->pPolygon( physdev, pt, count );
+        }
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -634,12 +834,18 @@ BOOL WINAPI PolyPolygon( HDC hdc, const POINT* pt, const INT* counts,
                              UINT polygons )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
+        update_dc( dc );
         if (PATH_IsPathOpen(dc->path)) ret = PATH_PolyPolygon(dc, pt, counts, polygons);
-        else if (dc->funcs->pPolyPolygon) ret = dc->funcs->pPolyPolygon(dc->physDev,pt,counts,polygons);
-        GDI_ReleaseObj( hdc );
+        else
+        {
+            PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPolyPolygon );
+            ret = physdev->funcs->pPolyPolygon( physdev, pt, counts, polygons );
+        }
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -651,12 +857,18 @@ BOOL WINAPI PolyPolyline( HDC hdc, const POINT* pt, const DWORD* counts,
                             DWORD polylines )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
+        update_dc( dc );
         if (PATH_IsPathOpen(dc->path)) ret = PATH_PolyPolyline(dc, pt, counts, polylines);
-        else if (dc->funcs->pPolyPolyline) ret = dc->funcs->pPolyPolyline(dc->physDev,pt,counts,polylines);
-        GDI_ReleaseObj( hdc );
+        else
+        {
+            PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPolyPolyline );
+            ret = physdev->funcs->pPolyPolyline( physdev, pt, counts, polylines );
+        }
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -668,11 +880,15 @@ BOOL WINAPI ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color,
                               UINT fillType )
 {
     BOOL ret = FALSE;
-    DC * dc = DC_GetDCUpdate( hdc );
+    DC * dc = get_dc_ptr( hdc );
+
     if (dc)
     {
-        if (dc->funcs->pExtFloodFill) ret = dc->funcs->pExtFloodFill(dc->physDev,x,y,color,fillType);
-        GDI_ReleaseObj( hdc );
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pExtFloodFill );
+
+        update_dc( dc );
+        ret = physdev->funcs->pExtFloodFill( physdev, x, y, color, fillType );
+        release_dc_ptr( dc );
     }
     return ret;
 }
@@ -708,27 +924,17 @@ BOOL WINAPI PolyBezier( HDC hdc, const POINT* lppt, DWORD cPoints )
     /* cPoints must be 3 * n + 1 (where n>=1) */
     if (cPoints == 1 || (cPoints % 3) != 1) return FALSE;
 
-    dc = DC_GetDCUpdate( hdc );
+    dc = get_dc_ptr( hdc );
     if(!dc) return FALSE;
 
-    if(PATH_IsPathOpen(dc->path))
-       ret = PATH_PolyBezier(dc, lppt, cPoints);
-    else if (dc->funcs->pPolyBezier)
-        ret = dc->funcs->pPolyBezier(dc->physDev, lppt, cPoints);
-    else  /* We'll convert it into line segments and draw them using Polyline */
+    update_dc( dc );
+    if(PATH_IsPathOpen(dc->path)) ret = PATH_PolyBezier(dc, lppt, cPoints);
+    else
     {
-        POINT *Pts;
-       INT nOut;
-
-       if ((Pts = GDI_Bezier( lppt, cPoints, &nOut )))
-        {
-           TRACE("Pts = %p, no = %d\n", Pts, nOut);
-           ret = Polyline( dc->hSelf, Pts, nOut );
-           HeapFree( GetProcessHeap(), 0, Pts );
-       }
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPolyBezier );
+        ret = physdev->funcs->pPolyBezier( physdev, lppt, cPoints );
     }
-
-    GDI_ReleaseObj( hdc );
+    release_dc_ptr( dc );
     return ret;
 }
 
@@ -748,33 +954,26 @@ BOOL WINAPI PolyBezier( HDC hdc, const POINT* lppt, DWORD cPoints )
 BOOL WINAPI PolyBezierTo( HDC hdc, const POINT* lppt, DWORD cPoints )
 {
     DC * dc;
-    BOOL ret;
+    BOOL ret = FALSE;
 
     /* cbPoints must be 3 * n (where n>=1) */
     if (!cPoints || (cPoints % 3) != 0) return FALSE;
 
-    dc = DC_GetDCUpdate( hdc );
+    dc = get_dc_ptr( hdc );
     if(!dc) return FALSE;
 
-    if(PATH_IsPathOpen(dc->path))
-        ret = PATH_PolyBezierTo(dc, lppt, cPoints);
-    else if(dc->funcs->pPolyBezierTo)
-        ret = dc->funcs->pPolyBezierTo(dc->physDev, lppt, cPoints);
-    else { /* We'll do it using PolyBezier */
-        POINT *pt;
-       pt = HeapAlloc( GetProcessHeap(), 0, sizeof(POINT) * (cPoints + 1) );
-       if(!pt) return FALSE;
-       pt[0].x = dc->CursPosX;
-       pt[0].y = dc->CursPosY;
-       memcpy(pt + 1, lppt, sizeof(POINT) * cPoints);
-       ret = PolyBezier(dc->hSelf, pt, cPoints+1);
-       HeapFree( GetProcessHeap(), 0, pt );
+    update_dc( dc );
+    if(PATH_IsPathOpen(dc->path)) ret = PATH_PolyBezierTo(dc, lppt, cPoints);
+    else
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPolyBezierTo );
+        ret = physdev->funcs->pPolyBezierTo( physdev, lppt, cPoints );
     }
     if(ret) {
         dc->CursPosX = lppt[cPoints-1].x;
         dc->CursPosY = lppt[cPoints-1].y;
     }
-    GDI_ReleaseObj( hdc );
+    release_dc_ptr( dc );
     return ret;
 }
 
@@ -790,18 +989,22 @@ BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius, FLOAT eStartAngle, F
     if( (signed int)dwRadius < 0 )
        return FALSE;
 
-    dc = DC_GetDCUpdate( hdc );
+    dc = get_dc_ptr( hdc );
     if(!dc) return FALSE;
 
     /* Calculate the end point */
-    x2 = x + cos((eStartAngle+eSweepAngle)*M_PI/180) * dwRadius;
-    y2 = y - sin((eStartAngle+eSweepAngle)*M_PI/180) * dwRadius;
+    x2 = GDI_ROUND( x + cos((eStartAngle+eSweepAngle)*M_PI/180) * dwRadius );
+    y2 = GDI_ROUND( y - sin((eStartAngle+eSweepAngle)*M_PI/180) * dwRadius );
 
-    if(!PATH_IsPathOpen(dc->path) && dc->funcs->pAngleArc)
-        result = dc->funcs->pAngleArc( dc->physDev, x, y, dwRadius, eStartAngle, eSweepAngle );
+    update_dc( dc );
+    if(!PATH_IsPathOpen(dc->path))
+    {
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pAngleArc );
+        result = physdev->funcs->pAngleArc( physdev, x, y, dwRadius, eStartAngle, eSweepAngle );
+    }
     else { /* do it using ArcTo */
-        x1 = x + cos(eStartAngle*M_PI/180) * dwRadius;
-        y1 = y - sin(eStartAngle*M_PI/180) * dwRadius;
+        x1 = GDI_ROUND( x + cos(eStartAngle*M_PI/180) * dwRadius );
+        y1 = GDI_ROUND( y - sin(eStartAngle*M_PI/180) * dwRadius );
 
         arcdir = SetArcDirection( hdc, eSweepAngle >= 0 ? AD_COUNTERCLOCKWISE : AD_CLOCKWISE);
         result = ArcTo( hdc, x-dwRadius, y-dwRadius, x+dwRadius, y+dwRadius,
@@ -812,7 +1015,7 @@ BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius, FLOAT eStartAngle, F
         dc->CursPosX = x2;
         dc->CursPosY = y2;
     }
-    GDI_ReleaseObj( hdc );
+    release_dc_ptr( dc );
     return result;
 }
 
@@ -822,70 +1025,19 @@ BOOL WINAPI AngleArc(HDC hdc, INT x, INT y, DWORD dwRadius, FLOAT eStartAngle, F
 BOOL WINAPI PolyDraw(HDC hdc, const POINT *lppt, const BYTE *lpbTypes,
                        DWORD cCount)
 {
-    DC *dc;
-    BOOL result;
-    POINT lastmove;
-    unsigned int i;
+    DC *dc = get_dc_ptr( hdc );
+    BOOL result = FALSE;
 
-    dc = DC_GetDCUpdate( hdc );
     if(!dc) return FALSE;
 
-    if(dc->funcs->pPolyDraw)
-    {
-        result = dc->funcs->pPolyDraw( dc->physDev, lppt, lpbTypes, cCount );
-        goto end;
-    }
-
-    /* check for each bezierto if there are two more points */
-    for( i = 0; i < cCount; i++ )
-       if( lpbTypes[i] != PT_MOVETO &&
-           lpbTypes[i] & PT_BEZIERTO )
-       {
-           if( cCount < i+3 ){
-               result = FALSE;
-                goto end;
-            }
-           else
-               i += 2;
-       }
-
-    /* if no moveto occurs, we will close the figure here */
-    lastmove.x = dc->CursPosX;
-    lastmove.y = dc->CursPosY;
-
-    /* now let's draw */
-    for( i = 0; i < cCount; i++ )
+    update_dc( dc );
+    if( PATH_IsPathOpen( dc->path ) ) result = PATH_PolyDraw(dc, lppt, lpbTypes, cCount);
+    else
     {
-       if( lpbTypes[i] == PT_MOVETO )
-       {
-           MoveToEx( hdc, lppt[i].x, lppt[i].y, NULL );
-           lastmove.x = dc->CursPosX;
-           lastmove.y = dc->CursPosY;
-       }
-       else if( lpbTypes[i] & PT_LINETO )
-           LineTo( hdc, lppt[i].x, lppt[i].y );
-       else if( lpbTypes[i] & PT_BEZIERTO )
-       {
-           PolyBezierTo( hdc, &lppt[i], 3 );
-           i += 2;
-       }
-       else{
-           result = FALSE;
-            goto end;
-        }
-
-       if( lpbTypes[i] & PT_CLOSEFIGURE )
-       {
-           if( PATH_IsPathOpen( dc->path ) )
-               CloseFigure( hdc );
-           else
-               LineTo( hdc, lastmove.x, lastmove.y );
-       }
+        PHYSDEV physdev = GET_DC_PHYSDEV( dc, pPolyDraw );
+        result = physdev->funcs->pPolyDraw( physdev, lppt, lpbTypes, cCount );
     }
-
-    result = TRUE;
-end:
-    GDI_ReleaseObj( hdc );
+    release_dc_ptr( dc );
     return result;
 }
 
@@ -915,7 +1067,7 @@ BOOL WINAPI LineDDA(INT nXStart, INT nYStart, INT nXEnd, INT nYEnd,
     if (dx > dy)  /* line is "more horizontal" */
     {
         err = 2*dy - dx; erradd = 2*dy - 2*dx;
-        for(cnt = 0;cnt <= dx; cnt++)
+        for(cnt = 0;cnt < dx; cnt++)
         {
             callback(nXStart,nYStart,lParam);
             if (err > 0)
@@ -930,7 +1082,7 @@ BOOL WINAPI LineDDA(INT nXStart, INT nYStart, INT nXEnd, INT nYEnd,
     else   /* line is "more vertical" */
     {
         err = 2*dx - dy; erradd = 2*dx - 2*dy;
-        for(cnt = 0;cnt <= dy; cnt++)
+        for(cnt = 0;cnt < dy; cnt++)
         {
             callback(nXStart,nYStart,lParam);
             if (err > 0)
@@ -951,7 +1103,7 @@ BOOL WINAPI LineDDA(INT nXStart, INT nYStart, INT nXEnd, INT nYEnd,
  *   *Very* simple bezier drawing code,
  *
  *   It uses a recursive algorithm to divide the curve in a series
- *   of straight line segements. Not ideal but for me sufficient.
+ *   of straight line segments. Not ideal but sufficient for me.
  *   If you are in need for something better look for some incremental
  *   algorithm.
  *
@@ -995,7 +1147,7 @@ BOOL WINAPI LineDDA(INT nXStart, INT nYStart, INT nXEnd, INT nYEnd,
 *       Points[0] and Points[3] are begin and endpoint
 *       Points[1] and Points[2] are control points
 *       level is the recursion depth
-*       returns true if the recusion can be terminated
+*       returns true if the recursion can be terminated
 */
 static BOOL BezierCheck( int level, POINT *Points)
 {
@@ -1110,10 +1262,10 @@ static void GDI_InternalBezier( POINT *Points, POINT **PtsOut, INT *dwOut,
  *
  *  RETURNS
  *
- *  Ptr to an array of POINTs that contain the lines that approximinate the
+ *  Ptr to an array of POINTs that contain the lines that approximate the
  *  Beziers.  The array is allocated on the process heap and it is the caller's
  *  responsibility to HeapFree it. [this is not a particularly nice interface
- *  but since we can't know in advance how many points will generate, the
+ *  but since we can't know in advance how many points we will generate, the
  *  alternative would be to call the function twice, once to determine the size
  *  and a second time to do the work - I decided this was too much of a pain].
  */
@@ -1151,8 +1303,8 @@ BOOL WINAPI GdiGradientFill( HDC hdc, TRIVERTEX *vert_array, ULONG nvert,
 {
   unsigned int i;
 
-  TRACE("vert_array:0x%08lx nvert:%d grad_array:0x%08lx ngrad:%d\n",
-        (long)vert_array, nvert, (long)grad_array, ngrad);
+  TRACE("vert_array:%p nvert:%d grad_array:%p ngrad:%d\n",
+        vert_array, nvert, grad_array, ngrad);
 
   switch(mode) 
     {
@@ -1291,3 +1443,13 @@ BOOL WINAPI GdiGradientFill( HDC hdc, TRIVERTEX *vert_array, ULONG nvert,
 
   return TRUE;
 }
+
+/******************************************************************************
+ *           GdiDrawStream   (GDI32.@)
+ *
+ */
+BOOL WINAPI GdiDrawStream( HDC hdc, ULONG in, void * pvin )
+{
+    FIXME("stub: %p, %d, %p\n", hdc, in, pvin);
+    return FALSE;
+}