Author: dchapyshev
Date: Sat May 9 13:26:16 2009
New Revision: 40851
URL:
http://svn.reactos.org/svn/reactos?rev=40851&view=rev
Log:
- Sync gdiplus with Wine 1.1.21
Modified:
trunk/reactos/dll/win32/gdiplus/brush.c
trunk/reactos/dll/win32/gdiplus/font.c
trunk/reactos/dll/win32/gdiplus/gdiplus.spec
trunk/reactos/dll/win32/gdiplus/gdiplus_private.h
trunk/reactos/dll/win32/gdiplus/graphics.c
trunk/reactos/dll/win32/gdiplus/image.c
Modified: trunk/reactos/dll/win32/gdiplus/brush.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/brush.c?…
==============================================================================
--- trunk/reactos/dll/win32/gdiplus/brush.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/gdiplus/brush.c [iso-8859-1] Sat May 9 13:26:16 2009
@@ -34,6 +34,33 @@
WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
+/*
+ Unix stuff
+ Code from
http://www.johndcook.com/blog/2009/01/19/stand-alone-error-function-erf/
+*/
+double erf(double x)
+{
+ const float a1 = 0.254829592;
+ const float a2 = -0.284496736;
+ const float a3 = 1.421413741;
+ const float a4 = -1.453152027;
+ const float a5 = 1.061405429;
+ const float p = 0.3275911;
+ float t, y, sign;
+
+ /* Save the sign of x */
+ sign = 1;
+ if (x < 0)
+ sign = -1;
+ x = abs(x);
+
+ /* A & S 7.1.26 */
+ t = 1.0/(1.0 + p*x);
+ y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);
+
+ return sign*y;
+}
+
/******************************************************************************
* GdipCloneBrush [GDIPLUS.@]
*/
@@ -108,14 +135,38 @@
break;
}
- case BrushTypeLinearGradient:
- *clone = GdipAlloc(sizeof(GpLineGradient));
- if(!*clone) return OutOfMemory;
-
- memcpy(*clone, brush, sizeof(GpLineGradient));
-
- (*clone)->gdibrush = CreateSolidBrush((*clone)->lb.lbColor);
+ case BrushTypeLinearGradient:{
+ GpLineGradient *dest, *src;
+ INT count;
+
+ dest = GdipAlloc(sizeof(GpLineGradient));
+ if(!dest) return OutOfMemory;
+
+ src = (GpLineGradient*)brush;
+
+ memcpy(dest, src, sizeof(GpLineGradient));
+
+ dest->brush.gdibrush = CreateSolidBrush(dest->brush.lb.lbColor);
+
+ count = dest->blendcount;
+ dest->blendfac = GdipAlloc(count * sizeof(REAL));
+ dest->blendpos = GdipAlloc(count * sizeof(REAL));
+
+ if (!dest->blendfac || !dest->blendpos)
+ {
+ GdipFree(dest->blendfac);
+ GdipFree(dest->blendpos);
+ DeleteObject(dest->brush.gdibrush);
+ GdipFree(dest);
+ return OutOfMemory;
+ }
+
+ memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
+ memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
+
+ *clone = &dest->brush;
break;
+ }
case BrushTypeTextureFill:
*clone = GdipAlloc(sizeof(GpTexture));
if(!*clone) return OutOfMemory;
@@ -226,6 +277,28 @@
(*line)->wrap = wrap;
(*line)->gamma = FALSE;
+ (*line)->rect.X = (startpoint->X < endpoint->X ? startpoint->X:
endpoint->X);
+ (*line)->rect.Y = (startpoint->Y < endpoint->Y ? startpoint->Y:
endpoint->Y);
+ (*line)->rect.Width = fabs(startpoint->X - endpoint->X);
+ (*line)->rect.Height = fabs(startpoint->Y - endpoint->Y);
+
+ (*line)->blendcount = 1;
+ (*line)->blendfac = GdipAlloc(sizeof(REAL));
+ (*line)->blendpos = GdipAlloc(sizeof(REAL));
+
+ if (!(*line)->blendfac || !(*line)->blendpos)
+ {
+ GdipFree((*line)->blendfac);
+ GdipFree((*line)->blendpos);
+ DeleteObject((*line)->brush.gdibrush);
+ GdipFree(*line);
+ *line = NULL;
+ return OutOfMemory;
+ }
+
+ (*line)->blendfac[0] = 1.0f;
+ (*line)->blendpos[0] = 1.0f;
+
return Ok;
}
@@ -255,6 +328,7 @@
GpLineGradient **line)
{
GpPointF start, end;
+ GpStatus stat;
TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
wrap, line);
@@ -262,12 +336,42 @@
if(!line || !rect)
return InvalidParameter;
- start.X = rect->X;
- start.Y = rect->Y;
- end.X = rect->X + rect->Width;
- end.Y = rect->Y + rect->Height;
-
- return GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap, line);
+ switch (mode)
+ {
+ case LinearGradientModeHorizontal:
+ start.X = rect->X;
+ start.Y = rect->Y;
+ end.X = rect->X + rect->Width;
+ end.Y = rect->Y;
+ break;
+ case LinearGradientModeVertical:
+ start.X = rect->X;
+ start.Y = rect->Y;
+ end.X = rect->X;
+ end.Y = rect->Y + rect->Height;
+ break;
+ case LinearGradientModeForwardDiagonal:
+ start.X = rect->X;
+ start.Y = rect->Y;
+ end.X = rect->X + rect->Width;
+ end.Y = rect->Y + rect->Height;
+ break;
+ case LinearGradientModeBackwardDiagonal:
+ start.X = rect->X + rect->Width;
+ start.Y = rect->Y;
+ end.X = rect->X;
+ end.Y = rect->Y + rect->Height;
+ break;
+ default:
+ return InvalidParameter;
+ }
+
+ stat = GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap, line);
+
+ if (stat == Ok)
+ (*line)->rect = *rect;
+
+ return stat;
}
GpStatus WINGDIPAPI GdipCreateLineBrushFromRectI(GDIPCONST GpRect* rect,
@@ -765,7 +869,10 @@
GdipFree(((GpPathGradient*) brush)->blendpos);
break;
case BrushTypeSolidColor:
+ break;
case BrushTypeLinearGradient:
+ GdipFree(((GpLineGradient*)brush)->blendfac);
+ GdipFree(((GpLineGradient*)brush)->blendpos);
break;
case BrushTypeTextureFill:
GdipDeleteMatrix(((GpTexture*)brush)->transform);
@@ -1071,15 +1178,64 @@
}
GpStatus WINGDIPAPI GdipSetLineBlend(GpLineGradient *brush,
- GDIPCONST REAL *blend, GDIPCONST REAL* positions, INT count)
-{
- static int calls;
-
- if(!brush || !blend || !positions || count <= 0)
- return InvalidParameter;
-
- if(!(calls++))
- FIXME("not implemented\n");
+ GDIPCONST REAL *factors, GDIPCONST REAL* positions, INT count)
+{
+ REAL *new_blendfac, *new_blendpos;
+
+ TRACE("(%p, %p, %p, %i)\n", brush, factors, positions, count);
+
+ if(!brush || !factors || !positions || count <= 0 ||
+ (count >= 2 && (positions[0] != 0.0f || positions[count-1] != 1.0f)))
+ return InvalidParameter;
+
+ new_blendfac = GdipAlloc(count * sizeof(REAL));
+ new_blendpos = GdipAlloc(count * sizeof(REAL));
+
+ if (!new_blendfac || !new_blendpos)
+ {
+ GdipFree(new_blendfac);
+ GdipFree(new_blendpos);
+ return OutOfMemory;
+ }
+
+ memcpy(new_blendfac, factors, count * sizeof(REAL));
+ memcpy(new_blendpos, positions, count * sizeof(REAL));
+
+ GdipFree(brush->blendfac);
+ GdipFree(brush->blendpos);
+
+ brush->blendcount = count;
+ brush->blendfac = new_blendfac;
+ brush->blendpos = new_blendpos;
+
+ return Ok;
+}
+
+GpStatus WINGDIPAPI GdipGetLineBlend(GpLineGradient *brush, REAL *factors,
+ REAL *positions, INT count)
+{
+ TRACE("(%p, %p, %p, %i)\n", brush, factors, positions, count);
+
+ if (!brush || !factors || !positions || count <= 0)
+ return InvalidParameter;
+
+ if (count < brush->blendcount)
+ return InsufficientBuffer;
+
+ memcpy(factors, brush->blendfac, brush->blendcount * sizeof(REAL));
+ memcpy(positions, brush->blendpos, brush->blendcount * sizeof(REAL));
+
+ return Ok;
+}
+
+GpStatus WINGDIPAPI GdipGetLineBlendCount(GpLineGradient *brush, INT *count)
+{
+ TRACE("(%p, %p)\n", brush, count);
+
+ if (!brush || !count)
+ return InvalidParameter;
+
+ *count = brush->blendcount;
return Ok;
}
@@ -1100,15 +1256,57 @@
GpStatus WINGDIPAPI GdipSetLineSigmaBlend(GpLineGradient *line, REAL focus,
REAL scale)
{
- static int calls;
+ REAL factors[33];
+ REAL positions[33];
+ int num_points = 0;
+ int i;
+ const int precision = 16;
+ REAL erf_range; /* we use values erf(-erf_range) through erf(+erf_range) */
+ REAL min_erf;
+ REAL scale_erf;
+
+ TRACE("(%p, %0.2f, %0.2f)\n", line, focus, scale);
if(!line || focus < 0.0 || focus > 1.0 || scale < 0.0 || scale > 1.0)
return InvalidParameter;
- if(!(calls++))
- FIXME("not implemented\n");
-
- return NotImplemented;
+ /* we want 2 standard deviations */
+ erf_range = 2.0 / sqrt(2);
+
+ /* calculate the constants we need to normalize the error function to be
+ between 0.0 and scale over the range we need */
+ min_erf = erf(-erf_range);
+ scale_erf = scale / (-2.0 * min_erf);
+
+ if (focus != 0.0)
+ {
+ positions[0] = 0.0;
+ factors[0] = 0.0;
+ for (i=1; i<precision; i++)
+ {
+ positions[i] = focus * i / precision;
+ factors[i] = scale_erf * (erf(2 * erf_range * i / precision - erf_range) -
min_erf);
+ }
+ num_points += precision;
+ }
+
+ positions[num_points] = focus;
+ factors[num_points] = scale;
+ num_points += 1;
+
+ if (focus != 1.0)
+ {
+ for (i=1; i<precision; i++)
+ {
+ positions[i+num_points-1] = (focus + ((1.0-focus) * i / precision));
+ factors[i+num_points-1] = scale_erf * (erf(erf_range - 2 * erf_range * i /
precision) - min_erf);
+ }
+ num_points += precision;
+ positions[num_points-1] = 1.0;
+ factors[num_points-1] = 0.0;
+ }
+
+ return GdipSetLineBlend(line, factors, positions, num_points);
}
GpStatus WINGDIPAPI GdipSetLineWrapMode(GpLineGradient *line,
@@ -1403,11 +1601,7 @@
if(!brush || !rect)
return InvalidParameter;
- rect->X = (brush->startpoint.X < brush->endpoint.X ?
brush->startpoint.X: brush->endpoint.X);
- rect->Y = (brush->startpoint.Y < brush->endpoint.Y ?
brush->startpoint.Y: brush->endpoint.Y);
-
- rect->Width = fabs(brush->startpoint.X - brush->endpoint.X);
- rect->Height = fabs(brush->startpoint.Y - brush->endpoint.Y);
+ *rect = brush->rect;
return Ok;
}
Modified: trunk/reactos/dll/win32/gdiplus/font.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/font.c?r…
==============================================================================
--- trunk/reactos/dll/win32/gdiplus/font.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/gdiplus/font.c [iso-8859-1] Sat May 9 13:26:16 2009
@@ -35,6 +35,8 @@
static const REAL mm_per_inch = 25.4;
static const REAL inch_per_point = 1.0/72.0;
+
+static GpFontCollection installedFontCollection = {0};
static inline REAL get_dpi (void)
{
@@ -193,7 +195,7 @@
oldfont = SelectObject(hdc, hfont);
GetTextMetricsW(hdc, &textmet);
- (*font)->lfw.lfHeight = -textmet.tmHeight;
+ (*font)->lfw.lfHeight = -(textmet.tmHeight-textmet.tmInternalLeading);
(*font)->lfw.lfWeight = textmet.tmWeight;
(*font)->lfw.lfCharSet = textmet.tmCharSet;
@@ -936,5 +938,7 @@
if (!fontCollection)
return InvalidParameter;
- return NotImplemented;
-}
+ *fontCollection = &installedFontCollection;
+
+ return Ok;
+}
Modified: trunk/reactos/dll/win32/gdiplus/gdiplus.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/gdiplus.…
==============================================================================
--- trunk/reactos/dll/win32/gdiplus/gdiplus.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/gdiplus/gdiplus.spec [iso-8859-1] Sat May 9 13:26:16 2009
@@ -42,7 +42,7 @@
@ stub GdipBitmapGetHistogramSize
@ stdcall GdipBitmapGetPixel(ptr long long ptr)
@ stdcall GdipBitmapLockBits(ptr ptr long long ptr)
-@ stub GdipBitmapSetPixel
+@ stdcall GdipBitmapSetPixel(ptr long long long)
@ stdcall GdipBitmapSetResolution(ptr long long)
@ stdcall GdipBitmapUnlockBits(ptr ptr)
@ stdcall GdipClearPathMarkers(ptr)
@@ -295,13 +295,13 @@
@ stdcall GdipGetImagePaletteSize(ptr ptr)
@ stdcall GdipGetImagePixelFormat(ptr ptr)
@ stdcall GdipGetImageRawFormat(ptr ptr)
-@ stub GdipGetImageThumbnail
+@ stdcall GdipGetImageThumbnail(ptr long long ptr ptr ptr)
@ stdcall GdipGetImageType(ptr ptr)
@ stdcall GdipGetImageVerticalResolution(ptr ptr)
@ stdcall GdipGetImageWidth(ptr ptr)
@ stdcall GdipGetInterpolationMode(ptr ptr)
-@ stub GdipGetLineBlend
-@ stub GdipGetLineBlendCount
+@ stdcall GdipGetLineBlend(ptr ptr ptr long)
+@ stdcall GdipGetLineBlendCount(ptr ptr)
@ stdcall GdipGetLineColors(ptr ptr)
@ stdcall GdipGetLineGammaCorrection(ptr ptr)
@ stub GdipGetLinePresetBlend
@@ -409,7 +409,7 @@
@ stdcall GdipImageGetFrameCount(ptr ptr ptr)
@ stdcall GdipImageGetFrameDimensionsCount(ptr ptr)
@ stdcall GdipImageGetFrameDimensionsList(ptr ptr long)
-@ stub GdipImageRotateFlip
+@ stdcall GdipImageRotateFlip(ptr long)
@ stdcall GdipImageSelectActiveFrame(ptr ptr long)
@ stub GdipImageSetAbort
@ stub GdipInitializePalette
@@ -582,7 +582,7 @@
@ stdcall GdipSetPenWidth(ptr long)
@ stdcall GdipSetPixelOffsetMode(ptr long)
@ stdcall GdipSetPropertyItem(ptr ptr)
-@ stub GdipSetRenderingOrigin
+@ stdcall GdipSetRenderingOrigin(ptr long long)
@ stdcall GdipSetSmoothingMode(ptr long)
@ stdcall GdipSetSolidFillColor(ptr ptr)
@ stdcall GdipSetStringFormatAlign(ptr long)
Modified: trunk/reactos/dll/win32/gdiplus/gdiplus_private.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/gdiplus_…
==============================================================================
--- trunk/reactos/dll/win32/gdiplus/gdiplus_private.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/gdiplus/gdiplus_private.h [iso-8859-1] Sat May 9 13:26:16
2009
@@ -91,6 +91,7 @@
struct GpGraphics{
HDC hdc;
HWND hwnd;
+ BOOL owndc;
SmoothingMode smoothing;
CompositingQuality compqual;
InterpolationMode interpolation;
@@ -142,8 +143,12 @@
GpPointF endpoint;
ARGB startcolor;
ARGB endcolor;
+ RectF rect;
GpWrapMode wrap;
BOOL gamma;
+ REAL* blendfac; /* blend factors */
+ REAL* blendpos; /* blend positions */
+ INT blendcount;
};
struct GpTexture{
Modified: trunk/reactos/dll/win32/gdiplus/graphics.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/graphics…
==============================================================================
--- trunk/reactos/dll/win32/gdiplus/graphics.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/gdiplus/graphics.c [iso-8859-1] Sat May 9 13:26:16 2009
@@ -172,13 +172,54 @@
}
}
-static ARGB blend_colors(ARGB start, ARGB end, int current, int total)
+static ARGB blend_colors(ARGB start, ARGB end, REAL position)
{
ARGB result=0;
ARGB i;
for (i=0xff; i<=0xff0000; i = i << 8)
- result |= (((start&i)*(total - current)+(end&i)*(current))/total)&i;
+ result |= (int)((start&i)*(1.0f - position)+(end&i)*(position))&i;
return result;
+}
+
+static ARGB blend_line_gradient(GpLineGradient* brush, REAL position)
+{
+ REAL blendfac;
+
+ /* clamp to between 0.0 and 1.0, using the wrap mode */
+ if (brush->wrap == WrapModeTile)
+ {
+ position = fmodf(position, 1.0f);
+ if (position < 0.0f) position += 1.0f;
+ }
+ else /* WrapModeFlip* */
+ {
+ position = fmodf(position, 2.0f);
+ if (position < 0.0f) position += 2.0f;
+ if (position > 1.0f) position = 2.0f - position;
+ }
+
+ if (brush->blendcount == 1)
+ blendfac = position;
+ else
+ {
+ int i=1;
+ REAL left_blendpos, left_blendfac, right_blendpos, right_blendfac;
+ REAL range;
+
+ /* locate the blend positions surrounding this position */
+ while (position > brush->blendpos[i])
+ i++;
+
+ /* interpolate between the blend positions */
+ left_blendpos = brush->blendpos[i-1];
+ left_blendfac = brush->blendfac[i-1];
+ right_blendpos = brush->blendpos[i];
+ right_blendfac = brush->blendfac[i];
+ range = right_blendpos - left_blendpos;
+ blendfac = (left_blendfac * (right_blendpos - position) +
+ right_blendfac * (position - left_blendpos)) / range;
+ }
+ return blend_colors(brush->startcolor, brush->endcolor, blendfac);
}
static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
@@ -189,7 +230,6 @@
{
GpLineGradient *line = (GpLineGradient*)brush;
RECT rc;
- int num_steps = 255;
SelectClipPath(graphics->hdc, RGN_AND);
if (GetClipBox(graphics->hdc, &rc) != NULLREGION)
@@ -200,9 +240,6 @@
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);
@@ -210,114 +247,100 @@
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 startbottomx; /* x co-ordinate of start point 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;
+ int leftx, rightx; /* x co-ordinates where the leftmost and rightmost
gradient lines hit the top of the visible rectangle */
+ int x;
+ int tilt; /* horizontal distance covered by a gradient line */
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;
+ tilt = startx - startbottomx;
+
+ if (startx >= startbottomx)
+ {
+ leftx = rc.left;
+ rightx = rc.right + tilt;
+ }
+ else
+ {
+ leftx = rc.left + tilt;
+ rightx = rc.right;
+ }
+
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++)
+ for (x=leftx; x<=rightx; x++)
{
- ARGB argb = blend_colors(line->startcolor, line->endcolor, i,
num_steps);
- int ofs = width * i / num_steps;
+ ARGB argb = blend_line_gradient(line, (x-startx)/(REAL)width);
col = ARGB2COLORREF(argb);
hbrush = CreateSolidBrush(col);
hprevbrush = SelectObject(graphics->hdc, hbrush);
- poly[2].x = startx + ofs;
- poly[3].x = startbottomx + ofs;
+ poly[0].x = x - tilt - 1;
+ poly[1].x = x - 1;
+ poly[2].x = x;
+ poly[3].x = x - tilt;
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 startrighty; /* y co-ordinate of start point 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;
+ int topy, bottomy; /* y co-ordinates where the topmost and bottommost
gradient lines hit the left of the visible rectangle */
+ int y;
+ int tilt; /* vertical distance covered by a gradient line */
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);
+ tilt = starty - startrighty;
+
+ if (starty >= startrighty)
+ {
+ topy = rc.top;
+ bottomy = rc.bottom + tilt;
+ }
+ else
+ {
+ topy = rc.top + tilt;
+ bottomy = rc.bottom;
+ }
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++)
+ for (y=topy; y<=bottomy; y++)
{
- ARGB argb = blend_colors(line->startcolor, line->endcolor, i,
num_steps);
- int ofs = height * i / num_steps;
+ ARGB argb = blend_line_gradient(line, (y-starty)/(REAL)height);
col = ARGB2COLORREF(argb);
hbrush = CreateSolidBrush(col);
hprevbrush = SelectObject(graphics->hdc, hbrush);
- poly[2].y = starty + ofs;
- poly[3].y = startrighty + ofs;
+ poly[0].y = y - tilt - 1;
+ poly[1].y = y - 1;
+ poly[2].y = y;
+ poly[3].y = y - tilt;
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 */
}
@@ -924,6 +947,7 @@
(*graphics)->hdc = hdc;
(*graphics)->hwnd = WindowFromDC(hdc);
+ (*graphics)->owndc = FALSE;
(*graphics)->smoothing = SmoothingModeDefault;
(*graphics)->compqual = CompositingQualityDefault;
(*graphics)->interpolation = InterpolationModeDefault;
@@ -940,13 +964,20 @@
GpStatus WINGDIPAPI GdipCreateFromHWND(HWND hwnd, GpGraphics **graphics)
{
GpStatus ret;
+ HDC hdc;
TRACE("(%p, %p)\n", hwnd, graphics);
- if((ret = GdipCreateFromHDC(GetDC(hwnd), graphics)) != Ok)
+ hdc = GetDC(hwnd);
+
+ if((ret = GdipCreateFromHDC(hdc, graphics)) != Ok)
+ {
+ ReleaseDC(hwnd, hdc);
return ret;
+ }
(*graphics)->hwnd = hwnd;
+ (*graphics)->owndc = TRUE;
return Ok;
}
@@ -1081,7 +1112,7 @@
if(!graphics) return InvalidParameter;
if(graphics->busy) return ObjectBusy;
- if(graphics->hwnd)
+ if(graphics->owndc)
ReleaseDC(graphics->hwnd, graphics->hdc);
GdipDeleteRegion(graphics->clip);
@@ -2448,12 +2479,14 @@
save_state = SaveDC(graphics->hdc);
EndPath(graphics->hdc);
- SelectObject(graphics->hdc, brush->gdibrush);
- SelectObject(graphics->hdc, GetStockObject(NULL_PEN));
transform_and_round_points(graphics, pti, ptf, 4);
+ BeginPath(graphics->hdc);
Polygon(graphics->hdc, pti, 4);
+ EndPath(graphics->hdc);
+
+ brush_fill_path(graphics, brush);
RestoreDC(graphics->hdc, save_state);
@@ -3210,6 +3243,18 @@
return Ok;
}
+GpStatus WINGDIPAPI GdipSetRenderingOrigin(GpGraphics *graphics, INT x, INT y)
+{
+ static int calls;
+
+ TRACE("(%p,%i,%i)\n", graphics, x, y);
+
+ if (!(calls++))
+ FIXME("not implemented\n");
+
+ return NotImplemented;
+}
+
GpStatus WINGDIPAPI GdipSetSmoothingMode(GpGraphics *graphics, SmoothingMode mode)
{
TRACE("(%p, %d)\n", graphics, mode);
Modified: trunk/reactos/dll/win32/gdiplus/image.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdiplus/image.c?…
==============================================================================
--- trunk/reactos/dll/win32/gdiplus/image.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/gdiplus/image.c [iso-8859-1] Sat May 9 13:26:16 2009
@@ -83,6 +83,21 @@
FIXME("not implemented\n");
*color = 0xdeadbeef;
+
+ return NotImplemented;
+}
+
+GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap* bitmap, INT x, INT y,
+ ARGB color)
+{
+ static int calls;
+ TRACE("bitmap:%p, x:%d, y:%d, color:%08x\n", bitmap, x, y, color);
+
+ if(!bitmap)
+ return InvalidParameter;
+
+ if(!(calls++))
+ FIXME("not implemented\n");
return NotImplemented;
}
@@ -1648,3 +1663,24 @@
return Ok;
}
+
+/*****************************************************************************
+ * GdipGetImageThumbnail [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipGetImageThumbnail(GpImage *image, UINT width, UINT height,
+ GpImage **ret_image, GetThumbnailImageAbort cb,
+ VOID * cb_data)
+{
+ FIXME("(%p %u %u %p %p %p) stub\n",
+ image, width, height, ret_image, cb, cb_data);
+ return NotImplemented;
+}
+
+/*****************************************************************************
+ * GdipImageRotateFlip [GDIPLUS.@]
+ */
+GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
+{
+ FIXME("(%p %u) stub\n", image, type);
+ return NotImplemented;
+}