Discussion:
difference between drawrectangle and fillrectangle
(too old to reply)
Frank Vanderlinden
2004-10-04 13:25:04 UTC
Permalink
Hi,

Can some one give me a reason for the following :

Test the following code:

Graphics g = this.CreateGraphics();

g.DrawRectangle(new SolidPen(Color.Red), 10,10,2,2);
g.FillRectangle(new SolidBrush(Color.Green), 10,10,2,2);

Normally you should expect a solid green rectangle, but if
you look close you'l see a red line at the right and at
the bottom of the square.

It appears that the DrawRectangle draws 3 pixels !!

Is this a bug ??

Kind regards
Frank Vanderlinden
Justin Rogers
2004-10-04 21:36:06 UTC
Permalink
This isn't a bug. Both of the APIs do a best fit match and that means
the fill is often a bit short in where it stops. You normally want to do
a fill followed by a draw.

Think of it this way... If you fill a box with water, does it take up the
entire box, or just the *inside* of the box. Shapes have insides and
edges and they are two separate things.
Post by Frank Vanderlinden
Hi,
Graphics g = this.CreateGraphics();
g.DrawRectangle(new SolidPen(Color.Red), 10,10,2,2);
g.FillRectangle(new SolidBrush(Color.Green), 10,10,2,2);
Normally you should expect a solid green rectangle, but if
you look close you'l see a red line at the right and at
the bottom of the square.
It appears that the DrawRectangle draws 3 pixels !!
Is this a bug ??
Kind regards
Frank Vanderlinden
Frank Hileman
2004-10-04 22:21:44 UTC
Permalink
It is not really a "best fit". Here is how it works.

Assume you are running with PixelOffsetMode set to None and no
anti-aliasing. When you draw the rectangle edge, the pen you are using is
width 1. Consider the x dimension: the pen is centered over the coordinate
10 and extends to the coordinate 12. Since the center of the coordinate 10
is at pixel 10.5, and the center of coordinate 12 is at pixel 12.5, the pen
will exactly cover the pixel 10 and pixel 12. This means the pen draws a
rectangle 2 coordinate units wide, and 3 pixels wide, from 10.5 to 12.5 in
pixel coordinates, extending half a pixel (half width) on either side: 10 to
13 in pixel coordinates.

When drawing the fill, you get exactly 2 pixels wide, because the fill has a
0-width edge. It goes exactly from 10.5 to 12.5 in pixel coordinates, which
is truncated to 10 to 12.

If you draw with SmoothingMode set to AntiAlias, you will see the fill now
drawn the same width as the rectangle drawn with the pen. Only now, you will
see the edges of the fill at a lower alpha level: this is because each edge
of the fill actually lies on a mid-pixel boundary, and contributes only 50%
of the alpha level on those pixels.

Bottom line: pens always draw a figure that is increased in width and height
by the pen width. Fills do not, unless anti-aliased.

Regards,
Frank Hileman

check out VG.net: www.vgdotnet.com
Animated vector graphics system
Integrated Visual Studio .NET graphics editor
Post by Justin Rogers
This isn't a bug. Both of the APIs do a best fit match and that means
the fill is often a bit short in where it stops. You normally want to do
a fill followed by a draw.
Think of it this way... If you fill a box with water, does it take up the
entire box, or just the *inside* of the box. Shapes have insides and
edges and they are two separate things.
Post by Frank Vanderlinden
Hi,
Graphics g = this.CreateGraphics();
g.DrawRectangle(new SolidPen(Color.Red), 10,10,2,2);
g.FillRectangle(new SolidBrush(Color.Green), 10,10,2,2);
Normally you should expect a solid green rectangle, but if
you look close you'l see a red line at the right and at
the bottom of the square.
It appears that the DrawRectangle draws 3 pixels !!
Is this a bug ??
Kind regards
Frank Vanderlinden
Microsoft
2004-10-05 07:43:51 UTC
Permalink
Does this mean that everty time I use a Draw.. function I've got to decrees
the width and height by 1.
To me this looks like sloppy programming.

