Remove unused libart_lgpl API.

According to CallCatcher.
This commit is contained in:
Matthew Barnes
2010-06-16 07:04:07 -04:00
parent f06717f6ef
commit d4a32e5a98
36 changed files with 0 additions and 5422 deletions

View File

@ -21,18 +21,11 @@ libart_lgplinclude_HEADERS = \
art_rect_svp.h \
art_rect_uta.h \
art_render.h \
art_render_gradient.h \
art_render_mask.h \
art_render_svp.h \
art_rgb.h \
art_rgb_a_affine.h \
art_rgb_affine.h \
art_rgb_affine_private.h \
art_rgb_bitmap_affine.h \
art_rgb_pixbuf_affine.h \
art_rgb_rgba_affine.h \
art_rgb_svp.h \
art_rgba.h \
art_svp.h \
art_svp_intersect.h \
art_svp_ops.h \
@ -42,7 +35,6 @@ libart_lgplinclude_HEADERS = \
art_svp_vpath_stroke.h \
art_svp_wind.h \
art_uta.h \
art_uta_ops.h \
art_uta_rect.h \
art_uta_svp.h \
art_uta_vpath.h \
@ -54,7 +46,6 @@ libart_lgplinclude_HEADERS = \
libart_lgpl_la_SOURCES = \
art_affine.c \
art_alphagamma.c \
art_bpath.c \
art_gray_svp.c \
art_misc.c \
@ -63,18 +54,11 @@ libart_lgpl_la_SOURCES = \
art_rect_svp.c \
art_rect_uta.c \
art_render.c \
art_render_gradient.c \
art_render_mask.c \
art_render_svp.c \
art_rgb.c \
art_rgb_a_affine.c \
art_rgb_affine.c \
art_rgb_affine_private.c \
art_rgb_bitmap_affine.c \
art_rgb_pixbuf_affine.c \
art_rgb_rgba_affine.c \
art_rgb_svp.c \
art_rgba.c \
art_svp.c \
art_svp_intersect.c \
art_svp_ops.c \
@ -82,9 +66,7 @@ libart_lgpl_la_SOURCES = \
art_svp_render_aa.c \
art_svp_vpath.c \
art_svp_vpath_stroke.c \
art_svp_wind.c \
art_uta.c \
art_uta_ops.c \
art_uta_rect.c \
art_uta_svp.c \
art_uta_vpath.c \

View File

@ -77,29 +77,6 @@ art_affine_invert (double dst[6], const double src[6])
dst[5] = -src[4] * dst[1] - src[5] * dst[3];
}
/**
* art_affine_flip: Flip an affine transformation horizontally and/or vertically.
* @dst_affine: Where the resulting affine is stored.
* @src_affine: The original affine transformation.
* @horiz: Whether or not to flip horizontally.
* @vert: Whether or not to flip horizontally.
*
* Flips the affine transform. FALSE for both @horiz and @vert implements
* a simple copy operation. TRUE for both @horiz and @vert is a
* 180 degree rotation. It is ok for @src_affine and @dst_affine to
* be equal pointers.
**/
void
art_affine_flip (double dst_affine[6], const double src_affine[6], int horz, int vert)
{
dst_affine[0] = horz ? - src_affine[0] : src_affine[0];
dst_affine[1] = horz ? - src_affine[1] : src_affine[1];
dst_affine[2] = vert ? - src_affine[2] : src_affine[2];
dst_affine[3] = vert ? - src_affine[3] : src_affine[3];
dst_affine[4] = horz ? - src_affine[4] : src_affine[4];
dst_affine[5] = vert ? - src_affine[5] : src_affine[5];
}
#define EPSILON 1e-6
/* It's ridiculous I have to write this myself. This is hardcoded to
@ -334,55 +311,6 @@ art_affine_scale (double dst[6], double sx, double sy)
dst[5] = 0;
}
/**
* art_affine_rotate: Set up a rotation affine transform.
* @dst: Where to store the resulting affine transform.
* @theta: Rotation angle in degrees.
*
* Sets up a rotation matrix. In the standard libart coordinate
* system, in which increasing y moves downward, this is a
* counterclockwise rotation. In the standard PostScript coordinate
* system, which is reversed in the y direction, it is a clockwise
* rotation.
**/
void
art_affine_rotate (double dst[6], double theta)
{
double s, c;
s = sin (theta * M_PI / 180.0);
c = cos (theta * M_PI / 180.0);
dst[0] = c;
dst[1] = s;
dst[2] = -s;
dst[3] = c;
dst[4] = 0;
dst[5] = 0;
}
/**
* art_affine_shear: Set up a shearing matrix.
* @dst: Where to store the resulting affine transform.
* @theta: Shear angle in degrees.
*
* Sets up a shearing matrix. In the standard libart coordinate system
* and a small value for theta, || becomes \\. Horizontal lines remain
* unchanged.
**/
void
art_affine_shear (double dst[6], double theta)
{
double t;
t = tan (theta * M_PI / 180.0);
dst[0] = 1;
dst[1] = 0;
dst[2] = t;
dst[3] = 1;
dst[4] = 0;
dst[5] = 0;
}
/**
* art_affine_translate: Set up a translation matrix.
* @dst: Where to store the resulting affine transform.
@ -419,40 +347,3 @@ art_affine_expansion (const double src[6])
return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
}
/**
* art_affine_rectilinear: Determine whether the affine transformation is rectilinear.
* @src: The original affine transformation.
*
* Determines whether @src is rectilinear, i.e. grid-aligned
* rectangles are transformed to other grid-aligned rectangles. The
* implementation has epsilon-tolerance for roundoff errors.
*
* Return value: TRUE if @src is rectilinear.
**/
int
art_affine_rectilinear (const double src[6])
{
return ((fabs (src[1]) < EPSILON && fabs (src[2]) < EPSILON) ||
(fabs (src[0]) < EPSILON && fabs (src[3]) < EPSILON));
}
/**
* art_affine_equal: Determine whether two affine transformations are equal.
* @matrix1: An affine transformation.
* @matrix2: Another affine transformation.
*
* Determines whether @matrix1 and @matrix2 are equal, with
* epsilon-tolerance for roundoff errors.
*
* Return value: TRUE if @matrix1 and @matrix2 are equal.
**/
int
art_affine_equal (double matrix1[6], double matrix2[6])
{
return (fabs (matrix1[0] - matrix2[0]) < EPSILON &&
fabs (matrix1[1] - matrix2[1]) < EPSILON &&
fabs (matrix1[2] - matrix2[2]) < EPSILON &&
fabs (matrix1[3] - matrix2[3]) < EPSILON &&
fabs (matrix1[4] - matrix2[4]) < EPSILON &&
fabs (matrix1[5] - matrix2[5]) < EPSILON);
}

View File

@ -33,12 +33,6 @@ art_affine_point (ArtPoint *dst, const ArtPoint *src,
void
art_affine_invert (double dst_affine[6], const double src_affine[6]);
/* flip the matrix, FALSE, FALSE is a simple copy operation, and
TRUE, TRUE equals a rotation by 180 degrees */
void
art_affine_flip (double dst_affine[6], const double src_affine[6],
int horz, int vert);
void
art_affine_to_string (char str[128], const double src[6]);
@ -54,14 +48,6 @@ art_affine_identity (double dst[6]);
void
art_affine_scale (double dst[6], double sx, double sy);
/* set up a rotation matrix; theta is given in degrees */
void
art_affine_rotate (double dst[6], double theta);
/* set up a shearing matrix; theta is given in degrees */
void
art_affine_shear (double dst[6], double theta);
/* set up a translation matrix */
void
art_affine_translate (double dst[6], double tx, double ty);
@ -71,16 +57,6 @@ art_affine_translate (double dst[6], double tx, double ty);
double
art_affine_expansion (const double src[6]);
/* Determine whether the affine transformation is rectilinear,
i.e. whether a rectangle aligned to the grid is transformed into
another rectangle aligned to the grid. */
int
art_affine_rectilinear (const double src[6]);
/* Determine whether two affine transformations are equal within grid allignment */
int
art_affine_equal (double matrix1[6], double matrix2[6]);
#ifdef __cplusplus
}

View File

@ -1,85 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998 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.
*/
/* Some functions to build alphagamma tables */
#include "config.h"
#include "art_alphagamma.h"
#include <math.h>
/**
* art_alphagamma_new: Create a new #ArtAlphaGamma.
* @gamma: Gamma value.
*
* Create a new #ArtAlphaGamma for a specific value of @gamma. When
* correctly implemented (which is generally not the case in libart),
* alpha compositing with an alphagamma parameter is equivalent to
* applying the gamma transformation to source images, doing the alpha
* compositing (in linear intensity space), then applying the inverse
* gamma transformation, bringing it back to a gamma-adjusted
* intensity space.
*
* Return value: The newly created #ArtAlphaGamma.
**/
ArtAlphaGamma *
art_alphagamma_new (double gamma)
{
int tablesize;
ArtAlphaGamma *alphagamma;
int i;
int *table;
art_u8 *invtable;
double s, r_gamma;
tablesize = ceil (gamma * 8);
if (tablesize < 10)
tablesize = 10;
alphagamma = (ArtAlphaGamma *)art_alloc (sizeof(ArtAlphaGamma) +
((1 << tablesize) - 1) *
sizeof(art_u8));
alphagamma->gamma = gamma;
alphagamma->invtable_size = tablesize;
table = alphagamma->table;
for (i = 0; i < 256; i++)
table[i] = (int)floor (((1 << tablesize) - 1) *
pow (i * (1.0 / 255), gamma) + 0.5);
invtable = alphagamma->invtable;
s = 1.0 / ((1 << tablesize) - 1);
r_gamma = 1.0 / gamma;
for (i = 0; i < 1 << tablesize; i++)
invtable[i] = (int)floor (255 * pow (i * s, r_gamma) + 0.5);
return alphagamma;
}
/**
* art_alphagamma_free: Free an #ArtAlphaGamma.
* @alphagamma: An #ArtAlphaGamma.
*
* Frees the #ArtAlphaGamma.
**/
void
art_alphagamma_free (ArtAlphaGamma *alphagamma)
{
art_free (alphagamma);
}

View File

