- include/crt/math.h: float type math functions are not c++ specific, they are especi...
authorGregor Schneider <grschneider@gmail.com>
Mon, 6 Apr 2009 14:58:12 +0000 (14:58 +0000)
committerGregor Schneider <grschneider@gmail.com>
Mon, 6 Apr 2009 14:58:12 +0000 (14:58 +0000)
- dll/win32/gdiplus: sync with current wine, correct sqrtf usage

svn path=/trunk/; revision=40394

reactos/dll/win32/gdiplus/graphics.c
reactos/dll/win32/gdiplus/graphicspath.c
reactos/dll/win32/gdiplus/image.c
reactos/include/crt/math.h

index f76e43c..2a98ee5 100644 (file)
@@ -172,6 +172,164 @@ static void transform_and_round_points(GpGraphics *graphics, POINT *pti,
     }
 }
 
+static ARGB blend_colors(ARGB start, ARGB end, int current, int total)
+{
+    ARGB result=0;
+    ARGB i;
+    for (i=0xff; i<=0xff0000; i = i << 8)
+        result |= (((start&i)*(total - current)+(end&i)*(current))/total)&i;
+    return result;
+}
+
+static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
+{
+    switch (brush->bt)
+    {
+    case BrushTypeLinearGradient:
+    {
+        GpLineGradient *line = (GpLineGradient*)brush;
+        RECT rc;
+        int num_steps = 255;
+
+        SelectClipPath(graphics->hdc, RGN_AND);
+        if (GetClipBox(graphics->hdc, &rc) != NULLREGION)
+        {
+            GpPointF endpointsf[2];
+            POINT endpointsi[2];
+            POINT poly[4];
+
+            SelectObject(graphics->hdc, GetStockObject(NULL_PEN));
+
+            /* fill with starting color */
+            FillRect(graphics->hdc, &rc, brush->gdibrush);
+
+            endpointsf[0] = line->startpoint;
+            endpointsf[1] = line->endpoint;
+            transform_and_round_points(graphics, endpointsi, endpointsf, 2);
+
+            if (abs(endpointsi[0].x-endpointsi[1].x) > abs(endpointsi[0].y-endpointsi[1].y))
+            {
+                /* vertical-ish gradient */
+                int endborderx; /* vertical rectangle boundary near endpoint */
+                int startx, endx; /* x co-ordinates of endpoints shifted to intersect the top of the visible rectangle */
+                int startbottomx, endbottomx; /* x co-ordinate of endpoints shifted to intersect the bottom of the visible rectangle */
+                int width;
+                COLORREF col;
+                HBRUSH hbrush, hprevbrush;
+                int i;
+
+                if (endpointsi[1].x > endpointsi[0].x)
+                    endborderx = rc.right;
+                else
+                    endborderx = rc.left;
+
+                startx = roundr((rc.top - endpointsf[0].Y) * (endpointsf[1].Y - endpointsf[0].Y) / (endpointsf[0].X - endpointsf[1].X) + endpointsf[0].X);
+                endx = roundr((rc.top - endpointsf[1].Y) * (endpointsf[1].Y - endpointsf[0].Y) / (endpointsf[0].X - endpointsf[1].X) + endpointsf[1].X);
+                width = endx - startx;
+                startbottomx = roundr((rc.bottom - endpointsf[0].Y) * (endpointsf[1].Y - endpointsf[0].Y) / (endpointsf[0].X - endpointsf[1].X) + endpointsf[0].X);
+                endbottomx = startbottomx+width;
+
+                if (num_steps > abs(width)) num_steps = abs(width);
+
+                poly[0].x = endborderx;
+                poly[0].y = rc.bottom;
+                poly[1].x = endborderx;
+                poly[1].y = rc.top;
+                poly[2].y = rc.top;
+                poly[3].y = rc.bottom;
+
+                for (i=1; i<num_steps; i++)
+                {
+                    ARGB argb = blend_colors(line->startcolor, line->endcolor, i, num_steps);
+                    int ofs = width * i / num_steps;
+                    col = ARGB2COLORREF(argb);
+                    hbrush = CreateSolidBrush(col);
+                    hprevbrush = SelectObject(graphics->hdc, hbrush);
+                    poly[2].x = startx + ofs;
+                    poly[3].x = startbottomx + ofs;
+                    Polygon(graphics->hdc, poly, 4);
+                    SelectObject(graphics->hdc, hprevbrush);
+                    DeleteObject(hbrush);
+                }
+
+                poly[2].x = endx;
+                poly[3].x = endbottomx;
+
+                /* draw the ending color */
+                col = ARGB2COLORREF(line->endcolor);
+                hbrush = CreateSolidBrush(col);
+                hprevbrush = SelectObject(graphics->hdc, hbrush);
+                Polygon(graphics->hdc, poly, 4);
+                SelectObject(graphics->hdc, hprevbrush);
+                DeleteObject(hbrush);
+            }
+            else if (endpointsi[0].y != endpointsi[1].y)
+            {
+                /* horizontal-ish gradient */
+                int endbordery; /* horizontal rectangle boundary near endpoint */
+                int starty, endy; /* y co-ordinates of endpoints shifted to intersect the left of the visible rectangle */
+                int startrighty, endrighty; /* y co-ordinate of endpoints shifted to intersect the right of the visible rectangle */
+                int height;
+                COLORREF col;
+                HBRUSH hbrush, hprevbrush;
+                int i;
+
+                if (endpointsi[1].y > endpointsi[0].y)
+                    endbordery = rc.bottom;
+                else
+                    endbordery = rc.top;
+
+                starty = roundr((rc.left - endpointsf[0].X) * (endpointsf[0].X - endpointsf[1].X) / (endpointsf[1].Y - endpointsf[0].Y) + endpointsf[0].Y);
+                endy = roundr((rc.left - endpointsf[1].X) * (endpointsf[0].X - endpointsf[1].X) / (endpointsf[1].Y - endpointsf[0].Y) + endpointsf[1].Y);
+                height = endy - starty;
+                startrighty = roundr((rc.right - endpointsf[0].X) * (endpointsf[0].X - endpointsf[1].X) / (endpointsf[1].Y - endpointsf[0].Y) + endpointsf[0].Y);
+                endrighty = startrighty+height;
+
+                if (num_steps > abs(height)) num_steps = abs(height);
+
+                poly[0].x = rc.right;
+                poly[0].y = endbordery;
+                poly[1].x = rc.left;
+                poly[1].y = endbordery;
+                poly[2].x = rc.left;
+                poly[3].x = rc.right;
+
+                for (i=1; i<num_steps; i++)
+                {
+                    ARGB argb = blend_colors(line->startcolor, line->endcolor, i, num_steps);
+                    int ofs = height * i / num_steps;
+                    col = ARGB2COLORREF(argb);
+                    hbrush = CreateSolidBrush(col);
+                    hprevbrush = SelectObject(graphics->hdc, hbrush);
+                    poly[2].y = starty + ofs;
+                    poly[3].y = startrighty + ofs;
+                    Polygon(graphics->hdc, poly, 4);
+                    SelectObject(graphics->hdc, hprevbrush);
+                    DeleteObject(hbrush);
+                }
+
+                poly[2].y = endy;
+                poly[3].y = endrighty;
+
+                /* draw the ending color */
+                col = ARGB2COLORREF(line->endcolor);
+                hbrush = CreateSolidBrush(col);
+                hprevbrush = SelectObject(graphics->hdc, hbrush);
+                Polygon(graphics->hdc, poly, 4);
+                SelectObject(graphics->hdc, hprevbrush);
+                DeleteObject(hbrush);
+            }
+            /* else startpoint == endpoint */
+        }
+        break;
+    }
+    default:
+        SelectObject(graphics->hdc, brush->gdibrush);
+        FillPath(graphics->hdc);
+        break;
+    }
+}
+
 /* GdipDrawPie/GdipFillPie helper function */
 static void draw_pie(GpGraphics *graphics, REAL x, REAL y, REAL width,
     REAL height, REAL startAngle, REAL sweepAngle)