By the way this has to run on the Compact Framework
-> No Pen.Width
-> No SmoothingMode = AntiAlias (wich has no effect on rectangles if I'm
correct, only on curved sides)
Post by Frank Hileman
It is not really a "best fit". Here is how it works.
Assume you are running with PixelOffsetMode set to None and no
anti-aliasing. When you draw the rectangle edge, the pen you are using is
width 1. Consider the x dimension: the pen is centered over the coordinate
10 and extends to the coordinate 12. Since the center of the coordinate 10
is at pixel 10.5, and the center of coordinate 12 is at pixel 12.5, the pen
will exactly cover the pixel 10 and pixel 12. This means the pen draws a
rectangle 2 coordinate units wide, and 3 pixels wide, from 10.5 to 12.5 in
pixel coordinates, extending half a pixel (half width) on either side: 10 to
13 in pixel coordinates.
When drawing the fill, you get exactly 2 pixels wide, because the fill has a
0-width edge. It goes exactly from 10.5 to 12.5 in pixel coordinates, which
is truncated to 10 to 12.
If you draw with SmoothingMode set to AntiAlias, you will see the fill now
drawn the same width as the rectangle drawn with the pen. Only now, you will
see the edges of the fill at a lower alpha level: this is because each edge
of the fill actually lies on a mid-pixel boundary, and contributes only 50%
of the alpha level on those pixels.
Bottom line: pens always draw a figure that is increased in width and height
by the pen width. Fills do not, unless anti-aliased.
Regards,
Frank Hileman
check out VG.net: www.vgdotnet.com
Animated vector graphics system
Integrated Visual Studio .NET graphics editor
Post by Justin Rogers
This isn't a bug. Both of the APIs do a best fit match and that means
the fill is often a bit short in where it stops. You normally want to do
a fill followed by a draw.
Think of it this way... If you fill a box with water, does it take up the
entire box, or just the *inside* of the box. Shapes have insides and
edges and they are two separate things.
Post by Frank Vanderlinden
Hi,
Graphics g = this.CreateGraphics();
g.DrawRectangle(new SolidPen(Color.Red), 10,10,2,2);
g.FillRectangle(new SolidBrush(Color.Green), 10,10,2,2);
Normally you should expect a solid green rectangle, but if
you look close you'l see a red line at the right and at
the bottom of the square.
It appears that the DrawRectangle draws 3 pixels !!
Is this a bug ??
Kind regards
Frank Vanderlinden
Microsoft
2004-10-05 07:43:34 UTC
Permalink
Does this mean that everty time I use a Draw.. function I've got to decrees
the width and height by 1.
To me this looks like sloppy programming.

By the way this has to run on the Compact Framework
-> No Pen.Width
-> No SmoothingMode = AntiAlias (wich has no effect on rectangles if I'm
correct, only on curved sides)
Post by Frank Hileman
It is not really a "best fit". Here is how it works.
Assume you are running with PixelOffsetMode set to None and no
anti-aliasing. When you draw the rectangle edge, the pen you are using is
width 1. Consider the x dimension: the pen is centered over the coordinate
10 and extends to the coordinate 12. Since the center of the coordinate 10
is at pixel 10.5, and the center of coordinate 12 is at pixel 12.5, the pen
will exactly cover the pixel 10 and pixel 12. This means the pen draws a
rectangle 2 coordinate units wide, and 3 pixels wide, from 10.5 to 12.5 in
pixel coordinates, extending half a pixel (half width) on either side: 10 to
13 in pixel coordinates.
When drawing the fill, you get exactly 2 pixels wide, because the fill has a
0-width edge. It goes exactly from 10.5 to 12.5 in pixel coordinates, which
is truncated to 10 to 12.
If you draw with SmoothingMode set to AntiAlias, you will see the fill now
drawn the same width as the rectangle drawn with the pen. Only now, you will
see the edges of the fill at a lower alpha level: this is because each edge
of the fill actually lies on a mid-pixel boundary, and contributes only 50%
of the alpha level on those pixels.
Bottom line: pens always draw a figure that is increased in width and height
by the pen width. Fills do not, unless anti-aliased.
Regards,
Frank Hileman
check out VG.net: www.vgdotnet.com
Animated vector graphics system
Integrated Visual Studio .NET graphics editor
Post by Justin Rogers
This isn't a bug. Both of the APIs do a best fit match and that means
the fill is often a bit short in where it stops. You normally want to do
a fill followed by a draw.
Think of it this way... If you fill a box with water, does it take up the
entire box, or just the *inside* of the box. Shapes have insides and
edges and they are two separate things.
Post by Frank Vanderlinden
Hi,
Graphics g = this.CreateGraphics();
g.DrawRectangle(new SolidPen(Color.Red), 10,10,2,2);
g.FillRectangle(new SolidBrush(Color.Green), 10,10,2,2);
Normally you should expect a solid green rectangle, but if
you look close you'l see a red line at the right and at
the bottom of the square.
It appears that the DrawRectangle draws 3 pixels !!
Is this a bug ??
Kind regards
Frank Vanderlinden
Frank Hileman
2004-10-05 16:09:41 UTC
Permalink
If you want the number of pixels drawn to be equal to the rectangle width,
yes you must subtract one, and not just rectangles -- this applies to all
figures. It is consistent with the old Win32 behavior so it should work on
the CF as well.

I was just trying to clarify the mathematical reasoning behind the behavior.

AntiAlias does affect rectangles as well as curved areas. If you pass in
fraction coordinates you will see more clearly. Or if you change the
PixelOffsetMode.

Regards,
Frank
Post by Microsoft
Does this mean that everty time I use a Draw.. function I've got to decrees
the width and height by 1.
To me this looks like sloppy programming.
By the way this has to run on the Compact Framework
-> No Pen.Width
-> No SmoothingMode = AntiAlias (wich has no effect on rectangles if I'm
correct, only on curved sides)
Loading...