@ -38,12 +38,6 @@ struct _ArtAlphaGamma {
art_u8 invtable[1];
};
ArtAlphaGamma *
art_alphagamma_new (double gamma);
void
art_alphagamma_free (ArtAlphaGamma *alphagamma);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -111,175 +111,3 @@ art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstrid
return pixbuf;
}
/**
* art_pixbuf_new_const_rgb: Create a new RGB #ArtPixBuf with constant pixel data.
* @pixels: A buffer containing the actual pixel data.
* @width: The width of the pixbuf.
* @height: The height of the pixbuf.
* @rowstride: The rowstride of the pixbuf.
*
* Creates a generic data structure for holding a buffer of RGB
* pixels. It is possible to think of an #ArtPixBuf as a
* virtualization over specific pixel buffer formats.
*
* No action is taken when the #ArtPixBuf is destroyed. Thus, this
* function is useful when the pixel data is constant or statically
* allocated.
*
* Return value: The newly created #ArtPixBuf.
**/
ArtPixBuf *
art_pixbuf_new_const_rgb (const art_u8 *pixels, int width, int height, int rowstride)
{
return art_pixbuf_new_rgb_dnotify ((art_u8 *) pixels, width, height, rowstride, NULL, NULL);
}
/**
* art_pixbuf_new_const_rgba: Create a new RGBA #ArtPixBuf with constant pixel data.
* @pixels: A buffer containing the actual pixel data.
* @width: The width of the pixbuf.
* @height: The height of the pixbuf.
* @rowstride: The rowstride of the pixbuf.
*
* Creates a generic data structure for holding a buffer of RGBA
* pixels. It is possible to think of an #ArtPixBuf as a
* virtualization over specific pixel buffer formats.
*
* No action is taken when the #ArtPixBuf is destroyed. Thus, this
* function is suitable when the pixel data is constant or statically
* allocated.
*
* Return value: The newly created #ArtPixBuf.
**/
ArtPixBuf *
art_pixbuf_new_const_rgba (const art_u8 *pixels, int width, int height, int rowstride)
{
return art_pixbuf_new_rgba_dnotify ((art_u8 *) pixels, width, height, rowstride, NULL, NULL);
}
static void
art_pixel_destroy (void *func_data, void *data)
{
art_free (data);
}
/**
* art_pixbuf_new_rgb: Create a new RGB #ArtPixBuf.
* @pixels: A buffer containing the actual pixel data.
* @width: The width of the pixbuf.
* @height: The height of the pixbuf.
* @rowstride: The rowstride of the pixbuf.
*
* Creates a generic data structure for holding a buffer of RGB
* pixels. It is possible to think of an #ArtPixBuf as a
* virtualization over specific pixel buffer formats.
*
* The @pixels buffer is freed with art_free() when the #ArtPixBuf is
* destroyed. Thus, this function is suitable when the pixel data is
* allocated with art_alloc().
*
* Return value: The newly created #ArtPixBuf.
**/
ArtPixBuf *
art_pixbuf_new_rgb (art_u8 *pixels, int width, int height, int rowstride)
{
return art_pixbuf_new_rgb_dnotify (pixels, width, height, rowstride, NULL, art_pixel_destroy);
}
/**
* art_pixbuf_new_rgba: Create a new RGBA #ArtPixBuf.
* @pixels: A buffer containing the actual pixel data.
* @width: The width of the pixbuf.
* @height: The height of the pixbuf.
* @rowstride: The rowstride of the pixbuf.
*
* Creates a generic data structure for holding a buffer of RGBA
* pixels. It is possible to think of an #ArtPixBuf as a
* virtualization over specific pixel buffer formats.
*
* The @pixels buffer is freed with art_free() when the #ArtPixBuf is
* destroyed. Thus, this function is suitable when the pixel data is
* allocated with art_alloc().
*
* Return value: The newly created #ArtPixBuf.
**/
ArtPixBuf *
art_pixbuf_new_rgba (art_u8 *pixels, int width, int height, int rowstride)
{
return art_pixbuf_new_rgba_dnotify (pixels, width, height, rowstride, NULL, art_pixel_destroy);
}
/**
* art_pixbuf_free: Destroy an #ArtPixBuf.
* @pixbuf: The #ArtPixBuf to be destroyed.
*
* Destroys the #ArtPixBuf, calling the destroy notification function
* (if non-NULL) so that the memory for the pixel buffer can be
* properly reclaimed.
**/
void
art_pixbuf_free (ArtPixBuf *pixbuf)
{
ArtDestroyNotify destroy = pixbuf->destroy;
void *destroy_data = pixbuf->destroy_data;
art_u8 *pixels = pixbuf->pixels;
pixbuf->pixels = NULL;
pixbuf->destroy = NULL;
pixbuf->destroy_data = NULL;
if (destroy)
destroy (destroy_data, pixels);
art_free (pixbuf);
}
/**
* art_pixbuf_free_shallow:
* @pixbuf: The #ArtPixBuf to be destroyed.
*
* Destroys the #ArtPixBuf without calling the destroy notification function.
*
* This function is deprecated. Use the _dnotify variants for
* allocation instead.
**/
void
art_pixbuf_free_shallow (ArtPixBuf *pixbuf)
{
art_free (pixbuf);
}
/**
* art_pixbuf_duplicate: Duplicate a pixbuf.
* @pixbuf: The #ArtPixBuf to duplicate.
*
* Duplicates a pixbuf, including duplicating the buffer.
*
* Return value: The duplicated pixbuf.
**/
ArtPixBuf *
art_pixbuf_duplicate (const ArtPixBuf *pixbuf)
{
ArtPixBuf *result;
int size;
result = art_new (ArtPixBuf, 1);
result->format = pixbuf->format;
result->n_channels = pixbuf->n_channels;
result->has_alpha = pixbuf->has_alpha;
result->bits_per_sample = pixbuf->bits_per_sample;
size = (pixbuf->height - 1) * pixbuf->rowstride +
pixbuf->width * ((pixbuf->n_channels * pixbuf->bits_per_sample + 7) >> 3);
result->pixels = art_alloc (size);
memcpy (result->pixels, pixbuf->pixels, size);
result->width = pixbuf->width;
result->height = pixbuf->height;
result->rowstride = pixbuf->rowstride;
result->destroy_data = NULL;
result->destroy = art_pixel_destroy;
return result;
}

View File

@ -59,20 +59,6 @@ struct _ArtPixBuf {
ArtDestroyNotify destroy;
};
/* allocate an ArtPixBuf from art_alloc()ed pixels (automated destruction) */
ArtPixBuf *
art_pixbuf_new_rgb (art_u8 *pixels, int width, int height, int rowstride);
ArtPixBuf *
art_pixbuf_new_rgba (art_u8 *pixels, int width, int height, int rowstride);
/* allocate an ArtPixBuf from constant pixels (no destruction) */
ArtPixBuf *
art_pixbuf_new_const_rgb (const art_u8 *pixels, int width, int height, int rowstride);
ArtPixBuf *
art_pixbuf_new_const_rgba (const art_u8 *pixels, int width, int height, int rowstride);
/* allocate an ArtPixBuf and notify creator upon destruction */
ArtPixBuf *
art_pixbuf_new_rgb_dnotify (art_u8 *pixels, int width, int height, int rowstride,
@ -82,17 +68,6 @@ ArtPixBuf *
art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstride,
void *dfunc_data, ArtDestroyNotify dfunc);
/* free an ArtPixBuf with destroy notification */
void
art_pixbuf_free (ArtPixBuf *pixbuf);
/* deprecated function, use the _dnotify variants for allocation instead */
void
art_pixbuf_free_shallow (ArtPixBuf *pixbuf);
ArtPixBuf *
art_pixbuf_duplicate (const ArtPixBuf *pixbuf);
#ifdef __cplusplus
}
#endif

View File

@ -47,28 +47,6 @@ art_irect_copy (ArtIRect *dest, const ArtIRect *src) {
dest->y1 = src->y1;
}
/**
* art_irect_union: Find union of two integer rectangles.
* @dest: Where the result is stored.
* @src1: A source rectangle.
* @src2: Another source rectangle.
*
* Finds the smallest rectangle that includes @src1 and @src2.
**/
void
art_irect_union (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
if (art_irect_empty (src1)) {
art_irect_copy (dest, src2);
} else if (art_irect_empty (src2)) {
art_irect_copy (dest, src1);
} else {
dest->x0 = MIN (src1->x0, src2->x0);
dest->y0 = MIN (src1->y0, src2->y0);
dest->x1 = MAX (src1->x1, src2->x1);
dest->y1 = MAX (src1->y1, src2->y1);
}
}
/**
* art_irect_intersection: Find intersection of two integer rectangles.
* @dest: Where the result is stored.
@ -140,22 +118,6 @@ art_drect_union (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
}
}
/**
* art_drect_intersection: Find intersection of two rectangles.
* @dest: Where the result is stored.
* @src1: A source rectangle.
* @src2: Another source rectangle.
*
* Finds the intersection of @src1 and @src2.
**/
void
art_drect_intersect (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
dest->x0 = MAX (src1->x0, src2->x0);
dest->y0 = MAX (src1->y0, src2->y0);
dest->x1 = MIN (src1->x1, src2->x1);
dest->y1 = MIN (src1->y1, src2->y1);
}
/**
* art_irect_empty: Determine whether rectangle is empty.
* @src: The source rectangle.

View File

@ -40,10 +40,6 @@ struct _ArtIRect {
/* Make a copy of the rectangle. */
void art_irect_copy (ArtIRect *dest, const ArtIRect *src);
/* Find the smallest rectangle that includes both source rectangles. */
void art_irect_union (ArtIRect *dest,
const ArtIRect *src1, const ArtIRect *src2);
/* Return the intersection of the two rectangles */
void art_irect_intersect (ArtIRect *dest,
const ArtIRect *src1, const ArtIRect *src2);
@ -58,10 +54,6 @@ void art_drect_copy (ArtDRect *dest, const ArtDRect *src);
void art_drect_union (ArtDRect *dest,
const ArtDRect *src1, const ArtDRect *src2);
/* Return the intersection of the two rectangles */
void art_drect_intersect (ArtDRect *dest,
const ArtDRect *src1, const ArtDRect *src2);
/* Return true if the rectangle is empty. */
int art_drect_empty (const ArtDRect *src);

View File

