mirror of
https://github.com/reactos/reactos.git
synced 2025-02-20 15:35:04 +00:00
- Sync gdiplus with Wine 1.1.21
svn path=/trunk/; revision=40851
This commit is contained in:
parent
8a68f45533
commit
182d8bb7f6
6 changed files with 382 additions and 98 deletions
|
@ -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 @@ GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
|
|||
|
||||
break;
|
||||
}
|
||||
case BrushTypeLinearGradient:
|
||||
*clone = GdipAlloc(sizeof(GpLineGradient));
|
||||
if(!*clone) return OutOfMemory;
|
||||
case BrushTypeLinearGradient:{
|
||||
GpLineGradient *dest, *src;
|
||||
INT count;
|
||||
|
||||
memcpy(*clone, brush, sizeof(GpLineGradient));
|
||||
dest = GdipAlloc(sizeof(GpLineGradient));
|
||||
if(!dest) return OutOfMemory;
|
||||
|
||||
(*clone)->gdibrush = CreateSolidBrush((*clone)->lb.lbColor);
|
||||
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 @@ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
|
|||
(*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 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect,
|
|||
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 @@ GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect,
|
|||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
return GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap, line);
|
||||
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 @@ GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
|
|||
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 GdipScaleTextureTransform(GpTexture* brush,
|
|||
}
|
||||
|
||||
GpStatus WINGDIPAPI GdipSetLineBlend(GpLineGradient *brush,
|
||||
GDIPCONST REAL *blend, GDIPCONST REAL* positions, INT count)
|
||||
GDIPCONST REAL *factors, GDIPCONST REAL* positions, INT count)
|
||||
{
|
||||
static int calls;
|
||||
REAL *new_blendfac, *new_blendpos;
|
||||
|
||||
if(!brush || !blend || !positions || count <= 0)
|
||||
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;
|
||||
|
||||
if(!(calls++))
|
||||
FIXME("not implemented\n");
|
||||
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 GdipSetLineGammaCorrection(GpLineGradient *line,
|
|||
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");
|
||||
/* we want 2 standard deviations */
|
||||
erf_range = 2.0 / sqrt(2);
|
||||
|
||||
return NotImplemented;
|
||||
/* 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 @@ GpStatus WINGDIPAPI GdipGetLineRect(GpLineGradient *brush, GpRectF *rect)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ WINE_DEFAULT_DEBUG_CHANNEL (gdiplus);
|
|||
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)
|
||||
{
|
||||
REAL dpi;
|
||||
|
@ -193,7 +195,7 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc,
|
|||
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 @@ GpStatus WINGDIPAPI GdipNewInstalledFontCollection(
|
|||
if (!fontCollection)
|
||||
return InvalidParameter;
|
||||
|
||||
return NotImplemented;
|
||||
*fontCollection = &installedFontCollection;
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -91,6 +91,7 @@ struct GpPen{
|
|||
struct GpGraphics{
|
||||
HDC hdc;
|
||||
HWND hwnd;
|
||||
BOOL owndc;
|
||||
SmoothingMode smoothing;
|
||||
CompositingQuality compqual;
|
||||
InterpolationMode interpolation;
|
||||
|
@ -142,8 +143,12 @@ struct GpLineGradient{
|
|||
GpPointF endpoint;
|
||||
ARGB startcolor;
|
||||
ARGB endcolor;
|
||||
RectF rect;
|
||||
GpWrapMode wrap;
|
||||
BOOL gamma;
|
||||
REAL* blendfac; /* blend factors */
|
||||
REAL* blendpos; /* blend positions */
|
||||
INT blendcount;
|
||||
};
|
||||
|
||||
struct GpTexture{
|
||||
|
|
|
@ -172,15 +172,56 @@ static void transform_and_round_points(GpGraphics *graphics, POINT *pti,
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
switch (brush->bt)
|
||||
|
@ -189,7 +230,6 @@ static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
|
|||
{
|
||||
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 @@ static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
|
|||
|
||||
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 @@ static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
|
|||
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;
|
||||
tilt = startx - startbottomx;
|
||||
|
||||
if (num_steps > abs(width)) num_steps = abs(width);
|
||||
if (startx >= startbottomx)
|
||||
{
|
||||
leftx = rc.left;
|
||||
rightx = rc.right + tilt;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftx = rc.left + tilt;
|
||||
rightx = rc.right;
|
||||
}
|
||||
|
||||
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++)
|
||||
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;
|
||||
tilt = starty - startrighty;
|
||||
|
||||
if (num_steps > abs(height)) num_steps = abs(height);
|
||||
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 @@ GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra
|
|||
|
||||
(*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 GdipCreateFromHDC2(HDC hdc, HANDLE hDevice, GpGraphics **gra
|
|||
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 @@ GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
|
|||
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 @@ GpStatus WINGDIPAPI GdipFillRectangle(GpGraphics *graphics, GpBrush *brush,
|
|||
|
||||
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 @@ GpStatus WINGDIPAPI GdipSetPixelOffsetMode(GpGraphics *graphics, PixelOffsetMode
|
|||
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);
|
||||
|
|
|
@ -87,6 +87,21 @@ GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap* bitmap, INT x, INT y,
|
|||
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;
|
||||
}
|
||||
|
||||
/* This function returns a pointer to an array of pixels that represents the
|
||||
* bitmap. The *entire* bitmap is locked according to the lock mode specified by
|
||||
* flags. It is correct behavior that a user who calls this function with write
|
||||
|
@ -1648,3 +1663,24 @@ GpStatus WINGDIPAPI GdipImageForceValidation(GpImage *image)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue