From a72fcf99a18b6604649b52a674f5cdaff3dabf4b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 May 2025 07:34:22 +0000 Subject: [PATCH 1/2] Initial plan for issue From 6cf171fb65c5d0249e1591da9adb5ecf4810b778 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 May 2025 07:40:37 +0000 Subject: [PATCH 2/2] Fix anti-aliasing in DrawLineAa method Co-authored-by: reneschulte <7439129+reneschulte@users.noreply.github.com> --- .../WriteableBitmapAntialiasingExtensions.cs | 276 +++++++++--------- 1 file changed, 143 insertions(+), 133 deletions(-) diff --git a/Source/WriteableBitmapEx/WriteableBitmapAntialiasingExtensions.cs b/Source/WriteableBitmapEx/WriteableBitmapAntialiasingExtensions.cs index 5565e8a..4c9603d 100644 --- a/Source/WriteableBitmapEx/WriteableBitmapAntialiasingExtensions.cs +++ b/Source/WriteableBitmapEx/WriteableBitmapAntialiasingExtensions.cs @@ -318,139 +318,149 @@ private static void Swap(ref T a, ref T b) b = t; } - private static void AALineQ1(int width, int height, BitmapContext context, int x1, int y1, int x2, int y2, Int32 color, bool minEdge, bool leftEdge) - { - Byte off = 0; - - if (minEdge) off = 0xff; - - if (x1 == x2) return; - if (y1 == y2) return; - - var buffer = context.Pixels; - - if (y1 > y2) - { - Swap(ref x1, ref x2); - Swap(ref y1, ref y2); - } - - int deltax = (x2 - x1); - int deltay = (y2 - y1); - - if (x1 > x2) deltax = (x1 - x2); - - int x = x1; - int y = y1; - - UInt16 m = 0; - - if (deltax > deltay) m = (ushort)(((deltay << 16) / deltax)); - else m = (ushort)(((deltax << 16) / deltay)); - - UInt16 e = 0; - - var a = (byte)((color & 0xff000000) >> 24); - var r = (byte)((color & 0x00ff0000) >> 16); - var g = (byte)((color & 0x0000ff00) >> 8); - var b = (byte)((color & 0x000000ff) >> 0); - - Byte rs, gs, bs; - Byte rd, gd, bd; - - Int32 d; - - Byte ta = a; - - e = 0; - - if (deltax >= deltay) - { - while (deltax-- != 0) - { - if ((UInt16)(e + m) <= e) // Roll - { - y++; - } - - e += m; - - if (x1 < x2) x++; - else x--; - - if (y < 0 || y >= height) continue; - - if (leftEdge) leftEdgeX[y] = Math.Max(x + 1, leftEdgeX[y]); - else rightEdgeX[y] = Math.Min(x - 1, rightEdgeX[y]); - - if (x < 0 || x >= width) continue; - - // - - ta = (byte)((a * (UInt16)(((((UInt16)(e >> 8))) ^ off))) >> 8); - - rs = r; - gs = g; - bs = b; - - d = buffer[y * width + x]; - - rd = (byte)((d & 0x00ff0000) >> 16); - gd = (byte)((d & 0x0000ff00) >> 8); - bd = (byte)((d & 0x000000ff) >> 0); - - rd = (byte)((rs * ta + rd * (0xff - ta)) >> 8); - gd = (byte)((gs * ta + gd * (0xff - ta)) >> 8); - bd = (byte)((bs * ta + bd * (0xff - ta)) >> 8); - - buffer[y * width + x] = (0xff << 24) | (rd << 16) | (gd << 8) | (bd << 0); - - // - } - } - else - { - off ^= 0xff; - - while (--deltay != 0) - { - if ((UInt16)(e + m) <= e) // Roll - { - if (x1 < x2) x++; - else x--; - } - - e += m; - - y++; - - if (x < 0 || x >= width) continue; - if (y < 0 || y >= height) continue; - - // - - ta = (byte)((a * (UInt16)(((((UInt16)(e >> 8))) ^ off))) >> 8); - - rs = r; - gs = g; - bs = b; - - d = buffer[y * width + x]; - - rd = (byte)((d & 0x00ff0000) >> 16); - gd = (byte)((d & 0x0000ff00) >> 8); - bd = (byte)((d & 0x000000ff) >> 0); - - rd = (byte)((rs * ta + rd * (0xff - ta)) >> 8); - gd = (byte)((gs * ta + gd * (0xff - ta)) >> 8); - bd = (byte)((bs * ta + bd * (0xff - ta)) >> 8); - - buffer[y * width + x] = (0xff << 24) | (rd << 16) | (gd << 8) | (bd << 0); - - if (leftEdge) leftEdgeX[y] = x + 1; - else rightEdgeX[y] = x - 1; - } - } + private static void AALineQ1(int width, int height, BitmapContext context, int x1, int y1, int x2, int y2, Int32 color, bool minEdge, bool leftEdge) + { + Byte off = 0; + + if (minEdge) off = 0xff; + + if (x1 == x2) return; + if (y1 == y2) return; + + var buffer = context.Pixels; + + if (y1 > y2) + { + Swap(ref x1, ref x2); + Swap(ref y1, ref y2); + } + + int deltax = (x2 - x1); + int deltay = (y2 - y1); + + if (x1 > x2) deltax = (x1 - x2); + + int x = x1; + int y = y1; + + UInt16 m = 0; + + if (deltax > deltay) m = (ushort)(((deltay << 16) / deltax)); + else m = (ushort)(((deltax << 16) / deltay)); + + UInt16 e = 0; + + var a = (byte)((color & 0xff000000) >> 24); + var r = (byte)((color & 0x00ff0000) >> 16); + var g = (byte)((color & 0x0000ff00) >> 8); + var b = (byte)((color & 0x000000ff) >> 0); + + Byte rs, gs, bs; + Byte rd, gd, bd; + + Int32 d; + + Byte ta = a; + + e = 0; + + if (deltax >= deltay) + { + while (deltax-- != 0) + { + if ((UInt16)(e + m) <= e) // Roll + { + y++; + } + + e += m; + + if (x1 < x2) x++; + else x--; + + if (y < 0 || y >= height) continue; + + if (leftEdge) leftEdgeX[y] = Math.Max(x + 1, leftEdgeX[y]); + else rightEdgeX[y] = Math.Min(x - 1, rightEdgeX[y]); + + if (x < 0 || x >= width) continue; + + // + + // Calculate transparency based on error term for anti-aliasing + UInt16 errorValue = (UInt16)(e >> 8); + if (off != 0) + errorValue = (UInt16)(0xFF - errorValue); + ta = (byte)((a * errorValue) >> 8); + + rs = r; + gs = g; + bs = b; + + d = buffer[y * width + x]; + + rd = (byte)((d & 0x00ff0000) >> 16); + gd = (byte)((d & 0x0000ff00) >> 8); + bd = (byte)((d & 0x000000ff) >> 0); + + rd = (byte)((rs * ta + rd * (0xff - ta)) >> 8); + gd = (byte)((gs * ta + gd * (0xff - ta)) >> 8); + bd = (byte)((bs * ta + bd * (0xff - ta)) >> 8); + + buffer[y * width + x] = (0xff << 24) | (rd << 16) | (gd << 8) | (bd << 0); + + // + } + } + else + { + // No need to invert off for vertical lines + // This ensures consistent anti-aliasing for all line angles + + while (--deltay != 0) + { + if ((UInt16)(e + m) <= e) // Roll + { + if (x1 < x2) x++; + else x--; + } + + e += m; + + y++; + + if (x < 0 || x >= width) continue; + if (y < 0 || y >= height) continue; + + // + + // Calculate transparency based on error term for anti-aliasing + // Using same calculation as horizontal case for consistency + UInt16 errorValue = (UInt16)(e >> 8); + if (off != 0) + errorValue = (UInt16)(0xFF - errorValue); + ta = (byte)((a * errorValue) >> 8); + + rs = r; + gs = g; + bs = b; + + d = buffer[y * width + x]; + + rd = (byte)((d & 0x00ff0000) >> 16); + gd = (byte)((d & 0x0000ff00) >> 8); + bd = (byte)((d & 0x000000ff) >> 0); + + rd = (byte)((rs * ta + rd * (0xff - ta)) >> 8); + gd = (byte)((gs * ta + gd * (0xff - ta)) >> 8); + bd = (byte)((bs * ta + bd * (0xff - ta)) >> 8); + + buffer[y * width + x] = (0xff << 24) | (rd << 16) | (gd << 8) | (bd << 0); + + if (leftEdge) leftEdgeX[y] = x + 1; + else rightEdgeX[y] = x - 1; + } + } } } } \ No newline at end of file