X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fart%2Fart_render_mask.c;fp=lib%2Fart%2Fart_render_mask.c;h=ce82608dcdf610e580a76699ba1f4ef73abe7b56;hb=418ef05b5d0b74e6f19200ffa40bcc3afccb5029;hp=0000000000000000000000000000000000000000;hpb=c1f4a906117e98e2f4ba59abc1ce153e8129bc19;p=swftools.git diff --git a/lib/art/art_render_mask.c b/lib/art/art_render_mask.c new file mode 100644 index 0000000..ce82608 --- /dev/null +++ b/lib/art/art_render_mask.c @@ -0,0 +1,168 @@ +/* + * art_render_mask.c: Alpha mask source for modular rendering. + * + * 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. + * + * Authors: Raph Levien + */ + +#include "config.h" +#include "art_render_mask.h" + +#include + + +typedef struct _ArtMaskSourceMask ArtMaskSourceMask; + +struct _ArtMaskSourceMask { + ArtMaskSource super; + ArtRender *render; + art_boolean first; + int x0; + int y0; + int x1; + int y1; + const art_u8 *mask_buf; + int rowstride; +}; + +static void +art_render_mask_done (ArtRenderCallback *self, ArtRender *render) +{ + art_free (self); +} + +static int +art_render_mask_can_drive (ArtMaskSource *self, ArtRender *render) +{ + return 0; +} + +static void +art_render_mask_render (ArtRenderCallback *self, ArtRender *render, + art_u8 *dest, int y) +{ + ArtMaskSourceMask *z = (ArtMaskSourceMask *)self; + int x0 = render->x0, x1 = render->x1; + int z_x0 = z->x0, z_x1 = z->x1; + int width = x1 - x0; + int z_width = z_x1 - z_x0; + art_u8 *alpha_buf = render->alpha_buf; + + if (y < z->y0 || y >= z->y1 || z_width <= 0) + memset (alpha_buf, 0, width); + else + { + const art_u8 *src_line = z->mask_buf + (y - z->y0) * z->rowstride; + art_u8 *dst_line = alpha_buf + z_x0 - x0; + + if (z_x0 > x0) + memset (alpha_buf, 0, z_x0 - x0); + + if (z->first) + memcpy (dst_line, src_line, z_width); + else + { + int x; + + for (x = 0; x < z_width; x++) + { + int v; + v = src_line[x]; + if (v) + { + v = v * dst_line[x] + 0x80; + v = (v + (v >> 8)) >> 8; + dst_line[x] = v; + } + else + { + dst_line[x] = 0; + } + } + } + + if (z_x1 < x1) + memset (alpha_buf + z_x1 - x0, 0, x1 - z_x1); + } +} + +static void +art_render_mask_prepare (ArtMaskSource *self, ArtRender *render, + art_boolean first) +{ + ArtMaskSourceMask *z = (ArtMaskSourceMask *)self; + self->super.render = art_render_mask_render; + z->first = first; +} + +/** + * art_render_mask: Use an alpha buffer as a render mask source. + * @render: Render object. + * @x0: Left coordinate of mask rect. + * @y0: Top coordinate of mask rect. + * @x1: Right coordinate of mask rect. + * @y1: Bottom coordinate of mask rect. + * @mask_buf: Buffer containing 8bpp alpha mask data. + * @rowstride: Rowstride of @mask_buf. + * + * Adds @mask_buf to the render object as a mask. Note: @mask_buf must + * remain allocated until art_render_invoke() is called on @render. + **/ +void +art_render_mask (ArtRender *render, + int x0, int y0, int x1, int y1, + const art_u8 *mask_buf, int rowstride) +{ + ArtMaskSourceMask *mask_source; + + if (x0 < render->x0) + { + mask_buf += render->x0 - x0; + x0 = render->x0; + } + if (x1 > render->x1) + x1 = render->x1; + + if (y0 < render->y0) + { + mask_buf += (render->y0 - y0) * rowstride; + y0 = render->y0; + } + if (y1 > render->y1) + y1 = render->y1; + + mask_source = art_new (ArtMaskSourceMask, 1); + + mask_source->super.super.render = NULL; + mask_source->super.super.done = art_render_mask_done; + mask_source->super.can_drive = art_render_mask_can_drive; + mask_source->super.invoke_driver = NULL; + mask_source->super.prepare = art_render_mask_prepare; + mask_source->render = render; + mask_source->x0 = x0; + mask_source->y0 = y0; + mask_source->x1 = x1; + mask_source->y1 = y1; + mask_source->mask_buf = mask_buf; + mask_source->rowstride = rowstride; + + art_render_add_mask_source (render, &mask_source->super); + +}