X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fart%2Fart_rgba.c;fp=lib%2Fart%2Fart_rgba.c;h=cde183cc52c2b03c227b1c7c6493bd23d3b2af9d;hb=418ef05b5d0b74e6f19200ffa40bcc3afccb5029;hp=0000000000000000000000000000000000000000;hpb=c1f4a906117e98e2f4ba59abc1ce153e8129bc19;p=swftools.git diff --git a/lib/art/art_rgba.c b/lib/art/art_rgba.c new file mode 100644 index 0000000..cde183c --- /dev/null +++ b/lib/art/art_rgba.c @@ -0,0 +1,258 @@ +/* + * art_rgba.c: Functions for manipulating RGBA pixel data. + * + * Libart_LGPL - library of basic graphic primitives + * Copyright (C) 2000 Raph Levien + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" +#include "art_rgba.h" + +#define ART_OPTIMIZE_SPACE + +#ifndef ART_OPTIMIZE_SPACE +#include "art_rgba_table.c" +#endif + +/** + * art_rgba_rgba_composite: Composite RGBA image over RGBA buffer. + * @dst: Destination RGBA buffer. + * @src: Source RGBA buffer. + * @n: Number of RGBA pixels to composite. + * + * Composites the RGBA pixels in @dst over the @src buffer. + **/ +void +art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n) +{ + int i; +#ifdef WORDS_BIGENDIAN + art_u32 src_rgba, dst_rgba; +#else + art_u32 src_abgr, dst_abgr; +#endif + art_u8 src_alpha, dst_alpha; + + for (i = 0; i < n; i++) + { +#ifdef WORDS_BIGENDIAN + src_rgba = ((art_u32 *)src)[i]; + src_alpha = src_rgba & 0xff; +#else + src_abgr = ((art_u32 *)src)[i]; + src_alpha = (src_abgr >> 24) & 0xff; +#endif + if (src_alpha) + { + if (src_alpha == 0xff || + ( +#ifdef WORDS_BIGENDIAN + dst_rgba = ((art_u32 *)dst)[i], + dst_alpha = dst_rgba & 0xff, +#else + dst_abgr = ((art_u32 *)dst)[i], + dst_alpha = (dst_abgr >> 24), +#endif + dst_alpha == 0)) +#ifdef WORDS_BIGENDIAN + ((art_u32 *)dst)[i] = src_rgba; +#else + ((art_u32 *)dst)[i] = src_abgr; +#endif + else + { + int r, g, b, a; + int src_r, src_g, src_b; + int dst_r, dst_g, dst_b; + int tmp; + int c; + +#ifdef ART_OPTIMIZE_SPACE + tmp = (255 - src_alpha) * (255 - dst_alpha) + 0x80; + a = 255 - ((tmp + (tmp >> 8)) >> 8); + c = ((src_alpha << 16) + (a >> 1)) / a; +#else + tmp = art_rgba_composite_table[(src_alpha << 8) + dst_alpha]; + c = tmp & 0x1ffff; + a = tmp >> 24; +#endif +#ifdef WORDS_BIGENDIAN + src_r = (src_rgba >> 24) & 0xff; + src_g = (src_rgba >> 16) & 0xff; + src_b = (src_rgba >> 8) & 0xff; + dst_r = (dst_rgba >> 24) & 0xff; + dst_g = (dst_rgba >> 16) & 0xff; + dst_b = (dst_rgba >> 8) & 0xff; +#else + src_r = src_abgr & 0xff; + src_g = (src_abgr >> 8) & 0xff; + src_b = (src_abgr >> 16) & 0xff; + dst_r = dst_abgr & 0xff; + dst_g = (dst_abgr >> 8) & 0xff; + dst_b = (dst_abgr >> 16) & 0xff; +#endif + r = dst_r + (((src_r - dst_r) * c + 0x8000) >> 16); + g = dst_g + (((src_g - dst_g) * c + 0x8000) >> 16); + b = dst_b + (((src_b - dst_b) * c + 0x8000) >> 16); +#ifdef WORDS_BIGENDIAN + ((art_u32 *)dst)[i] = (r << 24) | (g << 16) | (b << 8) | a; +#else + ((art_u32 *)dst)[i] = (a << 24) | (b << 16) | (g << 8) | r; +#endif + } + } +#if 0 + /* it's not clear to me this optimization really wins */ + else + { + /* skip over run of transparent pixels */ + for (; i < n - 1; i++) + { +#ifdef WORDS_BIGENDIAN + src_rgba = ((art_u32 *)src)[i + 1]; + if (src_rgba & 0xff) + break; +#else + src_abgr = ((art_u32 *)src)[i + 1]; + if (src_abgr & 0xff000000) + break; +#endif + } + } +#endif + } +} + +/** + * art_rgba_fill_run: fill an RGBA buffer a solid RGB color. + * @buf: Buffer to fill. + * @r: Red, range 0..255. + * @g: Green, range 0..255. + * @b: Blue, range 0..255. + * @n: Number of RGB triples to fill. + * + * Fills a buffer with @n copies of the (@r, @g, @b) triple, solid + * alpha. Thus, locations @buf (inclusive) through @buf + 4 * @n + * (exclusive) are written. + **/ +void +art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n) +{ + int i; +#ifdef WORDS_BIGENDIAN + art_u32 src_rgba; +#else + art_u32 src_abgr; +#endif + +#ifdef WORDS_BIGENDIAN + src_rgba = (r << 24) | (g << 16) | (b << 8) | 255; +#else + src_abgr = (255 << 24) | (b << 16) | (g << 8) | r; +#endif + for (i = 0; i < n; i++) + { +#ifdef WORDS_BIGENDIAN + ((art_u32 *)buf)[i] = src_rgba; +#else + ((art_u32 *)buf)[i] = src_abgr; +#endif + } +} + +/** + * art_rgba_run_alpha: Render semitransparent color over RGBA buffer. + * @buf: Buffer for rendering. + * @r: Red, range 0..255. + * @g: Green, range 0..255. + * @b: Blue, range 0..255. + * @alpha: Alpha, range 0..255. + * @n: Number of RGB triples to render. + * + * Renders a sequential run of solid (@r, @g, @b) color over @buf with + * opacity @alpha. Note that the range of @alpha is 0..255, in contrast + * to art_rgb_run_alpha, which has a range of 0..256. + **/ +void +art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n) +{ + int i; +#ifdef WORDS_BIGENDIAN + art_u32 src_rgba, dst_rgba; +#else + art_u32 src_abgr, dst_abgr; +#endif + art_u8 dst_alpha; + int a; + int dst_r, dst_g, dst_b; + int tmp; + int c; + +#ifdef WORDS_BIGENDIAN + src_rgba = (r << 24) | (g << 16) | (b << 8) | alpha; +#else + src_abgr = (alpha << 24) | (b << 16) | (g << 8) | r; +#endif + for (i = 0; i < n; i++) + { +#ifdef WORDS_BIGENDIAN + dst_rgba = ((art_u32 *)buf)[i]; + dst_alpha = dst_rgba & 0xff; +#else + dst_abgr = ((art_u32 *)buf)[i]; + dst_alpha = (dst_abgr >> 24) & 0xff; +#endif + if (dst_alpha) + { +#ifdef ART_OPTIMIZE_SPACE + tmp = (255 - alpha) * (255 - dst_alpha) + 0x80; + a = 255 - ((tmp + (tmp >> 8)) >> 8); + c = ((alpha << 16) + (a >> 1)) / a; +#else + tmp = art_rgba_composite_table[(alpha << 8) + dst_alpha]; + c = tmp & 0x1ffff; + a = tmp >> 24; +#endif +#ifdef WORDS_BIGENDIAN + dst_r = (dst_rgba >> 24) & 0xff; + dst_g = (dst_rgba >> 16) & 0xff; + dst_b = (dst_rgba >> 8) & 0xff; +#else + dst_r = dst_abgr & 0xff; + dst_g = (dst_abgr >> 8) & 0xff; + dst_b = (dst_abgr >> 16) & 0xff; +#endif + dst_r += (((r - dst_r) * c + 0x8000) >> 16); + dst_g += (((g - dst_g) * c + 0x8000) >> 16); + dst_b += (((b - dst_b) * c + 0x8000) >> 16); +#ifdef WORDS_BIGENDIAN + ((art_u32 *)buf)[i] = (dst_r << 24) | (dst_g << 16) | (dst_b << 8) | a; +#else + ((art_u32 *)buf)[i] = (a << 24) | (dst_b << 16) | (dst_g << 8) | dst_r; +#endif + } + else + { +#ifdef WORDS_BIGENDIAN + ((art_u32 *)buf)[i] = src_rgba; +#else + ((art_u32 *)buf)[i] = src_abgr; +#endif + } + } +}