EdgeFlagPathRasterizer.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright (c) 2023, MacDue <macdue@dueutil.tech>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Array.h>
  8. #include <AK/GenericShorthands.h>
  9. #include <AK/IntegralMath.h>
  10. #include <AK/Vector.h>
  11. #include <LibGfx/Bitmap.h>
  12. #include <LibGfx/DeprecatedPath.h>
  13. #include <LibGfx/Forward.h>
  14. #include <LibGfx/PaintStyle.h>
  15. #include <LibGfx/WindingRule.h>
  16. namespace Gfx {
  17. namespace Detail {
  18. static auto constexpr coverage_lut = [] {
  19. Array<u8, 256> coverage_lut {};
  20. for (u32 sample = 0; sample <= 255; sample++)
  21. coverage_lut[sample] = AK::popcount(sample);
  22. return coverage_lut;
  23. }();
  24. template<unsigned SamplesPerPixel>
  25. struct Sample {
  26. static_assert(!first_is_one_of(SamplesPerPixel, 8u, 16u, 32u), "EdgeFlagPathRasterizer: Invalid samples per pixel!");
  27. };
  28. // See paper for diagrams for how these offsets work, but they allow for nicely spread out samples in each pixel.
  29. template<>
  30. struct Sample<8> {
  31. using Type = u8;
  32. static constexpr Array nrooks_subpixel_offsets {
  33. (5.0f / 8.0f),
  34. (0.0f / 8.0f),
  35. (3.0f / 8.0f),
  36. (6.0f / 8.0f),
  37. (1.0f / 8.0f),
  38. (4.0f / 8.0f),
  39. (7.0f / 8.0f),
  40. (2.0f / 8.0f),
  41. };
  42. static u8 compute_coverage(Type sample)
  43. {
  44. return coverage_lut[sample];
  45. }
  46. };
  47. template<>
  48. struct Sample<16> {
  49. using Type = u16;
  50. static constexpr Array nrooks_subpixel_offsets {
  51. (1.0f / 16.0f),
  52. (8.0f / 16.0f),
  53. (4.0f / 16.0f),
  54. (15.0f / 16.0f),
  55. (11.0f / 16.0f),
  56. (2.0f / 16.0f),
  57. (6.0f / 16.0f),
  58. (14.0f / 16.0f),
  59. (10.0f / 16.0f),
  60. (3.0f / 16.0f),
  61. (7.0f / 16.0f),
  62. (12.0f / 16.0f),
  63. (0.0f / 16.0f),
  64. (9.0f / 16.0f),
  65. (5.0f / 16.0f),
  66. (13.0f / 16.0f),
  67. };
  68. static u8 compute_coverage(Type sample)
  69. {
  70. return (
  71. coverage_lut[(sample >> 0) & 0xff]
  72. + coverage_lut[(sample >> 8) & 0xff]);
  73. }
  74. };
  75. template<>
  76. struct Sample<32> {
  77. using Type = u32;
  78. static constexpr Array nrooks_subpixel_offsets {
  79. (28.0f / 32.0f),
  80. (13.0f / 32.0f),
  81. (6.0f / 32.0f),
  82. (23.0f / 32.0f),
  83. (0.0f / 32.0f),
  84. (17.0f / 32.0f),
  85. (10.0f / 32.0f),
  86. (27.0f / 32.0f),
  87. (4.0f / 32.0f),
  88. (21.0f / 32.0f),
  89. (14.0f / 32.0f),
  90. (31.0f / 32.0f),
  91. (8.0f / 32.0f),
  92. (25.0f / 32.0f),
  93. (18.0f / 32.0f),
  94. (3.0f / 32.0f),
  95. (12.0f / 32.0f),
  96. (29.0f / 32.0f),
  97. (22.0f / 32.0f),
  98. (7.0f / 32.0f),
  99. (16.0f / 32.0f),
  100. (1.0f / 32.0f),
  101. (26.0f / 32.0f),
  102. (11.0f / 32.0f),
  103. (20.0f / 32.0f),
  104. (5.0f / 32.0f),
  105. (30.0f / 32.0f),
  106. (15.0f / 32.0f),
  107. (24.0f / 32.0f),
  108. (9.0f / 32.0f),
  109. (2.0f / 32.0f),
  110. (19.0f / 32.0f),
  111. };
  112. static u8 compute_coverage(Type sample)
  113. {
  114. return (
  115. coverage_lut[(sample >> 0) & 0xff]
  116. + coverage_lut[(sample >> 8) & 0xff]
  117. + coverage_lut[(sample >> 16) & 0xff]
  118. + coverage_lut[(sample >> 24) & 0xff]);
  119. }
  120. };
  121. struct Edge {
  122. float x;
  123. int min_y;
  124. int max_y;
  125. float dxdy;
  126. i8 winding;
  127. Edge* next_edge;
  128. };
  129. }
  130. template<unsigned SamplesPerPixel = 32>
  131. class EdgeFlagPathRasterizer {
  132. public:
  133. EdgeFlagPathRasterizer(IntSize);
  134. void fill(DeprecatedPainter&, DeprecatedPath const&, Color, WindingRule, FloatPoint offset = {});
  135. void fill(DeprecatedPainter&, DeprecatedPath const&, PaintStyle const&, float opacity, WindingRule, FloatPoint offset = {});
  136. private:
  137. using SubpixelSample = Detail::Sample<SamplesPerPixel>;
  138. using SampleType = typename SubpixelSample::Type;
  139. static u8 coverage_to_alpha(u8 coverage)
  140. {
  141. constexpr auto alpha_shift = AK::log2(256 / SamplesPerPixel);
  142. if (!coverage)
  143. return 0;
  144. return (coverage << alpha_shift) - 1;
  145. }
  146. struct EdgeExtent {
  147. int min_x;
  148. int max_x;
  149. template<typename T>
  150. void memset_extent(T* data, int value)
  151. {
  152. if (min_x <= max_x)
  153. memset(data + min_x, value, (max_x - min_x + 1) * sizeof(T));
  154. }
  155. };
  156. void fill_internal(DeprecatedPainter&, DeprecatedPath const&, auto color_or_function, WindingRule, FloatPoint offset);
  157. Detail::Edge* plot_edges_for_scanline(int scanline, auto plot_edge, EdgeExtent&, Detail::Edge* active_edges = nullptr);
  158. template<WindingRule>
  159. FLATTEN void write_scanline(DeprecatedPainter&, int scanline, EdgeExtent, auto& color_or_function);
  160. Color scanline_color(int scanline, int offset, u8 alpha, auto& color_or_function);
  161. void write_pixel(BitmapFormat format, ARGB32* scanline_ptr, int scanline, int offset, SampleType sample, auto& color_or_function);
  162. void fast_fill_solid_color_span(ARGB32* scanline_ptr, int start, int end, Color color);
  163. template<WindingRule, typename Callback>
  164. auto accumulate_scanline(EdgeExtent, auto, Callback);
  165. auto accumulate_even_odd_scanline(EdgeExtent, auto, auto sample_callback);
  166. auto accumulate_non_zero_scanline(EdgeExtent, auto, auto sample_callback);
  167. struct WindingCounts {
  168. // NOTE: This only allows up to 256 winding levels. Increase this if required (i.e. to an i16).
  169. i8 counts[SamplesPerPixel];
  170. };
  171. struct NonZeroAcc {
  172. SampleType sample;
  173. WindingCounts winding;
  174. };
  175. template<WindingRule WindingRule>
  176. constexpr auto initial_acc() const
  177. {
  178. if constexpr (WindingRule == WindingRule::EvenOdd)
  179. return SampleType {};
  180. else
  181. return NonZeroAcc {};
  182. }
  183. IntSize m_size;
  184. IntPoint m_blit_origin;
  185. IntRect m_clip;
  186. Vector<SampleType> m_scanline;
  187. Vector<WindingCounts> m_windings;
  188. class EdgeTable {
  189. public:
  190. EdgeTable() = default;
  191. void set_scanline_range(int min_scanline, int max_scanline)
  192. {
  193. m_min_scanline = min_scanline;
  194. m_edges.resize(max_scanline - min_scanline + 1);
  195. }
  196. auto& operator[](int scanline) { return m_edges[scanline - m_min_scanline]; }
  197. private:
  198. Vector<Detail::Edge*> m_edges;
  199. int m_min_scanline { 0 };
  200. } m_edge_table;
  201. };
  202. extern template class EdgeFlagPathRasterizer<8>;
  203. extern template class EdgeFlagPathRasterizer<16>;
  204. extern template class EdgeFlagPathRasterizer<32>;
  205. }