@ -39,115 +39,10 @@ struct _ArtRenderPriv {
ArtRenderCallback **callbacks;
};
ArtRender *
art_render_new (int x0, int y0, int x1, int y1,
art_u8 *pixels, int rowstride,
int n_chan, int depth, ArtAlphaType alpha_type,
ArtAlphaGamma *alphagamma)
{
ArtRenderPriv *priv;
ArtRender *result;
priv = art_new (ArtRenderPriv, 1);
result = &priv->super;
if (n_chan > ART_MAX_CHAN)
{
art_warn ("art_render_new: n_chan = %d, exceeds %d max\n",
n_chan, ART_MAX_CHAN);
return NULL;
}
if (depth > ART_MAX_DEPTH)
{
art_warn ("art_render_new: depth = %d, exceeds %d max\n",
depth, ART_MAX_DEPTH);
return NULL;
}
if (x0 >= x1)
{
art_warn ("art_render_new: x0 >= x1 (x0 = %d, x1 = %d)\n", x0, x1);
return NULL;
}
result->x0 = x0;
result->y0 = y0;
result->x1 = x1;
result->y1 = y1;
result->pixels = pixels;
result->rowstride = rowstride;
result->n_chan = n_chan;
result->depth = depth;
result->alpha_type = alpha_type;
result->clear = ART_FALSE;
result->opacity = 0x10000;
result->compositing_mode = ART_COMPOSITE_NORMAL;
result->alphagamma = alphagamma;
result->alpha_buf = NULL;
result->image_buf = NULL;
result->run = NULL;
result->span_x = NULL;
result->need_span = ART_FALSE;
priv->image_source = NULL;
priv->n_mask_source = 0;
priv->mask_source = NULL;
return result;
}
/* todo on clear routines: I haven't really figured out what to do
with clearing the alpha channel. It _should_ be possible to clear
to an arbitrary RGBA color. */
/**
* art_render_clear: Set clear color.
* @clear_color: Color with which to clear dest.
*
* Sets clear color, equivalent to actually clearing the destination
* buffer before rendering. This is the most general form.
**/
void
art_render_clear (ArtRender *render, const ArtPixMaxDepth *clear_color)
{
int i;
int n_ch = render->n_chan + (render->alpha_type != ART_ALPHA_NONE);
render->clear = ART_TRUE;
for (i = 0; i < n_ch; i++)
render->clear_color[i] = clear_color[i];
}
/**
* art_render_clear_rgb: Set clear color, given in RGB format.
* @clear_rgb: Clear color, in 0xRRGGBB format.
*
* Sets clear color, equivalent to actually clearing the destination
* buffer before rendering.
**/
void
art_render_clear_rgb (ArtRender *render, art_u32 clear_rgb)
{
if (render->n_chan != 3)
art_warn ("art_render_clear_rgb: called on render with %d channels, only works with 3\n",
render->n_chan);
else
{
int r, g, b;
render->clear = ART_TRUE;
r = clear_rgb >> 16;
g = (clear_rgb >> 8) & 0xff;
b = clear_rgb & 0xff;
render->clear_color[0] = ART_PIX_MAX_FROM_8(r);
render->clear_color[1] = ART_PIX_MAX_FROM_8(g);
render->clear_color[2] = ART_PIX_MAX_FROM_8(b);
}
}
static void
art_render_nop_done (ArtRenderCallback *self, ArtRender *render)
{
@ -238,43 +133,6 @@ const ArtRenderCallback art_render_clear_16_obj =
#endif /* ART_MAX_DEPTH >= 16 */
/* todo: inline */
static ArtRenderCallback *
art_render_choose_clear_callback (ArtRender *render)
{
ArtRenderCallback *clear_callback;
if (render->depth == 8)
{
if (render->n_chan == 3 &&
render->alpha_type == ART_ALPHA_NONE)
clear_callback = (ArtRenderCallback *)&art_render_clear_rgb8_obj;
else
clear_callback = (ArtRenderCallback *)&art_render_clear_8_obj;
}
#if ART_MAX_DEPTH >= 16
else if (render->depth == 16)
clear_callback = (ArtRenderCallback *)&art_render_clear_16_obj;
#endif
else
{
art_die ("art_render_choose_clear_callback: inconsistent render->depth = %d\n",
render->depth);
}
return clear_callback;
}
#if 0
/* todo: get around to writing this */
static void
art_render_composite_render_noa_8_norm (ArtRenderCallback *self, ArtRender *render,
art_u8 *dest, int y)
{
int width = render->x1 - render->x0;
}
#endif
/* This is the most general form of the function. It is slow but
(hopefully) correct. Actually, I'm still worried about roundoff
errors in the premul case - it seems to me that an off-by-one could
@ -882,27 +740,6 @@ const ArtRenderCallback art_render_composite_8_opt2_obj =
};
/* todo: inline */
static ArtRenderCallback *
art_render_choose_compositing_callback (ArtRender *render)
{
if (render->depth == 8 && render->buf_depth == 8)
{
if (render->n_chan == 3 &&
render->alpha_buf == NULL &&
render->alpha_type == ART_ALPHA_SEPARATE)
{
if (render->buf_alpha == ART_ALPHA_NONE)
return (ArtRenderCallback *)&art_render_composite_8_opt1_obj;
else if (render->buf_alpha == ART_ALPHA_PREMUL)
return (ArtRenderCallback *)&art_render_composite_8_opt2_obj;
}
return (ArtRenderCallback *)&art_render_composite_8_obj;
}
return (ArtRenderCallback *)&art_render_composite_obj;
}
/**
* art_render_invoke_callbacks: Invoke the callbacks in the render object.
* @render: The render object.
@ -929,184 +766,6 @@ art_render_invoke_callbacks (ArtRender *render, art_u8 *dest, int y)
}
}
/**
* art_render_invoke: Perform the requested rendering task.
* @render: The render object.
*
* Invokes the renderer and all sources associated with it, to perform
* the requested rendering task.
**/
void
art_render_invoke (ArtRender *render)
{
ArtRenderPriv *priv = (ArtRenderPriv *)render;
int width;
int best_driver, best_score;
int i;
int n_callbacks, n_callbacks_max;
ArtImageSource *image_source;
ArtImageSourceFlags image_flags;
int buf_depth;
ArtAlphaType buf_alpha;
art_boolean first = ART_TRUE;
if (render == NULL)
{
art_warn ("art_render_invoke: called with render == NULL\n");
return;
}
if (priv->image_source == NULL)
{
art_warn ("art_render_invoke: no image source given\n");
return;
}
width = render->x1 - render->x0;
render->run = art_new (ArtRenderMaskRun, width + 1);
/* Elect a mask source as driver. */
best_driver = -1;
best_score = 0;
for (i = 0; i < priv->n_mask_source; i++)
{
int score;
ArtMaskSource *mask_source;
mask_source = priv->mask_source[i];
score = mask_source->can_drive (mask_source, render);
if (score > best_score)
{
best_score = score;
best_driver = i;
}
}
/* Allocate alpha buffer if needed. */
if (priv->n_mask_source > 1 ||
(priv->n_mask_source == 1 && best_driver < 0))
{
render->alpha_buf = art_new (art_u8, (width * render->depth) >> 3);
}
/* Negotiate image rendering and compositing. */
image_source = priv->image_source;
image_source->negotiate (image_source, render, &image_flags, &buf_depth,
&buf_alpha);
/* Build callback list. */
n_callbacks_max = priv->n_mask_source + 3;
priv->callbacks = art_new (ArtRenderCallback *, n_callbacks_max);
n_callbacks = 0;
for (i = 0; i < priv->n_mask_source; i++)
if (i != best_driver)
{
ArtMaskSource *mask_source = priv->mask_source[i];
mask_source->prepare (mask_source, render, first);
first = ART_FALSE;
priv->callbacks[n_callbacks++] = &mask_source->super;
}
if (render->clear && !(image_flags & ART_IMAGE_SOURCE_CAN_CLEAR))
priv->callbacks[n_callbacks++] =
art_render_choose_clear_callback (render);
priv->callbacks[n_callbacks++] = &image_source->super;
/* Allocate image buffer and add compositing callback if needed. */
if (!(image_flags & ART_IMAGE_SOURCE_CAN_COMPOSITE))
{
int bytespp = ((render->n_chan + (buf_alpha != ART_ALPHA_NONE)) *
buf_depth) >> 3;
render->buf_depth = buf_depth;
render->buf_alpha = buf_alpha;
render->image_buf = art_new (art_u8, width * bytespp);
priv->callbacks[n_callbacks++] =
art_render_choose_compositing_callback (render);
}
priv->n_callbacks = n_callbacks;
if (render->need_span)
render->span_x = art_new (int, width + 1);
/* Invoke the driver */
if (best_driver >= 0)
{
ArtMaskSource *driver;
driver = priv->mask_source[best_driver];
driver->invoke_driver (driver, render);
}
else
{
art_u8 *dest_ptr = render->pixels;
int y;
/* Dummy driver */
render->n_run = 2;
render->run[0].x = render->x0;
render->run[0].alpha = 0x8000 + 0xff * render->opacity;
render->run[1].x = render->x1;
render->run[1].alpha = 0x8000;
if (render->need_span)
{
render->n_span = 2;
render->span_x[0] = render->x0;
render->span_x[1] = render->x1;
}
for (y = render->y0; y < render->y1; y++)
{
art_render_invoke_callbacks (render, dest_ptr, y);
dest_ptr += render->rowstride;
}
}
if (priv->mask_source != NULL)
art_free (priv->mask_source);
/* clean up callbacks */
for (i = 0; i < priv->n_callbacks; i++)
{
ArtRenderCallback *callback;
callback = priv->callbacks[i];
callback->done (callback, render);
}
/* Tear down object */
if (render->alpha_buf != NULL)
art_free (render->alpha_buf);
if (render->image_buf != NULL)
art_free (render->image_buf);
art_free (render->run);
if (render->span_x != NULL)
art_free (render->span_x);
art_free (priv->callbacks);
art_free (render);
}
/**
* art_render_mask_solid: Add a solid translucent mask.
* @render: The render object.
* @opacity: Opacity in [0..0x10000] form.
*
* Adds a translucent mask to the rendering object.
**/
void
art_render_mask_solid (ArtRender *render, int opacity)
{
art_u32 old_opacity = render->opacity;
art_u32 new_opacity_tmp;
if (opacity == 0x10000)
/* avoid potential overflow */
return;
new_opacity_tmp = old_opacity * (art_u32)opacity + 0x8000;
render->opacity = new_opacity_tmp >> 16;
}
/**
* art_render_add_mask_source: Add a mask source to the render object.
* @render: Render object.
@ -1170,214 +829,3 @@ struct _ArtImageSourceSolid {
art_boolean init;
};
static void
art_render_image_solid_done (ArtRenderCallback *self, ArtRender *render)
{
ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
if (z->rgbtab != NULL)
art_free (z->rgbtab);
art_free (self);
}
static void
art_render_image_solid_rgb8_opaq_init (ArtImageSourceSolid *self, ArtRender *render)
{
ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
ArtPixMaxDepth color_max;
int r_fg, g_fg, b_fg;
int r_bg, g_bg, b_bg;
int r, g, b;
int dr, dg, db;
int i;
int tmp;
art_u32 *rgbtab;
rgbtab = art_new (art_u32, 256);
z->rgbtab = rgbtab;
color_max = self->color[0];
r_fg = ART_PIX_8_FROM_MAX (color_max);
color_max = self->color[1];
g_fg = ART_PIX_8_FROM_MAX (color_max);
color_max = self->color[2];
b_fg = ART_PIX_8_FROM_MAX (color_max);
color_max = render->clear_color[0];
r_bg = ART_PIX_8_FROM_MAX (color_max);
color_max = render->clear_color[1];
g_bg = ART_PIX_8_FROM_MAX (color_max);
color_max = render->clear_color[2];
b_bg = ART_PIX_8_FROM_MAX (color_max);
r = (r_bg << 16) + 0x8000;
g = (g_bg << 16) + 0x8000;
b = (b_bg << 16) + 0x8000;
tmp = ((r_fg - r_bg) << 16) + 0x80;
dr = (tmp + (tmp >> 8)) >> 8;
tmp = ((g_fg - g_bg) << 16) + 0x80;
dg = (tmp + (tmp >> 8)) >> 8;
tmp = ((b_fg - b_bg) << 16) + 0x80;
db = (tmp + (tmp >> 8)) >> 8;
for (i = 0; i < 256; i++)
{
rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
r += dr;
g += dg;
b += db;
}
}
static void
art_render_image_solid_rgb8_opaq (ArtRenderCallback *self, ArtRender *render,
art_u8 *dest, int y)
{
ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
ArtRenderMaskRun *run = render->run;
int n_run = render->n_run;
art_u32 *rgbtab = z->rgbtab;
art_u32 rgb;
int x0 = render->x0;
int x1 = render->x1;
int run_x0, run_x1;
int i;
int ix;
if (n_run > 0)
{
run_x1 = run[0].x;
if (run_x1 > x0)
{
rgb = rgbtab[0];
art_rgb_fill_run (dest,
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
run_x1 - x0);
}
for (i = 0; i < n_run - 1; i++)
{
run_x0 = run_x1;
run_x1 = run[i + 1].x;
rgb = rgbtab[(run[i].alpha >> 16) & 0xff];
ix = (run_x0 - x0) * 3;
#define OPTIMIZE_LEN_1
#ifdef OPTIMIZE_LEN_1
if (run_x1 - run_x0 == 1)
{
dest[ix] = rgb >> 16;
dest[ix + 1] = (rgb >> 8) & 0xff;
dest[ix + 2] = rgb & 0xff;
}
else
{
art_rgb_fill_run (dest + ix,
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
run_x1 - run_x0);
}
#else
art_rgb_fill_run (dest + ix,
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
run_x1 - run_x0);
#endif
}
}
else
{
run_x1 = x0;
}
if (run_x1 < x1)
{
rgb = rgbtab[0];
art_rgb_fill_run (dest + (run_x1 - x0) * 3,
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
x1 - run_x1);
}
}
static void
art_render_image_solid_rgb8 (ArtRenderCallback *self, ArtRender *render,
art_u8 *dest, int y)
{
ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
int width = render->x1 - render->x0;
art_u8 r, g, b;
ArtPixMaxDepth color_max;
/* todo: replace this simple test with real sparseness */
if (z->init)
return;
z->init = ART_TRUE;
color_max = z->color[0];
r = ART_PIX_8_FROM_MAX (color_max);
color_max = z->color[1];
g = ART_PIX_8_FROM_MAX (color_max);
color_max = z->color[2];
b = ART_PIX_8_FROM_MAX (color_max);
art_rgb_fill_run (render->image_buf, r, g, b, width);
}
static void
art_render_image_solid_negotiate (ArtImageSource *self, ArtRender *render,
ArtImageSourceFlags *p_flags,
int *p_buf_depth, ArtAlphaType *p_alpha)
{
ArtImageSourceSolid *z = (ArtImageSourceSolid *)self;
ArtImageSourceFlags flags = 0;
static void (*render_cbk) (ArtRenderCallback *self, ArtRender *render,
art_u8 *dest, int y);
render_cbk = NULL;
if (render->depth == 8 && render->n_chan == 3 &&
render->alpha_type == ART_ALPHA_NONE)
{
if (render->clear)
{
render_cbk = art_render_image_solid_rgb8_opaq;
flags |= ART_IMAGE_SOURCE_CAN_CLEAR | ART_IMAGE_SOURCE_CAN_COMPOSITE;
art_render_image_solid_rgb8_opaq_init (z, render);
}
}
if (render_cbk == NULL)
{
if (render->depth == 8)
{
render_cbk = art_render_image_solid_rgb8;
*p_buf_depth = 8;
*p_alpha = ART_ALPHA_NONE; /* todo */
}
}
/* todo: general case */
self->super.render = render_cbk;
*p_flags = flags;
}
/**
* art_render_image_solid: Add a solid color image source.
* @render: The render object.
* @color: Color.
*
* Adds an image source with the solid color given by @color. The
* color need not be retained in memory after this call.
**/
void
art_render_image_solid (ArtRender *render, ArtPixMaxDepth *color)
{
ArtImageSourceSolid *image_source;
int i;
image_source = art_new (ArtImageSourceSolid, 1);
image_source->super.super.render = NULL;
image_source->super.super.done = art_render_image_solid_done;
image_source->super.negotiate = art_render_image_solid_negotiate;
for (i = 0; i < render->n_chan; i++)
image_source->color[i] = color[i];
image_source->rgbtab = NULL;
image_source->init = ART_FALSE;
art_render_add_image_source (render, &image_source->super);
}

View File

@ -139,27 +139,6 @@ struct _ArtRender {
art_boolean need_span;
};
ArtRender *
art_render_new (int x0, int y0, int x1, int y1,
art_u8 *pixels, int rowstride,
int n_chan, int depth, ArtAlphaType alpha_type,
ArtAlphaGamma *alphagamma);
void
art_render_invoke (ArtRender *render);
void
art_render_clear (ArtRender *render, const ArtPixMaxDepth *clear_color);
void
art_render_clear_rgb (ArtRender *render, art_u32 clear_rgb);
void
art_render_mask_solid (ArtRender *render, int opacity);
void
art_render_image_solid (ArtRender *render, ArtPixMaxDepth *color);
/* The next two functions are for custom mask sources only. */
void
art_render_add_mask_source (ArtRender *render, ArtMaskSource *mask_source);

