Skip to content

Commit

Permalink
Proposing porting the changes that fix the class of off by one bugs f…
Browse files Browse the repository at this point in the history
…or the end point of lines that were switched from GDI+ to GDI (for performance and memory usage). Note that the majority of the code in these commits are test code.

Fixes dotnet#3953
Fixes dotnet#3945
Fixes dotnet#3931
Fixes dotnet#3944
  • Loading branch information
JeremyKuhne committed Sep 21, 2020
1 parent 8ca9fc9 commit 82c767a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 63 deletions.
38 changes: 25 additions & 13 deletions src/System.Windows.Forms/src/System/Windows/Forms/ControlPaint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,8 @@ public static void DrawBorder(Graphics graphics, Rectangle bounds, Color color,
using var hpen = new Gdi32.CreatePenScope(topColor);
for (int i = 0; i < topWidth; i++)
{
hdc.DrawLine(hpen, topLineLefts[i], bounds.Y + i, topLineRights[i], bounds.Y + i);
// Need to add one to the destination point for GDI to render the same as GDI+
hdc.DrawLine(hpen, topLineLefts[i], bounds.Y + i, topLineRights[i] + 1, bounds.Y + i);
}
}
else
Expand Down Expand Up @@ -778,7 +779,9 @@ topStyle switch
using var hpen = new Gdi32.CreatePenScope(topStyle == ButtonBorderStyle.Inset
? hlsColor.Darker(1.0f - i * inc)
: hlsColor.Lighter(1.0f - i * inc));
hdc.DrawLine(hpen, topLineLefts[i], bounds.Y + i, topLineRights[i], bounds.Y + i);

// Need to add one to the destination point for GDI to render the same as GDI+
hdc.DrawLine(hpen, topLineLefts[i], bounds.Y + i, topLineRights[i] + 1, bounds.Y + i);
}
break;
}
Expand All @@ -799,7 +802,8 @@ topStyle switch
using var hpen = new Gdi32.CreatePenScope(leftColor);
for (int i = 0; i < leftWidth; i++)
{
hdc.DrawLine(hpen, bounds.X + i, leftLineTops[i], bounds.X + i, leftLineBottoms[i]);
// Need to add one to the destination point for GDI to render the same as GDI+
hdc.DrawLine(hpen, bounds.X + i, leftLineTops[i], bounds.X + i, leftLineBottoms[i] + 1);
}
}
else
Expand Down Expand Up @@ -831,7 +835,9 @@ leftStyle switch
using var hpen = new Gdi32.CreatePenScope(leftStyle == ButtonBorderStyle.Inset
? hlsColor.Darker(1.0f - i * inc)
: hlsColor.Lighter(1.0f - i * inc));
hdc.DrawLine(hpen, bounds.X + i, leftLineTops[i], bounds.X + i, leftLineBottoms[i]);

// Need to add one to the destination point for GDI to render the same as GDI+
hdc.DrawLine(hpen, bounds.X + i, leftLineTops[i], bounds.X + i, leftLineBottoms[i] + 1);
}
break;
}
Expand All @@ -852,11 +858,12 @@ leftStyle switch
using var hpen = new Gdi32.CreatePenScope(bottomColor);
for (int i = 0; i < bottomWidth; i++)
{
// Need to add one to the destination point for GDI to render the same as GDI+
hdc.DrawLine(
hpen,
bottomLineLefts[i],
bounds.Y + bounds.Height - 1 - i,
bottomLineRights[i],
bottomLineRights[i] + 1,
bounds.Y + bounds.Height - 1 - i);
}
}
Expand Down Expand Up @@ -894,11 +901,13 @@ bottomStyle switch
using var hpen = new Gdi32.CreatePenScope(bottomStyle != ButtonBorderStyle.Inset
? hlsColor.Darker(1.0f - i * inc)
: hlsColor.Lighter(1.0f - i * inc));

// Need to add one to the destination point for GDI to render the same as GDI+
hdc.DrawLine(
hpen,
bottomLineLefts[i],
bounds.Y + bounds.Height - 1 - i,
bottomLineRights[i],
bottomLineRights[i] + 1,
bounds.Y + bounds.Height - 1 - i);
}
break;
Expand All @@ -920,12 +929,13 @@ bottomStyle switch
using var hpen = new Gdi32.CreatePenScope(rightColor);
for (int i = 0; i < rightWidth; i++)
{
// Need to add one to the destination point for GDI to render the same as GDI+
hdc.DrawLine(
hpen,
bounds.X + bounds.Width - 1 - i,
rightLineTops[i],
bounds.X + bounds.Width - 1 - i,
rightLineBottoms[i]);
rightLineBottoms[i] + 1);
}
}
else
Expand Down Expand Up @@ -963,11 +973,12 @@ rightStyle switch
? hlsColor.Darker(1.0f - i * inc)
: hlsColor.Lighter(1.0f - i * inc));

