Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygengradient.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
1.7.6.1
|