Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
276 changes: 143 additions & 133 deletions Source/WriteableBitmapEx/WriteableBitmapAntialiasingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -318,139 +318,149 @@ private static void Swap<T>(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;
}
}
}
}
}
Loading