diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2010-06-16 19:04:07 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2010-06-16 19:04:07 +0800 |
commit | d4a32e5a9867bc2dbd41ffa6e8eb3be44a70c00a (patch) | |
tree | b3646b030aca0b01e3717f07bc35e2789b97f00a /libart_lgpl | |
parent | f06717f6ef100bd840c0cd470c6227e47201f907 (diff) | |
download | gsoc2013-evolution-d4a32e5a9867bc2dbd41ffa6e8eb3be44a70c00a.tar gsoc2013-evolution-d4a32e5a9867bc2dbd41ffa6e8eb3be44a70c00a.tar.gz gsoc2013-evolution-d4a32e5a9867bc2dbd41ffa6e8eb3be44a70c00a.tar.bz2 gsoc2013-evolution-d4a32e5a9867bc2dbd41ffa6e8eb3be44a70c00a.tar.lz gsoc2013-evolution-d4a32e5a9867bc2dbd41ffa6e8eb3be44a70c00a.tar.xz gsoc2013-evolution-d4a32e5a9867bc2dbd41ffa6e8eb3be44a70c00a.tar.zst gsoc2013-evolution-d4a32e5a9867bc2dbd41ffa6e8eb3be44a70c00a.zip |
Remove unused libart_lgpl API.
According to CallCatcher.
Diffstat (limited to 'libart_lgpl')
34 files changed, 0 insertions, 5419 deletions
diff --git a/libart_lgpl/Makefile.am b/libart_lgpl/Makefile.am index bc45e33137..8f71243893 100644 --- a/libart_lgpl/Makefile.am +++ b/libart_lgpl/Makefile.am @@ -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 \ diff --git a/libart_lgpl/art_affine.c b/libart_lgpl/art_affine.c index 9f332a3520..96007d09c9 100644 --- a/libart_lgpl/art_affine.c +++ b/libart_lgpl/art_affine.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 @@ -335,55 +312,6 @@ art_affine_scale (double dst[6], double sx, double sy) } /** - * 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. * @tx: X translation amount. @@ -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); -} diff --git a/libart_lgpl/art_affine.h b/libart_lgpl/art_affine.h index 0baee70941..83f64b94ec 100644 --- a/libart_lgpl/art_affine.h +++ b/libart_lgpl/art_affine.h @@ -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 } diff --git a/libart_lgpl/art_alphagamma.c b/libart_lgpl/art_alphagamma.c deleted file mode 100644 index 4651883cf5..0000000000 --- a/libart_lgpl/art_alphagamma.c +++ /dev/null @@ -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); -} diff --git a/libart_lgpl/art_alphagamma.h b/libart_lgpl/art_alphagamma.h index 5f766c95ba..f3ee35765f 100644 --- a/libart_lgpl/art_alphagamma.h +++ b/libart_lgpl/art_alphagamma.h @@ -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 */ diff --git a/libart_lgpl/art_pixbuf.c b/libart_lgpl/art_pixbuf.c index e99375392e..c624c7dd7d 100644 --- a/libart_lgpl/art_pixbuf.c +++ b/libart_lgpl/art_pixbuf.c @@ -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; -} diff --git a/libart_lgpl/art_pixbuf.h b/libart_lgpl/art_pixbuf.h index 31f5620671..6d79f5d653 100644 --- a/libart_lgpl/art_pixbuf.h +++ b/libart_lgpl/art_pixbuf.h @@ -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 diff --git a/libart_lgpl/art_rect.c b/libart_lgpl/art_rect.c index c9dd5b3702..6d318a80eb 100644 --- a/libart_lgpl/art_rect.c +++ b/libart_lgpl/art_rect.c @@ -48,28 +48,6 @@ art_irect_copy (ArtIRect *dest, const ArtIRect *src) { } /** - * 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. * @src1: A source rectangle. @@ -141,22 +119,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. * diff --git a/libart_lgpl/art_rect.h b/libart_lgpl/art_rect.h index 088079f712..247cbea3e9 100644 --- a/libart_lgpl/art_rect.h +++ b/libart_lgpl/art_rect.h @@ -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); diff --git a/libart_lgpl/art_render.c b/libart_lgpl/art_render.c index 65b344cc56..771f15fe44 100644 --- a/libart_lgpl/art_render.c +++ b/libart_lgpl/art_render.c @@ -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. @@ -930,184 +767,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. * @mask_source: Mask source to add. @@ -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); -} diff --git a/libart_lgpl/art_render.h b/libart_lgpl/art_render.h index 399033cd0f..db0933ea83 100644 --- a/libart_lgpl/art_render.h +++ b/libart_lgpl/art_render.h @@ -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); diff --git a/libart_lgpl/art_render_gradient.c b/libart_lgpl/art_render_gradient.c deleted file mode 100644 index bf93c6fff1..0000000000 --- a/libart_lgpl/art_render_gradient.c +++ /dev/null @@ -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); -} diff --git a/libart_lgpl/art_render_gradient.h b/libart_lgpl/art_render_gradient.h deleted file mode 100644 index ff539033f1..0000000000 --- a/libart_lgpl/art_render_gradient.h +++ /dev/null @@ -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__ */ diff --git a/libart_lgpl/art_render_mask.c b/libart_lgpl/art_render_mask.c deleted file mode 100644 index ce82608dcd..0000000000 --- a/libart_lgpl/art_render_mask.c +++ /dev/null @@ -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); - -} diff --git a/libart_lgpl/art_render_mask.h b/libart_lgpl/art_render_mask.h deleted file mode 100644 index ef126e8042..0000000000 --- a/libart_lgpl/art_render_mask.h +++ /dev/null @@ -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__ */ diff --git a/libart_lgpl/art_render_svp.c b/libart_lgpl/art_render_svp.c deleted file mode 100644 index af75b7718e..0000000000 --- a/libart_lgpl/art_render_svp.c +++ /dev/null @@ -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); -} diff --git a/libart_lgpl/art_render_svp.h b/libart_lgpl/art_render_svp.h deleted file mode 100644 index edb1f92374..0000000000 --- a/libart_lgpl/art_render_svp.h +++ /dev/null @@ -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__ */ diff --git a/libart_lgpl/art_rgb_a_affine.c b/libart_lgpl/art_rgb_a_affine.c deleted file mode 100644 index ff38e2a5eb..0000000000 --- a/libart_lgpl/art_rgb_a_affine.c +++ /dev/null @@ -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; - } -} diff --git a/libart_lgpl/art_rgb_a_affine.h b/libart_lgpl/art_rgb_a_affine.h deleted file mode 100644 index 756fcbaaee..0000000000 --- a/libart_lgpl/art_rgb_a_affine.h +++ /dev/null @@ -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 diff --git a/libart_lgpl/art_rgb_bitmap_affine.c b/libart_lgpl/art_rgb_bitmap_affine.c deleted file mode 100644 index 825f8b5638..0000000000 --- a/libart_lgpl/art_rgb_bitmap_affine.c +++ /dev/null @@ -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; - } -} diff --git a/libart_lgpl/art_rgb_bitmap_affine.h b/libart_lgpl/art_rgb_bitmap_affine.h deleted file mode 100644 index 6c7d21d648..0000000000 --- a/libart_lgpl/art_rgb_bitmap_affine.h +++ /dev/null @@ -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 diff --git a/libart_lgpl/art_rgb_pixbuf_affine.c b/libart_lgpl/art_rgb_pixbuf_affine.c deleted file mode 100644 index 0a25b575db..0000000000 --- a/libart_lgpl/art_rgb_pixbuf_affine.c +++ /dev/null @@ -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); -} diff --git a/libart_lgpl/art_rgb_pixbuf_affine.h b/libart_lgpl/art_rgb_pixbuf_affine.h deleted file mode 100644 index 8d5b466858..0000000000 --- a/libart_lgpl/art_rgb_pixbuf_affine.h +++ /dev/null @@ -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 diff --git a/libart_lgpl/art_rgba.c b/libart_lgpl/art_rgba.c deleted file mode 100644 index cde183cc52..0000000000 --- a/libart_lgpl/art_rgba.c +++ /dev/null @@ -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 - } - } -} diff --git a/libart_lgpl/art_rgba.h b/libart_lgpl/art_rgba.h deleted file mode 100644 index 0d0fd432bd..0000000000 --- a/libart_lgpl/art_rgba.h +++ /dev/null @@ -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 diff --git a/libart_lgpl/art_svp_ops.c b/libart_lgpl/art_svp_ops.c index 5bb837c5ac..08991aac1b 100644 --- a/libart_lgpl/art_svp_ops.c +++ b/libart_lgpl/art_svp_ops.c @@ -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 */ diff --git a/libart_lgpl/art_svp_ops.h b/libart_lgpl/art_svp_ops.h index 1e511f5ed2..8f150c28dc 100644 --- a/libart_lgpl/art_svp_ops.h +++ b/libart_lgpl/art_svp_ops.h @@ -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 } diff --git a/libart_lgpl/art_svp_wind.c b/libart_lgpl/art_svp_wind.c deleted file mode 100644 index a12b1c7763..0000000000 --- a/libart_lgpl/art_svp_wind.c +++ /dev/null @@ -1,1545 +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. - */ - -/* Primitive intersection and winding number operations on sorted - vector paths. - - These routines are internal to libart, used to construct operations - like intersection, union, and difference. */ - -#include "config.h" -#include "art_svp_wind.h" - -#include <stdio.h> /* for printf of debugging info */ -#include <string.h> /* for memcpy */ -#include <math.h> -#include "art_misc.h" - -#include "art_rect.h" -#include "art_svp.h" - -#define noVERBOSE - -#define PT_EQ(p1,p2) ((p1).x == (p2).x && (p1).y == (p2).y) - -#define PT_CLOSE(p1,p2) (fabs ((p1).x - (p2).x) < 1e-6 && fabs ((p1).y - (p2).y) < 1e-6) - -/* return nonzero and set *p to the intersection point if the lines - z0-z1 and z2-z3 intersect each other. */ -static int -intersect_lines (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3, - ArtPoint *p) -{ - double a01, b01, c01; - double a23, b23, c23; - double d0, d1, d2, d3; - double det; - - /* if the vectors share an endpoint, they don't intersect */ - if (PT_EQ (z0, z2) || PT_EQ (z0, z3) || PT_EQ (z1, z2) || PT_EQ (z1, z3)) - return 0; - -#if 0 - if (PT_CLOSE (z0, z2) || PT_CLOSE (z0, z3) || PT_CLOSE (z1, z2) || PT_CLOSE (z1, z3)) - return 0; -#endif - - /* find line equations ax + by + c = 0 */ - a01 = z0.y - z1.y; - b01 = z1.x - z0.x; - c01 = -(z0.x * a01 + z0.y * b01); - /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y) - = (z1.x * z0.y - z1.y * z0.x) */ - - d2 = a01 * z2.x + b01 * z2.y + c01; - d3 = a01 * z3.x + b01 * z3.y + c01; - if ((d2 > 0) == (d3 > 0)) - return 0; - - a23 = z2.y - z3.y; - b23 = z3.x - z2.x; - c23 = -(z2.x * a23 + z2.y * b23); - - d0 = a23 * z0.x + b23 * z0.y + c23; - d1 = a23 * z1.x + b23 * z1.y + c23; - if ((d0 > 0) == (d1 > 0)) - return 0; - - /* now we definitely know that the lines intersect */ - /* solve the two linear equations ax + by + c = 0 */ - det = 1.0 / (a01 * b23 - a23 * b01); - p->x = det * (c23 * b01 - c01 * b23); - p->y = det * (c01 * a23 - c23 * a01); - - return 1; -} - -#define EPSILON 1e-6 - -static double -trap_epsilon (double v) -{ - const double epsilon = EPSILON; - - if (v < epsilon && v > -epsilon) return 0; - else return v; -} - -/* Determine the order of line segments z0-z1 and z2-z3. - Return +1 if z2-z3 lies entirely to the right of z0-z1, - -1 if entirely to the left, - or 0 if overlap. - - The case analysis in this function is quite ugly. The fact that it's - almost 200 lines long is ridiculous. - - Ok, so here's the plan to cut it down: - - First, do a bounding line comparison on the x coordinates. This is pretty - much the common case, and should go quickly. It also takes care of the - case where both lines are horizontal. - - Then, do d0 and d1 computation, but only if a23 is nonzero. - - Finally, do d2 and d3 computation, but only if a01 is nonzero. - - Fall through to returning 0 (this will happen when both lines are - horizontal and they overlap). - */ -static int -x_order (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3) -{ - double a01, b01, c01; - double a23, b23, c23; - double d0, d1, d2, d3; - - if (z0.y == z1.y) - { - if (z2.y == z3.y) - { - double x01min, x01max; - double x23min, x23max; - - if (z0.x > z1.x) - { - x01min = z1.x; - x01max = z0.x; - } - else - { - x01min = z0.x; - x01max = z1.x; - } - - if (z2.x > z3.x) - { - x23min = z3.x; - x23max = z2.x; - } - else - { - x23min = z2.x; - x23max = z3.x; - } - - if (x23min >= x01max) return 1; - else if (x01min >= x23max) return -1; - else return 0; - } - else - { - /* z0-z1 is horizontal, z2-z3 isn't */ - a23 = z2.y - z3.y; - b23 = z3.x - z2.x; - c23 = -(z2.x * a23 + z2.y * b23); - - if (z3.y < z2.y) - { - a23 = -a23; - b23 = -b23; - c23 = -c23; - } - - d0 = trap_epsilon (a23 * z0.x + b23 * z0.y + c23); - d1 = trap_epsilon (a23 * z1.x + b23 * z1.y + c23); - - if (d0 > 0) - { - if (d1 >= 0) return 1; - else return 0; - } - else if (d0 == 0) - { - if (d1 > 0) return 1; - else if (d1 < 0) return -1; - else printf ("case 1 degenerate\n"); - return 0; - } - else /* d0 < 0 */ - { - if (d1 <= 0) return -1; - else return 0; - } - } - } - else if (z2.y == z3.y) - { - /* z2-z3 is horizontal, z0-z1 isn't */ - a01 = z0.y - z1.y; - b01 = z1.x - z0.x; - c01 = -(z0.x * a01 + z0.y * b01); - /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y) - = (z1.x * z0.y - z1.y * z0.x) */ - - if (z1.y < z0.y) - { - a01 = -a01; - b01 = -b01; - c01 = -c01; - } - - d2 = trap_epsilon (a01 * z2.x + b01 * z2.y + c01); - d3 = trap_epsilon (a01 * z3.x + b01 * z3.y + c01); - - if (d2 > 0) - { - if (d3 >= 0) return -1; - else return 0; - } - else if (d2 == 0) - { - if (d3 > 0) return -1; - else if (d3 < 0) return 1; - else printf ("case 2 degenerate\n"); - return 0; - } - else /* d2 < 0 */ - { - if (d3 <= 0) return 1; - else return 0; - } - } - - /* find line equations ax + by + c = 0 */ - a01 = z0.y - z1.y; - b01 = z1.x - z0.x; - c01 = -(z0.x * a01 + z0.y * b01); - /* = -((z0.y - z1.y) * z0.x + (z1.x - z0.x) * z0.y) - = -(z1.x * z0.y - z1.y * z0.x) */ - - if (a01 > 0) - { - a01 = -a01; - b01 = -b01; - c01 = -c01; - } - /* so now, (a01, b01) points to the left, thus a01 * x + b01 * y + c01 - is negative if the point lies to the right of the line */ - - d2 = trap_epsilon (a01 * z2.x + b01 * z2.y + c01); - d3 = trap_epsilon (a01 * z3.x + b01 * z3.y + c01); - if (d2 > 0) - { - if (d3 >= 0) return -1; - } - else if (d2 == 0) - { - if (d3 > 0) return -1; - else if (d3 < 0) return 1; - else - fprintf (stderr, "colinear!\n"); - } - else /* d2 < 0 */ - { - if (d3 <= 0) return 1; - } - - a23 = z2.y - z3.y; - b23 = z3.x - z2.x; - c23 = -(z2.x * a23 + z2.y * b23); - - if (a23 > 0) - { - a23 = -a23; - b23 = -b23; - c23 = -c23; - } - d0 = trap_epsilon (a23 * z0.x + b23 * z0.y + c23); - d1 = trap_epsilon (a23 * z1.x + b23 * z1.y + c23); - if (d0 > 0) - { - if (d1 >= 0) return 1; - } - else if (d0 == 0) - { - if (d1 > 0) return 1; - else if (d1 < 0) return -1; - else - fprintf (stderr, "colinear!\n"); - } - else /* d0 < 0 */ - { - if (d1 <= 0) return -1; - } - - return 0; -} - -/* similar to x_order, but to determine whether point z0 + epsilon lies to - the left of the line z2-z3 or to the right */ -static int -x_order_2 (ArtPoint z0, ArtPoint z1, ArtPoint z2, ArtPoint z3) -{ - double a23, b23, c23; - double d0, d1; - - a23 = z2.y - z3.y; - b23 = z3.x - z2.x; - c23 = -(z2.x * a23 + z2.y * b23); - - if (a23 > 0) - { - a23 = -a23; - b23 = -b23; - c23 = -c23; - } - - d0 = a23 * z0.x + b23 * z0.y + c23; - - if (d0 > EPSILON) - return -1; - else if (d0 < -EPSILON) - return 1; - - d1 = a23 * z1.x + b23 * z1.y + c23; - if (d1 > EPSILON) - return -1; - else if (d1 < -EPSILON) - return 1; - - if (z0.x == z1.x && z1.x == z2.x && z2.x == z3.x) - { - art_dprint ("x_order_2: colinear and horizontally aligned!\n"); - return 0; - } - - if (z0.x <= z2.x && z1.x <= z2.x && z0.x <= z3.x && z1.x <= z3.x) - return -1; - if (z0.x >= z2.x && z1.x >= z2.x && z0.x >= z3.x && z1.x >= z3.x) - return 1; - - fprintf (stderr, "x_order_2: colinear!\n"); - return 0; -} - -#ifdef DEAD_CODE -/* Traverse the vector path, keeping it in x-sorted order. - - This routine doesn't actually do anything - it's just here for - explanatory purposes. */ -void -traverse (ArtSVP *vp) -{ - int *active_segs; - int n_active_segs; - int *cursor; - int seg_idx; - double y; - int tmp1, tmp2; - int asi; - int i, j; - - active_segs = art_new (int, vp->n_segs); - cursor = art_new (int, vp->n_segs); - - n_active_segs = 0; - seg_idx = 0; - y = vp->segs[0].points[0].y; - while (seg_idx < vp->n_segs || n_active_segs > 0) - { - printf ("y = %g\n", y); - /* delete segments ending at y from active list */ - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (vp->segs[asi].n_points - 1 == cursor[asi] && - vp->segs[asi].points[cursor[asi]].y == y) - { - printf ("deleting %d\n", asi); - n_active_segs--; - for (j = i; j < n_active_segs; j++) - active_segs[j] = active_segs[j + 1]; - i--; - } - } - - /* insert new segments into the active list */ - while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y) - { - cursor[seg_idx] = 0; - printf ("inserting %d\n", seg_idx); - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (x_order (vp->segs[asi].points[cursor[asi]], - vp->segs[asi].points[cursor[asi] + 1], - vp->segs[seg_idx].points[0], - vp->segs[seg_idx].points[1]) == -1) - break; - } - tmp1 = seg_idx; - for (j = i; j < n_active_segs; j++) - { - tmp2 = active_segs[j]; - active_segs[j] = tmp1; - tmp1 = tmp2; - } - active_segs[n_active_segs] = tmp1; - n_active_segs++; - seg_idx++; - } - - /* all active segs cross the y scanline (considering segs to be - closed on top and open on bottom) */ - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - printf ("%d (%g, %g) - (%g, %g) %s\n", asi, - vp->segs[asi].points[cursor[asi]].x, - vp->segs[asi].points[cursor[asi]].y, - vp->segs[asi].points[cursor[asi] + 1].x, - vp->segs[asi].points[cursor[asi] + 1].y, - vp->segs[asi].dir ? "v" : "^"); - } - - /* advance y to the next event */ - if (n_active_segs == 0) - { - if (seg_idx < vp->n_segs) - y = vp->segs[seg_idx].points[0].y; - /* else we're done */ - } - else - { - asi = active_segs[0]; - y = vp->segs[asi].points[cursor[asi] + 1].y; - for (i = 1; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (y > vp->segs[asi].points[cursor[asi] + 1].y) - y = vp->segs[asi].points[cursor[asi] + 1].y; - } - if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y) - y = vp->segs[seg_idx].points[0].y; - } - - /* advance cursors to reach new y */ - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - while (cursor[asi] < vp->segs[asi].n_points - 1 && - y >= vp->segs[asi].points[cursor[asi] + 1].y) - cursor[asi]++; - } - printf ("\n"); - } - art_free (cursor); - art_free (active_segs); -} -#endif - -/* I believe that the loop will always break with i=1. - - I think I'll want to change this from a simple sorted list to a - modified stack. ips[*][0] will get its own data structure, and - ips[*] will in general only be allocated if there is an intersection. - Finally, the segment can be traced through the initial point - (formerly ips[*][0]), backwards through the stack, and finally - to cursor + 1. - - This change should cut down on allocation bandwidth, and also - eliminate the iteration through n_ipl below. - -*/ -static void -insert_ip (int seg_i, int *n_ips, int *n_ips_max, ArtPoint **ips, ArtPoint ip) -{ - int i; - ArtPoint tmp1, tmp2; - int n_ipl; - ArtPoint *ipl; - - n_ipl = n_ips[seg_i]++; - if (n_ipl == n_ips_max[seg_i]) - art_expand (ips[seg_i], ArtPoint, n_ips_max[seg_i]); - ipl = ips[seg_i]; - for (i = 1; i < n_ipl; i++) - if (ipl[i].y > ip.y) - break; - tmp1 = ip; - for (; i <= n_ipl; i++) - { - tmp2 = ipl[i]; - ipl[i] = tmp1; - tmp1 = tmp2; - } -} - -/* test active segment (i - 1) against i for intersection, if - so, add intersection point to both ips lists. */ -static void -intersect_neighbors (int i, int *active_segs, - int *n_ips, int *n_ips_max, ArtPoint **ips, - int *cursor, ArtSVP *vp) -{ - ArtPoint z0, z1, z2, z3; - int asi01, asi23; - ArtPoint ip; - - asi01 = active_segs[i - 1]; - - z0 = ips[asi01][0]; - if (n_ips[asi01] == 1) - z1 = vp->segs[asi01].points[cursor[asi01] + 1]; - else - z1 = ips[asi01][1]; - - asi23 = active_segs[i]; - - z2 = ips[asi23][0]; - if (n_ips[asi23] == 1) - z3 = vp->segs[asi23].points[cursor[asi23] + 1]; - else - z3 = ips[asi23][1]; - - if (intersect_lines (z0, z1, z2, z3, &ip)) - { -#ifdef VERBOSE - printf ("new intersection point: (%g, %g)\n", ip.x, ip.y); -#endif - insert_ip (asi01, n_ips, n_ips_max, ips, ip); - insert_ip (asi23, n_ips, n_ips_max, ips, ip); - } -} - -/* Add a new point to a segment in the svp. - - Here, we also check to make sure that the segments satisfy nocross. - However, this is only valuable for debugging, and could possibly be - removed. -*/ -static void -svp_add_point (ArtSVP *svp, int *n_points_max, - ArtPoint p, int *seg_map, int *active_segs, int n_active_segs, - int i) -{ - int asi, asi_left, asi_right; - int n_points, n_points_left, n_points_right; - ArtSVPSeg *seg; - - asi = seg_map[active_segs[i]]; - seg = &svp->segs[asi]; - n_points = seg->n_points; - /* find out whether neighboring segments share a point */ - if (i > 0) - { - asi_left = seg_map[active_segs[i - 1]]; - n_points_left = svp->segs[asi_left].n_points; - if (n_points_left > 1 && - PT_EQ (svp->segs[asi_left].points[n_points_left - 2], - svp->segs[asi].points[n_points - 1])) - { - /* ok, new vector shares a top point with segment to the left - - now, check that it satisfies ordering invariant */ - if (x_order (svp->segs[asi_left].points[n_points_left - 2], - svp->segs[asi_left].points[n_points_left - 1], - svp->segs[asi].points[n_points - 1], - p) < 1) - - { -#ifdef VERBOSE - printf ("svp_add_point: cross on left!\n"); -#endif - } - } - } - - if (i + 1 < n_active_segs) - { - asi_right = seg_map[active_segs[i + 1]]; - n_points_right = svp->segs[asi_right].n_points; - if (n_points_right > 1 && - PT_EQ (svp->segs[asi_right].points[n_points_right - 2], - svp->segs[asi].points[n_points - 1])) - { - /* ok, new vector shares a top point with segment to the right - - now, check that it satisfies ordering invariant */ - if (x_order (svp->segs[asi_right].points[n_points_right - 2], - svp->segs[asi_right].points[n_points_right - 1], - svp->segs[asi].points[n_points - 1], - p) > -1) - { -#ifdef VERBOSE - printf ("svp_add_point: cross on right!\n"); -#endif - } - } - } - if (n_points_max[asi] == n_points) - art_expand (seg->points, ArtPoint, n_points_max[asi]); - seg->points[n_points] = p; - if (p.x < seg->bbox.x0) - seg->bbox.x0 = p.x; - else if (p.x > seg->bbox.x1) - seg->bbox.x1 = p.x; - seg->bbox.y1 = p.y; - seg->n_points++; -} - -#if 0 -/* find where the segment (currently at i) is supposed to go, and return - the target index - if equal to i, then there is no crossing problem. - - "Where it is supposed to go" is defined as following: - - Delete element i, re-insert at position target (bumping everything - target and greater to the right). - */ -static int -find_crossing (int i, int *active_segs, int n_active_segs, - int *cursor, ArtPoint **ips, int *n_ips, ArtSVP *vp) -{ - int asi, asi_left, asi_right; - ArtPoint p0, p1; - ArtPoint p0l, p1l; - ArtPoint p0r, p1r; - int target; - - asi = active_segs[i]; - p0 = ips[asi][0]; - if (n_ips[asi] == 1) - p1 = vp->segs[asi].points[cursor[asi] + 1]; - else - p1 = ips[asi][1]; - - for (target = i; target > 0; target--) - { - asi_left = active_segs[target - 1]; - p0l = ips[asi_left][0]; - if (n_ips[asi_left] == 1) - p1l = vp->segs[asi_left].points[cursor[asi_left] + 1]; - else - p1l = ips[asi_left][1]; - if (!PT_EQ (p0, p0l)) - break; - -#ifdef VERBOSE - printf ("point matches on left (%g, %g) - (%g, %g) x (%g, %g) - (%g, %g)!\n", - p0l.x, p0l.y, p1l.x, p1l.y, p0.x, p0.y, p1.x, p1.y); -#endif - if (x_order (p0l, p1l, p0, p1) == 1) - break; - -#ifdef VERBOSE - printf ("scanning to the left (i=%d, target=%d)\n", i, target); -#endif - } - - if (target < i) return target; - - for (; target < n_active_segs - 1; target++) - { - asi_right = active_segs[target + 1]; - p0r = ips[asi_right][0]; - if (n_ips[asi_right] == 1) - p1r = vp->segs[asi_right].points[cursor[asi_right] + 1]; - else - p1r = ips[asi_right][1]; - if (!PT_EQ (p0, p0r)) - break; - -#ifdef VERBOSE - printf ("point matches on left (%g, %g) - (%g, %g) x (%g, %g) - (%g, %g)!\n", - p0.x, p0.y, p1.x, p1.y, p0r.x, p0r.y, p1r.x, p1r.y); -#endif - if (x_order (p0r, p1r, p0, p1) == 1) - break; - -#ifdef VERBOSE - printf ("scanning to the right (i=%d, target=%d)\n", i, target); -#endif - } - - return target; -} -#endif - -/* This routine handles the case where the segment changes its position - in the active segment list. Generally, this will happen when the - segment (defined by i and cursor) shares a top point with a neighbor, - but breaks the ordering invariant. - - Essentially, this routine sorts the lines [start..end), all of which - share a top point. This is implemented as your basic insertion sort. - - This routine takes care of intersecting the appropriate neighbors, - as well. - - A first argument of -1 immediately returns, which helps reduce special - casing in the main unwind routine. -*/ -static void -fix_crossing (int start, int end, int *active_segs, int n_active_segs, - int *cursor, ArtPoint **ips, int *n_ips, int *n_ips_max, - ArtSVP *vp, int *seg_map, - ArtSVP **p_new_vp, int *pn_segs_max, - int **pn_points_max) -{ - int i, j; - int target; - int asi, asj; - ArtPoint p0i, p1i; - ArtPoint p0j, p1j; - int swap = 0; -#ifdef VERBOSE - int k; -#endif - ArtPoint *pts; - -#ifdef VERBOSE - printf ("fix_crossing: [%d..%d)", start, end); - for (k = 0; k < n_active_segs; k++) - printf (" %d", active_segs[k]); - printf ("\n"); -#endif - - if (start == -1) - return; - - for (i = start + 1; i < end; i++) - { - - asi = active_segs[i]; - if (cursor[asi] < vp->segs[asi].n_points - 1) { - p0i = ips[asi][0]; - if (n_ips[asi] == 1) - p1i = vp->segs[asi].points[cursor[asi] + 1]; - else - p1i = ips[asi][1]; - - for (j = i - 1; j >= start; j--) - { - asj = active_segs[j]; - if (cursor[asj] < vp->segs[asj].n_points - 1) - { - p0j = ips[asj][0]; - if (n_ips[asj] == 1) - p1j = vp->segs[asj].points[cursor[asj] + 1]; - else - p1j = ips[asj][1]; - - /* we _hope_ p0i = p0j */ - if (x_order_2 (p0j, p1j, p0i, p1i) == -1) - break; - } - } - - target = j + 1; - /* target is where active_seg[i] _should_ be in active_segs */ - - if (target != i) - { - swap = 1; - -#ifdef VERBOSE - printf ("fix_crossing: at %i should be %i\n", i, target); -#endif - - /* let's close off all relevant segments */ - for (j = i; j >= target; j--) - { - asi = active_segs[j]; - /* First conjunct: this isn't the last point in the original - segment. - - Second conjunct: this isn't the first point in the new - segment (i.e. already broken). - */ - if (cursor[asi] < vp->segs[asi].n_points - 1 && - (*p_new_vp)->segs[seg_map[asi]].n_points != 1) - { - int seg_num; - /* so break here */ -#ifdef VERBOSE - printf ("closing off %d\n", j); -#endif - - pts = art_new (ArtPoint, 16); - pts[0] = ips[asi][0]; - seg_num = art_svp_add_segment (p_new_vp, pn_segs_max, - pn_points_max, - 1, vp->segs[asi].dir, - pts, - NULL); - (*pn_points_max)[seg_num] = 16; - seg_map[asi] = seg_num; - } - } - - /* now fix the ordering in active_segs */ - asi = active_segs[i]; - for (j = i; j > target; j--) - active_segs[j] = active_segs[j - 1]; - active_segs[j] = asi; - } - } - } - if (swap && start > 0) - { - int as_start; - - as_start = active_segs[start]; - if (cursor[as_start] < vp->segs[as_start].n_points) - { -#ifdef VERBOSE - printf ("checking intersection of %d, %d\n", start - 1, start); -#endif - intersect_neighbors (start, active_segs, - n_ips, n_ips_max, ips, - cursor, vp); - } - } - - if (swap && end < n_active_segs) - { - int as_end; - - as_end = active_segs[end - 1]; - if (cursor[as_end] < vp->segs[as_end].n_points) - { -#ifdef VERBOSE - printf ("checking intersection of %d, %d\n", end - 1, end); -#endif - intersect_neighbors (end, active_segs, - n_ips, n_ips_max, ips, - cursor, vp); - } - } - if (swap) - { -#ifdef VERBOSE - printf ("fix_crossing return: [%d..%d)", start, end); - for (k = 0; k < n_active_segs; k++) - printf (" %d", active_segs[k]); - printf ("\n"); -#endif - } -} - -/* Return a new sorted vector that covers the same area as the - argument, but which satisfies the nocross invariant. - - Basically, this routine works by finding the intersection points, - and cutting the segments at those points. - - Status of this routine: - - Basic correctness: Seems ok. - - Numerical stability: known problems in the case of points falling - on lines, and colinear lines. For actual use, randomly perturbing - the vertices is currently recommended. - - Speed: pretty good, although a more efficient priority queue, as - well as bbox culling of potential intersections, are two - optimizations that could help. - - Precision: pretty good, although the numerical stability problems - make this routine unsuitable for precise calculations of - differences. - -*/ - -/* Here is a more detailed description of the algorithm. It follows - roughly the structure of traverse (above), but is obviously quite - a bit more complex. - - Here are a few important data structures: - - A new sorted vector path (new_svp). - - For each (active) segment in the original, a list of intersection - points. - - Of course, the original being traversed. - - The following invariants hold (in addition to the invariants - of the traverse procedure). - - The new sorted vector path lies entirely above the y scan line. - - The new sorted vector path keeps the nocross invariant. - - For each active segment, the y scan line crosses the line from the - first to the second of the intersection points (where the second - point is cursor + 1 if there is only one intersection point). - - The list of intersection points + the (cursor + 1) point is kept - in nondecreasing y order. - - Of the active segments, none of the lines from first to second - intersection point cross the 1st ip..2nd ip line of the left or - right neighbor. (However, such a line may cross further - intersection points of the neighbors, or segments past the - immediate neighbors). - - Of the active segments, all lines from 1st ip..2nd ip are in - strictly increasing x_order (this is very similar to the invariant - of the traverse procedure, but is explicitly stated here in terms - of ips). (this basically says that nocross holds on the active - segments) - - The combination of the new sorted vector path, the path through all - the intersection points to cursor + 1, and [cursor + 1, n_points) - covers the same area as the argument. - - Another important data structure is mapping from original segment - number to new segment number. - - The algorithm is perhaps best understood as advancing the cursors - while maintaining these invariants. Here's roughly how it's done. - - When deleting segments from the active list, those segments are added - to the new sorted vector path. In addition, the neighbors may intersect - each other, so they are intersection tested (see below). - - When inserting new segments, they are intersection tested against - their neighbors. The top point of the segment becomes the first - intersection point. - - Advancing the cursor is just a bit different from the traverse - routine, as the cursor may advance through the intersection points - as well. Only when there is a single intersection point in the list - does the cursor advance in the original segment. In either case, - the new vector is intersection tested against both neighbors. It - also causes the vector over which the cursor is advancing to be - added to the new svp. - - Two steps need further clarification: - - Intersection testing: the 1st ip..2nd ip lines of the neighbors - are tested to see if they cross (using intersect_lines). If so, - then the intersection point is added to the ip list of both - segments, maintaining the invariant that the list of intersection - points is nondecreasing in y). - - Adding vector to new svp: if the new vector shares a top x - coordinate with another vector, then it is checked to see whether - it is in order. If not, then both segments are "broken," and then - restarted. Note: in the case when both segments are in the same - order, they may simply be swapped without breaking. - - For the time being, I'm going to put some of these operations into - subroutines. If it turns out to be a performance problem, I could - try to reorganize the traverse procedure so that each is only - called once, and inline them. But if it's not a performance - problem, I'll just keep it this way, because it will probably help - to make the code clearer, and I believe this code could use all the - clarity it can get. */ -/** - * art_svp_uncross: Resolve self-intersections of an svp. - * @vp: The original svp. - * - * Finds all the intersections within @vp, and constructs a new svp - * with new points added at these intersections. - * - * This routine needs to be redone from scratch with numerical robustness - * in mind. I'm working on it. - * - * Return value: The new svp. - **/ -ArtSVP * -art_svp_uncross (ArtSVP *vp) -{ - int *active_segs; - int n_active_segs; - int *cursor; - int seg_idx; - double y; - int tmp1, tmp2; - int asi; - int i, j; - /* new data structures */ - /* intersection points; invariant: *ips[i] is only allocated if - i is active */ - int *n_ips, *n_ips_max; - ArtPoint **ips; - /* new sorted vector path */ - int n_segs_max, seg_num; - ArtSVP *new_vp; - int *n_points_max; - /* mapping from argument to new segment numbers - again, only valid - if active */ - int *seg_map; - double y_curs; - ArtPoint p_curs; - int first_share; - double share_x; - ArtPoint *pts; - - n_segs_max = 16; - new_vp = (ArtSVP *)art_alloc (sizeof(ArtSVP) + - (n_segs_max - 1) * sizeof(ArtSVPSeg)); - new_vp->n_segs = 0; - - if (vp->n_segs == 0) - return new_vp; - - active_segs = art_new (int, vp->n_segs); - cursor = art_new (int, vp->n_segs); - - seg_map = art_new (int, vp->n_segs); - n_ips = art_new (int, vp->n_segs); - n_ips_max = art_new (int, vp->n_segs); - ips = art_new (ArtPoint *, vp->n_segs); - - n_points_max = art_new (int, n_segs_max); - - n_active_segs = 0; - seg_idx = 0; - y = vp->segs[0].points[0].y; - while (seg_idx < vp->n_segs || n_active_segs > 0) - { -#ifdef VERBOSE - printf ("y = %g\n", y); -#endif - - /* maybe move deletions to end of loop (to avoid so much special - casing on the end of a segment)? */ - - /* delete segments ending at y from active list */ - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (vp->segs[asi].n_points - 1 == cursor[asi] && - vp->segs[asi].points[cursor[asi]].y == y) - { - do - { -#ifdef VERBOSE - printf ("deleting %d\n", asi); -#endif - art_free (ips[asi]); - n_active_segs--; - for (j = i; j < n_active_segs; j++) - active_segs[j] = active_segs[j + 1]; - if (i < n_active_segs) - asi = active_segs[i]; - else - break; - } - while (vp->segs[asi].n_points - 1 == cursor[asi] && - vp->segs[asi].points[cursor[asi]].y == y); - - /* test intersection of neighbors */ - if (i > 0 && i < n_active_segs) - intersect_neighbors (i, active_segs, - n_ips, n_ips_max, ips, - cursor, vp); - - i--; - } - } - - /* insert new segments into the active list */ - while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y) - { -#ifdef VERBOSE - printf ("inserting %d\n", seg_idx); -#endif - cursor[seg_idx] = 0; - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (x_order_2 (vp->segs[seg_idx].points[0], - vp->segs[seg_idx].points[1], - vp->segs[asi].points[cursor[asi]], - vp->segs[asi].points[cursor[asi] + 1]) == -1) - break; - } - - /* Create and initialize the intersection points data structure */ - n_ips[seg_idx] = 1; - n_ips_max[seg_idx] = 2; - ips[seg_idx] = art_new (ArtPoint, n_ips_max[seg_idx]); - ips[seg_idx][0] = vp->segs[seg_idx].points[0]; - - /* Start a new segment in the new vector path */ - pts = art_new (ArtPoint, 16); - pts[0] = vp->segs[seg_idx].points[0]; - seg_num = art_svp_add_segment (&new_vp, &n_segs_max, - &n_points_max, - 1, vp->segs[seg_idx].dir, - pts, - NULL); - n_points_max[seg_num] = 16; - seg_map[seg_idx] = seg_num; - - tmp1 = seg_idx; - for (j = i; j < n_active_segs; j++) - { - tmp2 = active_segs[j]; - active_segs[j] = tmp1; - tmp1 = tmp2; - } - active_segs[n_active_segs] = tmp1; - n_active_segs++; - - if (i > 0) - intersect_neighbors (i, active_segs, - n_ips, n_ips_max, ips, - cursor, vp); - - if (i + 1 < n_active_segs) - intersect_neighbors (i + 1, active_segs, - n_ips, n_ips_max, ips, - cursor, vp); - - seg_idx++; - } - - /* all active segs cross the y scanline (considering segs to be - closed on top and open on bottom) */ -#ifdef VERBOSE - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - printf ("%d ", asi); - for (j = 0; j < n_ips[asi]; j++) - printf ("(%g, %g) - ", - ips[asi][j].x, - ips[asi][j].y); - printf ("(%g, %g) %s\n", - vp->segs[asi].points[cursor[asi] + 1].x, - vp->segs[asi].points[cursor[asi] + 1].y, - vp->segs[asi].dir ? "v" : "^"); - } -#endif - - /* advance y to the next event - Note: this is quadratic. We'd probably get decent constant - factor speed improvement by caching the y_curs values. */ - if (n_active_segs == 0) - { - if (seg_idx < vp->n_segs) - y = vp->segs[seg_idx].points[0].y; - /* else we're done */ - } - else - { - asi = active_segs[0]; - if (n_ips[asi] == 1) - y = vp->segs[asi].points[cursor[asi] + 1].y; - else - y = ips[asi][1].y; - for (i = 1; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (n_ips[asi] == 1) - y_curs = vp->segs[asi].points[cursor[asi] + 1].y; - else - y_curs = ips[asi][1].y; - if (y > y_curs) - y = y_curs; - } - if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y) - y = vp->segs[seg_idx].points[0].y; - } - - first_share = -1; - share_x = 0; /* to avoid gcc warning, although share_x is never - used when first_share is -1 */ - /* advance cursors to reach new y */ - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (n_ips[asi] == 1) - p_curs = vp->segs[asi].points[cursor[asi] + 1]; - else - p_curs = ips[asi][1]; - if (p_curs.y == y) - { - svp_add_point (new_vp, n_points_max, - p_curs, seg_map, active_segs, n_active_segs, i); - - n_ips[asi]--; - for (j = 0; j < n_ips[asi]; j++) - ips[asi][j] = ips[asi][j + 1]; - - if (n_ips[asi] == 0) - { - ips[asi][0] = p_curs; - n_ips[asi] = 1; - cursor[asi]++; - } - - if (first_share < 0 || p_curs.x != share_x) - { - /* this is where crossings are detected, and if - found, the active segments switched around. */ - - fix_crossing (first_share, i, - active_segs, n_active_segs, - cursor, ips, n_ips, n_ips_max, vp, seg_map, - &new_vp, - &n_segs_max, &n_points_max); - - first_share = i; - share_x = p_curs.x; - } - - if (cursor[asi] < vp->segs[asi].n_points - 1) - { - - if (i > 0) - intersect_neighbors (i, active_segs, - n_ips, n_ips_max, ips, - cursor, vp); - - if (i + 1 < n_active_segs) - intersect_neighbors (i + 1, active_segs, - n_ips, n_ips_max, ips, - cursor, vp); - } - } - else - { - /* not on a cursor point */ - fix_crossing (first_share, i, - active_segs, n_active_segs, - cursor, ips, n_ips, n_ips_max, vp, seg_map, - &new_vp, - &n_segs_max, &n_points_max); - first_share = -1; - } - } - - /* fix crossing on last shared group */ - fix_crossing (first_share, i, - active_segs, n_active_segs, - cursor, ips, n_ips, n_ips_max, vp, seg_map, - &new_vp, - &n_segs_max, &n_points_max); - -#ifdef VERBOSE - printf ("\n"); -#endif - } - - /* not necessary to sort, new segments only get added at y, which - increases monotonically */ -#if 0 - qsort (&new_vp->segs, new_vp->n_segs, sizeof (svp_seg), svp_seg_compare); - { - int k; - for (k = 0; k < new_vp->n_segs - 1; k++) - { - printf ("(%g, %g) - (%g, %g) %s (%g, %g) - (%g, %g)\n", - new_vp->segs[k].points[0].x, - new_vp->segs[k].points[0].y, - new_vp->segs[k].points[1].x, - new_vp->segs[k].points[1].y, - svp_seg_compare (&new_vp->segs[k], &new_vp->segs[k + 1]) > 1 ? ">": "<", - new_vp->segs[k + 1].points[0].x, - new_vp->segs[k + 1].points[0].y, - new_vp->segs[k + 1].points[1].x, - new_vp->segs[k + 1].points[1].y); - } - } -#endif - - art_free (n_points_max); - art_free (seg_map); - art_free (n_ips_max); - art_free (n_ips); - art_free (ips); - art_free (cursor); - art_free (active_segs); - - return new_vp; -} - -#define noVERBOSE - -/* Rewind a svp satisfying the nocross invariant. - - The winding number of a segment is defined as the winding number of - the points to the left while travelling in the direction of the - segment. Therefore it preincrements and postdecrements as a scan - line is traversed from left to right. - - Status of this routine: - - Basic correctness: Was ok in gfonted. However, this code does not - yet compute bboxes for the resulting svp segs. - - Numerical stability: known problems in the case of horizontal - segments in polygons with any complexity. For actual use, randomly - perturbing the vertices is recommended. - - Speed: good. - - Precision: good, except that no attempt is made to remove "hair". - Doing random perturbation just makes matters worse. - -*/ -/** - * art_svp_rewind_uncrossed: Rewind an svp satisfying the nocross invariant. - * @vp: The original svp. - * @rule: The winding rule. - * - * Creates a new svp with winding number of 0 or 1 everywhere. The @rule - * argument specifies a rule for how winding numbers in the original - * @vp map to the winding numbers in the result. - * - * With @rule == ART_WIND_RULE_NONZERO, the resulting svp has a - * winding number of 1 where @vp has a nonzero winding number. - * - * With @rule == ART_WIND_RULE_INTERSECT, the resulting svp has a - * winding number of 1 where @vp has a winding number greater than - * 1. It is useful for computing intersections. - * - * With @rule == ART_WIND_RULE_ODDEVEN, the resulting svp has a - * winding number of 1 where @vp has an odd winding number. It is - * useful for implementing the even-odd winding rule of the - * PostScript imaging model. - * - * With @rule == ART_WIND_RULE_POSITIVE, the resulting svp has a - * winding number of 1 where @vp has a positive winding number. It is - * useful for implementing asymmetric difference. - * - * This routine needs to be redone from scratch with numerical robustness - * in mind. I'm working on it. - * - * Return value: The new svp. - **/ -ArtSVP * -art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule) -{ - int *active_segs; - int n_active_segs; - int *cursor; - int seg_idx; - double y; - int tmp1, tmp2; - int asi; - int i, j; - - ArtSVP *new_vp; - int n_segs_max; - int *winding; - int left_wind; - int wind; - int keep, invert; - -#ifdef VERBOSE - print_svp (vp); -#endif - n_segs_max = 16; - new_vp = (ArtSVP *)art_alloc (sizeof(ArtSVP) + - (n_segs_max - 1) * sizeof(ArtSVPSeg)); - new_vp->n_segs = 0; - - if (vp->n_segs == 0) - return new_vp; - - winding = art_new (int, vp->n_segs); - - active_segs = art_new (int, vp->n_segs); - cursor = art_new (int, vp->n_segs); - - n_active_segs = 0; - seg_idx = 0; - y = vp->segs[0].points[0].y; - while (seg_idx < vp->n_segs || n_active_segs > 0) - { -#ifdef VERBOSE - printf ("y = %g\n", y); -#endif - /* delete segments ending at y from active list */ - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (vp->segs[asi].n_points - 1 == cursor[asi] && - vp->segs[asi].points[cursor[asi]].y == y) - { -#ifdef VERBOSE - printf ("deleting %d\n", asi); -#endif - n_active_segs--; - for (j = i; j < n_active_segs; j++) - active_segs[j] = active_segs[j + 1]; - i--; - } - } - - /* insert new segments into the active list */ - while (seg_idx < vp->n_segs && y == vp->segs[seg_idx].points[0].y) - { -#ifdef VERBOSE - printf ("inserting %d\n", seg_idx); -#endif - cursor[seg_idx] = 0; - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (x_order_2 (vp->segs[seg_idx].points[0], - vp->segs[seg_idx].points[1], - vp->segs[asi].points[cursor[asi]], - vp->segs[asi].points[cursor[asi] + 1]) == -1) - break; - } - - /* Determine winding number for this segment */ - if (i == 0) - left_wind = 0; - else if (vp->segs[active_segs[i - 1]].dir) - left_wind = winding[active_segs[i - 1]]; - else - left_wind = winding[active_segs[i - 1]] - 1; - - if (vp->segs[seg_idx].dir) - wind = left_wind + 1; - else - wind = left_wind; - - winding[seg_idx] = wind; - - switch (rule) - { - case ART_WIND_RULE_NONZERO: - keep = (wind == 1 || wind == 0); - invert = (wind == 0); - break; - case ART_WIND_RULE_INTERSECT: - keep = (wind == 2); - invert = 0; - break; - case ART_WIND_RULE_ODDEVEN: - keep = 1; - invert = !(wind & 1); - break; - case ART_WIND_RULE_POSITIVE: - keep = (wind == 1); - invert = 0; - break; - default: - keep = 0; - invert = 0; - break; - } - - if (keep) - { - ArtPoint *points, *new_points; - int n_points; - int new_dir; - -#ifdef VERBOSE - printf ("keeping segment %d\n", seg_idx); -#endif - n_points = vp->segs[seg_idx].n_points; - points = vp->segs[seg_idx].points; - new_points = art_new (ArtPoint, n_points); - memcpy (new_points, points, n_points * sizeof (ArtPoint)); - new_dir = vp->segs[seg_idx].dir ^ invert; - art_svp_add_segment (&new_vp, &n_segs_max, - NULL, - n_points, new_dir, new_points, - &vp->segs[seg_idx].bbox); - } - - tmp1 = seg_idx; - for (j = i; j < n_active_segs; j++) - { - tmp2 = active_segs[j]; - active_segs[j] = tmp1; - tmp1 = tmp2; - } - active_segs[n_active_segs] = tmp1; - n_active_segs++; - seg_idx++; - } - -#ifdef VERBOSE - /* all active segs cross the y scanline (considering segs to be - closed on top and open on bottom) */ - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - printf ("%d:%d (%g, %g) - (%g, %g) %s %d\n", asi, - cursor[asi], - vp->segs[asi].points[cursor[asi]].x, - vp->segs[asi].points[cursor[asi]].y, - vp->segs[asi].points[cursor[asi] + 1].x, - vp->segs[asi].points[cursor[asi] + 1].y, - vp->segs[asi].dir ? "v" : "^", - winding[asi]); - } -#endif - - /* advance y to the next event */ - if (n_active_segs == 0) - { - if (seg_idx < vp->n_segs) - y = vp->segs[seg_idx].points[0].y; - /* else we're done */ - } - else - { - asi = active_segs[0]; - y = vp->segs[asi].points[cursor[asi] + 1].y; - for (i = 1; i < n_active_segs; i++) - { - asi = active_segs[i]; - if (y > vp->segs[asi].points[cursor[asi] + 1].y) - y = vp->segs[asi].points[cursor[asi] + 1].y; - } - if (seg_idx < vp->n_segs && y > vp->segs[seg_idx].points[0].y) - y = vp->segs[seg_idx].points[0].y; - } - - /* advance cursors to reach new y */ - for (i = 0; i < n_active_segs; i++) - { - asi = active_segs[i]; - while (cursor[asi] < vp->segs[asi].n_points - 1 && - y >= vp->segs[asi].points[cursor[asi] + 1].y) - cursor[asi]++; - } -#ifdef VERBOSE - printf ("\n"); -#endif - } - art_free (cursor); - art_free (active_segs); - art_free (winding); - - return new_vp; -} diff --git a/libart_lgpl/art_svp_wind.h b/libart_lgpl/art_svp_wind.h index 0e9d5e70d4..fd999b4bb9 100644 --- a/libart_lgpl/art_svp_wind.h +++ b/libart_lgpl/art_svp_wind.h @@ -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 */ diff --git a/libart_lgpl/art_uta_ops.c b/libart_lgpl/art_uta_ops.c deleted file mode 100644 index 1b4251607b..0000000000 --- a/libart_lgpl/art_uta_ops.c +++ /dev/null @@ -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; -} diff --git a/libart_lgpl/art_uta_ops.h b/libart_lgpl/art_uta_ops.h deleted file mode 100644 index fc19d012ee..0000000000 --- a/libart_lgpl/art_uta_ops.h +++ /dev/null @@ -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__ */ diff --git a/libart_lgpl/art_vpath.c b/libart_lgpl/art_vpath.c index fa7b903d11..5152188b1b 100644 --- a/libart_lgpl/art_vpath.c +++ b/libart_lgpl/art_vpath.c @@ -63,77 +63,6 @@ art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max, #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. * @drect: Where to store bounding box. @@ -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; -} diff --git a/libart_lgpl/art_vpath.h b/libart_lgpl/art_vpath.h index 4102d28908..f5557f6005 100644 --- a/libart_lgpl/art_vpath.h +++ b/libart_lgpl/art_vpath.h @@ -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 */ diff --git a/libart_lgpl/libart.h b/libart_lgpl/libart.h index 4a9eeea60a..6d93588bf5 100644 --- a/libart_lgpl/libart.h +++ b/libart_lgpl/libart.h @@ -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> |