blob: 852aee8445d52b12311ef8cfdd5927716313ebc6 [file] [log] [blame]
/*
* 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 */