View File

@ -1,716 +0,0 @@
/*
* art_render_gradient.c: Gradient image 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 <raph@acm.org>
* Alexander Larsson <alla@lysator.liu.se>
*/
#include "config.h"
#include "art_render_gradient.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
/* Hack to find out how to define alloca on different platforms.
* Modified version of glib/galloca.h.
*/
#ifdef __GNUC__
/* GCC does the right thing */
# undef alloca
# define alloca(size) __builtin_alloca (size)
#elif defined (HAVE_ALLOCA_H)
/* a native and working alloca.h is there */
# include <alloca.h>
#else /* !__GNUC__ && !HAVE_ALLOCA_H */
# ifdef _MSC_VER
# include <malloc.h>
# define alloca _alloca
# else /* !_MSC_VER */
# ifdef _AIX
#pragma alloca
# else /* !_AIX */
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif /* !alloca */
# endif /* !_AIX */
# endif /* !_MSC_VER */
#endif /* !__GNUC__ && !HAVE_ALLOCA_H */
#undef DEBUG_SPEW
typedef struct _ArtImageSourceGradLin ArtImageSourceGradLin;
typedef struct _ArtImageSourceGradRad ArtImageSourceGradRad;
/* The stops will be copied right after this structure */
struct _ArtImageSourceGradLin {
ArtImageSource super;
ArtGradientLinear gradient;
ArtGradientStop stops[1];
};
/* The stops will be copied right after this structure */
struct _ArtImageSourceGradRad {
ArtImageSource super;
ArtGradientRadial gradient;
double a;
ArtGradientStop stops[1];
};
#define EPSILON 1e-6
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif /* MAX */
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif /* MIN */
static void
art_rgba_gradient_run (art_u8 *buf,
art_u8 *color1,
art_u8 *color2,
int len)
{
int i;
int r, g, b, a;
int dr, dg, db, da;
#ifdef DEBUG_SPEW
printf ("gradient run from %3d %3d %3d %3d to %3d %3d %3d %3d in %d pixels\n",
color1[0], color1[1], color1[2], color1[3],
color2[0], color2[1], color2[2], color2[3],
len);
#endif
r = (color1[0] << 16) + 0x8000;
g = (color1[1] << 16) + 0x8000;
b = (color1[2] << 16) + 0x8000;
a = (color1[3] << 16) + 0x8000;
dr = ((color2[0] - color1[0]) << 16) / len;
dg = ((color2[1] - color1[1]) << 16) / len;
db = ((color2[2] - color1[2]) << 16) / len;
da = ((color2[3] - color1[3]) << 16) / len;
for (i = 0; i < len; i++)
{
*buf++ = (r>>16);
*buf++ = (g>>16);
*buf++ = (b>>16);
*buf++ = (a>>16);
r += dr;
g += dg;
b += db;
a += da;
}
}
static void
calc_color_at (ArtGradientStop *stops,
int n_stops,
ArtGradientSpread spread,
double offset,
double offset_fraction,
int favor_start,
int ix,
art_u8 *color)
{
double off0, off1;
int j;
if (spread == ART_GRADIENT_PAD)
{
if (offset < 0.0)
{
color[0] = ART_PIX_8_FROM_MAX (stops[0].color[0]);
color[1] = ART_PIX_8_FROM_MAX (stops[0].color[1]);
color[2] = ART_PIX_8_FROM_MAX (stops[0].color[2]);
color[3] = ART_PIX_8_FROM_MAX (stops[0].color[3]);
return;
}
if (offset >= 1.0)
{
color[0] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[0]);
color[1] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[1]);
color[2] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[2]);
color[3] = ART_PIX_8_FROM_MAX (stops[n_stops-1].color[3]);
return;
}
}
if (ix > 0 && ix < n_stops)
{
off0 = stops[ix - 1].offset;
off1 = stops[ix].offset;
if (fabs (off1 - off0) > EPSILON)
{
double interp;
double o;
o = offset_fraction;
if ((fabs (o) < EPSILON) && (!favor_start))
o = 1.0;
else if ((fabs (o-1.0) < EPSILON) && (favor_start))
o = 0.0;
/*
if (offset_fraction == 0.0 && !favor_start)
offset_fraction = 1.0;
*/
interp = (o - off0) / (off1 - off0);
for (j = 0; j < 4; j++)
{
int z0, z1;
int z;
z0 = stops[ix - 1].color[j];
z1 = stops[ix].color[j];
z = floor (z0 + (z1 - z0) * interp + 0.5);
color[j] = ART_PIX_8_FROM_MAX (z);
}
return;
}
/* If offsets are too close to safely do the division, just
pick the ix color. */
color[0] = ART_PIX_8_FROM_MAX (stops[ix].color[0]);
color[1] = ART_PIX_8_FROM_MAX (stops[ix].color[1]);
color[2] = ART_PIX_8_FROM_MAX (stops[ix].color[2]);
color[3] = ART_PIX_8_FROM_MAX (stops[ix].color[3]);
return;
}
printf ("WARNING! bad ix %d in calc_color_at() [internal error]\n", ix);
assert (0);
}
static void
art_render_gradient_linear_render_8 (ArtRenderCallback *self,
ArtRender *render,
art_u8 *dest, int y)
{
ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
const ArtGradientLinear *gradient = &(z->gradient);
int i;
int width = render->x1 - render->x0;
int len;
double offset, d_offset;
double offset_fraction;
int next_stop;
int ix;
art_u8 color1[4], color2[4];
int n_stops = gradient->n_stops;
int extra_stops;
ArtGradientStop *stops = gradient->stops;
ArtGradientStop *tmp_stops;
art_u8 *bufp = render->image_buf;
ArtGradientSpread spread = gradient->spread;
#ifdef DEBUG_SPEW
printf ("x1: %d, x2: %d, y: %d\n", render->x0, render->x1, y);
printf ("spread: %d, stops:", gradient->spread);
for (i=0;i<n_stops;i++)
{
printf ("%f, ", gradient->stops[i].offset);
}
printf ("\n");
printf ("a: %f, b: %f, c: %f\n", gradient->a, gradient->b, gradient->c);
#endif
offset = render->x0 * gradient->a + y * gradient->b + gradient->c;
d_offset = gradient->a;
/* We need to force the gradient to extend the whole 0..1 segment,
because the rest of the code doesn't handle partial gradients
correctly */
if ((gradient->stops[0].offset > EPSILON /* == 0.0 */) ||
(gradient->stops[n_stops-1].offset < (1.0 - EPSILON)))
{
extra_stops = 0;
tmp_stops = stops = alloca (sizeof (ArtGradientStop) * (n_stops + 2));
if (gradient->stops[0].offset > EPSILON /* 0.0 */)
{
memcpy (tmp_stops, gradient->stops, sizeof (ArtGradientStop));
tmp_stops[0].offset = 0.0;
tmp_stops += 1;
extra_stops++;
}
memcpy (tmp_stops, gradient->stops, sizeof (ArtGradientStop) * n_stops);
if (gradient->stops[n_stops-1].offset < (1.0 - EPSILON))
{
tmp_stops += n_stops;
memcpy (tmp_stops, &gradient->stops[n_stops-1], sizeof (ArtGradientStop));
tmp_stops[0].offset = 1.0;
extra_stops++;
}
n_stops += extra_stops;
#ifdef DEBUG_SPEW
printf ("start/stop modified stops:");
for (i=0;i<n_stops;i++)
{
printf ("%f, ", stops[i].offset);
}
printf ("\n");
#endif
}
if (spread == ART_GRADIENT_REFLECT)
{
tmp_stops = stops;
stops = alloca (sizeof (ArtGradientStop) * n_stops * 2);
memcpy (stops, tmp_stops, sizeof (ArtGradientStop) * n_stops);
for (i = 0; i< n_stops; i++)
{
stops[n_stops * 2 - 1 - i].offset = (1.0 - stops[i].offset / 2.0);
memcpy (stops[n_stops * 2 - 1 - i].color, stops[i].color, sizeof (stops[i].color));
stops[i].offset = stops[i].offset / 2.0;
}
spread = ART_GRADIENT_REPEAT;
offset = offset / 2.0;
d_offset = d_offset / 2.0;
n_stops = 2 * n_stops;
#ifdef DEBUG_SPEW
printf ("reflect modified stops:");
for (i=0;i<n_stops;i++)
{
printf ("%f, ", stops[i].offset);
}
printf ("\n");
#endif
}
offset_fraction = offset - floor (offset);
#ifdef DEBUG_SPEW
printf ("inital offset: %f, fraction: %f d_offset: %f\n", offset, offset_fraction, d_offset);
#endif
/* ix is selected so that offset_fraction is
stops[ix-1] <= offset_fraction <= stops[ix]
If offset_fraction is equal to one of the edges, ix
is selected so the the section of the line extending
in the same direction as d_offset is between ix-1 and ix.
*/
for (ix = 0; ix < n_stops; ix++)
if (stops[ix].offset > offset_fraction ||
(d_offset < 0.0 && fabs (stops[ix].offset - offset_fraction) < EPSILON))
break;
if (ix == 0)
ix = n_stops - 1;
else if (ix == n_stops)
ix = n_stops - 1;
#ifdef DEBUG_SPEW
printf ("Initial ix: %d\n", ix);
#endif
assert (ix > 0);
assert (ix < n_stops);
assert ((stops[ix-1].offset <= offset_fraction + EPSILON) ||
((stops[ix].offset > (1.0 - EPSILON)) && (offset_fraction < EPSILON /* == 0.0*/)));
assert (offset_fraction <= stops[ix].offset);
/* FIXME: These asserts may be broken, it is for now
safer to not use them. Should be fixed!
See bug #121850
assert ((offset_fraction != stops[ix-1].offset) ||
(d_offset >= 0.0));
assert ((offset_fraction != stops[ix].offset) ||
(d_offset <= 0.0));
*/
while (width > 0)
{
#ifdef DEBUG_SPEW
printf ("ix: %d\n", ix);
printf ("start offset: %f\n", offset);
#endif
calc_color_at (stops, n_stops,
spread,
offset,
offset_fraction,
(d_offset > -EPSILON),
ix,
color1);
if (d_offset > 0)
next_stop = ix;
else
next_stop = ix-1;
#ifdef DEBUG_SPEW
printf ("next_stop: %d\n", next_stop);
#endif
if (fabs (d_offset) > EPSILON)
{
double o;
o = offset_fraction;
if ((fabs (o) <= EPSILON) && (ix == n_stops - 1))
o = 1.0;
else if ((fabs (o-1.0) <= EPSILON) && (ix == 1))
o = 0.0;
#ifdef DEBUG_SPEW
printf ("o: %f\n", o);
#endif
len = (int)floor (fabs ((stops[next_stop].offset - o) / d_offset)) + 1;
len = MAX (len, 0);
len = MIN (len, width);
}
else
{
len = width;
}
#ifdef DEBUG_SPEW
printf ("len: %d\n", len);
#endif
if (len > 0)
{
offset = offset + (len-1) * d_offset;
offset_fraction = offset - floor (offset);
#ifdef DEBUG_SPEW
printf ("end offset: %f, fraction: %f\n", offset, offset_fraction);
#endif
calc_color_at (stops, n_stops,
spread,
offset,
offset_fraction,
(d_offset < EPSILON),
ix,
color2);
art_rgba_gradient_run (bufp,
color1,
color2,
len);
offset += d_offset;
offset_fraction = offset - floor (offset);
}
if (d_offset > 0)
{
do
{
ix++;
if (ix == n_stops)
ix = 1;
/* Note: offset_fraction can actually be one here on x86 machines that
does calculations with extended precision, but later rounds to 64bit.
This happens if the 80bit offset_fraction is larger than the
largest 64bit double that is less than one.
*/
}
while (!((stops[ix-1].offset <= offset_fraction &&
offset_fraction < stops[ix].offset) ||
(ix == 1 && offset_fraction > (1.0 - EPSILON))));
}
else
{
do
{
ix--;
if (ix == 0)
ix = n_stops - 1;
}
while (!((stops[ix-1].offset < offset_fraction &&
offset_fraction <= stops[ix].offset) ||
(ix == n_stops - 1 && offset_fraction < EPSILON /* == 0.0*/)));
}
bufp += 4*len;
width -= len;
}
}
/**
* art_render_gradient_setpix: Set a gradient pixel.
* @render: The render object.
* @dst: Pointer to destination (where to store pixel).
* @n_stops: Number of stops in @stops.
* @stops: The stops for the gradient.
* @offset: The offset.
*
* @n_stops must be > 0.
*
* Sets a gradient pixel, storing it at @dst.
**/
static void
art_render_gradient_setpix (ArtRender *render,
art_u8 *dst,
int n_stops, ArtGradientStop *stops,
double offset)
{
int ix;
int j;
double off0, off1;
int n_ch = render->n_chan + 1;
for (ix = 0; ix < n_stops; ix++)
if (stops[ix].offset > offset)
break;
/* stops[ix - 1].offset < offset < stops[ix].offset */
if (ix > 0 && ix < n_stops)
{
off0 = stops[ix - 1].offset;
off1 = stops[ix].offset;
if (fabs (off1 - off0) > EPSILON)
{
double interp;
interp = (offset - off0) / (off1 - off0);
for (j = 0; j < n_ch; j++)
{
int z0, z1;
int z;
z0 = stops[ix - 1].color[j];
z1 = stops[ix].color[j];
z = floor (z0 + (z1 - z0) * interp + 0.5);
if (render->buf_depth == 8)
dst[j] = ART_PIX_8_FROM_MAX (z);
else /* (render->buf_depth == 16) */
((art_u16 *)dst)[j] = z;
}
return;
}
}
else if (ix == n_stops)
ix--;
for (j = 0; j < n_ch; j++)
{
int z;
z = stops[ix].color[j];
if (render->buf_depth == 8)
dst[j] = ART_PIX_8_FROM_MAX (z);
else /* (render->buf_depth == 16) */
((art_u16 *)dst)[j] = z;
}
}
static void
art_render_gradient_linear_done (ArtRenderCallback *self, ArtRender *render)
{
art_free (self);
}
static void
art_render_gradient_linear_render (ArtRenderCallback *self, ArtRender *render,
art_u8 *dest, int y)
{
ArtImageSourceGradLin *z = (ArtImageSourceGradLin *)self;
const ArtGradientLinear *gradient = &(z->gradient);
int pixstride = (render->n_chan + 1) * (render->depth >> 3);
int x;
int width = render->x1 - render->x0;
double offset, d_offset;
double actual_offset;
int n_stops = gradient->n_stops;
ArtGradientStop *stops = gradient->stops;
art_u8 *bufp = render->image_buf;
ArtGradientSpread spread = gradient->spread;
offset = render->x0 * gradient->a + y * gradient->b + gradient->c;
d_offset = gradient->a;
for (x = 0; x < width; x++)
{
if (spread == ART_GRADIENT_PAD)
actual_offset = offset;
else if (spread == ART_GRADIENT_REPEAT)
actual_offset = offset - floor (offset);
else /* (spread == ART_GRADIENT_REFLECT) */
{
double tmp;
tmp = offset - 2 * floor (0.5 * offset);
actual_offset = tmp > 1 ? 2 - tmp : tmp;
}
art_render_gradient_setpix (render, bufp, n_stops, stops, actual_offset);
offset += d_offset;
bufp += pixstride;
}
}
static void
art_render_gradient_linear_negotiate (ArtImageSource *self, ArtRender *render,
ArtImageSourceFlags *p_flags,
int *p_buf_depth, ArtAlphaType *p_alpha)
{
if (render->depth == 8 &&
render->n_chan == 3)
{
self->super.render = art_render_gradient_linear_render_8;
*p_flags = 0;
*p_buf_depth = 8;
*p_alpha = ART_ALPHA_PREMUL;
return;
}
self->super.render = art_render_gradient_linear_render;
*p_flags = 0;
*p_buf_depth = render->depth;
*p_alpha = ART_ALPHA_PREMUL;
}
/**
* art_render_gradient_linear: Add a linear gradient image source.
* @render: The render object.
* @gradient: The linear gradient.
*
* Adds the linear gradient @gradient as the image source for rendering
* in the render object @render.
**/
void
art_render_gradient_linear (ArtRender *render,
const ArtGradientLinear *gradient,
ArtFilterLevel level)
{
ArtImageSourceGradLin *image_source = art_alloc (sizeof (ArtImageSourceGradLin) +
sizeof (ArtGradientStop) * (gradient->n_stops - 1));
image_source->super.super.render = NULL;
image_source->super.super.done = art_render_gradient_linear_done;
image_source->super.negotiate = art_render_gradient_linear_negotiate;
/* copy the gradient into the structure */
image_source->gradient = *gradient;
image_source->gradient.stops = image_source->stops;
memcpy (image_source->gradient.stops, gradient->stops, sizeof (ArtGradientStop) * gradient->n_stops);
art_render_add_image_source (render, &image_source->super);
}
static void
art_render_gradient_radial_done (ArtRenderCallback *self, ArtRender *render)
{
art_free (self);
}
static void
art_render_gradient_radial_render (ArtRenderCallback *self, ArtRender *render,
art_u8 *dest, int y)
{
ArtImageSourceGradRad *z = (ArtImageSourceGradRad *)self;
const ArtGradientRadial *gradient = &(z->gradient);
int pixstride = (render->n_chan + 1) * (render->depth >> 3);
int x;
int x0 = render->x0;
int width = render->x1 - x0;
int n_stops = gradient->n_stops;
ArtGradientStop *stops = gradient->stops;
art_u8 *bufp = render->image_buf;
double fx = gradient->fx;
double fy = gradient->fy;
double dx, dy;
const double *affine = gradient->affine;
double aff0 = affine[0];
double aff1 = affine[1];
const double a = z->a;
const double arecip = 1.0 / a;
double b, db;
double c, dc, ddc;
double b_a, db_a;
double rad, drad, ddrad;
dx = x0 * aff0 + y * affine[2] + affine[4] - fx;
dy = x0 * aff1 + y * affine[3] + affine[5] - fy;
b = dx * fx + dy * fy;
db = aff0 * fx + aff1 * fy;
c = dx * dx + dy * dy;
dc = 2 * aff0 * dx + aff0 * aff0 + 2 * aff1 * dy + aff1 * aff1;
ddc = 2 * aff0 * aff0 + 2 * aff1 * aff1;
b_a = b * arecip;
db_a = db * arecip;
rad = b_a * b_a + c * arecip;
drad = 2 * b_a * db_a + db_a * db_a + dc * arecip;
ddrad = 2 * db_a * db_a + ddc * arecip;
for (x = 0; x < width; x++)
{
double z;
if (rad > 0)
z = b_a + sqrt (rad);
else
z = b_a;
art_render_gradient_setpix (render, bufp, n_stops, stops, z);
bufp += pixstride;
b_a += db_a;
rad += drad;
drad += ddrad;
}
}
static void
art_render_gradient_radial_negotiate (ArtImageSource *self, ArtRender *render,
ArtImageSourceFlags *p_flags,
int *p_buf_depth, ArtAlphaType *p_alpha)
{
self->super.render = art_render_gradient_radial_render;
*p_flags = 0;
*p_buf_depth = render->depth;
*p_alpha = ART_ALPHA_PREMUL;
}
/**
* art_render_gradient_radial: Add a radial gradient image source.
* @render: The render object.
* @gradient: The radial gradient.
*
* Adds the radial gradient @gradient as the image source for rendering
* in the render object @render.
**/
void
art_render_gradient_radial (ArtRender *render,
const ArtGradientRadial *gradient,
ArtFilterLevel level)
{
ArtImageSourceGradRad *image_source = art_alloc (sizeof (ArtImageSourceGradRad) +
sizeof (ArtGradientStop) * (gradient->n_stops - 1));
double fx = gradient->fx;
double fy = gradient->fy;
image_source->super.super.render = NULL;
image_source->super.super.done = art_render_gradient_radial_done;
image_source->super.negotiate = art_render_gradient_radial_negotiate;
/* copy the gradient into the structure */
image_source->gradient = *gradient;
image_source->gradient.stops = image_source->stops;
memcpy (image_source->gradient.stops, gradient->stops, sizeof (ArtGradientStop) * gradient->n_stops);
/* todo: sanitycheck fx, fy? */
image_source->a = 1 - fx * fx - fy * fy;
art_render_add_image_source (render, &image_source->super);
}

