SurfaceBoxBaseRenderer.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace SmartCoalApplication.Core
  8. {
  9. public sealed class SurfaceBoxBaseRenderer : SurfaceBoxRenderer
  10. {
  11. private Surface source;
  12. private RenderDelegate renderDelegate;
  13. public Surface Source
  14. {
  15. get
  16. {
  17. return this.source;
  18. }
  19. set
  20. {
  21. this.source = value;
  22. Flush();
  23. }
  24. }
  25. private void Flush()
  26. {
  27. this.renderDelegate = null;
  28. }
  29. protected override void OnVisibleChanged()
  30. {
  31. Invalidate();
  32. }
  33. private void ChooseRenderDelegate()
  34. {
  35. if (SourceSize.Width > DestinationSize.Width)
  36. {
  37. // zoom out
  38. this.renderDelegate = new RenderDelegate(RenderZoomOutRotatedGridMultisampling);
  39. }
  40. else if (SourceSize == DestinationSize)
  41. {
  42. // zoom 100%
  43. this.renderDelegate = new RenderDelegate(RenderOneToOne);
  44. }
  45. else if (SourceSize.Width < DestinationSize.Width)
  46. {
  47. // zoom in
  48. this.renderDelegate = new RenderDelegate(RenderZoomInNearestNeighbor);
  49. }
  50. }
  51. public override void OnDestinationSizeChanged()
  52. {
  53. ChooseRenderDelegate();
  54. this.OwnerList.InvalidateLookups();
  55. base.OnDestinationSizeChanged();
  56. }
  57. public override void OnSourceSizeChanged()
  58. {
  59. ChooseRenderDelegate();
  60. this.OwnerList.InvalidateLookups();
  61. base.OnSourceSizeChanged();
  62. }
  63. public static void RenderOneToOne(Surface dst, Surface source, Point offset)
  64. {
  65. unsafe
  66. {
  67. Rectangle srcRect = new Rectangle(offset, dst.Size);
  68. srcRect.Intersect(source.Bounds);
  69. for (int dstRow = 0; dstRow < srcRect.Height; ++dstRow)
  70. {
  71. ColorBgra* dstRowPtr = dst.GetRowAddressUnchecked(dstRow);
  72. ColorBgra* srcRowPtr = source.GetPointAddressUnchecked(offset.X, dstRow + offset.Y);
  73. int dstCol = offset.X;
  74. int dstColEnd = offset.X + srcRect.Width;
  75. int checkerY = dstRow + offset.Y;
  76. while (dstCol < dstColEnd)
  77. {
  78. int b = srcRowPtr->B;
  79. int g = srcRowPtr->G;
  80. int r = srcRowPtr->R;
  81. int a = srcRowPtr->A;
  82. // Blend it over the checkerboard background
  83. int v = (((dstCol ^ checkerY) & 8) << 3) + 191;
  84. a = a + (a >> 7);
  85. int vmia = v * (256 - a);
  86. r = ((r * a) + vmia) >> 8;
  87. g = ((g * a) + vmia) >> 8;
  88. b = ((b * a) + vmia) >> 8;
  89. dstRowPtr->Bgra = (uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)255 << 24);
  90. ++dstRowPtr;
  91. ++srcRowPtr;
  92. ++dstCol;
  93. }
  94. }
  95. }
  96. }
  97. private void RenderOneToOne(Surface dst, Point offset)
  98. {
  99. RenderOneToOne(dst, this.source, offset);
  100. }
  101. private void RenderZoomInNearestNeighbor(Surface dst, Point offset)
  102. {
  103. unsafe
  104. {
  105. int[] d2SLookupY = OwnerList.Dst2SrcLookupY;
  106. int[] d2SLookupX = OwnerList.Dst2SrcLookupX;
  107. for (int dstRow = 0; dstRow < dst.Height; ++dstRow)
  108. {
  109. int nnY = dstRow + offset.Y;
  110. int srcY = d2SLookupY[nnY];
  111. ColorBgra* dstPtr = dst.GetRowAddressUnchecked(dstRow);
  112. ColorBgra* srcRow = this.source.GetRowAddressUnchecked(srcY);
  113. for (int dstCol = 0; dstCol < dst.Width; ++dstCol)
  114. {
  115. int nnX = dstCol + offset.X;
  116. int srcX = d2SLookupX[nnX];
  117. ColorBgra src = *(srcRow + srcX);
  118. int b = src.B;
  119. int g = src.G;
  120. int r = src.R;
  121. int a = src.A;
  122. // Blend it over the checkerboard background
  123. int v = (((dstCol + offset.X) ^ (dstRow + offset.Y)) & 8) * 8 + 191;
  124. a = a + (a >> 7);
  125. int vmia = v * (256 - a);
  126. r = ((r * a) + vmia) >> 8;
  127. g = ((g * a) + vmia) >> 8;
  128. b = ((b * a) + vmia) >> 8;
  129. dstPtr->Bgra = (uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)255 << 24);
  130. ++dstPtr;
  131. }
  132. }
  133. }
  134. }
  135. public static void RenderZoomOutRotatedGridMultisampling(Surface dst, Surface source, Point offset, Size destinationSize)
  136. {
  137. unsafe
  138. {
  139. const int fpShift = 12;
  140. const int fpFactor = (1 << fpShift);
  141. Size sourceSize = source.Size;
  142. long fDstLeftLong = ((long)offset.X * fpFactor * (long)sourceSize.Width) / (long)destinationSize.Width;
  143. long fDstTopLong = ((long)offset.Y * fpFactor * (long)sourceSize.Height) / (long)destinationSize.Height;
  144. long fDstRightLong = ((long)(offset.X + dst.Width) * fpFactor * (long)sourceSize.Width) / (long)destinationSize.Width;
  145. long fDstBottomLong = ((long)(offset.Y + dst.Height) * fpFactor * (long)sourceSize.Height) / (long)destinationSize.Height;
  146. int fDstLeft = (int)fDstLeftLong;
  147. int fDstTop = (int)fDstTopLong;
  148. int fDstRight = (int)fDstRightLong;
  149. int fDstBottom = (int)fDstBottomLong;
  150. int dx = (fDstRight - fDstLeft) / dst.Width;
  151. int dy = (fDstBottom - fDstTop) / dst.Height;
  152. for (int dstRow = 0, fDstY = fDstTop;
  153. dstRow < dst.Height && fDstY < fDstBottom;
  154. ++dstRow, fDstY += dy)
  155. {
  156. int srcY1 = fDstY >> fpShift; // y
  157. int srcY2 = (fDstY + (dy >> 2)) >> fpShift; // y + 0.25
  158. int srcY3 = (fDstY + (dy >> 1)) >> fpShift; // y + 0.50
  159. int srcY4 = (fDstY + (dy >> 1) + (dy >> 2)) >> fpShift; // y + 0.75
  160. ColorBgra* src1 = source.GetRowAddressUnchecked(srcY1);
  161. ColorBgra* src2 = source.GetRowAddressUnchecked(srcY2);
  162. ColorBgra* src3 = source.GetRowAddressUnchecked(srcY3);
  163. ColorBgra* src4 = source.GetRowAddressUnchecked(srcY4);
  164. ColorBgra* dstPtr = dst.GetRowAddressUnchecked(dstRow);
  165. int checkerY = dstRow + offset.Y;
  166. int checkerX = offset.X;
  167. int maxCheckerX = checkerX + dst.Width;
  168. for (int fDstX = fDstLeft;
  169. checkerX < maxCheckerX && fDstX < fDstRight;
  170. ++checkerX, fDstX += dx)
  171. {
  172. int srcX1 = (fDstX + (dx >> 2)) >> fpShift; // x + 0.25
  173. int srcX2 = (fDstX + (dx >> 1) + (dx >> 2)) >> fpShift; // x + 0.75
  174. int srcX3 = fDstX >> fpShift; // x
  175. int srcX4 = (fDstX + (dx >> 1)) >> fpShift; // x + 0.50
  176. ColorBgra* p1 = src1 + srcX1;
  177. ColorBgra* p2 = src2 + srcX2;
  178. ColorBgra* p3 = src3 + srcX3;
  179. ColorBgra* p4 = src4 + srcX4;
  180. int r = (2 + p1->R + p2->R + p3->R + p4->R) >> 2;
  181. int g = (2 + p1->G + p2->G + p3->G + p4->G) >> 2;
  182. int b = (2 + p1->B + p2->B + p3->B + p4->B) >> 2;
  183. int a = (2 + p1->A + p2->A + p3->A + p4->A) >> 2;
  184. // Blend it over the checkerboard background
  185. int v = ((checkerX ^ checkerY) & 8) * 8 + 191;
  186. a = a + (a >> 7);
  187. int vmia = v * (256 - a);
  188. r = ((r * a) + vmia) >> 8;
  189. g = ((g * a) + vmia) >> 8;
  190. b = ((b * a) + vmia) >> 8;
  191. dstPtr->Bgra = (uint)b + ((uint)g << 8) + ((uint)r << 16) + 0xff000000;
  192. ++dstPtr;
  193. }
  194. }
  195. }
  196. }
  197. private void RenderZoomOutRotatedGridMultisampling(Surface dst, Point offset)
  198. {
  199. RenderZoomOutRotatedGridMultisampling(dst, this.source, offset, this.DestinationSize);
  200. }
  201. public override void Render(Surface dst, Point offset)
  202. {
  203. if (this.renderDelegate == null)
  204. {
  205. ChooseRenderDelegate();
  206. }
  207. this.renderDelegate(dst, offset);
  208. }
  209. public SurfaceBoxBaseRenderer(SurfaceBoxRendererList ownerList, Surface source)
  210. : base(ownerList)
  211. {
  212. this.source = source;
  213. ChooseRenderDelegate();
  214. }
  215. }
  216. }