New implementation of GdiGradientFill using integer math.
This commit is contained in:
parent
0d0a4075bd
commit
e2607505db
|
@ -1072,190 +1072,120 @@ POINT *GDI_Bezier( const POINT *Points, INT count, INT *nPtsOut )
|
||||||
BOOL WINAPI GdiGradientFill( HDC hdc, TRIVERTEX *vert_array, ULONG nvert,
|
BOOL WINAPI GdiGradientFill( HDC hdc, TRIVERTEX *vert_array, ULONG nvert,
|
||||||
void * grad_array, ULONG ngrad, ULONG mode )
|
void * grad_array, ULONG ngrad, ULONG mode )
|
||||||
{
|
{
|
||||||
int i,j,y,x,t;
|
int i;
|
||||||
GRADIENT_RECT *rect;
|
|
||||||
GRADIENT_TRIANGLE *triangle;
|
|
||||||
double ired,igreen,iblue;
|
|
||||||
double red, green,blue;
|
|
||||||
double dx1,dx2,dx3;
|
|
||||||
double dr1,dr2,dr3;
|
|
||||||
double dg1,dg2,dg3;
|
|
||||||
double db1,db2,db3;
|
|
||||||
double sx,sy,sr,sg,sb;
|
|
||||||
double ex,ey,er,eb,eg;
|
|
||||||
double px,py,pr,pb,pg;
|
|
||||||
|
|
||||||
TRACE("vert_array:0x%08lx nvert:%ld grad_array:0x%08lx ngrad:%ld\n",(long)vert_array,nvert,(long)grad_array,ngrad);
|
TRACE("vert_array:0x%08lx nvert:%ld grad_array:0x%08lx ngrad:%ld\n",
|
||||||
|
(long)vert_array, nvert, (long)grad_array, ngrad);
|
||||||
|
|
||||||
switch(mode) {
|
switch(mode)
|
||||||
|
{
|
||||||
case GRADIENT_FILL_RECT_H:
|
case GRADIENT_FILL_RECT_H:
|
||||||
for(i=0;i<ngrad;i++) {
|
for(i = 0; i < ngrad; i++)
|
||||||
rect = (GRADIENT_RECT*)((long)grad_array+i*sizeof(GRADIENT_RECT));
|
{
|
||||||
y = vert_array[rect->UpperLeft].y;
|
GRADIENT_RECT *rect = ((GRADIENT_RECT *)grad_array) + i;
|
||||||
/* Precompute some stuffs to speed up a little bit */
|
TRIVERTEX *v1 = vert_array + rect->UpperLeft;
|
||||||
ired = (double)(vert_array[rect->LowerRight].Red - vert_array[rect->UpperLeft].Red) / (double)(vert_array[rect->LowerRight].x - vert_array[rect->UpperLeft].x);
|
TRIVERTEX *v2 = vert_array + rect->LowerRight;
|
||||||
igreen = (double)(vert_array[rect->LowerRight].Green - vert_array[rect->UpperLeft].Green) / (double)(vert_array[rect->LowerRight].x - vert_array[rect->UpperLeft].x);
|
int y1 = v1->y < v2->y ? v1->y : v2->y;
|
||||||
iblue = (double)(vert_array[rect->LowerRight].Blue - vert_array[rect->UpperLeft].Blue) / (double)(vert_array[rect->LowerRight].x - vert_array[rect->UpperLeft].x);
|
int y2 = v2->y > v1->y ? v2->y : v1->y;
|
||||||
red = vert_array[rect->UpperLeft].Red;
|
int x, y, dx;
|
||||||
green = vert_array[rect->UpperLeft].Green;
|
if (v1->x > v2->x)
|
||||||
blue = vert_array[rect->UpperLeft].Blue;
|
{
|
||||||
/* Draw the first line */
|
TRIVERTEX *t = v2;
|
||||||
for (j=vert_array[rect->UpperLeft].x; j<=vert_array[rect->LowerRight].x; j++) {
|
v2 = v1;
|
||||||
SetPixel(hdc,j,y,RGB(((int)red)>>8,((int)green)>>8,((int)blue)>>8));
|
v1 = t;
|
||||||
red += ired;
|
}
|
||||||
green += igreen;
|
dx = v2->x - v1->x;
|
||||||
blue += iblue;
|
for (x = 0; x < dx; x++)
|
||||||
|
{
|
||||||
|
for (y = y1; y < y2; y++)
|
||||||
|
SetPixel (hdc, x + v1->x, y, RGB(
|
||||||
|
(v1->Red * (dx - x) + v2->Red * x) / dx >> 8,
|
||||||
|
(v1->Green * (dx - x) + v2->Green * x) / dx >> 8,
|
||||||
|
(v1->Blue * (dx - x) + v2->Blue * x) / dx >> 8));
|
||||||
}
|
}
|
||||||
/* Extends to the correct size */
|
|
||||||
StretchBlt(hdc,vert_array[rect->UpperLeft].x, y+1,(vert_array[rect->LowerRight].x - vert_array[rect->UpperLeft].x), (vert_array[rect->LowerRight].y - y - 1),
|
|
||||||
hdc,vert_array[rect->UpperLeft].x, y , (vert_array[rect->LowerRight].x - vert_array[rect->UpperLeft].x), 1, SRCCOPY);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GRADIENT_FILL_RECT_V:
|
case GRADIENT_FILL_RECT_V:
|
||||||
for(i=0;i<ngrad;i++) {
|
for(i = 0; i < ngrad; i++)
|
||||||
rect = (GRADIENT_RECT*)((long)grad_array+i*sizeof(GRADIENT_RECT));
|
{
|
||||||
x = vert_array[rect->UpperLeft].x;
|
GRADIENT_RECT *rect = ((GRADIENT_RECT *)grad_array) + i;
|
||||||
/* Precompute some stuffs to speed up a little bit */
|
TRIVERTEX *v1 = vert_array + rect->UpperLeft;
|
||||||
ired = (double)(vert_array[rect->LowerRight].Red - vert_array[rect->UpperLeft].Red) / (double)(vert_array[rect->LowerRight].y - vert_array[rect->UpperLeft].y);
|
TRIVERTEX *v2 = vert_array + rect->LowerRight;
|
||||||
igreen = (double)(vert_array[rect->LowerRight].Green - vert_array[rect->UpperLeft].Green) / (double)(vert_array[rect->LowerRight].y - vert_array[rect->UpperLeft].y);
|
int x1 = v1->x < v2->x ? v1->x : v2->x;
|
||||||
iblue = (double)(vert_array[rect->LowerRight].Blue - vert_array[rect->UpperLeft].Blue) / (double)(vert_array[rect->LowerRight].y - vert_array[rect->UpperLeft].y);
|
int x2 = v2->x > v1->x ? v2->x : v1->x;
|
||||||
red = vert_array[rect->UpperLeft].Red;
|
int x, y, dy;
|
||||||
green = vert_array[rect->UpperLeft].Green;
|
if (v1->y > v2->y)
|
||||||
blue = vert_array[rect->UpperLeft].Blue;
|
{
|
||||||
/* Draw the first line */
|
TRIVERTEX *t = v2;
|
||||||
for (j=vert_array[rect->UpperLeft].y; j<=vert_array[rect->LowerRight].y; j++) {
|
v2 = v1;
|
||||||
SetPixel(hdc,x,j,RGB(((int)red)>>8,((int)green)>>8,((int)blue)>>8));
|
v1 = t;
|
||||||
red += ired;
|
}
|
||||||
green += igreen;
|
dy = v2->y - v1->y;
|
||||||
blue += iblue;
|
for (y = 0; y < dy; y++)
|
||||||
|
{
|
||||||
|
for (x = x1; x < x2; x++)
|
||||||
|
SetPixel (hdc, x, y + v1->y, RGB(
|
||||||
|
(v1->Red * (dy - y) + v2->Red * y) / dy >> 8,
|
||||||
|
(v1->Green * (dy - y) + v2->Green * y) / dy >> 8,
|
||||||
|
(v1->Blue * (dy - y) + v2->Blue * y) / dy >> 8));
|
||||||
}
|
}
|
||||||
/* Extends to the correct size */
|
|
||||||
StretchBlt(hdc,x+1,vert_array[rect->UpperLeft].y,
|
|
||||||
(vert_array[rect->LowerRight].x - vert_array[rect->UpperLeft].x) - 1, (vert_array[rect->LowerRight].y - vert_array[rect->UpperLeft].y),
|
|
||||||
hdc, x, vert_array[rect->UpperLeft].y, 1, (vert_array[rect->LowerRight].y - vert_array[rect->UpperLeft].y), SRCCOPY);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GRADIENT_FILL_TRIANGLE:
|
case GRADIENT_FILL_TRIANGLE:
|
||||||
/*
|
for (i = 0; i < ngrad; i++)
|
||||||
* Based on gouraud shading
|
{
|
||||||
* Do it for each triangle
|
GRADIENT_TRIANGLE *tri = ((GRADIENT_TRIANGLE *)grad_array) + i;
|
||||||
*/
|
TRIVERTEX *v1 = vert_array + tri->Vertex1;
|
||||||
for(i=0;i<ngrad;i++) {
|
TRIVERTEX *v2 = vert_array + tri->Vertex2;
|
||||||
triangle = (GRADIENT_TRIANGLE*)((long)grad_array+i*sizeof(GRADIENT_TRIANGLE));
|
TRIVERTEX *v3 = vert_array + tri->Vertex3;
|
||||||
/* Sort the points */
|
int y, dy;
|
||||||
if (vert_array[triangle->Vertex1].y>vert_array[triangle->Vertex2].y) {
|
|
||||||
/* swap 1 and 2 */
|
|
||||||
t = triangle->Vertex2;
|
|
||||||
triangle->Vertex2 = triangle->Vertex1;
|
|
||||||
triangle->Vertex1 = t;
|
|
||||||
}
|
|
||||||
if (vert_array[triangle->Vertex2].y>vert_array[triangle->Vertex3].y) {
|
|
||||||
/* swap 2 and 3 */
|
|
||||||
t = triangle->Vertex3;
|
|
||||||
triangle->Vertex3 = triangle->Vertex2;
|
|
||||||
triangle->Vertex2 = t;
|
|
||||||
}
|
|
||||||
if (vert_array[triangle->Vertex1].y>vert_array[triangle->Vertex2].y) {
|
|
||||||
/* swap 1 and 2 */
|
|
||||||
t = triangle->Vertex2;
|
|
||||||
triangle->Vertex2 = triangle->Vertex1;
|
|
||||||
triangle->Vertex1 = t;
|
|
||||||
}
|
|
||||||
/* precompute some interpolation stuffs */
|
|
||||||
if (vert_array[triangle->Vertex2].y>vert_array[triangle->Vertex1].y) {
|
|
||||||
dx1 = (double)(vert_array[triangle->Vertex2].x - vert_array[triangle->Vertex1].x) / (double)(vert_array[triangle->Vertex2].y - vert_array[triangle->Vertex1].y );
|
|
||||||
dr1 = (double)(vert_array[triangle->Vertex2].Red - vert_array[triangle->Vertex1].Red) / (double)(vert_array[triangle->Vertex2].y - vert_array[triangle->Vertex1].y );
|
|
||||||
dg1 = (double)(vert_array[triangle->Vertex2].Green - vert_array[triangle->Vertex1].Green) / (double)(vert_array[triangle->Vertex2].y - vert_array[triangle->Vertex1].y );
|
|
||||||
db1 = (double)(vert_array[triangle->Vertex2].Blue - vert_array[triangle->Vertex1].Blue) / (double)(vert_array[triangle->Vertex2].y - vert_array[triangle->Vertex1].y );
|
|
||||||
} else
|
|
||||||
dx1=dr1=dg1=db1=0;
|
|
||||||
|
|
||||||
if (vert_array[triangle->Vertex3].y>vert_array[triangle->Vertex1].y) {
|
if (v1->y > v2->y)
|
||||||
dx2 = (double)(vert_array[triangle->Vertex3].x - vert_array[triangle->Vertex1].x) / (double)(vert_array[triangle->Vertex3].y - vert_array[triangle->Vertex1].y );
|
{ TRIVERTEX *t = v1; v1 = v2; v2 = t; }
|
||||||
dr2 = (double)(vert_array[triangle->Vertex3].Red - vert_array[triangle->Vertex1].Red) / (double)(vert_array[triangle->Vertex3].y - vert_array[triangle->Vertex1].y );
|
if (v2->y > v3->y)
|
||||||
dg2 = (double)(vert_array[triangle->Vertex3].Green - vert_array[triangle->Vertex1].Green) / (double)(vert_array[triangle->Vertex3].y - vert_array[triangle->Vertex1].y );
|
{
|
||||||
db2 = (double)(vert_array[triangle->Vertex3].Blue - vert_array[triangle->Vertex1].Blue) / (double)(vert_array[triangle->Vertex3].y - vert_array[triangle->Vertex1].y );
|
TRIVERTEX *t = v2; v2 = v3; v3 = t;
|
||||||
} else
|
if (v1->y > v2->y)
|
||||||
dx2=dr2=dg2=db2=0;
|
{ t = v1; v1 = v2; v2 = t; }
|
||||||
|
}
|
||||||
|
/* v1->y <= v2->y <= v3->y */
|
||||||
|
|
||||||
if (vert_array[triangle->Vertex3].y>vert_array[triangle->Vertex2].y) {
|
dy = v3->y - v1->y;
|
||||||
dx3 = (double)(vert_array[triangle->Vertex3].x - vert_array[triangle->Vertex2].x) / (double)(vert_array[triangle->Vertex3].y - vert_array[triangle->Vertex2].y );
|
for (y = 0; y < dy; y++)
|
||||||
dr3 = (double)(vert_array[triangle->Vertex3].Red - vert_array[triangle->Vertex2].Red) / (double)(vert_array[triangle->Vertex3].y - vert_array[triangle->Vertex2].y );
|
{
|
||||||
dg3 = (double)(vert_array[triangle->Vertex3].Green - vert_array[triangle->Vertex2].Green) / (double)(vert_array[triangle->Vertex3].y - vert_array[triangle->Vertex2].y );
|
/* v1->y <= y < v3->y */
|
||||||
db3 = (double)(vert_array[triangle->Vertex3].Blue - vert_array[triangle->Vertex2].Blue) / (double)(vert_array[triangle->Vertex3].y - vert_array[triangle->Vertex2].y );
|
TRIVERTEX *v = y < (v2->y - v1->y) ? v1 : v3;
|
||||||
} else
|
/* (v->y <= y < v2->y) || (v2->y <= y < v->y) */
|
||||||
dx3=dr3=dg3=db3=0;
|
int dy2 = v2->y - v->y;
|
||||||
|
int y2 = y + v1->y - v->y;
|
||||||
|
|
||||||
/* backup the topmost point */
|
int x1 = (v3->x * y + v1->x * (dy - y )) / dy;
|
||||||
sx=vert_array[triangle->Vertex1].x;sy=vert_array[triangle->Vertex1].y;
|
int x2 = (v2->x * y2 + v-> x * (dy2 - y2)) / dy2;
|
||||||
sr=vert_array[triangle->Vertex1].Red;sg=vert_array[triangle->Vertex1].Green;sb=vert_array[triangle->Vertex1].Blue;
|
int r1 = (v3->Red * y + v1->Red * (dy - y )) / dy;
|
||||||
ex=sx;ey=sy;er=sr;eg=sg;eb=sb;
|
int r2 = (v2->Red * y2 + v-> Red * (dy2 - y2)) / dy2;
|
||||||
|
int g1 = (v3->Green * y + v1->Green * (dy - y )) / dy;
|
||||||
|
int g2 = (v2->Green * y2 + v-> Green * (dy2 - y2)) / dy2;
|
||||||
|
int b1 = (v3->Blue * y + v1->Blue * (dy - y )) / dy;
|
||||||
|
int b2 = (v2->Blue * y2 + v-> Blue * (dy2 - y2)) / dy2;
|
||||||
|
|
||||||
if (dx1 > dx2) {
|
int x;
|
||||||
for (;sy<vert_array[triangle->Vertex2].y;sy++,ey++) {
|
if (x1 < x2)
|
||||||
if ((ex-sx)>0) {
|
{
|
||||||
ired = (double)(er - sr) / (double)(ex - sx);
|
int dx = x2 - x1;
|
||||||
igreen = (double)(eg - sg) / (double)(ex - sx);
|
for (x = 0; x < dx; x++)
|
||||||
iblue = (double)(eb - sb) / (double)(ex - sx);
|
SetPixel (hdc, x + x1, y + v1->y, RGB(
|
||||||
} else
|
(r1 * (dx - x) + r2 * x) / dx >> 8,
|
||||||
ired=igreen=iblue=0;
|
(g1 * (dx - x) + g2 * x) / dx >> 8,
|
||||||
px=sx;py=sy;pr=sr;pg=sg;pb=sb;
|
(b1 * (dx - x) + b2 * x) / dx >> 8));
|
||||||
for(;px<ex;px++) {
|
|
||||||
SetPixel(hdc,px,py,RGB((int)pr>>8,(int)pg>>8,(int)pb>>8));
|
|
||||||
pr += ired; pg += igreen; pb += iblue;
|
|
||||||
}
|
}
|
||||||
sx+=dx2;sr+=dr2;sg+=dg2;sb+=db2;
|
else
|
||||||
ex+=dx1;er+=dr1;eg+=dg1;eb+=db1;
|
{
|
||||||
}
|
int dx = x1 - x2;
|
||||||
ex=vert_array[triangle->Vertex2].x;ey=vert_array[triangle->Vertex2].y;
|
for (x = 0; x < dx; x++)
|
||||||
er=vert_array[triangle->Vertex2].Red;eg=vert_array[triangle->Vertex2].Green;eb=vert_array[triangle->Vertex2].Blue;
|
SetPixel (hdc, x + x2, y + v1->y, RGB(
|
||||||
for (;sy<=vert_array[triangle->Vertex3].y;sy++,ey++) {
|
(r2 * (dx - x) + r1 * x) / dx >> 8,
|
||||||
if ((ex-sx)>0) {
|
(g2 * (dx - x) + g1 * x) / dx >> 8,
|
||||||
ired = (double)(er - sr) / (double)(ex - sx);
|
(b2 * (dx - x) + b1 * x) / dx >> 8));
|
||||||
igreen = (double)(eg - sg) / (double)(ex - sx);
|
|
||||||
iblue = (double)(eb - sb) / (double)(ex - sx);
|
|
||||||
} else
|
|
||||||
ired=igreen=iblue=0;
|
|
||||||
px=sx;py=sy;pr=sr;pg=sg;pb=sb;
|
|
||||||
for(;px<ex;px++) {
|
|
||||||
SetPixel(hdc,px,py,RGB((int)pr>>8,(int)pg>>8,(int)pb>>8));
|
|
||||||
pr += ired; pg += igreen; pb += iblue;
|
|
||||||
}
|
|
||||||
sx+=dx2;sr+=dr2;sg+=dg2;sb+=db2;
|
|
||||||
ex+=dx3;er+=dr3;eg+=dg3;eb+=db3;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (;sy<vert_array[triangle->Vertex2].y;sy++,ey++) {
|
|
||||||
if ((ex-sx)>0) {
|
|
||||||
ired = (double)(er - sr) / (double)(ex - sx);
|
|
||||||
igreen = (double)(eg - sg) / (double)(ex - sx);
|
|
||||||
iblue = (double)(eb - sb) / (double)(ex - sx);
|
|
||||||
} else
|
|
||||||
ired=igreen=iblue=0;
|
|
||||||
px=ex;py=ey;pr=er;pg=eg;pb=eb;
|
|
||||||
for(;px<ex;px++) {
|
|
||||||
SetPixel(hdc,px,py,RGB((int)pr>>8,(int)pg>>8,(int)pb>>8));
|
|
||||||
pr += ired; pg += igreen; pb += iblue;
|
|
||||||
}
|
|
||||||
sx+=dx1;sr+=dr1;sg+=dg1;sb+=db1;
|
|
||||||
ex+=dx2;er+=dr2;eg+=dg2;eb+=db2;
|
|
||||||
}
|
|
||||||
sx=vert_array[triangle->Vertex2].x;sy=vert_array[triangle->Vertex2].y;
|
|
||||||
sr=vert_array[triangle->Vertex2].Red;sg=vert_array[triangle->Vertex2].Green;sb=vert_array[triangle->Vertex2].Blue;
|
|
||||||
for (;sy<=vert_array[triangle->Vertex3].y;sy++,ey++) {
|
|
||||||
if ((ex-sx)<0) {
|
|
||||||
ired = (double)(er - sr) / (double)(ex - sx);
|
|
||||||
igreen = (double)(eg - sg) / (double)(ex - sx);
|
|
||||||
iblue = (double)(eb - sb) / (double)(ex - sx);
|
|
||||||
} else
|
|
||||||
ired=igreen=iblue=0;
|
|
||||||
px=ex;py=ey;pr=er;pg=eg;pb=eb;
|
|
||||||
for(;px<sx;px++) {
|
|
||||||
SetPixel(hdc,px,py,RGB((int)pr>>8,(int)pg>>8,(int)pb>>8));
|
|
||||||
pr += ired; pg += igreen; pb += iblue;
|
|
||||||
}
|
|
||||||
sx+=dx3;sr+=dr3;sg+=dg3;sb+=db3;
|
|
||||||
ex+=dx2;er+=dr2;eg+=dg2;eb+=db2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue