- Sync gdiplus with Wine 1.1.21

svn path=/trunk/; revision=40851
This commit is contained in:
Dmitry Chapyshev 2009-05-09 09:26:16 +00:00
parent 8a68f45533
commit 182d8bb7f6
6 changed files with 382 additions and 98 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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{

View file

@ -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);

View file

@ -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;
}