Remove unused libart_lgpl API.
According to CallCatcher.
This commit is contained in:
@ -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 \
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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__ */
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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__ */
|
||||
@ -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);
|
||||
}
|
||||
@ -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__ */
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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 */
|
||||
|
||||
@ -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
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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__ */
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
Reference in New Issue
Block a user