View File

@ -1,81 +0,0 @@
/*
* art_render_gradient.h: Gradient image 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 <raph@acm.org>
* Alexander Larsson <alla@lysator.liu.se>
*/
#ifndef __ART_RENDER_GRADIENT_H__
#define __ART_RENDER_GRADIENT_H__
#include <libart_lgpl/art_filterlevel.h>
#include <libart_lgpl/art_render.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct _ArtGradientLinear ArtGradientLinear;
typedef struct _ArtGradientRadial ArtGradientRadial;
typedef struct _ArtGradientStop ArtGradientStop;
typedef enum {
ART_GRADIENT_PAD,
ART_GRADIENT_REFLECT,
ART_GRADIENT_REPEAT
} ArtGradientSpread;
struct _ArtGradientLinear {
double a;
double b;
double c;
ArtGradientSpread spread;
int n_stops;
ArtGradientStop *stops;
};
struct _ArtGradientRadial {
double affine[6]; /* transforms user coordinates to unit circle */
double fx, fy; /* focal point in unit circle coords */
int n_stops;
ArtGradientStop *stops;
};
struct _ArtGradientStop {
double offset;
ArtPixMaxDepth color[ART_MAX_CHAN + 1];
};
void
art_render_gradient_linear (ArtRender *render,
const ArtGradientLinear *gradient,
ArtFilterLevel level);
void
art_render_gradient_radial (ArtRender *render,
const ArtGradientRadial *gradient,
ArtFilterLevel level);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __ART_RENDER_GRADIENT_H__ */

View File

@ -1,168 +0,0 @@
/*
* 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 <raph@acm.org>
*/
#include "config.h"
#include "art_render_mask.h"
#include <string.h>
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);
}

View File

@ -1,43 +0,0 @@
/*
* art_render_mask.h: 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 <raph@acm.org>
*/
#ifndef __ART_RENDER_MASK_H__
#define __ART_RENDER_MASK_H__
#include <libart_lgpl/art_render.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void
art_render_mask (ArtRender *render,
int x0, int y0, int x1, int y1,
const art_u8 *mask_buf, int rowstride);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __ART_RENDER_MASK_H__ */

View File

