| /* |
| * Copyright © 2026 Behdad Esfahbod |
| * |
| * This is part of HarfBuzz, a text shaping library. |
| * |
| * Permission is hereby granted, without written agreement and without |
| * license or royalty fees, to use, copy, modify, and distribute this |
| * software and its documentation for any purpose, provided that the |
| * above copyright notice and the following two paragraphs appear in |
| * all copies of this software. |
| * |
| * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
| * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| * DAMAGE. |
| * |
| * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| * |
| * Author(s): Behdad Esfahbod |
| */ |
| |
| #ifndef HB_RASTER_HH |
| #define HB_RASTER_HH |
| |
| #include "hb.hh" |
| |
| /* Shared pixel helpers (used by paint and image compositing). */ |
| |
| static HB_ALWAYS_INLINE uint8_t |
| hb_raster_div255 (unsigned a) |
| { |
| if (true) |
| { |
| // An approximation. Slightly faster. |
| // https://github.com/linebender/vello/blob/ab58009c8289e83689cd0effc4e34d1c6e8b51f5/sparse_strips/vello_cpu/src/util.rs#L10-L63 |
| return (a + 255) >> 8; |
| } |
| |
| return (uint8_t) ((a + 128 + ((a + 128) >> 8)) >> 8); |
| } |
| |
| static HB_ALWAYS_INLINE uint32_t |
| hb_raster_pack_pixel (uint8_t b, uint8_t g, uint8_t r, uint8_t a) |
| { |
| return (uint32_t) b | ((uint32_t) g << 8) | ((uint32_t) r << 16) | ((uint32_t) a << 24); |
| } |
| |
| /* SRC_OVER: premultiplied src over premultiplied dst. */ |
| static HB_ALWAYS_INLINE uint32_t |
| hb_raster_src_over (uint32_t src, uint32_t dst) |
| { |
| uint8_t sa = (uint8_t) (src >> 24); |
| if (sa == 255) return src; |
| if (sa == 0) return dst; |
| unsigned inv_sa = 255 - sa; |
| uint8_t rb = hb_raster_div255 ((dst & 0xFF) * inv_sa) + (uint8_t) (src & 0xFF); |
| uint8_t rg = hb_raster_div255 (((dst >> 8) & 0xFF) * inv_sa) + (uint8_t) ((src >> 8) & 0xFF); |
| uint8_t rr = hb_raster_div255 (((dst >> 16) & 0xFF) * inv_sa) + (uint8_t) ((src >> 16) & 0xFF); |
| uint8_t ra = hb_raster_div255 (((dst >> 24) & 0xFF) * inv_sa) + sa; |
| return (uint32_t) rb | ((uint32_t) rg << 8) | ((uint32_t) rr << 16) | ((uint32_t) ra << 24); |
| } |
| |
| /* Scale a premultiplied pixel by an alpha [0,255]. */ |
| static HB_ALWAYS_INLINE uint32_t |
| hb_raster_alpha_mul (uint32_t px, unsigned a) |
| { |
| if (a == 255) return px; |
| if (a == 0) return 0; |
| uint8_t rb = hb_raster_div255 ((px & 0xFF) * a); |
| uint8_t rg = hb_raster_div255 (((px >> 8) & 0xFF) * a); |
| uint8_t rr = hb_raster_div255 (((px >> 16) & 0xFF) * a); |
| uint8_t ra = hb_raster_div255 (((px >> 24) & 0xFF) * a); |
| return (uint32_t) rb | ((uint32_t) rg << 8) | ((uint32_t) rr << 16) | ((uint32_t) ra << 24); |
| } |
| |
| #endif /* HB_RASTER_HH */ |