ScanlineRenderer.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. using MatterHackers.Agg.Image;
  2. using MatterHackers.Agg.VertexSource;
  3. namespace MatterHackers.Agg
  4. {
  5. public class ScanlineRenderer
  6. {
  7. private VectorPOD<Color> tempSpanColors = new VectorPOD<Color>();
  8. private VectorPOD<ColorF> tempSpanColorsFloats = new VectorPOD<ColorF>();
  9. public void RenderSolid(IImageByte destImage, IRasterizer rasterizer, IScanlineCache scanLine, Color color)
  10. {
  11. if (rasterizer.rewind_scanlines())
  12. {
  13. scanLine.reset(rasterizer.min_x(), rasterizer.max_x());
  14. while (rasterizer.sweep_scanline(scanLine))
  15. {
  16. RenderSolidSingleScanLine(destImage, scanLine, color);
  17. }
  18. }
  19. }
  20. public void RenderSolid(IImageFloat destImage, IRasterizer rasterizer, IScanlineCache scanLine, ColorF color)
  21. {
  22. if (rasterizer.rewind_scanlines())
  23. {
  24. scanLine.reset(rasterizer.min_x(), rasterizer.max_x());
  25. while (rasterizer.sweep_scanline(scanLine))
  26. {
  27. RenderSolidSingleScanLine(destImage, scanLine, color);
  28. }
  29. }
  30. }
  31. protected virtual void RenderSolidSingleScanLine(IImageByte destImage, IScanlineCache scanLine, Color color)
  32. {
  33. int y = scanLine.y();
  34. int num_spans = scanLine.num_spans();
  35. ScanlineSpan scanlineSpan = scanLine.begin();
  36. byte[] ManagedCoversArray = scanLine.GetCovers();
  37. for (; ; )
  38. {
  39. int x = scanlineSpan.x;
  40. if (scanlineSpan.len > 0)
  41. {
  42. destImage.blend_solid_hspan(x, y, scanlineSpan.len, color, ManagedCoversArray, scanlineSpan.cover_index);
  43. }
  44. else
  45. {
  46. int x2 = (x - (int)scanlineSpan.len - 1);
  47. destImage.blend_hline(x, y, x2, color, ManagedCoversArray[scanlineSpan.cover_index]);
  48. }
  49. if (--num_spans == 0) break;
  50. scanlineSpan = scanLine.GetNextScanlineSpan();
  51. }
  52. }
  53. private void RenderSolidSingleScanLine(IImageFloat destImage, IScanlineCache scanLine, ColorF color)
  54. {
  55. int y = scanLine.y();
  56. int num_spans = scanLine.num_spans();
  57. ScanlineSpan scanlineSpan = scanLine.begin();
  58. byte[] ManagedCoversArray = scanLine.GetCovers();
  59. for (; ; )
  60. {
  61. int x = scanlineSpan.x;
  62. if (scanlineSpan.len > 0)
  63. {
  64. destImage.blend_solid_hspan(x, y, scanlineSpan.len, color, ManagedCoversArray, scanlineSpan.cover_index);
  65. }
  66. else
  67. {
  68. int x2 = (x - (int)scanlineSpan.len - 1);
  69. destImage.blend_hline(x, y, x2, color, ManagedCoversArray[scanlineSpan.cover_index]);
  70. }
  71. if (--num_spans == 0) break;
  72. scanlineSpan = scanLine.GetNextScanlineSpan();
  73. }
  74. }
  75. private void GenerateAndRenderSingleScanline(IScanlineCache scanLineCache, IImageByte destImage, span_allocator alloc, ISpanGenerator span_gen)
  76. {
  77. int y = scanLineCache.y();
  78. int num_spans = scanLineCache.num_spans();
  79. ScanlineSpan scanlineSpan = scanLineCache.begin();
  80. byte[] ManagedCoversArray = scanLineCache.GetCovers();
  81. for (; ; )
  82. {
  83. int x = scanlineSpan.x;
  84. int len = scanlineSpan.len;
  85. if (len < 0) len = -len;
  86. if (tempSpanColors.Capacity() < len)
  87. {
  88. tempSpanColors.Capacity(len);
  89. }
  90. span_gen.generate(tempSpanColors.Array, 0, x, y, len);
  91. bool useFirstCoverForAll = scanlineSpan.len < 0;
  92. destImage.blend_color_hspan(x, y, len, tempSpanColors.Array, 0, ManagedCoversArray, scanlineSpan.cover_index, useFirstCoverForAll);
  93. if (--num_spans == 0) break;
  94. scanlineSpan = scanLineCache.GetNextScanlineSpan();
  95. }
  96. }
  97. private void GenerateAndRenderSingleScanline(IScanlineCache scanLineCache, IImageFloat destImageFloat, span_allocator alloc, ISpanGeneratorFloat span_gen)
  98. {
  99. int y = scanLineCache.y();
  100. int num_spans = scanLineCache.num_spans();
  101. ScanlineSpan scanlineSpan = scanLineCache.begin();
  102. byte[] ManagedCoversArray = scanLineCache.GetCovers();
  103. for (; ; )
  104. {
  105. int x = scanlineSpan.x;
  106. int len = scanlineSpan.len;
  107. if (len < 0) len = -len;
  108. if (tempSpanColorsFloats.Capacity() < len)
  109. {
  110. tempSpanColorsFloats.Capacity(len);
  111. }
  112. span_gen.generate(tempSpanColorsFloats.Array, 0, x, y, len);
  113. bool useFirstCoverForAll = scanlineSpan.len < 0;
  114. destImageFloat.blend_color_hspan(x, y, len, tempSpanColorsFloats.Array, 0, ManagedCoversArray, scanlineSpan.cover_index, useFirstCoverForAll);
  115. if (--num_spans == 0) break;
  116. scanlineSpan = scanLineCache.GetNextScanlineSpan();
  117. }
  118. }
  119. public void GenerateAndRender(IRasterizer rasterizer, IScanlineCache scanlineCache, IImageByte destImage, span_allocator spanAllocator, ISpanGenerator spanGenerator)
  120. {
  121. if (rasterizer.rewind_scanlines())
  122. {
  123. scanlineCache.reset(rasterizer.min_x(), rasterizer.max_x());
  124. spanGenerator.prepare();
  125. while (rasterizer.sweep_scanline(scanlineCache))
  126. {
  127. GenerateAndRenderSingleScanline(scanlineCache, destImage, spanAllocator, spanGenerator);
  128. }
  129. }
  130. }
  131. public void GenerateAndRender(IRasterizer rasterizer, IScanlineCache scanlineCache, IImageFloat destImage, span_allocator spanAllocator, ISpanGeneratorFloat spanGenerator)
  132. {
  133. if (rasterizer.rewind_scanlines())
  134. {
  135. scanlineCache.reset(rasterizer.min_x(), rasterizer.max_x());
  136. spanGenerator.prepare();
  137. while (rasterizer.sweep_scanline(scanlineCache))
  138. {
  139. GenerateAndRenderSingleScanline(scanlineCache, destImage, spanAllocator, spanGenerator);
  140. }
  141. }
  142. }
  143. public void RenderCompound(rasterizer_compound_aa ras, IScanlineCache sl_aa, IScanlineCache sl_bin, IImageByte imageFormat, span_allocator alloc, IStyleHandler sh)
  144. {
  145. #if false
  146. unsafe
  147. {
  148. if (ras.rewind_scanlines())
  149. {
  150. int min_x = ras.min_x();
  151. int len = ras.max_x() - min_x + 2;
  152. sl_aa.reset(min_x, ras.max_x());
  153. sl_bin.reset(min_x, ras.max_x());
  154. //typedef typename BaseRenderer::color_type color_type;
  155. ArrayPOD<RGBA_Bytes> color_span = alloc.allocate((int)len * 2);
  156. byte[] ManagedCoversArray = sl_aa.GetCovers();
  157. fixed (byte* pCovers = ManagedCoversArray)
  158. {
  159. fixed (RGBA_Bytes* pColorSpan = color_span.Array)
  160. {
  161. int mix_bufferOffset = len;
  162. int num_spans;
  163. int num_styles;
  164. int style;
  165. bool solid;
  166. while ((num_styles = ras.sweep_styles()) > 0)
  167. {
  168. if (num_styles == 1)
  169. {
  170. // Optimization for a single style. Happens often
  171. //-------------------------
  172. if (ras.sweep_scanline(sl_aa, 0))
  173. {
  174. style = ras.style(0);
  175. if (sh.is_solid(style))
  176. {
  177. // Just solid fill
  178. //-----------------------
  179. RenderSolidSingleScanLine(imageFormat, sl_aa, sh.color(style));
  180. }
  181. else
  182. {
  183. // Arbitrary span generator
  184. //-----------------------
  185. ScanlineSpan span_aa = sl_aa.Begin();
  186. num_spans = sl_aa.num_spans();
  187. for (; ; )
  188. {
  189. len = span_aa.len;
  190. sh.generate_span(pColorSpan,
  191. span_aa.x,
  192. sl_aa.y(),
  193. (int)len,
  194. style);
  195. imageFormat.blend_color_hspan(span_aa.x,
  196. sl_aa.y(),
  197. (int)span_aa.len,
  198. pColorSpan,
  199. &pCovers[span_aa.cover_index], 0);
  200. if (--num_spans == 0) break;
  201. span_aa = sl_aa.GetNextScanlineSpan();
  202. }
  203. }
  204. }
  205. }
  206. else // there are multiple styles
  207. {
  208. if (ras.sweep_scanline(sl_bin, -1))
  209. {
  210. // Clear the spans of the mix_buffer
  211. //--------------------
  212. ScanlineSpan span_bin = sl_bin.Begin();
  213. num_spans = sl_bin.num_spans();
  214. for (; ; )
  215. {
  216. agg_basics.MemClear((byte*)&pColorSpan[mix_bufferOffset + span_bin.x - min_x],
  217. span_bin.len * sizeof(RGBA_Bytes));
  218. if (--num_spans == 0) break;
  219. span_bin = sl_bin.GetNextScanlineSpan();
  220. }
  221. for (int i = 0; i < num_styles; i++)
  222. {
  223. style = ras.style(i);
  224. solid = sh.is_solid(style);
  225. if (ras.sweep_scanline(sl_aa, (int)i))
  226. {
  227. //IColorType* colors;
  228. //IColorType* cspan;
  229. //typename ScanlineAA::cover_type* covers;
  230. ScanlineSpan span_aa = sl_aa.Begin();
  231. num_spans = sl_aa.num_spans();
  232. if (solid)
  233. {
  234. // Just solid fill
  235. //-----------------------
  236. for (; ; )
  237. {
  238. RGBA_Bytes c = sh.color(style);
  239. len = span_aa.len;
  240. RGBA_Bytes* colors = &pColorSpan[mix_bufferOffset + span_aa.x - min_x];
  241. byte* covers = &pCovers[span_aa.cover_index];
  242. do
  243. {
  244. if (*covers == cover_full)
  245. {
  246. *colors = c;
  247. }
  248. else
  249. {
  250. colors->add(c, *covers);
  251. }
  252. ++colors;
  253. ++covers;
  254. }
  255. while (--len != 0);
  256. if (--num_spans == 0) break;
  257. span_aa = sl_aa.GetNextScanlineSpan();
  258. }
  259. }
  260. else
  261. {
  262. // Arbitrary span generator
  263. //-----------------------
  264. for (; ; )
  265. {
  266. len = span_aa.len;
  267. RGBA_Bytes* colors = &pColorSpan[mix_bufferOffset + span_aa.x - min_x];
  268. RGBA_Bytes* cspan = pColorSpan;
  269. sh.generate_span(cspan,
  270. span_aa.x,
  271. sl_aa.y(),
  272. (int)len,
  273. style);
  274. byte* covers = &pCovers[span_aa.cover_index];
  275. do
  276. {
  277. if (*covers == cover_full)
  278. {
  279. *colors = *cspan;
  280. }
  281. else
  282. {
  283. colors->add(*cspan, *covers);
  284. }
  285. ++cspan;
  286. ++colors;
  287. ++covers;
  288. }
  289. while (--len != 0);
  290. if (--num_spans == 0) break;
  291. span_aa = sl_aa.GetNextScanlineSpan();
  292. }
  293. }
  294. }
  295. }
  296. // Emit the blended result as a color hspan
  297. //-------------------------
  298. span_bin = sl_bin.Begin();
  299. num_spans = sl_bin.num_spans();
  300. for (; ; )
  301. {
  302. imageFormat.blend_color_hspan(span_bin.x,
  303. sl_bin.y(),
  304. (int)span_bin.len,
  305. &pColorSpan[mix_bufferOffset + span_bin.x - min_x],
  306. null,
  307. cover_full);
  308. if (--num_spans == 0) break;
  309. span_bin = sl_bin.GetNextScanlineSpan();
  310. }
  311. } // if(ras.sweep_scanline(sl_bin, -1))
  312. } // if(num_styles == 1) ... else
  313. } // while((num_styles = ras.sweep_styles()) > 0)
  314. }
  315. }
  316. } // if(ras.rewind_scanlines())
  317. }
  318. #endif
  319. }
  320. }
  321. }