@ -1,421 +0,0 @@
/*
* art_render_gradient.c: SVP 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 <raph@acm.org>
*/
#include "art_render_svp.h"
#include "art_svp_render_aa.h"
typedef struct _ArtMaskSourceSVP ArtMaskSourceSVP;
struct _ArtMaskSourceSVP {
ArtMaskSource super;
ArtRender *render;
const ArtSVP *svp;
art_u8 *dest_ptr;
};
static void
art_render_svp_done (ArtRenderCallback *self, ArtRender *render)
{
art_free (self);
}
static int
art_render_svp_can_drive (ArtMaskSource *self, ArtRender *render)
{
return 10;
}
/* The basic art_render_svp_callback function is repeated four times,
for all combinations of non-unit opacity and generating spans. In
general, I'd consider this bad style, but in this case I plead
a measurable performance improvement. */
static void
art_render_svp_callback (void *callback_data, int y,
int start, ArtSVPRenderAAStep *steps, int n_steps)
{
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
ArtRender *render = z->render;
int n_run = 0;
int i;
int running_sum = start;
int x0 = render->x0;
int x1 = render->x1;
int run_x0, run_x1;
ArtRenderMaskRun *run = render->run;
if (n_steps > 0)
{
run_x1 = steps[0].x;
if (run_x1 > x0 && running_sum > 0x80ff)
{
run[0].x = x0;
run[0].alpha = running_sum;
n_run++;
}
for (i = 0; i < n_steps - 1; i++)
{
running_sum += steps[i].delta;
run_x0 = run_x1;
run_x1 = steps[i + 1].x;
if (run_x1 > run_x0)
{
run[n_run].x = run_x0;
run[n_run].alpha = running_sum;
n_run++;
}
}
if (x1 > run_x1)
{
running_sum += steps[n_steps - 1].delta;
run[n_run].x = run_x1;
run[n_run].alpha = running_sum;
n_run++;
}
if (running_sum > 0x80ff)
{
run[n_run].x = x1;
run[n_run].alpha = 0x8000;
n_run++;
}
}
else if ((running_sum >> 16) > 0)
{
run[0].x = x0;
run[0].alpha = running_sum;
run[1].x = x1;
run[1].alpha = running_sum;
n_run = 2;
}
render->n_run = n_run;
art_render_invoke_callbacks (render, z->dest_ptr, y);
z->dest_ptr += render->rowstride;
}
static void
art_render_svp_callback_span (void *callback_data, int y,
int start, ArtSVPRenderAAStep *steps, int n_steps)
{
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
ArtRender *render = z->render;
int n_run = 0;
int n_span = 0;
int i;
int running_sum = start;
int x0 = render->x0;
int x1 = render->x1;
int run_x0, run_x1;
ArtRenderMaskRun *run = render->run;
int *span_x = render->span_x;
if (n_steps > 0)
{
run_x1 = steps[0].x;
if (run_x1 > x0 && running_sum > 0x80ff)
{
run[0].x = x0;
run[0].alpha = running_sum;
n_run++;
span_x[0] = x0;
n_span++;
}
for (i = 0; i < n_steps - 1; i++)
{
running_sum += steps[i].delta;
run_x0 = run_x1;
run_x1 = steps[i + 1].x;
if (run_x1 > run_x0)
{
run[n_run].x = run_x0;
run[n_run].alpha = running_sum;
n_run++;
if ((n_span & 1) != (running_sum > 0x80ff))
span_x[n_span++] = run_x0;
}
}
if (x1 > run_x1)
{
running_sum += steps[n_steps - 1].delta;
run[n_run].x = run_x1;
run[n_run].alpha = running_sum;
n_run++;
if ((n_span & 1) != (running_sum > 0x80ff))
span_x[n_span++] = run_x1;
}
if (running_sum > 0x80ff)
{
run[n_run].x = x1;
run[n_run].alpha = 0x8000;
n_run++;
span_x[n_span++] = x1;
}
}
else if ((running_sum >> 16) > 0)
{
run[0].x = x0;
run[0].alpha = running_sum;
run[1].x = x1;
run[1].alpha = running_sum;
n_run = 2;
span_x[0] = x0;
span_x[1] = x1;
n_span = 2;
}
render->n_run = n_run;
render->n_span = n_span;
art_render_invoke_callbacks (render, z->dest_ptr, y);
z->dest_ptr += render->rowstride;
}
static void
art_render_svp_callback_opacity (void *callback_data, int y,
int start, ArtSVPRenderAAStep *steps, int n_steps)
{
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
ArtRender *render = z->render;
int n_run = 0;
int i;
art_u32 running_sum;
int x0 = render->x0;
int x1 = render->x1;
int run_x0, run_x1;
ArtRenderMaskRun *run = render->run;
art_u32 opacity = render->opacity;
art_u32 alpha;
running_sum = start - 0x7f80;
if (n_steps > 0)
{
run_x1 = steps[0].x;
alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
if (run_x1 > x0 && alpha > 0x80ff)
{
run[0].x = x0;
run[0].alpha = alpha;
n_run++;
}
for (i = 0; i < n_steps - 1; i++)
{
running_sum += steps[i].delta;
run_x0 = run_x1;
run_x1 = steps[i + 1].x;
if (run_x1 > run_x0)
{
run[n_run].x = run_x0;
alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
run[n_run].alpha = alpha;
n_run++;
}
}
if (x1 > run_x1)
{
running_sum += steps[n_steps - 1].delta;
run[n_run].x = run_x1;
alpha = ((running_sum >> 8) * opacity + 0x80080) >> 8;
run[n_run].alpha = alpha;
n_run++;
}
if (alpha > 0x80ff)
{
run[n_run].x = x1;
run[n_run].alpha = 0x8000;
n_run++;
}
}
else if ((running_sum >> 16) > 0)
{
run[0].x = x0;
run[0].alpha = running_sum;
run[1].x = x1;
run[1].alpha = running_sum;
n_run = 2;
}
render->n_run = n_run;
art_render_invoke_callbacks (render, z->dest_ptr, y);
z->dest_ptr += render->rowstride;
}
static void
art_render_svp_callback_opacity_span (void *callback_data, int y,
int start, ArtSVPRenderAAStep *steps, int n_steps)
{
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)callback_data;
ArtRender *render = z->render;
int n_run = 0;
int n_span = 0;
int i;
art_u32 running_sum;
int x0 = render->x0;
int x1 = render->x1;
int run_x0, run_x1;
ArtRenderMaskRun *run = render->run;
int *span_x = render->span_x;
art_u32 opacity = render->opacity;
art_u32 alpha;
running_sum = start - 0x7f80;
if (n_steps > 0)
{
run_x1 = steps[0].x;
alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
if (run_x1 > x0 && alpha > 0x80ff)
{
run[0].x = x0;
run[0].alpha = alpha;
n_run++;
span_x[0] = x0;
n_span++;
}
for (i = 0; i < n_steps - 1; i++)
{
running_sum += steps[i].delta;
run_x0 = run_x1;
run_x1 = steps[i + 1].x;
if (run_x1 > run_x0)
{
run[n_run].x = run_x0;
alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
run[n_run].alpha = alpha;
n_run++;
if ((n_span & 1) != (alpha > 0x80ff))
span_x[n_span++] = run_x0;
}
}
if (x1 > run_x1)
{
running_sum += steps[n_steps - 1].delta;
run[n_run].x = run_x1;
alpha = ((running_sum >> 8) * opacity + 0x800080) >> 8;
run[n_run].alpha = alpha;
n_run++;
if ((n_span & 1) != (alpha > 0x80ff))
span_x[n_span++] = run_x1;
}
if (alpha > 0x80ff)
{
run[n_run].x = x1;
run[n_run].alpha = 0x8000;
n_run++;
span_x[n_span++] = x1;
}
}
else if ((running_sum >> 16) > 0)
{
run[0].x = x0;
run[0].alpha = running_sum;
run[1].x = x1;
run[1].alpha = running_sum;
n_run = 2;
span_x[0] = x0;
span_x[1] = x1;
n_span = 2;
}
render->n_run = n_run;
render->n_span = n_span;
art_render_invoke_callbacks (render, z->dest_ptr, y);
z->dest_ptr += render->rowstride;
}
static void
art_render_svp_invoke_driver (ArtMaskSource *self, ArtRender *render)
{
ArtMaskSourceSVP *z = (ArtMaskSourceSVP *)self;
void (*callback) (void *callback_data,
int y,
int start,
ArtSVPRenderAAStep *steps, int n_steps);
z->dest_ptr = render->pixels;
if (render->opacity == 0x10000)
{
if (render->need_span)
callback = art_render_svp_callback_span;
else
callback = art_render_svp_callback;
}
else
{
if (render->need_span)
callback = art_render_svp_callback_opacity_span;
else
callback = art_render_svp_callback_opacity;
}
art_svp_render_aa (z->svp,
render->x0, render->y0,
render->x1, render->y1, callback,
self);
art_render_svp_done (&self->super, render);
}
G_GNUC_NORETURN static void
art_render_svp_prepare (ArtMaskSource *self, ArtRender *render,
art_boolean first)
{
/* todo */
art_die ("art_render_svp non-driver mode not yet implemented.\n");
}
/**
* art_render_svp: Use an SVP as a render mask source.
* @render: Render object.
* @svp: SVP.
*
* Adds @svp to the render object as a mask. Note: @svp must remain
* allocated until art_render_invoke() is called on @render.
**/
void
art_render_svp (ArtRender *render, const ArtSVP *svp)
{
ArtMaskSourceSVP *mask_source;
mask_source = art_new (ArtMaskSourceSVP, 1);
mask_source->super.super.render = NULL;
mask_source->super.super.done = art_render_svp_done;
mask_source->super.can_drive = art_render_svp_can_drive;
mask_source->super.invoke_driver = art_render_svp_invoke_driver;
mask_source->super.prepare = art_render_svp_prepare;
mask_source->render = render;
mask_source->svp = svp;
art_render_add_mask_source (render, &mask_source->super);
}

View File

@ -1,42 +0,0 @@
/*
* art_render_svp.h: SVP 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 <raph@acm.org>
*/
#ifndef __ART_RENDER_SVP_H__
#define __ART_RENDER_SVP_H__
#include <libart_lgpl/art_render.h>
#include <libart_lgpl/art_svp.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void
art_render_svp (ArtRender *render, const ArtSVP *svp);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __ART_RENDER_SVP_H__ */

View File

@ -1,149 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998 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_rgb_a_affine.h"
#include <math.h>
#include "art_affine.h"
#include "art_point.h"
#include "art_rgb_affine_private.h"
/* This module handles compositing of affine-transformed alpha only images
over rgb pixel buffers. */
/* Composite the source image over the destination image, applying the
affine transform. */
/**
* art_rgb_a_affine: Affine transform source Alpha image and composite.
* @dst: Destination image RGB buffer.
* @x0: Left coordinate of destination rectangle.
* @y0: Top coordinate of destination rectangle.
* @x1: Right coordinate of destination rectangle.
* @y1: Bottom coordinate of destination rectangle.
* @dst_rowstride: Rowstride of @dst buffer.
* @src: Source image alpha buffer.
* @src_width: Width of source image.
* @src_height: Height of source image.
* @src_rowstride: Rowstride of @src buffer.
* @rgb: RGB foreground color, in 0xRRGGBB.
* @affine: Affine transform.
* @level: Filter level.
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
*
* Affine transform the solid color rgb with alpha specified by the
* source image stored in @src, compositing over the area of destination
* image @dst specified by the rectangle (@x0, @y0) - (@x1, @y1).
* As usual in libart, the left and top edges of this rectangle are
* included, and the right and bottom edges are excluded.
*
* The @alphagamma parameter specifies that the alpha compositing be
* done in a gamma-corrected color space. In the current
* implementation, it is ignored.
*
* The @level parameter specifies the speed/quality tradeoff of the
* image interpolation. Currently, only ART_FILTER_NEAREST is
* implemented.
**/
void
art_rgb_a_affine (art_u8 *dst,
int x0, int y0, int x1, int y1, int dst_rowstride,
const art_u8 *src,
int src_width, int src_height, int src_rowstride,
art_u32 rgb,
const double affine[6],
ArtFilterLevel level,
ArtAlphaGamma *alphagamma)
{
/* Note: this is a slow implementation, and is missing all filter
levels other than NEAREST. It is here for clarity of presentation
and to establish the interface. */
int x, y;
double inv[6];
art_u8 *dst_p, *dst_linestart;
const art_u8 *src_p;
ArtPoint pt, src_pt;
int src_x, src_y;
int alpha;
art_u8 bg_r, bg_g, bg_b;
art_u8 fg_r, fg_g, fg_b;
int tmp;
int run_x0, run_x1;
art_u8 r, g, b;
r = (rgb>>16)&0xff;
g = (rgb>>8)&0xff;
b = (rgb)&0xff;
dst_linestart = dst;
art_affine_invert (inv, affine);
for (y = y0; y < y1; y++)
{
pt.y = y + 0.5;
run_x0 = x0;
run_x1 = x1;
art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
inv);
dst_p = dst_linestart + (run_x0 - x0) * 3;
for (x = run_x0; x < run_x1; x++)
{
pt.x = x + 0.5;
art_affine_point (&src_pt, &pt, inv);
src_x = floor (src_pt.x);
src_y = floor (src_pt.y);
src_p = src + (src_y * src_rowstride) + src_x;
if (src_x >= 0 && src_x < src_width &&
src_y >= 0 && src_y < src_height)
{
alpha = *src_p;
if (alpha)
{
if (alpha == 255)
{
dst_p[0] = r;
dst_p[1] = g;
dst_p[2] = b;
}
else
{
bg_r = dst_p[0];
bg_g = dst_p[1];
bg_b = dst_p[2];
tmp = (r - bg_r) * alpha;
fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (g - bg_g) * alpha;
fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (b - bg_b) * alpha;
fg_b = bg_b + ((tmp + (tmp >> 8) + 0x80) >> 8);
dst_p[0] = fg_r;
dst_p[1] = fg_g;
dst_p[2] = fg_b;
}
}
} else { dst_p[0] = 255; dst_p[1] = 0; dst_p[2] = 0; }
dst_p += 3;
}
dst_linestart += dst_rowstride;
}
}

View File

