honey_the_codewitch

template specializations for direct bitmap writes

Jul 21st, 2026 (edited)
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.27 KB | None | 0 0
  1. static inline uint32_t pixel_byte_mul32(uint32_t x, uint32_t a) {
  2.     uint32_t t = (x & 0xff00ff) * a;
  3.     t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
  4.     t &= 0xff00ff;
  5.     x = ((x >> 8) & 0xff00ff) * a;
  6.     x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
  7.     x &= 0xff00ff00;
  8.     x |= t;
  9.     return x;
  10. }
  11.  
  12. namespace helpers {
  13.  
  14. // one empty tag type per fast path, plus a generic fallback tag
  15. struct aa_row_565 {};
  16. struct aa_row_rgb24 {};
  17. struct aa_row_rgba32 {};
  18. struct aa_row_indexed {};
  19. struct aa_row_generic {};
  20.  
  21. // default now categorizes: indexed pixels -> indexed tag, everything else -> generic
  22. template <typename PixelType,
  23.           bool Indexed = PixelType::template has_channel_names<channel_name::index>::value>
  24. struct aa_row_tag { typedef aa_row_generic type; };
  25.  
  26. template <typename PixelType>
  27. struct aa_row_tag<PixelType, true> { typedef aa_row_indexed type; };
  28.  
  29. // fast-path overrides — all non-indexed, so the bool defaults to false
  30. template <> struct aa_row_tag<rgb_pixel<16>,  false> { typedef aa_row_565    type; };
  31. template <> struct aa_row_tag<rgb_pixel<24>,  false> { typedef aa_row_rgb24  type; };
  32. template <> struct aa_row_tag<rgba_pixel<32>, false> { typedef aa_row_rgba32 type; };
  33.  
  34. // --- one overload per tag; each sees only its own code ---
  35.  
  36. template <typename Destination>
  37. gfx_result aa_row_impl(aa_row_565, Destination& destination, spoint16 location,
  38.                        const uint8_t* cov, size_t width,
  39.                        typename Destination::pixel_type color) {
  40.     const int16_t minx = location.x, py = location.y;
  41.     const int16_t row_w = (int16_t)width;
  42.     rgb_pixel<16> rgb = color;
  43.     const uint16_t fg = rgb.native_value;
  44.     const uint32_t fg_s = (uint32_t)(fg & 0xF81F) | ((uint32_t)(fg & 0x07E0) << 16);
  45.     gfx_span span = destination.span(point16(minx, py));
  46.     uint8_t* d = span.data;
  47.     for (int i = 0; i < row_w; ++i) {
  48.         const uint8_t a = cov[i];
  49.         if (0 == a) continue;
  50.         const int j = i << 1;
  51.         if (a >= 255) {
  52. #ifndef HTCW_GFX_NO_SWAP
  53.             d[j] = (uint8_t)(fg >> 8); d[j+1] = (uint8_t)fg;
  54. #else
  55.             d[j] = (uint8_t)fg;        d[j+1] = (uint8_t)(fg >> 8);
  56. #endif
  57.             continue;
  58.         }
  59. #ifndef HTCW_GFX_NO_SWAP
  60.         const uint16_t bg = ((uint16_t)d[j] << 8) | (uint16_t)d[j+1];
  61. #else
  62.         const uint16_t bg = (uint16_t)d[j] | ((uint16_t)d[j+1] << 8);
  63. #endif
  64.         const uint32_t bg_s = (uint32_t)(bg & 0xF81F) | ((uint32_t)(bg & 0x07E0) << 16);
  65.         uint32_t a5 = (uint32_t)(a + 4) >> 3; if (a5 > 31) a5 = 31;
  66.         const uint32_t bl = (bg_s + (((fg_s - bg_s) * a5) >> 5)) & 0x07E0F81F;
  67.         const uint16_t out = (uint16_t)((bl & 0xFFFF) | (bl >> 16));
  68. #ifndef HTCW_GFX_NO_SWAP
  69.         d[j] = (uint8_t)(out >> 8); d[j+1] = (uint8_t)out;
  70. #else
  71.         d[j] = (uint8_t)out;        d[j+1] = (uint8_t)(out >> 8);
  72. #endif
  73.     }
  74.     return gfx_result::success;
  75. }
  76.  
  77. template <typename Destination>
  78. gfx_result aa_row_impl(aa_row_rgb24, Destination& destination, spoint16 location,
  79.                        const uint8_t* cov, size_t width,
  80.                        typename Destination::pixel_type color) {
  81.     const int16_t minx = location.x, py = location.y;
  82.     const int16_t row_w = (int16_t)width;
  83.     rgb_pixel<24> rgb = color;
  84.     const uint32_t fg = rgb.native_value;
  85.     gfx_span span = destination.span(point16(minx, py));
  86.     uint8_t* d = span.data;
  87.     for (int i = 0; i < row_w; ++i) {
  88.         const uint8_t a = cov[i];
  89.         if (0 == a) continue;
  90.         const int j = i * 3;
  91.         uint32_t out;
  92.         if (a >= 255) out = fg;
  93.         else {
  94. #ifndef HTCW_GFX_NO_SWAP
  95.             const uint32_t bg = ((uint32_t)d[j] << 24) | ((uint32_t)d[j+1] << 16) | ((uint32_t)d[j+2] << 8);
  96. #else
  97.             const uint32_t bg = ((uint32_t)d[j] << 8) | ((uint32_t)d[j+1] << 16) | ((uint32_t)d[j+2] << 24);
  98. #endif
  99.             out = pixel_byte_mul32(bg, 255 - a) + pixel_byte_mul32(fg, a);
  100.         }
  101. #ifndef HTCW_GFX_NO_SWAP
  102.         d[j] = (uint8_t)(out >> 24); d[j+1] = (uint8_t)(out >> 16); d[j+2] = (uint8_t)(out >> 8);
  103. #else
  104.         d[j] = (uint8_t)(out >> 8);  d[j+1] = (uint8_t)(out >> 16); d[j+2] = (uint8_t)(out >> 24);
  105. #endif
  106.     }
  107.     return gfx_result::success;
  108. }
  109.  
  110. template <typename Destination>
  111. gfx_result aa_row_impl(aa_row_rgba32, Destination& destination, spoint16 location,
  112.                        const uint8_t* cov, size_t width,
  113.                        typename Destination::pixel_type color) {
  114.     const int16_t minx = location.x, py = location.y;
  115.     const int16_t row_w = (int16_t)width;
  116.     rgba_pixel<32> rgba = color;
  117.     rgba.template channel<channel_name::A>(255);
  118.     const uint32_t fg = rgba.native_value;
  119.     gfx_span span = destination.span(point16(minx, py));
  120.     uint8_t* d = span.data;
  121.     for (int i = 0; i < row_w; ++i) {
  122.         const uint8_t a = cov[i];
  123.         if (0 == a) continue;
  124.         const int j = i << 2;
  125.         uint32_t out;
  126.         if (a >= 255) out = fg;
  127.         else {
  128. #ifndef HTCW_GFX_NO_SWAP
  129.             const uint32_t bg = ((uint32_t)d[j] << 24) | ((uint32_t)d[j+1] << 16) | ((uint32_t)d[j+2] << 8) | d[j+3];
  130. #else
  131.             const uint32_t bg = (uint32_t)d[j] | ((uint32_t)d[j+1] << 8) | ((uint32_t)d[j+2] << 16) | ((uint32_t)d[j+3] << 24);
  132. #endif
  133.             out = pixel_byte_mul32(bg, 255 - a) + pixel_byte_mul32(fg, a);
  134.         }
  135. #ifndef HTCW_GFX_NO_SWAP
  136.         d[j] = (uint8_t)(out >> 24); d[j+1] = (uint8_t)(out >> 16); d[j+2] = (uint8_t)(out >> 8); d[j+3] = (uint8_t)out;
  137. #else
  138.         d[j] = (uint8_t)out; d[j+1] = (uint8_t)(out >> 8); d[j+2] = (uint8_t)(out >> 16); d[j+3] = (uint8_t)(out >> 24);
  139. #endif
  140.     }
  141.     return gfx_result::success;
  142. }
  143. template <typename Destination>
  144. gfx_result aa_row_impl(aa_row_generic, Destination& destination, spoint16 location,
  145.                        const uint8_t* cov, size_t width,
  146.                        typename Destination::pixel_type color) {
  147.     const int16_t minx = location.x, py = location.y;
  148.     const int16_t row_w = (int16_t)width;
  149.     typename Destination::pixel_type bgpx, dpx;
  150.     gfx_result r;
  151.     for (int i = 0; i < row_w; ++i) {
  152.         const uint8_t c8 = cov[i];
  153.         if (0 == c8) continue;
  154.         const point16 p((uint16_t)(minx + i), (uint16_t)py);
  155.         if (c8 < 255) {
  156.             r = destination.point(p, &bgpx);
  157.             if (gfx_result::success != r) return r;
  158.             dpx = color.blend8(bgpx, c8);
  159.         } else {
  160.             dpx = color;
  161.         }
  162.         r = destination.point(p, dpx);
  163.         if (gfx_result::success != r) return r;
  164.     }
  165.     return gfx_result::success;
  166. }
  167.  
  168. template <typename Destination>
  169. gfx_result aa_row_impl(aa_row_indexed, Destination& destination, spoint16 location,
  170.                        const uint8_t* cov, size_t width,
  171.                        typename Destination::pixel_type color) {
  172.     const int16_t minx = location.x, py = location.y;
  173.     const int16_t row_w = (int16_t)width;
  174.     rgba_pixel<32> fgcol, bgcol;
  175.     convert_palette_to(destination, color, &fgcol);   // resolve fg once
  176.     typename Destination::pixel_type bgpx, dpx;
  177.     gfx_result r;
  178.     for (int i = 0; i < row_w; ++i) {
  179.         const uint8_t c8 = cov[i];
  180.         if (0 == c8) continue;
  181.         const point16 p((uint16_t)(minx + i), (uint16_t)py);
  182.         if (c8 < 255) {
  183.             r = destination.point(p, &bgpx);
  184.             if (gfx_result::success != r) return r;
  185.             convert_palette_to(destination, bgpx, &bgcol);   // palette -> rgba
  186.             bgcol = fgcol.blend8(bgcol, c8);                 // blend in rgba space
  187.             convert_palette_from(destination, bgcol, &dpx);  // rgba -> nearest index
  188.         } else {
  189.             dpx = color;
  190.         }
  191.         r = destination.point(p, dpx);
  192.         if (gfx_result::success != r) return r;
  193.     }
  194.     return gfx_result::success;
  195. }
  196.  
  197. } // namespace helpers
  198.  
  199. // public entry: picks the tag at compile time, dispatches to the one live overload
  200. template <typename Destination>
  201. gfx_result aa_rasterize_row(Destination& destination, spoint16 location,
  202.                             const uint8_t* cov, size_t width,
  203.                             typename Destination::pixel_type color) {
  204.     typename helpers::aa_row_tag<typename Destination::pixel_type>::type tag;
  205.     return helpers::aa_row_impl(tag, destination, location, cov, width, color);
  206. }
  207.  
Tags: cursed
Advertisement
Add Comment
Please, Sign In to add comment