public override void ResetSpans(int min_x, int max_x) { int max_len = max_x - min_x + 2; if (max_len > m_spans.Length) { m_spans = new ScanlineSpan[max_len]; m_covers = new byte[max_len]; } last_x = 0x7FFFFFF0; minX = min_x; last_span_index = 0; }
public override void AddCell(int x, int cover) { x -= minX; m_covers[x] = (byte)cover; if (x == last_x + 1) { m_spans[last_span_index].len++; } else { last_span_index++; m_spans[last_span_index] = new ScanlineSpan(x + minX, x); } last_x = x; }
public override void AddCell(int x, int cover) { m_covers[m_cover_index] = (byte)cover; if (x == last_x + 1 && m_spans[last_span_index].len > 0) { m_spans[last_span_index].len++; } else { last_span_index++; m_spans[last_span_index] = new ScanlineSpan((short)x, m_cover_index); } last_x = x; m_cover_index++; }
public override void AddSpan(int x, int len, int cover) { if (x == last_x + 1 && m_spans[last_span_index].len < 0 && cover == m_spans[last_span_index].cover_index) { m_spans[last_span_index].len -= (short)len; } else { m_covers[m_cover_index] = (byte)cover; last_span_index++; m_spans[last_span_index] = new ScanlineSpan((short)x, (short)(-len), m_cover_index++); } last_x = x + len - 1; }
//================================================render_scanline_aa_solid private static void RenderSolidSingleScanLine(IPixelFormat pixFormat, IScanlineCache scanLine, RGBA_Bytes color) { #if use_timers render_scanline_aa_solidTimer.Start(); #endif int y = scanLine.Y; uint num_spans = scanLine.NumSpans; ScanlineSpan scanlineSpan = scanLine.Begin(); byte[] ManagedCoversArray = scanLine.Covers; unsafe { fixed (byte* pCovers = ManagedCoversArray) { for (; ; ) { int x = scanlineSpan.X; if (scanlineSpan.Len > 0) { #if use_timers render_scanline_aa_solid_blend_solid_hspan.Start(); #endif pixFormat.BlendSolidHSpan(x, y, (uint)scanlineSpan.Len, color, &pCovers[scanlineSpan.CoverIndex]); #if use_timers render_scanline_aa_solid_blend_solid_hspan.Stop(); #endif } else { #if use_timers render_scanline_aa_solid_blend_hline.Start(); #endif pixFormat.BlendHLine(x, y, (x - (int)scanlineSpan.Len - 1), color, pCovers[scanlineSpan.CoverIndex]); #if use_timers render_scanline_aa_solid_blend_hline.Stop(); #endif } if (--num_spans == 0) break; scanlineSpan = scanLine.GetNextScanlineSpan(); } } } #if use_timers render_scanline_aa_solidTimer.Stop(); #endif }
public override void AddSpan(int x, int len, int cover) { x -= minX; for (int i = 0; i < len; i++) { m_covers[x + i] = (byte)cover; } if (x == last_x + 1) { m_spans[last_span_index].len += (short)len; } else { last_span_index++; m_spans[last_span_index] = new ScanlineSpan(x + minX, len, x); } last_x = x + (int)len - 1; }
//======================================================render_scanline_aa private static void GenerateAndRenderSingleScanline(IScanlineCache sl, IPixelFormat ren, SpanAllocator alloc, ISpanGenerator<T> span_gen) { int y = sl.Y; uint num_spans = sl.NumSpans; ScanlineSpan scanlineSpan = sl.Begin(); byte[] ManagedCoversArray = sl.Covers; unsafe { fixed (byte* pCovers = ManagedCoversArray) { for (; ; ) { int x = scanlineSpan.X; int len = scanlineSpan.Len; if (len < 0) len = -len; if (tempSpanColors.Capacity() < len) { tempSpanColors.Allocate((uint)(len)); } fixed (RGBA_Bytes* pColors = tempSpanColors.Array) { span_gen.Generate(pColors, x, y, (uint)len); #if use_timers blend_color_hspan.Start(); #endif ren.BlendColorHSpan(x, y, (uint)len, pColors, (scanlineSpan.Len < 0) ? null : &pCovers[scanlineSpan.CoverIndex], pCovers[scanlineSpan.CoverIndex]); #if use_timers blend_color_hspan.Stop(); #endif } if (--num_spans == 0) break; scanlineSpan = sl.GetNextScanlineSpan(); } } } }
void SubPixRender(IImageReaderWriter destImage, Scanline scanline, ColorRGBA color) { int y = scanline.Y; int num_spans = scanline.SpanCount; byte[] covers = scanline.GetCovers(); ScanlineRasterizer ras = gfx.ScanlineRasterizer; var rasToBmp = gfx.ScanlineRasToDestBitmap; ColorRGBA prevColor = ColorRGBA.White; for (int i = 0; i <= num_spans; ++i) { //render span by span ScanlineSpan span = scanline.GetSpan(i); int x = span.x; int num_pix = span.len; int coverIndex = span.cover_index; //test subpixel rendering concept //---------------------------------------------------- int prev_cover = 0; while (num_pix > 0) { int coverageValue = covers[coverIndex++]; if (coverageValue >= 255) { //100% cover ColorRGBA newc = new ColorRGBA(color.red, color.green, color.blue); prevColor = newc; int a = (coverageValue * color.Alpha0To255) >> 8; m_square.Draw(rasToBmp, ras, m_sl, destImage, new ColorRGBA(newc, a), x, y); prev_cover = 255;//full } else { //check direction : bool isLeftToRight = coverageValue >= prev_cover; prev_cover = coverageValue; byte c_r, c_g, c_b; float subpix_percent = ((float)(coverageValue) / 256f); if (coverageValue < cover_1_3) { if (isLeftToRight) { c_r = 255; c_g = 255; c_b = (byte)(255 - (255f * (subpix_percent))); } else { c_r = (byte)(255 - (255f * (subpix_percent))); c_g = 255; c_b = 255; } ColorRGBA newc = prevColor = new ColorRGBA(c_r, c_g, c_b); int a = (coverageValue * color.Alpha0To255) >> 8; m_square.Draw(rasToBmp, ras, m_sl, destImage, new ColorRGBA(newc, a), x, y); } else if (coverageValue < cover_2_3) { if (isLeftToRight) { c_r = prevColor.blue; c_g = (byte)(255 - (255f * (subpix_percent))); c_b = color.blue;// (byte)(255 - (255f * (subpix_percent)));// color.blue; } else { c_r = color.blue;// (byte)(255 - (255f * (subpix_percent))); //color.blue; c_g = (byte)(255 - (255f * (subpix_percent))); c_b = 255; } ColorRGBA newc = prevColor = new ColorRGBA(c_r, c_g, c_b); int a = (coverageValue * color.Alpha0To255) >> 8; m_square.Draw(rasToBmp, ras, m_sl, destImage, new ColorRGBA(newc, a), x, y); } else { //cover > 2/3 but not full if (isLeftToRight) { c_r = (byte)(255 - (255f * (subpix_percent))); c_g = color.green; c_b = color.blue; } else { c_r = prevColor.green; c_g = prevColor.blue; c_b = (byte)(255 - (255f * (subpix_percent))); } ColorRGBA newc = prevColor = new ColorRGBA(c_r, c_g, c_b); int a = (coverageValue * color.Alpha0To255) >> 8; m_square.Draw(rasToBmp, ras, m_sl, destImage, new ColorRGBA(newc, a), x, y); } } ++x; --num_pix; } } }
void SubPixRender(IImageReaderWriter destImage, Scanline scanline, Color color) { int y = scanline.Y; int num_spans = scanline.SpanCount; byte[] covers = scanline.GetCovers(); ScanlineRasterizer ras = gfx.ScanlineRasterizer; var rasToBmp = gfx.ScanlineRasToDestBitmap; //------------------------------------------ Color bgColor = Color.White; float cb_R = bgColor.R / 255f; float cb_G = bgColor.G / 255f; float cb_B = bgColor.B / 255f; float cf_R = color.R / 255f; float cf_G = color.G / 255f; float cf_B = color.B / 255f; //------------------------------------------ for (int i = 0; i <= num_spans; ++i) { //render span by span ScanlineSpan span = scanline.GetSpan(i); int x = span.x; int num_pix = span.len; int coverIndex = span.cover_index; //test subpixel rendering concept //---------------------------------------------------- int prev_cover = 0; while (num_pix > 0) { byte coverageValue = covers[coverIndex++]; if (coverageValue >= 255) { //100% cover int a = (coverageValue * color.Alpha0To255) >> 8; m_square.Draw(rasToBmp, ras, m_sl, destImage, Color.FromArgb(a, Color.FromArgb(color.red, color.green, color.blue)), x, y); prev_cover = 255;//full } else { //check direction : bool isUpHill = (coverageValue % 2) > 0; //-------------------------------------------------------------------- //TODO: review here //in somecase, demo3, isUpHill2 != isUpHill //but we skip it, because we don't want context color around the point //so when we use in fragment shader we can pick up a single color //and determine what color it should be bool isUpHill2 = coverageValue > prev_cover; if (isUpHill != isUpHill2) { } //-------------------------------------------------------------------- prev_cover = coverageValue; byte c_r, c_g, c_b; float subpix_percent = ((float)(coverageValue) / 256f); if (coverageValue < cover_1_3) { //assume LCD color arrangement is RGB if (isUpHill) { c_r = bgColor.R; c_g = bgColor.G; c_b = (byte)(mix(cb_B, cf_B, subpix_percent) * 255); } else { c_r = (byte)(mix(cb_R, cf_R, subpix_percent) * 255); c_g = bgColor.G; c_b = bgColor.B; } int a = (coverageValue * color.Alpha0To255) >> 8; m_square.Draw(rasToBmp, ras, m_sl, destImage, Color.FromArgb(a, Color.FromArgb(c_r, c_g, c_b)), x, y); } else if (coverageValue < cover_2_3) { if (isUpHill) { c_r = bgColor.R; c_g = (byte)(mix(cb_G, cf_G, subpix_percent) * 255); c_b = (byte)(mix(cb_B, cf_B, 1) * 255); } else { c_r = (byte)(mix(cb_R, cf_R, 1) * 255); c_g = (byte)(mix(cb_G, cf_G, subpix_percent) * 255); c_b = bgColor.B; } int a = (coverageValue * color.Alpha0To255) >> 8; m_square.Draw(rasToBmp, ras, m_sl, destImage, Color.FromArgb(a, Color.FromArgb(c_r, c_g, c_b)), x, y); } else { //cover > 2/3 but not full if (isUpHill) { c_r = (byte)(mix(cb_R, cf_R, subpix_percent) * 255); c_g = (byte)(mix(cb_G, cf_G, 1) * 255); c_b = (byte)(mix(cb_B, cf_B, 1) * 255); } else { c_r = (byte)(mix(cb_R, cf_R, 1) * 255); c_g = (byte)(mix(cb_G, cf_G, 1) * 255); c_b = (byte)(mix(cb_B, cf_B, subpix_percent) * 255); } int a = (coverageValue * color.Alpha0To255) >> 8; m_square.Draw(rasToBmp, ras, m_sl, destImage, Color.FromArgb(a, Color.FromArgb(c_r, c_g, c_b)), x, y); } } ++x; --num_pix; } } }
public static void RenderCompound(RasterizerCompoundAA<T> ras, IScanlineCache sl_aa, IScanlineCache sl_bin, IPixelFormat pixelFormat, SpanAllocator alloc, IStyleHandler sh) { #if true unsafe { if (ras.RewindScanlines()) { int min_x = ras.MinX; int len = ras.MaxX - min_x + 2; sl_aa.Reset(min_x, ras.MaxX); sl_bin.Reset(min_x, ras.MaxX); //typedef typename BaseRenderer::color_type color_type; ArrayPOD<RGBA_Bytes> color_span = alloc.Allocate((uint)len * 2); byte[] ManagedCoversArray = sl_aa.Covers; fixed (byte* pCovers = ManagedCoversArray) { fixed (RGBA_Bytes* pColorSpan = color_span.Array) { int mix_bufferOffset = len; uint num_spans; uint num_styles; uint style; bool solid; while ((num_styles = ras.SweepStyles()) > 0) { if (num_styles == 1) { // Optimization for a single style. Happens often //------------------------- if (ras.SweepScanline(sl_aa, 0)) { style = ras.Style(0); if (sh.IsSolid(style)) { // Just solid fill //----------------------- RenderSolidSingleScanLine(pixelFormat, sl_aa, sh.Color(style)); } else { // Arbitrary span generator //----------------------- ScanlineSpan span_aa = sl_aa.Begin(); num_spans = sl_aa.NumSpans; for (; ; ) { len = span_aa.Len; sh.GenerateSpan(pColorSpan, span_aa.X, sl_aa.Y, (uint)len, style); pixelFormat.BlendColorHSpan(span_aa.X, sl_aa.Y, (uint)span_aa.Len, pColorSpan, &pCovers[span_aa.CoverIndex], 0); if (--num_spans == 0) break; span_aa = sl_aa.GetNextScanlineSpan(); } } } } else // there are multiple styles { if (ras.SweepScanline(sl_bin, -1)) { // Clear the spans of the mix_buffer //-------------------- ScanlineSpan span_bin = sl_bin.Begin(); num_spans = sl_bin.NumSpans; for (; ; ) { Basics.MemClear((byte*)&pColorSpan[mix_bufferOffset + span_bin.X - min_x], span_bin.Len * sizeof(RGBA_Bytes)); if (--num_spans == 0) break; span_bin = sl_bin.GetNextScanlineSpan(); } for (uint i = 0; i < num_styles; i++) { style = ras.Style(i); solid = sh.IsSolid(style); if (ras.SweepScanline(sl_aa, (int)i)) { //IColorType* colors; //IColorType* cspan; //typename ScanlineAA::cover_type* covers; ScanlineSpan span_aa = sl_aa.Begin(); num_spans = sl_aa.NumSpans; if (solid) { // Just solid fill //----------------------- for (; ; ) { RGBA_Bytes c = sh.Color(style); len = span_aa.Len; RGBA_Bytes* colors = &pColorSpan[mix_bufferOffset + span_aa.X - min_x]; byte* covers = &pCovers[span_aa.CoverIndex]; do { if (*covers == CoverFull) { *colors = c; } else { colors->Add(c, *covers); } ++colors; ++covers; } while (--len != 0); if (--num_spans == 0) break; span_aa = sl_aa.GetNextScanlineSpan(); } } else { // Arbitrary span generator //----------------------- for (; ; ) { len = span_aa.Len; RGBA_Bytes* colors = &pColorSpan[mix_bufferOffset + span_aa.X - min_x]; RGBA_Bytes* cspan = pColorSpan; sh.GenerateSpan(cspan, span_aa.X, sl_aa.Y, (uint)len, style); byte* covers = &pCovers[span_aa.CoverIndex]; do { if (*covers == CoverFull) { *colors = *cspan; } else { colors->Add(*cspan, *covers); } ++cspan; ++colors; ++covers; } while (--len != 0); if (--num_spans == 0) break; span_aa = sl_aa.GetNextScanlineSpan(); } } } } // Emit the blended result as a color hspan //------------------------- span_bin = sl_bin.Begin(); num_spans = sl_bin.NumSpans; for (; ; ) { pixelFormat.BlendColorHSpan(span_bin.X, sl_bin.Y, (uint)span_bin.Len, &pColorSpan[mix_bufferOffset + span_bin.X - min_x], null, CoverFull); if (--num_spans == 0) break; span_bin = sl_bin.GetNextScanlineSpan(); } } // if(ras.sweep_scanline(sl_bin, -1)) } // if(num_styles == 1) ... else } // while((num_styles = ras.sweep_styles()) > 0) } } } // if(ras.rewind_scanlines()) #endif } }