@ -1,47 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998 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.
*/
#ifndef __ART_RGB_A_AFFINE_H__
#define __ART_RGB_A_AFFINE_H__
/* This module handles compositing of affine-transformed alpha only images
over rgb pixel buffers. */
#include <libart_lgpl/art_filterlevel.h>
#include <libart_lgpl/art_alphagamma.h>
#ifdef __cplusplus
extern "C" {
#endif
void
art_rgb_a_affine (art_u8 *dst,
int x0, int y0, int x1, int y1, int dst_rowstride,
const art_u8 *src,
int src_width, int src_height, int src_rowstride,
art_u32 rgb,
const double affine[6],
ArtFilterLevel level,
ArtAlphaGamma *alphagamma);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,198 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998 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_rgb_bitmap_affine.h"
#include <math.h>
#include "art_misc.h"
#include "art_point.h"
#include "art_affine.h"
#include "art_rgb_affine_private.h"
/* This module handles compositing of affine-transformed bitmap images
over rgb pixel buffers. */
/* Composite the source image over the destination image, applying the
affine transform. Foreground color is given and assumed to be
opaque, background color is assumed to be fully transparent. */
static void
art_rgb_bitmap_affine_opaque (art_u8 *dst,
int x0, int y0, int x1, int y1,
int dst_rowstride,
const art_u8 *src,
int src_width, int src_height, int src_rowstride,
art_u32 rgb,
const double affine[6],
ArtFilterLevel level,
ArtAlphaGamma *alphagamma)
{
/* Note: this is a slow implementation, and is missing all filter
levels other than NEAREST. It is here for clarity of presentation
and to establish the interface. */
int x, y;
double inv[6];
art_u8 *dst_p, *dst_linestart;
const art_u8 *src_p;
ArtPoint pt, src_pt;
int src_x, src_y;
art_u8 r, g, b;
int run_x0, run_x1;
r = rgb >> 16;
g = (rgb >> 8) & 0xff;
b = rgb & 0xff;
dst_linestart = dst;
art_affine_invert (inv, affine);
for (y = y0; y < y1; y++)
{
pt.y = y + 0.5;
run_x0 = x0;
run_x1 = x1;
art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
inv);
dst_p = dst_linestart + (run_x0 - x0) * 3;
for (x = run_x0; x < run_x1; x++)
{
pt.x = x + 0.5;
art_affine_point (&src_pt, &pt, inv);
src_x = floor (src_pt.x);
src_y = floor (src_pt.y);
src_p = src + (src_y * src_rowstride) + (src_x >> 3);
if (*src_p & (128 >> (src_x & 7)))
{
dst_p[0] = r;
dst_p[1] = g;
dst_p[2] = b;
}
dst_p += 3;
}
dst_linestart += dst_rowstride;
}
}
/* Composite the source image over the destination image, applying the
affine transform. Foreground color is given, background color is
assumed to be fully transparent. */
/**
* art_rgb_bitmap_affine: Affine transform source bitmap image and composite.
* @dst: Destination image RGB buffer.
* @x0: Left coordinate of destination rectangle.
* @y0: Top coordinate of destination rectangle.
* @x1: Right coordinate of destination rectangle.
* @y1: Bottom coordinate of destination rectangle.
* @dst_rowstride: Rowstride of @dst buffer.
* @src: Source image bitmap buffer.
* @src_width: Width of source image.
* @src_height: Height of source image.
* @src_rowstride: Rowstride of @src buffer.
* @rgba: RGBA foreground color, in 0xRRGGBBAA.
* @affine: Affine transform.
* @level: Filter level.
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
*
* Affine transform the source image stored in @src, compositing over
* the area of destination image @dst specified by the rectangle
* (@x0, @y0) - (@x1, @y1).
*
* The source bitmap stored with MSB as the leftmost pixel. Source 1
* bits correspond to the semitransparent color @rgba, while source 0
* bits are transparent.
*
* See art_rgb_affine() for a description of additional parameters.
**/
void
art_rgb_bitmap_affine (art_u8 *dst,
int x0, int y0, int x1, int y1, int dst_rowstride,
const art_u8 *src,
int src_width, int src_height, int src_rowstride,
art_u32 rgba,
const double affine[6],
ArtFilterLevel level,
ArtAlphaGamma *alphagamma)
{
/* Note: this is a slow implementation, and is missing all filter
levels other than NEAREST. It is here for clarity of presentation
and to establish the interface. */
int x, y;
double inv[6];
art_u8 *dst_p, *dst_linestart;
const art_u8 *src_p;
ArtPoint pt, src_pt;
int src_x, src_y;
int alpha;
art_u8 bg_r, bg_g, bg_b;
art_u8 fg_r, fg_g, fg_b;
art_u8 r, g, b;
int run_x0, run_x1;
alpha = rgba & 0xff;
if (alpha == 0xff)
{
art_rgb_bitmap_affine_opaque (dst, x0, y0, x1, y1, dst_rowstride,
src,
src_width, src_height, src_rowstride,
rgba >> 8,
affine,
level,
alphagamma);
return;
}
/* alpha = (65536 * alpha) / 255; */
alpha = (alpha << 8) + alpha + (alpha >> 7);
r = rgba >> 24;
g = (rgba >> 16) & 0xff;
b = (rgba >> 8) & 0xff;
dst_linestart = dst;
art_affine_invert (inv, affine);
for (y = y0; y < y1; y++)
{
pt.y = y + 0.5;
run_x0 = x0;
run_x1 = x1;
art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
inv);
dst_p = dst_linestart + (run_x0 - x0) * 3;
for (x = run_x0; x < run_x1; x++)
{
pt.x = x + 0.5;
art_affine_point (&src_pt, &pt, inv);
src_x = floor (src_pt.x);
src_y = floor (src_pt.y);
src_p = src + (src_y * src_rowstride) + (src_x >> 3);
if (*src_p & (128 >> (src_x & 7)))
{
bg_r = dst_p[0];
bg_g = dst_p[1];
bg_b = dst_p[2];
fg_r = bg_r + (((r - bg_r) * alpha + 0x8000) >> 16);
fg_g = bg_g + (((g - bg_g) * alpha + 0x8000) >> 16);
fg_b = bg_b + (((b - bg_b) * alpha + 0x8000) >> 16);
dst_p[0] = fg_r;
dst_p[1] = fg_g;
dst_p[2] = fg_b;
}
dst_p += 3;
}
dst_linestart += dst_rowstride;
}
}

View File

@ -1,47 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998 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.
*/
#ifndef __ART_RGB_BITMAP_AFFINE_H__
#define __ART_RGB_BITMAP_AFFINE_H__
/* This module handles compositing of affine-transformed bitmap images
over rgb pixel buffers. */
#include <libart_lgpl/art_filterlevel.h>
#include <libart_lgpl/art_alphagamma.h>
#ifdef __cplusplus
extern "C" {
#endif
void
art_rgb_bitmap_affine (art_u8 *dst,
int x0, int y0, int x1, int y1, int dst_rowstride,
const art_u8 *src,
int src_width, int src_height, int src_rowstride,
art_u32 rgba,
const double affine[6],
ArtFilterLevel level,
ArtAlphaGamma *alphagamma);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,104 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998 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_rgb_pixbuf_affine.h"
#include <math.h>
#include "art_misc.h"
#include "art_point.h"
#include "art_affine.h"
#include "art_pixbuf.h"
#include "art_rgb_affine.h"
#include "art_rgb_affine.h"
#include "art_rgb_rgba_affine.h"
/* This module handles compositing of affine-transformed generic
pixbuf images over rgb pixel buffers. */
/* Composite the source image over the destination image, applying the
affine transform. */
/**
* art_rgb_pixbuf_affine: Affine transform source RGB pixbuf and composite.
* @dst: Destination image RGB buffer.
* @x0: Left coordinate of destination rectangle.
* @y0: Top coordinate of destination rectangle.
* @x1: Right coordinate of destination rectangle.
* @y1: Bottom coordinate of destination rectangle.
* @dst_rowstride: Rowstride of @dst buffer.
* @pixbuf: source image pixbuf.
* @affine: Affine transform.
* @level: Filter level.
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
*
* Affine transform the source image stored in @src, compositing over
* the area of destination image @dst specified by the rectangle
* (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges
* of this rectangle are included, and the right and bottom edges are
* excluded.
*
* The @alphagamma parameter specifies that the alpha compositing be
* done in a gamma-corrected color space. In the current
* implementation, it is ignored.
*
* The @level parameter specifies the speed/quality tradeoff of the
* image interpolation. Currently, only ART_FILTER_NEAREST is
* implemented.
**/
void
art_rgb_pixbuf_affine (art_u8 *dst,
int x0, int y0, int x1, int y1, int dst_rowstride,
const ArtPixBuf *pixbuf,
const double affine[6],
ArtFilterLevel level,
ArtAlphaGamma *alphagamma)
{
if (pixbuf->format != ART_PIX_RGB)
{
art_warn ("art_rgb_pixbuf_affine: need RGB format image\n");
return;
}
if (pixbuf->bits_per_sample != 8)
{
art_warn ("art_rgb_pixbuf_affine: need 8-bit sample data\n");
return;
}
if (pixbuf->n_channels != 3 + (pixbuf->has_alpha != 0))
{
art_warn ("art_rgb_pixbuf_affine: need 8-bit sample data\n");
return;
}
if (pixbuf->has_alpha)
art_rgb_rgba_affine (dst, x0, y0, x1, y1, dst_rowstride,
pixbuf->pixels,
pixbuf->width, pixbuf->height, pixbuf->rowstride,
affine,
level,
alphagamma);
else
art_rgb_affine (dst, x0, y0, x1, y1, dst_rowstride,
pixbuf->pixels,
pixbuf->width, pixbuf->height, pixbuf->rowstride,
affine,
level,
alphagamma);
}

View File

@ -1,46 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998 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.
*/
#ifndef __ART_RGB_PIXBUF_AFFINE_H__
#define __ART_RGB_PIXBUF_AFFINE_H__
/* This module handles compositing of affine-transformed generic
pixbuf images over rgb pixel buffers. */
#include <libart_lgpl/art_filterlevel.h>
#include <libart_lgpl/art_alphagamma.h>
#include <libart_lgpl/art_pixbuf.h>
#ifdef __cplusplus
extern "C" {
#endif
void
art_rgb_pixbuf_affine (art_u8 *dst,
int x0, int y0, int x1, int y1, int dst_rowstride,
const ArtPixBuf *pixbuf,
const double affine[6],
ArtFilterLevel level,
ArtAlphaGamma *alphagamma);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,258 +0,0 @@
/*
* 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
}
}
}

View File

@ -1,45 +0,0 @@
/*
* art_rgba.h: 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.
*/
#ifndef __ART_RGBA_H__
#define __ART_RGBA_H__
#include <libart_lgpl/art_misc.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void
art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n);
void
art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n);
void
art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif

View File

