public void generate(RGBA_Bytes[] span, int spanIndex, int x, int y, int len) { m_rgba1.calc(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.calc(y + m_rgba2.m_1dy); } else { // Upper part (second subtriangle) m_rgba3.calc(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; dda_line_interpolator r = new dda_line_interpolator(pc1.m_r, pc2.m_r, nlen, 14); dda_line_interpolator g = new dda_line_interpolator(pc1.m_g, pc2.m_g, nlen, 14); dda_line_interpolator b = new dda_line_interpolator(pc1.m_b, pc2.m_b, nlen, 14); dda_line_interpolator a = new dda_line_interpolator(pc1.m_a, pc2.m_a, 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)subpixel_scale_e.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[spanIndex].red = (byte)vr; span[spanIndex].green = (byte)vg; span[spanIndex].blue = (byte)vb; span[spanIndex].alpha = (byte)va; r.Next((int)subpixel_scale_e.subpixel_scale); g.Next((int)subpixel_scale_e.subpixel_scale); b.Next((int)subpixel_scale_e.subpixel_scale); a.Next((int)subpixel_scale_e.subpixel_scale); nlen -= (int)subpixel_scale_e.subpixel_scale; start -= (int)subpixel_scale_e.subpixel_scale; ++spanIndex; --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[spanIndex].red = ((byte)r.y()); span[spanIndex].green = ((byte)g.y()); span[spanIndex].blue = ((byte)b.y()); span[spanIndex].alpha = ((byte)a.y()); r.Next((int)subpixel_scale_e.subpixel_scale); g.Next((int)subpixel_scale_e.subpixel_scale); b.Next((int)subpixel_scale_e.subpixel_scale); a.Next((int)subpixel_scale_e.subpixel_scale); nlen -= (int)subpixel_scale_e.subpixel_scale; ++spanIndex; --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[spanIndex].red = ((byte)vr); span[spanIndex].green = ((byte)vg); span[spanIndex].blue = ((byte)vb); span[spanIndex].alpha = ((byte)va); r.Next((int)subpixel_scale_e.subpixel_scale); g.Next((int)subpixel_scale_e.subpixel_scale); b.Next((int)subpixel_scale_e.subpixel_scale); a.Next((int)subpixel_scale_e.subpixel_scale); ++spanIndex; --len; } }
public void generate(Color[] span, int spanIndex, int x, int y, int len) { m_rgba1.calc(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.calc(y + m_rgba2.m_1dy); } else { // Upper part (second subtriangle) m_rgba3.calc(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; } dda_line_interpolator r = new dda_line_interpolator(pc1.m_r, pc2.m_r, nlen, 14); dda_line_interpolator g = new dda_line_interpolator(pc1.m_g, pc2.m_g, nlen, 14); dda_line_interpolator b = new dda_line_interpolator(pc1.m_b, pc2.m_b, nlen, 14); dda_line_interpolator a = new dda_line_interpolator(pc1.m_a, pc2.m_a, 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)subpixel_scale_e.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[spanIndex].red = (byte)vr; span[spanIndex].green = (byte)vg; span[spanIndex].blue = (byte)vb; span[spanIndex].alpha = (byte)va; r.Next((int)subpixel_scale_e.subpixel_scale); g.Next((int)subpixel_scale_e.subpixel_scale); b.Next((int)subpixel_scale_e.subpixel_scale); a.Next((int)subpixel_scale_e.subpixel_scale); nlen -= (int)subpixel_scale_e.subpixel_scale; start -= (int)subpixel_scale_e.subpixel_scale; ++spanIndex; --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[spanIndex].red = ((byte)r.y()); span[spanIndex].green = ((byte)g.y()); span[spanIndex].blue = ((byte)b.y()); span[spanIndex].alpha = ((byte)a.y()); r.Next((int)subpixel_scale_e.subpixel_scale); g.Next((int)subpixel_scale_e.subpixel_scale); b.Next((int)subpixel_scale_e.subpixel_scale); a.Next((int)subpixel_scale_e.subpixel_scale); nlen -= (int)subpixel_scale_e.subpixel_scale; ++spanIndex; --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[spanIndex].red = ((byte)vr); span[spanIndex].green = ((byte)vg); span[spanIndex].blue = ((byte)vb); span[spanIndex].alpha = ((byte)va); r.Next((int)subpixel_scale_e.subpixel_scale); g.Next((int)subpixel_scale_e.subpixel_scale); b.Next((int)subpixel_scale_e.subpixel_scale); a.Next((int)subpixel_scale_e.subpixel_scale); ++spanIndex; --len; } }