public void GenerateColors(ColorRGBA[] outputColors, int startIndex, int x, int y, int len) { m_rgba1.Calculate(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); RGBA_Calculator pc1 = m_rgba1; RGBA_Calculator 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_Calculator 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; } var line_r = new PixelFarm.Agg.Transform.LineInterpolatorDDA(pc1.m_r, pc2.m_r, nlen, 14); var line_g = new PixelFarm.Agg.Transform.LineInterpolatorDDA(pc1.m_g, pc2.m_g, nlen, 14); var line_b = new PixelFarm.Agg.Transform.LineInterpolatorDDA(pc1.m_b, pc2.m_b, nlen, 14); var line_a = new PixelFarm.Agg.Transform.LineInterpolatorDDA(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_SHIFT); line_r.Prev(start); line_g.Prev(start); line_b.Prev(start); line_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 = line_r.y(); vg = line_g.y(); vb = line_b.y(); va = line_a.y(); if (vr < 0) { vr = 0; } else if (vr > lim) { vr = (int)lim; } if (vg < 0) { vg = 0; } else if (vg > lim) { vg = (int)lim; } if (vb < 0) { vb = 0; } else if (vb > lim) { vb = (int)lim; } if (va < 0) { va = 0; } else if (va > lim) { va = (int)lim; } outputColors[startIndex].red = (byte)vr; outputColors[startIndex].green = (byte)vg; outputColors[startIndex].blue = (byte)vb; outputColors[startIndex].alpha = (byte)va; line_r.Next(SUBPIXEL_SCALE); line_g.Next(SUBPIXEL_SCALE); line_b.Next(SUBPIXEL_SCALE); line_a.Next(SUBPIXEL_SCALE); nlen -= SUBPIXEL_SCALE; start -= SUBPIXEL_SCALE; ++startIndex; --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) { outputColors[startIndex].red = ((byte)line_r.y()); outputColors[startIndex].green = ((byte)line_g.y()); outputColors[startIndex].blue = ((byte)line_b.y()); outputColors[startIndex].alpha = ((byte)line_a.y()); line_r.Next(SUBPIXEL_SCALE); line_g.Next(SUBPIXEL_SCALE); line_b.Next(SUBPIXEL_SCALE); line_a.Next(SUBPIXEL_SCALE); nlen -= SUBPIXEL_SCALE; ++startIndex; --len; } // Ending part; checking for overflow. // Typically it's 1-2 pixels, but may be more in some cases. //------------------------- while (len != 0) { vr = line_r.y(); vg = line_g.y(); vb = line_b.y(); va = line_a.y(); if (vr < 0) { vr = 0; } else if (vr > lim) { vr = (int)lim; } if (vg < 0) { vg = 0; } else if (vg > lim) { vg = (int)lim; } if (vb < 0) { vb = 0; } else if (vb > lim) { vb = (int)lim; } if (va < 0) { va = 0; } else if (va > lim) { va = (int)lim; } outputColors[startIndex].red = ((byte)vr); outputColors[startIndex].green = ((byte)vg); outputColors[startIndex].blue = ((byte)vb); outputColors[startIndex].alpha = ((byte)va); line_r.Next(SUBPIXEL_SCALE); line_g.Next(SUBPIXEL_SCALE); line_b.Next(SUBPIXEL_SCALE); line_a.Next(SUBPIXEL_SCALE); ++startIndex; --len; } }
public void GenerateColors(Color[] outputColors, int startIndex, int x, int y, int len) { m_rgba1.Calculate(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); RGBA_Calculator pc1 = m_rgba1; RGBA_Calculator 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_Calculator 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; var line_r = new PixelFarm.Agg.Transform.LineInterpolatorDDA(pc1.m_r, pc2.m_r, nlen, 14); var line_g = new PixelFarm.Agg.Transform.LineInterpolatorDDA(pc1.m_g, pc2.m_g, nlen, 14); var line_b = new PixelFarm.Agg.Transform.LineInterpolatorDDA(pc1.m_b, pc2.m_b, nlen, 14); var line_a = new PixelFarm.Agg.Transform.LineInterpolatorDDA(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_SHIFT); line_r.Prev(start); line_g.Prev(start); line_b.Prev(start); line_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 = line_r.y(); vg = line_g.y(); vb = line_b.y(); va = line_a.y(); if (vr < 0) { vr = 0; } else if (vr > lim) { vr = (int)lim; } if (vg < 0) { vg = 0; } else if (vg > lim) { vg = (int)lim; } if (vb < 0) { vb = 0; } else if (vb > lim) { vb = (int)lim; } if (va < 0) { va = 0; } else if (va > lim) { va = (int)lim; } outputColors[startIndex].red = (byte)vr; outputColors[startIndex].green = (byte)vg; outputColors[startIndex].blue = (byte)vb; outputColors[startIndex].alpha = (byte)va; line_r.Next(SUBPIXEL_SCALE); line_g.Next(SUBPIXEL_SCALE); line_b.Next(SUBPIXEL_SCALE); line_a.Next(SUBPIXEL_SCALE); nlen -= SUBPIXEL_SCALE; start -= SUBPIXEL_SCALE; ++startIndex; --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) { outputColors[startIndex].red = ((byte)line_r.y()); outputColors[startIndex].green = ((byte)line_g.y()); outputColors[startIndex].blue = ((byte)line_b.y()); outputColors[startIndex].alpha = ((byte)line_a.y()); line_r.Next(SUBPIXEL_SCALE); line_g.Next(SUBPIXEL_SCALE); line_b.Next(SUBPIXEL_SCALE); line_a.Next(SUBPIXEL_SCALE); nlen -= SUBPIXEL_SCALE; ++startIndex; --len; } // Ending part; checking for overflow. // Typically it's 1-2 pixels, but may be more in some cases. //------------------------- while (len != 0) { vr = line_r.y(); vg = line_g.y(); vb = line_b.y(); va = line_a.y(); if (vr < 0) { vr = 0; } else if (vr > lim) { vr = (int)lim; } if (vg < 0) { vg = 0; } else if (vg > lim) { vg = (int)lim; } if (vb < 0) { vb = 0; } else if (vb > lim) { vb = (int)lim; } if (va < 0) { va = 0; } else if (va > lim) { va = (int)lim; } outputColors[startIndex].red = ((byte)vr); outputColors[startIndex].green = ((byte)vg); outputColors[startIndex].blue = ((byte)vb); outputColors[startIndex].alpha = ((byte)va); line_r.Next(SUBPIXEL_SCALE); line_g.Next(SUBPIXEL_SCALE); line_b.Next(SUBPIXEL_SCALE); line_a.Next(SUBPIXEL_SCALE); ++startIndex; --len; } }