ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

brush.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Google (Evan Stade)
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include <stdarg.h>
00020 
00021 #include "windef.h"
00022 #include "winbase.h"
00023 #include "winuser.h"
00024 #include "wingdi.h"
00025 
00026 #define COBJMACROS
00027 #include "objbase.h"
00028 #include "olectl.h"
00029 #include "ole2.h"
00030 
00031 #include "gdiplus.h"
00032 #include "gdiplus_private.h"
00033 #include "wine/debug.h"
00034 
00035 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
00036 
00037 /*
00038     Unix stuff
00039     Code from http://www.johndcook.com/blog/2009/01/19/stand-alone-error-function-erf/
00040 */
00041 double erf(double x)
00042 {
00043     const float a1 =  0.254829592;
00044     const float a2 = -0.284496736;
00045     const float a3 =  1.421413741;
00046     const float a4 = -1.453152027;
00047     const float a5 =  1.061405429;
00048     const float p  =  0.3275911;
00049     float t, y, sign;
00050 
00051     /* Save the sign of x */
00052     sign = 1;
00053     if (x < 0)
00054         sign = -1;
00055     x = abs(x);
00056 
00057     /* A & S 7.1.26 */
00058     t = 1.0/(1.0 + p*x);
00059     y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);
00060 
00061     return sign*y;
00062 }
00063 
00064 /******************************************************************************
00065  * GdipCloneBrush [GDIPLUS.@]
00066  */
00067 GpStatus WINGDIPAPI GdipCloneBrush(GpBrush *brush, GpBrush **clone)
00068 {
00069     TRACE("(%p, %p)\n", brush, clone);
00070 
00071     if(!brush || !clone)
00072         return InvalidParameter;
00073 
00074     switch(brush->bt){
00075         case BrushTypeSolidColor:
00076         {
00077             *clone = GdipAlloc(sizeof(GpSolidFill));
00078             if (!*clone) return OutOfMemory;
00079             memcpy(*clone, brush, sizeof(GpSolidFill));
00080             break;
00081         }
00082         case BrushTypeHatchFill:
00083         {
00084             GpHatch *hatch = (GpHatch*)brush;
00085 
00086             return GdipCreateHatchBrush(hatch->hatchstyle, hatch->forecol, hatch->backcol, (GpHatch**)clone);
00087         }
00088         case BrushTypePathGradient:{
00089             GpPathGradient *src, *dest;
00090             INT count, pcount;
00091             GpStatus stat;
00092 
00093             *clone = GdipAlloc(sizeof(GpPathGradient));
00094             if (!*clone) return OutOfMemory;
00095 
00096             src = (GpPathGradient*) brush,
00097             dest = (GpPathGradient*) *clone;
00098 
00099             memcpy(dest, src, sizeof(GpPathGradient));
00100 
00101             stat = GdipClonePath(src->path, &dest->path);
00102 
00103             if(stat != Ok){
00104                 GdipFree(dest);
00105                 return stat;
00106             }
00107 
00108             stat = GdipCloneMatrix(src->transform, &dest->transform);
00109 
00110             if(stat != Ok){
00111                 GdipDeletePath(dest->path);
00112                 GdipFree(dest);
00113                 return stat;
00114             }
00115 
00116             /* blending */
00117             count = src->blendcount;
00118             dest->blendcount = count;
00119             dest->blendfac = GdipAlloc(count * sizeof(REAL));
00120             dest->blendpos = GdipAlloc(count * sizeof(REAL));
00121             dest->surroundcolors = GdipAlloc(dest->surroundcolorcount * sizeof(ARGB));
00122             pcount = dest->pblendcount;
00123             if (pcount)
00124             {
00125                 dest->pblendcolor = GdipAlloc(pcount * sizeof(ARGB));
00126                 dest->pblendpos = GdipAlloc(pcount * sizeof(REAL));
00127             }
00128 
00129             if(!dest->blendfac || !dest->blendpos || !dest->surroundcolors ||
00130                (pcount && (!dest->pblendcolor || !dest->pblendpos))){
00131                 GdipDeletePath(dest->path);
00132                 GdipDeleteMatrix(dest->transform);
00133                 GdipFree(dest->blendfac);
00134                 GdipFree(dest->blendpos);
00135                 GdipFree(dest->surroundcolors);
00136                 GdipFree(dest->pblendcolor);
00137                 GdipFree(dest->pblendpos);
00138                 GdipFree(dest);
00139                 return OutOfMemory;
00140             }
00141 
00142             memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
00143             memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
00144             memcpy(dest->surroundcolors, src->surroundcolors, dest->surroundcolorcount * sizeof(ARGB));
00145 
00146             if (pcount)
00147             {
00148                 memcpy(dest->pblendcolor, src->pblendcolor, pcount * sizeof(ARGB));
00149                 memcpy(dest->pblendpos, src->pblendpos, pcount * sizeof(REAL));
00150             }
00151 
00152             break;
00153         }
00154         case BrushTypeLinearGradient:{
00155             GpLineGradient *dest, *src;
00156             INT count, pcount;
00157 
00158             dest = GdipAlloc(sizeof(GpLineGradient));
00159             if(!dest)    return OutOfMemory;
00160 
00161             src = (GpLineGradient*)brush;
00162 
00163             memcpy(dest, src, sizeof(GpLineGradient));
00164 
00165             count = dest->blendcount;
00166             dest->blendfac = GdipAlloc(count * sizeof(REAL));
00167             dest->blendpos = GdipAlloc(count * sizeof(REAL));
00168             pcount = dest->pblendcount;
00169             if (pcount)
00170             {
00171                 dest->pblendcolor = GdipAlloc(pcount * sizeof(ARGB));
00172                 dest->pblendpos = GdipAlloc(pcount * sizeof(REAL));
00173             }
00174 
00175             if (!dest->blendfac || !dest->blendpos ||
00176                 (pcount && (!dest->pblendcolor || !dest->pblendpos)))
00177             {
00178                 GdipFree(dest->blendfac);
00179                 GdipFree(dest->blendpos);
00180                 GdipFree(dest->pblendcolor);
00181                 GdipFree(dest->pblendpos);
00182                 GdipFree(dest);
00183                 return OutOfMemory;
00184             }
00185 
00186             memcpy(dest->blendfac, src->blendfac, count * sizeof(REAL));
00187             memcpy(dest->blendpos, src->blendpos, count * sizeof(REAL));
00188 
00189             if (pcount)
00190             {
00191                 memcpy(dest->pblendcolor, src->pblendcolor, pcount * sizeof(ARGB));
00192                 memcpy(dest->pblendpos, src->pblendpos, pcount * sizeof(REAL));
00193             }
00194 
00195             *clone = &dest->brush;
00196             break;
00197         }
00198         case BrushTypeTextureFill:
00199         {
00200             GpStatus stat;
00201             GpTexture *texture = (GpTexture*)brush;
00202             GpTexture *new_texture;
00203             UINT width, height;
00204 
00205             stat = GdipGetImageWidth(texture->image, &width);
00206             if (stat != Ok) return stat;
00207             stat = GdipGetImageHeight(texture->image, &height);
00208             if (stat != Ok) return stat;
00209 
00210             stat = GdipCreateTextureIA(texture->image, texture->imageattributes, 0, 0, width, height, &new_texture);
00211 
00212             if (stat == Ok)
00213             {
00214                 memcpy(new_texture->transform, texture->transform, sizeof(GpMatrix));
00215                 *clone = (GpBrush*)new_texture;
00216             }
00217             else
00218                 *clone = NULL;
00219 
00220             return stat;
00221         }
00222         default:
00223             ERR("not implemented for brush type %d\n", brush->bt);
00224             return NotImplemented;
00225     }
00226 
00227     TRACE("<-- %p\n", *clone);
00228     return Ok;
00229 }
00230 
00231 static const char HatchBrushes[][8] = {
00232     { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }, /* HatchStyleHorizontal */
00233     { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, /* HatchStyleVertical */
00234     { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }, /* HatchStyleForwardDiagonal */
00235     { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, /* HatchStyleBackwardDiagonal */
00236     { 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08 }, /* HatchStyleCross */
00237     { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }, /* HatchStyleDiagonalCross */
00238     { 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80 }, /* HatchStyle05Percent */
00239     { 0x00, 0x02, 0x00, 0x88, 0x00, 0x20, 0x00, 0x88 }, /* HatchStyle10Percent */
00240     { 0x00, 0x22, 0x00, 0xcc, 0x00, 0x22, 0x00, 0xcc }, /* HatchStyle20Percent */
00241     { 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xcc }, /* HatchStyle25Percent */
00242     { 0x00, 0xcc, 0x04, 0xcc, 0x00, 0xcc, 0x40, 0xcc }, /* HatchStyle30Percent */
00243     { 0x44, 0xcc, 0x22, 0xcc, 0x44, 0xcc, 0x22, 0xcc }, /* HatchStyle40Percent */
00244     { 0x55, 0xcc, 0x55, 0xcc, 0x55, 0xcc, 0x55, 0xcc }, /* HatchStyle50Percent */
00245     { 0x55, 0xcd, 0x55, 0xee, 0x55, 0xdc, 0x55, 0xee }, /* HatchStyle60Percent */
00246     { 0x55, 0xdd, 0x55, 0xff, 0x55, 0xdd, 0x55, 0xff }, /* HatchStyle70Percent */
00247     { 0x55, 0xff, 0x55, 0xff, 0x55, 0xff, 0x55, 0xff }, /* HatchStyle75Percent */
00248     { 0x55, 0xff, 0x59, 0xff, 0x55, 0xff, 0x99, 0xff }, /* HatchStyle80Percent */
00249     { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xfd, 0xff }, /* HatchStyle90Percent */
00250     { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, /* HatchStyleLightDownwardDiagonal */
00251     { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 }, /* HatchStyleLightUpwardDiagonal */
00252     { 0x99, 0x33, 0x66, 0xcc, 0x99, 0x33, 0x66, 0xcc }, /* HatchStyleDarkDownwardDiagonal */
00253     { 0xcc, 0x66, 0x33, 0x99, 0xcc, 0x66, 0x33, 0x99 }, /* HatchStyleDarkUpwardDiagonal */
00254     { 0xc1, 0x83, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0 }, /* HatchStyleWideDownwardDiagonal */
00255     { 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x83, 0xc1 }, /* HatchStyleWideUpwardDiagonal */
00256     { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, /* HatchStyleLightVertical */
00257     { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff }, /* HatchStyleLightHorizontal */
00258     { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, /* HatchStyleNarrowVertical */
00259     { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff }, /* HatchStyleNarrowHorizontal */
00260     { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }, /* HatchStyleDarkVertical */
00261     { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff }, /* HatchStyleDarkHorizontal */
00262 };
00263 
00264 GpStatus get_hatch_data(HatchStyle hatchstyle, const char **result)
00265 {
00266     if (hatchstyle < sizeof(HatchBrushes) / sizeof(HatchBrushes[0]))
00267     {
00268         *result = HatchBrushes[hatchstyle];
00269         return Ok;
00270     }
00271     else
00272         return NotImplemented;
00273 }
00274 
00275 /******************************************************************************
00276  * GdipCreateHatchBrush [GDIPLUS.@]
00277  */
00278 GpStatus WINGDIPAPI GdipCreateHatchBrush(HatchStyle hatchstyle, ARGB forecol, ARGB backcol, GpHatch **brush)
00279 {
00280     TRACE("(%d, %d, %d, %p)\n", hatchstyle, forecol, backcol, brush);
00281 
00282     if(!brush)  return InvalidParameter;
00283 
00284     *brush = GdipAlloc(sizeof(GpHatch));
00285     if (!*brush) return OutOfMemory;
00286 
00287     (*brush)->brush.bt = BrushTypeHatchFill;
00288     (*brush)->forecol = forecol;
00289     (*brush)->backcol = backcol;
00290     (*brush)->hatchstyle = hatchstyle;
00291     TRACE("<-- %p\n", *brush);
00292 
00293     return Ok;
00294 }
00295 
00296 /******************************************************************************
00297  * GdipCreateLineBrush [GDIPLUS.@]
00298  */
00299 GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint,
00300     GDIPCONST GpPointF* endpoint, ARGB startcolor, ARGB endcolor,
00301     GpWrapMode wrap, GpLineGradient **line)
00302 {
00303     TRACE("(%s, %s, %x, %x, %d, %p)\n", debugstr_pointf(startpoint),
00304           debugstr_pointf(endpoint), startcolor, endcolor, wrap, line);
00305 
00306     if(!line || !startpoint || !endpoint || wrap == WrapModeClamp)
00307         return InvalidParameter;
00308 
00309     if (startpoint->X == endpoint->X && startpoint->Y == endpoint->Y)
00310         return OutOfMemory;
00311 
00312     *line = GdipAlloc(sizeof(GpLineGradient));
00313     if(!*line)  return OutOfMemory;
00314 
00315     (*line)->brush.bt = BrushTypeLinearGradient;
00316 
00317     (*line)->startpoint.X = startpoint->X;
00318     (*line)->startpoint.Y = startpoint->Y;
00319     (*line)->endpoint.X = endpoint->X;
00320     (*line)->endpoint.Y = endpoint->Y;
00321     (*line)->startcolor = startcolor;
00322     (*line)->endcolor = endcolor;
00323     (*line)->wrap = wrap;
00324     (*line)->gamma = FALSE;
00325 
00326     (*line)->rect.X = (startpoint->X < endpoint->X ? startpoint->X: endpoint->X);
00327     (*line)->rect.Y = (startpoint->Y < endpoint->Y ? startpoint->Y: endpoint->Y);
00328     (*line)->rect.Width  = fabs(startpoint->X - endpoint->X);
00329     (*line)->rect.Height = fabs(startpoint->Y - endpoint->Y);
00330 
00331     if ((*line)->rect.Width == 0)
00332     {
00333         (*line)->rect.X -= (*line)->rect.Height / 2.0f;
00334         (*line)->rect.Width = (*line)->rect.Height;
00335     }
00336     else if ((*line)->rect.Height == 0)
00337     {
00338         (*line)->rect.Y -= (*line)->rect.Width / 2.0f;
00339         (*line)->rect.Height = (*line)->rect.Width;
00340     }
00341 
00342     (*line)->blendcount = 1;
00343     (*line)->blendfac = GdipAlloc(sizeof(REAL));
00344     (*line)->blendpos = GdipAlloc(sizeof(REAL));
00345 
00346     if (!(*line)->blendfac || !(*line)->blendpos)
00347     {
00348         GdipFree((*line)->blendfac);
00349         GdipFree((*line)->blendpos);
00350         GdipFree(*line);
00351         *line = NULL;
00352         return OutOfMemory;
00353     }
00354 
00355     (*line)->blendfac[0] = 1.0f;
00356     (*line)->blendpos[0] = 1.0f;
00357 
00358     (*line)->pblendcolor = NULL;
00359     (*line)->pblendpos = NULL;
00360     (*line)->pblendcount = 0;
00361 
00362     TRACE("<-- %p\n", *line);
00363 
00364     return Ok;
00365 }
00366 
00367 GpStatus WINGDIPAPI GdipCreateLineBrushI(GDIPCONST GpPoint* startpoint,
00368     GDIPCONST GpPoint* endpoint, ARGB startcolor, ARGB endcolor,
00369     GpWrapMode wrap, GpLineGradient **line)
00370 {
00371     GpPointF stF;
00372     GpPointF endF;
00373 
00374     TRACE("(%p, %p, %x, %x, %d, %p)\n", startpoint, endpoint,
00375           startcolor, endcolor, wrap, line);
00376 
00377     if(!startpoint || !endpoint)
00378         return InvalidParameter;
00379 
00380     stF.X  = (REAL)startpoint->X;
00381     stF.Y  = (REAL)startpoint->Y;
00382     endF.X = (REAL)endpoint->X;
00383     endF.Y = (REAL)endpoint->Y;
00384 
00385     return GdipCreateLineBrush(&stF, &endF, startcolor, endcolor, wrap, line);
00386 }
00387 
00388 GpStatus WINGDIPAPI GdipCreateLineBrushFromRect(GDIPCONST GpRectF* rect,
00389     ARGB startcolor, ARGB endcolor, LinearGradientMode mode, GpWrapMode wrap,
00390     GpLineGradient **line)
00391 {
00392     GpPointF start, end;
00393     GpStatus stat;
00394 
00395     TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
00396           wrap, line);
00397 
00398     if(!line || !rect)
00399         return InvalidParameter;
00400 
00401     switch (mode)
00402     {
00403     case LinearGradientModeHorizontal:
00404         start.X = rect->X;
00405         start.Y = rect->Y;
00406         end.X = rect->X + rect->Width;
00407         end.Y = rect->Y;
00408         break;
00409     case LinearGradientModeVertical:
00410         start.X = rect->X;
00411         start.Y = rect->Y;
00412         end.X = rect->X;
00413         end.Y = rect->Y + rect->Height;
00414         break;
00415     case LinearGradientModeForwardDiagonal:
00416         start.X = rect->X;
00417         start.Y = rect->Y;
00418         end.X = rect->X + rect->Width;
00419         end.Y = rect->Y + rect->Height;
00420         break;
00421     case LinearGradientModeBackwardDiagonal:
00422         start.X = rect->X + rect->Width;
00423         start.Y = rect->Y;
00424         end.X = rect->X;
00425         end.Y = rect->Y + rect->Height;
00426         break;
00427     default:
00428         return InvalidParameter;
00429     }
00430 
00431     stat = GdipCreateLineBrush(&start, &end, startcolor, endcolor, wrap, line);
00432 
00433     if (stat == Ok)
00434         (*line)->rect = *rect;
00435 
00436     return stat;
00437 }
00438 
00439 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectI(GDIPCONST GpRect* rect,
00440     ARGB startcolor, ARGB endcolor, LinearGradientMode mode, GpWrapMode wrap,
00441     GpLineGradient **line)
00442 {
00443     GpRectF rectF;
00444 
00445     TRACE("(%p, %x, %x, %d, %d, %p)\n", rect, startcolor, endcolor, mode,
00446           wrap, line);
00447 
00448     rectF.X      = (REAL) rect->X;
00449     rectF.Y      = (REAL) rect->Y;
00450     rectF.Width  = (REAL) rect->Width;
00451     rectF.Height = (REAL) rect->Height;
00452 
00453     return GdipCreateLineBrushFromRect(&rectF, startcolor, endcolor, mode, wrap, line);
00454 }
00455 
00456 /******************************************************************************
00457  * GdipCreateLineBrushFromRectWithAngle [GDIPLUS.@]
00458  */
00459 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngle(GDIPCONST GpRectF* rect,
00460     ARGB startcolor, ARGB endcolor, REAL angle, BOOL isAngleScalable, GpWrapMode wrap,
00461     GpLineGradient **line)
00462 {
00463     GpStatus stat;
00464     LinearGradientMode mode;
00465     REAL width, height, exofs, eyofs;
00466     REAL sin_angle, cos_angle, sin_cos_angle;
00467 
00468     TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
00469           wrap, line);
00470 
00471     sin_angle = sinf(deg2rad(angle));
00472     cos_angle = cosf(deg2rad(angle));
00473     sin_cos_angle = sin_angle * cos_angle;
00474 
00475     if (isAngleScalable)
00476     {
00477         width = height = 1.0;
00478     }
00479     else
00480     {
00481         width = rect->Width;
00482         height = rect->Height;
00483     }
00484 
00485     if (sin_cos_angle >= 0)
00486         mode = LinearGradientModeForwardDiagonal;
00487     else
00488         mode = LinearGradientModeBackwardDiagonal;
00489 
00490     stat = GdipCreateLineBrushFromRect(rect, startcolor, endcolor, mode, wrap, line);
00491 
00492     if (stat == Ok)
00493     {
00494         if (sin_cos_angle >= 0)
00495         {
00496             exofs = width * sin_cos_angle + height * cos_angle * cos_angle;
00497             eyofs = width * sin_angle * sin_angle + height * sin_cos_angle;
00498         }
00499         else
00500         {
00501             exofs = width * sin_angle * sin_angle + height * sin_cos_angle;
00502             eyofs = -width * sin_cos_angle + height * sin_angle * sin_angle;
00503         }
00504 
00505         if (isAngleScalable)
00506         {
00507             exofs = exofs * rect->Width;
00508             eyofs = eyofs * rect->Height;
00509         }
00510 
00511         if (sin_angle >= 0)
00512         {
00513             (*line)->endpoint.X = rect->X + exofs;
00514             (*line)->endpoint.Y = rect->Y + eyofs;
00515         }
00516         else
00517         {
00518             (*line)->endpoint.X = (*line)->startpoint.X;
00519             (*line)->endpoint.Y = (*line)->startpoint.Y;
00520             (*line)->startpoint.X = rect->X + exofs;
00521             (*line)->startpoint.Y = rect->Y + eyofs;
00522         }
00523     }
00524 
00525     return stat;
00526 }
00527 
00528 GpStatus WINGDIPAPI GdipCreateLineBrushFromRectWithAngleI(GDIPCONST GpRect* rect,
00529     ARGB startcolor, ARGB endcolor, REAL angle, BOOL isAngleScalable, GpWrapMode wrap,
00530     GpLineGradient **line)
00531 {
00532     TRACE("(%p, %x, %x, %.2f, %d, %d, %p)\n", rect, startcolor, endcolor, angle, isAngleScalable,
00533           wrap, line);
00534 
00535     return GdipCreateLineBrushFromRectI(rect, startcolor, endcolor, LinearGradientModeForwardDiagonal,
00536                                         wrap, line);
00537 }
00538 
00539 static GpStatus create_path_gradient(GpPath *path, ARGB centercolor, GpPathGradient **grad)
00540 {
00541     GpRectF bounds;
00542     GpStatus stat;
00543 
00544     if(!path || !grad)
00545         return InvalidParameter;
00546 
00547     if (path->pathdata.Count < 2)
00548         return OutOfMemory;
00549 
00550     GdipGetPathWorldBounds(path, &bounds, NULL, NULL);
00551 
00552     *grad = GdipAlloc(sizeof(GpPathGradient));
00553     if (!*grad)
00554     {
00555         return OutOfMemory;
00556     }
00557 
00558     stat = GdipCreateMatrix(&(*grad)->transform);
00559     if (stat != Ok)
00560     {
00561         GdipFree(*grad);
00562         return stat;
00563     }
00564 
00565     (*grad)->blendfac = GdipAlloc(sizeof(REAL));
00566     (*grad)->blendpos = GdipAlloc(sizeof(REAL));
00567     (*grad)->surroundcolors = GdipAlloc(sizeof(ARGB));
00568     if(!(*grad)->blendfac || !(*grad)->blendpos || !(*grad)->surroundcolors){
00569         GdipDeleteMatrix((*grad)->transform);
00570         GdipFree((*grad)->blendfac);
00571         GdipFree((*grad)->blendpos);
00572         GdipFree((*grad)->surroundcolors);
00573         GdipFree(*grad);
00574         *grad = NULL;
00575         return OutOfMemory;
00576     }
00577     (*grad)->blendfac[0] = 1.0;
00578     (*grad)->blendpos[0] = 1.0;
00579     (*grad)->blendcount  = 1;
00580 
00581     (*grad)->path = path;
00582 
00583     (*grad)->brush.bt = BrushTypePathGradient;
00584     (*grad)->centercolor = centercolor;
00585     (*grad)->wrap = WrapModeClamp;
00586     (*grad)->gamma = FALSE;
00587     /* FIXME: this should be set to the "centroid" of the path by default */
00588     (*grad)->center.X = bounds.X + bounds.Width / 2;
00589     (*grad)->center.Y = bounds.Y + bounds.Height / 2;
00590     (*grad)->focus.X = 0.0;
00591     (*grad)->focus.Y = 0.0;
00592     (*grad)->surroundcolors[0] = 0xffffffff;
00593     (*grad)->surroundcolorcount = 1;
00594 
00595     TRACE("<-- %p\n", *grad);
00596 
00597     return Ok;
00598 }
00599 
00600 GpStatus WINGDIPAPI GdipCreatePathGradient(GDIPCONST GpPointF* points,
00601     INT count, GpWrapMode wrap, GpPathGradient **grad)
00602 {
00603     GpStatus stat;
00604     GpPath *path;
00605 
00606     TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
00607 
00608     if(!grad)
00609         return InvalidParameter;
00610 
00611     if(!points || count <= 0)
00612         return OutOfMemory;
00613 
00614     stat = GdipCreatePath(FillModeAlternate, &path);
00615 
00616     if (stat == Ok)
00617     {
00618         stat = GdipAddPathLine2(path, points, count);
00619 
00620         if (stat == Ok)
00621             stat = create_path_gradient(path, 0xff000000, grad);
00622 
00623         if (stat != Ok)
00624             GdipDeletePath(path);
00625     }
00626 
00627     if (stat == Ok)
00628         (*grad)->wrap = wrap;
00629 
00630     return stat;
00631 }
00632 
00633 GpStatus WINGDIPAPI GdipCreatePathGradientI(GDIPCONST GpPoint* points,
00634     INT count, GpWrapMode wrap, GpPathGradient **grad)
00635 {
00636     GpStatus stat;
00637     GpPath *path;
00638 
00639     TRACE("(%p, %d, %d, %p)\n", points, count, wrap, grad);
00640 
00641     if(!grad)
00642         return InvalidParameter;
00643 
00644     if(!points || count <= 0)
00645         return OutOfMemory;
00646 
00647     stat = GdipCreatePath(FillModeAlternate, &path);
00648 
00649     if (stat == Ok)
00650     {
00651         stat = GdipAddPathLine2I(path, points, count);
00652 
00653         if (stat == Ok)
00654             stat = create_path_gradient(path, 0xff000000, grad);
00655 
00656         if (stat != Ok)
00657             GdipDeletePath(path);
00658     }
00659 
00660     if (stat == Ok)
00661         (*grad)->wrap = wrap;
00662 
00663     return stat;
00664 }
00665 
00666 /******************************************************************************
00667  * GdipCreatePathGradientFromPath [GDIPLUS.@]
00668  */
00669 GpStatus WINGDIPAPI GdipCreatePathGradientFromPath(GDIPCONST GpPath* path,
00670     GpPathGradient **grad)
00671 {
00672     GpStatus stat;
00673     GpPath *new_path;
00674 
00675     TRACE("(%p, %p)\n", path, grad);
00676 
00677     if(!grad)
00678         return InvalidParameter;
00679 
00680     if (!path)
00681         return OutOfMemory;
00682 
00683     stat = GdipClonePath((GpPath*)path, &new_path);
00684 
00685     if (stat == Ok)
00686     {
00687         stat = create_path_gradient(new_path, 0xffffffff, grad);
00688 
00689         if (stat != Ok)
00690             GdipDeletePath(new_path);
00691     }
00692 
00693     return stat;
00694 }
00695 
00696 /******************************************************************************
00697  * GdipCreateSolidFill [GDIPLUS.@]
00698  */
00699 GpStatus WINGDIPAPI GdipCreateSolidFill(ARGB color, GpSolidFill **sf)
00700 {
00701     TRACE("(%x, %p)\n", color, sf);
00702 
00703     if(!sf)  return InvalidParameter;
00704 
00705     *sf = GdipAlloc(sizeof(GpSolidFill));
00706     if (!*sf) return OutOfMemory;
00707 
00708     (*sf)->brush.bt = BrushTypeSolidColor;
00709     (*sf)->color = color;
00710 
00711     TRACE("<-- %p\n", *sf);
00712 
00713     return Ok;
00714 }
00715 
00716 /******************************************************************************
00717  * GdipCreateTexture [GDIPLUS.@]
00718  *
00719  * PARAMS
00720  *  image       [I] image to use
00721  *  wrapmode    [I] optional
00722  *  texture     [O] pointer to the resulting texturebrush
00723  *
00724  * RETURNS
00725  *  SUCCESS: Ok
00726  *  FAILURE: element of GpStatus
00727  */
00728 GpStatus WINGDIPAPI GdipCreateTexture(GpImage *image, GpWrapMode wrapmode,
00729         GpTexture **texture)
00730 {
00731     UINT width, height;
00732     GpImageAttributes *attributes;
00733     GpStatus stat;
00734 
00735     TRACE("%p, %d %p\n", image, wrapmode, texture);
00736 
00737     if (!(image && texture))
00738         return InvalidParameter;
00739 
00740     stat = GdipGetImageWidth(image, &width);
00741     if (stat != Ok) return stat;
00742     stat = GdipGetImageHeight(image, &height);
00743     if (stat != Ok) return stat;
00744 
00745     stat = GdipCreateImageAttributes(&attributes);
00746 
00747     if (stat == Ok)
00748     {
00749         attributes->wrap = wrapmode;
00750 
00751         stat = GdipCreateTextureIA(image, attributes, 0, 0, width, height,
00752             texture);
00753 
00754         GdipDisposeImageAttributes(attributes);
00755     }
00756 
00757     return stat;
00758 }
00759 
00760 /******************************************************************************
00761  * GdipCreateTexture2 [GDIPLUS.@]
00762  */
00763 GpStatus WINGDIPAPI GdipCreateTexture2(GpImage *image, GpWrapMode wrapmode,
00764         REAL x, REAL y, REAL width, REAL height, GpTexture **texture)
00765 {
00766     GpImageAttributes *attributes;
00767     GpStatus stat;
00768 
00769     TRACE("%p %d %f %f %f %f %p\n", image, wrapmode,
00770             x, y, width, height, texture);
00771 
00772     stat = GdipCreateImageAttributes(&attributes);
00773 
00774     if (stat == Ok)
00775     {
00776         attributes->wrap = wrapmode;
00777 
00778         stat = GdipCreateTextureIA(image, attributes, x, y, width, height,
00779                 texture);
00780 
00781         GdipDisposeImageAttributes(attributes);
00782     }
00783 
00784     return stat;
00785 }
00786 
00787 /******************************************************************************
00788  * GdipCreateTextureIA [GDIPLUS.@]
00789  *
00790  * FIXME: imageattr ignored
00791  */
00792 GpStatus WINGDIPAPI GdipCreateTextureIA(GpImage *image,
00793     GDIPCONST GpImageAttributes *imageattr, REAL x, REAL y, REAL width,
00794     REAL height, GpTexture **texture)
00795 {
00796     GpStatus status;
00797     GpImage *new_image=NULL;
00798 
00799     TRACE("(%p, %p, %.2f, %.2f, %.2f, %.2f, %p)\n", image, imageattr, x, y, width, height,
00800            texture);
00801 
00802     if(!image || !texture || x < 0.0 || y < 0.0 || width < 0.0 || height < 0.0)
00803         return InvalidParameter;
00804 
00805     *texture = NULL;
00806 
00807     if(image->type != ImageTypeBitmap){
00808         FIXME("not implemented for image type %d\n", image->type);
00809         return NotImplemented;
00810     }
00811 
00812     status = GdipCloneBitmapArea(x, y, width, height, PixelFormatDontCare, (GpBitmap*)image, (GpBitmap**)&new_image);
00813     if (status != Ok)
00814         return status;
00815 
00816     *texture = GdipAlloc(sizeof(GpTexture));
00817     if (!*texture){
00818         status = OutOfMemory;
00819         goto exit;
00820     }
00821 
00822     if((status = GdipCreateMatrix(&(*texture)->transform)) != Ok){
00823         goto exit;
00824     }
00825 
00826     if (imageattr)
00827     {
00828         status = GdipCloneImageAttributes(imageattr, &(*texture)->imageattributes);
00829     }
00830     else
00831     {
00832         status = GdipCreateImageAttributes(&(*texture)->imageattributes);
00833         if (status == Ok)
00834             (*texture)->imageattributes->wrap = WrapModeTile;
00835     }
00836     if (status == Ok)
00837     {
00838         (*texture)->brush.bt = BrushTypeTextureFill;
00839         (*texture)->image = new_image;
00840     }
00841 
00842 exit:
00843     if (status == Ok)
00844     {
00845         TRACE("<-- %p\n", *texture);
00846     }
00847     else
00848     {
00849         if (*texture)
00850         {
00851             GdipDeleteMatrix((*texture)->transform);
00852             GdipDisposeImageAttributes((*texture)->imageattributes);
00853             GdipFree(*texture);
00854             *texture = NULL;
00855         }
00856         GdipDisposeImage(new_image);
00857         TRACE("<-- error %u\n", status);
00858     }
00859 
00860     return status;
00861 }
00862 
00863 /******************************************************************************
00864  * GdipCreateTextureIAI [GDIPLUS.@]
00865  */
00866 GpStatus WINGDIPAPI GdipCreateTextureIAI(GpImage *image, GDIPCONST GpImageAttributes *imageattr,
00867     INT x, INT y, INT width, INT height, GpTexture **texture)
00868 {
00869     TRACE("(%p, %p, %d, %d, %d, %d, %p)\n", image, imageattr, x, y, width, height,
00870            texture);
00871 
00872     return GdipCreateTextureIA(image,imageattr,(REAL)x,(REAL)y,(REAL)width,(REAL)height,texture);
00873 }
00874 
00875 GpStatus WINGDIPAPI GdipCreateTexture2I(GpImage *image, GpWrapMode wrapmode,
00876         INT x, INT y, INT width, INT height, GpTexture **texture)
00877 {
00878     GpImageAttributes *imageattr;
00879     GpStatus stat;
00880 
00881     TRACE("%p %d %d %d %d %d %p\n", image, wrapmode, x, y, width, height,
00882             texture);
00883 
00884     stat = GdipCreateImageAttributes(&imageattr);
00885 
00886     if (stat == Ok)
00887     {
00888         imageattr->wrap = wrapmode;
00889 
00890         stat = GdipCreateTextureIA(image, imageattr, x, y, width, height, texture);
00891     }
00892 
00893     return stat;
00894 }
00895 
00896 GpStatus WINGDIPAPI GdipGetBrushType(GpBrush *brush, GpBrushType *type)
00897 {
00898     TRACE("(%p, %p)\n", brush, type);
00899 
00900     if(!brush || !type)  return InvalidParameter;
00901 
00902     *type = brush->bt;
00903 
00904     return Ok;
00905 }
00906 
00907 GpStatus WINGDIPAPI GdipGetHatchBackgroundColor(GpHatch *brush, ARGB *backcol)
00908 {
00909     TRACE("(%p, %p)\n", brush, backcol);
00910 
00911     if(!brush || !backcol)  return InvalidParameter;
00912 
00913     *backcol = brush->backcol;
00914 
00915     return Ok;
00916 }
00917 
00918 GpStatus WINGDIPAPI GdipGetHatchForegroundColor(GpHatch *brush, ARGB *forecol)
00919 {
00920     TRACE("(%p, %p)\n", brush, forecol);
00921 
00922     if(!brush || !forecol)  return InvalidParameter;
00923 
00924     *forecol = brush->forecol;
00925 
00926     return Ok;
00927 }
00928 
00929 GpStatus WINGDIPAPI GdipGetHatchStyle(GpHatch *brush, HatchStyle *hatchstyle)
00930 {
00931     TRACE("(%p, %p)\n", brush, hatchstyle);
00932 
00933     if(!brush || !hatchstyle)  return InvalidParameter;
00934 
00935     *hatchstyle = brush->hatchstyle;
00936 
00937     return Ok;
00938 }
00939 
00940 GpStatus WINGDIPAPI GdipDeleteBrush(GpBrush *brush)
00941 {
00942     TRACE("(%p)\n", brush);
00943 
00944     if(!brush)  return InvalidParameter;
00945 
00946     switch(brush->bt)
00947     {
00948         case BrushTypePathGradient:
00949             GdipDeletePath(((GpPathGradient*) brush)->path);
00950             GdipDeleteMatrix(((GpPathGradient*) brush)->transform);
00951             GdipFree(((GpPathGradient*) brush)->blendfac);
00952             GdipFree(((GpPathGradient*) brush)->blendpos);
00953             GdipFree(((GpPathGradient*) brush)->surroundcolors);
00954             GdipFree(((GpPathGradient*) brush)->pblendcolor);
00955             GdipFree(((GpPathGradient*) brush)->pblendpos);
00956             break;
00957         case BrushTypeLinearGradient:
00958             GdipFree(((GpLineGradient*)brush)->blendfac);
00959             GdipFree(((GpLineGradient*)brush)->blendpos);
00960             GdipFree(((GpLineGradient*)brush)->pblendcolor);
00961             GdipFree(((GpLineGradient*)brush)->pblendpos);
00962             break;
00963         case BrushTypeTextureFill:
00964             GdipDeleteMatrix(((GpTexture*)brush)->transform);
00965             GdipDisposeImage(((GpTexture*)brush)->image);
00966             GdipDisposeImageAttributes(((GpTexture*)brush)->imageattributes);
00967             GdipFree(((GpTexture*)brush)->bitmap_bits);
00968             break;
00969         default:
00970             break;
00971     }
00972 
00973     GdipFree(brush);
00974 
00975     return Ok;
00976 }
00977 
00978 GpStatus WINGDIPAPI GdipGetLineGammaCorrection(GpLineGradient *line,
00979     BOOL *usinggamma)
00980 {
00981     TRACE("(%p, %p)\n", line, usinggamma);
00982 
00983     if(!line || !usinggamma)
00984         return InvalidParameter;
00985 
00986     *usinggamma = line->gamma;
00987 
00988     return Ok;
00989 }
00990 
00991 GpStatus WINGDIPAPI GdipGetLineWrapMode(GpLineGradient *brush, GpWrapMode *wrapmode)
00992 {
00993     TRACE("(%p, %p)\n", brush, wrapmode);
00994 
00995     if(!brush || !wrapmode)
00996         return InvalidParameter;
00997 
00998     *wrapmode = brush->wrap;
00999 
01000     return Ok;
01001 }
01002 
01003 GpStatus WINGDIPAPI GdipGetPathGradientBlend(GpPathGradient *brush, REAL *blend,
01004     REAL *positions, INT count)
01005 {
01006     TRACE("(%p, %p, %p, %d)\n", brush, blend, positions, count);
01007 
01008     if(!brush || !blend || !positions || count <= 0)
01009         return InvalidParameter;
01010 
01011     if(count < brush->blendcount)
01012         return InsufficientBuffer;
01013 
01014     memcpy(blend, brush->blendfac, count*sizeof(REAL));
01015     if(brush->blendcount > 1){
01016         memcpy(positions, brush->blendpos, count*sizeof(REAL));
01017     }
01018 
01019     return Ok;
01020 }
01021 
01022 GpStatus WINGDIPAPI GdipGetPathGradientBlendCount(GpPathGradient *brush, INT *count)
01023 {
01024     TRACE("(%p, %p)\n", brush, count);
01025 
01026     if(!brush || !count)
01027         return InvalidParameter;
01028 
01029     *count = brush->blendcount;
01030 
01031     return Ok;
01032 }
01033 
01034 GpStatus WINGDIPAPI GdipGetPathGradientCenterPoint(GpPathGradient *grad,
01035     GpPointF *point)
01036 {
01037     TRACE("(%p, %p)\n", grad, point);
01038 
01039     if(!grad || !point)
01040         return InvalidParameter;
01041 
01042     point->X = grad->center.X;
01043     point->Y = grad->center.Y;
01044 
01045     return Ok;
01046 }
01047 
01048 GpStatus WINGDIPAPI GdipGetPathGradientCenterPointI(GpPathGradient *grad,
01049     GpPoint *point)
01050 {
01051     GpStatus ret;
01052     GpPointF ptf;
01053 
01054     TRACE("(%p, %p)\n", grad, point);
01055 
01056     if(!point)
01057         return InvalidParameter;
01058 
01059     ret = GdipGetPathGradientCenterPoint(grad,&ptf);
01060 
01061     if(ret == Ok){
01062         point->X = roundr(ptf.X);
01063         point->Y = roundr(ptf.Y);
01064     }
01065 
01066     return ret;
01067 }
01068 
01069 GpStatus WINGDIPAPI GdipGetPathGradientCenterColor(GpPathGradient *grad,
01070     ARGB *colors)
01071 {
01072     TRACE("(%p,%p)\n", grad, colors);
01073 
01074     if (!grad || !colors)
01075         return InvalidParameter;
01076 
01077     *colors = grad->centercolor;
01078 
01079     return Ok;
01080 }
01081 
01082 GpStatus WINGDIPAPI GdipGetPathGradientFocusScales(GpPathGradient *grad,
01083     REAL *x, REAL *y)
01084 {
01085     TRACE("(%p, %p, %p)\n", grad, x, y);
01086 
01087     if(!grad || !x || !y)
01088         return InvalidParameter;
01089 
01090     *x = grad->focus.X;
01091     *y = grad->focus.Y;
01092 
01093     return Ok;
01094 }
01095 
01096 GpStatus WINGDIPAPI GdipGetPathGradientGammaCorrection(GpPathGradient *grad,
01097     BOOL *gamma)
01098 {
01099     TRACE("(%p, %p)\n", grad, gamma);
01100 
01101     if(!grad || !gamma)
01102         return InvalidParameter;
01103 
01104     *gamma = grad->gamma;
01105 
01106     return Ok;
01107 }
01108 
01109 GpStatus WINGDIPAPI GdipGetPathGradientPath(GpPathGradient *grad, GpPath *path)
01110 {
01111     static int calls;
01112 
01113     TRACE("(%p, %p)\n", grad, path);
01114 
01115     if (!(calls++))
01116         FIXME("not implemented\n");
01117 
01118     return NotImplemented;
01119 }
01120 
01121 GpStatus WINGDIPAPI GdipGetPathGradientPointCount(GpPathGradient *grad,
01122     INT *count)
01123 {
01124     TRACE("(%p, %p)\n", grad, count);
01125 
01126     if(!grad || !count)
01127         return InvalidParameter;
01128 
01129     *count = grad->path->pathdata.Count;
01130 
01131     return Ok;
01132 }
01133 
01134 GpStatus WINGDIPAPI GdipGetPathGradientRect(GpPathGradient *brush, GpRectF *rect)
01135 {
01136     GpStatus stat;
01137 
01138     TRACE("(%p, %p)\n", brush, rect);
01139 
01140     if(!brush || !rect)
01141         return InvalidParameter;
01142 
01143     stat = GdipGetPathWorldBounds(brush->path, rect, NULL, NULL);
01144 
01145     return stat;
01146 }
01147 
01148 GpStatus WINGDIPAPI GdipGetPathGradientRectI(GpPathGradient *brush, GpRect *rect)
01149 {
01150     GpRectF rectf;
01151     GpStatus stat;
01152 
01153     TRACE("(%p, %p)\n", brush, rect);
01154 
01155     if(!brush || !rect)
01156         return InvalidParameter;
01157 
01158     stat = GdipGetPathGradientRect(brush, &rectf);
01159     if(stat != Ok)  return stat;
01160 
01161     rect->X = roundr(rectf.X);
01162     rect->Y = roundr(rectf.Y);
01163     rect->Width  = roundr(rectf.Width);
01164     rect->Height = roundr(rectf.Height);
01165 
01166     return Ok;
01167 }
01168 
01169 GpStatus WINGDIPAPI GdipGetPathGradientSurroundColorsWithCount(GpPathGradient
01170     *grad, ARGB *argb, INT *count)
01171 {
01172     INT i;
01173 
01174     TRACE("(%p,%p,%p)\n", grad, argb, count);
01175 
01176     if(!grad || !argb || !count || (*count < grad->path->pathdata.Count))
01177         return InvalidParameter;
01178 
01179     for (i=0; i<grad->path->pathdata.Count; i++)
01180     {
01181         if (i < grad->surroundcolorcount)
01182             argb[i] = grad->surroundcolors[i];
01183         else
01184             argb[i] = grad->surroundcolors[grad->surroundcolorcount-1];
01185     }
01186 
01187     *count = grad->surroundcolorcount;
01188 
01189     return Ok;
01190 }
01191 
01192 GpStatus WINGDIPAPI GdipGetPathGradientSurroundColorCount(GpPathGradient *brush, INT *count)
01193 {
01194     TRACE("(%p, %p)\n", brush, count);
01195 
01196     if (!brush || !count)
01197        return InvalidParameter;
01198 
01199     /* Yes, this actually returns the number of points in the path (which is the
01200      * required size of a buffer to get the surround colors), rather than the
01201      * number of surround colors. The real count is returned when getting the
01202      * colors. */
01203     *count = brush->path->pathdata.Count;
01204 
01205     return Ok;
01206 }
01207 
01208 GpStatus WINGDIPAPI GdipGetPathGradientWrapMode(GpPathGradient *brush,
01209     GpWrapMode *wrapmode)
01210 {
01211     TRACE("(%p, %p)\n", brush, wrapmode);
01212 
01213     if(!brush || !wrapmode)
01214         return InvalidParameter;
01215 
01216     *wrapmode = brush->wrap;
01217 
01218     return Ok;
01219 }
01220 
01221 GpStatus WINGDIPAPI GdipGetSolidFillColor(GpSolidFill *sf, ARGB *argb)
01222 {
01223     TRACE("(%p, %p)\n", sf, argb);
01224 
01225     if(!sf || !argb)
01226         return InvalidParameter;
01227 
01228     *argb = sf->color;
01229 
01230     return Ok;
01231 }
01232 
01233 /******************************************************************************
01234  * GdipGetTextureImage [GDIPLUS.@]
01235  */
01236 GpStatus WINGDIPAPI GdipGetTextureImage(GpTexture *brush, GpImage **image)
01237 {
01238     TRACE("(%p, %p)\n", brush, image);
01239 
01240     if(!brush || !image)
01241         return InvalidParameter;
01242 
01243     return GdipCloneImage(brush->image, image);
01244 }
01245 
01246 /******************************************************************************
01247  * GdipGetTextureTransform [GDIPLUS.@]
01248  */
01249 GpStatus WINGDIPAPI GdipGetTextureTransform(GpTexture *brush, GpMatrix *matrix)
01250 {
01251     TRACE("(%p, %p)\n", brush, matrix);
01252 
01253     if(!brush || !matrix)
01254         return InvalidParameter;
01255 
01256     memcpy(matrix, brush->transform, sizeof(GpMatrix));
01257 
01258     return Ok;
01259 }
01260 
01261 /******************************************************************************
01262  * GdipGetTextureWrapMode [GDIPLUS.@]
01263  */
01264 GpStatus WINGDIPAPI GdipGetTextureWrapMode(GpTexture *brush, GpWrapMode *wrapmode)
01265 {
01266     TRACE("(%p, %p)\n", brush, wrapmode);
01267 
01268     if(!brush || !wrapmode)
01269         return InvalidParameter;
01270 
01271     *wrapmode = brush->imageattributes->wrap;
01272 
01273     return Ok;
01274 }
01275 
01276 /******************************************************************************
01277  * GdipMultiplyTextureTransform [GDIPLUS.@]
01278  */
01279 GpStatus WINGDIPAPI GdipMultiplyTextureTransform(GpTexture* brush,
01280     GDIPCONST GpMatrix *matrix, GpMatrixOrder order)
01281 {
01282     TRACE("(%p, %p, %d)\n", brush, matrix, order);
01283 
01284     if(!brush || !matrix)
01285         return InvalidParameter;
01286 
01287     return GdipMultiplyMatrix(brush->transform, matrix, order);
01288 }
01289 
01290 /******************************************************************************
01291  * GdipResetTextureTransform [GDIPLUS.@]
01292  */
01293 GpStatus WINGDIPAPI GdipResetTextureTransform(GpTexture* brush)
01294 {
01295     TRACE("(%p)\n", brush);
01296 
01297     if(!brush)
01298         return InvalidParameter;
01299 
01300     return GdipSetMatrixElements(brush->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
01301 }
01302 
01303 /******************************************************************************
01304  * GdipScaleTextureTransform [GDIPLUS.@]
01305  */
01306 GpStatus WINGDIPAPI GdipScaleTextureTransform(GpTexture* brush,
01307     REAL sx, REAL sy, GpMatrixOrder order)
01308 {
01309     TRACE("(%p, %.2f, %.2f, %d)\n", brush, sx, sy, order);
01310 
01311     if(!brush)
01312         return InvalidParameter;
01313 
01314     return GdipScaleMatrix(brush->transform, sx, sy, order);
01315 }
01316 
01317 GpStatus WINGDIPAPI GdipSetLineBlend(GpLineGradient *brush,
01318     GDIPCONST REAL *factors, GDIPCONST REAL* positions, INT count)
01319 {
01320     REAL *new_blendfac, *new_blendpos;
01321 
01322     TRACE("(%p, %p, %p, %i)\n", brush, factors, positions, count);
01323 
01324     if(!brush || !factors || !positions || count <= 0 ||
01325        (count >= 2 && (positions[0] != 0.0f || positions[count-1] != 1.0f)))
01326         return InvalidParameter;
01327 
01328     new_blendfac = GdipAlloc(count * sizeof(REAL));
01329     new_blendpos = GdipAlloc(count * sizeof(REAL));
01330 
01331     if (!new_blendfac || !new_blendpos)
01332     {
01333         GdipFree(new_blendfac);
01334         GdipFree(new_blendpos);
01335         return OutOfMemory;
01336     }
01337 
01338     memcpy(new_blendfac, factors, count * sizeof(REAL));
01339     memcpy(new_blendpos, positions, count * sizeof(REAL));
01340 
01341     GdipFree(brush->blendfac);
01342     GdipFree(brush->blendpos);
01343 
01344     brush->blendcount = count;
01345     brush->blendfac = new_blendfac;
01346     brush->blendpos = new_blendpos;
01347 
01348     return Ok;
01349 }
01350 
01351 GpStatus WINGDIPAPI GdipGetLineBlend(GpLineGradient *brush, REAL *factors,
01352     REAL *positions, INT count)
01353 {
01354     TRACE("(%p, %p, %p, %i)\n", brush, factors, positions, count);
01355 
01356     if (!brush || !factors || !positions || count <= 0)
01357         return InvalidParameter;
01358 
01359     if (count < brush->blendcount)
01360         return InsufficientBuffer;
01361 
01362     memcpy(factors, brush->blendfac, brush->blendcount * sizeof(REAL));
01363     memcpy(positions, brush->blendpos, brush->blendcount * sizeof(REAL));
01364 
01365     return Ok;
01366 }
01367 
01368 GpStatus WINGDIPAPI GdipGetLineBlendCount(GpLineGradient *brush, INT *count)
01369 {
01370     TRACE("(%p, %p)\n", brush, count);
01371 
01372     if (!brush || !count)
01373         return InvalidParameter;
01374 
01375     *count = brush->blendcount;
01376 
01377     return Ok;
01378 }
01379 
01380 GpStatus WINGDIPAPI GdipSetLineGammaCorrection(GpLineGradient *line,
01381     BOOL usegamma)
01382 {
01383     TRACE("(%p, %d)\n", line, usegamma);
01384 
01385     if(!line)
01386         return InvalidParameter;
01387 
01388     line->gamma = usegamma;
01389 
01390     return Ok;
01391 }
01392 
01393 GpStatus WINGDIPAPI GdipSetLineSigmaBlend(GpLineGradient *line, REAL focus,
01394     REAL scale)
01395 {
01396     REAL factors[33];
01397     REAL positions[33];
01398     int num_points = 0;
01399     int i;
01400     const int precision = 16;
01401     REAL erf_range; /* we use values erf(-erf_range) through erf(+erf_range) */
01402     REAL min_erf;
01403     REAL scale_erf;
01404 
01405     TRACE("(%p, %0.2f, %0.2f)\n", line, focus, scale);
01406 
01407     if(!line || focus < 0.0 || focus > 1.0 || scale < 0.0 || scale > 1.0)
01408         return InvalidParameter;
01409 
01410     /* we want 2 standard deviations */
01411     erf_range = 2.0 / sqrt(2);
01412 
01413     /* calculate the constants we need to normalize the error function to be
01414         between 0.0 and scale over the range we need */
01415     min_erf = erf(-erf_range);
01416     scale_erf = scale / (-2.0 * min_erf);
01417 
01418     if (focus != 0.0)
01419     {
01420         positions[0] = 0.0;
01421         factors[0] = 0.0;
01422         for (i=1; i<precision; i++)
01423         {
01424             positions[i] = focus * i / precision;
01425             factors[i] = scale_erf * (erf(2 * erf_range * i / precision - erf_range) - min_erf);
01426         }
01427         num_points += precision;
01428     }
01429 
01430     positions[num_points] = focus;
01431     factors[num_points] = scale;
01432     num_points += 1;
01433 
01434     if (focus != 1.0)
01435     {
01436         for (i=1; i<precision; i++)
01437         {
01438             positions[i+num_points-1] = (focus + ((1.0-focus) * i / precision));
01439             factors[i+num_points-1] = scale_erf * (erf(erf_range - 2 * erf_range * i / precision) - min_erf);
01440         }
01441         num_points += precision;
01442         positions[num_points-1] = 1.0;
01443         factors[num_points-1] = 0.0;
01444     }
01445 
01446     return GdipSetLineBlend(line, factors, positions, num_points);
01447 }
01448 
01449 GpStatus WINGDIPAPI GdipSetLineWrapMode(GpLineGradient *line,
01450     GpWrapMode wrap)
01451 {
01452     TRACE("(%p, %d)\n", line, wrap);
01453 
01454     if(!line || wrap == WrapModeClamp)
01455         return InvalidParameter;
01456 
01457     line->wrap = wrap;
01458 
01459     return Ok;
01460 }
01461 
01462 GpStatus WINGDIPAPI GdipSetPathGradientBlend(GpPathGradient *brush, GDIPCONST REAL *blend,
01463     GDIPCONST REAL *pos, INT count)
01464 {
01465     REAL *new_blendfac, *new_blendpos;
01466 
01467     TRACE("(%p,%p,%p,%i)\n", brush, blend, pos, count);
01468 
01469     if(!brush || !blend || !pos || count <= 0 ||
01470        (count >= 2 && (pos[0] != 0.0f || pos[count-1] != 1.0f)))
01471         return InvalidParameter;
01472 
01473     new_blendfac = GdipAlloc(count * sizeof(REAL));
01474     new_blendpos = GdipAlloc(count * sizeof(REAL));
01475 
01476     if (!new_blendfac || !new_blendpos)
01477     {
01478         GdipFree(new_blendfac);
01479         GdipFree(new_blendpos);
01480         return OutOfMemory;
01481     }
01482 
01483     memcpy(new_blendfac, blend, count * sizeof(REAL));
01484     memcpy(new_blendpos, pos, count * sizeof(REAL));
01485 
01486     GdipFree(brush->blendfac);
01487     GdipFree(brush->blendpos);
01488 
01489     brush->blendcount = count;
01490     brush->blendfac = new_blendfac;
01491     brush->blendpos = new_blendpos;
01492 
01493     return Ok;
01494 }
01495 
01496 GpStatus WINGDIPAPI GdipSetPathGradientLinearBlend(GpPathGradient *brush,
01497     REAL focus, REAL scale)
01498 {
01499     REAL factors[3];
01500     REAL positions[3];
01501     int num_points = 0;
01502 
01503     TRACE("(%p,%0.2f,%0.2f)\n", brush, focus, scale);
01504 
01505     if (!brush) return InvalidParameter;
01506 
01507     if (focus != 0.0)
01508     {
01509         factors[num_points] = 0.0;
01510         positions[num_points] = 0.0;
01511         num_points++;
01512     }
01513 
01514     factors[num_points] = scale;
01515     positions[num_points] = focus;
01516     num_points++;
01517 
01518     if (focus != 1.0)
01519     {
01520         factors[num_points] = 0.0;
01521         positions[num_points] = 1.0;
01522         num_points++;
01523     }
01524 
01525     return GdipSetPathGradientBlend(brush, factors, positions, num_points);
01526 }
01527 
01528 GpStatus WINGDIPAPI GdipSetPathGradientPresetBlend(GpPathGradient *brush,
01529     GDIPCONST ARGB *blend, GDIPCONST REAL *pos, INT count)
01530 {
01531     ARGB *new_color;
01532     REAL *new_pos;
01533     TRACE("(%p,%p,%p,%i)\n", brush, blend, pos, count);
01534 
01535     if (!brush || !blend || !pos || count < 2 ||
01536         pos[0] != 0.0f || pos[count-1] != 1.0f)
01537     {
01538         return InvalidParameter;
01539     }
01540 
01541     new_color = GdipAlloc(count * sizeof(ARGB));
01542     new_pos = GdipAlloc(count * sizeof(REAL));
01543     if (!new_color || !new_pos)
01544     {
01545         GdipFree(new_color);
01546         GdipFree(new_pos);
01547         return OutOfMemory;
01548     }
01549 
01550     memcpy(new_color, blend, sizeof(ARGB) * count);
01551     memcpy(new_pos, pos, sizeof(REAL) * count);
01552 
01553     GdipFree(brush->pblendcolor);
01554     GdipFree(brush->pblendpos);
01555 
01556     brush->pblendcolor = new_color;
01557     brush->pblendpos = new_pos;
01558     brush->pblendcount = count;
01559 
01560     return Ok;
01561 }
01562 
01563 GpStatus WINGDIPAPI GdipGetPathGradientPresetBlend(GpPathGradient *brush,
01564     ARGB *blend, REAL *pos, INT count)
01565 {
01566     TRACE("(%p,%p,%p,%i)\n", brush, blend, pos, count);
01567 
01568     if (count < 0)
01569         return OutOfMemory;
01570 
01571     if (!brush || !blend || !pos || count < 2)
01572         return InvalidParameter;
01573 
01574     if (brush->pblendcount == 0)
01575         return GenericError;
01576 
01577     if (count != brush->pblendcount)
01578     {
01579         /* Native lines up the ends of each array, and copies the destination size. */
01580         FIXME("Braindead behavior on wrong-sized buffer not implemented.\n");
01581         return InvalidParameter;
01582     }
01583 
01584     memcpy(blend, brush->pblendcolor, sizeof(ARGB) * brush->pblendcount);
01585     memcpy(pos, brush->pblendpos, sizeof(REAL) * brush->pblendcount);
01586 
01587     return Ok;
01588 }
01589 
01590 GpStatus WINGDIPAPI GdipGetPathGradientPresetBlendCount(GpPathGradient *brush,
01591     INT *count)
01592 {
01593     TRACE("(%p,%p)\n", brush, count);
01594 
01595     if (!brush || !count)
01596         return InvalidParameter;
01597 
01598     *count = brush->pblendcount;
01599 
01600     return Ok;
01601 }
01602 
01603 GpStatus WINGDIPAPI GdipSetPathGradientCenterColor(GpPathGradient *grad,
01604     ARGB argb)
01605 {
01606     TRACE("(%p, %x)\n", grad, argb);
01607 
01608     if(!grad)
01609         return InvalidParameter;
01610 
01611     grad->centercolor = argb;
01612     return Ok;
01613 }
01614 
01615 GpStatus WINGDIPAPI GdipSetPathGradientCenterPoint(GpPathGradient *grad,
01616     GpPointF *point)
01617 {
01618     TRACE("(%p, %s)\n", grad, debugstr_pointf(point));
01619 
01620     if(!grad || !point)
01621         return InvalidParameter;
01622 
01623     grad->center.X = point->X;
01624     grad->center.Y = point->Y;
01625 
01626     return Ok;
01627 }
01628 
01629 GpStatus WINGDIPAPI GdipSetPathGradientCenterPointI(GpPathGradient *grad,
01630     GpPoint *point)
01631 {
01632     GpPointF ptf;
01633 
01634     TRACE("(%p, %p)\n", grad, point);
01635 
01636     if(!point)
01637         return InvalidParameter;
01638 
01639     ptf.X = (REAL)point->X;
01640     ptf.Y = (REAL)point->Y;
01641 
01642     return GdipSetPathGradientCenterPoint(grad,&ptf);
01643 }
01644 
01645 GpStatus WINGDIPAPI GdipSetPathGradientFocusScales(GpPathGradient *grad,
01646     REAL x, REAL y)
01647 {
01648     TRACE("(%p, %.2f, %.2f)\n", grad, x, y);
01649 
01650     if(!grad)
01651         return InvalidParameter;
01652 
01653     grad->focus.X = x;
01654     grad->focus.Y = y;
01655 
01656     return Ok;
01657 }
01658 
01659 GpStatus WINGDIPAPI GdipSetPathGradientGammaCorrection(GpPathGradient *grad,
01660     BOOL gamma)
01661 {
01662     TRACE("(%p, %d)\n", grad, gamma);
01663 
01664     if(!grad)
01665         return InvalidParameter;
01666 
01667     grad->gamma = gamma;
01668 
01669     return Ok;
01670 }
01671 
01672 GpStatus WINGDIPAPI GdipSetPathGradientSigmaBlend(GpPathGradient *grad,
01673     REAL focus, REAL scale)
01674 {
01675     REAL factors[33];
01676     REAL positions[33];
01677     int num_points = 0;
01678     int i;
01679     const int precision = 16;
01680     REAL erf_range; /* we use values erf(-erf_range) through erf(+erf_range) */
01681     REAL min_erf;
01682     REAL scale_erf;
01683 
01684     TRACE("(%p,%0.2f,%0.2f)\n", grad, focus, scale);
01685 
01686     if(!grad || focus < 0.0 || focus > 1.0 || scale < 0.0 || scale > 1.0)
01687         return InvalidParameter;
01688 
01689     /* we want 2 standard deviations */
01690     erf_range = 2.0 / sqrt(2);
01691 
01692     /* calculate the constants we need to normalize the error function to be
01693         between 0.0 and scale over the range we need */
01694     min_erf = erf(-erf_range);
01695     scale_erf = scale / (-2.0 * min_erf);
01696 
01697     if (focus != 0.0)
01698     {
01699         positions[0] = 0.0;
01700         factors[0] = 0.0;
01701         for (i=1; i<precision; i++)
01702         {
01703             positions[i] = focus * i / precision;
01704             factors[i] = scale_erf * (erf(2 * erf_range * i / precision - erf_range) - min_erf);
01705         }
01706         num_points += precision;
01707     }
01708 
01709     positions[num_points] = focus;
01710     factors[num_points] = scale;
01711     num_points += 1;
01712 
01713     if (focus != 1.0)
01714     {
01715         for (i=1; i<precision; i++)
01716         {
01717             positions[i+num_points-1] = (focus + ((1.0-focus) * i / precision));
01718             factors[i+num_points-1] = scale_erf * (erf(erf_range - 2 * erf_range * i / precision) - min_erf);
01719         }
01720         num_points += precision;
01721         positions[num_points-1] = 1.0;
01722         factors[num_points-1] = 0.0;
01723     }
01724 
01725     return GdipSetPathGradientBlend(grad, factors, positions, num_points);
01726 }
01727 
01728 GpStatus WINGDIPAPI GdipSetPathGradientSurroundColorsWithCount(GpPathGradient
01729     *grad, GDIPCONST ARGB *argb, INT *count)
01730 {
01731     ARGB *new_surroundcolors;
01732     INT i, num_colors;
01733 
01734     TRACE("(%p,%p,%p)\n", grad, argb, count);
01735 
01736     if(!grad || !argb || !count || (*count <= 0) ||
01737         (*count > grad->path->pathdata.Count))
01738         return InvalidParameter;
01739 
01740     num_colors = *count;
01741 
01742     /* If all colors are the same, only store 1 color. */
01743     if (*count > 1)
01744     {
01745         for (i=1; i < num_colors; i++)
01746             if (argb[i] != argb[i-1])
01747                 break;
01748 
01749         if (i == num_colors)
01750             num_colors = 1;
01751     }
01752 
01753     new_surroundcolors = GdipAlloc(num_colors * sizeof(ARGB));
01754     if (!new_surroundcolors)
01755         return OutOfMemory;
01756 
01757     memcpy(new_surroundcolors, argb, num_colors * sizeof(ARGB));
01758 
01759     GdipFree(grad->surroundcolors);
01760 
01761     grad->surroundcolors = new_surroundcolors;
01762     grad->surroundcolorcount = num_colors;
01763 
01764     return Ok;
01765 }
01766 
01767 GpStatus WINGDIPAPI GdipSetPathGradientWrapMode(GpPathGradient *grad,
01768     GpWrapMode wrap)
01769 {
01770     TRACE("(%p, %d)\n", grad, wrap);
01771 
01772     if(!grad)
01773         return InvalidParameter;
01774 
01775     grad->wrap = wrap;
01776 
01777     return Ok;
01778 }
01779 
01780 GpStatus WINGDIPAPI GdipSetPathGradientTransform(GpPathGradient *grad,
01781     GpMatrix *matrix)
01782 {
01783     TRACE("(%p,%p)\n", grad, matrix);
01784 
01785     if (!grad || !matrix)
01786         return InvalidParameter;
01787 
01788     memcpy(grad->transform, matrix, sizeof(GpMatrix));
01789 
01790     return Ok;
01791 }
01792 
01793 GpStatus WINGDIPAPI GdipGetPathGradientTransform(GpPathGradient *grad,
01794     GpMatrix *matrix)
01795 {
01796     TRACE("(%p,%p)\n", grad, matrix);
01797 
01798     if (!grad || !matrix)
01799         return InvalidParameter;
01800 
01801     memcpy(matrix, grad->transform, sizeof(GpMatrix));
01802 
01803     return Ok;
01804 }
01805 
01806 GpStatus WINGDIPAPI GdipMultiplyPathGradientTransform(GpPathGradient *grad,
01807     GDIPCONST GpMatrix *matrix, GpMatrixOrder order)
01808 {
01809     TRACE("(%p,%p,%i)\n", grad, matrix, order);
01810 
01811     if (!grad)
01812         return InvalidParameter;
01813 
01814     return GdipMultiplyMatrix(grad->transform, matrix, order);
01815 }
01816 
01817 GpStatus WINGDIPAPI GdipResetPathGradientTransform(GpPathGradient *grad)
01818 {
01819     TRACE("(%p)\n", grad);
01820 
01821     if (!grad)
01822         return InvalidParameter;
01823 
01824     return GdipSetMatrixElements(grad->transform, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
01825 }
01826 
01827 GpStatus WINGDIPAPI GdipRotatePathGradientTransform(GpPathGradient *grad,
01828     REAL angle, GpMatrixOrder order)
01829 {
01830     TRACE("(%p,%0.2f,%i)\n", grad, angle, order);
01831 
01832     if (!grad)
01833         return InvalidParameter;
01834 
01835     return GdipRotateMatrix(grad->transform, angle, order);
01836 }
01837 
01838 GpStatus WINGDIPAPI GdipScalePathGradientTransform(GpPathGradient *grad,
01839     REAL sx, REAL sy, GpMatrixOrder order)
01840 {
01841     TRACE("(%p,%0.2f,%0.2f,%i)\n", grad, sx, sy, order);
01842 
01843     if (!grad)
01844         return InvalidParameter;
01845 
01846     return GdipScaleMatrix(grad->transform, sx, sy, order);
01847 }
01848 
01849 GpStatus WINGDIPAPI GdipTranslatePathGradientTransform(GpPathGradient *grad,
01850     REAL dx, REAL dy, GpMatrixOrder order)
01851 {
01852     TRACE("(%p,%0.2f,%0.2f,%i)\n", grad, dx, dy, order);
01853 
01854     if (!grad)
01855         return InvalidParameter;
01856 
01857     return GdipTranslateMatrix(grad->transform, dx, dy, order);
01858 }
01859 
01860 GpStatus WINGDIPAPI GdipSetSolidFillColor(GpSolidFill *sf, ARGB argb)
01861 {
01862     TRACE("(%p, %x)\n", sf, argb);
01863 
01864     if(!sf)
01865         return InvalidParameter;
01866 
01867     sf->color = argb;
01868     return Ok;
01869 }
01870 
01871 /******************************************************************************
01872  * GdipSetTextureTransform [GDIPLUS.@]
01873  */
01874 GpStatus WINGDIPAPI GdipSetTextureTransform(GpTexture *texture,
01875     GDIPCONST GpMatrix *matrix)
01876 {
01877     TRACE("(%p, %p)\n", texture, matrix);
01878 
01879     if(!texture || !matrix)
01880         return InvalidParameter;
01881 
01882     memcpy(texture->transform, matrix, sizeof(GpMatrix));
01883 
01884     return Ok;
01885 }
01886 
01887 /******************************************************************************
01888  * GdipSetTextureWrapMode [GDIPLUS.@]
01889  *
01890  * WrapMode not used, only stored
01891  */
01892 GpStatus WINGDIPAPI GdipSetTextureWrapMode(GpTexture *brush, GpWrapMode wrapmode)
01893 {
01894     TRACE("(%p, %d)\n", brush, wrapmode);
01895 
01896     if(!brush)
01897         return InvalidParameter;
01898 
01899     brush->imageattributes->wrap = wrapmode;
01900 
01901     return Ok;
01902 }
01903 
01904 GpStatus WINGDIPAPI GdipSetLineColors(GpLineGradient *brush, ARGB color1,
01905     ARGB color2)
01906 {
01907     TRACE("(%p, %x, %x)\n", brush, color1, color2);
01908 
01909     if(!brush)
01910         return InvalidParameter;
01911 
01912     brush->startcolor = color1;
01913     brush->endcolor   = color2;
01914 
01915     return Ok;
01916 }
01917 
01918 GpStatus WINGDIPAPI GdipGetLineColors(GpLineGradient *brush, ARGB *colors)
01919 {
01920     TRACE("(%p, %p)\n", brush, colors);
01921 
01922     if(!brush || !colors)
01923         return InvalidParameter;
01924 
01925     colors[0] = brush->startcolor;
01926     colors[1] = brush->endcolor;
01927 
01928     return Ok;
01929 }
01930 
01931 /******************************************************************************
01932  * GdipRotateTextureTransform [GDIPLUS.@]
01933  */
01934 GpStatus WINGDIPAPI GdipRotateTextureTransform(GpTexture* brush, REAL angle,
01935     GpMatrixOrder order)
01936 {
01937     TRACE("(%p, %.2f, %d)\n", brush, angle, order);
01938 
01939     if(!brush)
01940         return InvalidParameter;
01941 
01942     return GdipRotateMatrix(brush->transform, angle, order);
01943 }
01944 
01945 GpStatus WINGDIPAPI GdipSetLineLinearBlend(GpLineGradient *brush, REAL focus,
01946     REAL scale)
01947 {
01948     REAL factors[3];
01949     REAL positions[3];
01950     int num_points = 0;
01951 
01952     TRACE("(%p,%.2f,%.2f)\n", brush, focus, scale);
01953 
01954     if (!brush) return InvalidParameter;
01955 
01956     if (focus != 0.0)
01957     {
01958         factors[num_points] = 0.0;
01959         positions[num_points] = 0.0;
01960         num_points++;
01961     }
01962 
01963     factors[num_points] = scale;
01964     positions[num_points] = focus;
01965     num_points++;
01966 
01967     if (focus != 1.0)
01968     {
01969         factors[num_points] = 0.0;
01970         positions[num_points] = 1.0;
01971         num_points++;
01972     }
01973 
01974     return GdipSetLineBlend(brush, factors, positions, num_points);
01975 }
01976 
01977 GpStatus WINGDIPAPI GdipSetLinePresetBlend(GpLineGradient *brush,
01978     GDIPCONST ARGB *blend, GDIPCONST REAL* positions, INT count)
01979 {
01980     ARGB *new_color;
01981     REAL *new_pos;
01982     TRACE("(%p,%p,%p,%i)\n", brush, blend, positions, count);
01983 
01984     if (!brush || !blend || !positions || count < 2 ||
01985         positions[0] != 0.0f || positions[count-1] != 1.0f)
01986     {
01987         return InvalidParameter;
01988     }
01989 
01990     new_color = GdipAlloc(count * sizeof(ARGB));
01991     new_pos = GdipAlloc(count * sizeof(REAL));
01992     if (!new_color || !new_pos)
01993     {
01994         GdipFree(new_color);
01995         GdipFree(new_pos);
01996         return OutOfMemory;
01997     }
01998 
01999     memcpy(new_color, blend, sizeof(ARGB) * count);
02000     memcpy(new_pos, positions, sizeof(REAL) * count);
02001 
02002     GdipFree(brush->pblendcolor);
02003     GdipFree(brush->pblendpos);
02004 
02005     brush->pblendcolor = new_color;
02006     brush->pblendpos = new_pos;
02007     brush->pblendcount = count;
02008 
02009     return Ok;
02010 }
02011 
02012 GpStatus WINGDIPAPI GdipGetLinePresetBlend(GpLineGradient *brush,
02013     ARGB *blend, REAL* positions, INT count)
02014 {
02015     if (!brush || !blend || !positions || count < 2)
02016         return InvalidParameter;
02017 
02018     if (brush->pblendcount == 0)
02019         return GenericError;
02020 
02021     if (count < brush->pblendcount)
02022         return InsufficientBuffer;
02023 
02024     memcpy(blend, brush->pblendcolor, sizeof(ARGB) * brush->pblendcount);
02025     memcpy(positions, brush->pblendpos, sizeof(REAL) * brush->pblendcount);
02026 
02027     return Ok;
02028 }
02029 
02030 GpStatus WINGDIPAPI GdipGetLinePresetBlendCount(GpLineGradient *brush,
02031     INT *count)
02032 {
02033     if (!brush || !count)
02034         return InvalidParameter;
02035 
02036     *count = brush->pblendcount;
02037 
02038     return Ok;
02039 }
02040 
02041 GpStatus WINGDIPAPI GdipResetLineTransform(GpLineGradient *brush)
02042 {
02043     static int calls;
02044 
02045     TRACE("(%p)\n", brush);
02046 
02047     if(!(calls++))
02048         FIXME("not implemented\n");
02049 
02050     return NotImplemented;
02051 }
02052 
02053 GpStatus WINGDIPAPI GdipSetLineTransform(GpLineGradient *brush,
02054     GDIPCONST GpMatrix *matrix)
02055 {
02056     static int calls;
02057 
02058     TRACE("(%p,%p)\n", brush,  matrix);
02059 
02060     if(!(calls++))
02061         FIXME("not implemented\n");
02062 
02063     return NotImplemented;
02064 }
02065 
02066 GpStatus WINGDIPAPI GdipGetLineTransform(GpLineGradient *brush, GpMatrix *matrix)
02067 {
02068     static int calls;
02069 
02070     TRACE("(%p,%p)\n", brush, matrix);
02071 
02072     if(!(calls++))
02073         FIXME("not implemented\n");
02074 
02075     return NotImplemented;
02076 }
02077 
02078 GpStatus WINGDIPAPI GdipScaleLineTransform(GpLineGradient *brush, REAL sx, REAL sy,
02079     GpMatrixOrder order)
02080 {
02081     static int calls;
02082 
02083     TRACE("(%p,%0.2f,%0.2f,%u)\n", brush, sx, sy, order);
02084 
02085     if(!(calls++))
02086         FIXME("not implemented\n");
02087 
02088     return NotImplemented;
02089 }
02090 
02091 GpStatus WINGDIPAPI GdipMultiplyLineTransform(GpLineGradient *brush,
02092     GDIPCONST GpMatrix *matrix, GpMatrixOrder order)
02093 {
02094     static int calls;
02095 
02096     TRACE("(%p,%p,%u)\n", brush, matrix, order);
02097 
02098     if(!(calls++))
02099         FIXME("not implemented\n");
02100 
02101     return NotImplemented;
02102 }
02103 
02104 GpStatus WINGDIPAPI GdipTranslateLineTransform(GpLineGradient* brush,
02105         REAL dx, REAL dy, GpMatrixOrder order)
02106 {
02107     static int calls;
02108 
02109     TRACE("(%p,%f,%f,%d)\n", brush, dx, dy, order);
02110 
02111     if(!(calls++))
02112         FIXME("not implemented\n");
02113 
02114     return Ok;
02115 }
02116 
02117 /******************************************************************************
02118  * GdipTranslateTextureTransform [GDIPLUS.@]
02119  */
02120 GpStatus WINGDIPAPI GdipTranslateTextureTransform(GpTexture* brush, REAL dx, REAL dy,
02121     GpMatrixOrder order)
02122 {
02123     TRACE("(%p, %.2f, %.2f, %d)\n", brush, dx, dy, order);
02124 
02125     if(!brush)
02126         return InvalidParameter;
02127 
02128     return GdipTranslateMatrix(brush->transform, dx, dy, order);
02129 }
02130 
02131 GpStatus WINGDIPAPI GdipGetLineRect(GpLineGradient *brush, GpRectF *rect)
02132 {
02133     TRACE("(%p, %p)\n", brush, rect);
02134 
02135     if(!brush || !rect)
02136         return InvalidParameter;
02137 
02138     *rect = brush->rect;
02139 
02140     return Ok;
02141 }
02142 
02143 GpStatus WINGDIPAPI GdipGetLineRectI(GpLineGradient *brush, GpRect *rect)
02144 {
02145     GpRectF  rectF;
02146     GpStatus ret;
02147 
02148     TRACE("(%p, %p)\n", brush, rect);
02149 
02150     if(!rect)
02151         return InvalidParameter;
02152 
02153     ret = GdipGetLineRect(brush, &rectF);
02154 
02155     if(ret == Ok){
02156         rect->X      = roundr(rectF.X);
02157         rect->Y      = roundr(rectF.Y);
02158         rect->Width  = roundr(rectF.Width);
02159         rect->Height = roundr(rectF.Height);
02160     }
02161 
02162     return ret;
02163 }
02164 
02165 GpStatus WINGDIPAPI GdipRotateLineTransform(GpLineGradient* brush,
02166     REAL angle, GpMatrixOrder order)
02167 {
02168     static int calls;
02169 
02170     TRACE("(%p,%0.2f,%u)\n", brush, angle, order);
02171 
02172     if(!brush)
02173         return InvalidParameter;
02174 
02175     if(!(calls++))
02176         FIXME("(%p, %.2f, %d) stub\n", brush, angle, order);
02177 
02178     return NotImplemented;
02179 }

Generated on Sat May 26 2012 04:22:09 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.