//-------------------------------------------------------------------- unsafe public void Generate(RGBA_Bytes *span, int x, int y, uint len) { m_rgba1.Calculate(y); //(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); rgba_calc pc1 = m_rgba1; rgba_calc pc2 = m_rgba2; if (y <= m_y2) { // Bottom part of the triangle (first subtriangle) //------------------------- m_rgba2.Calculate(y + m_rgba2.m_1dy); } else { // Upper part (second subtriangle) m_rgba3.Calculate(y - m_rgba3.m_1dy); //------------------------- pc2 = m_rgba3; } if (m_swap) { // It means that the triangle is oriented clockwise, // so that we need to swap the controlling structures //------------------------- rgba_calc t = pc2; pc2 = pc1; pc1 = t; } // Get the horizontal length with subpixel accuracy // and protect it from division by zero //------------------------- int nlen = Math.Abs(pc2.m_x - pc1.m_x); if (nlen <= 0) { nlen = 1; } DdaLineInterpolator r = new DdaLineInterpolator(pc1.m_r, pc2.m_r, (uint)nlen, 14); DdaLineInterpolator g = new DdaLineInterpolator(pc1.m_g, pc2.m_g, (uint)nlen, 14); DdaLineInterpolator b = new DdaLineInterpolator(pc1.m_b, pc2.m_b, (uint)nlen, 14); DdaLineInterpolator a = new DdaLineInterpolator(pc1.m_a, pc2.m_a, (uint)nlen, 14); // Calculate the starting point of the Gradient with subpixel // accuracy and correct (roll back) the interpolators. // This operation will also Clip the beginning of the Span // if necessary. //------------------------- int start = pc1.m_x - (x << (int)ESubpixelScale.subpixel_shift); r.Prev(start); g.Prev(start); b.Prev(start); a.Prev(start); nlen += start; int vr, vg, vb, va; uint lim = 255; // Beginning part of the Span. Since we rolled back the // interpolators, the Color values may have overflowed. // So that, we render the beginning part with checking // for overflow. It lasts until "Start" is positive; // typically it's 1-2 pixels, but may be more in some cases. //------------------------- while (len != 0 && start > 0) { vr = r.y(); vg = g.y(); vb = b.y(); va = a.y(); if (vr < 0) { vr = 0; } if (vr > lim) { vr = (int)lim; } if (vg < 0) { vg = 0; } if (vg > lim) { vg = (int)lim; } if (vb < 0) { vb = 0; } if (vb > lim) { vb = (int)lim; } if (va < 0) { va = 0; } if (va > lim) { va = (int)lim; } span[0].m_R = (byte)vr; span[0].m_G = (byte)vg; span[0].m_B = (byte)vb; span[0].m_A = (byte)va; r.Next((int)ESubpixelScale.subpixel_scale); g.Next((int)ESubpixelScale.subpixel_scale); b.Next((int)ESubpixelScale.subpixel_scale); a.Next((int)ESubpixelScale.subpixel_scale); nlen -= (int)ESubpixelScale.subpixel_scale; start -= (int)ESubpixelScale.subpixel_scale; ++span; --len; } // Middle part, no checking for overflow. // Actual spans can be longer than the calculated length // because of anti-aliasing, thus, the interpolators can // overflow. But while "nlen" is positive we are safe. //------------------------- while (len != 0 && nlen > 0) { span[0].m_R = (byte)r.y(); span[0].m_G = (byte)g.y(); span[0].m_B = (byte)b.y(); span[0].m_A = (byte)a.y(); r.Next((int)ESubpixelScale.subpixel_scale); g.Next((int)ESubpixelScale.subpixel_scale); b.Next((int)ESubpixelScale.subpixel_scale); a.Next((int)ESubpixelScale.subpixel_scale); nlen -= (int)ESubpixelScale.subpixel_scale; ++span; --len; } // Ending part; checking for overflow. // Typically it's 1-2 pixels, but may be more in some cases. //------------------------- while (len != 0) { vr = r.y(); vg = g.y(); vb = b.y(); va = a.y(); if (vr < 0) { vr = 0; } if (vr > lim) { vr = (int)lim; } if (vg < 0) { vg = 0; } if (vg > lim) { vg = (int)lim; } if (vb < 0) { vb = 0; } if (vb > lim) { vb = (int)lim; } if (va < 0) { va = 0; } if (va > lim) { va = (int)lim; } span[0].m_R = (byte)vr; span[0].m_G = (byte)vg; span[0].m_B = (byte)vb; span[0].m_A = (byte)va; r.Next((int)ESubpixelScale.subpixel_scale); g.Next((int)ESubpixelScale.subpixel_scale); b.Next((int)ESubpixelScale.subpixel_scale); a.Next((int)ESubpixelScale.subpixel_scale); ++span; --len; } }
//-------------------------------------------------------------------- public unsafe void Generate(RGBA_Bytes* span, int x, int y, uint len) { m_rgba1.Calculate(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); rgba_calc pc1 = m_rgba1; rgba_calc pc2 = m_rgba2; if (y <= m_y2) { // Bottom part of the triangle (first subtriangle) //------------------------- m_rgba2.Calculate(y + m_rgba2.m_1dy); } else { // Upper part (second subtriangle) m_rgba3.Calculate(y - m_rgba3.m_1dy); //------------------------- pc2 = m_rgba3; } if (m_swap) { // It means that the triangle is oriented clockwise, // so that we need to swap the controlling structures //------------------------- rgba_calc t = pc2; pc2 = pc1; pc1 = t; } // Get the horizontal length with subpixel accuracy // and protect it from division by zero //------------------------- int nlen = Math.Abs(pc2.m_x - pc1.m_x); if (nlen <= 0) nlen = 1; DdaLineInterpolator r = new DdaLineInterpolator(pc1.m_r, pc2.m_r, (uint)nlen, 14); DdaLineInterpolator g = new DdaLineInterpolator(pc1.m_g, pc2.m_g, (uint)nlen, 14); DdaLineInterpolator b = new DdaLineInterpolator(pc1.m_b, pc2.m_b, (uint)nlen, 14); DdaLineInterpolator a = new DdaLineInterpolator(pc1.m_a, pc2.m_a, (uint)nlen, 14); // Calculate the starting point of the Gradient with subpixel // accuracy and correct (roll back) the interpolators. // This operation will also Clip the beginning of the Span // if necessary. //------------------------- int start = pc1.m_x - (x << (int)ESubpixelScale.subpixel_shift); r.Prev(start); g.Prev(start); b.Prev(start); a.Prev(start); nlen += start; int vr, vg, vb, va; uint lim = 255; // Beginning part of the Span. Since we rolled back the // interpolators, the Color values may have overflowed. // So that, we render the beginning part with checking // for overflow. It lasts until "Start" is positive; // typically it's 1-2 pixels, but may be more in some cases. //------------------------- while (len != 0 && start > 0) { vr = r.y(); vg = g.y(); vb = b.y(); va = a.y(); if (vr < 0) vr = 0; if (vr > lim) vr = (int)lim; if (vg < 0) vg = 0; if (vg > lim) vg = (int)lim; if (vb < 0) vb = 0; if (vb > lim) vb = (int)lim; if (va < 0) va = 0; if (va > lim) va = (int)lim; span[0].m_R = (byte)vr; span[0].m_G = (byte)vg; span[0].m_B = (byte)vb; span[0].m_A = (byte)va; r.Next((int)ESubpixelScale.subpixel_scale); g.Next((int)ESubpixelScale.subpixel_scale); b.Next((int)ESubpixelScale.subpixel_scale); a.Next((int)ESubpixelScale.subpixel_scale); nlen -= (int)ESubpixelScale.subpixel_scale; start -= (int)ESubpixelScale.subpixel_scale; ++span; --len; } // Middle part, no checking for overflow. // Actual spans can be longer than the calculated length // because of anti-aliasing, thus, the interpolators can // overflow. But while "nlen" is positive we are safe. //------------------------- while (len != 0 && nlen > 0) { span[0].m_R = (byte)r.y(); span[0].m_G = (byte)g.y(); span[0].m_B = (byte)b.y(); span[0].m_A = (byte)a.y(); r.Next((int)ESubpixelScale.subpixel_scale); g.Next((int)ESubpixelScale.subpixel_scale); b.Next((int)ESubpixelScale.subpixel_scale); a.Next((int)ESubpixelScale.subpixel_scale); nlen -= (int)ESubpixelScale.subpixel_scale; ++span; --len; } // Ending part; checking for overflow. // Typically it's 1-2 pixels, but may be more in some cases. //------------------------- while (len != 0) { vr = r.y(); vg = g.y(); vb = b.y(); va = a.y(); if (vr < 0) vr = 0; if (vr > lim) vr = (int)lim; if (vg < 0) vg = 0; if (vg > lim) vg = (int)lim; if (vb < 0) vb = 0; if (vb > lim) vb = (int)lim; if (va < 0) va = 0; if (va > lim) va = (int)lim; span[0].m_R = (byte)vr; span[0].m_G = (byte)vg; span[0].m_B = (byte)vb; span[0].m_A = (byte)va; r.Next((int)ESubpixelScale.subpixel_scale); g.Next((int)ESubpixelScale.subpixel_scale); b.Next((int)ESubpixelScale.subpixel_scale); a.Next((int)ESubpixelScale.subpixel_scale); ++span; --len; } }