diff options
Diffstat (limited to '')
-rw-r--r-- | apply-glyph.h | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/apply-glyph.h b/apply-glyph.h new file mode 100644 index 0000000..09cb9aa --- /dev/null +++ b/apply-glyph.h @@ -0,0 +1,141 @@ +/* See LICENSE file for copyright and license details. */ + +#ifndef NARROW_FLOAT_TYPE +# define NARROW_FLOAT_TYPE double +# define NARROW_FLOAT_TYPE_AUTO +#endif +#ifndef WIDE_FLOAT_TYPE +# define WIDE_FLOAT_TYPE NARROW_FLOAT_TYPE +# define WIDE_FLOAT_TYPE_AUTO +#endif +#ifndef TYPE +# define TYPE NARROW_FLOAT_TYPE +# define TYPE_AUTO +# define TYPEMAX 1 +#else +# define TYPEMAX ((TYPE)~(TYPE)0) +#endif +#ifndef RMAP +# define RMAP(Y) ((NARROW_FLOAT_TYPE)((WIDE_FLOAT_TYPE)(Y) / TYPEMAX)) +# define RMAP_AUTO +#endif +#define MAP(Y) (TYPE)((WIDE_FLOAT_TYPE)(Y) * TYPEMAX + (WIDE_FLOAT_TYPE)0.5f) +#define R (&((TYPE *)&img[i])[settings.rpos]) +#define G (&((TYPE *)&img[i])[settings.gpos]) +#define B (&((TYPE *)&img[i])[settings.bpos]) +#define A (&((TYPE *)&img[i])[settings.apos]) + +do { + NARROW_FLOAT_TYPE opacity = (NARROW_FLOAT_TYPE)colour->opacity / 255; + NARROW_FLOAT_TYPE al, alpha = (NARROW_FLOAT_TYPE)colour->alpha / 255; + NARROW_FLOAT_TYPE re, red = (NARROW_FLOAT_TYPE)colour->red / 255; + NARROW_FLOAT_TYPE gr, green = (NARROW_FLOAT_TYPE)colour->green / 255; + NARROW_FLOAT_TYPE bl, blue = (NARROW_FLOAT_TYPE)colour->blue / 255; + NARROW_FLOAT_TYPE transparency; + + if (settings.apos < 0) { + if (gly_psize > 1) { + for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) { + for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) { + *R = MAP(RMAP(*R) * (1 - opacity * gly[c + ri]) + gly[c + ri] * red); + *G = MAP(RMAP(*G) * (1 - opacity * gly[c + gi]) + gly[c + gi] * green); + *B = MAP(RMAP(*B) * (1 - opacity * gly[c + bi]) + gly[c + bi] * blue); + } + } + } else { + for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) { + for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) { + transparency = 1 - opacity * gly[c + ri]; + *R = MAP(RMAP(*R) * transparency + gly[c + ri] * red); + *G = MAP(RMAP(*G) * transparency + gly[c + gi] * green); + *B = MAP(RMAP(*B) * transparency + gly[c + bi] * blue); + } + } + } + } else if (image->premultiplied) { + if (gly_psize > 1) { + for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) { + for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) { + high = gly[c + ri] > gly[c + gi] ? gly[c + ri] : gly[c + gi]; + high = high > gly[c + bi] ? high : gly[c + bi]; + *R = MAP(RMAP(*R) * (1 - opacity * gly[c + ri]) + gly[c + ri] * red); + *G = MAP(RMAP(*G) * (1 - opacity * gly[c + gi]) + gly[c + gi] * green); + *B = MAP(RMAP(*B) * (1 - opacity * gly[c + bi]) + gly[c + bi] * blue); + *A = MAP(RMAP(*A) * (1 - opacity * high) + high * alpha); + } + } + } else { + for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) { + for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) { + transparency = 1 - opacity * gly[c + ri]; + *R = MAP(RMAP(*R) * transparency + gly[c + ri] * red); + *G = MAP(RMAP(*G) * transparency + gly[c + ri] * green); + *B = MAP(RMAP(*B) * transparency + gly[c + ri] * blue); + *A = MAP(RMAP(*A) * transparency + gly[c + ri] * alpha); + } + } + } + } else { + if (gly_psize > 1) { + for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) { + for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) { + high = gly[c + ri] > gly[c + gi] ? gly[c + ri] : gly[c + gi]; + high = high > gly[c + bi] ? high : gly[c + bi]; + re = RMAP(*R) * RMAP(*A) * (1 - opacity * gly[c + ri]) + gly[c + ri] * red; + gr = RMAP(*G) * RMAP(*A) * (1 - opacity * gly[c + gi]) + gly[c + gi] * green; + bl = RMAP(*B) * RMAP(*A) * (1 - opacity * gly[c + bi]) + gly[c + bi] * blue; + al = RMAP(*A) * (1 - opacity * high) + high * alpha; + if (fpclassify(al) != FP_ZERO) { + *R = MAP(re); + *G = MAP(gr); + *B = MAP(bl); + *A = MAP(al); + } else { + *R = *G = *B = *A = 0; + } + } + } + } else { + for (img = img_start, r = startr; r < endr; r++, img += img_linesize, gly += gly_linesize) { + for (c = startc, i = 0; c < endc; c += gly_psize, i += psize) { + transparency = 1 - opacity * gly[c + ri]; + re = RMAP(*R) * RMAP(*A) * transparency + gly[c + ri] * red; + gr = RMAP(*G) * RMAP(*A) * transparency + gly[c + ri] * green; + bl = RMAP(*B) * RMAP(*A) * transparency + gly[c + ri] * blue; + al = RMAP(*A) * transparency + gly[c + ri] * alpha; + if (fpclassify(al) != FP_ZERO) { + *R = MAP(re); + *G = MAP(gr); + *B = MAP(bl); + *A = MAP(al); + } else { + *R = *G = *B = *A = 0; + } + } + } + } + } +} while (0); + +#ifdef NARROW_FLOAT_TYPE_AUTO +# undef NARROW_FLOAT_TYPE_AUTO +# undef NARROW_FLOAT_TYPE +#endif +#ifdef WIDE_FLOAT_TYPE_AUTO +# undef WIDE_FLOAT_TYPE_AUTO +# undef WIDE_FLOAT_TYPE +#endif +#ifdef TYPE_AUTO +# undef TYPE_AUTO +# undef TYPE +#endif +#undef TYPEMAX +#ifdef RMAP_AUTO +# undef RMAP_AUTO +# undef RMAP +#endif +#undef MAP +#undef R +#undef G +#undef B +#undef A |