Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- static inline uint32_t pixel_byte_mul32(uint32_t x, uint32_t a) {
- uint32_t t = (x & 0xff00ff) * a;
- t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
- t &= 0xff00ff;
- x = ((x >> 8) & 0xff00ff) * a;
- x = (x + ((x >> 8) & 0xff00ff) + 0x800080);
- x &= 0xff00ff00;
- x |= t;
- return x;
- }
- namespace helpers {
- // one empty tag type per fast path, plus a generic fallback tag
- struct aa_row_565 {};
- struct aa_row_rgb24 {};
- struct aa_row_rgba32 {};
- struct aa_row_indexed {};
- struct aa_row_generic {};
- // default now categorizes: indexed pixels -> indexed tag, everything else -> generic
- template <typename PixelType,
- bool Indexed = PixelType::template has_channel_names<channel_name::index>::value>
- struct aa_row_tag { typedef aa_row_generic type; };
- template <typename PixelType>
- struct aa_row_tag<PixelType, true> { typedef aa_row_indexed type; };
- // fast-path overrides — all non-indexed, so the bool defaults to false
- template <> struct aa_row_tag<rgb_pixel<16>, false> { typedef aa_row_565 type; };
- template <> struct aa_row_tag<rgb_pixel<24>, false> { typedef aa_row_rgb24 type; };
- template <> struct aa_row_tag<rgba_pixel<32>, false> { typedef aa_row_rgba32 type; };
- // --- one overload per tag; each sees only its own code ---
- template <typename Destination>
- gfx_result aa_row_impl(aa_row_565, Destination& destination, spoint16 location,
- const uint8_t* cov, size_t width,
- typename Destination::pixel_type color) {
- const int16_t minx = location.x, py = location.y;
- const int16_t row_w = (int16_t)width;
- rgb_pixel<16> rgb = color;
- const uint16_t fg = rgb.native_value;
- const uint32_t fg_s = (uint32_t)(fg & 0xF81F) | ((uint32_t)(fg & 0x07E0) << 16);
- gfx_span span = destination.span(point16(minx, py));
- uint8_t* d = span.data;
- for (int i = 0; i < row_w; ++i) {
- const uint8_t a = cov[i];
- if (0 == a) continue;
- const int j = i << 1;
- if (a >= 255) {
- #ifndef HTCW_GFX_NO_SWAP
- d[j] = (uint8_t)(fg >> 8); d[j+1] = (uint8_t)fg;
- #else
- d[j] = (uint8_t)fg; d[j+1] = (uint8_t)(fg >> 8);
- #endif
- continue;
- }
- #ifndef HTCW_GFX_NO_SWAP
- const uint16_t bg = ((uint16_t)d[j] << 8) | (uint16_t)d[j+1];
- #else
- const uint16_t bg = (uint16_t)d[j] | ((uint16_t)d[j+1] << 8);
- #endif
- const uint32_t bg_s = (uint32_t)(bg & 0xF81F) | ((uint32_t)(bg & 0x07E0) << 16);
- uint32_t a5 = (uint32_t)(a + 4) >> 3; if (a5 > 31) a5 = 31;
- const uint32_t bl = (bg_s + (((fg_s - bg_s) * a5) >> 5)) & 0x07E0F81F;
- const uint16_t out = (uint16_t)((bl & 0xFFFF) | (bl >> 16));
- #ifndef HTCW_GFX_NO_SWAP
- d[j] = (uint8_t)(out >> 8); d[j+1] = (uint8_t)out;
- #else
- d[j] = (uint8_t)out; d[j+1] = (uint8_t)(out >> 8);
- #endif
- }
- return gfx_result::success;
- }
- template <typename Destination>
- gfx_result aa_row_impl(aa_row_rgb24, Destination& destination, spoint16 location,
- const uint8_t* cov, size_t width,
- typename Destination::pixel_type color) {
- const int16_t minx = location.x, py = location.y;
- const int16_t row_w = (int16_t)width;
- rgb_pixel<24> rgb = color;
- const uint32_t fg = rgb.native_value;
- gfx_span span = destination.span(point16(minx, py));
- uint8_t* d = span.data;
- for (int i = 0; i < row_w; ++i) {
- const uint8_t a = cov[i];
- if (0 == a) continue;
- const int j = i * 3;
- uint32_t out;
- if (a >= 255) out = fg;
- else {
- #ifndef HTCW_GFX_NO_SWAP
- const uint32_t bg = ((uint32_t)d[j] << 24) | ((uint32_t)d[j+1] << 16) | ((uint32_t)d[j+2] << 8);
- #else
- const uint32_t bg = ((uint32_t)d[j] << 8) | ((uint32_t)d[j+1] << 16) | ((uint32_t)d[j+2] << 24);
- #endif
- out = pixel_byte_mul32(bg, 255 - a) + pixel_byte_mul32(fg, a);
- }
- #ifndef HTCW_GFX_NO_SWAP
- d[j] = (uint8_t)(out >> 24); d[j+1] = (uint8_t)(out >> 16); d[j+2] = (uint8_t)(out >> 8);
- #else
- d[j] = (uint8_t)(out >> 8); d[j+1] = (uint8_t)(out >> 16); d[j+2] = (uint8_t)(out >> 24);
- #endif
- }
- return gfx_result::success;
- }
- template <typename Destination>
- gfx_result aa_row_impl(aa_row_rgba32, Destination& destination, spoint16 location,
- const uint8_t* cov, size_t width,
- typename Destination::pixel_type color) {
- const int16_t minx = location.x, py = location.y;
- const int16_t row_w = (int16_t)width;
- rgba_pixel<32> rgba = color;
- rgba.template channel<channel_name::A>(255);
- const uint32_t fg = rgba.native_value;
- gfx_span span = destination.span(point16(minx, py));
- uint8_t* d = span.data;
- for (int i = 0; i < row_w; ++i) {
- const uint8_t a = cov[i];
- if (0 == a) continue;
- const int j = i << 2;
- uint32_t out;
- if (a >= 255) out = fg;
- else {
- #ifndef HTCW_GFX_NO_SWAP
- const uint32_t bg = ((uint32_t)d[j] << 24) | ((uint32_t)d[j+1] << 16) | ((uint32_t)d[j+2] << 8) | d[j+3];
- #else
- 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);
- #endif
- out = pixel_byte_mul32(bg, 255 - a) + pixel_byte_mul32(fg, a);
- }
- #ifndef HTCW_GFX_NO_SWAP
- 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;
- #else
- 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);
- #endif
- }
- return gfx_result::success;
- }
- template <typename Destination>
- gfx_result aa_row_impl(aa_row_generic, Destination& destination, spoint16 location,
- const uint8_t* cov, size_t width,
- typename Destination::pixel_type color) {
- const int16_t minx = location.x, py = location.y;
- const int16_t row_w = (int16_t)width;
- typename Destination::pixel_type bgpx, dpx;
- gfx_result r;
- for (int i = 0; i < row_w; ++i) {
- const uint8_t c8 = cov[i];
- if (0 == c8) continue;
- const point16 p((uint16_t)(minx + i), (uint16_t)py);
- if (c8 < 255) {
- r = destination.point(p, &bgpx);
- if (gfx_result::success != r) return r;
- dpx = color.blend8(bgpx, c8);
- } else {
- dpx = color;
- }
- r = destination.point(p, dpx);
- if (gfx_result::success != r) return r;
- }
- return gfx_result::success;
- }
- template <typename Destination>
- gfx_result aa_row_impl(aa_row_indexed, Destination& destination, spoint16 location,
- const uint8_t* cov, size_t width,
- typename Destination::pixel_type color) {
- const int16_t minx = location.x, py = location.y;
- const int16_t row_w = (int16_t)width;
- rgba_pixel<32> fgcol, bgcol;
- convert_palette_to(destination, color, &fgcol); // resolve fg once
- typename Destination::pixel_type bgpx, dpx;
- gfx_result r;
- for (int i = 0; i < row_w; ++i) {
- const uint8_t c8 = cov[i];
- if (0 == c8) continue;
- const point16 p((uint16_t)(minx + i), (uint16_t)py);
- if (c8 < 255) {
- r = destination.point(p, &bgpx);
- if (gfx_result::success != r) return r;
- convert_palette_to(destination, bgpx, &bgcol); // palette -> rgba
- bgcol = fgcol.blend8(bgcol, c8); // blend in rgba space
- convert_palette_from(destination, bgcol, &dpx); // rgba -> nearest index
- } else {
- dpx = color;
- }
- r = destination.point(p, dpx);
- if (gfx_result::success != r) return r;
- }
- return gfx_result::success;
- }
- } // namespace helpers
- // public entry: picks the tag at compile time, dispatches to the one live overload
- template <typename Destination>
- gfx_result aa_rasterize_row(Destination& destination, spoint16 location,
- const uint8_t* cov, size_t width,
- typename Destination::pixel_type color) {
- typename helpers::aa_row_tag<typename Destination::pixel_type>::type tag;
- return helpers::aa_row_impl(tag, destination, location, cov, width, color);
- }
Advertisement
Add Comment
Please, Sign In to add comment