@@ -1853,20 +2011,35 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
     rectcpy[3].Y = rectcpy[2].Y = rect->Y + rect->Height;
     transform_and_round_points(graphics, corners, rectcpy, 4);
 
-    if(roundr(rect->Width) == 0 && roundr(rect->Height) == 0){
-        rel_width = rel_height = 1.0;
-        nwidth = nheight = INT_MAX;
+    if (roundr(rect->Width) == 0)
+    {
+        rel_width = 1.0;
+        nwidth = INT_MAX;
     }
-    else{
+    else
+    {
         rel_width = sqrt((corners[1].x - corners[0].x) * (corners[1].x - corners[0].x) +
                          (corners[1].y - corners[0].y) * (corners[1].y - corners[0].y))
                          / rect->Width;
+        nwidth = roundr(rel_width * rect->Width);
+    }
+
+    if (roundr(rect->Height) == 0)
+    {
+        rel_height = 1.0;
+        nheight = INT_MAX;
+    }
+    else
+    {
         rel_height = sqrt((corners[2].x - corners[1].x) * (corners[2].x - corners[1].x) +
                           (corners[2].y - corners[1].y) * (corners[2].y - corners[1].y))
                           / rect->Height;
-
-        nwidth = roundr(rel_width * rect->Width);
         nheight = roundr(rel_height * rect->Height);
+    }
+
+    if (roundr(rect->Width) != 0 && roundr(rect->Height) != 0)
+    {
+        /* FIXME: If only the width or only the height is 0, we should probably still clip */
         rgn = CreatePolygonRgn(corners, 4, ALTERNATE);
         SelectClipRgn(graphics->hdc, rgn);
     }
@@ -1894,7 +2067,7 @@ GpStatus WINGDIPAPI GdipDrawString(GpGraphics *graphics, GDIPCONST WCHAR *string
     DeleteObject(SelectObject(graphics->hdc, CreateFontIndirectW(&lfw)));
 
     for(i = 0, j = 0; i < length; i++){
-        if(!isprint(string[i]) && (string[i] != '\n'))
+        if(!isprintW(string[i]) && (string[i] != '\n'))
             continue;
 
         stringdup[j] = string[i];
@@ -2086,7 +2259,6 @@ GpStatus WINGDIPAPI GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *p
 
     save_state = SaveDC(graphics->hdc);
     EndPath(graphics->hdc);
-    SelectObject(graphics->hdc, brush->gdibrush);
     SetPolyFillMode(graphics->hdc, (path->fill == FillModeAlternate ? ALTERNATE
                                                                     : WINDING));
 
@@ -2098,7 +2270,7 @@ GpStatus WINGDIPAPI GdipFillPath(GpGraphics *graphics, GpBrush *brush, GpPath *p
         goto end;
 
     EndPath(graphics->hdc);
-    FillPath(graphics->hdc);
+    brush_fill_path(graphics, brush);
 
     retval = Ok;
 
@@ -2749,7 +2921,7 @@ GpStatus WINGDIPAPI GdipMeasureString(GpGraphics *graphics,
         nwidth = nheight = INT_MAX;
 
     for(i = 0, j = 0; i < length; i++){
-        if(!isprint(string[i]) && (string[i] != '\n'))
+        if(!isprintW(string[i]) && (string[i] != '\n'))
             continue;
 
         stringdup[j] = string[i];
index 6a4c99d..ca33082 100644 (file)
@@ -147,7 +147,7 @@ static BOOL flatten_bezier(path_list_node_t *start, REAL x2, REAL y2, REAL x3, R
     /* check flatness as a half of distance between middle point and a linearized path */
     if(fabs(((pt.Y - pt_st.Y)*mp[2].X + (pt_st.X - pt.X)*mp[2].Y +
         (pt_st.Y*pt.X - pt_st.X*pt.Y))) <=
-        (0.5 * flatness*sqrt((powf(pt.Y - pt_st.Y, 2.0) + powf(pt_st.X - pt.X, 2.0))))){
+        (0.5 * flatness*sqrtf((powf(pt.Y - pt_st.Y, 2.0) + powf(pt_st.X - pt.X, 2.0))))){
         return TRUE;
     }
     else
index a229f8b..8a4dcc2 100644 (file)
@@ -249,6 +249,14 @@ GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap* bitmap,
     return Ok;
 }
 
+GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height,
+    PixelFormat format, GpBitmap* srcBitmap, GpBitmap** dstBitmap)
+{
+    FIXME("(%i,%i,%i,%i,%i,%p,%p)\n", x, y, width, height, format, srcBitmap, dstBitmap);
+
+    return NotImplemented;
+}
+
 GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
 {
     IStream* stream;
@@ -549,6 +557,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
         ERR("could not make stream\n");
         GdipFree(*bitmap);
         GdipFree(buff);
+        *bitmap = NULL;
         return GenericError;
     }
 
@@ -558,6 +567,7 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride,
         IStream_Release(stream);
         GdipFree(*bitmap);
         GdipFree(buff);
+        *bitmap = NULL;
         return GenericError;
     }
 
index 2647b03..6fa5a43 100644 (file)
@@ -189,6 +189,9 @@ extern "C" {
     return res;
   }
   __CRT_INLINE float __cdecl ldexpf (float x, int expn) { return (float) ldexp (x, expn); }
+#endif
+#endif
+
 #ifndef __x86_64
   __CRT_INLINE float acosf(float _X) { return ((float)acos((double)_X)); }
   __CRT_INLINE float asinf(float _X) { return ((float)asin((double)_X)); }
@@ -214,8 +217,6 @@ extern "C" {
   __CRT_INLINE float tanf(float _X) { return ((float)tan((double)_X)); }
   __CRT_INLINE float tanhf(float _X) { return ((float)tanh((double)_X)); }
 #endif
-#endif
-#endif
 
 #ifndef        NO_OLDNAMES
 #define DOMAIN _DOMAIN