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

gradient.c
Go to the documentation of this file.
00001 /* 
00002  * COPYRIGHT:         See COPYING in the top level directory
00003  * PROJECT:           ReactOS kernel
00004  * PURPOSE:           GDI Driver Gradient Functions
00005  * FILE:              subsys/win32k/eng/gradient.c
00006  * PROGRAMER:         Thomas Weidenmueller
00007  */
00008 
00009 #include <win32k.h>
00010 
00011 #define NDEBUG
00012 #include <debug.h>
00013 
00014 /* MACROS *********************************************************************/
00015 
00016 const LONG LINC[2] = {-1, 1};
00017 
00018 #define VERTEX(n) (pVertex + gt->n)
00019 #define COMPAREVERTEX(a, b) ((a)->x == (b)->x && (a)->y == (b)->y)
00020 
00021 #define VCMPCLR(a,b,c,color) (a->color != b->color || a->color != c->color)
00022 #define VCMPCLRS(a,b,c) \
00023   !(!VCMPCLR(a,b,c,Red) || !VCMPCLR(a,b,c,Green) || !VCMPCLR(a,b,c,Blue))
00024 
00025 /* Horizontal/Vertical gradients */
00026 #define HVINITCOL(Col, id) \
00027   c[id] = v1->Col >> 8; \
00028   dc[id] = abs((v2->Col >> 8) - c[id]); \
00029   ec[id] = -(dy >> 1); \
00030   ic[id] = LINC[(v2->Col >> 8) > c[id]]
00031 #define HVSTEPCOL(id) \
00032   ec[id] += dc[id]; \
00033   while(ec[id] > 0) \
00034   { \
00035     c[id] += ic[id]; \
00036     ec[id] -= dy; \
00037   }
00038 
00039 /* FUNCTIONS ******************************************************************/
00040 
00041 BOOL FASTCALL
00042 IntEngGradientFillRect(
00043     IN SURFOBJ  *psoDest,
00044     IN CLIPOBJ  *pco,
00045     IN XLATEOBJ  *pxlo,
00046     IN TRIVERTEX  *pVertex,
00047     IN ULONG  nVertex,
00048     IN PGRADIENT_RECT gRect,
00049     IN RECTL  *prclExtents,
00050     IN POINTL  *pptlDitherOrg,
00051     IN BOOL Horizontal)
00052 {
00053   SURFOBJ *psoOutput;
00054   TRIVERTEX *v1, *v2;
00055   RECTL rcGradient, rcSG;
00056   RECT_ENUM RectEnum;
00057   BOOL EnumMore;
00058   ULONG i;
00059   POINTL Translate;
00060   INTENG_ENTER_LEAVE EnterLeave;
00061   LONG y, dy, c[3], dc[3], ec[3], ic[3];
00062 
00063   v1 = (pVertex + gRect->UpperLeft);
00064   v2 = (pVertex + gRect->LowerRight);
00065 
00066   rcGradient.left = min(v1->x, v2->x);
00067   rcGradient.right = max(v1->x, v2->x);
00068   rcGradient.top = min(v1->y, v2->y);
00069   rcGradient.bottom = max(v1->y, v2->y);
00070   rcSG = rcGradient;
00071   RECTL_vOffsetRect(&rcSG, pptlDitherOrg->x, pptlDitherOrg->y);
00072 
00073   if(Horizontal)
00074   {
00075     dy = abs(rcGradient.right - rcGradient.left);
00076   }
00077   else
00078   {
00079     dy = abs(rcGradient.bottom - rcGradient.top);
00080   }
00081 
00082   if(!IntEngEnter(&EnterLeave, psoDest, &rcSG, FALSE, &Translate, &psoOutput))
00083   {
00084     return FALSE;
00085   }
00086 
00087   if((v1->Red != v2->Red || v1->Green != v2->Green || v1->Blue != v2->Blue) && dy > 1)
00088   {
00089     CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
00090     do
00091     {
00092       RECTL FillRect;
00093       ULONG Color;
00094 
00095       if(Horizontal)
00096       {
00097         EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
00098         for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++)
00099         {
00100           if(RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG))
00101           {
00102             HVINITCOL(Red, 0);
00103             HVINITCOL(Green, 1);
00104             HVINITCOL(Blue, 2);
00105 
00106             for(y = rcSG.left; y < FillRect.right; y++)
00107             {
00108               if(y >= FillRect.left)
00109               {
00110                 Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2]));
00111                 DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_VLine(
00112                   psoOutput, y + Translate.x, FillRect.top + Translate.y, FillRect.bottom + Translate.y, Color);
00113               }
00114               HVSTEPCOL(0);
00115               HVSTEPCOL(1);
00116               HVSTEPCOL(2);
00117             }
00118           }
00119         }
00120 
00121         continue;
00122       }
00123 
00124       /* vertical */
00125       EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
00126       for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++)
00127       {
00128         if(RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG))
00129         {
00130           HVINITCOL(Red, 0);
00131           HVINITCOL(Green, 1);
00132           HVINITCOL(Blue, 2);
00133 
00134           for(y = rcSG.top; y < FillRect.bottom; y++)
00135           {
00136             if(y >= FillRect.top)
00137             {
00138               Color = XLATEOBJ_iXlate(pxlo, RGB(c[0], c[1], c[2]));
00139               DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(
00140                 psoOutput, FillRect.left + Translate.x, FillRect.right + Translate.x, y + Translate.y, Color);
00141             }
00142             HVSTEPCOL(0);
00143             HVSTEPCOL(1);
00144             HVSTEPCOL(2);
00145           }
00146         }
00147       }
00148 
00149     } while(EnumMore);
00150 
00151     return IntEngLeave(&EnterLeave);
00152   }
00153 
00154   /* rectangle has only one color, no calculation required */
00155   CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
00156   do
00157   {
00158     RECTL FillRect;
00159     ULONG Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red, v1->Green, v1->Blue));
00160 
00161     EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
00162     for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= rcSG.bottom; i++)
00163     {
00164       if(RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], &rcSG))
00165       {
00166         for(; FillRect.top < FillRect.bottom; FillRect.top++)
00167         {
00168           DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(
00169             psoOutput, FillRect.left + Translate.x, FillRect.right + Translate.x, FillRect.top + Translate.y, Color);
00170         }
00171       }
00172     }
00173   } while(EnumMore);
00174 
00175   return IntEngLeave(&EnterLeave);
00176 }
00177 
00178 /* Fill triangle with solid color */
00179 #define S_FILLLINE(linefrom,lineto) \
00180   if(sx[lineto] < sx[linefrom]) \
00181     DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput, max(sx[lineto], FillRect.left), min(sx[linefrom], FillRect.right), sy, Color); \
00182   else \
00183     DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_HLine(psoOutput, max(sx[linefrom], FillRect.left), min(sx[lineto], FillRect.right), sy, Color);
00184 #define S_DOLINE(a,b,line) \
00185   ex[line] += dx[line]; \
00186   while(ex[line] > 0 && x[line] != destx[line]) \
00187   { \
00188     x[line] += incx[line]; \
00189     sx[line] += incx[line]; \
00190     ex[line] -= dy[line]; \
00191   }
00192 #define S_GOLINE(a,b,line) \
00193   if(y >= a->y && y <= b->y) \
00194   {
00195 #define S_ENDLINE(a,b,line) \
00196   }
00197 #define S_INITLINE(a,b,line) \
00198   x[line] = a->x; \
00199   sx[line] =  a->x + pptlDitherOrg->x; \
00200   dx[line] = abs(b->x - a->x); \
00201   dy[line] = abs(b->y - a->y); \
00202   incx[line] = LINC[b->x > a->x]; \
00203   ex[line] = -(dy[line]>>1); \
00204   destx[line] = b->x
00205 
00206 /* Fill triangle with gradient */
00207 #define INITCOL(a,b,line,col,id) \
00208   c[line][id] = a->col >> 8; \
00209   dc[line][id] = abs((b->col >> 8) - c[line][id]); \
00210   ec[line][id] = -(dy[line]>>1); \
00211   ic[line][id] = LINC[(b->col >> 8) > c[line][id]]
00212 #define STEPCOL(a,b,line,col,id) \
00213   ec[line][id] += dc[line][id]; \
00214   while(ec[line][id] > 0) \
00215   { \
00216     c[line][id] += ic[line][id]; \
00217     ec[line][id] -= dy[line]; \
00218   }
00219 #define FINITCOL(linefrom,lineto,colid) \
00220   gc[colid] = c[linefrom][colid]; \
00221   gd[colid] = abs(c[lineto][colid] - gc[colid]); \
00222   ge[colid] = -(gx >> 1); \
00223   gi[colid] = LINC[c[lineto][colid] > gc[colid]]
00224 #define FDOCOL(linefrom,lineto,colid) \
00225   ge[colid] += gd[colid]; \
00226   while(ge[colid] > 0) \
00227   { \
00228     gc[colid] += gi[colid]; \
00229     ge[colid] -= gx; \
00230   }
00231 #define FILLLINE(linefrom,lineto) \
00232   gx = abs(sx[lineto] - sx[linefrom]); \
00233   gxi = LINC[sx[linefrom] < sx[lineto]]; \
00234   FINITCOL(linefrom, lineto, 0); \
00235   FINITCOL(linefrom, lineto, 1); \
00236   FINITCOL(linefrom, lineto, 2); \
00237   for(g = sx[linefrom]; g != sx[lineto]; g += gxi) \
00238   { \
00239     if(InY && g >= FillRect.left && g < FillRect.right) \
00240     { \
00241       Color = XLATEOBJ_iXlate(pxlo, RGB(gc[0], gc[1], gc[2])); \
00242       DibFunctionsForBitmapFormat[psoOutput->iBitmapFormat].DIB_PutPixel(psoOutput, g, sy, Color); \
00243     } \
00244     FDOCOL(linefrom, lineto, 0); \
00245     FDOCOL(linefrom, lineto, 1); \
00246     FDOCOL(linefrom, lineto, 2); \
00247   }
00248 #define DOLINE(a,b,line) \
00249   STEPCOL(a, b, line, Red, 0); \
00250   STEPCOL(a, b, line, Green, 1); \
00251   STEPCOL(a, b, line, Blue, 2); \
00252   ex[line] += dx[line]; \
00253   while(ex[line] > 0 && x[line] != destx[line]) \
00254   { \
00255     x[line] += incx[line]; \
00256     sx[line] += incx[line]; \
00257     ex[line] -= dy[line]; \
00258   }
00259 #define GOLINE(a,b,line) \
00260   if(y >= a->y && y <= b->y) \
00261   {
00262 #define ENDLINE(a,b,line) \
00263   }
00264 #define INITLINE(a,b,line) \
00265   x[line] = a->x; \
00266   sx[line] =  a->x + pptlDitherOrg->x; \
00267   dx[line] = abs(b->x - a->x); \
00268   dy[line] = abs(b->y - a->y); \
00269   incx[line] = LINC[b->x > a->x]; \
00270   ex[line] = -(dy[line]>>1); \
00271   destx[line] = b->x
00272 #define DOINIT(a, b, line) \
00273   INITLINE(a, b, line); \
00274   INITCOL(a, b, line, Red, 0); \
00275   INITCOL(a, b, line, Green, 1); \
00276   INITCOL(a, b, line, Blue, 2);
00277 #define SMALLER(a,b)     (a->y < b->y) || (a->y == b->y && a->x < b->x)
00278 #define SWAP(a,b,c)  c = a;\
00279                      a = b;\
00280                      b = c
00281 #define NLINES 3
00282 BOOL FASTCALL
00283 IntEngGradientFillTriangle(
00284     IN SURFOBJ  *psoDest,
00285     IN CLIPOBJ  *pco,
00286     IN XLATEOBJ  *pxlo,
00287     IN TRIVERTEX  *pVertex,
00288     IN ULONG  nVertex,
00289     IN PGRADIENT_TRIANGLE gTriangle,
00290     IN RECTL  *prclExtents,
00291     IN POINTL  *pptlDitherOrg)
00292 {
00293   SURFOBJ *psoOutput;
00294   PTRIVERTEX v1, v2, v3;
00295   //RECT_ENUM RectEnum;
00296   //BOOL EnumMore;
00297   //ULONG i;
00298   POINTL Translate;
00299   INTENG_ENTER_LEAVE EnterLeave;
00300   RECTL FillRect = { 0, 0, 0, 0 };
00301   //ULONG Color;
00302 
00303   //BOOL sx[NLINES];
00304   //LONG x[NLINES], dx[NLINES], dy[NLINES], incx[NLINES], ex[NLINES], destx[NLINES];
00305   //LONG c[NLINES][3], dc[NLINES][3], ec[NLINES][3], ic[NLINES][3]; /* colors on lines */
00306   //LONG g, gx, gxi, gc[3], gd[3], ge[3], gi[3]; /* colors in triangle */
00307   //LONG sy, y, bt;
00308 
00309   v1 = (pVertex + gTriangle->Vertex1);
00310   v2 = (pVertex + gTriangle->Vertex2);
00311   v3 = (pVertex + gTriangle->Vertex3);
00312 
00313   /* bubble sort */
00314   if(SMALLER(v2,v1))
00315   {
00316     TRIVERTEX *t;
00317     SWAP(v1,v2,t);
00318   }
00319   if(SMALLER(v3,v2))
00320   {
00321     TRIVERTEX *t;
00322     SWAP(v2,v3,t);
00323     if(SMALLER(v2,v1))
00324     {
00325       SWAP(v1,v2,t);
00326     }
00327   }
00328 
00329   DPRINT1("Triangle: (%i,%i) (%i,%i) (%i,%i)\n", v1->x, v1->y, v2->x, v2->y, v3->x, v3->y);
00330   /* FIXME: commented out because of an endless loop - fix triangles first */
00331   DPRINT1("FIXME: IntEngGradientFillTriangle is broken\n");
00332 
00333   if(!IntEngEnter(&EnterLeave, psoDest, &FillRect, FALSE, &Translate, &psoOutput))
00334   {
00335     return FALSE;
00336   }
00337 
00338   //if(VCMPCLRS(v1, v2, v3))
00339   //{
00340   //  CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
00341   //  do
00342   //  {
00343   //    EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
00344   //    for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= prclExtents->bottom; i++)
00345   //    {
00346   //      if(RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], prclExtents))
00347   //      {
00348   //        BOOL InY;
00349 
00350   //        DOINIT(v1, v3, 0);
00351   //        DOINIT(v1, v2, 1);
00352   //        DOINIT(v2, v3, 2);
00353 
00354   //        y = v1->y;
00355   //        sy = v1->y + pptlDitherOrg->y;
00356   //        bt = min(v3->y + pptlDitherOrg->y, FillRect.bottom);
00357 
00358   //        while(sy < bt)
00359   //        {
00360   //          InY = !(sy < FillRect.top || sy >= FillRect.bottom);
00361   //          GOLINE(v1, v3, 0);
00362   //          DOLINE(v1, v3, 0);
00363   //          ENDLINE(v1, v3, 0);
00364 
00365   //          GOLINE(v1, v2, 1);
00366   //          DOLINE(v1, v2, 1);
00367   //          FILLLINE(0, 1);
00368   //          ENDLINE(v1, v2, 1);
00369 
00370   //          GOLINE(v2, v3, 2);
00371   //          DOLINE(v2, v3, 2);
00372   //          FILLLINE(0, 2);
00373   //          ENDLINE(23, v3, 2);
00374 
00375   //          y++;
00376   //          sy++;
00377   //        }
00378   //      }
00379   //    }
00380   //  } while(EnumMore);
00381 
00382   //  return IntEngLeave(&EnterLeave);
00383   //}
00384 
00386 
00387   //Color = XLATEOBJ_iXlate(pxlo, RGB(v1->Red >> 8, v1->Green >> 8, v1->Blue >> 8));
00388   //CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
00389   //do
00390   //{
00391   //  EnumMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
00392   //  for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= prclExtents->bottom; i++)
00393   //  {
00394   //    if(RECTL_bIntersectRect(&FillRect, &RectEnum.arcl[i], prclExtents))
00395   //    {
00396   //      S_INITLINE(v1, v3, 0);
00397   //      S_INITLINE(v1, v2, 1);
00398   //      S_INITLINE(v2, v3, 2);
00399 
00400   //      y = v1->y;
00401   //      sy = v1->y + pptlDitherOrg->y;
00402   //      bt = min(v3->y + pptlDitherOrg->y, FillRect.bottom);
00403 
00404   //      while(sy < bt)
00405   //      {
00406   //        S_GOLINE(v1, v3, 0);
00407   //        S_DOLINE(v1, v3, 0);
00408   //        S_ENDLINE(v1, v3, 0);
00409 
00410   //        S_GOLINE(v1, v2, 1);
00411   //        S_DOLINE(v1, v2, 1);
00412   //        S_FILLLINE(0, 1);
00413   //        S_ENDLINE(v1, v2, 1);
00414 
00415   //        S_GOLINE(v2, v3, 2);
00416   //        S_DOLINE(v2, v3, 2);
00417   //        S_FILLLINE(0, 2);
00418   //        S_ENDLINE(23, v3, 2);
00419 
00420   //        y++;
00421   //        sy++;
00422   //      }
00423   //    }
00424   //  }
00425   //} while(EnumMore);
00426 
00427   return IntEngLeave(&EnterLeave);
00428 }
00429 
00430 
00431 static BOOL
00432 IntEngIsNULLTriangle(TRIVERTEX  *pVertex, GRADIENT_TRIANGLE *gt)
00433 {
00434   if(COMPAREVERTEX(VERTEX(Vertex1), VERTEX(Vertex2)))
00435     return TRUE;
00436   if(COMPAREVERTEX(VERTEX(Vertex1), VERTEX(Vertex3)))
00437     return TRUE;
00438   if(COMPAREVERTEX(VERTEX(Vertex2), VERTEX(Vertex3)))
00439     return TRUE;
00440   return FALSE;
00441 }
00442 
00443 
00444 BOOL APIENTRY
00445 EngGradientFill(
00446     IN SURFOBJ  *psoDest,
00447     IN CLIPOBJ  *pco,
00448     IN XLATEOBJ  *pxlo,
00449     IN TRIVERTEX  *pVertex,
00450     IN ULONG  nVertex,
00451     IN PVOID  pMesh,
00452     IN ULONG  nMesh,
00453     IN RECTL  *prclExtents,
00454     IN POINTL  *pptlDitherOrg,
00455     IN ULONG  ulMode)
00456 {
00457   ULONG i;
00458   BOOL ret = FALSE;
00459 
00460   if (!pco)
00461   {
00462     pco = IntEngCreateClipRegion(0, 0, prclExtents);
00463     if (!pco)
00464     {
00465       return FALSE;
00466     }
00467   }
00468 
00469   switch(ulMode)
00470   {
00471     case GRADIENT_FILL_RECT_H:
00472     case GRADIENT_FILL_RECT_V:
00473     {
00474       PGRADIENT_RECT gr = (PGRADIENT_RECT)pMesh;
00475       for(i = 0; i < nMesh; i++, gr++)
00476       {
00477         if(!IntEngGradientFillRect(psoDest, pco, pxlo, pVertex, nVertex, gr, prclExtents,
00478                                    pptlDitherOrg, (ulMode == GRADIENT_FILL_RECT_H)))
00479         {
00480           break;
00481         }
00482       }
00483       ret = TRUE;
00484       break;
00485     }
00486     case GRADIENT_FILL_TRIANGLE:
00487     {
00488       PGRADIENT_TRIANGLE gt = (PGRADIENT_TRIANGLE)pMesh;
00489       for(i = 0; i < nMesh; i++, gt++)
00490       {
00491         if(IntEngIsNULLTriangle(pVertex, gt))
00492         {
00493           /* skip empty triangles */
00494           continue;
00495         }
00496         if(!IntEngGradientFillTriangle(psoDest, pco, pxlo, pVertex, nVertex, gt, prclExtents,
00497                                        pptlDitherOrg))
00498         {
00499           break;
00500         }
00501       }
00502       ret = TRUE;
00503       break;
00504     }
00505   }
00506 
00507   return ret;
00508 }
00509 
00510 BOOL APIENTRY
00511 IntEngGradientFill(
00512     IN SURFOBJ  *psoDest,
00513     IN CLIPOBJ  *pco,
00514     IN XLATEOBJ  *pxlo,
00515     IN TRIVERTEX  *pVertex,
00516     IN ULONG  nVertex,
00517     IN PVOID  pMesh,
00518     IN ULONG  nMesh,
00519     IN RECTL  *prclExtents,
00520     IN POINTL  *pptlDitherOrg,
00521     IN ULONG  ulMode)
00522 {
00523   BOOL Ret;
00524   SURFACE *psurf;
00525   ASSERT(psoDest);
00526 
00527   psurf = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
00528   ASSERT(psurf);
00529 
00530   if(psurf->flags & HOOK_GRADIENTFILL)
00531   {
00532     Ret = GDIDEVFUNCS(psoDest).GradientFill(
00533       psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh,
00534       prclExtents, pptlDitherOrg, ulMode);
00535   }
00536   else
00537   {
00538     Ret = EngGradientFill(psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh, prclExtents,
00539                           pptlDitherOrg, ulMode);
00540   }
00541 
00542   return Ret;
00543 }

Generated on Sun May 27 2012 04:38:20 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.