@ -183,69 +183,6 @@ art_svp_merge_perturbed (const ArtSVP *svp1, const ArtSVP *svp2)
}
#endif
/* Compute the union of two vector paths.
Status of this routine:
Basic correctness: Seems to work.
Numerical stability: We cheat (adding random perturbation). Thus,
it seems very likely that no numerical stability problems will be
seen in practice.
Speed: Would be better if we didn't go to unsorted vector path
and back to add the perturbation.
Precision: The perturbation fuzzes the coordinates slightly. In
cases of butting segments, razor thin long holes may appear.
*/
/**
* art_svp_union: Compute the union of two sorted vector paths.
* @svp1: One sorted vector path.
* @svp2: The other sorted vector path.
*
* Computes the union of the two argument svp's. Given two svp's with
* winding numbers of 0 and 1 everywhere, the resulting winding number
* will be 1 where either (or both) of the argument svp's has a
* winding number 1, 0 otherwise. The result is newly allocated.
*
* Currently, this routine has accuracy problems pending the
* implementation of the new intersector.
*
* Return value: The union of @svp1 and @svp2.
**/
ArtSVP *
art_svp_union (const ArtSVP *svp1, const ArtSVP *svp2)
{
#ifdef ART_USE_NEW_INTERSECTOR
ArtSVP *svp3, *svp_new;
ArtSvpWriter *swr;
svp3 = art_svp_merge (svp1, svp2);
swr = art_svp_writer_rewind_new (ART_WIND_RULE_POSITIVE);
art_svp_intersector (svp3, swr);
svp_new = art_svp_writer_rewind_reap (swr);
art_free (svp3); /* shallow free because svp3 contains shared segments */
return svp_new;
#else
ArtSVP *svp3, *svp4, *svp_new;
svp3 = art_svp_merge_perturbed (svp1, svp2);
svp4 = art_svp_uncross (svp3);
art_svp_free (svp3);
svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_POSITIVE);
#ifdef VERBOSE
print_ps_svp (svp4);
print_ps_svp (svp_new);
#endif
art_svp_free (svp4);
return svp_new;
#endif
}
/* Compute the intersection of two vector paths.
Status of this routine:
@ -307,95 +244,3 @@ art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2)
#endif
}
/* Compute the symmetric difference of two vector paths.
Status of this routine:
Basic correctness: Seems to work.
Numerical stability: We cheat (adding random perturbation). Thus,
it seems very likely that no numerical stability problems will be
seen in practice.
Speed: We could do a lot better by scanning through the svp
representations and culling out any segments that are exactly
identical. It would also be better if we didn't go to unsorted
vector path and back to add the perturbation.
Precision: Awful. In the case of inputs which are similar (the
common case for canvas display), the entire outline is "hairy." In
addition, the perturbation fuzzes the coordinates slightly. It can
be used as a conservative approximation.
*/
/**
* art_svp_diff: Compute the symmetric difference of two sorted vector paths.
* @svp1: One sorted vector path.
* @svp2: The other sorted vector path.
*
* Computes the symmetric of the two argument svp's. Given two svp's
* with winding numbers of 0 and 1 everywhere, the resulting winding
* number will be 1 where either, but not both, of the argument svp's
* has a winding number 1, 0 otherwise. The result is newly allocated.
*
* Currently, this routine has accuracy problems pending the
* implementation of the new intersector.
*
* Return value: The symmetric difference of @svp1 and @svp2.
**/
ArtSVP *
art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2)
{
#ifdef ART_USE_NEW_INTERSECTOR
ArtSVP *svp3, *svp_new;
ArtSvpWriter *swr;
svp3 = art_svp_merge (svp1, svp2);
swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
art_svp_intersector (svp3, swr);
svp_new = art_svp_writer_rewind_reap (swr);
art_free (svp3); /* shallow free because svp3 contains shared segments */
return svp_new;
#else
ArtSVP *svp3, *svp4, *svp_new;
svp3 = art_svp_merge_perturbed (svp1, svp2);
svp4 = art_svp_uncross (svp3);
art_svp_free (svp3);
svp_new = art_svp_rewind_uncrossed (svp4, ART_WIND_RULE_ODDEVEN);
art_svp_free (svp4);
return svp_new;
#endif
}
#ifdef ART_USE_NEW_INTERSECTOR
ArtSVP *
art_svp_minus (const ArtSVP *svp1, const ArtSVP *svp2)
{
ArtSVP *svp2_mod;
ArtSVP *svp3, *svp_new;
ArtSvpWriter *swr;
int i;
svp2_mod = (ArtSVP *) svp2; /* get rid of the const for a while */
/* First invert svp2 to "turn it inside out" */
for (i = 0; i < svp2_mod->n_segs; i++)
svp2_mod->segs[i].dir = !svp2_mod->segs[i].dir;
svp3 = art_svp_merge (svp1, svp2_mod);
swr = art_svp_writer_rewind_new (ART_WIND_RULE_POSITIVE);
art_svp_intersector (svp3, swr);
svp_new = art_svp_writer_rewind_reap (swr);
art_free (svp3); /* shallow free because svp3 contains shared segments */
/* Flip svp2 back to its original state */
for (i = 0; i < svp2_mod->n_segs; i++)
svp2_mod->segs[i].dir = !svp2_mod->segs[i].dir;
return svp_new;
}
#endif /* ART_USE_NEW_INTERSECTOR */

View File

@ -28,10 +28,7 @@ extern "C" {
/* Vector path set operations, over sorted vpaths. */
ArtSVP *art_svp_union (const ArtSVP *svp1, const ArtSVP *svp2);
ArtSVP *art_svp_intersect (const ArtSVP *svp1, const ArtSVP *svp2);
ArtSVP *art_svp_diff (const ArtSVP *svp1, const ArtSVP *svp2);
ArtSVP *art_svp_minus (const ArtSVP *svp1, const ArtSVP *svp2);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -39,13 +39,6 @@ typedef enum {
} ArtWindRule;
#endif
ArtSVP *
art_svp_uncross (ArtSVP *vp);
ArtSVP *
art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -1,112 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998-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_uta_ops.h"
#include <string.h>
#include "art_misc.h"
#include "art_uta.h"
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
/**
* art_uta_union: Compute union of two uta's.
* @uta1: One uta.
* @uta2: The other uta.
*
* Computes the union of @uta1 and @uta2. The union is approximate,
* but coverage is guaranteed over all pixels included in either of
* the arguments, ie more pixels may be covered than the "exact"
* union.
*
* Note: this routine is used in the Gnome Canvas to accumulate the
* region that needs to be repainted. However, since it copies over
* the entire uta (which might be largish) even when the update may be
* small, it can be a performance bottleneck. There are two approaches
* to this problem, both of which are probably worthwhile. First, the
* generated uta's should always be limited to the visible window,
* thus guaranteeing that uta's never become large. Second, there
* should be a new, destructive union operation that only touches a
* small part of the uta when the update is small.
*
* Return value: The new union uta.
**/
ArtUta *
art_uta_union (ArtUta *uta1, ArtUta *uta2)
{
ArtUta *uta;
int x0, y0, x1, y1;
int x, y;
int ix, ix1, ix2;
ArtUtaBbox bb, bb1, bb2;
x0 = MIN(uta1->x0, uta2->x0);
y0 = MIN(uta1->y0, uta2->y0);
x1 = MAX(uta1->x0 + uta1->width, uta2->x0 + uta2->width);
y1 = MAX(uta1->y0 + uta1->height, uta2->y0 + uta2->height);
uta = art_uta_new (x0, y0, x1, y1);
/* could move the first two if/else statements out of the loop */
ix = 0;
for (y = y0; y < y1; y++)
{
ix1 = (y - uta1->y0) * uta1->width + x0 - uta1->x0;
ix2 = (y - uta2->y0) * uta2->width + x0 - uta2->x0;
for (x = x0; x < x1; x++)
{
if (x < uta1->x0 || y < uta1->y0 ||
x >= uta1->x0 + uta1->width || y >= uta1->y0 + uta1->height)
bb1 = 0;
else
bb1 = uta1->utiles[ix1];
if (x < uta2->x0 || y < uta2->y0 ||
x >= uta2->x0 + uta2->width || y >= uta2->y0 + uta2->height)
bb2 = 0;
else
bb2 = uta2->utiles[ix2];
if (bb1 == 0)
bb = bb2;
else if (bb2 == 0)
bb = bb1;
else
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb1),
ART_UTA_BBOX_X0(bb2)),
MIN(ART_UTA_BBOX_Y0(bb1),
ART_UTA_BBOX_Y0(bb2)),
MAX(ART_UTA_BBOX_X1(bb1),
ART_UTA_BBOX_X1(bb2)),
MAX(ART_UTA_BBOX_Y1(bb1),
ART_UTA_BBOX_Y1(bb2)));
uta->utiles[ix] = bb;
ix++;
ix1++;
ix2++;
}
}
return uta;
}

View File

@ -1,38 +0,0 @@
/* Libart_LGPL - library of basic graphic primitives
* Copyright (C) 1998 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.
*/
#ifndef __ART_UTA_OPS_H__
#define __ART_UTA_OPS_H__
/* Basic operations on microtile arrays */
#include <libart_lgpl/art_uta.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
ArtUta *
art_uta_union (ArtUta *uta1, ArtUta *uta2);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __ART_UTA_OPS_H__ */

View File

@ -62,77 +62,6 @@ art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
/* number of steps should really depend on radius. */
#define CIRCLE_STEPS 128
/**
* art_vpath_new_circle: Create a new circle.
* @x: X coordinate of center.
* @y: Y coordinate of center.
* @r: radius.
*
* Creates a new polygon closely approximating a circle with center
* (@x, @y) and radius @r. Currently, the number of points used in the
* approximation is fixed, but that will probably change.
*
* Return value: The newly created #ArtVpath.
**/
ArtVpath *
art_vpath_new_circle (double x, double y, double r)
{
int i;
ArtVpath *vec;
double theta;
vec = art_new (ArtVpath, CIRCLE_STEPS + 2);
for (i = 0; i < CIRCLE_STEPS + 1; i++)
{
vec[i].code = i ? ART_LINETO : ART_MOVETO;
theta = (i & (CIRCLE_STEPS - 1)) * (M_PI * 2.0 / CIRCLE_STEPS);
vec[i].x = x + r * cos (theta);
vec[i].y = y - r * sin (theta);
}
vec[i].code = ART_END;
return vec;
}
/**
* art_vpath_affine_transform: Affine transform a vpath.
* @src: Source vpath to transform.
* @matrix: Affine transform.
*
* Computes the affine transform of the vpath, using @matrix as the
* transform. @matrix is stored in the same format as PostScript, ie.
* x' = @matrix[0] * x + @matrix[2] * y + @matrix[4]
* y' = @matrix[1] * x + @matrix[3] * y + @matrix[5]
*
* Return value: the newly allocated vpath resulting from the transform.
**/
ArtVpath *
art_vpath_affine_transform (const ArtVpath *src, const double matrix[6])
{
int i;
int size;
ArtVpath *new;
double x, y;
for (i = 0; src[i].code != ART_END; i++);
size = i;
new = art_new (ArtVpath, size + 1);
for (i = 0; i < size; i++)
{
new[i].code = src[i].code;
x = src[i].x;
y = src[i].y;
new[i].x = matrix[0] * x + matrix[2] * y + matrix[4];
new[i].y = matrix[1] * x + matrix[3] * y + matrix[5];
}
new[i].code = ART_END;
return new;
}
/**
* art_vpath_bbox_drect: Determine bounding box of vpath.
* @vec: Source vpath.
@ -184,58 +113,3 @@ art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect)
art_drect_to_irect (irect, &drect);
}
#define PERTURBATION 2e-3
/**
* art_vpath_perturb: Perturb each point in vpath by small random amount.
* @src: Source vpath.
*
* Perturbs each of the points by a small random amount. This is
* helpful for cheating in cases when algorithms haven't attained
* numerical stability yet.
*
* Return value: Newly allocated vpath containing perturbed @src.
**/
ArtVpath *
art_vpath_perturb (ArtVpath *src)
{
int i;
int size;
ArtVpath *new;
double x, y;
double x_start, y_start;
int open;
for (i = 0; src[i].code != ART_END; i++);
size = i;
new = art_new (ArtVpath, size + 1);
x_start = 0;
y_start = 0;
open = 0;
for (i = 0; i < size; i++)
{
new[i].code = src[i].code;
x = src[i].x + (PERTURBATION * rand ()) / RAND_MAX - PERTURBATION * 0.5;
y = src[i].y + (PERTURBATION * rand ()) / RAND_MAX - PERTURBATION * 0.5;
if (src[i].code == ART_MOVETO)
{
x_start = x;
y_start = y;
open = 0;
}
else if (src[i].code == ART_MOVETO_OPEN)
open = 1;
if (!open && (i + 1 == size || src[i + 1].code != ART_LINETO))
{
x = x_start;
y = y_start;
}
new[i].x = x;
new[i].y = y;
}
new[i].code = ART_END;
return new;
}

View File

@ -44,21 +44,12 @@ void
art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
ArtPathcode code, double x, double y);
ArtVpath *
art_vpath_new_circle (double x, double y, double r);
ArtVpath *
art_vpath_affine_transform (const ArtVpath *src, const double matrix[6]);
void
art_vpath_bbox_drect (const ArtVpath *vec, ArtDRect *drect);
void
art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect);
ArtVpath *
art_vpath_perturb (ArtVpath *src);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -27,7 +27,6 @@
#include <libart_lgpl/art_svp_vpath_stroke.h>
#include <libart_lgpl/art_svp_wind.h>
#include <libart_lgpl/art_uta.h>
#include <libart_lgpl/art_uta_ops.h>
#include <libart_lgpl/art_uta_rect.h>
#include <libart_lgpl/art_uta_svp.h>
#include <libart_lgpl/art_uta_vpath.h>

View File

@ -42,9 +42,7 @@
#include <pango/pangoft2.h>
#include <libart_lgpl/art_affine.h>
#include <libart_lgpl/art_rgb_a_affine.h>
#include <libart_lgpl/art_rgb.h>
#include <libart_lgpl/art_rgb_bitmap_affine.h>
#include "gnome-canvas-util.h"
#include "gnome-canvas-i18n.h"

View File

@ -86,7 +86,6 @@
#include <libart_lgpl/art_rect.h>
#include <libart_lgpl/art_rect_uta.h>
#include <libart_lgpl/art_uta_rect.h>
#include <libart_lgpl/art_uta_ops.h>
#include "gnome-canvas-marshal.h"
#include "gnome-canvas-marshal.c"