Arc, RoundRect:

- Converted over to use the new draw/fill square algorithm for draw arcs and draw/fill round rects.
- Tested with (Area.exe) Yuan program. Getting better.



svn path=/trunk/; revision=34248
This commit is contained in:
James Tabor 2008-07-02 07:47:23 +00:00
parent 2964504432
commit d170af286f
3 changed files with 636 additions and 479 deletions

View file

@ -26,6 +26,7 @@
#define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0))) #define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
BOOL FASTCALL IntFillArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype); BOOL FASTCALL IntFillArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype);
BOOL FASTCALL IntDrawArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype, PGDIBRUSHOBJ PenBrushObj);
static static
BOOL BOOL
@ -147,6 +148,16 @@ IntArc( DC *dc,
arctype); arctype);
} }
ret = IntDrawArc( dc,
RectBounds.left,
RectBounds.top,
abs(RectBounds.right-RectBounds.left), // Width
abs(RectBounds.bottom-RectBounds.top), // Height
AngleStart,
AngleEnd,
arctype,
PenBrushObj);
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap); BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
if (NULL == BitmapObj) if (NULL == BitmapObj)
{ {
@ -161,62 +172,10 @@ IntArc( DC *dc,
if (arctype == GdiTypePie) if (arctype == GdiTypePie)
{ {
PUTLINE(CenterX, CenterY, SfCx + CenterX, SfCy + CenterY, PenBrushInst); PUTLINE(CenterX, CenterY, SfCx + CenterX, SfCy + CenterY, PenBrushInst);
}
{
double AngS = AngleStart, AngT = AngleEnd,
Factor = fabs(RadiusX) < 25 ? 1.0 : (25/fabs(RadiusX));
int x,y, ox = 0, oy = 0;
BOOL Start = TRUE;
if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
{
DPRINT1("Arc CW\n");
for (; AngS < AngT; AngS += Factor)
{
x = (RadiusX * Rcos(AngS));
y = (RadiusY * Rsin(AngS));
DPRINT("Arc CW -> %d, X: %d Y: %d\n",(INT)AngS,x,y);
if (Start)
{
PUTPIXEL(x + CenterX, y + CenterY, PenBrushInst);
ox = x;
oy = y;
Start = FALSE;
continue;
}
PUTLINE(ox + CenterX, oy + CenterY, x + CenterX, y + CenterY, PenBrushInst);
ox = x;
oy = y;
}
}
else
{
DPRINT1("Arc CCW\n");
for (; AngT < AngS; AngS -= Factor)
{
x = (RadiusX * Rcos(AngS));
y = (RadiusY * Rsin(AngS));
DPRINT("Arc CCW -> %d, X: %d Y: %d\n",(INT)AngS,x,y);
if (Start)
{
PUTPIXEL(x + CenterX, y + CenterY, PenBrushInst);
ox = x;
oy = y;
Start = FALSE;
continue;
}
PUTLINE(ox + CenterX, oy + CenterY, x + CenterX, y + CenterY, PenBrushInst);
ox = x;
oy = y;
}
}
}
if (arctype == GdiTypePie)
PUTLINE(EfCx + CenterX, EfCy + CenterY, CenterX, CenterY, PenBrushInst); PUTLINE(EfCx + CenterX, EfCy + CenterY, CenterX, CenterY, PenBrushInst);
}
if (arctype == GdiTypeChord) if (arctype == GdiTypeChord)
PUTLINE(EfCx + CenterX, EfCy + CenterY, SfCx + CenterX, SfCy + CenterY, PenBrushInst); PUTLINE(EfCx + CenterX, EfCy + CenterY, SfCx + CenterX, SfCy + CenterY, PenBrushInst);
PenBrushObj->ptPenWidth.x = PenOrigWidth; PenBrushObj->ptPenWidth.x = PenOrigWidth;
BITMAPOBJ_UnlockBitmap(BitmapObj); BITMAPOBJ_UnlockBitmap(BitmapObj);

View file

@ -63,6 +63,9 @@ typedef struct _Rect
int width, height; /* width and height of rect */ int width, height; /* width and height of rect */
} Rect, *PRect; } Rect, *PRect;
int FASTCALL IntFillRect(DC *dc, INT XLeft, INT YLeft, INT Width, INT Height, PGDIBRUSHOBJ BrushObj, BOOL Pen);
int FASTCALL app_fill_rect(DC *dc, Rect r, PGDIBRUSHOBJ BrushObj, BOOL Pen);
static static
POINT POINT
INTERNAL_CALL INTERNAL_CALL
@ -101,152 +104,8 @@ rect(int x, int y, int width, int height)
* is no way for the program to know which portions of the * is no way for the program to know which portions of the
* window are currently obscured. * window are currently obscured.
*/ */
static #define app_fill_rect( dc, r, BrushObj, Pen) \
int IntFillRect(dc, r.x, r.y, r.width, r.height, BrushObj, Pen)
INTERNAL_CALL
app_fill_rect(DC *dc, Rect r, PGDIBRUSHOBJ BrushObj)
{
DWORD ROP = PATCOPY;
RECTL DestRect;
BITMAPOBJ *BitmapObj;
GDIBRUSHINST BrushInst;
POINTL BrushOrigin;
BOOL Ret = TRUE;
PDC_ATTR Dc_Attr = NULL;
ASSERT(BrushObj);
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
if (BitmapObj == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
if (!(BrushObj->flAttrs & GDIBRUSH_IS_NULL))
{
Dc_Attr = dc->pDc_Attr;
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
/* fix negative spaces */
if (r.width < 0)
{
r.x += r.width;
r.width = 0 - r.width;
}
if (r.height < 0)
{
r.y += r.height;
r.height = 0 - r.height;
}
DestRect.left = r.x;
DestRect.right = r.x + r.width;
DestRect.top = r.y;
DestRect.bottom = r.y + r.height;
BrushOrigin.x = BrushObj->ptOrigin.x;
BrushOrigin.y = BrushObj->ptOrigin.y;
if (Dc_Attr->jROP2 == R2_XORPEN)
ROP = PATINVERT;
else
ROP = PATCOPY;
IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlateBrush);
Ret = IntEngBitBlt(
&BitmapObj->SurfObj,
NULL,
NULL,
dc->CombinedClip,
NULL,
&DestRect,
NULL,
NULL,
&BrushInst.BrushObject, // use pDC->eboFill
&BrushOrigin,
ROP3_TO_ROP4(ROP));
}
BITMAPOBJ_UnlockBitmap(BitmapObj);
return (int)Ret;
}
static
int
INTERNAL_CALL
app_fill_rect_pen(DC *dc, Rect r, PGDIBRUSHOBJ BrushObj)
{
DWORD ROP = PATCOPY;
RECTL DestRect;
BITMAPOBJ *BitmapObj;
GDIBRUSHINST BrushInst;
POINTL BrushOrigin;
BOOL Ret = TRUE;
PDC_ATTR Dc_Attr = NULL;
ASSERT(BrushObj);
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
if (BitmapObj == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
if (!(BrushObj->flAttrs & GDIBRUSH_IS_NULL))
{
Dc_Attr = dc->pDc_Attr;
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
/* fix negative spaces */
if (r.width < 0)
{
r.x += r.width;
r.width = 0 - r.width;
}
if (r.height < 0)
{
r.y += r.height;
r.height = 0 - r.height;
}
DestRect.left = r.x;
DestRect.right = r.x + r.width;
DestRect.top = r.y;
DestRect.bottom = r.y + r.height;
BrushOrigin.x = BrushObj->ptOrigin.x;
BrushOrigin.y = BrushObj->ptOrigin.y;
if (Dc_Attr->jROP2 == R2_XORPEN)
ROP = PATINVERT;
else
ROP = PATCOPY;
IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlatePen);
Ret = IntEngBitBlt(
&BitmapObj->SurfObj,
NULL,
NULL,
dc->CombinedClip,
NULL,
&DestRect,
NULL,
NULL,
&BrushInst.BrushObject, // use pDC->eboFill
&BrushOrigin,
ROP3_TO_ROP4(ROP));
}
BITMAPOBJ_UnlockBitmap(BitmapObj);
return (int)Ret;
}
/* /*
* Drawing an ellipse with a certain line thickness. * Drawing an ellipse with a certain line thickness.
@ -306,7 +165,7 @@ app_draw_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
// START_DEBUG(); // START_DEBUG();
if ((r.width <= 2) || (r.height <= 2)) if ((r.width <= 2) || (r.height <= 2))
return app_fill_rect_pen(g, r, BrushObj); return app_fill_rect(g, r, BrushObj, TRUE);
r1.x = r.x + a; r1.x = r.x + a;
r1.y = r.y; r1.y = r.y;
@ -405,8 +264,8 @@ app_draw_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
if ((r1.y < r.y+w) || (r1.x+W >= r1.x+r1.width-W)) if ((r1.y < r.y+w) || (r1.x+W >= r1.x+r1.width-W))
{ {
result &= app_fill_rect_pen(g, r1, BrushObj); result &= app_fill_rect(g, r1, BrushObj, TRUE);
result &= app_fill_rect_pen(g, r2, BrushObj); result &= app_fill_rect(g, r2, BrushObj, TRUE);
prevx = r1.x; prevx = r1.x;
prevy = r1.y; prevy = r1.y;
@ -414,14 +273,14 @@ app_draw_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
else if (r1.y+r1.height < r2.y) else if (r1.y+r1.height < r2.y)
{ {
/* draw distinct rectangles */ /* draw distinct rectangles */
result &= app_fill_rect_pen(g, rect(r1.x,r1.y, result &= app_fill_rect(g, rect(r1.x,r1.y,
W,1), BrushObj); W,1), BrushObj, TRUE);
result &= app_fill_rect_pen(g, rect( result &= app_fill_rect(g, rect(
r1.x+r1.width-W,r1.y,W,1), BrushObj); r1.x+r1.width-W,r1.y,W,1), BrushObj, TRUE);
result &= app_fill_rect_pen(g, rect(r2.x, result &= app_fill_rect(g, rect(r2.x,
r2.y,W,1), BrushObj); r2.y,W,1), BrushObj, TRUE);
result &= app_fill_rect_pen(g, rect( result &= app_fill_rect(g, rect(
r2.x+r2.width-W,r2.y,W,1), BrushObj); r2.x+r2.width-W,r2.y,W,1), BrushObj, TRUE);
prevx = r1.x; prevx = r1.x;
prevy = r1.y; prevy = r1.y;
@ -450,14 +309,14 @@ app_draw_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
W = w; W = w;
if (W+W >= r.width) { if (W+W >= r.width) {
result &= app_fill_rect_pen(g, rect(r.x, r1.y, result &= app_fill_rect(g, rect(r.x, r1.y,
r.width, r1.height), BrushObj); r.width, r1.height), BrushObj, TRUE);
return result; return result;
} }
result &= app_fill_rect_pen(g, rect(r.x, r1.y, W, r1.height), BrushObj); result &= app_fill_rect(g, rect(r.x, r1.y, W, r1.height), BrushObj, TRUE);
result &= app_fill_rect_pen(g, rect(r.x+r.width-W, r1.y, result &= app_fill_rect(g, rect(r.x+r.width-W, r1.y,
W, r1.height), BrushObj); W, r1.height), BrushObj, TRUE);
} }
return result; return result;
} }
@ -505,7 +364,8 @@ app_fill_arc_rect(DC *g,
POINT p2, // End POINT p2, // End
int start_angle, int start_angle,
int end_angle, int end_angle,
PGDIBRUSHOBJ BrushObj) PGDIBRUSHOBJ BrushObj,
BOOL Pen)
{ {
int x1, x2; int x1, x2;
int start_above, end_above; int start_above, end_above;
@ -580,36 +440,36 @@ app_fill_arc_rect(DC *g,
{ {
/* fill outsides of wedge */ /* fill outsides of wedge */
if (! app_fill_rect(g, rect(r.x, r.y, if (! app_fill_rect(g, rect(r.x, r.y,
x1-r.x, r.height), BrushObj)) x1-r.x, r.height), BrushObj, Pen))
return 0; return 0;
return app_fill_rect(g, rect(x2, r.y, return app_fill_rect(g, rect(x2, r.y,
r.x+r.width-x2, r.height), BrushObj); r.x+r.width-x2, r.height), BrushObj, Pen);
} }
else else
{ {
/* fill inside of wedge */ /* fill inside of wedge */
r.width = x1-x2; r.width = x1-x2;
r.x = x2; r.x = x2;
return app_fill_rect(g, r, BrushObj); return app_fill_rect(g, r, BrushObj, Pen);
} }
} }
else if (start_above) else if (start_above)
{ {
/* fill to the left of the start_line */ /* fill to the left of the start_line */
r.width = x1-r.x; r.width = x1-r.x;
return app_fill_rect(g, r, BrushObj); return app_fill_rect(g, r, BrushObj, Pen);
} }
else if (end_above) else if (end_above)
{ {
/* fill right of end_line */ /* fill right of end_line */
r.width = r.x+r.width-x2; r.width = r.x+r.width-x2;
r.x = x2; r.x = x2;
return app_fill_rect(g, r, BrushObj); return app_fill_rect(g, r, BrushObj, Pen);
} }
else else
{ {
if (start_angle > end_angle) if (start_angle > end_angle)
return app_fill_rect(g,r, BrushObj); return app_fill_rect(g,r, BrushObj, Pen);
else else
return 1; return 1;
} }
@ -675,7 +535,7 @@ app_fill_arc_rect(DC *g,
if (start_above && end_above) if (start_above && end_above)
{ {
if (start_angle > end_angle) if (start_angle > end_angle)
return app_fill_rect(g,r, BrushObj); return app_fill_rect(g,r, BrushObj, Pen);
else else
return 1; return 1;
} }
@ -683,14 +543,14 @@ app_fill_arc_rect(DC *g,
{ {
/* fill to the left of end_line */ /* fill to the left of end_line */
r.width = x2-r.x; r.width = x2-r.x;
return app_fill_rect(g,r, BrushObj); return app_fill_rect(g,r, BrushObj, Pen);
} }
else if (end_above) else if (end_above)
{ {
/* fill right of start_line */ /* fill right of start_line */
r.width = r.x+r.width-x1; r.width = r.x+r.width-x1;
r.x = x1; r.x = x1;
return app_fill_rect(g,r, BrushObj); return app_fill_rect(g,r, BrushObj, Pen);
} }
else else
{ {
@ -698,17 +558,17 @@ app_fill_arc_rect(DC *g,
{ {
/* fill outsides of wedge */ /* fill outsides of wedge */
if (! app_fill_rect(g, rect(r.x, r.y, if (! app_fill_rect(g, rect(r.x, r.y,
x2-r.x, r.height), BrushObj)) x2-r.x, r.height), BrushObj, Pen))
return 0; return 0;
return app_fill_rect(g, rect(x1, r.y, return app_fill_rect(g, rect(x1, r.y,
r.x+r.width-x1, r.height), BrushObj); r.x+r.width-x1, r.height), BrushObj, Pen);
} }
else else
{ {
/* fill inside of wedge */ /* fill inside of wedge */
r.width = x2-x1; r.width = x2-x1;
r.x = x1; r.x = x1;
return app_fill_rect(g, r, BrushObj); return app_fill_rect(g, r, BrushObj, Pen);
} }
} }
} }
@ -767,7 +627,7 @@ app_fill_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
// START_DEBUG(); // START_DEBUG();
if ((r.width <= 2) || (r.height <= 2)) if ((r.width <= 2) || (r.height <= 2))
return app_fill_rect(g, r, BrushObj); return app_fill_rect(g, r, BrushObj, FALSE);
r1.x = r.x + a; r1.x = r.x + a;
r1.y = r.y; r1.y = r.y;
@ -813,8 +673,8 @@ app_fill_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
if (r1.y+r1.height < r2.y) { if (r1.y+r1.height < r2.y) {
/* distinct rectangles */ /* distinct rectangles */
result &= app_fill_rect(g, r1, BrushObj); result &= app_fill_rect(g, r1, BrushObj, FALSE);
result &= app_fill_rect(g, r2, BrushObj); result &= app_fill_rect(g, r2, BrushObj, FALSE);
} }
/* move down */ /* move down */
@ -839,7 +699,7 @@ app_fill_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
r1.x = r.x; r1.x = r.x;
r1.width = r.width; r1.width = r.width;
r1.height = r2.y+r2.height-r1.y; r1.height = r2.y+r2.height-r1.y;
result &= app_fill_rect(g, r1, BrushObj); result &= app_fill_rect(g, r1, BrushObj, FALSE);
} }
else if (x <= a) { else if (x <= a) {
/* crossover, draw final line */ /* crossover, draw final line */
@ -847,7 +707,7 @@ app_fill_ellipse(DC *g, Rect r, PGDIBRUSHOBJ BrushObj)
r1.width = r.width; r1.width = r.width;
r1.height = r1.y+r1.height-r2.y; r1.height = r1.y+r1.height-r2.y;
r1.y = r2.y; r1.y = r2.y;
result &= app_fill_rect(g, r1, BrushObj); result &= app_fill_rect(g, r1, BrushObj, FALSE);
} }
return result; return result;
} }
@ -1014,10 +874,10 @@ app_fill_arc(DC *g, Rect r, int start_angle, int end_angle, PGDIBRUSHOBJ BrushOb
/* distinct rectangles */ /* distinct rectangles */
result &= app_fill_arc_rect(g, r1, result &= app_fill_arc_rect(g, r1,
p0, p1, p2, p0, p1, p2,
start_angle, end_angle, BrushObj); start_angle, end_angle, BrushObj, FALSE);
result &= app_fill_arc_rect(g, r2, result &= app_fill_arc_rect(g, r2,
p0, p1, p2, p0, p1, p2,
start_angle, end_angle, BrushObj); start_angle, end_angle, BrushObj, FALSE);
} }
/* move down */ /* move down */
@ -1039,7 +899,7 @@ app_fill_arc(DC *g, Rect r, int start_angle, int end_angle, PGDIBRUSHOBJ BrushOb
while (r1.height > 0) { while (r1.height > 0) {
result &= app_fill_arc_rect(g, result &= app_fill_arc_rect(g,
rect(r1.x, r1.y, r1.width, 1), rect(r1.x, r1.y, r1.width, 1),
p0, p1, p2, start_angle, end_angle, BrushObj); p0, p1, p2, start_angle, end_angle, BrushObj, FALSE);
r1.y += 1; r1.y += 1;
r1.height -= 1; r1.height -= 1;
} }
@ -1053,7 +913,7 @@ app_fill_arc(DC *g, Rect r, int start_angle, int end_angle, PGDIBRUSHOBJ BrushOb
while (r1.height > 0) { while (r1.height > 0) {
result &= app_fill_arc_rect(g, result &= app_fill_arc_rect(g,
rect(r1.x, r1.y, r1.width, 1), rect(r1.x, r1.y, r1.width, 1),
p0, p1, p2, start_angle, end_angle, BrushObj); p0, p1, p2, start_angle, end_angle, BrushObj, FALSE);
r1.y += 1; r1.y += 1;
r1.height -= 1; r1.height -= 1;
} }
@ -1061,8 +921,345 @@ app_fill_arc(DC *g, Rect r, int start_angle, int end_angle, PGDIBRUSHOBJ BrushOb
return result; return result;
} }
int app_draw_arc(DC *g, Rect r, int start_angle, int end_angle, PGDIBRUSHOBJ PenBrushObj, BOOL Chord)
{
/* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
int a = r.width / 2;
int b = r.height / 2;
int x = 0;
int y = b;
long a2 = a*a;
long b2 = b*b;
long xcrit = (3 * a2 / 4) + 1;
long ycrit = (3 * b2 / 4) + 1;
long t = b2 + a2 - 2*a2*b; /* t = e(x+1,y-1) */
long dxt = b2*(3+x+x);
long dyt = a2*(3-y-y);
int d2xt = b2+b2;
int d2yt = a2+a2;
int w = PenBrushObj->ptPenWidth.x;
/* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
int A = a-w > 0 ? a-w : 0;
int B = b-w > 0 ? b-w : 0;
int X = 0;
int Y = B;
long A2 = A*A;
long B2 = B*B;
long XCRIT = (3 * A2 / 4) + 1;
long YCRIT = (3 * B2 / 4) + 1;
long T = B2 + A2 - 2*A2*B; /* T = E(X+1,Y-1) */
long DXT = B2*(3+X+X);
long DYT = A2*(3-Y-Y);
int D2XT = B2+B2;
int D2YT = A2+A2;
/* arc rectangle calculations */
int movedown, moveout;
int innerX = 0, prevx, prevy, W;
Rect r1, r2;
int result = 1;
/* line descriptions */
POINT p0, p1, p2;
// START_DEBUG();
/* if angles differ by 360 degrees or more, close the shape */
if ((start_angle + 360 <= end_angle) ||
(start_angle - 360 >= end_angle))
{
return app_draw_ellipse(g, r, PenBrushObj);
}
/* make start_angle >= 0 and <= 360 */
while (start_angle < 0)
start_angle += 360;
start_angle %= 360;
/* make end_angle >= 0 and <= 360 */
while (end_angle < 0)
end_angle += 360;
end_angle %= 360;
/* draw nothing if the angles are equal */
if (start_angle == end_angle)
return 1;
/* find arc wedge line end points */
p1 = app_boundary_point(r, start_angle);
p2 = app_boundary_point(r, end_angle);
if (Chord)
p0 = pt((p1.x+p2.x)/2,(p1.y+p2.y)/2);
else
p0 = pt(r.x + r.width/2, r.y + r.height/2);
/* determine ellipse rectangles */
r1.x = r.x + a;
r1.y = r.y;
r1.width = r.width & 1; /* i.e. if width is odd */
r1.height = 1;
r2 = r1;
r2.y = r.y + r.height - 1;
prevx = r1.x;
prevy = r1.y;
while (y > 0)
{
while (Y == y)
{
innerX = X;
if (T + A2*Y < XCRIT) /* E(X+1,Y-1/2) <= 0 */
{
/* move outwards to encounter edge */
X += 1;
T += DXT;
DXT += D2XT;
}
else if (T - B2*X >= YCRIT) /* e(x+1/2,y-1) > 0 */
{
/* drop down one line */
Y -= 1;
T += DYT;
DYT += D2YT;
}
else {
/* drop diagonally down and out */
X += 1;
Y -= 1;
T += DXT + DYT;
DXT += D2XT;
DYT += D2YT;
}
}
movedown = moveout = 0;
W = x - innerX;
if (r1.x + W < prevx)
W = prevx - r1.x;
if (W < w)
W = w;
if (t + a2*y < xcrit) /* e(x+1,y-1/2) <= 0 */
{
/* move outwards to encounter edge */
x += 1;
t += dxt;
dxt += d2xt;
moveout = 1;
}
else if (t - b2*x >= ycrit) /* e(x+1/2,y-1) > 0 */
{
/* drop down one line */
y -= 1;
t += dyt;
dyt += d2yt;
movedown = 1;
}
else {
/* drop diagonally down and out */
x += 1;
y -= 1;
t += dxt + dyt;
dxt += d2xt;
dyt += d2yt;
movedown = 1;
moveout = 1;
}
if (movedown) {
if (r1.width == 0) {
r1.x -= 1; r1.width += 2;
r2.x -= 1; r2.width += 2;
moveout = 0;
}
if (r1.x < r.x)
r1.x = r2.x = r.x;
if (r1.width > r.width)
r1.width = r2.width = r.width;
if (r1.y == r2.y-1) {
r1.x = r2.x = r.x;
r1.width = r2.width = r.width;
}
if ((r1.y < r.y+w) || (r1.x+W >= r1.x+r1.width-W))
{
result &= app_fill_arc_rect(g, r1,
p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
result &= app_fill_arc_rect(g, r2,
p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
prevx = r1.x;
prevy = r1.y;
}
else if (r1.y+r1.height < r2.y)
{
/* draw distinct rectangles */
result &= app_fill_arc_rect(g, rect(
r1.x,r1.y,W,1),
p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
result &= app_fill_arc_rect(g, rect(
r1.x+r1.width-W,r1.y,W,1),
p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
result &= app_fill_arc_rect(g, rect(
r2.x,r2.y,W,1),
p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
result &= app_fill_arc_rect(g, rect(
r2.x+r2.width-W,r2.y,W,1),
p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
prevx = r1.x;
prevy = r1.y;
}
/* move down */
r1.y += 1;
r2.y -= 1;
}
if (moveout) {
/* move outwards */
r1.x -= 1; r1.width += 2;
r2.x -= 1; r2.width += 2;
}
}
if ((x <= a) && (prevy < r2.y)) {
/* draw final lines */
r1.height = r1.y+r1.height-r2.y;
r1.y = r2.y;
W = w;
if (r.x + W != prevx)
W = prevx - r.x;
if (W < w)
W = w;
if (W+W >= r.width) {
while (r1.height > 0) {
result &= app_fill_arc_rect(g, rect(r.x,
r1.y, r.width, 1), p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
r1.y += 1;
r1.height -= 1;
}
return result;
}
while (r1.height > 0) {
result &= app_fill_arc_rect(g, rect(r.x, r1.y,
W, 1), p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
result &= app_fill_arc_rect(g, rect(r.x+r.width-W,
r1.y, W, 1), p0, p1, p2,
start_angle, end_angle, PenBrushObj, TRUE);
r1.y += 1;
r1.height -= 1;
}
}
return result;
}
/* ReactOS Interface *********************************************************/ /* ReactOS Interface *********************************************************/
int
FASTCALL
IntFillRect( DC *dc,
INT XLeft,
INT YLeft,
INT Width,
INT Height,
PGDIBRUSHOBJ BrushObj,
BOOL Pen)
{
DWORD ROP = PATCOPY;
RECTL DestRect;
BITMAPOBJ *BitmapObj;
GDIBRUSHINST BrushInst;
POINTL BrushOrigin;
BOOL Ret = TRUE;
PDC_ATTR Dc_Attr = NULL;
ASSERT(BrushObj);
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
if (BitmapObj == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
if (!(BrushObj->flAttrs & GDIBRUSH_IS_NULL))
{
Dc_Attr = dc->pDc_Attr;
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
/* fix negative spaces */
if (Width < 0)
{
XLeft += Width;
Width = 0 - Width;
}
if (Height < 0)
{
YLeft += Height;
Height = 0 - Height;
}
DestRect.left = XLeft;
DestRect.right = XLeft + Width;
DestRect.top = YLeft;
DestRect.bottom = YLeft + Height;
BrushOrigin.x = BrushObj->ptOrigin.x;
BrushOrigin.y = BrushObj->ptOrigin.y;
if (Dc_Attr->jROP2 == R2_XORPEN)
ROP = PATINVERT;
else
ROP = PATCOPY;
if (Pen)
IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlatePen);
else
IntGdiInitBrushInstance(&BrushInst, BrushObj, dc->XlateBrush);
Ret = IntEngBitBlt(
&BitmapObj->SurfObj,
NULL,
NULL,
dc->CombinedClip,
NULL,
&DestRect,
NULL,
NULL,
&BrushInst.BrushObject, // use pDC->eboFill
&BrushOrigin,
ROP3_TO_ROP4(ROP));
}
BITMAPOBJ_UnlockBitmap(BitmapObj);
return (int)Ret;
}
BOOL BOOL
FASTCALL FASTCALL
IntFillArc( PDC dc, IntFillArc( PDC dc,
@ -1100,6 +1297,28 @@ IntFillArc( PDC dc,
return ret; return ret;
} }
BOOL
FASTCALL
IntDrawArc( PDC dc,
INT XLeft,
INT YLeft,
INT Width,
INT Height,
double StartArc,
double EndArc,
ARCTYPE arctype,
PGDIBRUSHOBJ PenBrushObj)
{
int Start = ceill(StartArc);
int End = ceill(EndArc);
BOOL Chord = (arctype == GdiTypeChord);
// Sort out alignment here.
return app_draw_arc(dc, rect( XLeft, YLeft, Width, Height),
(dc->DcLevel.flPath & DCPATH_CLOCKWISE) ? -End : -Start,
(dc->DcLevel.flPath & DCPATH_CLOCKWISE) ? -Start : -End,
PenBrushObj, Chord);
}
BOOL BOOL
FASTCALL FASTCALL
IntDrawEllipse( PDC dc, IntDrawEllipse( PDC dc,
@ -1139,3 +1358,154 @@ IntFillEllipse( PDC dc,
BRUSHOBJ_UnlockBrush(FillBrushObj); BRUSHOBJ_UnlockBrush(FillBrushObj);
return ret; return ret;
} }
BOOL
FASTCALL
IntFillRoundRect( PDC dc,
INT Left,
INT Top,
INT Right,
INT Bottom,
INT Wellipse,
INT Hellipse)
{
PDC_ATTR Dc_Attr;
PGDIBRUSHOBJ FillBrushObj;
Rect r;
int rx, ry; /* radius in x and y directions */
Dc_Attr = dc->pDc_Attr;
if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush);
if (NULL == FillBrushObj)
{
DPRINT1("FillEllipse Fail\n");
SetLastWin32Error(ERROR_INTERNAL_ERROR);
return FALSE;
}
// x y Width Height
r = rect( Left, Top, abs(Right-Left), abs(Bottom-Top));
rx = Wellipse/2;
ry = Hellipse/2;
if (Wellipse > r.width)
{
if (Hellipse > r.height) // > W > H
ret = app_fill_ellipse(dc, r, FillBrushObj);
else // > W < H
{
app_fill_arc(dc, rect( r.x, r.y, r.width - 1, Hellipse),
0, 180, FillBrushObj,FALSE);
app_fill_arc(dc, rect(r.x, Bottom - Hellipse - 1, r.width - 1, Hellipse),
180, 360, FillBrushObj, FALSE);
}
}
else if(Hellipse > r.height) // < W > H
{
app_fill_arc(dc, rect(r.x, r.y, Wellipse, r.height - 1),
90, 270, FillBrushObj, FALSE);
app_fill_arc(dc, rect(Right - Wellipse - 1, r.y, Wellipse, r.height - 1),
270, 90, FillBrushObj,FALSE);
}
else // < W < H
{
app_fill_arc(dc, rect(r.x, r.y, Wellipse, Hellipse),
90, 180, FillBrushObj, FALSE);
app_fill_arc(dc, rect(r.x, Bottom - Hellipse - 1, Wellipse, Hellipse),
180, 270, FillBrushObj, FALSE);
app_fill_arc(dc, rect(Right - Wellipse - 1, Bottom - Hellipse - 1, Wellipse, Hellipse),
270, 360, FillBrushObj,FALSE);
app_fill_arc(dc, rect(Right - Wellipse - 1, r.y, Wellipse, Hellipse ),
0, 90, FillBrushObj,FALSE);
}
if (Wellipse < r.width)
{
app_fill_rect(dc, rect(r.x+rx, r.y, r.width-rx-rx, ry+1), FillBrushObj, FALSE);
app_fill_rect(dc, rect(r.x+rx, r.y+r.height-ry+1, r.width-rx-rx, ry-1), FillBrushObj, FALSE);
}
if (Hellipse < r.height)
{
app_fill_rect(dc, rect(r.x, r.y+ry+1, r.width, r.height-ry-ry), FillBrushObj, FALSE);
}
BRUSHOBJ_UnlockBrush(FillBrushObj);
return TRUE;
}
BOOL
FASTCALL
IntDrawRoundRect( PDC dc,
INT Left,
INT Top,
INT Right,
INT Bottom,
INT Wellipse,
INT Hellipse,
PGDIBRUSHOBJ PenBrushObj)
{
Rect r;
int rx, ry; /* radius in x and y directions */
int w = PenBrushObj->ptPenWidth.x;
r = rect( Left, Top, abs(Right-Left), abs(Bottom-Top));
rx = Wellipse/2;
ry = Hellipse/2;
if (Wellipse > r.width)
{
if (Hellipse > r.height) // > W > H
app_draw_ellipse(dc, r, PenBrushObj);
else // > W < H
{
app_draw_arc(dc, rect( r.x, r.y, r.width - 1, Hellipse - 1),
0, 180, PenBrushObj, FALSE);
app_draw_arc(dc, rect(r.x, Bottom - Hellipse, r.width - 1, Hellipse - 1),
180, 360, PenBrushObj, FALSE);
}
}
else if(Hellipse > r.height) // < W > H
{
app_draw_arc(dc, rect(r.x, r.y, Wellipse - 1, r.height - 1),
90, 270, PenBrushObj, FALSE);
app_draw_arc(dc, rect(Right - Wellipse, r.y, Wellipse - 1, r.height - 1),
270, 90, PenBrushObj, FALSE);
}
else // < W < H
{
app_draw_arc(dc, rect(r.x, r.y, Wellipse-1, Hellipse - 1),
90, 180, PenBrushObj, FALSE);
app_draw_arc(dc, rect(r.x, Bottom - Hellipse, Wellipse - 1, Hellipse - 1),
180, 270, PenBrushObj, FALSE);
app_draw_arc(dc, rect(Right - Wellipse, Bottom - Hellipse, Wellipse - 1, Hellipse - 1),
270, 360, PenBrushObj, FALSE);
app_draw_arc(dc, rect(Right - Wellipse, r.y, Wellipse - 1, Hellipse - 1 ),
0, 90, PenBrushObj, FALSE);
}
if ( Hellipse < r.height)
{
app_fill_rect(dc, rect(r.x, r.y+ry+1, w, r.height-ry-ry), PenBrushObj, TRUE);
app_fill_rect(dc, rect(r.x+r.width-w, r.y+ry+1, w, r.height-ry-ry),
PenBrushObj, TRUE);
}
if ( Wellipse < r.width)
{
app_fill_rect(dc, rect(r.x+rx, r.y+r.height-w, r.width-rx-rx, w),
PenBrushObj, TRUE);
app_fill_rect(dc, rect(r.x+rx, r.y, r.width-rx-rx, w), PenBrushObj, TRUE);
}
return TRUE;
}

View file

@ -46,6 +46,8 @@
BOOL FASTCALL IntFillEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height); BOOL FASTCALL IntFillEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height);
BOOL FASTCALL IntDrawEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PGDIBRUSHOBJ PenBrushObj); BOOL FASTCALL IntDrawEllipse( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, PGDIBRUSHOBJ PenBrushObj);
BOOL FASTCALL IntFillRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse);
BOOL FASTCALL IntDrawRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom, INT Wellipse, INT Hellipse, PGDIBRUSHOBJ PenBrushObj);
BOOL FASTCALL BOOL FASTCALL
IntGdiPolygon(PDC dc, IntGdiPolygon(PDC dc,
@ -669,271 +671,97 @@ BOOL
FASTCALL FASTCALL
IntRoundRect( IntRoundRect(
PDC dc, PDC dc,
int left, int Left,
int top, int Top,
int right, int Right,
int bottom, int Bottom,
int xCurveDiameter, int xCurveDiameter,
int yCurveDiameter) int yCurveDiameter)
{ {
PDC_ATTR Dc_Attr; PDC_ATTR Dc_Attr;
BITMAPOBJ *BitmapObj; PGDIBRUSHOBJ PenBrushObj;
PGDIBRUSHOBJ PenBrushObj, FillBrushObj; RECTL RectBounds;
GDIBRUSHINST FillBrushInst, PenBrushInst; LONG PenWidth, PenOrigWidth;
RECTL RectBounds; BOOL ret = TRUE; // default to success
int potential_steps;
int i, col, row, width, height, x1, x1start, x2, x2start, y1, y2;
int xradius, yradius;
//float aspect_square;
long a_square, b_square,
two_a_square, two_b_square,
four_a_square, four_b_square,
d, dinc, ddec;
BOOL first,
ret = TRUE; // default to success
ASSERT ( dc ); // caller's responsibility to set this up ASSERT ( dc ); // caller's responsibility to set this up
if ( PATH_IsPathOpen(dc->DcLevel) ) if ( PATH_IsPathOpen(dc->DcLevel) )
return PATH_RoundRect ( dc, left, top, right, bottom, return PATH_RoundRect ( dc, Left, Top, Right, Bottom,
xCurveDiameter, yCurveDiameter ); xCurveDiameter, yCurveDiameter );
if ((Left == Right) || (Top == Bottom)) return TRUE;
xCurveDiameter = max(abs( xCurveDiameter ), 1);
yCurveDiameter = max(abs( yCurveDiameter ), 1);
if (Right < Left)
{
INT tmp = Right; Right = Left; Left = tmp;
}
if (Bottom < Top)
{
INT tmp = Bottom; Bottom = Top; Top = tmp;
}
Dc_Attr = dc->pDc_Attr; Dc_Attr = dc->pDc_Attr;
if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
xradius = xCurveDiameter >> 1; PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
yradius = yCurveDiameter >> 1; if (!PenBrushObj)
left += dc->ptlDCOrig.x;
right += dc->ptlDCOrig.x;
top += dc->ptlDCOrig.y;
bottom += dc->ptlDCOrig.y;
RectBounds.left = left;
RectBounds.right = right;
RectBounds.top = top;
RectBounds.bottom = bottom;
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
if (!BitmapObj)
{ {
/* Nothing to do, as we don't have a bitmap */ /* Nothing to do, as we don't have a bitmap */
SetLastWin32Error(ERROR_INTERNAL_ERROR); SetLastWin32Error(ERROR_INTERNAL_ERROR);
return FALSE; return FALSE;
} }
FillBrushObj = BRUSHOBJ_LockBrush(Dc_Attr->hbrush); PenOrigWidth = PenWidth = PenBrushObj->ptPenWidth.x;
if (FillBrushObj) if (PenBrushObj->ulPenStyle == PS_NULL) PenWidth = 0;
if (PenBrushObj->ulPenStyle == PS_INSIDEFRAME)
{ {
if (FillBrushObj->flAttrs & GDIBRUSH_IS_NULL) if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
{ if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
/* make null brush check simpler... */ Left += PenWidth / 2;
BRUSHOBJ_UnlockBrush(FillBrushObj); Right -= (PenWidth - 1) / 2;
FillBrushObj = NULL; Top += PenWidth / 2;
} Bottom -= (PenWidth - 1) / 2;
else
{
IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
}
} }
PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen); if (!PenWidth) PenWidth = 1;
if (PenBrushObj) PenBrushObj->ptPenWidth.x = PenWidth;
{
if (PenBrushObj->flAttrs & GDIBRUSH_IS_NULL)
{
/* make null pen check simpler... */
PENOBJ_UnlockPen(PenBrushObj);
PenBrushObj = NULL;
}
else
{
IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
}
}
right--; RectBounds.left = Left;
bottom--; RectBounds.top = Top;
RectBounds.right = Right;
RectBounds.bottom = Bottom;
width = right - left; IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
height = bottom - top;
if ( (xradius<<1) > width ) RectBounds.left += dc->ptlDCOrig.x;
xradius = width >> 1; RectBounds.top += dc->ptlDCOrig.y;
if ( (yradius<<1) > height ) RectBounds.right += dc->ptlDCOrig.x;
yradius = height >> 1; RectBounds.bottom += dc->ptlDCOrig.y;
b_square = yradius * yradius; ret = IntFillRoundRect( dc,
a_square = xradius * xradius; RectBounds.left,
row = yradius; RectBounds.top,
col = 0; RectBounds.right,
two_a_square = a_square << 1; RectBounds.bottom,
four_a_square = a_square << 2; xCurveDiameter,
four_b_square = b_square << 2; yCurveDiameter);
two_b_square = b_square << 1; if (ret)
d = two_a_square * ((row - 1) * (row)) ret = IntDrawRoundRect( dc,
+ a_square RectBounds.left,
+ two_b_square * (1 - a_square); RectBounds.top,
RectBounds.right,
x1 = left+xradius; RectBounds.bottom,
x2 = right-xradius; xCurveDiameter,
y1 = top; yCurveDiameter,
y2 = bottom; PenBrushObj);
x1start = x1;
x2start = x2;
dinc = two_b_square*3; /* two_b_square * (3 + (col << 1)); */
ddec = four_a_square * row;
first = TRUE;
for ( ;; )
{
if ( d >= 0 )
{
if ( FillBrushObj )
PUTLINE ( x1, y1, x2, y1, FillBrushInst );
if ( first )
{
if ( PenBrushObj )
{
if ( x1start > x1 )
{
PUTLINE ( x1, y1, x1start, y1, PenBrushInst );
PUTLINE ( x2start+1, y2, x2+1, y2, PenBrushInst );
}
else
{
PUTPIXEL ( x1, y1, PenBrushInst );
PUTPIXEL ( x2, y2, PenBrushInst );
}
}
first = FALSE;
}
else
{
if ( FillBrushObj )
PUTLINE ( x1, y2, x2, y2, FillBrushInst );
if ( PenBrushObj )
{
if ( x1start >= x1 )
{
PUTLINE ( x1, y1, x1start+1, y1, PenBrushInst );
PUTLINE ( x2start, y2, x2+1, y2, PenBrushInst );
}
else
{
PUTPIXEL ( x1, y1, PenBrushInst );
PUTPIXEL ( x2, y2, PenBrushInst );
}
}
}
if ( PenBrushObj )
{
if ( x1start > x1 )
{
PUTLINE ( x1, y2, x1start+1, y2, PenBrushInst );
PUTLINE ( x2start, y1, x2+1, y1, PenBrushInst );
}
else
{
PUTPIXEL ( x1, y2, PenBrushInst );
PUTPIXEL ( x2, y1, PenBrushInst );
}
}
x1start = x1-1;
x2start = x2+1;
row--, y1++, y2--, ddec -= four_a_square;
d -= ddec;
}
potential_steps = ( a_square * row ) / b_square - col + 1;
while ( d < 0 && potential_steps-- )
{
d += dinc; /* two_b_square * (3 + (col << 1)); */
col++, x1--, x2++, dinc += four_b_square;
}
if ( a_square * row <= b_square * col )
break;
};
d = two_b_square * (col + 1) * col
+ two_a_square * (row * (row - 2) + 1)
+ (1 - two_a_square) * b_square;
dinc = ddec; /* four_b_square * col; */
ddec = two_a_square * ((row << 1) - 3);
while ( row )
{
if ( FillBrushObj )
{
PUTLINE ( x1, y1, x2, y1, FillBrushInst );
PUTLINE ( x1, y2, x2, y2, FillBrushInst );
}
if ( PenBrushObj )
{
PUTPIXEL ( x2, y1, PenBrushInst );
PUTPIXEL ( x1, y2, PenBrushInst );
PUTPIXEL ( x2, y2, PenBrushInst );
PUTPIXEL ( x1, y1, PenBrushInst );
}
if ( d <= 0 )
{
col++, x1--, x2++, dinc += four_b_square;
d += dinc; //four_b_square * col;
}
row--, y1++, y2--, ddec -= four_a_square;
d -= ddec; //two_a_square * ((row << 1) - 3);
}
if ( FillBrushObj )
{
PUTLINE ( left, y1, right, y1, FillBrushInst );
PUTLINE ( left, y2, right, y2, FillBrushInst );
}
if ( PenBrushObj )
{
if ( x1 > (left+1) )
{
PUTLINE ( left, y1, x1, y1, PenBrushInst );
PUTLINE ( x2+1, y1, right, y1, PenBrushInst );
PUTLINE ( left+1, y2, x1, y2, PenBrushInst );
PUTLINE ( x2+1, y2, right+1, y2, PenBrushInst );
}
else
{
PUTPIXEL ( left, y1, PenBrushInst );
PUTPIXEL ( right, y2, PenBrushInst );
}
}
x1 = left+xradius;
x2 = right-xradius;
y1 = top+yradius;
y2 = bottom-yradius;
if ( FillBrushObj )
{
for ( i = y1+1; i < y2; i++ )
PUTLINE ( left, i, right, i, FillBrushInst );
}
if ( PenBrushObj )
{
PUTLINE ( x1, top, x2, top, PenBrushInst );
PUTLINE ( right, y1, right, y2, PenBrushInst );
PUTLINE ( x2, bottom, x1, bottom, PenBrushInst );
PUTLINE ( left, y2, left, y1, PenBrushInst );
}
BITMAPOBJ_UnlockBitmap(BitmapObj);
if (PenBrushObj != NULL)
PENOBJ_UnlockPen(PenBrushObj);
if (FillBrushObj != NULL)
BRUSHOBJ_UnlockBrush(FillBrushObj);
PenBrushObj->ptPenWidth.x = PenOrigWidth;
PENOBJ_UnlockPen(PenBrushObj);
return ret; return ret;
} }