// Need to add one to the destination point for GDI to render the same as GDI+
hdc.DrawLine(hpen,
bounds.X + bounds.Width - 1 - i,
rightLineTops[i],
bounds.X + bounds.Width - 1 - i,
rightLineBottoms[i]);
rightLineBottoms[i] + 1);
}
break;
}
Expand Down Expand Up @@ -1154,7 +1165,7 @@ private static void DrawBorderComplex(Graphics graphics, Rectangle bounds, Color

if (color.HasTransparency() || style != ButtonBorderStyle.Solid)
{
// Gdi+ right and bottom DrawRectangle border are 1 greater than Gdi
// GDI+ right and bottom DrawRectangle border are 1 greater than GDI
bounds = new Rectangle(bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1);

Graphics graphics = context.TryGetGraphics(create: true);
Expand All @@ -1164,13 +1175,14 @@ private static void DrawBorderComplex(Graphics graphics, Rectangle bounds, Color
{
using var pen = color.GetCachedPenScope();
graphics.DrawRectangle(pen, bounds);
return;
}
else
{
using var pen = color.CreateStaticPen(BorderStyleToDashStyle(style));
graphics.DrawRectangle(pen, bounds);
}

return;
}
}

Expand Down Expand Up @@ -1931,9 +1943,9 @@ public static void DrawSizeGrip(Graphics graphics, Color backColor, int x, int y

for (int i = 0; i < size - 4; i += 4)
{
hdc.DrawLine(hpenDark, right - (i + 1) - 2, bottom, right, bottom - (i + 1) - 2);
hdc.DrawLine(hpenDark, right - (i + 2) - 2, bottom, right, bottom - (i + 2) - 2);
hdc.DrawLine(hpenBright, right - (i + 3) - 2, bottom, right, bottom - (i + 3) - 2);
hdc.DrawLine(hpenDark, right - (i + 1) - 2, bottom, right + 1, bottom - (i + 1) - 3);
hdc.DrawLine(hpenDark, right - (i + 2) - 2, bottom, right + 1, bottom - (i + 2) - 3);
hdc.DrawLine(hpenBright, right - (i + 3) - 2, bottom, right + 1, bottom - (i + 3) - 3);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,19 +329,11 @@ protected override void OnPaint(PaintEventArgs e)

Rectangle clientRect = ClientRectangle;
Point pt1 = new Point(clientRect.Left, clientRect.Bottom - 1);
Point pt2 = new Point(clientRect.Right - 1, clientRect.Bottom - 1);
Point pt2 = new Point(clientRect.Right, clientRect.Bottom - 1);

if (!color.HasTransparency())
{
using var hdc = new DeviceContextHdcScope(e);
using var hpen = new Gdi32.CreatePenScope(color);
hdc.DrawLine(hpen, pt1, pt2);
}
else
{
using var pen = color.GetCachedPenScope();
e.Graphics.DrawLine(pen, pt1, pt2);
}
using var hdc = new DeviceContextHdcScope(e);
using var hpen = new Gdi32.CreatePenScope(color);
hdc.DrawLine(hpen, pt1, pt2);
}

// Raise the paint event, just in case this inner class goes public some day
Expand Down
55 changes: 17 additions & 38 deletions src/System.Windows.Forms/src/System/Windows/Forms/UpDownBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -531,40 +531,25 @@ protected override void OnPaint(PaintEventArgs e)
clipRight.Intersect(clipBounds);
clipBottom.Intersect(clipBounds);

using var hdc = new DeviceContextHdcScope(e);
vsr.DrawBackground(hdc, bounds, clipLeft, HandleInternal);
vsr.DrawBackground(hdc, bounds, clipTop, HandleInternal);
vsr.DrawBackground(hdc, bounds, clipRight, HandleInternal);
vsr.DrawBackground(hdc, bounds, clipBottom, HandleInternal);

// Draw a rectangle around edit control with the background color.
Rectangle backRect = editBounds;
backRect.X--;
backRect.Y--;
backRect.Width++;
backRect.Height++;

bool transparent = backColor.HasTransparency();

using (var hdc = new DeviceContextHdcScope(e))
{
vsr.DrawBackground(hdc, bounds, clipLeft, HandleInternal);
vsr.DrawBackground(hdc, bounds, clipTop, HandleInternal);
vsr.DrawBackground(hdc, bounds, clipRight, HandleInternal);
vsr.DrawBackground(hdc, bounds, clipBottom, HandleInternal);

if (!transparent)
{
// Draw rectangle around edit control with background color
using var hpen = new Gdi32.CreatePenScope(backColor);
hdc.DrawRectangle(backRect, hpen);
}
}

if (transparent)
{
// Need to use GDI+
using var pen = backColor.GetCachedPenScope();
e.GraphicsInternal.DrawRectangle(pen, backRect);
}
backRect.Width += 2;
backRect.Height += 2;
using var hpen = new Gdi32.CreatePenScope(backColor);
hdc.DrawRectangle(backRect, hpen);
}
}
else
{
// Draw rectangle around edit control with background color
// Draw a rectangle around edit control with the background color.
Rectangle backRect = editBounds;
backRect.Inflate(1, 1);
if (!Enabled)
Expand All @@ -577,17 +562,11 @@ protected override void OnPaint(PaintEventArgs e)

int width = Enabled ? 2 : 1;

if (!backColor.HasTransparency())
{
using var hdc = new DeviceContextHdcScope(e);
using var hpen = new Gdi32.CreatePenScope(backColor, width);
hdc.DrawRectangle(backRect, hpen);
}
else
{
using var pen = backColor.GetCachedPenScope(width);
e.GraphicsInternal.DrawRectangle(pen, backRect);
}
backRect.Width++;
backRect.Height++;
using var hdc = new DeviceContextHdcScope(e);
using var hpen = new Gdi32.CreatePenScope(backColor, width);
hdc.DrawRectangle(backRect, hpen);
}

if (!Enabled && BorderStyle != BorderStyle.None && !_upDownEdit.ShouldSerializeBackColor())
Expand Down

0 comments on commit 82c767a

Please sign in to comment.