commit
a9eaee5264
@ -0,0 +1,177 @@
|
||||
noinst_PROGRAMS = testart testuta
|
||||
|
||||
bin_SCRIPTS = \
|
||||
libart2-config
|
||||
|
||||
noinst_SCRIPTS = gen_art_config.sh
|
||||
|
||||
BUILT_SOURCES = art_config.h
|
||||
|
||||
art_config.h:
|
||||
./gen_art_config.sh > art_config.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
libart.def \
|
||||
libart-config.in \
|
||||
libart-2.0.pc.in \
|
||||
libart-2.0-uninstalled.pc.in
|
||||
|
||||
lib_LTLIBRARIES = libart_lgpl_2.la
|
||||
|
||||
if PLATFORM_WIN32
|
||||
no_undefined = -no-undefined
|
||||
endif
|
||||
|
||||
if OS_WIN32
|
||||
export_symbols = -export-symbols libart.def
|
||||
|
||||
install-libtool-import-lib:
|
||||
$(INSTALL) .libs/libart_lgpl_2.dll.a $(DESTDIR)$(libdir)
|
||||
uninstall-libtool-import-lib:
|
||||
-rm $(DESTDIR)$(libdir)/libart_lgpl_2.dll.a
|
||||
else
|
||||
install-libtool-import-lib:
|
||||
uninstall-libtool-import-lib:
|
||||
|
||||
libm = -lm
|
||||
endif
|
||||
|
||||
if MS_LIB_AVAILABLE
|
||||
noinst_DATA = art_lgpl_2.lib
|
||||
|
||||
install-ms-lib:
|
||||
$(INSTALL) art_lgpl_2.lib $(DESTDIR)$(libdir)
|
||||
|
||||
uninstall-ms-lib:
|
||||
-rm $(DESTDIR)$(libdir)/art_lgpl_2.lib
|
||||
|
||||
art_lgpl_2.lib : libart_lgpl_2.la
|
||||
lib -name:libart_lgpl_2-@LIBART_MAJOR_VERSION@.dll -def:libart.def -out:$@
|
||||
|
||||
else
|
||||
install-ms-lib:
|
||||
uninstall-ms-lib:
|
||||
endif
|
||||
|
||||
libart_lgpl_2_la_SOURCES = \
|
||||
art_affine.c \
|
||||
art_alphagamma.c \
|
||||
art_bpath.c \
|
||||
art_gray_svp.c \
|
||||
art_misc.c \
|
||||
art_pixbuf.c \
|
||||
art_rect.c \
|
||||
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_affine.c \
|
||||
art_rgb_affine_private.c \
|
||||
art_rgb_affine_private.h \
|
||||
art_rgb_bitmap_affine.c \
|
||||
art_rgb_pixbuf_affine.c \
|
||||
art_rgb_rgba_affine.c \
|
||||
art_rgb_a_affine.c \
|
||||
art_rgba.c \
|
||||
art_rgb_svp.c \
|
||||
art_svp.c \
|
||||
art_svp_intersect.c \
|
||||
art_svp_ops.c \
|
||||
art_svp_point.c \
|
||||
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_vpath.c \
|
||||
art_uta_svp.c \
|
||||
art_vpath.c \
|
||||
art_vpath_bpath.c \
|
||||
art_vpath_dash.c \
|
||||
art_vpath_svp.c \
|
||||
libart-features.c
|
||||
|
||||
libart_lgpl_2_la_LDFLAGS = -version-info @LIBART_VERSION_INFO@ $(no_undefined) $(export_symbols)
|
||||
libart_lgpl_2_la_LIBADD = $(libm)
|
||||
|
||||
libart_lgplincdir = $(includedir)/libart-2.0/libart_lgpl
|
||||
libart_lgplinc_HEADERS = \
|
||||
art_affine.h \
|
||||
art_alphagamma.h \
|
||||
art_bpath.h \
|
||||
art_config.h \
|
||||
art_filterlevel.h \
|
||||
art_gray_svp.h \
|
||||
art_misc.h \
|
||||
art_pathcode.h \
|
||||
art_pixbuf.h \
|
||||
art_point.h \
|
||||
art_rect.h \
|
||||
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_affine.h \
|
||||
art_rgb_bitmap_affine.h \
|
||||
art_rgb_pixbuf_affine.h \
|
||||
art_rgb_rgba_affine.h \
|
||||
art_rgb_a_affine.h \
|
||||
art_rgb_svp.h \
|
||||
art_rgba.h \
|
||||
art_svp.h \
|
||||
art_svp_intersect.h \
|
||||
art_svp_ops.h \
|
||||
art_svp_point.h \
|
||||
art_svp_render_aa.h \
|
||||
art_svp_vpath.h \
|
||||
art_svp_vpath_stroke.h \
|
||||
art_svp_wind.h \
|
||||
art_uta.h \
|
||||
art_uta_ops.h \
|
||||
art_uta_rect.h \
|
||||
art_uta_vpath.h \
|
||||
art_uta_svp.h \
|
||||
art_vpath.h \
|
||||
art_vpath_bpath.h \
|
||||
art_vpath_dash.h \
|
||||
art_vpath_svp.h \
|
||||
libart.h \
|
||||
libart-features.h
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_builddir) -DLIBART_COMPILATION
|
||||
|
||||
DEPS = $(top_builddir)/libart_lgpl_2.la
|
||||
LDADDS = $(top_builddir)/libart_lgpl_2.la
|
||||
|
||||
testart_SOURCES=testart.c
|
||||
testart_LDFLAGS =
|
||||
testart_DEPENDENCIES = $(DEPS)
|
||||
testart_LDADD = $(LDADDS) $(libm)
|
||||
|
||||
testuta_SOURCES=testuta.c
|
||||
testuta_LDFLAGS =
|
||||
testuta_DEPENDENCIES = $(DEPS)
|
||||
testuta_LDADD = $(LDADDS) $(libm)
|
||||
|
||||
tests: testart testuta
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libart-2.0.pc
|
||||
|
||||
libart2-config: libart-config
|
||||
cp -f libart-config libart2-config
|
||||
|
||||
install-data-local: install-ms-lib install-libtool-import-lib
|
||||
|
||||
uninstall-local: uninstall-ms-lib uninstall-libtool-import-lib
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES) $(bin_SCRIPTS)
|
||||
DISTCLEANFILES = $(BUILT_SOURCES) $(bin_SCRIPTS)
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,35 @@
|
||||
==============
|
||||
Version 2.3.21
|
||||
==============
|
||||
|
||||
- Allow crosscompiling without using different emulators (Fridrich Strba)
|
||||
|
||||
==============
|
||||
Version 2.3.20
|
||||
==============
|
||||
|
||||
- Fix including art_misc.h from C++
|
||||
|
||||
==============
|
||||
Version 2.3.19
|
||||
==============
|
||||
|
||||
- Fix typo that broke versioning. (Yanko Kaneti)
|
||||
|
||||
==============
|
||||
Version 2.3.18
|
||||
==============
|
||||
|
||||
- Port to automake 1.9 (Christian Persch)
|
||||
- Cygwin build fixes (Cygwin ports maintainer)
|
||||
- Fixes for memory management on win32 (Dom Lachowicz)
|
||||
- Compiler warning fixes (Kjartan, Tor Lillqvist)
|
||||
|
||||
==============
|
||||
Version 2.3.17
|
||||
==============
|
||||
|
||||
- Updated pkg-config files (Glynn Foster)
|
||||
- Distribute libart.def (Michael Meeks)
|
||||
- Add link to Mathieu's tutorial on libart (Kjartan)
|
||||
|
@ -0,0 +1,19 @@
|
||||
This is the LGPL'd component of libart. All functions needed for
|
||||
running the Gnome canvas, and for printing support, will be going in
|
||||
here. The GPL'd component will be getting various enhanced functions
|
||||
for specific applications.
|
||||
|
||||
Libart is free software. It is also for sale. For information about
|
||||
licensing libart, please contact Raph Levien
|
||||
<raph@acm.org>. Contributions to the codebase are also very welcome,
|
||||
but the copyright must be assigned in writing to preserve the
|
||||
licensing flexibility.
|
||||
|
||||
|
||||
For more information about libart, see the web page:
|
||||
|
||||
http://www.levien.com/libart/
|
||||
|
||||
There's also a libart tutorial available at
|
||||
http://www.gnome.org/~mathieu/libart/libart.html
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,458 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Simple manipulations with affine transformations */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_affine.h"
|
||||
#include "art_misc.h" /* for M_PI */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h> /* for sprintf */
|
||||
#include <string.h> /* for strcpy */
|
||||
|
||||
|
||||
/* According to a strict interpretation of the libart structure, this
|
||||
routine should go into its own module, art_point_affine. However,
|
||||
it's only two lines of code, and it can be argued that it is one of
|
||||
the natural basic functions of an affine transformation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* art_affine_point: Do an affine transformation of a point.
|
||||
* @dst: Where the result point is stored.
|
||||
* @src: The original point.
|
||||
@ @affine: The affine transformation.
|
||||
**/
|
||||
void
|
||||
art_affine_point (ArtPoint *dst, const ArtPoint *src,
|
||||
const double affine[6])
|
||||
{
|
||||
double x, y;
|
||||
|
||||
x = src->x;
|
||||
y = src->y;
|
||||
dst->x = x * affine[0] + y * affine[2] + affine[4];
|
||||
dst->y = x * affine[1] + y * affine[3] + affine[5];
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_invert: Find the inverse of an affine transformation.
|
||||
* @dst: Where the resulting affine is stored.
|
||||
* @src: The original affine transformation.
|
||||
*
|
||||
* All non-degenerate affine transforms are invertible. If the original
|
||||
* affine is degenerate or nearly so, expect numerical instability and
|
||||
* very likely core dumps on Alpha and other fp-picky architectures.
|
||||
* Otherwise, @dst multiplied with @src, or @src multiplied with @dst
|
||||
* will be (to within roundoff error) the identity affine.
|
||||
**/
|
||||
void
|
||||
art_affine_invert (double dst[6], const double src[6])
|
||||
{
|
||||
double r_det;
|
||||
|
||||
r_det = 1.0 / (src[0] * src[3] - src[1] * src[2]);
|
||||
dst[0] = src[3] * r_det;
|
||||
dst[1] = -src[1] * r_det;
|
||||
dst[2] = -src[2] * r_det;
|
||||
dst[3] = src[0] * r_det;
|
||||
dst[4] = -src[4] * dst[0] - src[5] * dst[2];
|
||||
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
|
||||
six digits of precision, which is good enough for PostScript.
|
||||
|
||||
The return value is the number of characters (i.e. strlen (str)).
|
||||
It is no more than 12. */
|
||||
static int
|
||||
art_ftoa (char str[80], double x)
|
||||
{
|
||||
char *p = str;
|
||||
int i, j;
|
||||
|
||||
p = str;
|
||||
if (fabs (x) < EPSILON / 2)
|
||||
{
|
||||
strcpy (str, "0");
|
||||
return 1;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
*p++ = '-';
|
||||
x = -x;
|
||||
}
|
||||
if ((int)floor ((x + EPSILON / 2) < 1))
|
||||
{
|
||||
*p++ = '0';
|
||||
*p++ = '.';
|
||||
i = sprintf (p, "%06d", (int)floor ((x + EPSILON / 2) * 1e6));
|
||||
while (i && p[i - 1] == '0')
|
||||
i--;
|
||||
if (i == 0)
|
||||
i--;
|
||||
p += i;
|
||||
}
|
||||
else if (x < 1e6)
|
||||
{
|
||||
i = sprintf (p, "%d", (int)floor (x + EPSILON / 2));
|
||||
p += i;
|
||||
if (i < 6)
|
||||
{
|
||||
int ix;
|
||||
|
||||
*p++ = '.';
|
||||
x -= floor (x + EPSILON / 2);
|
||||
for (j = i; j < 6; j++)
|
||||
x *= 10;
|
||||
ix = floor (x + 0.5);
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
ix *= 10;
|
||||
|
||||
/* A cheap hack, this routine can round wrong for fractions
|
||||
near one. */
|
||||
if (ix == 1000000)
|
||||
ix = 999999;
|
||||
|
||||
sprintf (p, "%06d", ix);
|
||||
i = 6 - i;
|
||||
while (i && p[i - 1] == '0')
|
||||
i--;
|
||||
if (i == 0)
|
||||
i--;
|
||||
p += i;
|
||||
}
|
||||
}
|
||||
else
|
||||
p += sprintf (p, "%g", x);
|
||||
|
||||
*p = '\0';
|
||||
return p - str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
/**
|
||||
* art_affine_to_string: Convert affine transformation to concise PostScript string representation.
|
||||
* @str: Where to store the resulting string.
|
||||
* @src: The affine transform.
|
||||
*
|
||||
* Converts an affine transform into a bit of PostScript code that
|
||||
* implements the transform. Special cases of scaling, rotation, and
|
||||
* translation are detected, and the corresponding PostScript
|
||||
* operators used (this greatly aids understanding the output
|
||||
* generated). The identity transform is mapped to the null string.
|
||||
**/
|
||||
void
|
||||
art_affine_to_string (char str[128], const double src[6])
|
||||
{
|
||||
char tmp[80];
|
||||
int i, ix;
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
double d = rand () * .1 / RAND_MAX;
|
||||
art_ftoa (tmp, d);
|
||||
printf ("%g %f %s\n", d, d, tmp);
|
||||
}
|
||||
#endif
|
||||
if (fabs (src[4]) < EPSILON && fabs (src[5]) < EPSILON)
|
||||
{
|
||||
/* could be scale or rotate */
|
||||
if (fabs (src[1]) < EPSILON && fabs (src[2]) < EPSILON)
|
||||
{
|
||||
/* scale */
|
||||
if (fabs (src[0] - 1) < EPSILON && fabs (src[3] - 1) < EPSILON)
|
||||
{
|
||||
/* identity transform */
|
||||
str[0] = '\0';
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ix = 0;
|
||||
ix += art_ftoa (str + ix, src[0]);
|
||||
str[ix++] = ' ';
|
||||
ix += art_ftoa (str + ix, src[3]);
|
||||
strcpy (str + ix, " scale");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* could be rotate */
|
||||
if (fabs (src[0] - src[3]) < EPSILON &&
|
||||
fabs (src[1] + src[2]) < EPSILON &&
|
||||
fabs (src[0] * src[0] + src[1] * src[1] - 1) < 2 * EPSILON)
|
||||
{
|
||||
double theta;
|
||||
|
||||
theta = (180 / M_PI) * atan2 (src[1], src[0]);
|
||||
art_ftoa (tmp, theta);
|
||||
sprintf (str, "%s rotate", tmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* could be translate */
|
||||
if (fabs (src[0] - 1) < EPSILON && fabs (src[1]) < EPSILON &&
|
||||
fabs (src[2]) < EPSILON && fabs (src[3] - 1) < EPSILON)
|
||||
{
|
||||
ix = 0;
|
||||
ix += art_ftoa (str + ix, src[4]);
|
||||
str[ix++] = ' ';
|
||||
ix += art_ftoa (str + ix, src[5]);
|
||||
strcpy (str + ix, " translate");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ix = 0;
|
||||
str[ix++] = '[';
|
||||
str[ix++] = ' ';
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
ix += art_ftoa (str + ix, src[i]);
|
||||
str[ix++] = ' ';
|
||||
}
|
||||
strcpy (str + ix, "] concat");
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_multiply: Multiply two affine transformation matrices.
|
||||
* @dst: Where to store the result.
|
||||
* @src1: The first affine transform to multiply.
|
||||
* @src2: The second affine transform to multiply.
|
||||
*
|
||||
* Multiplies two affine transforms together, i.e. the resulting @dst
|
||||
* is equivalent to doing first @src1 then @src2. Note that the
|
||||
* PostScript concat operator multiplies on the left, i.e. "M concat"
|
||||
* is equivalent to "CTM = multiply (M, CTM)";
|
||||
*
|
||||
* It is safe to call this function with @dst equal to @src1 or @src2.
|
||||
**/
|
||||
void
|
||||
art_affine_multiply (double dst[6], const double src1[6], const double src2[6])
|
||||
{
|
||||
double d0, d1, d2, d3, d4, d5;
|
||||
|
||||
d0 = src1[0] * src2[0] + src1[1] * src2[2];
|
||||
d1 = src1[0] * src2[1] + src1[1] * src2[3];
|
||||
d2 = src1[2] * src2[0] + src1[3] * src2[2];
|
||||
d3 = src1[2] * src2[1] + src1[3] * src2[3];
|
||||
d4 = src1[4] * src2[0] + src1[5] * src2[2] + src2[4];
|
||||
d5 = src1[4] * src2[1] + src1[5] * src2[3] + src2[5];
|
||||
dst[0] = d0;
|
||||
dst[1] = d1;
|
||||
dst[2] = d2;
|
||||
dst[3] = d3;
|
||||
dst[4] = d4;
|
||||
dst[5] = d5;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_identity: Set up the identity matrix.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
*
|
||||
* Sets up an identity matrix.
|
||||
**/
|
||||
void
|
||||
art_affine_identity (double dst[6])
|
||||
{
|
||||
dst[0] = 1;
|
||||
dst[1] = 0;
|
||||
dst[2] = 0;
|
||||
dst[3] = 1;
|
||||
dst[4] = 0;
|
||||
dst[5] = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* art_affine_scale: Set up a scaling matrix.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
* @sx: X scale factor.
|
||||
* @sy: Y scale factor.
|
||||
*
|
||||
* Sets up a scaling matrix.
|
||||
**/
|
||||
void
|
||||
art_affine_scale (double dst[6], double sx, double sy)
|
||||
{
|
||||
dst[0] = sx;
|
||||
dst[1] = 0;
|
||||
dst[2] = 0;
|
||||
dst[3] = sy;
|
||||
dst[4] = 0;
|
||||
dst[5] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_rotate: Set up a rotation affine transform.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
* @theta: Rotation angle in degrees.
|
||||
*
|
||||
* Sets up a rotation matrix. In the standard libart coordinate
|
||||
* system, in which increasing y moves downward, this is a
|
||||
* counterclockwise rotation. In the standard PostScript coordinate
|
||||
* system, which is reversed in the y direction, it is a clockwise
|
||||
* rotation.
|
||||
**/
|
||||
void
|
||||
art_affine_rotate (double dst[6], double theta)
|
||||
{
|
||||
double s, c;
|
||||
|
||||
s = sin (theta * M_PI / 180.0);
|
||||
c = cos (theta * M_PI / 180.0);
|
||||
dst[0] = c;
|
||||
dst[1] = s;
|
||||
dst[2] = -s;
|
||||
dst[3] = c;
|
||||
dst[4] = 0;
|
||||
dst[5] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_shear: Set up a shearing matrix.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
* @theta: Shear angle in degrees.
|
||||
*
|
||||
* Sets up a shearing matrix. In the standard libart coordinate system
|
||||
* and a small value for theta, || becomes \\. Horizontal lines remain
|
||||
* unchanged.
|
||||
**/
|
||||
void
|
||||
art_affine_shear (double dst[6], double theta)
|
||||
{
|
||||
double t;
|
||||
|
||||
t = tan (theta * M_PI / 180.0);
|
||||
dst[0] = 1;
|
||||
dst[1] = 0;
|
||||
dst[2] = t;
|
||||
dst[3] = 1;
|
||||
dst[4] = 0;
|
||||
dst[5] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_translate: Set up a translation matrix.
|
||||
* @dst: Where to store the resulting affine transform.
|
||||
* @tx: X translation amount.
|
||||
* @tx: Y translation amount.
|
||||
*
|
||||
* Sets up a translation matrix.
|
||||
**/
|
||||
void
|
||||
art_affine_translate (double dst[6], double tx, double ty)
|
||||
{
|
||||
dst[0] = 1;
|
||||
dst[1] = 0;
|
||||
dst[2] = 0;
|
||||
dst[3] = 1;
|
||||
dst[4] = tx;
|
||||
dst[5] = ty;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_affine_expansion: Find the affine's expansion factor.
|
||||
* @src: The affine transformation.
|
||||
*
|
||||
* Finds the expansion factor, i.e. the square root of the factor
|
||||
* by which the affine transform affects area. In an affine transform
|
||||
* composed of scaling, rotation, shearing, and translation, returns
|
||||
* the amount of scaling.
|
||||
*
|
||||
* Return value: the expansion factor.
|
||||
**/
|
||||
double
|
||||
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);
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/* 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_AFFINE_H__
|
||||
#define __ART_AFFINE_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_point.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_affine_point (ArtPoint *dst, const ArtPoint *src,
|
||||
const double affine[6]);
|
||||
|
||||
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]);
|
||||
|
||||
void
|
||||
art_affine_multiply (double dst[6],
|
||||
const double src1[6], const double src2[6]);
|
||||
|
||||
/* set up the identity matrix */
|
||||
void
|
||||
art_affine_identity (double dst[6]);
|
||||
|
||||
/* set up a scaling matrix */
|
||||
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);
|
||||
|
||||
|
||||
/* find the affine's "expansion factor", i.e. the scale amount */
|
||||
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
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_AFFINE_H__ */
|
@ -0,0 +1,85 @@
|
||||
/* 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);
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/* 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_ALPHAGAMMA_H__
|
||||
#define __ART_ALPHAGAMMA_H__
|
||||
|
||||
/* Alphagamma tables */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_misc.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtAlphaGamma ArtAlphaGamma;
|
||||
|
||||
struct _ArtAlphaGamma {
|
||||
/*< private >*/
|
||||
double gamma;
|
||||
int invtable_size;
|
||||
int table[256];
|
||||
art_u8 invtable[1];
|
||||
};
|
||||
|
||||
ArtAlphaGamma *
|
||||
art_alphagamma_new (double gamma);
|
||||
|
||||
void
|
||||
art_alphagamma_free (ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_H__ */
|
@ -0,0 +1,92 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Basic constructors and operations for bezier paths */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_bpath.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/**
|
||||
* art_bpath_affine_transform: Affine transform an #ArtBpath.
|
||||
* @src: The source #ArtBpath.
|
||||
* @matrix: The affine transform.
|
||||
*
|
||||
* Affine transform the bezpath, returning a newly allocated #ArtBpath
|
||||
* (allocated using art_alloc()).
|
||||
*
|
||||
* Result (x', y') = (matrix[0] * x + matrix[2] * y + matrix[4],
|
||||
* matrix[1] * x + matrix[3] * y + matrix[5])
|
||||
*
|
||||
* Return value: the transformed #ArtBpath.
|
||||
**/
|
||||
ArtBpath *
|
||||
art_bpath_affine_transform (const ArtBpath *src, const double matrix[6])
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
ArtBpath *new;
|
||||
ArtPathcode code;
|
||||
double x, y;
|
||||
|
||||
for (i = 0; src[i].code != ART_END; i++);
|
||||
size = i;
|
||||
|
||||
new = art_new (ArtBpath, size + 1);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
code = src[i].code;
|
||||
new[i].code = code;
|
||||
if (code == ART_CURVETO)
|
||||
{
|
||||
x = src[i].x1;
|
||||
y = src[i].y1;
|
||||
new[i].x1 = matrix[0] * x + matrix[2] * y + matrix[4];
|
||||
new[i].y1 = matrix[1] * x + matrix[3] * y + matrix[5];
|
||||
x = src[i].x2;
|
||||
y = src[i].y2;
|
||||
new[i].x2 = matrix[0] * x + matrix[2] * y + matrix[4];
|
||||
new[i].y2 = matrix[1] * x + matrix[3] * y + matrix[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
new[i].x1 = 0;
|
||||
new[i].y1 = 0;
|
||||
new[i].x2 = 0;
|
||||
new[i].y2 = 0;
|
||||
}
|
||||
x = src[i].x3;
|
||||
y = src[i].y3;
|
||||
new[i].x3 = matrix[0] * x + matrix[2] * y + matrix[4];
|
||||
new[i].y3 = matrix[1] * x + matrix[3] * y + matrix[5];
|
||||
}
|
||||
new[i].code = ART_END;
|
||||
new[i].x1 = 0;
|
||||
new[i].y1 = 0;
|
||||
new[i].x2 = 0;
|
||||
new[i].y2 = 0;
|
||||
new[i].x3 = 0;
|
||||
new[i].y3 = 0;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
/* 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_BPATH_H__
|
||||
#define __ART_BPATH_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_pathcode.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#include <libart_lgpl/art_pathcode.h>
|
||||
#endif
|
||||
|
||||
/* Basic data structures and constructors for bezier paths */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtBpath ArtBpath;
|
||||
|
||||
struct _ArtBpath {
|
||||
/*< public >*/
|
||||
ArtPathcode code;
|
||||
double x1;
|
||||
double y1;
|
||||
double x2;
|
||||
double y2;
|
||||
double x3;
|
||||
double y3;
|
||||
};
|
||||
|
||||
ArtBpath *
|
||||
art_bpath_affine_transform (const ArtBpath *src, const double matrix[6]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_BPATH_H__ */
|
@ -0,0 +1,10 @@
|
||||
/* Automatically generated by gen_art_config */
|
||||
|
||||
#define ART_SIZEOF_CHAR 1
|
||||
#define ART_SIZEOF_SHORT 2
|
||||
#define ART_SIZEOF_INT 4
|
||||
#define ART_SIZEOF_LONG 4
|
||||
|
||||
typedef unsigned char art_u8;
|
||||
typedef unsigned short art_u16;
|
||||
typedef unsigned int art_u32;
|
@ -0,0 +1,68 @@
|
||||
/* 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_FILTERLEVEL_H__
|
||||
#define __ART_FILTERLEVEL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum {
|
||||
ART_FILTER_NEAREST,
|
||||
ART_FILTER_TILES,
|
||||
ART_FILTER_BILINEAR,
|
||||
ART_FILTER_HYPER
|
||||
} ArtFilterLevel;
|
||||
|
||||
/* NEAREST is nearest neighbor. It is the fastest and lowest quality.
|
||||
|
||||
TILES is an accurate simulation of the PostScript image operator
|
||||
without any interpolation enabled; each pixel is rendered as a tiny
|
||||
parallelogram of solid color, the edges of which are implemented
|
||||
with antialiasing. It resembles nearest neighbor for enlargement,
|
||||
and bilinear for reduction.
|
||||
|
||||
BILINEAR is bilinear interpolation. For enlargement, it is
|
||||
equivalent to point-sampling the ideal bilinear-interpolated
|
||||
image. For reduction, it is equivalent to laying down small tiles
|
||||
and integrating over the coverage area.
|
||||
|
||||
HYPER is the highest quality reconstruction function. It is derived
|
||||
from the hyperbolic filters in Wolberg's "Digital Image Warping,"
|
||||
and is formally defined as the hyperbolic-filter sampling the ideal
|
||||
hyperbolic-filter interpolated image (the filter is designed to be
|
||||
idempotent for 1:1 pixel mapping). It is the slowest and highest
|
||||
quality.
|
||||
|
||||
Note: at this stage of implementation, most filter modes are likely
|
||||
not to be implemented.
|
||||
|
||||
Note: cubic filtering is missing from this list, because there isn't
|
||||
much point - hyper is just as fast to implement and slightly better
|
||||
in quality.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_PATHCODE_H__ */
|
@ -0,0 +1,123 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Render a sorted vector path into a graymap. */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_gray_svp.h"
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_svp.h"
|
||||
#include "art_svp_render_aa.h"
|
||||
|
||||
typedef struct _ArtGraySVPData ArtGraySVPData;
|
||||
|
||||
struct _ArtGraySVPData {
|
||||
art_u8 *buf;
|
||||
int rowstride;
|
||||
int x0, x1;
|
||||
};
|
||||
|
||||
static void
|
||||
art_gray_svp_callback (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtGraySVPData *data = (ArtGraySVPData *)callback_data;
|
||||
art_u8 *linebuf;
|
||||
int run_x0, run_x1;
|
||||
int running_sum = start;
|
||||
int x0, x1;
|
||||
int k;
|
||||
|
||||
#if 0
|
||||
printf ("start = %d", start);
|
||||
running_sum = start;
|
||||
for (k = 0; k < n_steps; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
printf (" %d:%d", steps[k].x, running_sum >> 16);
|
||||
}
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
linebuf = data->buf;
|
||||
x0 = data->x0;
|
||||
x1 = data->x1;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0)
|
||||
memset (linebuf, running_sum >> 16, run_x1 - x0);
|
||||
|
||||
for (k = 0; k < n_steps - 1; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[k + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
memset (linebuf + run_x0 - x0, running_sum >> 16, run_x1 - run_x0);
|
||||
}
|
||||
running_sum += steps[k].delta;
|
||||
if (x1 > run_x1)
|
||||
memset (linebuf + run_x1 - x0, running_sum >> 16, x1 - run_x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (linebuf, running_sum >> 16, x1 - x0);
|
||||
}
|
||||
|
||||
data->buf += data->rowstride;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_gray_svp_aa: Render the vector path into the bytemap.
|
||||
* @svp: The SVP to render.
|
||||
* @x0: The view window's left coord.
|
||||
* @y0: The view window's top coord.
|
||||
* @x1: The view window's right coord.
|
||||
* @y1: The view window's bottom coord.
|
||||
* @buf: The buffer where the bytemap is stored.
|
||||
* @rowstride: the rowstride for @buf.
|
||||
*
|
||||
* Each pixel gets a value proportional to the area within the pixel
|
||||
* overlapping the (filled) SVP. Pixel (x, y) is stored at:
|
||||
*
|
||||
* @buf[(y - * @y0) * @rowstride + (x - @x0)]
|
||||
*
|
||||
* All pixels @x0 <= x < @x1, @y0 <= y < @y1 are generated. A
|
||||
* stored value of zero is no coverage, and a value of 255 is full
|
||||
* coverage. The area within the pixel (x, y) is the region covered
|
||||
* by [x..x+1] and [y..y+1].
|
||||
**/
|
||||
void
|
||||
art_gray_svp_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u8 *buf, int rowstride)
|
||||
{
|
||||
ArtGraySVPData data;
|
||||
|
||||
data.buf = buf;
|
||||
data.rowstride = rowstride;
|
||||
data.x0 = x0;
|
||||
data.x1 = x1;
|
||||
art_svp_render_aa (svp, x0, y0, x1, y1, art_gray_svp_callback, &data);
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Render a sorted vector path into a graymap. */
|
||||
|
||||
#ifndef __ART_GRAY_SVP_H__
|
||||
#define __ART_GRAY_SVP_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_misc.h"
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_gray_svp_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u8 *buf, int rowstride);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_GRAY_SVP_H__ */
|
@ -0,0 +1,93 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Various utility functions RLL finds useful. */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_misc.h"
|
||||
|
||||
#ifdef HAVE_UINSTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/**
|
||||
* art_die: Print the error message to stderr and exit with a return code of 1.
|
||||
* @fmt: The printf-style format for the error message.
|
||||
*
|
||||
* Used for dealing with severe errors.
|
||||
**/
|
||||
void
|
||||
art_die (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_warn: Print the warning message to stderr.
|
||||
* @fmt: The printf-style format for the warning message.
|
||||
*
|
||||
* Used for generating warnings.
|
||||
**/
|
||||
void
|
||||
art_warn (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_dprint: Print the debug message to stderr.
|
||||
* @fmt: The printf-style format for the debug message.
|
||||
*
|
||||
* Used for generating debug output.
|
||||
**/
|
||||
void
|
||||
art_dprint (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
vfprintf (stderr, fmt, ap);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
void *art_alloc(size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void art_free(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void *art_realloc(void *ptr, size_t size)
|
||||
{
|
||||
return realloc(ptr, size);
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Simple macros to set up storage allocation and basic types for libart
|
||||
functions. */
|
||||
|
||||
#ifndef __ART_MISC_H__
|
||||
#define __ART_MISC_H__
|
||||
|
||||
#include <stdlib.h> /* for malloc, etc. */
|
||||
|
||||
/* The art_config.h file is automatically generated by
|
||||
gen_art_config.c and contains definitions of
|
||||
ART_SIZEOF_{CHAR,SHORT,INT,LONG} and art_u{8,16,32}. */
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_config.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_config.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void *art_alloc(size_t size);
|
||||
void art_free(void *ptr);
|
||||
void *art_realloc(void *ptr, size_t size);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* These aren't, strictly speaking, configuration macros, but they're
|
||||
damn handy to have around, and may be worth playing with for
|
||||
debugging. */
|
||||
#define art_new(type, n) ((type *)art_alloc ((n) * sizeof(type)))
|
||||
|
||||
#define art_renew(p, type, n) ((type *)art_realloc (p, (n) * sizeof(type)))
|
||||
|
||||
/* This one must be used carefully - in particular, p and max should
|
||||
be variables. They can also be pstruct->el lvalues. */
|
||||
#define art_expand(p, type, max) do { if(max) { p = art_renew (p, type, max <<= 1); } else { max = 1; p = art_new(type, 1); } } while (0)
|
||||
|
||||
typedef int art_boolean;
|
||||
#define ART_FALSE 0
|
||||
#define ART_TRUE 1
|
||||
|
||||
/* define pi */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif /* M_PI */
|
||||
|
||||
#ifndef M_SQRT2
|
||||
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||
#endif /* M_SQRT2 */
|
||||
|
||||
/* Provide macros to feature the GCC function attribute.
|
||||
*/
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
|
||||
#define ART_GNUC_PRINTF( format_idx, arg_idx ) \
|
||||
__attribute__((__format__ (__printf__, format_idx, arg_idx)))
|
||||
#define ART_GNUC_NORETURN \
|
||||
__attribute__((__noreturn__))
|
||||
#else /* !__GNUC__ */
|
||||
#define ART_GNUC_PRINTF( format_idx, arg_idx )
|
||||
#define ART_GNUC_NORETURN
|
||||
#endif /* !__GNUC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ART_GNUC_NORETURN
|
||||
art_die (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
|
||||
|
||||
void
|
||||
art_warn (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
|
||||
|
||||
void
|
||||
art_dprint (const char *fmt, ...) ART_GNUC_PRINTF (1, 2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ART_USE_NEW_INTERSECTOR
|
||||
|
||||
#endif /* __ART_MISC_H__ */
|
@ -0,0 +1,39 @@
|
||||
/* 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_PATHCODE_H__
|
||||
#define __ART_PATHCODE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum {
|
||||
ART_MOVETO,
|
||||
ART_MOVETO_OPEN,
|
||||
ART_CURVETO,
|
||||
ART_LINETO,
|
||||
ART_END
|
||||
} ArtPathcode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_PATHCODE_H__ */
|
@ -0,0 +1,285 @@
|
||||
/* 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_pixbuf.h"
|
||||
|
||||
#include "art_misc.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* art_pixbuf_new_rgb_dnotify: Create a new RGB #ArtPixBuf with explicit destroy notification.
|
||||
* @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.
|
||||
* @dfunc_data: The private data passed to @dfunc.
|
||||
* @dfunc: The destroy notification function.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @dfunc is called with @dfunc_data and @pixels as arguments when the
|
||||
* #ArtPixBuf is destroyed. Using a destroy notification function
|
||||
* allows a wide range of memory management disciplines for the pixel
|
||||
* memory. A NULL value for @dfunc is also allowed and means that no
|
||||
* special action will be taken on destruction.
|
||||
*
|
||||
* Return value: The newly created #ArtPixBuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgb_dnotify (art_u8 *pixels, int width, int height, int rowstride,
|
||||
void *dfunc_data, ArtDestroyNotify dfunc)
|
||||
{
|
||||
ArtPixBuf *pixbuf;
|
||||
|
||||
pixbuf = art_new (ArtPixBuf, 1);
|
||||
|
||||
pixbuf->format = ART_PIX_RGB;
|
||||
pixbuf->n_channels = 3;
|
||||
pixbuf->has_alpha = 0;
|
||||
pixbuf->bits_per_sample = 8;
|
||||
|
||||
pixbuf->pixels = (art_u8 *) pixels;
|
||||
pixbuf->width = width;
|
||||
pixbuf->height = height;
|
||||
pixbuf->rowstride = rowstride;
|
||||
pixbuf->destroy_data = dfunc_data;
|
||||
pixbuf->destroy = dfunc;
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_pixbuf_new_rgba_dnotify: Create a new RGBA #ArtPixBuf with explicit destroy notification.
|
||||
* @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.
|
||||
* @dfunc_data: The private data passed to @dfunc.
|
||||
* @dfunc: The destroy notification function.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @dfunc is called with @dfunc_data and @pixels as arguments when the
|
||||
* #ArtPixBuf is destroyed. Using a destroy notification function
|
||||
* allows a wide range of memory management disciplines for the pixel
|
||||
* memory. A NULL value for @dfunc is also allowed and means that no
|
||||
* special action will be taken on destruction.
|
||||
*
|
||||
* Return value: The newly created #ArtPixBuf.
|
||||
**/
|
||||
ArtPixBuf *
|
||||
art_pixbuf_new_rgba_dnotify (art_u8 *pixels, int width, int height, int rowstride,
|
||||
void *dfunc_data, ArtDestroyNotify dfunc)
|
||||
{
|
||||
ArtPixBuf *pixbuf;
|
||||
|
||||
pixbuf = art_new (ArtPixBuf, 1);
|
||||
|
||||
pixbuf->format = ART_PIX_RGB;
|
||||
pixbuf->n_channels = 4;
|
||||
pixbuf->has_alpha = 1;
|
||||
pixbuf->bits_per_sample = 8;
|
||||
|
||||
pixbuf->pixels = (art_u8 *) pixels;
|
||||
pixbuf->width = width;
|
||||
pixbuf->height = height;
|
||||
pixbuf->rowstride = rowstride;
|
||||
pixbuf->destroy_data = dfunc_data;
|
||||
pixbuf->destroy = dfunc;
|
||||
|
||||
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;
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/* 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_PIXBUF_H__
|
||||
#define __ART_PIXBUF_H__
|
||||
|
||||
/* A generic data structure for holding a buffer of pixels. One way
|
||||
to think about this module is as a virtualization over specific
|
||||
pixel buffer formats. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_misc.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef void (*ArtDestroyNotify) (void *func_data, void *data);
|
||||
|
||||
typedef struct _ArtPixBuf ArtPixBuf;
|
||||
|
||||
typedef enum {
|
||||
ART_PIX_RGB
|
||||
/* gray, cmyk, lab, ... ? */
|
||||
} ArtPixFormat;
|
||||
|
||||
|
||||
/* The pixel buffer consists of width * height pixels, each of which
|
||||
has n_channels samples. It is stored in simple packed format. */
|
||||
|
||||
struct _ArtPixBuf {
|
||||
/*< public >*/
|
||||
ArtPixFormat format;
|
||||
int n_channels;
|
||||
int has_alpha;
|
||||
int bits_per_sample;
|
||||
|
||||
art_u8 *pixels;
|
||||
int width;
|
||||
int height;
|
||||
int rowstride;
|
||||
void *destroy_data;
|
||||
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,
|
||||
void *dfunc_data, ArtDestroyNotify dfunc);
|
||||
|
||||
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
|
||||
|
||||
#endif
|
@ -0,0 +1,38 @@
|
||||
/* 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_POINT_H__
|
||||
#define __ART_POINT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtPoint ArtPoint;
|
||||
|
||||
struct _ArtPoint {
|
||||
/*< public >*/
|
||||
double x, y;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_POINT_H__ */
|
@ -0,0 +1,215 @@
|
||||
/* 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_rect.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif /* MAX */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif /* MIN */
|
||||
|
||||
/* rectangle primitives stolen from gzilla */
|
||||
|
||||
/**
|
||||
* art_irect_copy: Make a copy of an integer rectangle.
|
||||
* @dest: Where the copy is stored.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Copies the rectangle.
|
||||
**/
|
||||
void
|
||||
art_irect_copy (ArtIRect *dest, const ArtIRect *src) {
|
||||
dest->x0 = src->x0;
|
||||
dest->y0 = src->y0;
|
||||
dest->x1 = src->x1;
|
||||
dest->y1 = src->y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_irect_union: Find union of two integer rectangles.
|
||||
* @dest: Where the result is stored.
|
||||
* @src1: A source rectangle.
|
||||
* @src2: Another source rectangle.
|
||||
*
|
||||
* Finds the smallest rectangle that includes @src1 and @src2.
|
||||
**/
|
||||
void
|
||||
art_irect_union (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *src2) {
|
||||
if (art_irect_empty (src1)) {
|
||||
art_irect_copy (dest, src2);
|
||||
} else if (art_irect_empty (src2)) {
|
||||
art_irect_copy (dest, src1);
|
||||
} else {
|
||||
dest->x0 = MIN (src1->x0, src2->x0);
|
||||
dest->y0 = MIN (src1->y0, src2->y0);
|
||||
dest->x1 = MAX (src1->x1, src2->x1);
|
||||
dest->y1 = MAX (src1->y1, src2->y1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_irect_intersection: Find intersection of two integer rectangles.
|
||||
* @dest: Where the result is stored.
|
||||
* @src1: A source rectangle.
|
||||
* @src2: Another source rectangle.
|
||||
*
|
||||
* Finds the intersection of @src1 and @src2.
|
||||
**/
|
||||
void
|
||||
art_irect_intersect (ArtIRect *dest, const ArtIRect *src1, const ArtIRect *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 integer rectangle is empty.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
|
||||
**/
|
||||
int
|
||||
art_irect_empty (const ArtIRect *src) {
|
||||
return (src->x1 <= src->x0 || src->y1 <= src->y0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
gboolean irect_point_inside (ArtIRect *rect, GzwPoint *point) {
|
||||
return (point->x >= rect->x0 && point->y >= rect->y0 &&
|
||||
point->x < rect->x1 && point->y < rect->y1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_drect_copy: Make a copy of a rectangle.
|
||||
* @dest: Where the copy is stored.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Copies the rectangle.
|
||||
**/
|
||||
void
|
||||
art_drect_copy (ArtDRect *dest, const ArtDRect *src) {
|
||||
dest->x0 = src->x0;
|
||||
dest->y0 = src->y0;
|
||||
dest->x1 = src->x1;
|
||||
dest->y1 = src->y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_union: Find union of two 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_drect_union (ArtDRect *dest, const ArtDRect *src1, const ArtDRect *src2) {
|
||||
if (art_drect_empty (src1)) {
|
||||
art_drect_copy (dest, src2);
|
||||
} else if (art_drect_empty (src2)) {
|
||||
art_drect_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_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.
|
||||
*
|
||||
* Return value: TRUE if @src is an empty rectangle, FALSE otherwise.
|
||||
**/
|
||||
int
|
||||
art_drect_empty (const ArtDRect *src) {
|
||||
return (src->x1 <= src->x0 || src->y1 <= src->y0);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_affine_transform: Affine transform rectangle.
|
||||
* @dst: Where to store the result.
|
||||
* @src: The source rectangle.
|
||||
* @matrix: The affine transformation.
|
||||
*
|
||||
* Find the smallest rectangle enclosing the affine transformed @src.
|
||||
* The result is exactly the affine transformation of @src when
|
||||
* @matrix specifies a rectilinear affine transformation, otherwise it
|
||||
* is a conservative approximation.
|
||||
**/
|
||||
void
|
||||
art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src, const double matrix[6])
|
||||
{
|
||||
double x00, y00, x10, y10;
|
||||
double x01, y01, x11, y11;
|
||||
|
||||
x00 = src->x0 * matrix[0] + src->y0 * matrix[2] + matrix[4];
|
||||
y00 = src->x0 * matrix[1] + src->y0 * matrix[3] + matrix[5];
|
||||
x10 = src->x1 * matrix[0] + src->y0 * matrix[2] + matrix[4];
|
||||
y10 = src->x1 * matrix[1] + src->y0 * matrix[3] + matrix[5];
|
||||
x01 = src->x0 * matrix[0] + src->y1 * matrix[2] + matrix[4];
|
||||
y01 = src->x0 * matrix[1] + src->y1 * matrix[3] + matrix[5];
|
||||
x11 = src->x1 * matrix[0] + src->y1 * matrix[2] + matrix[4];
|
||||
y11 = src->x1 * matrix[1] + src->y1 * matrix[3] + matrix[5];
|
||||
dst->x0 = MIN (MIN (x00, x10), MIN (x01, x11));
|
||||
dst->y0 = MIN (MIN (y00, y10), MIN (y01, y11));
|
||||
dst->x1 = MAX (MAX (x00, x10), MAX (x01, x11));
|
||||
dst->y1 = MAX (MAX (y00, y10), MAX (y01, y11));
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_to_irect: Convert rectangle to integer rectangle.
|
||||
* @dst: Where to store resulting integer rectangle.
|
||||
* @src: The source rectangle.
|
||||
*
|
||||
* Find the smallest integer rectangle that encloses @src.
|
||||
**/
|
||||
void
|
||||
art_drect_to_irect (ArtIRect *dst, ArtDRect *src)
|
||||
{
|
||||
dst->x0 = floor (src->x0);
|
||||
dst->y0 = floor (src->y0);
|
||||
dst->x1 = ceil (src->x1);
|
||||
dst->y1 = ceil (src->y1);
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/* 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_RECT_H__
|
||||
#define __ART_RECT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _ArtDRect ArtDRect;
|
||||
typedef struct _ArtIRect ArtIRect;
|
||||
|
||||
struct _ArtDRect {
|
||||
/*< public >*/
|
||||
double x0, y0, x1, y1;
|
||||
};
|
||||
|
||||
struct _ArtIRect {
|
||||
/*< public >*/
|
||||
int x0, y0, x1, y1;
|
||||
};
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Return true if the rectangle is empty. */
|
||||
int art_irect_empty (const ArtIRect *src);
|
||||
|
||||
/* Make a copy of the rectangle. */
|
||||
void art_drect_copy (ArtDRect *dest, const ArtDRect *src);
|
||||
|
||||
/* Find the smallest rectangle that includes both source rectangles. */
|
||||
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);
|
||||
|
||||
void
|
||||
art_drect_affine_transform (ArtDRect *dst, const ArtDRect *src,
|
||||
const double matrix[6]);
|
||||
|
||||
void art_drect_to_irect (ArtIRect *dst, ArtDRect *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,82 @@
|
||||
/* 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_rect_svp.h"
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_svp.h"
|
||||
#include "art_rect.h"
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif /* MAX */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif /* MIN */
|
||||
|
||||
/**
|
||||
* art_drect_svp: Find the bounding box of a sorted vector path.
|
||||
* @bbox: Where to store the bounding box.
|
||||
* @svp: The SVP.
|
||||
*
|
||||
* Finds the bounding box of the SVP.
|
||||
**/
|
||||
void
|
||||
art_drect_svp (ArtDRect *bbox, const ArtSVP *svp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (svp->n_segs == 0)
|
||||
{
|
||||
bbox->x0 = 0;
|
||||
bbox->y0 = 0;
|
||||
bbox->x1 = 0;
|
||||
bbox->y1 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
art_drect_copy (bbox, &svp->segs[0].bbox);
|
||||
|
||||
for (i = 1; i < svp->n_segs; i++)
|
||||
{
|
||||
bbox->x0 = MIN (bbox->x0, svp->segs[i].bbox.x0);
|
||||
bbox->y0 = MIN (bbox->y0, svp->segs[i].bbox.y0);
|
||||
bbox->x1 = MAX (bbox->x1, svp->segs[i].bbox.x1);
|
||||
bbox->y1 = MAX (bbox->y1, svp->segs[i].bbox.y1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_drect_svp_union: Compute the bounding box of the svp and union it in to the existing bounding box.
|
||||
* @bbox: Initial boundin box and where to store the bounding box.
|
||||
* @svp: The SVP.
|
||||
*
|
||||
* Finds the bounding box of the SVP, computing its union with an
|
||||
* existing bbox.
|
||||
**/
|
||||
void
|
||||
art_drect_svp_union (ArtDRect *bbox, const ArtSVP *svp)
|
||||
{
|
||||
ArtDRect svp_bbox;
|
||||
|
||||
art_drect_svp (&svp_bbox, svp);
|
||||
art_drect_union (bbox, bbox, &svp_bbox);
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/* 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_RECT_SVP_H__
|
||||
#define __ART_RECT_SVP_H__
|
||||
|
||||
/* Find the bounding box of a sorted vector path. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_drect_svp (ArtDRect *bbox, const ArtSVP *svp);
|
||||
|
||||
/* Compute the bounding box of the svp and union it in to the
|
||||
existing bounding box. */
|
||||
void
|
||||
art_drect_svp_union (ArtDRect *bbox, const ArtSVP *svp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RECT_SVP_H__ */
|
@ -0,0 +1,134 @@
|
||||
/* 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_rect_uta.h"
|
||||
|
||||
/* Functions to decompose a microtile array into a list of rectangles. */
|
||||
|
||||
/**
|
||||
* art_rect_list_from_uta: Decompose uta into list of rectangles.
|
||||
* @uta: The source uta.
|
||||
* @max_width: The maximum width of the resulting rectangles.
|
||||
* @max_height: The maximum height of the resulting rectangles.
|
||||
* @p_nrects: Where to store the number of returned rectangles.
|
||||
*
|
||||
* Allocates a new list of rectangles, sets *@p_nrects to the number
|
||||
* in the list. This list should be freed with art_free().
|
||||
*
|
||||
* Each rectangle bounded in size by (@max_width, @max_height).
|
||||
* However, these bounds must be at least the size of one tile.
|
||||
*
|
||||
* This routine provides a precise implementation, i.e. the rectangles
|
||||
* cover exactly the same area as the uta. It is thus appropriate in
|
||||
* cases where the overhead per rectangle is small compared with the
|
||||
* cost of filling in extra pixels.
|
||||
*
|
||||
* Return value: An array containing the resulting rectangles.
|
||||
**/
|
||||
ArtIRect *
|
||||
art_rect_list_from_uta (ArtUta *uta, int max_width, int max_height,
|
||||
int *p_nrects)
|
||||
{
|
||||
ArtIRect *rects;
|
||||
int n_rects, n_rects_max;
|
||||
int x, y;
|
||||
int width, height;
|
||||
int ix;
|
||||
int left_ix;
|
||||
ArtUtaBbox *utiles;
|
||||
ArtUtaBbox bb;
|
||||
int x0, y0, x1, y1;
|
||||
int *glom;
|
||||
int glom_rect;
|
||||
|
||||
n_rects = 0;
|
||||
n_rects_max = 1;
|
||||
rects = art_new (ArtIRect, n_rects_max);
|
||||
|
||||
width = uta->width;
|
||||
height = uta->height;
|
||||
utiles = uta->utiles;
|
||||
|
||||
glom = art_new (int, width * height);
|
||||
for (ix = 0; ix < width * height; ix++)
|
||||
glom[ix] = -1;
|
||||
|
||||
ix = 0;
|
||||
for (y = 0; y < height; y++)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
bb = utiles[ix];
|
||||
if (bb)
|
||||
{
|
||||
x0 = ((uta->x0 + x) << ART_UTILE_SHIFT) + ART_UTA_BBOX_X0(bb);
|
||||
y0 = ((uta->y0 + y) << ART_UTILE_SHIFT) + ART_UTA_BBOX_Y0(bb);
|
||||
y1 = ((uta->y0 + y) << ART_UTILE_SHIFT) + ART_UTA_BBOX_Y1(bb);
|
||||
|
||||
left_ix = ix;
|
||||
/* now try to extend to the right */
|
||||
while (x != width - 1 &&
|
||||
ART_UTA_BBOX_X1(bb) == ART_UTILE_SIZE &&
|
||||
(((bb & 0xffffff) ^ utiles[ix + 1]) & 0xffff00ff) == 0 &&
|
||||
(((uta->x0 + x + 1) << ART_UTILE_SHIFT) +
|
||||
ART_UTA_BBOX_X1(utiles[ix + 1]) -
|
||||
x0) <= max_width)
|
||||
{
|
||||
bb = utiles[ix + 1];
|
||||
ix++;
|
||||
x++;
|
||||
}
|
||||
x1 = ((uta->x0 + x) << ART_UTILE_SHIFT) + ART_UTA_BBOX_X1(bb);
|
||||
|
||||
|
||||
/* if rectangle nonempty */
|
||||
if ((x1 ^ x0) | (y1 ^ y0))
|
||||
{
|
||||
/* try to glom onto an existing rectangle */
|
||||
glom_rect = glom[left_ix];
|
||||
if (glom_rect != -1 &&
|
||||
x0 == rects[glom_rect].x0 &&
|
||||
x1 == rects[glom_rect].x1 &&
|
||||
y0 == rects[glom_rect].y1 &&
|
||||
y1 - rects[glom_rect].y0 <= max_height)
|
||||
{
|
||||
rects[glom_rect].y1 = y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n_rects == n_rects_max)
|
||||
art_expand (rects, ArtIRect, n_rects_max);
|
||||
rects[n_rects].x0 = x0;
|
||||
rects[n_rects].y0 = y0;
|
||||
rects[n_rects].x1 = x1;
|
||||
rects[n_rects].y1 = y1;
|
||||
glom_rect = n_rects;
|
||||
n_rects++;
|
||||
}
|
||||
if (y != height - 1)
|
||||
glom[left_ix + width] = glom_rect;
|
||||
}
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
|
||||
art_free (glom);
|
||||
*p_nrects = n_rects;
|
||||
return rects;
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/* 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_RECT_UTA_H__
|
||||
#define __ART_RECT_UTA_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_rect.h"
|
||||
#include "art_uta.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_uta.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtIRect *
|
||||
art_rect_list_from_uta (ArtUta *uta, int max_width, int max_height,
|
||||
int *p_nrects);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RECT_UTA_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* art_render.h: Modular rendering architecture.
|
||||
*
|
||||
* 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_RENDER_H__
|
||||
#define __ART_RENDER_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Render object */
|
||||
|
||||
#ifndef ART_MAX_DEPTH
|
||||
#define ART_MAX_DEPTH 16
|
||||
#endif
|
||||
|
||||
#if ART_MAX_DEPTH == 16
|
||||
typedef art_u16 ArtPixMaxDepth;
|
||||
#define ART_PIX_MAX_FROM_8(x) ((x) | ((x) << 8))
|
||||
#define ART_PIX_8_FROM_MAX(x) (((x) + 0x80 - (((x) + 0x80) >> 8)) >> 8)
|
||||
#else
|
||||
#if ART_MAX_DEPTH == 8
|
||||
typedef art_u8 ArtPixMaxDepth;
|
||||
#define ART_PIX_MAX_FROM_8(x) (x)
|
||||
#define ART_PIX_8_FROM_MAX(x) (x)
|
||||
#else
|
||||
#error ART_MAX_DEPTH must be either 8 or 16
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ART_MAX_CHAN 16
|
||||
|
||||
typedef struct _ArtRender ArtRender;
|
||||
typedef struct _ArtRenderCallback ArtRenderCallback;
|
||||
typedef struct _ArtRenderMaskRun ArtRenderMaskRun;
|
||||
typedef struct _ArtImageSource ArtImageSource;
|
||||
typedef struct _ArtMaskSource ArtMaskSource;
|
||||
|
||||
typedef enum {
|
||||
ART_ALPHA_NONE = 0,
|
||||
ART_ALPHA_SEPARATE = 1,
|
||||
ART_ALPHA_PREMUL = 2
|
||||
} ArtAlphaType;
|
||||
|
||||
typedef enum {
|
||||
ART_COMPOSITE_NORMAL,
|
||||
ART_COMPOSITE_MULTIPLY,
|
||||
/* todo: more */
|
||||
ART_COMPOSITE_CUSTOM
|
||||
} ArtCompositingMode;
|
||||
|
||||
typedef enum {
|
||||
ART_IMAGE_SOURCE_CAN_CLEAR = 1,
|
||||
ART_IMAGE_SOURCE_CAN_COMPOSITE = 2
|
||||
} ArtImageSourceFlags;
|
||||
|
||||
struct _ArtRenderMaskRun {
|
||||
int x;
|
||||
int alpha;
|
||||
};
|
||||
|
||||
struct _ArtRenderCallback {
|
||||
void (*render) (ArtRenderCallback *self, ArtRender *render,
|
||||
art_u8 *dest, int y);
|
||||
void (*done) (ArtRenderCallback *self, ArtRender *render);
|
||||
};
|
||||
|
||||
struct _ArtImageSource {
|
||||
ArtRenderCallback super;
|
||||
void (*negotiate) (ArtImageSource *self, ArtRender *render,
|
||||
ArtImageSourceFlags *p_flags,
|
||||
int *p_buf_depth, ArtAlphaType *p_alpha_type);
|
||||
};
|
||||
|
||||
struct _ArtMaskSource {
|
||||
ArtRenderCallback super;
|
||||
int (*can_drive) (ArtMaskSource *self, ArtRender *render);
|
||||
/* For each mask source, ::prepare() is invoked if it is not
|
||||
a driver, or ::invoke_driver() if it is. */
|
||||
void (*invoke_driver) (ArtMaskSource *self, ArtRender *render);
|
||||
void (*prepare) (ArtMaskSource *self, ArtRender *render, art_boolean first);
|
||||
};
|
||||
|
||||
struct _ArtRender {
|
||||
/* parameters of destination image */
|
||||
int x0, y0;
|
||||
int x1, y1;
|
||||
art_u8 *pixels;
|
||||
int rowstride;
|
||||
int n_chan;
|
||||
int depth;
|
||||
ArtAlphaType alpha_type;
|
||||
|
||||
art_boolean clear;
|
||||
ArtPixMaxDepth clear_color[ART_MAX_CHAN + 1];
|
||||
art_u32 opacity; /* [0..0x10000] */
|
||||
|
||||
ArtCompositingMode compositing_mode;
|
||||
|
||||
ArtAlphaGamma *alphagamma;
|
||||
|
||||
art_u8 *alpha_buf;
|
||||
|
||||
/* parameters of intermediate buffer */
|
||||
int buf_depth;
|
||||
ArtAlphaType buf_alpha;
|
||||
art_u8 *image_buf;
|
||||
|
||||
/* driving alpha scanline data */
|
||||
/* A "run" is a contiguous sequence of x values with the same alpha value. */
|
||||
int n_run;
|
||||
ArtRenderMaskRun *run;
|
||||
|
||||
/* A "span" is a contiguous sequence of x values with non-zero alpha. */
|
||||
int n_span;
|
||||
int *span_x;
|
||||
|
||||
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);
|
||||
|
||||
void
|
||||
art_render_invoke_callbacks (ArtRender *render, art_u8 *dest, int y);
|
||||
|
||||
/* The following function is for custom image sources only. */
|
||||
void
|
||||
art_render_add_image_source (ArtRender *render, ArtImageSource *image_source);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RENDER_H__ */
|
||||
|
@ -0,0 +1,716 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_render.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_render.h>
|
||||
#endif
|
||||
|
||||
#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__ */
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* art_render_mask.c: Alpha mask source for modular rendering.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authors: Raph Levien <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);
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_render.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_render.h>
|
||||
#endif
|
||||
|
||||
#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__ */
|
@ -0,0 +1,421 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_render.h"
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_render.h>
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_render_svp (ArtRender *render, const ArtSVP *svp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RENDER_SVP_H__ */
|
@ -0,0 +1,175 @@
|
||||
/* 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.h"
|
||||
|
||||
#include <string.h> /* for memset */
|
||||
|
||||
/* Basic operators for manipulating 24-bit packed RGB buffers. */
|
||||
|
||||
#define COLOR_RUN_COMPLEX
|
||||
|
||||
#ifdef COLOR_RUN_SIMPLE
|
||||
/* This is really slow. Is there any way we might speed it up?
|
||||
Two ideas:
|
||||
|
||||
First, maybe we should be working at 32-bit alignment. Then,
|
||||
this can be a simple loop over word stores.
|
||||
|
||||
Second, we can keep working at 24-bit alignment, but have some
|
||||
intelligence about storing. For example, we can iterate over
|
||||
4-pixel chunks (aligned at 4 pixels), with an inner loop
|
||||
something like:
|
||||
|
||||
*buf++ = v1;
|
||||
*buf++ = v2;
|
||||
*buf++ = v3;
|
||||
|
||||
One source of extra complexity is the need to make sure linebuf is
|
||||
aligned to a 32-bit boundary.
|
||||
|
||||
This second alternative has some complexity to it, but is
|
||||
appealing because it really minimizes the memory bandwidth. */
|
||||
void
|
||||
art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, gint n)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (r == g && g == b)
|
||||
{
|
||||
memset (buf, g, n + n + n);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
*buf++ = r;
|
||||
*buf++ = g;
|
||||
*buf++ = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef COLOR_RUN_COMPLEX
|
||||
/* This implements the second of the two ideas above. The test results
|
||||
are _very_ encouraging - it seems the speed is within 10% of
|
||||
memset, which is quite good! */
|
||||
/**
|
||||
* art_rgb_fill_run: fill a 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. Thus,
|
||||
* locations @buf (inclusive) through @buf + 3 * @n (exclusive) are
|
||||
* written.
|
||||
*
|
||||
* The implementation of this routine is very highly optimized.
|
||||
**/
|
||||
void
|
||||
art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
|
||||
{
|
||||
int i;
|
||||
unsigned int v1, v2, v3;
|
||||
|
||||
if (r == g && g == b)
|
||||
{
|
||||
memset (buf, g, n + n + n);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n < 8)
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
*buf++ = r;
|
||||
*buf++ = g;
|
||||
*buf++ = b;
|
||||
}
|
||||
} else {
|
||||
/* handle prefix up to byte alignment */
|
||||
/* I'm worried about this cast on sizeof(long) != sizeof(uchar *)
|
||||
architectures, but it _should_ work. */
|
||||
for (i = 0; ((unsigned long)buf) & 3; i++)
|
||||
{
|
||||
*buf++ = r;
|
||||
*buf++ = g;
|
||||
*buf++ = b;
|
||||
}
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
v1 = r | (g << 8) | (b << 16) | (r << 24);
|
||||
v3 = (v1 << 8) | b;
|
||||
v2 = (v3 << 8) | g;
|
||||
#else
|
||||
v1 = (r << 24) | (g << 16) | (b << 8) | r;
|
||||
v2 = (v1 << 8) | g;
|
||||
v3 = (v2 << 8) | b;
|
||||
#endif
|
||||
for (; i < n - 3; i += 4)
|
||||
{
|
||||
((art_u32 *)buf)[0] = v1;
|
||||
((art_u32 *)buf)[1] = v2;
|
||||
((art_u32 *)buf)[2] = v3;
|
||||
buf += 12;
|
||||
}
|
||||
/* handle postfix */
|
||||
for (; i < n; i++)
|
||||
{
|
||||
*buf++ = r;
|
||||
*buf++ = g;
|
||||
*buf++ = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_rgb_run_alpha: Render semitransparent color over RGB buffer.
|
||||
* @buf: Buffer for rendering.
|
||||
* @r: Red, range 0..255.
|
||||
* @g: Green, range 0..255.
|
||||
* @b: Blue, range 0..255.
|
||||
* @alpha: Alpha, range 0..256.
|
||||
* @n: Number of RGB triples to render.
|
||||
*
|
||||
* Renders a sequential run of solid (@r, @g, @b) color over @buf with
|
||||
* opacity @alpha.
|
||||
**/
|
||||
void
|
||||
art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
|
||||
{
|
||||
int i;
|
||||
int v;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
v = *buf;
|
||||
*buf++ = v + (((r - v) * alpha + 0x80) >> 8);
|
||||
v = *buf;
|
||||
*buf++ = v + (((g - v) * alpha + 0x80) >> 8);
|
||||
v = *buf;
|
||||
*buf++ = v + (((b - v) * alpha + 0x80) >> 8);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/* 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_H__
|
||||
#define __ART_RGB_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_misc.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n);
|
||||
|
||||
void
|
||||
art_rgb_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha,
|
||||
int n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,149 @@
|
||||
/* 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/* 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. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#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
|
@ -0,0 +1,106 @@
|
||||
/* 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_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 rgb images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
/**
|
||||
* art_rgb_affine: Affine transform source RGB 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 RGB buffer.
|
||||
* @src_width: Width of source image.
|
||||
* @src_height: Height of source image.
|
||||
* @src_rowstride: Rowstride of @src buffer.
|
||||
* @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. Since the source image is opaque RGB,
|
||||
* this argument only affects the edges. 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_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,
|
||||
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 run_x0, run_x1;
|
||||
|
||||
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;
|
||||
dst_p[0] = src_p[0];
|
||||
dst_p[1] = src_p[1];
|
||||
dst_p[2] = src_p[2];
|
||||
dst_p += 3;
|
||||
}
|
||||
dst_linestart += dst_rowstride;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/* 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_AFFINE_H__
|
||||
#define __ART_RGB_AFFINE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed rgb images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_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,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,127 @@
|
||||
/* 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_affine_private.h"
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_point.h"
|
||||
#include "art_affine.h"
|
||||
|
||||
/* Private functions for the rgb affine image compositors - primarily,
|
||||
the determination of runs, eliminating the need for source image
|
||||
bbox calculation in the inner loop. */
|
||||
|
||||
/* Determine a "run", such that the inverse affine of all pixels from
|
||||
(x0, y) inclusive to (x1, y) exclusive fit within the bounds
|
||||
of the source image.
|
||||
|
||||
Initial values of x0, x1, and result values stored in first two
|
||||
pointer arguments.
|
||||
*/
|
||||
|
||||
#define EPSILON 1e-6
|
||||
|
||||
void
|
||||
art_rgb_affine_run (int *p_x0, int *p_x1, int y,
|
||||
int src_width, int src_height,
|
||||
const double affine[6])
|
||||
{
|
||||
int x0, x1;
|
||||
double z;
|
||||
double x_intercept;
|
||||
int xi;
|
||||
|
||||
x0 = *p_x0;
|
||||
x1 = *p_x1;
|
||||
|
||||
/* do left and right edges */
|
||||
if (affine[0] > EPSILON)
|
||||
{
|
||||
z = affine[2] * (y + 0.5) + affine[4];
|
||||
x_intercept = -z / affine[0];
|
||||
xi = ceil (x_intercept + EPSILON - 0.5);
|
||||
if (xi > x0)
|
||||
x0 = xi;
|
||||
x_intercept = (-z + src_width) / affine[0];
|
||||
xi = ceil (x_intercept - EPSILON - 0.5);
|
||||
if (xi < x1)
|
||||
x1 = xi;
|
||||
}
|
||||
else if (affine[0] < -EPSILON)
|
||||
{
|
||||
z = affine[2] * (y + 0.5) + affine[4];
|
||||
x_intercept = (-z + src_width) / affine[0];
|
||||
xi = ceil (x_intercept + EPSILON - 0.5);
|
||||
if (xi > x0)
|
||||
x0 = xi;
|
||||
x_intercept = -z / affine[0];
|
||||
xi = ceil (x_intercept - EPSILON - 0.5);
|
||||
if (xi < x1)
|
||||
x1 = xi;
|
||||
}
|
||||
else
|
||||
{
|
||||
z = affine[2] * (y + 0.5) + affine[4];
|
||||
if (z < 0 || z >= src_width)
|
||||
{
|
||||
*p_x1 = *p_x0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* do top and bottom edges */
|
||||
if (affine[1] > EPSILON)
|
||||
{
|
||||
z = affine[3] * (y + 0.5) + affine[5];
|
||||
x_intercept = -z / affine[1];
|
||||
xi = ceil (x_intercept + EPSILON - 0.5);
|
||||
if (xi > x0)
|
||||
x0 = xi;
|
||||
x_intercept = (-z + src_height) / affine[1];
|
||||
xi = ceil (x_intercept - EPSILON - 0.5);
|
||||
if (xi < x1)
|
||||
x1 = xi;
|
||||
}
|
||||
else if (affine[1] < -EPSILON)
|
||||
{
|
||||
z = affine[3] * (y + 0.5) + affine[5];
|
||||
x_intercept = (-z + src_height) / affine[1];
|
||||
xi = ceil (x_intercept + EPSILON - 0.5);
|
||||
if (xi > x0)
|
||||
x0 = xi;
|
||||
x_intercept = -z / affine[1];
|
||||
xi = ceil (x_intercept - EPSILON - 0.5);
|
||||
if (xi < x1)
|
||||
x1 = xi;
|
||||
}
|
||||
else
|
||||
{
|
||||
z = affine[3] * (y + 0.5) + affine[5];
|
||||
if (z < 0 || z >= src_height)
|
||||
{
|
||||
*p_x1 = *p_x0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*p_x0 = x0;
|
||||
*p_x1 = x1;
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/* 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_AFFINE_PRIVATE_H__
|
||||
#define __ART_RGB_AFFINE_PRIVATE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed rgb images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_affine_run (int *p_x0, int *p_x1, int y,
|
||||
int src_width, int src_height,
|
||||
const double affine[6]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,198 @@
|
||||
/* 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/* 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. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#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
|
@ -0,0 +1,104 @@
|
||||
/* 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);
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/* 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. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#include "art_pixbuf.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#include <libart_lgpl/art_pixbuf.h>
|
||||
#endif
|
||||
|
||||
#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
|
@ -0,0 +1,142 @@
|
||||
/* 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_rgba_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 rgba images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
/* Composite the source image over the destination image, applying the
|
||||
affine transform. */
|
||||
|
||||
/**
|
||||
* art_rgb_rgba_affine: Affine transform source RGBA 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 RGBA buffer.
|
||||
* @src_width: Width of source image.
|
||||
* @src_height: Height of source image.
|
||||
* @src_rowstride: Rowstride of @src buffer.
|
||||
* @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_rgba_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,
|
||||
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;
|
||||
|
||||
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 * 4;
|
||||
if (src_x >= 0 && src_x < src_width &&
|
||||
src_y >= 0 && src_y < src_height)
|
||||
{
|
||||
|
||||
alpha = src_p[3];
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha == 255)
|
||||
{
|
||||
dst_p[0] = src_p[0];
|
||||
dst_p[1] = src_p[1];
|
||||
dst_p[2] = src_p[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
bg_r = dst_p[0];
|
||||
bg_g = dst_p[1];
|
||||
bg_b = dst_p[2];
|
||||
|
||||
tmp = (src_p[0] - bg_r) * alpha;
|
||||
fg_r = bg_r + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
tmp = (src_p[1] - bg_g) * alpha;
|
||||
fg_g = bg_g + ((tmp + (tmp >> 8) + 0x80) >> 8);
|
||||
tmp = (src_p[2] - 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/* 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_RGBA_AFFINE_H__
|
||||
#define __ART_RGB_RGBA_AFFINE_H__
|
||||
|
||||
/* This module handles compositing of affine-transformed rgba images
|
||||
over rgb pixel buffers. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_filterlevel.h"
|
||||
#include "art_alphagamma.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
art_rgb_rgba_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,
|
||||
const double affine[6],
|
||||
ArtFilterLevel level,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,457 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Render a sorted vector path into an RGB buffer. */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_rgb_svp.h"
|
||||
|
||||
#include "art_svp.h"
|
||||
#include "art_svp_render_aa.h"
|
||||
#include "art_rgb.h"
|
||||
|
||||
typedef struct _ArtRgbSVPData ArtRgbSVPData;
|
||||
typedef struct _ArtRgbSVPAlphaData ArtRgbSVPAlphaData;
|
||||
|
||||
struct _ArtRgbSVPData {
|
||||
art_u32 rgbtab[256];
|
||||
art_u8 *buf;
|
||||
int rowstride;
|
||||
int x0, x1;
|
||||
};
|
||||
|
||||
struct _ArtRgbSVPAlphaData {
|
||||
int alphatab[256];
|
||||
art_u8 r, g, b, alpha;
|
||||
art_u8 *buf;
|
||||
int rowstride;
|
||||
int x0, x1;
|
||||
};
|
||||
|
||||
static void
|
||||
art_rgb_svp_callback (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtRgbSVPData *data = (ArtRgbSVPData *)callback_data;
|
||||
art_u8 *linebuf;
|
||||
int run_x0, run_x1;
|
||||
art_u32 running_sum = start;
|
||||
art_u32 rgb;
|
||||
int x0, x1;
|
||||
int k;
|
||||
|
||||
linebuf = data->buf;
|
||||
x0 = data->x0;
|
||||
x1 = data->x1;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0)
|
||||
{
|
||||
rgb = data->rgbtab[(running_sum >> 16) & 0xff];
|
||||
art_rgb_fill_run (linebuf,
|
||||
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
|
||||
run_x1 - x0);
|
||||
}
|
||||
|
||||
for (k = 0; k < n_steps - 1; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[k + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
rgb = data->rgbtab[(running_sum >> 16) & 0xff];
|
||||
art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
|
||||
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
|
||||
run_x1 - run_x0);
|
||||
}
|
||||
}
|
||||
running_sum += steps[k].delta;
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
rgb = data->rgbtab[(running_sum >> 16) & 0xff];
|
||||
art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
|
||||
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
|
||||
x1 - run_x1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rgb = data->rgbtab[(running_sum >> 16) & 0xff];
|
||||
art_rgb_fill_run (linebuf,
|
||||
rgb >> 16, (rgb >> 8) & 0xff, rgb & 0xff,
|
||||
x1 - x0);
|
||||
}
|
||||
|
||||
data->buf += data->rowstride;
|
||||
}
|
||||
|
||||
/* Render the vector path into the RGB buffer. */
|
||||
|
||||
/**
|
||||
* art_rgb_svp_aa: Render sorted vector path into RGB buffer.
|
||||
* @svp: The source sorted vector path.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @fg_color: Foreground color in 0xRRGGBB format.
|
||||
* @bg_color: Background color in 0xRRGGBB format.
|
||||
* @buf: Destination RGB buffer.
|
||||
* @rowstride: Rowstride of @buf buffer.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the rendering.
|
||||
*
|
||||
* Renders the shape specified with @svp into the @buf RGB buffer.
|
||||
* @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
|
||||
* of the rectangle rendered. The new pixels are stored starting at
|
||||
* the first byte of @buf. Thus, the @x0 and @y0 parameters specify
|
||||
* an offset within @svp, and may be tweaked as a way of doing
|
||||
* integer-pixel translations without fiddling with @svp itself.
|
||||
*
|
||||
* The @fg_color and @bg_color arguments specify the opaque colors to
|
||||
* be used for rendering. For pixels of entirely 0 winding-number,
|
||||
* @bg_color is used. For pixels of entirely 1 winding number,
|
||||
* @fg_color is used. In between, the color is interpolated based on
|
||||
* the fraction of the pixel with a winding number of 1. If
|
||||
* @alphagamma is NULL, then linear interpolation (in pixel counts) is
|
||||
* the default. Otherwise, the interpolation is as specified by
|
||||
* @alphagamma.
|
||||
**/
|
||||
void
|
||||
art_rgb_svp_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u32 fg_color, art_u32 bg_color,
|
||||
art_u8 *buf, int rowstride,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
ArtRgbSVPData data;
|
||||
|
||||
int r_fg, g_fg, b_fg;
|
||||
int r_bg, g_bg, b_bg;
|
||||
int r, g, b;
|
||||
int dr, dg, db;
|
||||
int i;
|
||||
|
||||
if (alphagamma == NULL)
|
||||
{
|
||||
r_fg = fg_color >> 16;
|
||||
g_fg = (fg_color >> 8) & 0xff;
|
||||
b_fg = fg_color & 0xff;
|
||||
|
||||
r_bg = bg_color >> 16;
|
||||
g_bg = (bg_color >> 8) & 0xff;
|
||||
b_bg = bg_color & 0xff;
|
||||
|
||||
r = (r_bg << 16) + 0x8000;
|
||||
g = (g_bg << 16) + 0x8000;
|
||||
b = (b_bg << 16) + 0x8000;
|
||||
dr = ((r_fg - r_bg) << 16) / 255;
|
||||
dg = ((g_fg - g_bg) << 16) / 255;
|
||||
db = ((b_fg - b_bg) << 16) / 255;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
data.rgbtab[i] = (r & 0xff0000) | ((g & 0xff0000) >> 8) | (b >> 16);
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int *table;
|
||||
art_u8 *invtab;
|
||||
|
||||
table = alphagamma->table;
|
||||
|
||||
r_fg = table[fg_color >> 16];
|
||||
g_fg = table[(fg_color >> 8) & 0xff];
|
||||
b_fg = table[fg_color & 0xff];
|
||||
|
||||
r_bg = table[bg_color >> 16];
|
||||
g_bg = table[(bg_color >> 8) & 0xff];
|
||||
b_bg = table[bg_color & 0xff];
|
||||
|
||||
r = (r_bg << 16) + 0x8000;
|
||||
g = (g_bg << 16) + 0x8000;
|
||||
b = (b_bg << 16) + 0x8000;
|
||||
dr = ((r_fg - r_bg) << 16) / 255;
|
||||
dg = ((g_fg - g_bg) << 16) / 255;
|
||||
db = ((b_fg - b_bg) << 16) / 255;
|
||||
|
||||
invtab = alphagamma->invtable;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
data.rgbtab[i] = (invtab[r >> 16] << 16) |
|
||||
(invtab[g >> 16] << 8) |
|
||||
invtab[b >> 16];
|
||||
r += dr;
|
||||
g += dg;
|
||||
b += db;
|
||||
}
|
||||
}
|
||||
data.buf = buf;
|
||||
data.rowstride = rowstride;
|
||||
data.x0 = x0;
|
||||
data.x1 = x1;
|
||||
art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_callback, &data);
|
||||
}
|
||||
|
||||
static void
|
||||
art_rgb_svp_alpha_callback (void *callback_data, int y,
|
||||
int start, ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
|
||||
art_u8 *linebuf;
|
||||
int run_x0, run_x1;
|
||||
art_u32 running_sum = start;
|
||||
int x0, x1;
|
||||
int k;
|
||||
art_u8 r, g, b;
|
||||
int *alphatab;
|
||||
int alpha;
|
||||
|
||||
linebuf = data->buf;
|
||||
x0 = data->x0;
|
||||
x1 = data->x1;
|
||||
|
||||
r = data->r;
|
||||
g = data->g;
|
||||
b = data->b;
|
||||
alphatab = data->alphatab;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0)
|
||||
{
|
||||
alpha = (running_sum >> 16) & 0xff;
|
||||
if (alpha)
|
||||
art_rgb_run_alpha (linebuf,
|
||||
r, g, b, alphatab[alpha],
|
||||
run_x1 - x0);
|
||||
}
|
||||
|
||||
for (k = 0; k < n_steps - 1; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[k + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
alpha = (running_sum >> 16) & 0xff;
|
||||
if (alpha)
|
||||
art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
|
||||
r, g, b, alphatab[alpha],
|
||||
run_x1 - run_x0);
|
||||
}
|
||||
}
|
||||
running_sum += steps[k].delta;
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
alpha = (running_sum >> 16) & 0xff;
|
||||
if (alpha)
|
||||
art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
|
||||
r, g, b, alphatab[alpha],
|
||||
x1 - run_x1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = (running_sum >> 16) & 0xff;
|
||||
if (alpha)
|
||||
art_rgb_run_alpha (linebuf,
|
||||
r, g, b, alphatab[alpha],
|
||||
x1 - x0);
|
||||
}
|
||||
|
||||
data->buf += data->rowstride;
|
||||
}
|
||||
|
||||
static void
|
||||
art_rgb_svp_alpha_opaque_callback (void *callback_data, int y,
|
||||
int start,
|
||||
ArtSVPRenderAAStep *steps, int n_steps)
|
||||
{
|
||||
ArtRgbSVPAlphaData *data = (ArtRgbSVPAlphaData *)callback_data;
|
||||
art_u8 *linebuf;
|
||||
int run_x0, run_x1;
|
||||
art_u32 running_sum = start;
|
||||
int x0, x1;
|
||||
int k;
|
||||
art_u8 r, g, b;
|
||||
int *alphatab;
|
||||
int alpha;
|
||||
|
||||
linebuf = data->buf;
|
||||
x0 = data->x0;
|
||||
x1 = data->x1;
|
||||
|
||||
r = data->r;
|
||||
g = data->g;
|
||||
b = data->b;
|
||||
alphatab = data->alphatab;
|
||||
|
||||
if (n_steps > 0)
|
||||
{
|
||||
run_x1 = steps[0].x;
|
||||
if (run_x1 > x0)
|
||||
{
|
||||
alpha = running_sum >> 16;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
art_rgb_fill_run (linebuf,
|
||||
r, g, b,
|
||||
run_x1 - x0);
|
||||
else
|
||||
art_rgb_run_alpha (linebuf,
|
||||
r, g, b, alphatab[alpha],
|
||||
run_x1 - x0);
|
||||
}
|
||||
}
|
||||
|
||||
for (k = 0; k < n_steps - 1; k++)
|
||||
{
|
||||
running_sum += steps[k].delta;
|
||||
run_x0 = run_x1;
|
||||
run_x1 = steps[k + 1].x;
|
||||
if (run_x1 > run_x0)
|
||||
{
|
||||
alpha = running_sum >> 16;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
art_rgb_fill_run (linebuf + (run_x0 - x0) * 3,
|
||||
r, g, b,
|
||||
run_x1 - run_x0);
|
||||
else
|
||||
art_rgb_run_alpha (linebuf + (run_x0 - x0) * 3,
|
||||
r, g, b, alphatab[alpha],
|
||||
run_x1 - run_x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
running_sum += steps[k].delta;
|
||||
if (x1 > run_x1)
|
||||
{
|
||||
alpha = running_sum >> 16;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
art_rgb_fill_run (linebuf + (run_x1 - x0) * 3,
|
||||
r, g, b,
|
||||
x1 - run_x1);
|
||||
else
|
||||
art_rgb_run_alpha (linebuf + (run_x1 - x0) * 3,
|
||||
r, g, b, alphatab[alpha],
|
||||
x1 - run_x1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = running_sum >> 16;
|
||||
if (alpha)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
art_rgb_fill_run (linebuf,
|
||||
r, g, b,
|
||||
x1 - x0);
|
||||
else
|
||||
art_rgb_run_alpha (linebuf,
|
||||
r, g, b, alphatab[alpha],
|
||||
x1 - x0);
|
||||
}
|
||||
}
|
||||
|
||||
data->buf += data->rowstride;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_rgb_svp_alpha: Alpha-composite sorted vector path over RGB buffer.
|
||||
* @svp: The source sorted vector path.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @rgba: Color in 0xRRGGBBAA format.
|
||||
* @buf: Destination RGB buffer.
|
||||
* @rowstride: Rowstride of @buf buffer.
|
||||
* @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
|
||||
*
|
||||
* Renders the shape specified with @svp over the @buf RGB buffer.
|
||||
* @x1 - @x0 specifies the width, and @y1 - @y0 specifies the height,
|
||||
* of the rectangle rendered. The new pixels are stored starting at
|
||||
* the first byte of @buf. Thus, the @x0 and @y0 parameters specify
|
||||
* an offset within @svp, and may be tweaked as a way of doing
|
||||
* integer-pixel translations without fiddling with @svp itself.
|
||||
*
|
||||
* The @rgba argument specifies the color for the rendering. Pixels of
|
||||
* entirely 0 winding number are left untouched. Pixels of entirely
|
||||
* 1 winding number have the color @rgba composited over them (ie,
|
||||
* are replaced by the red, green, blue components of @rgba if the alpha
|
||||
* component is 0xff). Pixels of intermediate coverage are interpolated
|
||||
* according to the rule in @alphagamma, or default to linear if
|
||||
* @alphagamma is NULL.
|
||||
**/
|
||||
void
|
||||
art_rgb_svp_alpha (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u32 rgba,
|
||||
art_u8 *buf, int rowstride,
|
||||
ArtAlphaGamma *alphagamma)
|
||||
{
|
||||
ArtRgbSVPAlphaData data;
|
||||
int r, g, b, alpha;
|
||||
int i;
|
||||
int a, da;
|
||||
|
||||
r = rgba >> 24;
|
||||
g = (rgba >> 16) & 0xff;
|
||||
b = (rgba >> 8) & 0xff;
|
||||
alpha = rgba & 0xff;
|
||||
|
||||
data.r = r;
|
||||
data.g = g;
|
||||
data.b = b;
|
||||
data.alpha = alpha;
|
||||
|
||||
a = 0x8000;
|
||||
da = (alpha * 66051 + 0x80) >> 8; /* 66051 equals 2 ^ 32 / (255 * 255) */
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
data.alphatab[i] = a >> 16;
|
||||
a += da;
|
||||
}
|
||||
|
||||
data.buf = buf;
|
||||
data.rowstride = rowstride;
|
||||
data.x0 = x0;
|
||||
data.x1 = x1;
|
||||
if (alpha == 255)
|
||||
art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_opaque_callback,
|
||||
&data);
|
||||
else
|
||||
art_svp_render_aa (svp, x0, y0, x1, y1, art_rgb_svp_alpha_callback, &data);
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
/* 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_SVP_H__
|
||||
#define __ART_RGB_SVP_H__
|
||||
|
||||
/* Render a sorted vector path into an RGB buffer. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_alphagamma.h"
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void
|
||||
art_rgb_svp_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u32 fg_color, art_u32 bg_color,
|
||||
art_u8 *buf, int rowstride,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
void
|
||||
art_rgb_svp_alpha (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
art_u32 rgba,
|
||||
art_u8 *buf, int rowstride,
|
||||
ArtAlphaGamma *alphagamma);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_RGB_SVP_H__ */
|
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* art_rgba.c: Functions for manipulating RGBA pixel data.
|
||||
*
|
||||
* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2000 Raph Levien
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "art_rgba.h"
|
||||
|
||||
#define ART_OPTIMIZE_SPACE
|
||||
|
||||
#ifndef ART_OPTIMIZE_SPACE
|
||||
#include "art_rgba_table.c"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_rgba_rgba_composite: Composite RGBA image over RGBA buffer.
|
||||
* @dst: Destination RGBA buffer.
|
||||
* @src: Source RGBA buffer.
|
||||
* @n: Number of RGBA pixels to composite.
|
||||
*
|
||||
* Composites the RGBA pixels in @dst over the @src buffer.
|
||||
**/
|
||||
void
|
||||
art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n)
|
||||
{
|
||||
int i;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
art_u32 src_rgba, dst_rgba;
|
||||
#else
|
||||
art_u32 src_abgr, dst_abgr;
|
||||
#endif
|
||||
art_u8 src_alpha, dst_alpha;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_rgba = ((art_u32 *)src)[i];
|
||||
src_alpha = src_rgba & 0xff;
|
||||
#else
|
||||
src_abgr = ((art_u32 *)src)[i];
|
||||
src_alpha = (src_abgr >> 24) & 0xff;
|
||||
#endif
|
||||
if (src_alpha)
|
||||
{
|
||||
if (src_alpha == 0xff ||
|
||||
(
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
dst_rgba = ((art_u32 *)dst)[i],
|
||||
dst_alpha = dst_rgba & 0xff,
|
||||
#else
|
||||
dst_abgr = ((art_u32 *)dst)[i],
|
||||
dst_alpha = (dst_abgr >> 24),
|
||||
#endif
|
||||
dst_alpha == 0))
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)dst)[i] = src_rgba;
|
||||
#else
|
||||
((art_u32 *)dst)[i] = src_abgr;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
int r, g, b, a;
|
||||
int src_r, src_g, src_b;
|
||||
int dst_r, dst_g, dst_b;
|
||||
int tmp;
|
||||
int c;
|
||||
|
||||
#ifdef ART_OPTIMIZE_SPACE
|
||||
tmp = (255 - src_alpha) * (255 - dst_alpha) + 0x80;
|
||||
a = 255 - ((tmp + (tmp >> 8)) >> 8);
|
||||
c = ((src_alpha << 16) + (a >> 1)) / a;
|
||||
#else
|
||||
tmp = art_rgba_composite_table[(src_alpha << 8) + dst_alpha];
|
||||
c = tmp & 0x1ffff;
|
||||
a = tmp >> 24;
|
||||
#endif
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_r = (src_rgba >> 24) & 0xff;
|
||||
src_g = (src_rgba >> 16) & 0xff;
|
||||
src_b = (src_rgba >> 8) & 0xff;
|
||||
dst_r = (dst_rgba >> 24) & 0xff;
|
||||
dst_g = (dst_rgba >> 16) & 0xff;
|
||||
dst_b = (dst_rgba >> 8) & 0xff;
|
||||
#else
|
||||
src_r = src_abgr & 0xff;
|
||||
src_g = (src_abgr >> 8) & 0xff;
|
||||
src_b = (src_abgr >> 16) & 0xff;
|
||||
dst_r = dst_abgr & 0xff;
|
||||
dst_g = (dst_abgr >> 8) & 0xff;
|
||||
dst_b = (dst_abgr >> 16) & 0xff;
|
||||
#endif
|
||||
r = dst_r + (((src_r - dst_r) * c + 0x8000) >> 16);
|
||||
g = dst_g + (((src_g - dst_g) * c + 0x8000) >> 16);
|
||||
b = dst_b + (((src_b - dst_b) * c + 0x8000) >> 16);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)dst)[i] = (r << 24) | (g << 16) | (b << 8) | a;
|
||||
#else
|
||||
((art_u32 *)dst)[i] = (a << 24) | (b << 16) | (g << 8) | r;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/* it's not clear to me this optimization really wins */
|
||||
else
|
||||
{
|
||||
/* skip over run of transparent pixels */
|
||||
for (; i < n - 1; i++)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_rgba = ((art_u32 *)src)[i + 1];
|
||||
if (src_rgba & 0xff)
|
||||
break;
|
||||
#else
|
||||
src_abgr = ((art_u32 *)src)[i + 1];
|
||||
if (src_abgr & 0xff000000)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_rgba_fill_run: fill an RGBA buffer a solid RGB color.
|
||||
* @buf: Buffer to fill.
|
||||
* @r: Red, range 0..255.
|
||||
* @g: Green, range 0..255.
|
||||
* @b: Blue, range 0..255.
|
||||
* @n: Number of RGB triples to fill.
|
||||
*
|
||||
* Fills a buffer with @n copies of the (@r, @g, @b) triple, solid
|
||||
* alpha. Thus, locations @buf (inclusive) through @buf + 4 * @n
|
||||
* (exclusive) are written.
|
||||
**/
|
||||
void
|
||||
art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
|
||||
{
|
||||
int i;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
art_u32 src_rgba;
|
||||
#else
|
||||
art_u32 src_abgr;
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_rgba = (r << 24) | (g << 16) | (b << 8) | 255;
|
||||
#else
|
||||
src_abgr = (255 << 24) | (b << 16) | (g << 8) | r;
|
||||
#endif
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)buf)[i] = src_rgba;
|
||||
#else
|
||||
((art_u32 *)buf)[i] = src_abgr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_rgba_run_alpha: Render semitransparent color over RGBA buffer.
|
||||
* @buf: Buffer for rendering.
|
||||
* @r: Red, range 0..255.
|
||||
* @g: Green, range 0..255.
|
||||
* @b: Blue, range 0..255.
|
||||
* @alpha: Alpha, range 0..255.
|
||||
* @n: Number of RGB triples to render.
|
||||
*
|
||||
* Renders a sequential run of solid (@r, @g, @b) color over @buf with
|
||||
* opacity @alpha. Note that the range of @alpha is 0..255, in contrast
|
||||
* to art_rgb_run_alpha, which has a range of 0..256.
|
||||
**/
|
||||
void
|
||||
art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
|
||||
{
|
||||
int i;
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
art_u32 src_rgba, dst_rgba;
|
||||
#else
|
||||
art_u32 src_abgr, dst_abgr;
|
||||
#endif
|
||||
art_u8 dst_alpha;
|
||||
int a;
|
||||
int dst_r, dst_g, dst_b;
|
||||
int tmp;
|
||||
int c;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
src_rgba = (r << 24) | (g << 16) | (b << 8) | alpha;
|
||||
#else
|
||||
src_abgr = (alpha << 24) | (b << 16) | (g << 8) | r;
|
||||
#endif
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
dst_rgba = ((art_u32 *)buf)[i];
|
||||
dst_alpha = dst_rgba & 0xff;
|
||||
#else
|
||||
dst_abgr = ((art_u32 *)buf)[i];
|
||||
dst_alpha = (dst_abgr >> 24) & 0xff;
|
||||
#endif
|
||||
if (dst_alpha)
|
||||
{
|
||||
#ifdef ART_OPTIMIZE_SPACE
|
||||
tmp = (255 - alpha) * (255 - dst_alpha) + 0x80;
|
||||
a = 255 - ((tmp + (tmp >> 8)) >> 8);
|
||||
c = ((alpha << 16) + (a >> 1)) / a;
|
||||
#else
|
||||
tmp = art_rgba_composite_table[(alpha << 8) + dst_alpha];
|
||||
c = tmp & 0x1ffff;
|
||||
a = tmp >> 24;
|
||||
#endif
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
dst_r = (dst_rgba >> 24) & 0xff;
|
||||
dst_g = (dst_rgba >> 16) & 0xff;
|
||||
dst_b = (dst_rgba >> 8) & 0xff;
|
||||
#else
|
||||
dst_r = dst_abgr & 0xff;
|
||||
dst_g = (dst_abgr >> 8) & 0xff;
|
||||
dst_b = (dst_abgr >> 16) & 0xff;
|
||||
#endif
|
||||
dst_r += (((r - dst_r) * c + 0x8000) >> 16);
|
||||
dst_g += (((g - dst_g) * c + 0x8000) >> 16);
|
||||
dst_b += (((b - dst_b) * c + 0x8000) >> 16);
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)buf)[i] = (dst_r << 24) | (dst_g << 16) | (dst_b << 8) | a;
|
||||
#else
|
||||
((art_u32 *)buf)[i] = (a << 24) | (dst_b << 16) | (dst_g << 8) | dst_r;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
((art_u32 *)buf)[i] = src_rgba;
|
||||
#else
|
||||
((art_u32 *)buf)[i] = src_abgr;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_misc.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#endif
|
||||
|
||||
#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
|
@ -0,0 +1,152 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Basic constructors and operations for sorted vector paths */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_svp.h"
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
/* Add a new segment. The arguments can be zero and NULL if the caller
|
||||
would rather fill them in later.
|
||||
|
||||
We also realloc one auxiliary array of ints of size n_segs if
|
||||
desired.
|
||||
*/
|
||||
/**
|
||||
* art_svp_add_segment: Add a segment to an #ArtSVP structure.
|
||||
* @p_vp: Pointer to where the #ArtSVP structure is stored.
|
||||
* @pn_segs_max: Pointer to the allocated size of *@p_vp.
|
||||
* @pn_points_max: Pointer to where auxiliary array is stored.
|
||||
* @n_points: Number of points for new segment.
|
||||
* @dir: Direction for new segment; 0 is up, 1 is down.
|
||||
* @points: Points for new segment.
|
||||
* @bbox: Bounding box for new segment.
|
||||
*
|
||||
* Adds a new segment to an ArtSVP structure. This routine reallocates
|
||||
* the structure if necessary, updating *@p_vp and *@pn_segs_max as
|
||||
* necessary.
|
||||
*
|
||||
* The new segment is simply added after all other segments. Thus,
|
||||
* this routine should be called in order consistent with the #ArtSVP
|
||||
* sorting rules.
|
||||
*
|
||||
* If the @bbox argument is given, it is simply stored in the new
|
||||
* segment. Otherwise (if it is NULL), the bounding box is computed
|
||||
* from the @points given.
|
||||
**/
|
||||
int
|
||||
art_svp_add_segment (ArtSVP **p_vp, int *pn_segs_max,
|
||||
int **pn_points_max,
|
||||
int n_points, int dir, ArtPoint *points,
|
||||
ArtDRect *bbox)
|
||||
{
|
||||
int seg_num;
|
||||
ArtSVP *svp;
|
||||
ArtSVPSeg *seg;
|
||||
|
||||
svp = *p_vp;
|
||||
seg_num = svp->n_segs++;
|
||||
if (*pn_segs_max == seg_num)
|
||||
{
|
||||
*pn_segs_max <<= 1;
|
||||
svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
|
||||
(*pn_segs_max - 1) * sizeof(ArtSVPSeg));
|
||||
*p_vp = svp;
|
||||
if (pn_points_max != NULL)
|
||||
*pn_points_max = art_renew (*pn_points_max, int, *pn_segs_max);
|
||||
}
|
||||
seg = &svp->segs[seg_num];
|
||||
seg->n_points = n_points;
|
||||
seg->dir = dir;
|
||||
seg->points = points;
|
||||
if (bbox)
|
||||
seg->bbox = *bbox;
|
||||
else if (points)
|
||||
{
|
||||
double x_min, x_max;
|
||||
int i;
|
||||
|
||||
x_min = x_max = points[0].x;
|
||||
for (i = 1; i < n_points; i++)
|
||||
{
|
||||
if (x_min > points[i].x)
|
||||
x_min = points[i].x;
|
||||
if (x_max < points[i].x)
|
||||
x_max = points[i].x;
|
||||
}
|
||||
seg->bbox.x0 = x_min;
|
||||
seg->bbox.y0 = points[0].y;
|
||||
|
||||
seg->bbox.x1 = x_max;
|
||||
seg->bbox.y1 = points[n_points - 1].y;
|
||||
}
|
||||
return seg_num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* art_svp_free: Free an #ArtSVP structure.
|
||||
* @svp: #ArtSVP to free.
|
||||
*
|
||||
* Frees an #ArtSVP structure and all the segments in it.
|
||||
**/
|
||||
void
|
||||
art_svp_free (ArtSVP *svp)
|
||||
{
|
||||
int n_segs = svp->n_segs;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_segs; i++)
|
||||
art_free (svp->segs[i].points);
|
||||
art_free (svp);
|
||||
}
|
||||
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
#define EPSILON 0
|
||||
#else
|
||||
#define EPSILON 1e-6
|
||||
#endif
|
||||
|
||||
/**
|
||||
* art_svp_seg_compare: Compare two segments of an svp.
|
||||
* @seg1: First segment to compare.
|
||||
* @seg2: Second segment to compare.
|
||||
*
|
||||
* Compares two segments of an svp. Return 1 if @seg2 is below or to the
|
||||
* right of @seg1, -1 otherwise.
|
||||
**/
|
||||
int
|
||||
art_svp_seg_compare (const void *s1, const void *s2)
|
||||
{
|
||||
const ArtSVPSeg *seg1 = s1;
|
||||
const ArtSVPSeg *seg2 = s2;
|
||||
|
||||
if (seg1->points[0].y - EPSILON > seg2->points[0].y) return 1;
|
||||
else if (seg1->points[0].y + EPSILON < seg2->points[0].y) return -1;
|
||||
else if (seg1->points[0].x - EPSILON > seg2->points[0].x) return 1;
|
||||
else if (seg1->points[0].x + EPSILON < seg2->points[0].x) return -1;
|
||||
else if ((seg1->points[1].x - seg1->points[0].x) *
|
||||
(seg2->points[1].y - seg2->points[0].y) -
|
||||
(seg1->points[1].y - seg1->points[0].y) *
|
||||
(seg2->points[1].x - seg2->points[0].x) > 0) return 1;
|
||||
else return -1;
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
/* 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_SVP_H__
|
||||
#define __ART_SVP_H__
|
||||
|
||||
/* Basic data structures and constructors for sorted vector paths */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_rect.h"
|
||||
#include "art_point.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtSVP ArtSVP;
|
||||
typedef struct _ArtSVPSeg ArtSVPSeg;
|
||||
|
||||
struct _ArtSVPSeg {
|
||||
int n_points;
|
||||
int dir; /* == 0 for "up", 1 for "down" */
|
||||
ArtDRect bbox;
|
||||
ArtPoint *points;
|
||||
};
|
||||
|
||||
struct _ArtSVP {
|
||||
int n_segs;
|
||||
ArtSVPSeg segs[1];
|
||||
};
|
||||
|
||||
int
|
||||
art_svp_add_segment (ArtSVP **p_vp, int *pn_segs_max,
|
||||
int **pn_points_max,
|
||||
int n_points, int dir, ArtPoint *points,
|
||||
ArtDRect *bbox);
|
||||
|
||||
void
|
||||
art_svp_free (ArtSVP *svp);
|
||||
|
||||
int
|
||||
art_svp_seg_compare (const void *s1, const void *s2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,70 @@
|
||||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 2001 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_SVP_INTERSECT_H__
|
||||
#define __ART_SVP_INTERSECT_H__
|
||||
|
||||
/* The funky new SVP intersector. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef ART_WIND_RULE_DEFINED
|
||||
#define ART_WIND_RULE_DEFINED
|
||||
typedef enum {
|
||||
ART_WIND_RULE_NONZERO,
|
||||
ART_WIND_RULE_INTERSECT,
|
||||
ART_WIND_RULE_ODDEVEN,
|
||||
ART_WIND_RULE_POSITIVE
|
||||
} ArtWindRule;
|
||||
#endif
|
||||
|
||||
typedef struct _ArtSvpWriter ArtSvpWriter;
|
||||
|
||||
struct _ArtSvpWriter {
|
||||
int (*add_segment) (ArtSvpWriter *self, int wind_left, int delta_wind,
|
||||
double x, double y);
|
||||
void (*add_point) (ArtSvpWriter *self, int seg_id, double x, double y);
|
||||
void (*close_segment) (ArtSvpWriter *self, int seg_id);
|
||||
};
|
||||
|
||||
ArtSvpWriter *
|
||||
art_svp_writer_rewind_new (ArtWindRule rule);
|
||||
|
||||
ArtSVP *
|
||||
art_svp_writer_rewind_reap (ArtSvpWriter *self);
|
||||
|
||||
int
|
||||
art_svp_seg_compare (const void *s1, const void *s2);
|
||||
|
||||
void
|
||||
art_svp_intersector (const ArtSVP *in, ArtSvpWriter *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_INTERSECT_H__ */
|
@ -0,0 +1,401 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#define noVERBOSE
|
||||
|
||||
/* Vector path set operations, over sorted vpaths. */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_svp_ops.h"
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_svp.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
#include "art_svp_intersect.h"
|
||||
#else
|
||||
#include "art_svp_wind.h"
|
||||
#endif
|
||||
#include "art_vpath_svp.h"
|
||||
|
||||
/* Merge the segments of the two svp's. The resulting svp will share
|
||||
segments with args passed in, so be super-careful with the
|
||||
allocation. */
|
||||
/**
|
||||
* art_svp_merge: Merge the segments of two svp's.
|
||||
* @svp1: One svp to merge.
|
||||
* @svp2: The other svp to merge.
|
||||
*
|
||||
* Merges the segments of two SVP's into a new one. The resulting
|
||||
* #ArtSVP data structure will share the segments of the argument
|
||||
* svp's, so it is probably a good idea to free it shallowly,
|
||||
* especially if the arguments will be freed with art_svp_free().
|
||||
*
|
||||
* Return value: The merged #ArtSVP.
|
||||
**/
|
||||
static ArtSVP *
|
||||
art_svp_merge (const ArtSVP *svp1, const ArtSVP *svp2)
|
||||
{
|
||||
ArtSVP *svp_new;
|
||||
int ix;
|
||||
int ix1, ix2;
|
||||
|
||||
svp_new = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
|
||||
(svp1->n_segs + svp2->n_segs - 1) *
|
||||
sizeof(ArtSVPSeg));
|
||||
ix1 = 0;
|
||||
ix2 = 0;
|
||||
for (ix = 0; ix < svp1->n_segs + svp2->n_segs; ix++)
|
||||
{
|
||||
if (ix1 < svp1->n_segs &&
|
||||
(ix2 == svp2->n_segs ||
|
||||
art_svp_seg_compare (&svp1->segs[ix1], &svp2->segs[ix2]) < 1))
|
||||
svp_new->segs[ix] = svp1->segs[ix1++];
|
||||
else
|
||||
svp_new->segs[ix] = svp2->segs[ix2++];
|
||||
}
|
||||
|
||||
svp_new->n_segs = ix;
|
||||
return svp_new;
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
|
||||
#define XOFF 50
|
||||
#define YOFF 700
|
||||
|
||||
static void
|
||||
print_ps_vpath (ArtVpath *vpath)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf ("gsave %d %d translate 1 -1 scale\n", XOFF, YOFF);
|
||||
for (i = 0; vpath[i].code != ART_END; i++)
|
||||
{
|
||||
switch (vpath[i].code)
|
||||
{
|
||||
case ART_MOVETO:
|
||||
printf ("%g %g moveto\n", vpath[i].x, vpath[i].y);
|
||||
break;
|
||||
case ART_LINETO:
|
||||
printf ("%g %g lineto\n", vpath[i].x, vpath[i].y);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf ("stroke grestore showpage\n");
|
||||
}
|
||||
|
||||
#define DELT 4
|
||||
|
||||
static void
|
||||
print_ps_svp (ArtSVP *vpath)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
printf ("%% begin\n");
|
||||
for (i = 0; i < vpath->n_segs; i++)
|
||||
{
|
||||
printf ("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0);
|
||||
for (j = 0; j < vpath->segs[i].n_points; j++)
|
||||
{
|
||||
printf ("%g %g %s\n",
|
||||
XOFF + vpath->segs[i].points[j].x,
|
||||
YOFF - vpath->segs[i].points[j].y,
|
||||
j ? "lineto" : "moveto");
|
||||
}
|
||||
printf ("%g %g moveto %g %g lineto %g %g lineto %g %g lineto stroke\n",
|
||||
XOFF + vpath->segs[i].points[0].x - DELT,
|
||||
YOFF - DELT - vpath->segs[i].points[0].y,
|
||||
XOFF + vpath->segs[i].points[0].x - DELT,
|
||||
YOFF - vpath->segs[i].points[0].y,
|
||||
XOFF + vpath->segs[i].points[0].x + DELT,
|
||||
YOFF - vpath->segs[i].points[0].y,
|
||||
XOFF + vpath->segs[i].points[0].x + DELT,
|
||||
YOFF - DELT - vpath->segs[i].points[0].y);
|
||||
printf ("%g %g moveto %g %g lineto %g %g lineto %g %g lineto stroke\n",
|
||||
XOFF + vpath->segs[i].points[j - 1].x - DELT,
|
||||
YOFF + DELT - vpath->segs[i].points[j - 1].y,
|
||||
XOFF + vpath->segs[i].points[j - 1].x - DELT,
|
||||
YOFF - vpath->segs[i].points[j - 1].y,
|
||||
XOFF + vpath->segs[i].points[j - 1].x + DELT,
|
||||
YOFF - vpath->segs[i].points[j - 1].y,
|
||||
XOFF + vpath->segs[i].points[j - 1].x + DELT,
|
||||
YOFF + DELT - vpath->segs[i].points[j - 1].y);
|
||||
printf ("stroke\n");
|
||||
}
|
||||
|
||||
printf ("showpage\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ART_USE_NEW_INTERSECTOR
|
||||
static ArtSVP *
|
||||
art_svp_merge_perturbed (const ArtSVP *svp1, const ArtSVP *svp2)
|
||||
{
|
||||
ArtVpath *vpath1, *vpath2;
|
||||
ArtVpath *vpath1_p, *vpath2_p;
|
||||
ArtSVP *svp1_p, *svp2_p;
|
||||
ArtSVP *svp_new;
|
||||
|
||||
vpath1 = art_vpath_from_svp (svp1);
|
||||
vpath1_p = art_vpath_perturb (vpath1);
|
||||
art_free (vpath1);
|
||||
svp1_p = art_svp_from_vpath (vpath1_p);
|
||||
art_free (vpath1_p);
|
||||
|
||||
vpath2 = art_vpath_from_svp (svp2);
|
||||
vpath2_p = art_vpath_perturb (vpath2);
|
||||
art_free (vpath2);
|
||||
svp2_p = art_svp_from_vpath (vpath2_p);
|
||||
art_free (vpath2_p);
|
||||
|
||||
svp_new = art_svp_merge (svp1_p, svp2_p);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp1_p);
|
||||
print_ps_svp (svp2_p);
|
||||
print_ps_svp (svp_new);
|
||||
#endif
|
||||
art_free (svp1_p);
|
||||
art_free (svp2_p);
|
||||
|
||||
return svp_new;
|
||||
}
|
||||
#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:
|
||||
|
||||
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 isolated segments may
|
||||
appear.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* art_svp_intersect: Compute the intersection of two sorted vector paths.
|
||||
* @svp1: One sorted vector path.
|
||||
* @svp2: The other sorted vector path.
|
||||
*
|
||||
* Computes the intersection 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 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 intersection of @svp1 and @svp2.
|
||||
**/
|
||||
ArtSVP *
|
||||
art_svp_intersect (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_INTERSECT);
|
||||
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_INTERSECT);
|
||||
art_svp_free (svp4);
|
||||
return svp_new;
|
||||
#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 */
|
@ -0,0 +1,44 @@
|
||||
/* 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_SVP_OPS_H__
|
||||
#define __ART_SVP_OPS_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* 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
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_OPS_H__ */
|
@ -0,0 +1,144 @@
|
||||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1999 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_svp_point.h"
|
||||
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_svp.h"
|
||||
|
||||
/* Determine whether a point is inside, or near, an svp. */
|
||||
|
||||
/* return winding number of point wrt svp */
|
||||
/**
|
||||
* art_svp_point_wind: Determine winding number of a point with respect to svp.
|
||||
* @svp: The svp.
|
||||
* @x: The X coordinate of the point.
|
||||
* @y: The Y coordinate of the point.
|
||||
*
|
||||
* Determine the winding number of the point @x, @y with respect to @svp.
|
||||
*
|
||||
* Return value: the winding number.
|
||||
**/
|
||||
int
|
||||
art_svp_point_wind (ArtSVP *svp, double x, double y)
|
||||
{
|
||||
int i, j;
|
||||
int wind = 0;
|
||||
|
||||
for (i = 0; i < svp->n_segs; i++)
|
||||
{
|
||||
ArtSVPSeg *seg = &svp->segs[i];
|
||||
|
||||
if (seg->bbox.y0 > y)
|
||||
break;
|
||||
|
||||
if (seg->bbox.y1 > y)
|
||||
{
|
||||
if (seg->bbox.x1 < x)
|
||||
wind += seg->dir ? 1 : -1;
|
||||
else if (seg->bbox.x0 <= x)
|
||||
{
|
||||
double x0, y0, x1, y1, dx, dy;
|
||||
|
||||
for (j = 0; j < seg->n_points - 1; j++)
|
||||
{
|
||||
if (seg->points[j + 1].y > y)
|
||||
break;
|
||||
}
|
||||
x0 = seg->points[j].x;
|
||||
y0 = seg->points[j].y;
|
||||
x1 = seg->points[j + 1].x;
|
||||
y1 = seg->points[j + 1].y;
|
||||
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
if ((x - x0) * dy > (y - y0) * dx)
|
||||
wind += seg->dir ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wind;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_svp_point_dist: Determine distance between point and svp.
|
||||
* @svp: The svp.
|
||||
* @x: The X coordinate of the point.
|
||||
* @y: The Y coordinate of the point.
|
||||
*
|
||||
* Determines the distance of the point @x, @y to the closest edge in
|
||||
* @svp. A large number is returned if @svp is empty.
|
||||
*
|
||||
* Return value: the distance.
|
||||
**/
|
||||
double
|
||||
art_svp_point_dist (ArtSVP *svp, double x, double y)
|
||||
{
|
||||
int i, j;
|
||||
double dist_sq;
|
||||
double best_sq = -1;
|
||||
|
||||
for (i = 0; i < svp->n_segs; i++)
|
||||
{
|
||||
ArtSVPSeg *seg = &svp->segs[i];
|
||||
for (j = 0; j < seg->n_points - 1; j++)
|
||||
{
|
||||
double x0 = seg->points[j].x;
|
||||
double y0 = seg->points[j].y;
|
||||
double x1 = seg->points[j + 1].x;
|
||||
double y1 = seg->points[j + 1].y;
|
||||
|
||||
double dx = x1 - x0;
|
||||
double dy = y1 - y0;
|
||||
|
||||
double dxx0 = x - x0;
|
||||
double dyy0 = y - y0;
|
||||
|
||||
double dot = dxx0 * dx + dyy0 * dy;
|
||||
|
||||
if (dot < 0)
|
||||
dist_sq = dxx0 * dxx0 + dyy0 * dyy0;
|
||||
else
|
||||
{
|
||||
double rr = dx * dx + dy * dy;
|
||||
|
||||
if (dot > rr)
|
||||
dist_sq = (x - x1) * (x - x1) + (y - y1) * (y - y1);
|
||||
else
|
||||
{
|
||||
double perp = (y - y0) * dx - (x - x0) * dy;
|
||||
|
||||
dist_sq = perp * perp / rr;
|
||||
}
|
||||
}
|
||||
if (best_sq < 0 || dist_sq < best_sq)
|
||||
best_sq = dist_sq;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_sq >= 0)
|
||||
return sqrt (best_sq);
|
||||
else
|
||||
return 1e12;
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1999 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_SVP_POINT_H__
|
||||
#define __ART_SVP_POINT_H__
|
||||
|
||||
/* Determine whether a point is inside, or near, an svp. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int
|
||||
art_svp_point_wind (ArtSVP *svp, double x, double y);
|
||||
|
||||
double
|
||||
art_svp_point_dist (ArtSVP *svp, double x, double y);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_H__ */
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,463 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* The spiffy antialiased renderer for sorted vector paths. */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_svp_render_aa.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h> /* for memmove */
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_rect.h"
|
||||
#include "art_svp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
typedef double artfloat;
|
||||
|
||||
struct _ArtSVPRenderAAIter {
|
||||
const ArtSVP *svp;
|
||||
int x0, x1;
|
||||
int y;
|
||||
int seg_ix;
|
||||
|
||||
int *active_segs;
|
||||
int n_active_segs;
|
||||
int *cursor;
|
||||
artfloat *seg_x;
|
||||
artfloat *seg_dx;
|
||||
|
||||
ArtSVPRenderAAStep *steps;
|
||||
};
|
||||
|
||||
static void
|
||||
art_svp_render_insert_active (int i, int *active_segs, int n_active_segs,
|
||||
artfloat *seg_x, artfloat *seg_dx)
|
||||
{
|
||||
int j;
|
||||
artfloat x;
|
||||
int tmp1, tmp2;
|
||||
|
||||
/* this is a cheap hack to get ^'s sorted correctly */
|
||||
x = seg_x[i] + 0.001 * seg_dx[i];
|
||||
for (j = 0; j < n_active_segs && seg_x[active_segs[j]] < x; j++);
|
||||
|
||||
tmp1 = i;
|
||||
while (j < n_active_segs)
|
||||
{
|
||||
tmp2 = active_segs[j];
|
||||
active_segs[j] = tmp1;
|
||||
tmp1 = tmp2;
|
||||
j++;
|
||||
}
|
||||
active_segs[j] = tmp1;
|
||||
}
|
||||
|
||||
static void
|
||||
art_svp_render_delete_active (int *active_segs, int j, int n_active_segs)
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = j; k < n_active_segs; k++)
|
||||
active_segs[k] = active_segs[k + 1];
|
||||
}
|
||||
|
||||
#define EPSILON 1e-6
|
||||
|
||||
/* Render the sorted vector path in the given rectangle, antialiased.
|
||||
|
||||
This interface uses a callback for the actual pixel rendering. The
|
||||
callback is called y1 - y0 times (once for each scan line). The y
|
||||
coordinate is given as an argument for convenience (it could be
|
||||
stored in the callback's private data and incremented on each
|
||||
call).
|
||||
|
||||
The rendered polygon is represented in a semi-runlength format: a
|
||||
start value and a sequence of "steps". Each step has an x
|
||||
coordinate and a value delta. The resulting value at position x is
|
||||
equal to the sum of the start value and all step delta values for
|
||||
which the step x coordinate is less than or equal to x. An
|
||||
efficient algorithm will traverse the steps left to right, keeping
|
||||
a running sum.
|
||||
|
||||
All x coordinates in the steps are guaranteed to be x0 <= x < x1.
|
||||
(This guarantee is a change from the gfonted vpaar renderer, and is
|
||||
designed to simplify the callback).
|
||||
|
||||
There is now a further guarantee that no two steps will have the
|
||||
same x value. This may allow for further speedup and simplification
|
||||
of renderers.
|
||||
|
||||
The value 0x8000 represents 0% coverage by the polygon, while
|
||||
0xff8000 represents 100% coverage. This format is designed so that
|
||||
>> 16 results in a standard 0x00..0xff value range, with nice
|
||||
rounding.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: OK
|
||||
|
||||
Numerical stability: pretty good, although probably not
|
||||
bulletproof.
|
||||
|
||||
Speed: Needs more aggressive culling of bounding boxes. Can
|
||||
probably speed up the [x0,x1) clipping of step values. Can do more
|
||||
of the step calculation in fixed point.
|
||||
|
||||
Precision: No known problems, although it should be tested
|
||||
thoroughly, especially for symmetry.
|
||||
|
||||
*/
|
||||
|
||||
ArtSVPRenderAAIter *
|
||||
art_svp_render_aa_iter (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1)
|
||||
{
|
||||
ArtSVPRenderAAIter *iter = art_new (ArtSVPRenderAAIter, 1);
|
||||
|
||||
iter->svp = svp;
|
||||
iter->y = y0;
|
||||
iter->x0 = x0;
|
||||
iter->x1 = x1;
|
||||
iter->seg_ix = 0;
|
||||
|
||||
iter->active_segs = art_new (int, svp->n_segs);
|
||||
iter->cursor = art_new (int, svp->n_segs);
|
||||
iter->seg_x = art_new (artfloat, svp->n_segs);
|
||||
iter->seg_dx = art_new (artfloat, svp->n_segs);
|
||||
iter->steps = art_new (ArtSVPRenderAAStep, x1 - x0);
|
||||
iter->n_active_segs = 0;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
#define ADD_STEP(xpos, xdelta) \
|
||||
/* stereotype code fragment for adding a step */ \
|
||||
if (n_steps == 0 || steps[n_steps - 1].x < xpos) \
|
||||
{ \
|
||||
sx = n_steps; \
|
||||
steps[sx].x = xpos; \
|
||||
steps[sx].delta = xdelta; \
|
||||
n_steps++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
for (sx = n_steps; sx > 0; sx--) \
|
||||
{ \
|
||||
if (steps[sx - 1].x == xpos) \
|
||||
{ \
|
||||
steps[sx - 1].delta += xdelta; \
|
||||
sx = n_steps; \
|
||||
break; \
|
||||
} \
|
||||
else if (steps[sx - 1].x < xpos) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (sx < n_steps) \
|
||||
{ \
|
||||
memmove (&steps[sx + 1], &steps[sx], \
|
||||
(n_steps - sx) * sizeof(steps[0])); \
|
||||
steps[sx].x = xpos; \
|
||||
steps[sx].delta = xdelta; \
|
||||
n_steps++; \
|
||||
} \
|
||||
}
|
||||
|
||||
void
|
||||
art_svp_render_aa_iter_step (ArtSVPRenderAAIter *iter, int *p_start,
|
||||
ArtSVPRenderAAStep **p_steps, int *p_n_steps)
|
||||
{
|
||||
const ArtSVP *svp = iter->svp;
|
||||
int *active_segs = iter->active_segs;
|
||||
int n_active_segs = iter->n_active_segs;
|
||||
int *cursor = iter->cursor;
|
||||
artfloat *seg_x = iter->seg_x;
|
||||
artfloat *seg_dx = iter->seg_dx;
|
||||
int i = iter->seg_ix;
|
||||
int j;
|
||||
int x0 = iter->x0;
|
||||
int x1 = iter->x1;
|
||||
int y = iter->y;
|
||||
int seg_index;
|
||||
|
||||
int x;
|
||||
ArtSVPRenderAAStep *steps = iter->steps;
|
||||
int n_steps;
|
||||
artfloat y_top, y_bot;
|
||||
artfloat x_top, x_bot;
|
||||
artfloat x_min, x_max;
|
||||
int ix_min, ix_max;
|
||||
artfloat delta; /* delta should be int too? */
|
||||
int last, this;
|
||||
int xdelta;
|
||||
artfloat rslope, drslope;
|
||||
int start;
|
||||
const ArtSVPSeg *seg;
|
||||
int curs;
|
||||
artfloat dy;
|
||||
|
||||
int sx;
|
||||
|
||||
/* insert new active segments */
|
||||
for (; i < svp->n_segs && svp->segs[i].bbox.y0 < y + 1; i++)
|
||||
{
|
||||
if (svp->segs[i].bbox.y1 > y &&
|
||||
svp->segs[i].bbox.x0 < x1)
|
||||
{
|
||||
seg = &svp->segs[i];
|
||||
/* move cursor to topmost vector which overlaps [y,y+1) */
|
||||
for (curs = 0; seg->points[curs + 1].y < y; curs++);
|
||||
cursor[i] = curs;
|
||||
dy = seg->points[curs + 1].y - seg->points[curs].y;
|
||||
if (fabs (dy) >= EPSILON)
|
||||
seg_dx[i] = (seg->points[curs + 1].x - seg->points[curs].x) /
|
||||
dy;
|
||||
else
|
||||
seg_dx[i] = 1e12;
|
||||
seg_x[i] = seg->points[curs].x +
|
||||
(y - seg->points[curs].y) * seg_dx[i];
|
||||
art_svp_render_insert_active (i, active_segs, n_active_segs++,
|
||||
seg_x, seg_dx);
|
||||
}
|
||||
}
|
||||
|
||||
n_steps = 0;
|
||||
|
||||
/* render the runlengths, advancing and deleting as we go */
|
||||
start = 0x8000;
|
||||
|
||||
for (j = 0; j < n_active_segs; j++)
|
||||
{
|
||||
seg_index = active_segs[j];
|
||||
seg = &svp->segs[seg_index];
|
||||
curs = cursor[seg_index];
|
||||
while (curs != seg->n_points - 1 &&
|
||||
seg->points[curs].y < y + 1)
|
||||
{
|
||||
y_top = y;
|
||||
if (y_top < seg->points[curs].y)
|
||||
y_top = seg->points[curs].y;
|
||||
y_bot = y + 1;
|
||||
if (y_bot > seg->points[curs + 1].y)
|
||||
y_bot = seg->points[curs + 1].y;
|
||||
if (y_top != y_bot) {
|
||||
delta = (seg->dir ? 16711680.0 : -16711680.0) *
|
||||
(y_bot - y_top);
|
||||
x_top = seg_x[seg_index] + (y_top - y) * seg_dx[seg_index];
|
||||
x_bot = seg_x[seg_index] + (y_bot - y) * seg_dx[seg_index];
|
||||
if (x_top < x_bot)
|
||||
{
|
||||
x_min = x_top;
|
||||
x_max = x_bot;
|
||||
}
|
||||
else
|
||||
{
|
||||
x_min = x_bot;
|
||||
x_max = x_top;
|
||||
}
|
||||
ix_min = floor (x_min);
|
||||
ix_max = floor (x_max);
|
||||
if (ix_min >= x1)
|
||||
{
|
||||
/* skip; it starts to the right of the render region */
|
||||
}
|
||||
else if (ix_max < x0)
|
||||
/* it ends to the left of the render region */
|
||||
start += delta;
|
||||
else if (ix_min == ix_max)
|
||||
{
|
||||
/* case 1, antialias a single pixel */
|
||||
xdelta = (ix_min + 1 - (x_min + x_max) * 0.5) * delta;
|
||||
|
||||
ADD_STEP(ix_min, xdelta)
|
||||
|
||||
if (ix_min + 1 < x1)
|
||||
{
|
||||
xdelta = delta - xdelta;
|
||||
|
||||
ADD_STEP(ix_min + 1, xdelta)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* case 2, antialias a run */
|
||||
rslope = 1.0 / fabs (seg_dx[seg_index]);
|
||||
drslope = delta * rslope;
|
||||
last =
|
||||
drslope * 0.5 *
|
||||
(ix_min + 1 - x_min) * (ix_min + 1 - x_min);
|
||||
xdelta = last;
|
||||
if (ix_min >= x0)
|
||||
{
|
||||
ADD_STEP(ix_min, xdelta)
|
||||
|
||||
x = ix_min + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
start += last;
|
||||
x = x0;
|
||||
}
|
||||
if (ix_max > x1)
|
||||
ix_max = x1;
|
||||
for (; x < ix_max; x++)
|
||||
{
|
||||
this = (seg->dir ? 16711680.0 : -16711680.0) * rslope *
|
||||
(x + 0.5 - x_min);
|
||||
xdelta = this - last;
|
||||
last = this;
|
||||
|
||||
ADD_STEP(x, xdelta)
|
||||
}
|
||||
if (x < x1)
|
||||
{
|
||||
this =
|
||||
delta * (1 - 0.5 *
|
||||
(x_max - ix_max) * (x_max - ix_max) *
|
||||
rslope);
|
||||
xdelta = this - last;
|
||||
last = this;
|
||||
|
||||
ADD_STEP(x, xdelta)
|
||||
|
||||
if (x + 1 < x1)
|
||||
{
|
||||
xdelta = delta - last;
|
||||
|
||||
ADD_STEP(x + 1, xdelta)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
curs++;
|
||||
if (curs != seg->n_points - 1 &&
|
||||
seg->points[curs].y < y + 1)
|
||||
{
|
||||
dy = seg->points[curs + 1].y - seg->points[curs].y;
|
||||
if (fabs (dy) >= EPSILON)
|
||||
seg_dx[seg_index] = (seg->points[curs + 1].x -
|
||||
seg->points[curs].x) / dy;
|
||||
else
|
||||
seg_dx[seg_index] = 1e12;
|
||||
seg_x[seg_index] = seg->points[curs].x +
|
||||
(y - seg->points[curs].y) * seg_dx[seg_index];
|
||||
}
|
||||
/* break here, instead of duplicating predicate in while? */
|
||||
}
|
||||
if (seg->points[curs].y >= y + 1)
|
||||
{
|
||||
curs--;
|
||||
cursor[seg_index] = curs;
|
||||
seg_x[seg_index] += seg_dx[seg_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
art_svp_render_delete_active (active_segs, j--,
|
||||
--n_active_segs);
|
||||
}
|
||||
}
|
||||
|
||||
*p_start = start;
|
||||
*p_steps = steps;
|
||||
*p_n_steps = n_steps;
|
||||
|
||||
iter->seg_ix = i;
|
||||
iter->n_active_segs = n_active_segs;
|
||||
iter->y++;
|
||||
}
|
||||
|
||||
void
|
||||
art_svp_render_aa_iter_done (ArtSVPRenderAAIter *iter)
|
||||
{
|
||||
art_free (iter->steps);
|
||||
|
||||
art_free (iter->seg_dx);
|
||||
art_free (iter->seg_x);
|
||||
art_free (iter->cursor);
|
||||
art_free (iter->active_segs);
|
||||
art_free (iter);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_svp_render_aa: Render SVP antialiased.
|
||||
* @svp: The #ArtSVP to render.
|
||||
* @x0: Left coordinate of destination rectangle.
|
||||
* @y0: Top coordinate of destination rectangle.
|
||||
* @x1: Right coordinate of destination rectangle.
|
||||
* @y1: Bottom coordinate of destination rectangle.
|
||||
* @callback: The callback which actually paints the pixels.
|
||||
* @callback_data: Private data for @callback.
|
||||
*
|
||||
* Renders the sorted vector path in the given rectangle, antialiased.
|
||||
*
|
||||
* This interface uses a callback for the actual pixel rendering. The
|
||||
* callback is called @y1 - @y0 times (once for each scan line). The y
|
||||
* coordinate is given as an argument for convenience (it could be
|
||||
* stored in the callback's private data and incremented on each
|
||||
* call).
|
||||
*
|
||||
* The rendered polygon is represented in a semi-runlength format: a
|
||||
* start value and a sequence of "steps". Each step has an x
|
||||
* coordinate and a value delta. The resulting value at position x is
|
||||
* equal to the sum of the start value and all step delta values for
|
||||
* which the step x coordinate is less than or equal to x. An
|
||||
* efficient algorithm will traverse the steps left to right, keeping
|
||||
* a running sum.
|
||||
*
|
||||
* All x coordinates in the steps are guaranteed to be @x0 <= x < @x1.
|
||||
* (This guarantee is a change from the gfonted vpaar renderer from
|
||||
* which this routine is derived, and is designed to simplify the
|
||||
* callback).
|
||||
*
|
||||
* The value 0x8000 represents 0% coverage by the polygon, while
|
||||
* 0xff8000 represents 100% coverage. This format is designed so that
|
||||
* >> 16 results in a standard 0x00..0xff value range, with nice
|
||||
* rounding.
|
||||
*
|
||||
**/
|
||||
void
|
||||
art_svp_render_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
void (*callback) (void *callback_data,
|
||||
int y,
|
||||
int start,
|
||||
ArtSVPRenderAAStep *steps, int n_steps),
|
||||
void *callback_data)
|
||||
{
|
||||
ArtSVPRenderAAIter *iter;
|
||||
int y;
|
||||
int start;
|
||||
ArtSVPRenderAAStep *steps;
|
||||
int n_steps;
|
||||
|
||||
iter = art_svp_render_aa_iter (svp, x0, y0, x1, y1);
|
||||
|
||||
|
||||
for (y = y0; y < y1; y++)
|
||||
{
|
||||
art_svp_render_aa_iter_step (iter, &start, &steps, &n_steps);
|
||||
(*callback) (callback_data, y, start, steps, n_steps);
|
||||
}
|
||||
|
||||
art_svp_render_aa_iter_done (iter);
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/* 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_SVP_RENDER_AA_H__
|
||||
#define __ART_SVP_RENDER_AA_H__
|
||||
|
||||
/* The spiffy antialiased renderer for sorted vector paths. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtSVPRenderAAStep ArtSVPRenderAAStep;
|
||||
typedef struct _ArtSVPRenderAAIter ArtSVPRenderAAIter;
|
||||
|
||||
struct _ArtSVPRenderAAStep {
|
||||
int x;
|
||||
int delta; /* stored with 16 fractional bits */
|
||||
};
|
||||
|
||||
ArtSVPRenderAAIter *
|
||||
art_svp_render_aa_iter (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1);
|
||||
|
||||
void
|
||||
art_svp_render_aa_iter_step (ArtSVPRenderAAIter *iter, int *p_start,
|
||||
ArtSVPRenderAAStep **p_steps, int *p_n_steps);
|
||||
|
||||
void
|
||||
art_svp_render_aa_iter_done (ArtSVPRenderAAIter *iter);
|
||||
|
||||
void
|
||||
art_svp_render_aa (const ArtSVP *svp,
|
||||
int x0, int y0, int x1, int y1,
|
||||
void (*callback) (void *callback_data,
|
||||
int y,
|
||||
int start,
|
||||
ArtSVPRenderAAStep *steps, int n_steps),
|
||||
void *callback_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_RENDER_AA_H__ */
|
@ -0,0 +1,215 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Sort vector paths into sorted vector paths */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_svp_vpath.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp.h"
|
||||
|
||||
|
||||
/* reverse a list of points in place */
|
||||
static void
|
||||
reverse_points (ArtPoint *points, int n_points)
|
||||
{
|
||||
int i;
|
||||
ArtPoint tmp_p;
|
||||
|
||||
for (i = 0; i < (n_points >> 1); i++)
|
||||
{
|
||||
tmp_p = points[i];
|
||||
points[i] = points[n_points - (i + 1)];
|
||||
points[n_points - (i + 1)] = tmp_p;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_svp_from_vpath: Convert a vpath to a sorted vector path.
|
||||
* @vpath: #ArtVPath to convert.
|
||||
*
|
||||
* Converts a vector path into sorted vector path form. The svp form is
|
||||
* more efficient for rendering and other vector operations.
|
||||
*
|
||||
* Basically, the implementation is to traverse the vector path,
|
||||
* generating a new segment for each "run" of points in the vector
|
||||
* path with monotonically increasing Y values. All the resulting
|
||||
* values are then sorted.
|
||||
*
|
||||
* Note: I'm not sure that the sorting rule is correct with respect
|
||||
* to numerical stability issues.
|
||||
*
|
||||
* Return value: Resulting sorted vector path.
|
||||
**/
|
||||
ArtSVP *
|
||||
art_svp_from_vpath (ArtVpath *vpath)
|
||||
{
|
||||
int n_segs, n_segs_max;
|
||||
ArtSVP *svp;
|
||||
int dir;
|
||||
int new_dir;
|
||||
int i;
|
||||
ArtPoint *points;
|
||||
int n_points, n_points_max;
|
||||
double x, y;
|
||||
double x_min, x_max;
|
||||
|
||||
n_segs = 0;
|
||||
n_segs_max = 16;
|
||||
svp = (ArtSVP *)art_alloc (sizeof(ArtSVP) +
|
||||
(n_segs_max - 1) * sizeof(ArtSVPSeg));
|
||||
|
||||
dir = 0;
|
||||
n_points = 0;
|
||||
n_points_max = 0;
|
||||
points = NULL;
|
||||
i = 0;
|
||||
|
||||
x = y = 0; /* unnecessary, given "first code must not be LINETO" invariant,
|
||||
but it makes gcc -Wall -ansi -pedantic happier */
|
||||
x_min = x_max = 0; /* same */
|
||||
|
||||
while (vpath[i].code != ART_END) {
|
||||
if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN)
|
||||
{
|
||||
if (points != NULL && n_points >= 2)
|
||||
{
|
||||
if (n_segs == n_segs_max)
|
||||
{
|
||||
n_segs_max <<= 1;
|
||||
svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
|
||||
(n_segs_max - 1) *
|
||||
sizeof(ArtSVPSeg));
|
||||
}
|
||||
svp->segs[n_segs].n_points = n_points;
|
||||
svp->segs[n_segs].dir = (dir > 0);
|
||||
if (dir < 0)
|
||||
reverse_points (points, n_points);
|
||||
svp->segs[n_segs].points = points;
|
||||
svp->segs[n_segs].bbox.x0 = x_min;
|
||||
svp->segs[n_segs].bbox.x1 = x_max;
|
||||
svp->segs[n_segs].bbox.y0 = points[0].y;
|
||||
svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
|
||||
n_segs++;
|
||||
points = NULL;
|
||||
}
|
||||
|
||||
if (points == NULL)
|
||||
{
|
||||
n_points_max = 4;
|
||||
points = art_new (ArtPoint, n_points_max);
|
||||
}
|
||||
|
||||
n_points = 1;
|
||||
points[0].x = x = vpath[i].x;
|
||||
points[0].y = y = vpath[i].y;
|
||||
x_min = x;
|
||||
x_max = x;
|
||||
dir = 0;
|
||||
}
|
||||
else /* must be LINETO */
|
||||
{
|
||||
new_dir = (vpath[i].y > y ||
|
||||
(vpath[i].y == y && vpath[i].x > x)) ? 1 : -1;
|
||||
if (dir && dir != new_dir)
|
||||
{
|
||||
/* new segment */
|
||||
x = points[n_points - 1].x;
|
||||
y = points[n_points - 1].y;
|
||||
if (n_segs == n_segs_max)
|
||||
{
|
||||
n_segs_max <<= 1;
|
||||
svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
|
||||
(n_segs_max - 1) *
|
||||
sizeof(ArtSVPSeg));
|
||||
}
|
||||
svp->segs[n_segs].n_points = n_points;
|
||||
svp->segs[n_segs].dir = (dir > 0);
|
||||
if (dir < 0)
|
||||
reverse_points (points, n_points);
|
||||
svp->segs[n_segs].points = points;
|
||||
svp->segs[n_segs].bbox.x0 = x_min;
|
||||
svp->segs[n_segs].bbox.x1 = x_max;
|
||||
svp->segs[n_segs].bbox.y0 = points[0].y;
|
||||
svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
|
||||
n_segs++;
|
||||
|
||||
n_points = 1;
|
||||
n_points_max = 4;
|
||||
points = art_new (ArtPoint, n_points_max);
|
||||
points[0].x = x;
|
||||
points[0].y = y;
|
||||
x_min = x;
|
||||
x_max = x;
|
||||
}
|
||||
|
||||
if (points != NULL)
|
||||
{
|
||||
if (n_points == n_points_max)
|
||||
art_expand (points, ArtPoint, n_points_max);
|
||||
points[n_points].x = x = vpath[i].x;
|
||||
points[n_points].y = y = vpath[i].y;
|
||||
if (x < x_min) x_min = x;
|
||||
else if (x > x_max) x_max = x;
|
||||
n_points++;
|
||||
}
|
||||
dir = new_dir;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (points != NULL)
|
||||
{
|
||||
if (n_points >= 2)
|
||||
{
|
||||
if (n_segs == n_segs_max)
|
||||
{
|
||||
n_segs_max <<= 1;
|
||||
svp = (ArtSVP *)art_realloc (svp, sizeof(ArtSVP) +
|
||||
(n_segs_max - 1) *
|
||||
sizeof(ArtSVPSeg));
|
||||
}
|
||||
svp->segs[n_segs].n_points = n_points;
|
||||
svp->segs[n_segs].dir = (dir > 0);
|
||||
if (dir < 0)
|
||||
reverse_points (points, n_points);
|
||||
svp->segs[n_segs].points = points;
|
||||
svp->segs[n_segs].bbox.x0 = x_min;
|
||||
svp->segs[n_segs].bbox.x1 = x_max;
|
||||
svp->segs[n_segs].bbox.y0 = points[0].y;
|
||||
svp->segs[n_segs].bbox.y1 = points[n_points - 1].y;
|
||||
n_segs++;
|
||||
}
|
||||
else
|
||||
art_free (points);
|
||||
}
|
||||
|
||||
svp->n_segs = n_segs;
|
||||
|
||||
qsort (&svp->segs, n_segs, sizeof (ArtSVPSeg), art_svp_seg_compare);
|
||||
|
||||
return svp;
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/* 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_SVP_VPATH_H__
|
||||
#define __ART_SVP_VPATH_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#include "art_vpath.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#endif
|
||||
|
||||
/* Sort vector paths into sorted vector paths. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtSVP *
|
||||
art_svp_from_vpath (ArtVpath *vpath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_VPATH_H__ */
|
@ -0,0 +1,739 @@
|
||||
/* 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_svp_vpath_stroke.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
#include "art_svp_intersect.h"
|
||||
#else
|
||||
#include "art_svp_wind.h"
|
||||
#endif
|
||||
#include "art_svp_vpath.h"
|
||||
|
||||
#define EPSILON 1e-6
|
||||
#define EPSILON_2 1e-12
|
||||
|
||||
#define yes_OPTIMIZE_INNER
|
||||
|
||||
/* Render an arc segment starting at (xc + x0, yc + y0) to (xc + x1,
|
||||
yc + y1), centered at (xc, yc), and with given radius. Both x0^2 +
|
||||
y0^2 and x1^2 + y1^2 should be equal to radius^2.
|
||||
|
||||
A positive value of radius means curve to the left, negative means
|
||||
curve to the right.
|
||||
*/
|
||||
static void
|
||||
art_svp_vpath_stroke_arc (ArtVpath **p_vpath, int *pn, int *pn_max,
|
||||
double xc, double yc,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double radius,
|
||||
double flatness)
|
||||
{
|
||||
double theta;
|
||||
double th_0, th_1;
|
||||
int n_pts;
|
||||
int i;
|
||||
double aradius;
|
||||
|
||||
aradius = fabs (radius);
|
||||
theta = 2 * M_SQRT2 * sqrt (flatness / aradius);
|
||||
th_0 = atan2 (y0, x0);
|
||||
th_1 = atan2 (y1, x1);
|
||||
if (radius > 0)
|
||||
{
|
||||
/* curve to the left */
|
||||
if (th_0 < th_1) th_0 += M_PI * 2;
|
||||
n_pts = ceil ((th_0 - th_1) / theta);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* curve to the right */
|
||||
if (th_1 < th_0) th_1 += M_PI * 2;
|
||||
n_pts = ceil ((th_1 - th_0) / theta);
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
printf ("start %f %f; th_0 = %f, th_1 = %f, r = %f, theta = %f\n", x0, y0, th_0, th_1, radius, theta);
|
||||
#endif
|
||||
art_vpath_add_point (p_vpath, pn, pn_max,
|
||||
ART_LINETO, xc + x0, yc + y0);
|
||||
for (i = 1; i < n_pts; i++)
|
||||
{
|
||||
theta = th_0 + (th_1 - th_0) * i / n_pts;
|
||||
art_vpath_add_point (p_vpath, pn, pn_max,
|
||||
ART_LINETO, xc + cos (theta) * aradius,
|
||||
yc + sin (theta) * aradius);
|
||||
#ifdef VERBOSE
|
||||
printf ("mid %f %f\n", cos (theta) * radius, sin (theta) * radius);
|
||||
#endif
|
||||
}
|
||||
art_vpath_add_point (p_vpath, pn, pn_max,
|
||||
ART_LINETO, xc + x1, yc + y1);
|
||||
#ifdef VERBOSE
|
||||
printf ("end %f %f\n", x1, y1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Assume that forw and rev are at point i0. Bring them to i1,
|
||||
joining with the vector i1 - i2.
|
||||
|
||||
This used to be true, but isn't now that the stroke_raw code is
|
||||
filtering out (near)zero length vectors: {It so happens that all
|
||||
invocations of this function maintain the precondition i1 = i0 + 1,
|
||||
so we could decrease the number of arguments by one. We haven't
|
||||
done that here, though.}
|
||||
|
||||
forw is to the line's right and rev is to its left.
|
||||
|
||||
Precondition: no zero-length vectors, otherwise a divide by
|
||||
zero will happen. */
|
||||
static void
|
||||
render_seg (ArtVpath **p_forw, int *pn_forw, int *pn_forw_max,
|
||||
ArtVpath **p_rev, int *pn_rev, int *pn_rev_max,
|
||||
ArtVpath *vpath, int i0, int i1, int i2,
|
||||
ArtPathStrokeJoinType join,
|
||||
double line_width, double miter_limit, double flatness)
|
||||
{
|
||||
double dx0, dy0;
|
||||
double dx1, dy1;
|
||||
double dlx0, dly0;
|
||||
double dlx1, dly1;
|
||||
double dmx, dmy;
|
||||
double dmr2;
|
||||
double scale;
|
||||
double cross;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("join style = %d\n", join);
|
||||
#endif
|
||||
|
||||
/* The vectors of the lines from i0 to i1 and i1 to i2. */
|
||||
dx0 = vpath[i1].x - vpath[i0].x;
|
||||
dy0 = vpath[i1].y - vpath[i0].y;
|
||||
|
||||
dx1 = vpath[i2].x - vpath[i1].x;
|
||||
dy1 = vpath[i2].y - vpath[i1].y;
|
||||
|
||||
/* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise
|
||||
90 degrees, and scaled to the length of line_width. */
|
||||
scale = line_width / sqrt (dx0 * dx0 + dy0 * dy0);
|
||||
dlx0 = dy0 * scale;
|
||||
dly0 = -dx0 * scale;
|
||||
|
||||
/* Set dl[xy]1 to the vector from i1 to i2, rotated counterclockwise
|
||||
90 degrees, and scaled to the length of line_width. */
|
||||
scale = line_width / sqrt (dx1 * dx1 + dy1 * dy1);
|
||||
dlx1 = dy1 * scale;
|
||||
dly1 = -dx1 * scale;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("%% render_seg: (%g, %g) - (%g, %g) - (%g, %g)\n",
|
||||
vpath[i0].x, vpath[i0].y,
|
||||
vpath[i1].x, vpath[i1].y,
|
||||
vpath[i2].x, vpath[i2].y);
|
||||
|
||||
printf ("%% render_seg: d[xy]0 = (%g, %g), dl[xy]0 = (%g, %g)\n",
|
||||
dx0, dy0, dlx0, dly0);
|
||||
|
||||
printf ("%% render_seg: d[xy]1 = (%g, %g), dl[xy]1 = (%g, %g)\n",
|
||||
dx1, dy1, dlx1, dly1);
|
||||
#endif
|
||||
|
||||
/* now, forw's last point is expected to be colinear along d[xy]0
|
||||
to point i0 - dl[xy]0, and rev with i0 + dl[xy]0. */
|
||||
|
||||
/* positive for positive area (i.e. left turn) */
|
||||
cross = dx1 * dy0 - dx0 * dy1;
|
||||
|
||||
dmx = (dlx0 + dlx1) * 0.5;
|
||||
dmy = (dly0 + dly1) * 0.5;
|
||||
dmr2 = dmx * dmx + dmy * dmy;
|
||||
|
||||
if (join == ART_PATH_STROKE_JOIN_MITER &&
|
||||
dmr2 * miter_limit * miter_limit < line_width * line_width)
|
||||
join = ART_PATH_STROKE_JOIN_BEVEL;
|
||||
|
||||
/* the case when dmr2 is zero or very small bothers me
|
||||
(i.e. near a 180 degree angle)
|
||||
ALEX: So, we avoid the optimization when dmr2 is very small. This should
|
||||
be safe since dmx/y is only used in optimization and in MITER case, and MITER
|
||||
should be converted to BEVEL when dmr2 is very small. */
|
||||
if (dmr2 > EPSILON_2)
|
||||
{
|
||||
scale = line_width * line_width / dmr2;
|
||||
dmx *= scale;
|
||||
dmy *= scale;
|
||||
}
|
||||
|
||||
if (cross * cross < EPSILON_2 && dx0 * dx1 + dy0 * dy1 >= 0)
|
||||
{
|
||||
/* going straight */
|
||||
#ifdef VERBOSE
|
||||
printf ("%% render_seg: straight\n");
|
||||
#endif
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
}
|
||||
else if (cross > 0)
|
||||
{
|
||||
/* left turn, forw is outside and rev is inside */
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("%% render_seg: left\n");
|
||||
#endif
|
||||
if (
|
||||
#ifdef NO_OPTIMIZE_INNER
|
||||
0 &&
|
||||
#endif
|
||||
(dmr2 > EPSILON_2) &&
|
||||
/* check that i1 + dm[xy] is inside i0-i1 rectangle */
|
||||
(dx0 + dmx) * dx0 + (dy0 + dmy) * dy0 > 0 &&
|
||||
/* and that i1 + dm[xy] is inside i1-i2 rectangle */
|
||||
((dx1 - dmx) * dx1 + (dy1 - dmy) * dy1 > 0)
|
||||
#ifdef PEDANTIC_INNER
|
||||
&&
|
||||
/* check that i1 + dl[xy]1 is inside i0-i1 rectangle */
|
||||
(dx0 + dlx1) * dx0 + (dy0 + dly1) * dy0 > 0 &&
|
||||
/* and that i1 + dl[xy]0 is inside i1-i2 rectangle */
|
||||
((dx1 - dlx0) * dx1 + (dy1 - dly0) * dy1 > 0)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* can safely add single intersection point */
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* need to loop-de-loop the inside */
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x, vpath[i1].y);
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1);
|
||||
}
|
||||
|
||||
if (join == ART_PATH_STROKE_JOIN_BEVEL)
|
||||
{
|
||||
/* bevel */
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1);
|
||||
}
|
||||
else if (join == ART_PATH_STROKE_JOIN_MITER)
|
||||
{
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy);
|
||||
}
|
||||
else if (join == ART_PATH_STROKE_JOIN_ROUND)
|
||||
art_svp_vpath_stroke_arc (p_forw, pn_forw, pn_forw_max,
|
||||
vpath[i1].x, vpath[i1].y,
|
||||
-dlx0, -dly0,
|
||||
-dlx1, -dly1,
|
||||
line_width,
|
||||
flatness);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* right turn, rev is outside and forw is inside */
|
||||
#ifdef VERBOSE
|
||||
printf ("%% render_seg: right\n");
|
||||
#endif
|
||||
|
||||
if (
|
||||
#ifdef NO_OPTIMIZE_INNER
|
||||
0 &&
|
||||
#endif
|
||||
(dmr2 > EPSILON_2) &&
|
||||
/* check that i1 - dm[xy] is inside i0-i1 rectangle */
|
||||
(dx0 - dmx) * dx0 + (dy0 - dmy) * dy0 > 0 &&
|
||||
/* and that i1 - dm[xy] is inside i1-i2 rectangle */
|
||||
((dx1 + dmx) * dx1 + (dy1 + dmy) * dy1 > 0)
|
||||
#ifdef PEDANTIC_INNER
|
||||
&&
|
||||
/* check that i1 - dl[xy]1 is inside i0-i1 rectangle */
|
||||
(dx0 - dlx1) * dx0 + (dy0 - dly1) * dy0 > 0 &&
|
||||
/* and that i1 - dl[xy]0 is inside i1-i2 rectangle */
|
||||
((dx1 + dlx0) * dx1 + (dy1 + dly0) * dy1 > 0)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* can safely add single intersection point */
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dmx, vpath[i1].y - dmy);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* need to loop-de-loop the inside */
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x, vpath[i1].y);
|
||||
art_vpath_add_point (p_forw, pn_forw, pn_forw_max,
|
||||
ART_LINETO, vpath[i1].x - dlx1, vpath[i1].y - dly1);
|
||||
}
|
||||
|
||||
if (join == ART_PATH_STROKE_JOIN_BEVEL)
|
||||
{
|
||||
/* bevel */
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dlx1, vpath[i1].y + dly1);
|
||||
}
|
||||
else if (join == ART_PATH_STROKE_JOIN_MITER)
|
||||
{
|
||||
art_vpath_add_point (p_rev, pn_rev, pn_rev_max,
|
||||
ART_LINETO, vpath[i1].x + dmx, vpath[i1].y + dmy);
|
||||
}
|
||||
else if (join == ART_PATH_STROKE_JOIN_ROUND)
|
||||
art_svp_vpath_stroke_arc (p_rev, pn_rev, pn_rev_max,
|
||||
vpath[i1].x, vpath[i1].y,
|
||||
dlx0, dly0,
|
||||
dlx1, dly1,
|
||||
-line_width,
|
||||
flatness);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* caps i1, under the assumption of a vector from i0 */
|
||||
static void
|
||||
render_cap (ArtVpath **p_result, int *pn_result, int *pn_result_max,
|
||||
ArtVpath *vpath, int i0, int i1,
|
||||
ArtPathStrokeCapType cap, double line_width, double flatness)
|
||||
{
|
||||
double dx0, dy0;
|
||||
double dlx0, dly0;
|
||||
double scale;
|
||||
int n_pts;
|
||||
int i;
|
||||
|
||||
dx0 = vpath[i1].x - vpath[i0].x;
|
||||
dy0 = vpath[i1].y - vpath[i0].y;
|
||||
|
||||
/* Set dl[xy]0 to the vector from i0 to i1, rotated counterclockwise
|
||||
90 degrees, and scaled to the length of line_width. */
|
||||
scale = line_width / sqrt (dx0 * dx0 + dy0 * dy0);
|
||||
dlx0 = dy0 * scale;
|
||||
dly0 = -dx0 * scale;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("cap style = %d\n", cap);
|
||||
#endif
|
||||
|
||||
switch (cap)
|
||||
{
|
||||
case ART_PATH_STROKE_CAP_BUTT:
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
break;
|
||||
case ART_PATH_STROKE_CAP_ROUND:
|
||||
n_pts = ceil (M_PI / (2.0 * M_SQRT2 * sqrt (flatness / line_width)));
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO, vpath[i1].x - dlx0, vpath[i1].y - dly0);
|
||||
for (i = 1; i < n_pts; i++)
|
||||
{
|
||||
double theta, c_th, s_th;
|
||||
|
||||
theta = M_PI * i / n_pts;
|
||||
c_th = cos (theta);
|
||||
s_th = sin (theta);
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO,
|
||||
vpath[i1].x - dlx0 * c_th - dly0 * s_th,
|
||||
vpath[i1].y - dly0 * c_th + dlx0 * s_th);
|
||||
}
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO, vpath[i1].x + dlx0, vpath[i1].y + dly0);
|
||||
break;
|
||||
case ART_PATH_STROKE_CAP_SQUARE:
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO,
|
||||
vpath[i1].x - dlx0 - dly0,
|
||||
vpath[i1].y - dly0 + dlx0);
|
||||
art_vpath_add_point (p_result, pn_result, pn_result_max,
|
||||
ART_LINETO,
|
||||
vpath[i1].x + dlx0 - dly0,
|
||||
vpath[i1].y + dly0 + dlx0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_svp_from_vpath_raw: Stroke a vector path, raw version
|
||||
* @vpath: #ArtVPath to stroke.
|
||||
* @join: Join style.
|
||||
* @cap: Cap style.
|
||||
* @line_width: Width of stroke.
|
||||
* @miter_limit: Miter limit.
|
||||
* @flatness: Flatness.
|
||||
*
|
||||
* Exactly the same as art_svp_vpath_stroke(), except that the resulting
|
||||
* stroke outline may self-intersect and have regions of winding number
|
||||
* greater than 1.
|
||||
*
|
||||
* Return value: Resulting raw stroked outline in svp format.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_svp_vpath_stroke_raw (ArtVpath *vpath,
|
||||
ArtPathStrokeJoinType join,
|
||||
ArtPathStrokeCapType cap,
|
||||
double line_width,
|
||||
double miter_limit,
|
||||
double flatness)
|
||||
{
|
||||
int begin_idx, end_idx;
|
||||
int i;
|
||||
ArtVpath *forw, *rev;
|
||||
int n_forw, n_rev;
|
||||
int n_forw_max, n_rev_max;
|
||||
ArtVpath *result;
|
||||
int n_result, n_result_max;
|
||||
double half_lw = 0.5 * line_width;
|
||||
int closed;
|
||||
int last, this, next, second;
|
||||
double dx, dy;
|
||||
|
||||
n_forw_max = 16;
|
||||
forw = art_new (ArtVpath, n_forw_max);
|
||||
|
||||
n_rev_max = 16;
|
||||
rev = art_new (ArtVpath, n_rev_max);
|
||||
|
||||
n_result = 0;
|
||||
n_result_max = 16;
|
||||
result = art_new (ArtVpath, n_result_max);
|
||||
|
||||
for (begin_idx = 0; vpath[begin_idx].code != ART_END; begin_idx = end_idx)
|
||||
{
|
||||
n_forw = 0;
|
||||
n_rev = 0;
|
||||
|
||||
closed = (vpath[begin_idx].code == ART_MOVETO);
|
||||
|
||||
/* we don't know what the first point joins with until we get to the
|
||||
last point and see if it's closed. So we start with the second
|
||||
line in the path.
|
||||
|
||||
Note: this is not strictly true (we now know it's closed from
|
||||
the opening pathcode), but why fix code that isn't broken?
|
||||
*/
|
||||
|
||||
this = begin_idx;
|
||||
/* skip over identical points at the beginning of the subpath */
|
||||
for (i = this + 1; vpath[i].code == ART_LINETO; i++)
|
||||
{
|
||||
dx = vpath[i].x - vpath[this].x;
|
||||
dy = vpath[i].y - vpath[this].y;
|
||||
if (dx * dx + dy * dy > EPSILON_2)
|
||||
break;
|
||||
}
|
||||
next = i;
|
||||
second = next;
|
||||
|
||||
/* invariant: this doesn't coincide with next */
|
||||
while (vpath[next].code == ART_LINETO)
|
||||
{
|
||||
last = this;
|
||||
this = next;
|
||||
/* skip over identical points after the beginning of the subpath */
|
||||
for (i = this + 1; vpath[i].code == ART_LINETO; i++)
|
||||
{
|
||||
dx = vpath[i].x - vpath[this].x;
|
||||
dy = vpath[i].y - vpath[this].y;
|
||||
if (dx * dx + dy * dy > EPSILON_2)
|
||||
break;
|
||||
}
|
||||
next = i;
|
||||
if (vpath[next].code != ART_LINETO)
|
||||
{
|
||||
/* reached end of path */
|
||||
/* make "closed" detection conform to PostScript
|
||||
semantics (i.e. explicit closepath code rather than
|
||||
just the fact that end of the path is the beginning) */
|
||||
if (closed &&
|
||||
vpath[this].x == vpath[begin_idx].x &&
|
||||
vpath[this].y == vpath[begin_idx].y)
|
||||
{
|
||||
int j;
|
||||
|
||||
/* path is closed, render join to beginning */
|
||||
render_seg (&forw, &n_forw, &n_forw_max,
|
||||
&rev, &n_rev, &n_rev_max,
|
||||
vpath, last, this, second,
|
||||
join, half_lw, miter_limit, flatness);
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("%% forw %d, rev %d\n", n_forw, n_rev);
|
||||
#endif
|
||||
/* do forward path */
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_MOVETO, forw[n_forw - 1].x,
|
||||
forw[n_forw - 1].y);
|
||||
for (j = 0; j < n_forw; j++)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, forw[j].x,
|
||||
forw[j].y);
|
||||
|
||||
/* do reverse path, reversed */
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_MOVETO, rev[0].x,
|
||||
rev[0].y);
|
||||
for (j = n_rev - 1; j >= 0; j--)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, rev[j].x,
|
||||
rev[j].y);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* path is open */
|
||||
int j;
|
||||
|
||||
/* add to forw rather than result to ensure that
|
||||
forw has at least one point. */
|
||||
render_cap (&forw, &n_forw, &n_forw_max,
|
||||
vpath, last, this,
|
||||
cap, half_lw, flatness);
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_MOVETO, forw[0].x,
|
||||
forw[0].y);
|
||||
for (j = 1; j < n_forw; j++)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, forw[j].x,
|
||||
forw[j].y);
|
||||
for (j = n_rev - 1; j >= 0; j--)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, rev[j].x,
|
||||
rev[j].y);
|
||||
render_cap (&result, &n_result, &n_result_max,
|
||||
vpath, second, begin_idx,
|
||||
cap, half_lw, flatness);
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, forw[0].x,
|
||||
forw[0].y);
|
||||
}
|
||||
}
|
||||
else
|
||||
render_seg (&forw, &n_forw, &n_forw_max,
|
||||
&rev, &n_rev, &n_rev_max,
|
||||
vpath, last, this, next,
|
||||
join, half_lw, miter_limit, flatness);
|
||||
}
|
||||
end_idx = next;
|
||||
}
|
||||
|
||||
art_free (forw);
|
||||
art_free (rev);
|
||||
#ifdef VERBOSE
|
||||
printf ("%% n_result = %d\n", n_result);
|
||||
#endif
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max, ART_END, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
#define noVERBOSE
|
||||
|
||||
#ifdef VERBOSE
|
||||
|
||||
#define XOFF 50
|
||||
#define YOFF 700
|
||||
|
||||
static void
|
||||
print_ps_vpath (ArtVpath *vpath)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; vpath[i].code != ART_END; i++)
|
||||
{
|
||||
switch (vpath[i].code)
|
||||
{
|
||||
case ART_MOVETO:
|
||||
printf ("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
|
||||
break;
|
||||
case ART_LINETO:
|
||||
printf ("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf ("stroke showpage\n");
|
||||
}
|
||||
|
||||
static void
|
||||
print_ps_svp (ArtSVP *vpath)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
printf ("%% begin\n");
|
||||
for (i = 0; i < vpath->n_segs; i++)
|
||||
{
|
||||
printf ("%g setgray\n", vpath->segs[i].dir ? 0.7 : 0);
|
||||
for (j = 0; j < vpath->segs[i].n_points; j++)
|
||||
{
|
||||
printf ("%g %g %s\n",
|
||||
XOFF + vpath->segs[i].points[j].x,
|
||||
YOFF - vpath->segs[i].points[j].y,
|
||||
j ? "lineto" : "moveto");
|
||||
}
|
||||
printf ("stroke\n");
|
||||
}
|
||||
|
||||
printf ("showpage\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Render a vector path into a stroked outline.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: Only miter and bevel line joins are implemented,
|
||||
and only butt line caps. Otherwise, seems to be fine.
|
||||
|
||||
Numerical stability: We cheat (adding random perturbation). Thus,
|
||||
it seems very likely that no numerical stability problems will be
|
||||
seen in practice.
|
||||
|
||||
Speed: Should be pretty good.
|
||||
|
||||
Precision: The perturbation fuzzes the coordinates slightly,
|
||||
but not enough to be visible. */
|
||||
/**
|
||||
* art_svp_vpath_stroke: Stroke a vector path.
|
||||
* @vpath: #ArtVPath to stroke.
|
||||
* @join: Join style.
|
||||
* @cap: Cap style.
|
||||
* @line_width: Width of stroke.
|
||||
* @miter_limit: Miter limit.
|
||||
* @flatness: Flatness.
|
||||
*
|
||||
* Computes an svp representing the stroked outline of @vpath. The
|
||||
* width of the stroked line is @line_width.
|
||||
*
|
||||
* Lines are joined according to the @join rule. Possible values are
|
||||
* ART_PATH_STROKE_JOIN_MITER (for mitered joins),
|
||||
* ART_PATH_STROKE_JOIN_ROUND (for round joins), and
|
||||
* ART_PATH_STROKE_JOIN_BEVEL (for bevelled joins). The mitered join
|
||||
* is converted to a bevelled join if the miter would extend to a
|
||||
* distance of more than @miter_limit * @line_width from the actual
|
||||
* join point.
|
||||
*
|
||||
* If there are open subpaths, the ends of these subpaths are capped
|
||||
* according to the @cap rule. Possible values are
|
||||
* ART_PATH_STROKE_CAP_BUTT (squared cap, extends exactly to end
|
||||
* point), ART_PATH_STROKE_CAP_ROUND (rounded half-circle centered at
|
||||
* the end point), and ART_PATH_STROKE_CAP_SQUARE (squared cap,
|
||||
* extending half @line_width past the end point).
|
||||
*
|
||||
* The @flatness parameter controls the accuracy of the rendering. It
|
||||
* is most important for determining the number of points to use to
|
||||
* approximate circular arcs for round lines and joins. In general, the
|
||||
* resulting vector path will be within @flatness pixels of the "ideal"
|
||||
* path containing actual circular arcs. I reserve the right to use
|
||||
* the @flatness parameter to convert bevelled joins to miters for very
|
||||
* small turn angles, as this would reduce the number of points in the
|
||||
* resulting outline path.
|
||||
*
|
||||
* The resulting path is "clean" with respect to self-intersections, i.e.
|
||||
* the winding number is 0 or 1 at each point.
|
||||
*
|
||||
* Return value: Resulting stroked outline in svp format.
|
||||
**/
|
||||
ArtSVP *
|
||||
art_svp_vpath_stroke (ArtVpath *vpath,
|
||||
ArtPathStrokeJoinType join,
|
||||
ArtPathStrokeCapType cap,
|
||||
double line_width,
|
||||
double miter_limit,
|
||||
double flatness)
|
||||
{
|
||||
#ifdef ART_USE_NEW_INTERSECTOR
|
||||
ArtVpath *vpath_stroke;
|
||||
ArtSVP *svp, *svp2;
|
||||
ArtSvpWriter *swr;
|
||||
|
||||
vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
|
||||
line_width, miter_limit, flatness);
|
||||
#ifdef VERBOSE
|
||||
print_ps_vpath (vpath_stroke);
|
||||
#endif
|
||||
svp = art_svp_from_vpath (vpath_stroke);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp);
|
||||
#endif
|
||||
art_free (vpath_stroke);
|
||||
|
||||
swr = art_svp_writer_rewind_new (ART_WIND_RULE_NONZERO);
|
||||
art_svp_intersector (svp, swr);
|
||||
|
||||
svp2 = art_svp_writer_rewind_reap (swr);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp2);
|
||||
#endif
|
||||
art_svp_free (svp);
|
||||
return svp2;
|
||||
#else
|
||||
ArtVpath *vpath_stroke, *vpath2;
|
||||
ArtSVP *svp, *svp2, *svp3;
|
||||
|
||||
vpath_stroke = art_svp_vpath_stroke_raw (vpath, join, cap,
|
||||
line_width, miter_limit, flatness);
|
||||
#ifdef VERBOSE
|
||||
print_ps_vpath (vpath_stroke);
|
||||
#endif
|
||||
vpath2 = art_vpath_perturb (vpath_stroke);
|
||||
#ifdef VERBOSE
|
||||
print_ps_vpath (vpath2);
|
||||
#endif
|
||||
art_free (vpath_stroke);
|
||||
svp = art_svp_from_vpath (vpath2);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp);
|
||||
#endif
|
||||
art_free (vpath2);
|
||||
svp2 = art_svp_uncross (svp);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp2);
|
||||
#endif
|
||||
art_svp_free (svp);
|
||||
svp3 = art_svp_rewind_uncrossed (svp2, ART_WIND_RULE_NONZERO);
|
||||
#ifdef VERBOSE
|
||||
print_ps_svp (svp3);
|
||||
#endif
|
||||
art_svp_free (svp2);
|
||||
|
||||
return svp3;
|
||||
#endif
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/* 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_SVP_VPATH_STROKE_H__
|
||||
#define __ART_SVP_VPATH_STROKE_H__
|
||||
|
||||
/* Sort vector paths into sorted vector paths. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#include "art_vpath.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum {
|
||||
ART_PATH_STROKE_JOIN_MITER,
|
||||
ART_PATH_STROKE_JOIN_ROUND,
|
||||
ART_PATH_STROKE_JOIN_BEVEL
|
||||
} ArtPathStrokeJoinType;
|
||||
|
||||
typedef enum {
|
||||
ART_PATH_STROKE_CAP_BUTT,
|
||||
ART_PATH_STROKE_CAP_ROUND,
|
||||
ART_PATH_STROKE_CAP_SQUARE
|
||||
} ArtPathStrokeCapType;
|
||||
|
||||
ArtSVP *
|
||||
art_svp_vpath_stroke (ArtVpath *vpath,
|
||||
ArtPathStrokeJoinType join,
|
||||
ArtPathStrokeCapType cap,
|
||||
double line_width,
|
||||
double miter_limit,
|
||||
double flatness);
|
||||
|
||||
/* This version may have winding numbers exceeding 1. */
|
||||
ArtVpath *
|
||||
art_svp_vpath_stroke_raw (ArtVpath *vpath,
|
||||
ArtPathStrokeJoinType join,
|
||||
ArtPathStrokeCapType cap,
|
||||
double line_width,
|
||||
double miter_limit,
|
||||
double flatness);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_VPATH_STROKE_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,57 @@
|
||||
/* 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_SVP_WIND_H__
|
||||
#define __ART_SVP_WIND_H__
|
||||
|
||||
/* Primitive intersection and winding number operations on sorted
|
||||
vector paths. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef ART_WIND_RULE_DEFINED
|
||||
#define ART_WIND_RULE_DEFINED
|
||||
typedef enum {
|
||||
ART_WIND_RULE_NONZERO,
|
||||
ART_WIND_RULE_INTERSECT,
|
||||
ART_WIND_RULE_ODDEVEN,
|
||||
ART_WIND_RULE_POSITIVE
|
||||
} ArtWindRule;
|
||||
#endif
|
||||
|
||||
ArtSVP *
|
||||
art_svp_uncross (ArtSVP *vp);
|
||||
|
||||
ArtSVP *
|
||||
art_svp_rewind_uncrossed (ArtSVP *vp, ArtWindRule rule);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_SVP_WIND_H__ */
|
@ -0,0 +1,88 @@
|
||||
/* 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_uta.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "art_misc.h"
|
||||
|
||||
/**
|
||||
* art_uta_new: Allocate a new uta.
|
||||
* @x0: Left coordinate of uta.
|
||||
* @y0: Top coordinate of uta.
|
||||
* @x1: Right coordinate of uta.
|
||||
* @y1: Bottom coordinate of uta.
|
||||
*
|
||||
* Allocates a new microtile array. The arguments are in units of
|
||||
* tiles, not pixels.
|
||||
*
|
||||
* Returns: the newly allocated #ArtUta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_new (int x0, int y0, int x1, int y1)
|
||||
{
|
||||
ArtUta *uta;
|
||||
|
||||
uta = art_new (ArtUta, 1);
|
||||
uta->x0 = x0;
|
||||
uta->y0 = y0;
|
||||
uta->width = x1 - x0;
|
||||
uta->height = y1 - y0;
|
||||
|
||||
uta->utiles = art_new (ArtUtaBbox, uta->width * uta->height);
|
||||
|
||||
memset (uta->utiles, 0, uta->width * uta->height * sizeof(ArtUtaBbox));
|
||||
return uta;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_uta_new_coords: Allocate a new uta, based on pixel coordinates.
|
||||
* @x0: Left coordinate of uta.
|
||||
* @y0: Top coordinate of uta.
|
||||
* @x1: Right coordinate of uta.
|
||||
* @y1: Bottom coordinate of uta.
|
||||
*
|
||||
* Allocates a new microtile array. The arguments are in pixels
|
||||
*
|
||||
* Returns: the newly allocated #ArtUta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_new_coords (int x0, int y0, int x1, int y1)
|
||||
{
|
||||
return art_uta_new (x0 >> ART_UTILE_SHIFT, y0 >> ART_UTILE_SHIFT,
|
||||
1 + (x1 >> ART_UTILE_SHIFT),
|
||||
1 + (y1 >> ART_UTILE_SHIFT));
|
||||
}
|
||||
|
||||
/**
|
||||
* art_uta_free: Free a uta.
|
||||
* @uta: The uta to free.
|
||||
*
|
||||
* Frees the microtile array structure, including the actual microtile
|
||||
* data.
|
||||
**/
|
||||
void
|
||||
art_uta_free (ArtUta *uta)
|
||||
{
|
||||
art_free (uta->utiles);
|
||||
art_free (uta);
|
||||
}
|
||||
|
||||
/* User to Aardvark! */
|
@ -0,0 +1,72 @@
|
||||
/* 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_H__
|
||||
#define __ART_UTA_H__
|
||||
|
||||
/* Basic data structures and constructors for microtile arrays */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_misc.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef art_u32 ArtUtaBbox;
|
||||
typedef struct _ArtUta ArtUta;
|
||||
|
||||
#define ART_UTA_BBOX_CONS(x0, y0, x1, y1) (((x0) << 24) | ((y0) << 16) | \
|
||||
((x1) << 8) | (y1))
|
||||
|
||||
#define ART_UTA_BBOX_X0(ub) ((ub) >> 24)
|
||||
#define ART_UTA_BBOX_Y0(ub) (((ub) >> 16) & 0xff)
|
||||
#define ART_UTA_BBOX_X1(ub) (((ub) >> 8) & 0xff)
|
||||
#define ART_UTA_BBOX_Y1(ub) ((ub) & 0xff)
|
||||
|
||||
#define ART_UTILE_SHIFT 5
|
||||
#define ART_UTILE_SIZE (1 << ART_UTILE_SHIFT)
|
||||
|
||||
/* Coordinates are shifted right by ART_UTILE_SHIFT wrt the real
|
||||
coordinates. */
|
||||
struct _ArtUta {
|
||||
int x0;
|
||||
int y0;
|
||||
int width;
|
||||
int height;
|
||||
ArtUtaBbox *utiles;
|
||||
};
|
||||
|
||||
ArtUta *
|
||||
art_uta_new (int x0, int y0, int x1, int y1);
|
||||
|
||||
ArtUta *
|
||||
art_uta_new_coords (int x0, int y0, int x1, int y1);
|
||||
|
||||
void
|
||||
art_uta_free (ArtUta *uta);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_H__ */
|
@ -0,0 +1,112 @@
|
||||
/* 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;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/* 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 */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_uta.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_uta.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtUta *
|
||||
art_uta_union (ArtUta *uta1, ArtUta *uta2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_OPS_H__ */
|
@ -0,0 +1,111 @@
|
||||
/* 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_uta_rect.h"
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_uta.h"
|
||||
#include "art_rect.h"
|
||||
|
||||
/**
|
||||
* art_uta_from_irect: Generate uta covering a rectangle.
|
||||
* @bbox: The source rectangle.
|
||||
*
|
||||
* Generates a uta exactly covering @bbox. Please do not call this
|
||||
* function with a @bbox with zero height or width.
|
||||
*
|
||||
* Return value: the new uta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_from_irect (ArtIRect *bbox)
|
||||
{
|
||||
ArtUta *uta;
|
||||
ArtUtaBbox *utiles;
|
||||
ArtUtaBbox bb;
|
||||
int width, height;
|
||||
int x, y;
|
||||
int xf0, yf0, xf1, yf1;
|
||||
int ix;
|
||||
|
||||
uta = art_new (ArtUta, 1);
|
||||
uta->x0 = bbox->x0 >> ART_UTILE_SHIFT;
|
||||
uta->y0 = bbox->y0 >> ART_UTILE_SHIFT;
|
||||
width = ((bbox->x1 + ART_UTILE_SIZE - 1) >> ART_UTILE_SHIFT) - uta->x0;
|
||||
height = ((bbox->y1 + ART_UTILE_SIZE - 1) >> ART_UTILE_SHIFT) - uta->y0;
|
||||
utiles = art_new (ArtUtaBbox, width * height);
|
||||
|
||||
uta->width = width;
|
||||
uta->height = height;
|
||||
uta->utiles = utiles;
|
||||
|
||||
xf0 = bbox->x0 & (ART_UTILE_SIZE - 1);
|
||||
yf0 = bbox->y0 & (ART_UTILE_SIZE - 1);
|
||||
xf1 = ((bbox->x1 - 1) & (ART_UTILE_SIZE - 1)) + 1;
|
||||
yf1 = ((bbox->y1 - 1) & (ART_UTILE_SIZE - 1)) + 1;
|
||||
if (height == 1)
|
||||
{
|
||||
if (width == 1)
|
||||
utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, xf1, yf1);
|
||||
else
|
||||
{
|
||||
utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, ART_UTILE_SIZE, yf1);
|
||||
bb = ART_UTA_BBOX_CONS (0, yf0, ART_UTILE_SIZE, yf1);
|
||||
for (x = 1; x < width - 1; x++)
|
||||
utiles[x] = bb;
|
||||
utiles[x] = ART_UTA_BBOX_CONS (0, yf0, xf1, yf1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (width == 1)
|
||||
{
|
||||
utiles[0] = ART_UTA_BBOX_CONS (xf0, yf0, xf1, ART_UTILE_SIZE);
|
||||
bb = ART_UTA_BBOX_CONS (xf0, 0, xf1, ART_UTILE_SIZE);
|
||||
for (y = 1; y < height - 1; y++)
|
||||
utiles[y] = bb;
|
||||
utiles[y] = ART_UTA_BBOX_CONS (xf0, 0, xf1, yf1);
|
||||
}
|
||||
else
|
||||
{
|
||||
utiles[0] =
|
||||
ART_UTA_BBOX_CONS (xf0, yf0, ART_UTILE_SIZE, ART_UTILE_SIZE);
|
||||
bb = ART_UTA_BBOX_CONS (0, yf0, ART_UTILE_SIZE, ART_UTILE_SIZE);
|
||||
for (x = 1; x < width - 1; x++)
|
||||
utiles[x] = bb;
|
||||
utiles[x] = ART_UTA_BBOX_CONS (0, yf0, xf1, ART_UTILE_SIZE);
|
||||
ix = width;
|
||||
for (y = 1; y < height - 1; y++)
|
||||
{
|
||||
utiles[ix++] =
|
||||
ART_UTA_BBOX_CONS (xf0, 0, ART_UTILE_SIZE, ART_UTILE_SIZE);
|
||||
bb = ART_UTA_BBOX_CONS (0, 0, ART_UTILE_SIZE, ART_UTILE_SIZE);
|
||||
for (x = 1; x < width - 1; x++)
|
||||
utiles[ix++] = bb;
|
||||
utiles[ix++] = ART_UTA_BBOX_CONS (0, 0, xf1, ART_UTILE_SIZE);
|
||||
}
|
||||
utiles[ix++] = ART_UTA_BBOX_CONS (xf0, 0, ART_UTILE_SIZE, yf1);
|
||||
bb = ART_UTA_BBOX_CONS (0, 0, ART_UTILE_SIZE, yf1);
|
||||
for (x = 1; x < width - 1; x++)
|
||||
utiles[ix++] = bb;
|
||||
utiles[ix++] = ART_UTA_BBOX_CONS (0, 0, xf1, yf1);
|
||||
}
|
||||
}
|
||||
return uta;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/* 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_RECT_H__
|
||||
#define __ART_UTA_RECT_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_rect.h"
|
||||
#include "art_uta.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_uta.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtUta *
|
||||
art_uta_from_irect (ArtIRect *bbox);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_RECT_H__ */
|
@ -0,0 +1,54 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* LGPL Copyright 1998 Raph Levien <raph@acm.org> */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_uta_svp.h"
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_uta.h"
|
||||
#include "art_uta_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#include "art_vpath_svp.h"
|
||||
|
||||
/**
|
||||
* art_uta_from_svp: Generate uta covering an svp.
|
||||
* @svp: The source svp.
|
||||
*
|
||||
* Generates a uta covering @svp. The resulting uta is of course
|
||||
* approximate, ie it may cover more pixels than covered by @svp.
|
||||
*
|
||||
* Note: I will want to replace this with a more direct
|
||||
* implementation. But this gets the api in place.
|
||||
*
|
||||
* Return value: the new uta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_from_svp (const ArtSVP *svp)
|
||||
{
|
||||
ArtVpath *vpath;
|
||||
ArtUta *uta;
|
||||
|
||||
vpath = art_vpath_from_svp (svp);
|
||||
uta = art_uta_from_vpath (vpath);
|
||||
art_free (vpath);
|
||||
return uta;
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/* 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_SVP_H__
|
||||
#define __ART_UTA_SVP_H__
|
||||
|
||||
/* Basic data structures and constructors for microtile arrays */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#include "art_uta.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#include <libart_lgpl/art_uta.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtUta *
|
||||
art_uta_from_svp (const ArtSVP *svp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_SVP_H__ */
|
||||
|
@ -0,0 +1,382 @@
|
||||
/* 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_vpath.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_uta.h"
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif /* MAX */
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif /* MIN */
|
||||
|
||||
/**
|
||||
* art_uta_add_line: Add a line to the uta.
|
||||
* @uta: The uta to modify.
|
||||
* @x0: X coordinate of line start point.
|
||||
* @y0: Y coordinate of line start point.
|
||||
* @x1: X coordinate of line end point.
|
||||
* @y1: Y coordinate of line end point.
|
||||
* @rbuf: Buffer containing first difference of winding number.
|
||||
* @rbuf_rowstride: Rowstride of @rbuf.
|
||||
*
|
||||
* Add the line (@x0, @y0) - (@x1, @y1) to @uta, and also update the
|
||||
* winding number buffer used for rendering the interior. @rbuf
|
||||
* contains the first partial difference (in the X direction) of the
|
||||
* winding number, measured in grid cells. Thus, each time that a line
|
||||
* crosses a horizontal uta grid line, an entry of @rbuf is
|
||||
* incremented if @y1 > @y0, decremented otherwise.
|
||||
*
|
||||
* Note that edge handling is fairly delicate. Please rtfs for
|
||||
* details.
|
||||
**/
|
||||
void
|
||||
art_uta_add_line (ArtUta *uta, double x0, double y0, double x1, double y1,
|
||||
int *rbuf, int rbuf_rowstride)
|
||||
{
|
||||
int xmin, ymin;
|
||||
double xmax, ymax;
|
||||
int xmaxf, ymaxf;
|
||||
int xmaxc, ymaxc;
|
||||
int xt0, yt0;
|
||||
int xt1, yt1;
|
||||
int xf0, yf0;
|
||||
int xf1, yf1;
|
||||
int ix, ix1;
|
||||
ArtUtaBbox bb;
|
||||
|
||||
xmin = floor (MIN(x0, x1));
|
||||
xmax = MAX(x0, x1);
|
||||
xmaxf = floor (xmax);
|
||||
xmaxc = ceil (xmax);
|
||||
ymin = floor (MIN(y0, y1));
|
||||
ymax = MAX(y0, y1);
|
||||
ymaxf = floor (ymax);
|
||||
ymaxc = ceil (ymax);
|
||||
xt0 = (xmin >> ART_UTILE_SHIFT) - uta->x0;
|
||||
yt0 = (ymin >> ART_UTILE_SHIFT) - uta->y0;
|
||||
xt1 = (xmaxf >> ART_UTILE_SHIFT) - uta->x0;
|
||||
yt1 = (ymaxf >> ART_UTILE_SHIFT) - uta->y0;
|
||||
if (xt0 == xt1 && yt0 == yt1)
|
||||
{
|
||||
/* entirely inside a microtile, this is easy! */
|
||||
xf0 = xmin & (ART_UTILE_SIZE - 1);
|
||||
yf0 = ymin & (ART_UTILE_SIZE - 1);
|
||||
xf1 = (xmaxf & (ART_UTILE_SIZE - 1)) + xmaxc - xmaxf;
|
||||
yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
|
||||
|
||||
ix = yt0 * uta->width + xt0;
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
MAX(ART_UTA_BBOX_X1(bb), xf1),
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
}
|
||||
else
|
||||
{
|
||||
double dx, dy;
|
||||
int sx, sy;
|
||||
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
sx = dx > 0 ? 1 : dx < 0 ? -1 : 0;
|
||||
sy = dy > 0 ? 1 : dy < 0 ? -1 : 0;
|
||||
if (ymin == ymaxf)
|
||||
{
|
||||
/* special case horizontal (dx/dy slope would be infinite) */
|
||||
xf0 = xmin & (ART_UTILE_SIZE - 1);
|
||||
yf0 = ymin & (ART_UTILE_SIZE - 1);
|
||||
xf1 = (xmaxf & (ART_UTILE_SIZE - 1)) + xmaxc - xmaxf;
|
||||
yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
|
||||
|
||||
ix = yt0 * uta->width + xt0;
|
||||
ix1 = yt0 * uta->width + xt1;
|
||||
while (ix != ix1)
|
||||
{
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(xf0, yf0, ART_UTILE_SIZE, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
ART_UTILE_SIZE,
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
xf0 = 0;
|
||||
ix++;
|
||||
}
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(0, yf0, xf1, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(0,
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
MAX(ART_UTA_BBOX_X1(bb), xf1),
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do a Bresenham-style traversal of the line */
|
||||
double dx_dy;
|
||||
double x, y;
|
||||
double xn, yn;
|
||||
|
||||
/* normalize coordinates to uta origin */
|
||||
x0 -= uta->x0 << ART_UTILE_SHIFT;
|
||||
y0 -= uta->y0 << ART_UTILE_SHIFT;
|
||||
x1 -= uta->x0 << ART_UTILE_SHIFT;
|
||||
y1 -= uta->y0 << ART_UTILE_SHIFT;
|
||||
if (dy < 0)
|
||||
{
|
||||
double tmp;
|
||||
|
||||
tmp = x0;
|
||||
x0 = x1;
|
||||
x1 = tmp;
|
||||
|
||||
tmp = y0;
|
||||
y0 = y1;
|
||||
y1 = tmp;
|
||||
|
||||
dx = -dx;
|
||||
sx = -sx;
|
||||
dy = -dy;
|
||||
/* we leave sy alone, because it would always be 1,
|
||||
and we need it for the rbuf stuff. */
|
||||
}
|
||||
xt0 = ((int)floor (x0) >> ART_UTILE_SHIFT);
|
||||
xt1 = ((int)floor (x1) >> ART_UTILE_SHIFT);
|
||||
/* now [xy]0 is above [xy]1 */
|
||||
|
||||
ix = yt0 * uta->width + xt0;
|
||||
ix1 = yt1 * uta->width + xt1;
|
||||
#ifdef VERBOSE
|
||||
printf ("%% ix = %d,%d; ix1 = %d,%d\n", xt0, yt0, xt1, yt1);
|
||||
#endif
|
||||
|
||||
dx_dy = dx / dy;
|
||||
x = x0;
|
||||
y = y0;
|
||||
while (ix != ix1)
|
||||
{
|
||||
int dix;
|
||||
|
||||
/* figure out whether next crossing is horizontal or vertical */
|
||||
#ifdef VERBOSE
|
||||
printf ("%% %d,%d\n", xt0, yt0);
|
||||
#endif
|
||||
yn = (yt0 + 1) << ART_UTILE_SHIFT;
|
||||
|
||||
/* xn is the intercept with bottom edge of this tile. The
|
||||
following expression is careful to result in exactly
|
||||
x1 when yn = y1. */
|
||||
xn = x1 + dx_dy * (yn - y1);
|
||||
|
||||
if (xt0 != (int)floor (xn) >> ART_UTILE_SHIFT)
|
||||
{
|
||||
/* horizontal crossing */
|
||||
xt0 += sx;
|
||||
dix = sx;
|
||||
if (dx > 0)
|
||||
{
|
||||
xn = xt0 << ART_UTILE_SHIFT;
|
||||
yn = y0 + (xn - x0) / dx_dy;
|
||||
|
||||
xf0 = (int)floor (x) & (ART_UTILE_SIZE - 1);
|
||||
xf1 = ART_UTILE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xn = (xt0 + 1) << ART_UTILE_SHIFT;
|
||||
yn = y0 + (xn - x0) / dx_dy;
|
||||
|
||||
xf0 = 0;
|
||||
xmaxc = (int)ceil (x);
|
||||
xf1 = xmaxc - ((xt0 + 1) << ART_UTILE_SHIFT);
|
||||
}
|
||||
ymaxf = (int)floor (yn);
|
||||
ymaxc = (int)ceil (yn);
|
||||
yf1 = (ymaxf & (ART_UTILE_SIZE - 1)) + ymaxc - ymaxf;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* vertical crossing */
|
||||
dix = uta->width;
|
||||
xf0 = (int)floor (MIN(x, xn)) & (ART_UTILE_SIZE - 1);
|
||||
xmax = MAX(x, xn);
|
||||
xmaxc = (int)ceil (xmax);
|
||||
xf1 = xmaxc - (xt0 << ART_UTILE_SHIFT);
|
||||
yf1 = ART_UTILE_SIZE;
|
||||
|
||||
if (rbuf != NULL)
|
||||
rbuf[yt0 * rbuf_rowstride + xt0] += sy;
|
||||
|
||||
yt0++;
|
||||
}
|
||||
yf0 = (int)floor (y) & (ART_UTILE_SIZE - 1);
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
MAX(ART_UTA_BBOX_X1(bb), xf1),
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
|
||||
x = xn;
|
||||
y = yn;
|
||||
ix += dix;
|
||||
}
|
||||
xmax = MAX(x, x1);
|
||||
xmaxc = ceil (xmax);
|
||||
ymaxc = ceil (y1);
|
||||
xf0 = (int)floor (MIN(x1, x)) & (ART_UTILE_SIZE - 1);
|
||||
yf0 = (int)floor (y) & (ART_UTILE_SIZE - 1);
|
||||
xf1 = xmaxc - (xt0 << ART_UTILE_SHIFT);
|
||||
yf1 = ymaxc - (yt0 << ART_UTILE_SHIFT);
|
||||
bb = uta->utiles[ix];
|
||||
if (bb == 0)
|
||||
bb = ART_UTA_BBOX_CONS(xf0, yf0, xf1, yf1);
|
||||
else
|
||||
bb = ART_UTA_BBOX_CONS(MIN(ART_UTA_BBOX_X0(bb), xf0),
|
||||
MIN(ART_UTA_BBOX_Y0(bb), yf0),
|
||||
MAX(ART_UTA_BBOX_X1(bb), xf1),
|
||||
MAX(ART_UTA_BBOX_Y1(bb), yf1));
|
||||
uta->utiles[ix] = bb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* art_uta_from_vpath: Generate uta covering a vpath.
|
||||
* @vec: The source vpath.
|
||||
*
|
||||
* Generates a uta covering @vec. The resulting uta is of course
|
||||
* approximate, ie it may cover more pixels than covered by @vec.
|
||||
*
|
||||
* Return value: the new uta.
|
||||
**/
|
||||
ArtUta *
|
||||
art_uta_from_vpath (const ArtVpath *vec)
|
||||
{
|
||||
ArtUta *uta;
|
||||
ArtIRect bbox;
|
||||
int *rbuf;
|
||||
int i;
|
||||
double x, y;
|
||||
int sum;
|
||||
int xt, yt;
|
||||
ArtUtaBbox *utiles;
|
||||
ArtUtaBbox bb;
|
||||
int width;
|
||||
int height;
|
||||
int ix;
|
||||
|
||||
art_vpath_bbox_irect (vec, &bbox);
|
||||
|
||||
uta = art_uta_new_coords (bbox.x0, bbox.y0, bbox.x1, bbox.y1);
|
||||
|
||||
width = uta->width;
|
||||
height = uta->height;
|
||||
utiles = uta->utiles;
|
||||
|
||||
rbuf = art_new (int, width * height);
|
||||
for (i = 0; i < width * height; i++)
|
||||
rbuf[i] = 0;
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
for (i = 0; vec[i].code != ART_END; i++)
|
||||
{
|
||||
switch (vec[i].code)
|
||||
{
|
||||
case ART_MOVETO:
|
||||
x = vec[i].x;
|
||||
y = vec[i].y;
|
||||
break;
|
||||
case ART_LINETO:
|
||||
art_uta_add_line (uta, vec[i].x, vec[i].y, x, y, rbuf, width);
|
||||
x = vec[i].x;
|
||||
y = vec[i].y;
|
||||
break;
|
||||
default:
|
||||
/* this shouldn't happen */
|
||||
art_free (rbuf);
|
||||
art_free (uta);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* now add in the filling from rbuf */
|
||||
ix = 0;
|
||||
for (yt = 0; yt < height; yt++)
|
||||
{
|
||||
sum = 0;
|
||||
for (xt = 0; xt < width; xt++)
|
||||
{
|
||||
sum += rbuf[ix];
|
||||
/* Nonzero winding rule - others are possible, but hardly
|
||||
worth it. */
|
||||
if (sum != 0)
|
||||
{
|
||||
bb = utiles[ix];
|
||||
bb &= 0xffff0000;
|
||||
bb |= (ART_UTILE_SIZE << 8) | ART_UTILE_SIZE;
|
||||
utiles[ix] = bb;
|
||||
if (xt != width - 1)
|
||||
{
|
||||
bb = utiles[ix + 1];
|
||||
bb &= 0xffff00;
|
||||
bb |= ART_UTILE_SIZE;
|
||||
utiles[ix + 1] = bb;
|
||||
}
|
||||
if (yt != height - 1)
|
||||
{
|
||||
bb = utiles[ix + width];
|
||||
bb &= 0xff0000ff;
|
||||
bb |= ART_UTILE_SIZE << 8;
|
||||
utiles[ix + width] = bb;
|
||||
if (xt != width - 1)
|
||||
{
|
||||
utiles[ix + width + 1] &= 0xffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
}
|
||||
|
||||
art_free (rbuf);
|
||||
|
||||
return uta;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/* 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_VPATH_H__
|
||||
#define __ART_UTA_VPATH_H__
|
||||
|
||||
/* Basic data structures and constructors for microtile arrays */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_uta.h"
|
||||
#include "art_vpath.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_uta.h>
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtUta *
|
||||
art_uta_from_vpath (const ArtVpath *vec);
|
||||
|
||||
/* This is a private function: */
|
||||
void
|
||||
art_uta_add_line (ArtUta *uta, double x0, double y0, double x1, double y1,
|
||||
int *rbuf, int rbuf_rowstride);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_UTA_VPATH_H__ */
|
||||
|
@ -0,0 +1,241 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Basic constructors and operations for vector paths */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_vpath.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_rect.h"
|
||||
|
||||
/**
|
||||
* art_vpath_add_point: Add point to vpath.
|
||||
* @p_vpath: Where the pointer to the #ArtVpath structure is stored.
|
||||
* @pn_points: Pointer to the number of points in *@p_vpath.
|
||||
* @pn_points_max: Pointer to the number of points allocated.
|
||||
* @code: The pathcode for the new point.
|
||||
* @x: The X coordinate of the new point.
|
||||
* @y: The Y coordinate of the new point.
|
||||
*
|
||||
* Adds a new point to *@p_vpath, reallocating and updating *@p_vpath
|
||||
* and *@pn_points_max as necessary. *@pn_points is incremented.
|
||||
*
|
||||
* This routine always adds the point after all points already in the
|
||||
* vpath. Thus, it should be called in the order the points are
|
||||
* desired.
|
||||
**/
|
||||
void
|
||||
art_vpath_add_point (ArtVpath **p_vpath, int *pn_points, int *pn_points_max,
|
||||
ArtPathcode code, double x, double y)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = (*pn_points)++;
|
||||
if (i == *pn_points_max)
|
||||
art_expand (*p_vpath, ArtVpath, *pn_points_max);
|
||||
(*p_vpath)[i].code = code;
|
||||
(*p_vpath)[i].x = x;
|
||||
(*p_vpath)[i].y = y;
|
||||
}
|
||||
|
||||
/* number of steps should really depend on radius. */
|
||||
#define CIRCLE_STEPS 128
|
||||
|
||||
/**
|
||||
* art_vpath_new_circle: Create a new circle.
|
||||
* @x: X coordinate of center.
|
||||
* @y: Y coordinate of center.
|
||||
* @r: radius.
|
||||
*
|
||||
* Creates a new polygon closely approximating a circle with center
|
||||
* (@x, @y) and radius @r. Currently, the number of points used in the
|
||||
* approximation is fixed, but that will probably change.
|
||||
*
|
||||
* Return value: The newly created #ArtVpath.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_new_circle (double x, double y, double r)
|
||||
{
|
||||
int i;
|
||||
ArtVpath *vec;
|
||||
double theta;
|
||||
|
||||
vec = art_new (ArtVpath, CIRCLE_STEPS + 2);
|
||||
|
||||
for (i = 0; i < CIRCLE_STEPS + 1; i++)
|
||||
{
|
||||
vec[i].code = i ? ART_LINETO : ART_MOVETO;
|
||||
theta = (i & (CIRCLE_STEPS - 1)) * (M_PI * 2.0 / CIRCLE_STEPS);
|
||||
vec[i].x = x + r * cos (theta);
|
||||
vec[i].y = y - r * sin (theta);
|
||||
}
|
||||
vec[i].code = ART_END;
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_vpath_affine_transform: Affine transform a vpath.
|
||||
* @src: Source vpath to transform.
|
||||
* @matrix: Affine transform.
|
||||
*
|
||||
* Computes the affine transform of the vpath, using @matrix as the
|
||||
* transform. @matrix is stored in the same format as PostScript, ie.
|
||||
* x' = @matrix[0] * x + @matrix[2] * y + @matrix[4]
|
||||
* y' = @matrix[1] * x + @matrix[3] * y + @matrix[5]
|
||||
*
|
||||
* Return value: the newly allocated vpath resulting from the transform.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_affine_transform (const ArtVpath *src, const double matrix[6])
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
ArtVpath *new;
|
||||
double x, y;
|
||||
|
||||
for (i = 0; src[i].code != ART_END; i++);
|
||||
size = i;
|
||||
|
||||
new = art_new (ArtVpath, size + 1);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
new[i].code = src[i].code;
|
||||
x = src[i].x;
|
||||
y = src[i].y;
|
||||
new[i].x = matrix[0] * x + matrix[2] * y + matrix[4];
|
||||
new[i].y = matrix[1] * x + matrix[3] * y + matrix[5];
|
||||
}
|
||||
new[i].code = ART_END;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_vpath_bbox_drect: Determine bounding box of vpath.
|
||||
* @vec: Source vpath.
|
||||
* @drect: Where to store bounding box.
|
||||
*
|
||||
* Determines bounding box of @vec, and stores it in @drect.
|
||||
**/
|
||||
void
|
||||
art_vpath_bbox_drect (const ArtVpath *vec, ArtDRect *drect)
|
||||
{
|
||||
int i;
|
||||
double x0, y0, x1, y1;
|
||||
|
||||
if (vec[0].code == ART_END)
|
||||
{
|
||||
x0 = y0 = x1 = y1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x0 = x1 = vec[0].x;
|
||||
y0 = y1 = vec[0].y;
|
||||
for (i = 1; vec[i].code != ART_END; i++)
|
||||
{
|
||||
if (vec[i].x < x0) x0 = vec[i].x;
|
||||
if (vec[i].x > x1) x1 = vec[i].x;
|
||||
if (vec[i].y < y0) y0 = vec[i].y;
|
||||
if (vec[i].y > y1) y1 = vec[i].y;
|
||||
}
|
||||
}
|
||||
drect->x0 = x0;
|
||||
drect->y0 = y0;
|
||||
drect->x1 = x1;
|
||||
drect->y1 = y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_vpath_bbox_irect: Determine integer bounding box of vpath.
|
||||
* @vec: Source vpath.
|
||||
* idrect: Where to store bounding box.
|
||||
*
|
||||
* Determines integer bounding box of @vec, and stores it in @irect.
|
||||
**/
|
||||
void
|
||||
art_vpath_bbox_irect (const ArtVpath *vec, ArtIRect *irect)
|
||||
{
|
||||
ArtDRect drect;
|
||||
|
||||
art_vpath_bbox_drect (vec, &drect);
|
||||
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;
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/* 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_VPATH_H__
|
||||
#define __ART_VPATH_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_rect.h"
|
||||
#include "art_pathcode.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_pathcode.h>
|
||||
#endif
|
||||
|
||||
/* Basic data structures and constructors for simple vector paths */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtVpath ArtVpath;
|
||||
|
||||
/* CURVETO is not allowed! */
|
||||
struct _ArtVpath {
|
||||
ArtPathcode code;
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
/* Some of the functions need to go into their own modules */
|
||||
|
||||
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 */
|
||||
|
||||
#endif /* __ART_VPATH_H__ */
|
@ -0,0 +1,328 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Basic constructors and operations for bezier paths */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_vpath_bpath.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_bpath.h"
|
||||
#include "art_vpath.h"
|
||||
|
||||
/* p must be allocated 2^level points. */
|
||||
|
||||
/* level must be >= 1 */
|
||||
ArtPoint *
|
||||
art_bezier_to_vec (double x0, double y0,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
ArtPoint *p,
|
||||
int level)
|
||||
{
|
||||
double x_m, y_m;
|
||||
|
||||
#ifdef VERBOSE
|
||||
printf ("bezier_to_vec: %g,%g %g,%g %g,%g %g,%g %d\n",
|
||||
x0, y0, x1, y1, x2, y2, x3, y3, level);
|
||||
#endif
|
||||
if (level == 1) {
|
||||
x_m = (x0 + 3 * (x1 + x2) + x3) * 0.125;
|
||||
y_m = (y0 + 3 * (y1 + y2) + y3) * 0.125;
|
||||
p->x = x_m;
|
||||
p->y = y_m;
|
||||
p++;
|
||||
p->x = x3;
|
||||
p->y = y3;
|
||||
p++;
|
||||
#ifdef VERBOSE
|
||||
printf ("-> (%g, %g) -> (%g, %g)\n", x_m, y_m, x3, y3);
|
||||
#endif
|
||||
} else {
|
||||
double xa1, ya1;
|
||||
double xa2, ya2;
|
||||
double xb1, yb1;
|
||||
double xb2, yb2;
|
||||
|
||||
xa1 = (x0 + x1) * 0.5;
|
||||
ya1 = (y0 + y1) * 0.5;
|
||||
xa2 = (x0 + 2 * x1 + x2) * 0.25;
|
||||
ya2 = (y0 + 2 * y1 + y2) * 0.25;
|
||||
xb1 = (x1 + 2 * x2 + x3) * 0.25;
|
||||
yb1 = (y1 + 2 * y2 + y3) * 0.25;
|
||||
xb2 = (x2 + x3) * 0.5;
|
||||
yb2 = (y2 + y3) * 0.5;
|
||||
x_m = (xa2 + xb1) * 0.5;
|
||||
y_m = (ya2 + yb1) * 0.5;
|
||||
#ifdef VERBOSE
|
||||
printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
|
||||
xb1, yb1, xb2, yb2);
|
||||
#endif
|
||||
p = art_bezier_to_vec (x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, p, level - 1);
|
||||
p = art_bezier_to_vec (x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, p, level - 1);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
#define RENDER_LEVEL 4
|
||||
#define RENDER_SIZE (1 << (RENDER_LEVEL))
|
||||
|
||||
/**
|
||||
* art_vpath_render_bez: Render a bezier segment into the vpath.
|
||||
* @p_vpath: Where the pointer to the #ArtVpath structure is stored.
|
||||
* @pn_points: Pointer to the number of points in *@p_vpath.
|
||||
* @pn_points_max: Pointer to the number of points allocated.
|
||||
* @x0: X coordinate of starting bezier point.
|
||||
* @y0: Y coordinate of starting bezier point.
|
||||
* @x1: X coordinate of first bezier control point.
|
||||
* @y1: Y coordinate of first bezier control point.
|
||||
* @x2: X coordinate of second bezier control point.
|
||||
* @y2: Y coordinate of second bezier control point.
|
||||
* @x3: X coordinate of ending bezier point.
|
||||
* @y3: Y coordinate of ending bezier point.
|
||||
* @flatness: Flatness control.
|
||||
*
|
||||
* Renders a bezier segment into the vector path, reallocating and
|
||||
* updating *@p_vpath and *@pn_vpath_max as necessary. *@pn_vpath is
|
||||
* incremented by the number of vector points added.
|
||||
*
|
||||
* This step includes (@x0, @y0) but not (@x3, @y3).
|
||||
*
|
||||
* The @flatness argument guides the amount of subdivision. The Adobe
|
||||
* PostScript reference manual defines flatness as the maximum
|
||||
* deviation between the any point on the vpath approximation and the
|
||||
* corresponding point on the "true" curve, and we follow this
|
||||
* definition here. A value of 0.25 should ensure high quality for aa
|
||||
* rendering.
|
||||
**/
|
||||
static void
|
||||
art_vpath_render_bez (ArtVpath **p_vpath, int *pn, int *pn_max,
|
||||
double x0, double y0,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
double flatness)
|
||||
{
|
||||
double x3_0, y3_0;
|
||||
double z3_0_dot;
|
||||
double z1_dot, z2_dot;
|
||||
double z1_perp, z2_perp;
|
||||
double max_perp_sq;
|
||||
|
||||
double x_m, y_m;
|
||||
double xa1, ya1;
|
||||
double xa2, ya2;
|
||||
double xb1, yb1;
|
||||
double xb2, yb2;
|
||||
|
||||
/* It's possible to optimize this routine a fair amount.
|
||||
|
||||
First, once the _dot conditions are met, they will also be met in
|
||||
all further subdivisions. So we might recurse to a different
|
||||
routine that only checks the _perp conditions.
|
||||
|
||||
Second, the distance _should_ decrease according to fairly
|
||||
predictable rules (a factor of 4 with each subdivision). So it might
|
||||
be possible to note that the distance is within a factor of 4 of
|
||||
acceptable, and subdivide once. But proving this might be hard.
|
||||
|
||||
Third, at the last subdivision, x_m and y_m can be computed more
|
||||
expeditiously (as in the routine above).
|
||||
|
||||
Finally, if we were able to subdivide by, say 2 or 3, this would
|
||||
allow considerably finer-grain control, i.e. fewer points for the
|
||||
same flatness tolerance. This would speed things up downstream.
|
||||
|
||||
In any case, this routine is unlikely to be the bottleneck. It's
|
||||
just that I have this undying quest for more speed...
|
||||
|
||||
*/
|
||||
|
||||
x3_0 = x3 - x0;
|
||||
y3_0 = y3 - y0;
|
||||
|
||||
/* z3_0_dot is dist z0-z3 squared */
|
||||
z3_0_dot = x3_0 * x3_0 + y3_0 * y3_0;
|
||||
|
||||
if (z3_0_dot < 0.001)
|
||||
{
|
||||
/* if start and end point are almost identical, the flatness tests
|
||||
* don't work properly, so fall back on testing whether both of
|
||||
* the other two control points are the same as the start point,
|
||||
* too.
|
||||
*/
|
||||
if (hypot(x1 - x0, y1 - y0) < 0.001
|
||||
&& hypot(x2 - x0, y2 - y0) < 0.001)
|
||||
goto nosubdivide;
|
||||
else
|
||||
goto subdivide;
|
||||
}
|
||||
|
||||
/* we can avoid subdivision if:
|
||||
|
||||
z1 has distance no more than flatness from the z0-z3 line
|
||||
|
||||
z1 is no more z0'ward than flatness past z0-z3
|
||||
|
||||
z1 is more z0'ward than z3'ward on the line traversing z0-z3
|
||||
|
||||
and correspondingly for z2 */
|
||||
|
||||
/* perp is distance from line, multiplied by dist z0-z3 */
|
||||
max_perp_sq = flatness * flatness * z3_0_dot;
|
||||
|
||||
z1_perp = (y1 - y0) * x3_0 - (x1 - x0) * y3_0;
|
||||
if (z1_perp * z1_perp > max_perp_sq)
|
||||
goto subdivide;
|
||||
|
||||
z2_perp = (y3 - y2) * x3_0 - (x3 - x2) * y3_0;
|
||||
if (z2_perp * z2_perp > max_perp_sq)
|
||||
goto subdivide;
|
||||
|
||||
z1_dot = (x1 - x0) * x3_0 + (y1 - y0) * y3_0;
|
||||
if (z1_dot < 0 && z1_dot * z1_dot > max_perp_sq)
|
||||
goto subdivide;
|
||||
|
||||
z2_dot = (x3 - x2) * x3_0 + (y3 - y2) * y3_0;
|
||||
if (z2_dot < 0 && z2_dot * z2_dot > max_perp_sq)
|
||||
goto subdivide;
|
||||
|
||||
if (z1_dot + z1_dot > z3_0_dot)
|
||||
goto subdivide;
|
||||
|
||||
if (z2_dot + z2_dot > z3_0_dot)
|
||||
goto subdivide;
|
||||
|
||||
|
||||
nosubdivide:
|
||||
/* don't subdivide */
|
||||
art_vpath_add_point (p_vpath, pn, pn_max,
|
||||
ART_LINETO, x3, y3);
|
||||
return;
|
||||
|
||||
subdivide:
|
||||
|
||||
xa1 = (x0 + x1) * 0.5;
|
||||
ya1 = (y0 + y1) * 0.5;
|
||||
xa2 = (x0 + 2 * x1 + x2) * 0.25;
|
||||
ya2 = (y0 + 2 * y1 + y2) * 0.25;
|
||||
xb1 = (x1 + 2 * x2 + x3) * 0.25;
|
||||
yb1 = (y1 + 2 * y2 + y3) * 0.25;
|
||||
xb2 = (x2 + x3) * 0.5;
|
||||
yb2 = (y2 + y3) * 0.5;
|
||||
x_m = (xa2 + xb1) * 0.5;
|
||||
y_m = (ya2 + yb1) * 0.5;
|
||||
#ifdef VERBOSE
|
||||
printf ("%g,%g %g,%g %g,%g %g,%g\n", xa1, ya1, xa2, ya2,
|
||||
xb1, yb1, xb2, yb2);
|
||||
#endif
|
||||
art_vpath_render_bez (p_vpath, pn, pn_max,
|
||||
x0, y0, xa1, ya1, xa2, ya2, x_m, y_m, flatness);
|
||||
art_vpath_render_bez (p_vpath, pn, pn_max,
|
||||
x_m, y_m, xb1, yb1, xb2, yb2, x3, y3, flatness);
|
||||
}
|
||||
|
||||
/**
|
||||
* art_bez_path_to_vec: Create vpath from bezier path.
|
||||
* @bez: Bezier path.
|
||||
* @flatness: Flatness control.
|
||||
*
|
||||
* Creates a vector path closely approximating the bezier path defined by
|
||||
* @bez. The @flatness argument controls the amount of subdivision. In
|
||||
* general, the resulting vpath deviates by at most @flatness pixels
|
||||
* from the "ideal" path described by @bez.
|
||||
*
|
||||
* Return value: Newly allocated vpath.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_bez_path_to_vec (const ArtBpath *bez, double flatness)
|
||||
{
|
||||
ArtVpath *vec;
|
||||
int vec_n, vec_n_max;
|
||||
int bez_index;
|
||||
double x, y;
|
||||
|
||||
vec_n = 0;
|
||||
vec_n_max = RENDER_SIZE;
|
||||
vec = art_new (ArtVpath, vec_n_max);
|
||||
|
||||
/* Initialization is unnecessary because of the precondition that the
|
||||
bezier path does not begin with LINETO or CURVETO, but is here
|
||||
to make the code warning-free. */
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
bez_index = 0;
|
||||
do
|
||||
{
|
||||
#ifdef VERBOSE
|
||||
printf ("%s %g %g\n",
|
||||
bez[bez_index].code == ART_CURVETO ? "curveto" :
|
||||
bez[bez_index].code == ART_LINETO ? "lineto" :
|
||||
bez[bez_index].code == ART_MOVETO ? "moveto" :
|
||||
bez[bez_index].code == ART_MOVETO_OPEN ? "moveto-open" :
|
||||
"end", bez[bez_index].x3, bez[bez_index].y3);
|
||||
#endif
|
||||
/* make sure space for at least one more code */
|
||||
if (vec_n >= vec_n_max)
|
||||
art_expand (vec, ArtVpath, vec_n_max);
|
||||
switch (bez[bez_index].code)
|
||||
{
|
||||
case ART_MOVETO_OPEN:
|
||||
case ART_MOVETO:
|
||||
case ART_LINETO:
|
||||
x = bez[bez_index].x3;
|
||||
y = bez[bez_index].y3;
|
||||
vec[vec_n].code = bez[bez_index].code;
|
||||
vec[vec_n].x = x;
|
||||
vec[vec_n].y = y;
|
||||
vec_n++;
|
||||
break;
|
||||
case ART_END:
|
||||
vec[vec_n].code = bez[bez_index].code;
|
||||
vec[vec_n].x = 0;
|
||||
vec[vec_n].y = 0;
|
||||
vec_n++;
|
||||
break;
|
||||
case ART_CURVETO:
|
||||
#ifdef VERBOSE
|
||||
printf ("%g,%g %g,%g %g,%g %g,%g\n", x, y,
|
||||
bez[bez_index].x1, bez[bez_index].y1,
|
||||
bez[bez_index].x2, bez[bez_index].y2,
|
||||
bez[bez_index].x3, bez[bez_index].y3);
|
||||
#endif
|
||||
art_vpath_render_bez (&vec, &vec_n, &vec_n_max,
|
||||
x, y,
|
||||
bez[bez_index].x1, bez[bez_index].y1,
|
||||
bez[bez_index].x2, bez[bez_index].y2,
|
||||
bez[bez_index].x3, bez[bez_index].y3,
|
||||
flatness);
|
||||
x = bez[bez_index].x3;
|
||||
y = bez[bez_index].y3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (bez[bez_index++].code != ART_END);
|
||||
return vec;
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
/* 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_VPATH_BPATH_H__
|
||||
#define __ART_VPATH_BPATH_H__
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_bpath.h"
|
||||
#include "art_vpath.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_bpath.h>
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtPoint *art_bezier_to_vec (double x0, double y0,
|
||||
double x1, double y1,
|
||||
double x2, double y2,
|
||||
double x3, double y3,
|
||||
ArtPoint *p,
|
||||
int level);
|
||||
|
||||
ArtVpath *art_bez_path_to_vec (const ArtBpath *bez, double flatness);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_VPATH_BPATH_H__ */
|
@ -0,0 +1,200 @@
|
||||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1999-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.
|
||||
*/
|
||||
|
||||
/* Apply a dash style to a vector path. */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_vpath_dash.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_vpath.h"
|
||||
|
||||
|
||||
/* Return the length of the largest subpath within vpath */
|
||||
static int
|
||||
art_vpath_dash_max_subpath (const ArtVpath *vpath)
|
||||
{
|
||||
int max_subpath;
|
||||
int i;
|
||||
int start;
|
||||
|
||||
max_subpath = 0;
|
||||
start = 0;
|
||||
for (i = 0; vpath[i].code != ART_END; i++)
|
||||
{
|
||||
if (vpath[i].code == ART_MOVETO || vpath[i].code == ART_MOVETO_OPEN)
|
||||
{
|
||||
if (i - start > max_subpath)
|
||||
max_subpath = i - start;
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
if (i - start > max_subpath)
|
||||
max_subpath = i - start;
|
||||
|
||||
return max_subpath;
|
||||
}
|
||||
|
||||
/**
|
||||
* art_vpath_dash: Add dash style to vpath.
|
||||
* @vpath: Original vpath.
|
||||
* @dash: Dash style.
|
||||
*
|
||||
* Creates a new vpath that is the result of applying dash style @dash
|
||||
* to @vpath.
|
||||
*
|
||||
* This implementation has two known flaws:
|
||||
*
|
||||
* First, it adds a spurious break at the beginning of the vpath. The
|
||||
* only way I see to resolve this flaw is to run the state forward one
|
||||
* dash break at the beginning, and fix up by looping back to the
|
||||
* first dash break at the end. This is doable but of course adds some
|
||||
* complexity.
|
||||
*
|
||||
* Second, it does not suppress output points that are within epsilon
|
||||
* of each other.
|
||||
*
|
||||
* Return value: Newly created vpath.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_dash (const ArtVpath *vpath, const ArtVpathDash *dash)
|
||||
{
|
||||
int max_subpath;
|
||||
double *dists;
|
||||
ArtVpath *result;
|
||||
int n_result, n_result_max;
|
||||
int start, end;
|
||||
int i;
|
||||
double total_dist;
|
||||
|
||||
/* state while traversing dasharray - offset is offset of current dash
|
||||
value, toggle is 0 for "off" and 1 for "on", and phase is the distance
|
||||
in, >= 0, < dash->dash[offset]. */
|
||||
int offset, toggle;
|
||||
double phase;
|
||||
|
||||
/* initial values */
|
||||
int offset_init, toggle_init;
|
||||
double phase_init;
|
||||
|
||||
max_subpath = art_vpath_dash_max_subpath (vpath);
|
||||
dists = art_new (double, max_subpath);
|
||||
|
||||
n_result = 0;
|
||||
n_result_max = 16;
|
||||
result = art_new (ArtVpath, n_result_max);
|
||||
|
||||
/* determine initial values of dash state */
|
||||
toggle_init = 1;
|
||||
offset_init = 0;
|
||||
phase_init = dash->offset;
|
||||
while (phase_init >= dash->dash[offset_init])
|
||||
{
|
||||
toggle_init = !toggle_init;
|
||||
phase_init -= dash->dash[offset_init];
|
||||
offset_init++;
|
||||
if (offset_init == dash->n_dash)
|
||||
offset_init = 0;
|
||||
}
|
||||
|
||||
for (start = 0; vpath[start].code != ART_END; start = end)
|
||||
{
|
||||
for (end = start + 1; vpath[end].code == ART_LINETO; end++);
|
||||
/* subpath is [start..end) */
|
||||
total_dist = 0;
|
||||
for (i = start; i < end - 1; i++)
|
||||
{
|
||||
double dx, dy;
|
||||
|
||||
dx = vpath[i + 1].x - vpath[i].x;
|
||||
dy = vpath[i + 1].y - vpath[i].y;
|
||||
dists[i - start] = sqrt (dx * dx + dy * dy);
|
||||
total_dist += dists[i - start];
|
||||
}
|
||||
if (total_dist <= dash->dash[offset_init] - phase_init)
|
||||
{
|
||||
/* subpath fits entirely within first dash */
|
||||
if (toggle_init)
|
||||
{
|
||||
for (i = start; i < end; i++)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
vpath[i].code, vpath[i].x, vpath[i].y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* subpath is composed of at least one dash - thus all
|
||||
generated pieces are open */
|
||||
double dist;
|
||||
|
||||
phase = phase_init;
|
||||
offset = offset_init;
|
||||
toggle = toggle_init;
|
||||
dist = 0;
|
||||
i = start;
|
||||
if (toggle)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_MOVETO_OPEN, vpath[i].x, vpath[i].y);
|
||||
while (i != end - 1)
|
||||
{
|
||||
if (dists[i - start] - dist > dash->dash[offset] - phase)
|
||||
{
|
||||
/* dash boundary is next */
|
||||
double a;
|
||||
double x, y;
|
||||
|
||||
dist += dash->dash[offset] - phase;
|
||||
a = dist / dists[i - start];
|
||||
x = vpath[i].x + a * (vpath[i + 1].x - vpath[i].x);
|
||||
y = vpath[i].y + a * (vpath[i + 1].y - vpath[i].y);
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
toggle ? ART_LINETO : ART_MOVETO_OPEN,
|
||||
x, y);
|
||||
/* advance to next dash */
|
||||
toggle = !toggle;
|
||||
phase = 0;
|
||||
offset++;
|
||||
if (offset == dash->n_dash)
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* end of line in vpath is next */
|
||||
phase += dists[i - start] - dist;
|
||||
i++;
|
||||
dist = 0;
|
||||
if (toggle)
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_LINETO, vpath[i].x, vpath[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
art_vpath_add_point (&result, &n_result, &n_result_max,
|
||||
ART_END, 0, 0);
|
||||
|
||||
art_free (dists);
|
||||
|
||||
return result;
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1999 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_VPATH_DASH_H__
|
||||
#define __ART_VPATH_DASH_H__
|
||||
|
||||
/* Apply a dash style to a vector path. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_vpath.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct _ArtVpathDash ArtVpathDash;
|
||||
|
||||
struct _ArtVpathDash {
|
||||
double offset;
|
||||
int n_dash;
|
||||
double *dash;
|
||||
};
|
||||
|
||||
ArtVpath *
|
||||
art_vpath_dash (const ArtVpath *vpath, const ArtVpathDash *dash);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_VPATH_DASH_H__ */
|
@ -0,0 +1,196 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* "Unsort" a sorted vector path into an ordinary vector path. */
|
||||
|
||||
#include "config.h"
|
||||
#include "art_vpath_svp.h"
|
||||
|
||||
#include <stdio.h> /* for printf - debugging */
|
||||
#include "art_misc.h"
|
||||
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp.h"
|
||||
|
||||
typedef struct _ArtVpathSVPEnd ArtVpathSVPEnd;
|
||||
|
||||
struct _ArtVpathSVPEnd {
|
||||
int seg_num;
|
||||
int which; /* 0 = top, 1 = bottom */
|
||||
double x, y;
|
||||
};
|
||||
|
||||
#define EPSILON 1e-6
|
||||
|
||||
static int
|
||||
art_vpath_svp_point_compare (double x1, double y1, double x2, double y2)
|
||||
{
|
||||
if (y1 - EPSILON > y2) return 1;
|
||||
if (y1 + EPSILON < y2) return -1;
|
||||
if (x1 - EPSILON > x2) return 1;
|
||||
if (x1 + EPSILON < x2) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
art_vpath_svp_compare (const void *s1, const void *s2)
|
||||
{
|
||||
const ArtVpathSVPEnd *e1 = s1;
|
||||
const ArtVpathSVPEnd *e2 = s2;
|
||||
|
||||
return art_vpath_svp_point_compare (e1->x, e1->y, e2->x, e2->y);
|
||||
}
|
||||
|
||||
/* Convert from sorted vector path representation into regular
|
||||
vector path representation.
|
||||
|
||||
Status of this routine:
|
||||
|
||||
Basic correctness: Only works with closed paths.
|
||||
|
||||
Numerical stability: Not known to work when more than two segments
|
||||
meet at a point.
|
||||
|
||||
Speed: Should be pretty good.
|
||||
|
||||
Precision: Does not degrade precision.
|
||||
|
||||
*/
|
||||
/**
|
||||
* art_vpath_from_svp: Convert from svp to vpath form.
|
||||
* @svp: Original #ArtSVP.
|
||||
*
|
||||
* Converts the sorted vector path @svp into standard vpath form.
|
||||
*
|
||||
* Return value: the newly allocated vpath.
|
||||
**/
|
||||
ArtVpath *
|
||||
art_vpath_from_svp (const ArtSVP *svp)
|
||||
{
|
||||
int n_segs = svp->n_segs;
|
||||
ArtVpathSVPEnd *ends;
|
||||
ArtVpath *new;
|
||||
int *visited;
|
||||
int n_new, n_new_max;
|
||||
int i, k;
|
||||
int j = 0; /* Quiet compiler */
|
||||
int seg_num;
|
||||
int first;
|
||||
double last_x, last_y;
|
||||
int n_points;
|
||||
int pt_num;
|
||||
|
||||
last_x = 0; /* to eliminate "uninitialized" warning */
|
||||
last_y = 0;
|
||||
|
||||
ends = art_new (ArtVpathSVPEnd, n_segs * 2);
|
||||
for (i = 0; i < svp->n_segs; i++)
|
||||
{
|
||||
int lastpt;
|
||||
|
||||
ends[i * 2].seg_num = i;
|
||||
ends[i * 2].which = 0;
|
||||
ends[i * 2].x = svp->segs[i].points[0].x;
|
||||
ends[i * 2].y = svp->segs[i].points[0].y;
|
||||
|
||||
lastpt = svp->segs[i].n_points - 1;
|
||||
ends[i * 2 + 1].seg_num = i;
|
||||
ends[i * 2 + 1].which = 1;
|
||||
ends[i * 2 + 1].x = svp->segs[i].points[lastpt].x;
|
||||
ends[i * 2 + 1].y = svp->segs[i].points[lastpt].y;
|
||||
}
|
||||
qsort (ends, n_segs * 2, sizeof (ArtVpathSVPEnd), art_vpath_svp_compare);
|
||||
|
||||
n_new = 0;
|
||||
n_new_max = 16; /* I suppose we _could_ estimate this from traversing
|
||||
the svp, so we don't have to reallocate */
|
||||
new = art_new (ArtVpath, n_new_max);
|
||||
|
||||
visited = art_new (int, n_segs);
|
||||
for (i = 0; i < n_segs; i++)
|
||||
visited[i] = 0;
|
||||
|
||||
first = 1;
|
||||
for (i = 0; i < n_segs; i++)
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
/* search for the continuation of the existing subpath */
|
||||
/* This could be a binary search (which is why we sorted, above) */
|
||||
for (j = 0; j < n_segs * 2; j++)
|
||||
{
|
||||
if (!visited[ends[j].seg_num] &&
|
||||
art_vpath_svp_point_compare (last_x, last_y,
|
||||
ends[j].x, ends[j].y) == 0)
|
||||
break;
|
||||
}
|
||||
if (j == n_segs * 2)
|
||||
first = 1;
|
||||
}
|
||||
if (first)
|
||||
{
|
||||
/* start a new subpath */
|
||||
for (j = 0; j < n_segs * 2; j++)
|
||||
if (!visited[ends[j].seg_num])
|
||||
break;
|
||||
}
|
||||
if (j == n_segs * 2)
|
||||
{
|
||||
printf ("failure\n");
|
||||
}
|
||||
seg_num = ends[j].seg_num;
|
||||
n_points = svp->segs[seg_num].n_points;
|
||||
for (k = 0; k < n_points; k++)
|
||||
{
|
||||
pt_num = svp->segs[seg_num].dir ? k : n_points - (1 + k);
|
||||
if (k == 0)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
art_vpath_add_point (&new, &n_new, &n_new_max,
|
||||
ART_MOVETO,
|
||||
svp->segs[seg_num].points[pt_num].x,
|
||||
svp->segs[seg_num].points[pt_num].y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
art_vpath_add_point (&new, &n_new, &n_new_max,
|
||||
ART_LINETO,
|
||||
svp->segs[seg_num].points[pt_num].x,
|
||||
svp->segs[seg_num].points[pt_num].y);
|
||||
if (k == n_points - 1)
|
||||
{
|
||||
last_x = svp->segs[seg_num].points[pt_num].x;
|
||||
last_y = svp->segs[seg_num].points[pt_num].y;
|
||||
/* to make more robust, check for meeting first_[xy],
|
||||
set first if so */
|
||||
}
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
visited[seg_num] = 1;
|
||||
}
|
||||
|
||||
art_vpath_add_point (&new, &n_new, &n_new_max,
|
||||
ART_END, 0, 0);
|
||||
art_free (visited);
|
||||
art_free (ends);
|
||||
return new;
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/* 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_VPATH_SVP_H__
|
||||
#define __ART_VPATH_SVP_H__
|
||||
|
||||
/* "Unsort" a sorted vector path into an ordinary vector path. */
|
||||
|
||||
#ifdef LIBART_COMPILATION
|
||||
#include "art_svp.h"
|
||||
#include "art_vpath.h"
|
||||
#else
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
ArtVpath *art_vpath_from_svp (const ArtSVP *svp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __ART_VPATH_SVP_H__ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,109 @@
|
||||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define if building universal (internal helper macro) */
|
||||
#undef AC_APPLE_UNIVERSAL_BUILD
|
||||
|
||||
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
|
||||
systems. This function is required for `alloca.c' support on those systems.
|
||||
*/
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define to 1 if using `alloca.c'. */
|
||||
#undef C_ALLOCA
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
#undef HAVE_ALLOCA
|
||||
|
||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
|
||||
*/
|
||||
#undef HAVE_ALLOCA_H
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* The size of `char', as computed by sizeof. */
|
||||
#undef SIZEOF_CHAR
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#undef SIZEOF_INT
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#undef SIZEOF_LONG
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#undef SIZEOF_SHORT
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at runtime.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
#undef STACK_DIRECTION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#if defined AC_APPLE_UNIVERSAL_BUILD
|
||||
# if defined __BIG_ENDIAN__
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef WORDS_BIGENDIAN
|
||||
# undef WORDS_BIGENDIAN
|
||||
# endif
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,114 @@
|
||||
m4_define([libart_major_version], [2])
|
||||
m4_define([libart_minor_version], [3])
|
||||
m4_define([libart_micro_version], [21])
|
||||
m4_define([libart_version],
|
||||
[libart_major_version.libart_minor_version.libart_micro_version])
|
||||
|
||||
AC_INIT([libart-lgpl],[libart_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libart],[libart_lgpl])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
LIBART_MAJOR_VERSION=libart_major_version
|
||||
LIBART_MINOR_VERSION=libart_minor_version
|
||||
LIBART_MICRO_VERSION=libart_micro_version
|
||||
LIBART_VERSION=libart_version
|
||||
|
||||
LIBART_VERSION_INFO=`expr $LIBART_MAJOR_VERSION + $LIBART_MINOR_VERSION`:$LIBART_MICRO_VERSION:$LIBART_MINOR_VERSION
|
||||
|
||||
AC_SUBST(LIBART_MAJOR_VERSION)
|
||||
AC_SUBST(LIBART_MINOR_VERSION)
|
||||
AC_SUBST(LIBART_MICRO_VERSION)
|
||||
AC_SUBST(LIBART_VERSION)
|
||||
AC_SUBST(LIBART_VERSION_INFO)
|
||||
|
||||
AM_INIT_AUTOMAKE([1.9 foreign no-dist-gzip dist-bzip2])
|
||||
|
||||
AC_ARG_ENABLE(ansi, [ --enable-ansi turn on strict ansi [default=no]],
|
||||
, enable_ansi=no)
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_MSG_CHECKING([for some Win32 platform])
|
||||
case "$host" in
|
||||
*-*-mingw*|*-*-cygwin*)
|
||||
platform_win32=yes
|
||||
;;
|
||||
*)
|
||||
platform_win32=no
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$platform_win32])
|
||||
AM_CONDITIONAL(PLATFORM_WIN32, test "$platform_win32" = "yes")
|
||||
|
||||
AC_MSG_CHECKING([for native Win32])
|
||||
case "$host" in
|
||||
*-*-mingw*)
|
||||
os_win32=yes
|
||||
;;
|
||||
*)
|
||||
os_win32=no
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$os_win32])
|
||||
AM_CONDITIONAL(OS_WIN32, test "$os_win32" = "yes")
|
||||
|
||||
if test "$os_win32" = "yes"; then
|
||||
AC_CHECK_PROG(ms_librarian, lib.exe, yes, no)
|
||||
fi
|
||||
AM_CONDITIONAL(MS_LIB_AVAILABLE, test x$ms_librarian = xyes)
|
||||
|
||||
changequote(,)dnl
|
||||
if test "x$GCC" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wall[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wall" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
|
||||
esac
|
||||
|
||||
if test "x$enable_ansi" = "xyes"; then
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-ansi[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -ansi" ;;
|
||||
esac
|
||||
|
||||
case " $CFLAGS " in
|
||||
*[\ \ ]-pedantic[\ \ ]*) ;;
|
||||
*) CFLAGS="$CFLAGS -pedantic" ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
changequote([,])dnl
|
||||
|
||||
AC_FUNC_ALLOCA
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
AC_CHECK_SIZEOF(char)
|
||||
AC_SUBST(ART_SIZEOF_CHAR, $ac_cv_sizeof_char)
|
||||
AC_CHECK_SIZEOF(short)
|
||||
AC_SUBST(ART_SIZEOF_SHORT, $ac_cv_sizeof_short)
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_SUBST(ART_SIZEOF_INT, $ac_cv_sizeof_int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_SUBST(ART_SIZEOF_LONG, $ac_cv_sizeof_long)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
libart-features.h
|
||||
Makefile
|
||||
libart-2.0.pc
|
||||
libart-2.0-uninstalled.pc
|
||||
libart-zip])
|
||||
|
||||
AC_CONFIG_FILES([libart-config],[chmod +x libart-config])
|
||||
AC_CONFIG_FILES([gen_art_config.sh],[chmod +x gen_art_config.sh])
|
||||
|
||||
AC_OUTPUT
|
@ -0,0 +1,246 @@
|
||||
libart-lgpl (2.3.21-1) unstable; urgency=low
|
||||
|
||||
[ Loic Minier ]
|
||||
* Properly anchor package name regexp.
|
||||
|
||||
[ Sebastian Dröge ]
|
||||
* New upstream bugfix release:
|
||||
+ debian/control.in:
|
||||
- Update Standards-Version and build-depend on autotools-dev.
|
||||
+ debian/patches/70_relibtoolize.patch:
|
||||
- Regenerated for the new version.
|
||||
|
||||
-- Sebastian Dröge <slomo@debian.org> Sun, 25 Apr 2010 11:35:30 +0200
|
||||
|
||||
libart-lgpl (2.3.20-2) unstable; urgency=low
|
||||
|
||||
* Let libart-2.0-dev depend on shlibs:Depends.
|
||||
* Extract library package name from control instead of hardcoding it in
|
||||
rules.
|
||||
* New patch, 60_libart-config-static, adds --static flag to libart2-config
|
||||
to avoid -lm in the output of --libs; please consider switching to
|
||||
pkg-config instead; GNOME #531278; closes: #375812.
|
||||
* Fix copyright to state LGPL 2 or later as checked with licensecheck;
|
||||
thanks Thomas Viehmann; closes: #478766.
|
||||
|
||||
-- Loic Minier <lool@dooz.org> Sat, 03 May 2008 22:21:18 +0200
|
||||
|
||||
libart-lgpl (2.3.20-1) unstable; urgency=low
|
||||
|
||||
[ Kilian Krause ]
|
||||
* Use binary:version and source:Version for binNMU-safe uploads as
|
||||
added in dpkg-dev 1.13.19. Add to Build-Depends accordingly.
|
||||
|
||||
[ Sebastian Dröge ]
|
||||
* New upstream bugfix release:
|
||||
+ debian/patches/90_fix-headers-for-cplusplus.patch:
|
||||
- Dropped, merged upstream.
|
||||
+ debian/patches/70_relibtoolize.patch:
|
||||
- Regenerated for the new version.
|
||||
* debian/control.in:
|
||||
+ Update Standards-Version to 3.7.3, no additional changes needed.
|
||||
|
||||
-- Sebastian Dröge <slomo@debian.org> Wed, 30 Jan 2008 13:38:26 +0100
|
||||
|
||||
libart-lgpl (2.3.19-3) unstable; urgency=low
|
||||
|
||||
* Upload to unstable; drop check-dist include.
|
||||
* Wrap build-deps and deps.
|
||||
* Drop libc6-dev dep in libart-2.0-dev.
|
||||
* Add ${misc:Depends}.
|
||||
|
||||
-- Loic Minier <lool@dooz.org> Wed, 11 Apr 2007 16:23:30 +0200
|
||||
|
||||
libart-lgpl (2.3.19-2) experimental; urgency=high
|
||||
|
||||
* Use clean-la.mk and require gnome-pkg-tools 0.7.
|
||||
* New patch, 90_fix-headers-for-cplusplus.patch, fixes linking with C++
|
||||
applications; GNOME #413197; SVN r278; closes: #417568.
|
||||
* Rename patch 070_relibtoolize to 70_relibtoolize.
|
||||
|
||||
-- Loic Minier <lool@dooz.org> Tue, 03 Apr 2007 15:23:09 +0200
|
||||
|
||||
libart-lgpl (2.3.19-1) experimental; urgency=low
|
||||
|
||||
* Add a get-orig-source target to retrieve the upstream tarball.
|
||||
* Add complete licensing information in copyright file.
|
||||
* Update upstream URL in copyright file.
|
||||
* Bump up Standards-Version to 3.7.2.
|
||||
* Use debian/libart-2.0-dev.manpages instead of
|
||||
DEB_INSTALL_MANPAGES_libart-2.0-dev.
|
||||
* Use HTTP in watch file and track all branches.
|
||||
* Include CDBS's utils.
|
||||
* New upstream releases with API additions.
|
||||
- Include the new check-dist Makefile to prevent accidental uploads to
|
||||
unstable; bump build-dep on gnome-pkg-tools to >= 0.10.
|
||||
- Set shlibs to >= 2.3.18.
|
||||
- Update and rename relibtoolizing patch, 070_relibtoolize.
|
||||
* Drop useless libart-2.0-dev.files.
|
||||
* Drop build-dep on libc6-dev | libc-dev; doh.
|
||||
* Bump up DebHelper compatibility level to 5.
|
||||
|
||||
-- Loic Minier <lool@dooz.org> Wed, 28 Feb 2007 15:20:45 +0100
|
||||
|
||||
libart-lgpl (2.3.17-1) unstable; urgency=low
|
||||
|
||||
* GNOME Team Upload.
|
||||
* New upstream release.
|
||||
* debian/patches/001_relibtoolize.patch:
|
||||
- updated.
|
||||
* debian/watch:
|
||||
- added.
|
||||
|
||||
-- Sebastien Bacher <seb128@debian.org> Tue, 25 Jan 2005 23:51:07 +0100
|
||||
|
||||
libart-lgpl (2.3.16-6) unstable; urgency=low
|
||||
|
||||
* Relibtoolize (Closes: #260639)
|
||||
|
||||
-- Ondřej Surý <ondrej@debian.org> Wed, 21 Jul 2004 17:27:15 +0200
|
||||
|
||||
libart-lgpl (2.3.16-5) unstable; urgency=low
|
||||
|
||||
* Set shlibs version to current.
|
||||
|
||||
-- Ondřej Surý <ondrej@debian.org> Mon, 19 Apr 2004 18:49:50 +0200
|
||||
|
||||
libart-lgpl (2.3.16-4) unstable; urgency=low
|
||||
|
||||
* Gnome Team upload.
|
||||
* Setting again the shlibs file.
|
||||
|
||||
-- Sebastien Bacher <seb128@debian.org> Thu, 15 Apr 2004 19:35:09 +0200
|
||||
|
||||
libart-lgpl (2.3.16-3) unstable; urgency=low
|
||||
|
||||
* New maintainer (Closes: #238891)
|
||||
|
||||
-- Ondřej Surý <ondrej@debian.org> Sat, 20 Mar 2004 15:14:54 +0100
|
||||
|
||||
libart-lgpl (2.3.16-2) unstable; urgency=low
|
||||
|
||||
* Orphaned package.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Fri, 19 Mar 2004 16:06:24 +0100
|
||||
|
||||
libart-lgpl (2.3.16-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Fix an "assertion failed" who crash gdm (Closes: #208919)
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Wed, 10 Sep 2003 09:48:22 +0200
|
||||
|
||||
libart-lgpl (2.3.15-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Tue, 2 Sep 2003 14:14:16 +0200
|
||||
|
||||
libart-lgpl (2.3.14-2) unstable; urgency=low
|
||||
|
||||
* Compiled with -mieee for alpha (Closes: #207748)
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Fri, 29 Aug 2003 19:24:46 +0200
|
||||
|
||||
libart-lgpl (2.3.14-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Fri, 8 Aug 2003 10:23:11 +0200
|
||||
|
||||
libart-lgpl (2.3.13-1) unstable; urgency=low
|
||||
|
||||
* new upstream release.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Fri, 11 Jul 2003 14:59:55 +0200
|
||||
|
||||
libart-lgpl (2.3.12-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Mon, 5 May 2003 12:58:07 +0200
|
||||
|
||||
libart-lgpl (2.3.11-4) unstable; urgency=low
|
||||
|
||||
* Update section
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Tue, 1 Apr 2003 18:52:25 +0200
|
||||
|
||||
libart-lgpl (2.3.11-3) unstable; urgency=low
|
||||
|
||||
* Add a patche to fix configure for mipsel
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Sat, 18 Jan 2003 10:11:41 +0100
|
||||
|
||||
libart-lgpl (2.3.11-2) unstable; urgency=low
|
||||
|
||||
* Update description (Closes: #177003)
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Fri, 17 Jan 2003 21:27:15 +0100
|
||||
|
||||
libart-lgpl (2.3.11-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
* Bump Standards-Version to 3.5.8
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Tue, 7 Jan 2003 19:40:48 +0100
|
||||
|
||||
libart-lgpl (2.3.10-4) unstable; urgency=low
|
||||
|
||||
* Update to standards version 3.5.7
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Sat, 21 Sep 2002 14:41:00 +0200
|
||||
|
||||
libart-lgpl (2.3.10-3) unstable; urgency=low
|
||||
|
||||
* Replace libc6-dev by libc-dev for -dev package.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Thu, 5 Sep 2002 18:25:28 +0200
|
||||
|
||||
libart-lgpl (2.3.10-2) unstable; urgency=low
|
||||
|
||||
* Move libc6-dev dependency in the -dev package.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Thu, 8 Aug 2002 14:34:51 +0200
|
||||
|
||||
libart-lgpl (2.3.10-1) unstable; urgency=low
|
||||
|
||||
* New upstream release (Closes: #151622)
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Tue, 2 Jul 2002 01:38:03 +0200
|
||||
|
||||
libart-lgpl (2.3.9-2) unstable; urgency=low
|
||||
|
||||
* debian/control add a versioned dependency for the -dev package
|
||||
(Closes: #151369)
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Sat, 29 Jun 2002 17:39:39 +0200
|
||||
|
||||
libart-lgpl (2.3.9-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Tue, 25 Jun 2002 10:26:05 +0200
|
||||
|
||||
libart-lgpl (2.3.8-2) unstable; urgency=low
|
||||
|
||||
* Add support for DEB_HOST_GNU_TYPE DEB_BUILD_GNU_TYPE and
|
||||
DEB_BUILD_OPTIONS
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Wed, 15 May 2002 22:28:40 +0200
|
||||
|
||||
libart-lgpl (2.3.8-1) unstable; urgency=low
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Mon, 14 Jan 2002 10:58:19 +0100
|
||||
|
||||
libart-lgpl (2.3.7-1) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
-- Christian Marillat <marillat@debian.org> Mon, 19 Nov 2001 18:29:06 +0100
|
||||
|
||||
Local variables:
|
||||
mode: debian-changelog
|
||||
End:
|
@ -0,0 +1 @@
|
||||
5
|
@ -0,0 +1,42 @@
|
||||
# This file is autogenerated. DO NOT EDIT!
|
||||
#
|
||||
# Modifications should be made to debian/control.in instead.
|
||||
# This file is regenerated automatically in the clean target.
|
||||
|
||||
Source: libart-lgpl
|
||||
Section: devel
|
||||
Priority: optional
|
||||
Maintainer: Josselin Mouette <joss@debian.org>
|
||||
Uploaders: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>, Loic Minier <lool@dooz.org>, Sebastian Dröge <slomo@debian.org>, Sebastien Bacher <seb128@debian.org>
|
||||
Standards-Version: 3.8.4
|
||||
Build-Depends: debhelper (>= 5),
|
||||
gnome-pkg-tools (>= 0.7),
|
||||
cdbs,
|
||||
dpkg-dev (>= 1.13.19),
|
||||
autotools-dev
|
||||
|
||||
Package: libart-2.0-2
|
||||
Architecture: any
|
||||
Section: libs
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Description: Library of functions for 2D graphics - runtime files
|
||||
A library of functions for 2D graphics supporting a superset of the
|
||||
PostScript imaging model, designed to be integrated with graphics, artwork,
|
||||
and illustration programs. It is written in optimized C, and is fully
|
||||
compatible with C++. With a small footprint of 10,000 lines of code, it is
|
||||
especially suitable for embedded applications.
|
||||
|
||||
Package: libart-2.0-dev
|
||||
Architecture: any
|
||||
Section: libdevel
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
libart-2.0-2 (= ${binary:Version}),
|
||||
pkg-config
|
||||
Description: Library of functions for 2D graphics - development files
|
||||
A library of functions for 2D graphics supporting a superset of the
|
||||
PostScript imaging model, designed to be integrated with graphics, artwork,
|
||||
and illustration programs. It is written in optimized C, and is fully
|
||||
compatible with C++. With a small footprint of 10,000 lines of code, it is
|
||||
especially suitable for embedded applications.
|
@ -0,0 +1,37 @@
|
||||
Source: libart-lgpl
|
||||
Section: devel
|
||||
Priority: optional
|
||||
Maintainer: Josselin Mouette <joss@debian.org>
|
||||
Uploaders: @GNOME_TEAM@
|
||||
Standards-Version: 3.8.4
|
||||
Build-Depends: debhelper (>= 5),
|
||||
gnome-pkg-tools (>= 0.7),
|
||||
cdbs,
|
||||
dpkg-dev (>= 1.13.19),
|
||||
autotools-dev
|
||||
|
||||
Package: libart-2.0-2
|
||||
Architecture: any
|
||||
Section: libs
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Description: Library of functions for 2D graphics - runtime files
|
||||
A library of functions for 2D graphics supporting a superset of the
|
||||
PostScript imaging model, designed to be integrated with graphics, artwork,
|
||||
and illustration programs. It is written in optimized C, and is fully
|
||||
compatible with C++. With a small footprint of 10,000 lines of code, it is
|
||||
especially suitable for embedded applications.
|
||||
|
||||
Package: libart-2.0-dev
|
||||
Architecture: any
|
||||
Section: libdevel
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends},
|
||||
libart-2.0-2 (= ${binary:Version}),
|
||||
pkg-config
|
||||
Description: Library of functions for 2D graphics - development files
|
||||
A library of functions for 2D graphics supporting a superset of the
|
||||
PostScript imaging model, designed to be integrated with graphics, artwork,
|
||||
and illustration programs. It is written in optimized C, and is fully
|
||||
compatible with C++. With a small footprint of 10,000 lines of code, it is
|
||||
especially suitable for embedded applications.
|
@ -0,0 +1,27 @@
|
||||
This package was debianized by Christian Marillat <marillat@debian.org> on
|
||||
Mon, 19 Nov 2001 18:29:06 +0100
|
||||
|
||||
It was downloaded from http://ftp.gnome.org/pub/GNOME/sources/libart_lgpl/
|
||||
|
||||
Upstream Author: Raph Levien <raph@acm.org>
|
||||
|
||||
Copyright: 1998, 1999, 2000, 2001 Raph Levien <raph@acm.org>
|
||||
|
||||
License:
|
||||
|
||||
This package is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This package 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
On Debian systems, the complete text of the GNU Lesser General
|
||||
Public License can be found in `/usr/share/common-licenses/LGPL'.
|
@ -0,0 +1 @@
|
||||
debian/tmp/usr/lib/libart_lgpl_2.so.*
|
@ -0,0 +1,6 @@
|
||||
debian/tmp/usr/include
|
||||
debian/tmp/usr/lib/pkgconfig
|
||||
debian/tmp/usr/bin/libart2-config
|
||||
debian/tmp/usr/lib/libart_lgpl_2.a
|
||||
debian/tmp/usr/lib/libart_lgpl_2.la
|
||||
debian/tmp/usr/lib/libart_lgpl_2.so
|
@ -0,0 +1 @@
|
||||
debian/libart2-config.1
|
@ -0,0 +1,52 @@
|
||||
.\" This manpage has been automatically generated by docbook2man
|
||||
.\" from a DocBook document. This tool can be found at:
|
||||
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
|
||||
.\" Please send any bug reports, improvements, comments, patches,
|
||||
.\" etc. to Steve Cheng <steve@ggi-project.org>.
|
||||
.TH "LIBART2-CONFIG" "1" "08 August 2003" "" ""
|
||||
.SH NAME
|
||||
libart2-config \- script to get information about the installed version of libart 2.x
|
||||
.SH SYNOPSIS
|
||||
|
||||
\fBlibart2-config\fR [ \fB --prefix\fI[=DIR]\fB \fR ] [ \fB --exec-prefix\fI[=DIR]\fB \fR ] [ \fB --libs \fR ] [ \fB --cflags \fR ] [ \fB --version \fR ]
|
||||
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
\fBlibart2-config\fR is a tool that is used to determine
|
||||
the compiler and linker flags that should be used to compile and
|
||||
link programs that use \fIlibart\fR library.
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
\fB--prefix=PREFIX\fR
|
||||
If specified, use \fIPREFIX\fR instead
|
||||
of the installation prefix that
|
||||
\fIlibart\fR was built with when computing
|
||||
the output for the \fB--cflags\fR and
|
||||
\fB--libs\fR options. This option is also used for
|
||||
the exec prefix if \fB--exec-prefix\fR was
|
||||
not specified. This option must be specified before any
|
||||
\fB--libs\fR or \fB--cflags\fR options.
|
||||
.TP
|
||||
\fB--exec-prefix=PREFIX\fR
|
||||
If specified, use \fIPREFIX\fR instead
|
||||
of the installation exec prefix that
|
||||
\fIlibart\fR was built with when computing
|
||||
the output for the \fB--cflags\fR and
|
||||
\fB--libs\fR options. This option must be specified
|
||||
before any \fB--libs\fR or \fB--cflags\fR options.
|
||||
.TP
|
||||
\fB--libs\fR
|
||||
Print the linker flags that are necessary to link a
|
||||
\fIlibart\fR program.
|
||||
.TP
|
||||
\fB--cflags\fR
|
||||
Print the compiler flags that are necessary to compile a
|
||||
\fIlibart\fR program.
|
||||
.TP
|
||||
\fB--version\fR
|
||||
Print the currently installed version of
|
||||
\fIlibart\fR on the standard output.
|
||||
.SH "AUTHOR"
|
||||
.PP
|
||||
This manual page was written by Christian Marillat <marillat@debian.org> for
|
||||
the Debian GNU/Linux system (but may be used by others).
|
@ -0,0 +1,38 @@
|
||||
Add --static support to libart2-config --libs to avoid -lm
|
||||
Debian #375812, GNOME #531278
|
||||
|
||||
Index: libart-config.in
|
||||
===================================================================
|
||||
--- libart-config.in (revision 280)
|
||||
+++ libart-config.in (working copy)
|
||||
@@ -3,6 +3,8 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
exec_prefix_set=no
|
||||
+libs=""
|
||||
+output_libs=no
|
||||
|
||||
usage="\
|
||||
Usage: libart-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
|
||||
@@ -43,8 +45,11 @@ while test $# -gt 0; do
|
||||
echo $includes
|
||||
;;
|
||||
--libs)
|
||||
- libdirs=-L@libdir@
|
||||
- echo $libdirs -lart_lgpl_2 -lm
|
||||
+ libs="$libs -L@libdir@ -lart_lgpl_2"
|
||||
+ output_libs=yes
|
||||
+ ;;
|
||||
+ --static)
|
||||
+ libs="$libs -lm"
|
||||
;;
|
||||
*)
|
||||
echo "${usage}" 1>&2
|
||||
@@ -54,3 +59,7 @@ while test $# -gt 0; do
|
||||
shift
|
||||
done
|
||||
|
||||
+if test $output_libs = yes ; then
|
||||
+ echo $libs
|
||||
+fi
|
||||
+
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
include /usr/share/cdbs/1/rules/debhelper.mk
|
||||
include /usr/share/cdbs/1/rules/simple-patchsys.mk
|
||||
include /usr/share/cdbs/1/rules/utils.mk
|
||||
include /usr/share/cdbs/1/class/gnome.mk
|
||||
include /usr/share/gnome-pkg-tools/1/rules/uploaders.mk
|
||||
include /usr/share/gnome-pkg-tools/1/rules/clean-la.mk
|
||||
-include /usr/share/gnome-pkg-tools/1/rules/gnome-get-source.mk
|
||||
|
||||
libart-2.0-N := $(shell sed -rn 's/^Package:[[:space:]]*(libart-2\.0-[0-9]+)[[:space:]]*$$/\1/p' debian/control)
|
||||
|
||||
GNOME_MODULE := libart_lgpl
|
||||
|
||||
DEB_DH_MAKESHLIBS_ARGS_$(libart-2.0-N) += -V '$(libart-2.0-N)(>= 2.3.18)'
|
||||
|
@ -0,0 +1,4 @@
|
||||
version=2
|
||||
http://ftp.gnome.org/pub/GNOME/sources/libart_lgpl/([\d\.]+)/ \
|
||||
libart_lgpl-(.*)\.tar\.gz \
|
||||
debian uupdate
|
@ -0,0 +1,630 @@
|
||||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
|
||||
# Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by `PROGRAMS ARGS'.
|
||||
object Object file output by `PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputing dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u="sed s,\\\\\\\\,/,g"
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the `deleted header file' problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the `:'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like `#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr '
|
||||
' ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts `$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form `foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
# That's a tab and a space in the [].
|
||||
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler understands `-MD -MF file'. However on
|
||||
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want:
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using \ :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
|
||||
sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add `dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in `foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mechanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
# That's a tab and a space in the [].
|
||||
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for `:'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' '
|
||||
' | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
|
||||
echo " " >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
|
||||
# A little utility function to generate header info.
|
||||
#
|
||||
# The output of this program is generally written to art_config.h,
|
||||
# which is installed in libart's include dir.
|
||||
|
||||
|
||||
echo "/* Automatically generated by gen_art_config */"
|
||||
echo
|
||||
echo "#define ART_SIZEOF_CHAR @ART_SIZEOF_CHAR@"
|
||||
echo "#define ART_SIZEOF_SHORT @ART_SIZEOF_SHORT@"
|
||||
echo "#define ART_SIZEOF_INT @ART_SIZEOF_INT@"
|
||||
echo "#define ART_SIZEOF_LONG @ART_SIZEOF_LONG@"
|
||||
echo
|
||||
|
||||
if test @ART_SIZEOF_CHAR@ -eq 1; then
|
||||
echo "typedef unsigned char art_u8;"
|
||||
else
|
||||
echo 1>&2 "sizeof(char) != 1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test @ART_SIZEOF_SHORT@ -eq 2; then
|
||||
echo "typedef unsigned short art_u16;"
|
||||
else
|
||||
echo 1>&2 "sizeof(short) != 2"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if test @ART_SIZEOF_INT@ -eq 4; then
|
||||
echo "typedef unsigned int art_u32;"
|
||||
else
|
||||
if test @ART_SIZEOF_LONG@ -eq 4; then
|
||||
echo "typedef unsigned long art_u32;"
|
||||
else
|
||||
echo 1>&2 "sizeof(int) != 4 and sizeof(long) != 4"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
@ -0,0 +1,520 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
case $src in
|
||||
-*) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dst_arg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst;;
|
||||
esac
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
-*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test -z "$d" && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
@ -0,0 +1,10 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libart
|
||||
Description: LGPL version of the libart library
|
||||
Version: @VERSION@
|
||||
Libs: ${pc_top_builddir}/${pcfiledir}/libart_lgpl_2.la
|
||||
Cflags: -I${pc_top_builddir}/${pcfiledir}
|
@ -0,0 +1,10 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: libart
|
||||
Description: LGPL version of the libart library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lart_lgpl_2
|
||||
Cflags: -I${includedir}/libart-2.0
|
@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
exec_prefix_set=no
|
||||
|
||||
usage="\
|
||||
Usage: libart-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]"
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo "${usage}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
|
||||
*) optarg= ;;
|
||||
esac
|
||||
|
||||
case $1 in
|
||||
--prefix=*)
|
||||
prefix=$optarg
|
||||
if test $exec_prefix_set = no ; then
|
||||
exec_prefix=$optarg
|
||||
fi
|
||||
;;
|
||||
--prefix)
|
||||
echo $prefix
|
||||
;;
|
||||
--exec-prefix=*)
|
||||
exec_prefix=$optarg
|
||||
exec_prefix_set=yes
|
||||
;;
|
||||
--exec-prefix)
|
||||
echo $exec_prefix
|
||||
;;
|
||||
--version)
|
||||
echo @LIBART_VERSION@
|
||||
;;
|
||||
--cflags)
|
||||
includes=-I@includedir@/libart-2.0
|
||||
echo $includes
|
||||
;;
|
||||
--libs)
|
||||
libdirs=-L@libdir@
|
||||
echo $libdirs -lart_lgpl_2 -lm
|
||||
;;
|
||||
*)
|
||||
echo "${usage}" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
@ -0,0 +1,18 @@
|
||||
#include "libart-features.h"
|
||||
|
||||
/* General initialization hooks */
|
||||
const unsigned int libart_major_version=LIBART_MAJOR_VERSION,
|
||||
libart_minor_version=LIBART_MINOR_VERSION,
|
||||
libart_micro_version=LIBART_MICRO_VERSION;
|
||||
|
||||
const char *libart_version = LIBART_VERSION;
|
||||
|
||||
void
|
||||
libart_preinit(void *app, void *modinfo)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
libart_postinit(void *app, void *modinfo)
|
||||
{
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#ifndef LIBART_FEATURES_H
|
||||
#define LIBART_FEATURES_H 1
|
||||
|
||||
#define LIBART_MAJOR_VERSION (2)
|
||||
#define LIBART_MINOR_VERSION (3)
|
||||
#define LIBART_MICRO_VERSION (21)
|
||||
#define LIBART_VERSION "2.3.21"
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef LIBART_COMPILATION
|
||||
# define LIBART_VAR __declspec(dllexport)
|
||||
# else
|
||||
# define LIBART_VAR extern __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define LIBART_VAR extern
|
||||
#endif
|
||||
|
||||
LIBART_VAR const unsigned int libart_major_version, libart_minor_version, libart_micro_version;
|
||||
LIBART_VAR const char *libart_version;
|
||||
|
||||
void libart_preinit(void *app, void *modinfo);
|
||||
void libart_postinit(void *app, void *modinfo);
|
||||
#endif
|
@ -0,0 +1,24 @@
|
||||
#ifndef LIBART_FEATURES_H
|
||||
#define LIBART_FEATURES_H 1
|
||||
|
||||
#define LIBART_MAJOR_VERSION (@LIBART_MAJOR_VERSION@)
|
||||
#define LIBART_MINOR_VERSION (@LIBART_MINOR_VERSION@)
|
||||
#define LIBART_MICRO_VERSION (@LIBART_MICRO_VERSION@)
|
||||
#define LIBART_VERSION "@LIBART_VERSION@"
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef LIBART_COMPILATION
|
||||
# define LIBART_VAR __declspec(dllexport)
|
||||
# else
|
||||
# define LIBART_VAR extern __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define LIBART_VAR extern
|
||||
#endif
|
||||
|
||||
LIBART_VAR const unsigned int libart_major_version, libart_minor_version, libart_micro_version;
|
||||
LIBART_VAR const char *libart_version;
|
||||
|
||||
void libart_preinit(void *app, void *modinfo);
|
||||
void libart_postinit(void *app, void *modinfo);
|
||||
#endif
|
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Build zipfiles for libart_lgpl on Win32, runtime and developer.
|
||||
|
||||
ZIP=/tmp/libart_lgpl-@LIBART_VERSION@.zip
|
||||
DEVZIP=/tmp/libart_lgpl-dev-@LIBART_VERSION@.zip
|
||||
cd @prefix@
|
||||
|
||||
rm $ZIP
|
||||
|
||||
DLLDIR=lib
|
||||
[ -f bin/libart_lgpl_2-@LIBART_MAJOR_VERSION@.dll ] && DLLDIR=bin
|
||||
|
||||
zip -r $ZIP -@ <<EOF
|
||||
$DLLDIR/libart_lgpl_2-@LIBART_MAJOR_VERSION@.dll
|
||||
EOF
|
||||
|
||||
rm $DEVZIP
|
||||
zip -r $DEVZIP -@ <<EOF
|
||||
include/libart-2.0
|
||||
lib/libart_lgpl_2.dll.a
|
||||
lib/art_lgpl_2.lib
|
||||
lib/pkgconfig/libart-2.0.pc
|
||||
EOF
|
@ -0,0 +1,124 @@
|
||||
EXPORTS
|
||||
art_affine_equal
|
||||
art_affine_expansion
|
||||
art_affine_flip
|
||||
art_affine_identity
|
||||
art_affine_invert
|
||||
art_affine_multiply
|
||||
art_affine_point
|
||||
art_affine_rectilinear
|
||||
art_affine_rotate
|
||||
art_affine_scale
|
||||
art_affine_shear
|
||||
art_affine_to_string
|
||||
art_affine_translate
|
||||
art_alphagamma_free
|
||||
art_alphagamma_new
|
||||
art_bez_path_to_vec
|
||||
art_bezier_to_vec
|
||||
art_bpath_affine_transform
|
||||
art_die
|
||||
art_dprint
|
||||
art_drect_affine_transform
|
||||
art_drect_copy
|
||||
art_drect_empty
|
||||
art_drect_intersect
|
||||
art_drect_svp
|
||||
art_drect_svp_union
|
||||
art_drect_to_irect
|
||||
art_drect_union
|
||||
art_gray_svp_aa
|
||||
art_irect_copy
|
||||
art_irect_empty
|
||||
art_irect_intersect
|
||||
art_irect_union
|
||||
art_pixbuf_duplicate
|
||||
art_pixbuf_free
|
||||
art_pixbuf_free_shallow
|
||||
art_pixbuf_new_const_rgb
|
||||
art_pixbuf_new_const_rgba
|
||||
art_pixbuf_new_rgb
|
||||
art_pixbuf_new_rgb_dnotify
|
||||
art_pixbuf_new_rgba
|
||||
art_pixbuf_new_rgba_dnotify
|
||||
art_rect_list_from_uta
|
||||
art_render_add_image_source
|
||||
art_render_add_mask_source
|
||||
art_render_clear
|
||||
art_render_clear_16_obj
|
||||
art_render_clear_8_obj
|
||||
art_render_clear_rgb
|
||||
art_render_clear_rgb8_obj
|
||||
art_render_composite_8_obj
|
||||
art_render_composite_8_opt1_obj
|
||||
art_render_composite_8_opt2_obj
|
||||
art_render_composite_obj
|
||||
art_render_gradient_linear
|
||||
art_render_gradient_radial
|
||||
art_render_image_solid
|
||||
art_render_invoke
|
||||
art_render_invoke_callbacks
|
||||
art_render_mask
|
||||
art_render_mask_solid
|
||||
art_render_new
|
||||
art_render_svp
|
||||
art_rgb_a_affine
|
||||
art_rgba_rgba_composite
|
||||
art_rgba_fill_run
|
||||
art_rgba_run_alpha
|
||||
art_rgb_affine
|
||||
art_rgb_affine_run
|
||||
art_rgb_bitmap_affine
|
||||
art_rgb_fill_run
|
||||
art_rgb_pixbuf_affine
|
||||
art_rgb_rgba_affine
|
||||
art_rgb_run_alpha
|
||||
art_rgb_svp_aa
|
||||
art_rgb_svp_alpha
|
||||
art_svp_add_segment
|
||||
art_svp_diff
|
||||
art_svp_free
|
||||
art_svp_from_vpath
|
||||
art_svp_intersect
|
||||
art_svp_intersector
|
||||
art_svp_minus
|
||||
art_svp_point_dist
|
||||
art_svp_point_wind
|
||||
art_svp_render_aa
|
||||
art_svp_render_aa_iter
|
||||
art_svp_render_aa_iter_done
|
||||
art_svp_render_aa_iter_step
|
||||
art_svp_rewind_uncrossed
|
||||
art_svp_seg_compare
|
||||
art_svp_uncross
|
||||
art_svp_union
|
||||
art_svp_vpath_stroke
|
||||
art_svp_vpath_stroke_raw
|
||||
art_svp_writer_rewind_new
|
||||
art_svp_writer_rewind_reap
|
||||
art_uta_add_line
|
||||
art_uta_free
|
||||
art_uta_from_irect
|
||||
art_uta_from_svp
|
||||
art_uta_from_vpath
|
||||
art_uta_new
|
||||
art_uta_new_coords
|
||||
art_uta_union
|
||||
art_vpath_add_point
|
||||
art_vpath_affine_transform
|
||||
art_vpath_bbox_drect
|
||||
art_vpath_bbox_irect
|
||||
art_vpath_dash
|
||||
art_vpath_from_svp
|
||||
art_vpath_new_circle
|
||||
art_vpath_perturb
|
||||
art_warn
|
||||
art_alloc
|
||||
art_free
|
||||
art_realloc
|
||||
libart_major_version
|
||||
libart_micro_version
|
||||
libart_minor_version
|
||||
libart_postinit
|
||||
libart_preinit
|
||||
libart_version
|
@ -0,0 +1,39 @@
|
||||
#ifndef LIBART_H
|
||||
#define LIBART_H 1
|
||||
|
||||
#include <libart_lgpl/art_affine.h>
|
||||
#include <libart_lgpl/art_alphagamma.h>
|
||||
#include <libart_lgpl/art_bpath.h>
|
||||
#include <libart_lgpl/art_filterlevel.h>
|
||||
#include <libart_lgpl/art_gray_svp.h>
|
||||
#include <libart_lgpl/art_misc.h>
|
||||
#include <libart_lgpl/art_pathcode.h>
|
||||
#include <libart_lgpl/art_pixbuf.h>
|
||||
#include <libart_lgpl/art_point.h>
|
||||
#include <libart_lgpl/art_rect.h>
|
||||
#include <libart_lgpl/art_rect_svp.h>
|
||||
#include <libart_lgpl/art_rect_uta.h>
|
||||
#include <libart_lgpl/art_rgb.h>
|
||||
#include <libart_lgpl/art_rgb_affine.h>
|
||||
#include <libart_lgpl/art_rgb_bitmap_affine.h>
|
||||
#include <libart_lgpl/art_rgb_pixbuf_affine.h>
|
||||
#include <libart_lgpl/art_rgb_rgba_affine.h>
|
||||
#include <libart_lgpl/art_rgb_svp.h>
|
||||
#include <libart_lgpl/art_svp.h>
|
||||
#include <libart_lgpl/art_svp_ops.h>
|
||||
#include <libart_lgpl/art_svp_point.h>
|
||||
#include <libart_lgpl/art_svp_render_aa.h>
|
||||
#include <libart_lgpl/art_svp_vpath.h>
|
||||
#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>
|
||||
#include <libart_lgpl/art_vpath.h>
|
||||
#include <libart_lgpl/art_vpath_bpath.h>
|
||||
#include <libart_lgpl/art_vpath_dash.h>
|
||||
#include <libart_lgpl/art_vpath_svp.h>
|
||||
|
||||
#endif
|
@ -0,0 +1,376 @@
|
||||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
|
||||
scriptversion=2009-04-28.21; # UTC
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
|
||||
# 2008, 2009 Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
|
||||
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case $1 in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
autom4te touch the output file, or create a stub one
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
|
||||
\`g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# normalize program name to check for.
|
||||
program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program). This is about non-GNU programs, so use $1 not
|
||||
# $program.
|
||||
case $1 in
|
||||
lex*|yacc*)
|
||||
# Not GNU programs, they don't have --version.
|
||||
;;
|
||||
|
||||
tar*)
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case $program in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case $f in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison*|yacc*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG="\${$#}"
|
||||
case $LASTARG in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f y.tab.h; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if test ! -f y.tab.c; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex*|flex*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG="\${$#}"
|
||||
case $LASTARG in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f lex.yy.c; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit $?
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# The file to touch is that specified with -o ...
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -z "$file"; then
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '
|
||||
/^@setfilename/{
|
||||
s/.* \([^ ]*\) *$/\1/
|
||||
p
|
||||
q
|
||||
}' $infile`
|
||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
fi
|
||||
# If the file does not exist, the user really needs makeinfo;
|
||||
# let's fail without touching anything.
|
||||
test -f $file || exit 1
|
||||
touch $file
|
||||
;;
|
||||
|
||||
tar*)
|
||||
shift
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case $firstarg in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case $firstarg in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
@ -0,0 +1,636 @@
|
||||
/* Libart_LGPL - library of basic graphic primitives
|
||||
* Copyright (C) 1998, 1999 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_svp.h"
|
||||
#include "art_svp_vpath.h"
|
||||
#include "art_gray_svp.h"
|
||||
#include "art_rgb_svp.h"
|
||||
#include "art_svp_vpath_stroke.h"
|
||||
#include "art_svp_ops.h"
|
||||
#include "art_affine.h"
|
||||
#include "art_rgb_affine.h"
|
||||
#include "art_rgb_bitmap_affine.h"
|
||||
#include "art_rgb_rgba_affine.h"
|
||||
#include "art_alphagamma.h"
|
||||
#include "art_svp_point.h"
|
||||
#include "art_vpath_dash.h"
|
||||
#include "art_render.h"
|
||||
#include "art_render_gradient.h"
|
||||
#include "art_render_svp.h"
|
||||
#include "art_svp_intersect.h"
|
||||
|
||||
#ifdef DEAD_CODE
|
||||
static void
|
||||
test_affine (void) {
|
||||
double src[6];
|
||||
double dst[6];
|
||||
double src2[6];
|
||||
char str[128];
|
||||
int i;
|
||||
ArtPoint ps, pd, ptmp;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
src[i] = (rand () * 2.0 / RAND_MAX) - 1.0;
|
||||
src2[i] = (rand () * 2.0 / RAND_MAX) - 1.0;
|
||||
}
|
||||
#if 0
|
||||
src[0] = 0.9999999;
|
||||
src[1] = -0.000001;
|
||||
src[2] = 0.000001;
|
||||
src[3] = 0.9999999;
|
||||
src[4] = 0;
|
||||
src[5] = 0;
|
||||
#if 1
|
||||
src[0] = 0.98480775;
|
||||
src[1] = -0.17364818;
|
||||
src[2] = 0.17364818;
|
||||
src[3] = 0.98480775;
|
||||
#endif
|
||||
|
||||
src2[0] = 0.98480775;
|
||||
src2[1] = -0.17364818;
|
||||
src2[2] = 0.17364818;
|
||||
src2[3] = 0.98480775;
|
||||
#endif
|
||||
|
||||
|
||||
ps.x = rand() * 100.0 / RAND_MAX;
|
||||
ps.y = rand() * 100.0 / RAND_MAX;
|
||||
|
||||
art_affine_point (&pd, &ps, src);
|
||||
art_affine_invert (dst, src);
|
||||
art_affine_point (&ptmp, &pd, dst);
|
||||
art_affine_to_string (str, src);
|
||||
printf ("src = %s\n", str);
|
||||
art_affine_to_string (str, dst);
|
||||
printf ("dst = %s\n", str);
|
||||
printf ("point (%g, %g) -> (%g, %g) -> (%g, %g)\n",
|
||||
ps.x, ps.y, pd.x, pd.y, ptmp.x, ptmp.y);
|
||||
|
||||
art_affine_point (&ptmp, &ps, src);
|
||||
art_affine_point (&pd, &ptmp, src2);
|
||||
art_affine_to_string (str, src2);
|
||||
printf ("src2 = %s\n", str);
|
||||
printf ("point (%g, %g) -> (%g, %g) -> (%g, %g)\n",
|
||||
ps.x, ps.y, ptmp.x, ptmp.y, pd.x, pd.y);
|
||||
art_affine_multiply (dst, src, src2);
|
||||
art_affine_to_string (str, dst);
|
||||
printf ("dst = %s\n", str);
|
||||
art_affine_point (&pd, &ps, dst);
|
||||
printf ("point (%g, %g) -> (%g, %g)\n",
|
||||
ps.x, ps.y, pd.x, pd.y);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static ArtVpath *
|
||||
randstar (int n)
|
||||
{
|
||||
ArtVpath *vec;
|
||||
int i;
|
||||
double r, th;
|
||||
|
||||
vec = art_new (ArtVpath, n + 2);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
vec[i].code = i ? ART_LINETO : ART_MOVETO;
|
||||
r = rand () * (250.0 / RAND_MAX);
|
||||
#if 0
|
||||
r = r + 0.9 * (250 - r);
|
||||
#endif
|
||||
th = i * 2 * M_PI / n;
|
||||
vec[i].x = 250 + r * cos (th);
|
||||
vec[i].y = 250 - r * sin (th);
|
||||
}
|
||||
vec[i].code = ART_LINETO;
|
||||
vec[i].x = vec[0].x;
|
||||
vec[i].y = vec[0].y;
|
||||
i++;
|
||||
vec[i].code = ART_END;
|
||||
vec[i].x = 0;
|
||||
vec[i].y = 0;
|
||||
return vec;
|
||||
}
|
||||
|
||||
#define TILE_SIZE 512
|
||||
#define NUM_ITERS 1
|
||||
#define COLOR
|
||||
|
||||
#ifdef COLOR
|
||||
#define BYTES_PP 3
|
||||
#else
|
||||
#define BYTES_PP 1
|
||||
#endif
|
||||
|
||||
#ifndef nDEAD_CODE
|
||||
static void
|
||||
print_svp (ArtSVP *vp)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < vp->n_segs; i++)
|
||||
{
|
||||
printf ("segment %d, dir = %s (%f, %f) - (%f, %f)\n",
|
||||
i, vp->segs[i].dir ? "down" : "up",
|
||||
vp->segs[i].bbox.x0,
|
||||
vp->segs[i].bbox.y0,
|
||||
vp->segs[i].bbox.x1,
|
||||
vp->segs[i].bbox.y1);
|
||||
for (j = 0; j < vp->segs[i].n_points; j++)
|
||||
printf (" (%g, %g)\n",
|
||||
vp->segs[i].points[j].x,
|
||||
vp->segs[i].points[j].y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
print_vpath (ArtVpath *vpath)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; vpath[i].code != ART_END; i++)
|
||||
printf ("%g %g %s\n",
|
||||
vpath[i].x, vpath[i].y,
|
||||
vpath[i].code == ART_MOVETO_OPEN ? "moveto %open" :
|
||||
vpath[i].code == ART_MOVETO ? "moveto" :
|
||||
vpath[i].code == ART_LINETO ? "lineto" :
|
||||
"?");
|
||||
|
||||
printf ("stroke\n");
|
||||
}
|
||||
|
||||
static void
|
||||
make_testpat (void)
|
||||
{
|
||||
ArtVpath *vpath, *vpath2, *vpath3;
|
||||
ArtSVP *svp, *svp2;
|
||||
ArtSVP *svp3;
|
||||
art_u8 buf[512 * 512 * BYTES_PP];
|
||||
int i, j;
|
||||
int iter;
|
||||
art_u8 colorimg[256][256][3];
|
||||
art_u8 rgbaimg[256][256][4];
|
||||
art_u8 bitimg[16][2];
|
||||
int x, y;
|
||||
double affine[6];
|
||||
double affine2[6];
|
||||
double affine3[6];
|
||||
ArtAlphaGamma *alphagamma;
|
||||
double dash_data[] = { 20 };
|
||||
ArtVpathDash dash;
|
||||
|
||||
dash.offset = 0;
|
||||
dash.n_dash = 1;
|
||||
dash.dash = dash_data;
|
||||
|
||||
#ifdef TEST_AFFINE
|
||||
test_affine ();
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
vpath = randstar (50);
|
||||
svp = art_svp_from_vpath (vpath);
|
||||
art_free (vpath);
|
||||
|
||||
vpath2 = randstar (50);
|
||||
#if 1
|
||||
vpath3 = art_vpath_dash (vpath2, &dash);
|
||||
art_free (vpath2);
|
||||
svp2 = art_svp_vpath_stroke (vpath3,
|
||||
ART_PATH_STROKE_JOIN_MITER,
|
||||
ART_PATH_STROKE_CAP_BUTT,
|
||||
15,
|
||||
4,
|
||||
0.5);
|
||||
art_free (vpath3);
|
||||
#else
|
||||
svp2 = art_svp_from_vpath (vpath2);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
svp3 = art_svp_intersect (svp, svp2);
|
||||
#else
|
||||
svp3 = svp2;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
print_svp (svp);
|
||||
#endif
|
||||
|
||||
for (y = 0; y < 256; y++)
|
||||
for (x = 0; x < 256; x++)
|
||||
{
|
||||
colorimg[y][x][0] = (x + y) >> 1;
|
||||
colorimg[y][x][1] = (x + (255 - y)) >> 1;
|
||||
colorimg[y][x][2] = ((255 - x) + y) >> 1;
|
||||
|
||||
rgbaimg[y][x][0] = (x + y) >> 1;
|
||||
rgbaimg[y][x][1] = (x + (255 - y)) >> 1;
|
||||
rgbaimg[y][x][2] = ((255 - x) + y) >> 1;
|
||||
rgbaimg[y][x][3] = y;
|
||||
}
|
||||
|
||||
for (y = 0; y < 16; y++)
|
||||
for (x = 0; x < 2; x++)
|
||||
bitimg[y][x] = (x << 4) | y;
|
||||
|
||||
affine[0] = 0.5;
|
||||
affine[1] = .2;
|
||||
affine[2] = -.2;
|
||||
affine[3] = 0.5;
|
||||
affine[4] = 64;
|
||||
affine[5] = 64;
|
||||
|
||||
affine2[0] = 1;
|
||||
affine2[1] = -.2;
|
||||
affine2[2] = .2;
|
||||
affine2[3] = 1;
|
||||
affine2[4] = 128;
|
||||
affine2[5] = 128;
|
||||
|
||||
affine3[0] = 5;
|
||||
affine3[1] = -.2;
|
||||
affine3[2] = .2;
|
||||
affine3[3] = 5;
|
||||
affine3[4] = 384;
|
||||
affine3[5] = 32;
|
||||
|
||||
#if 0
|
||||
alphagamma = art_alphagamma_new (1.8);
|
||||
#else
|
||||
alphagamma = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef COLOR
|
||||
printf ("P6\n512 512\n255\n");
|
||||
#else
|
||||
printf ("P5\n512 512\n255\n");
|
||||
#endif
|
||||
for (iter = 0; iter < NUM_ITERS; iter++)
|
||||
for (j = 0; j < 512; j += TILE_SIZE)
|
||||
for (i = 0; i < 512; i += TILE_SIZE)
|
||||
{
|
||||
#ifdef COLOR
|
||||
art_rgb_svp_aa (svp, i, j, i + TILE_SIZE, j + TILE_SIZE,
|
||||
0xffe0a0, 0x100040,
|
||||
buf + (j * 512 + i) * BYTES_PP, 512 * BYTES_PP,
|
||||
alphagamma);
|
||||
art_rgb_svp_alpha (svp2, i, j, i + TILE_SIZE, j + TILE_SIZE,
|
||||
0xff000080,
|
||||
buf + (j * 512 + i) * BYTES_PP, 512 * BYTES_PP,
|
||||
alphagamma);
|
||||
art_rgb_svp_alpha (svp3, i, j, i + TILE_SIZE, j + TILE_SIZE,
|
||||
0x00ff0080,
|
||||
buf + (j * 512 + i) * BYTES_PP, 512 * BYTES_PP,
|
||||
alphagamma);
|
||||
art_rgb_affine (buf + (j * 512 + i) * BYTES_PP,
|
||||
i, j, i + TILE_SIZE, j + TILE_SIZE, 512 * BYTES_PP,
|
||||
(art_u8 *)colorimg, 256, 256, 256 * 3,
|
||||
affine,
|
||||
ART_FILTER_NEAREST, alphagamma);
|
||||
art_rgb_rgba_affine (buf + (j * 512 + i) * BYTES_PP,
|
||||
i, j, i + TILE_SIZE, j + TILE_SIZE,
|
||||
512 * BYTES_PP,
|
||||
(art_u8 *)rgbaimg, 256, 256, 256 * 4,
|
||||
affine2,
|
||||
ART_FILTER_NEAREST, alphagamma);
|
||||
art_rgb_bitmap_affine (buf + (j * 512 + i) * BYTES_PP,
|
||||
i, j, i + TILE_SIZE, j + TILE_SIZE,
|
||||
512 * BYTES_PP,
|
||||
(art_u8 *)bitimg, 16, 16, 2,
|
||||
0xffff00ff,
|
||||
affine3,
|
||||
ART_FILTER_NEAREST, alphagamma);
|
||||
#else
|
||||
art_gray_svp_aa (svp, i, j, i + TILE_SIZE, j + TILE_SIZE,
|
||||
buf + (j * 512 + i) * BYTES_PP, 512 * BYTES_PP);
|
||||
#endif
|
||||
}
|
||||
|
||||
art_svp_free (svp2);
|
||||
art_svp_free (svp3);
|
||||
art_svp_free (svp);
|
||||
|
||||
#if 1
|
||||
fwrite (buf, 1, 512 * 512 * BYTES_PP, stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_dist (void)
|
||||
{
|
||||
ArtVpath *vpath;
|
||||
ArtSVP *svp;
|
||||
art_u8 buf[512 * 512 * BYTES_PP];
|
||||
int x, y;
|
||||
int ix;
|
||||
double dist;
|
||||
int wind;
|
||||
|
||||
vpath = randstar (20);
|
||||
#ifdef NO_STROKE
|
||||
svp = art_svp_from_vpath (vpath);
|
||||
#else
|
||||
svp = art_svp_vpath_stroke (vpath,
|
||||
ART_PATH_STROKE_JOIN_MITER,
|
||||
ART_PATH_STROKE_CAP_BUTT,
|
||||
15,
|
||||
4,
|
||||
0.5);
|
||||
#endif
|
||||
|
||||
art_rgb_svp_aa (svp, 0, 0, 512, 512,
|
||||
0xffe0a0, 0x100040,
|
||||
buf, 512 * BYTES_PP,
|
||||
NULL);
|
||||
|
||||
ix = 0;
|
||||
for (y = 0; y < 512; y++)
|
||||
{
|
||||
for (x = 0; x < 512; x++)
|
||||
{
|
||||
wind = art_svp_point_wind (svp, x, y);
|
||||
buf[ix] = 204 - wind * 51;
|
||||
dist = art_svp_point_dist (svp, x, y);
|
||||
if (((x | y) & 0x3f) == 0)
|
||||
{
|
||||
fprintf (stderr, "%d,%d: %f\n", x, y, dist);
|
||||
}
|
||||
buf[ix + 1] = 255 - dist;
|
||||
ix += 3;
|
||||
}
|
||||
}
|
||||
|
||||
printf ("P6\n512 512\n255\n");
|
||||
fwrite (buf, 1, 512 * 512 * BYTES_PP, stdout);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_dash (void)
|
||||
{
|
||||
ArtVpath *vpath, *vpath2;
|
||||
double dash_data[] = { 10, 4, 1, 4};
|
||||
ArtVpathDash dash;
|
||||
|
||||
dash.offset = 0;
|
||||
dash.n_dash = 3;
|
||||
dash.dash = dash_data;
|
||||
|
||||
vpath = randstar (50);
|
||||
vpath2 = art_vpath_dash (vpath, &dash);
|
||||
printf ("%%!\n");
|
||||
print_vpath (vpath2);
|
||||
printf ("showpage\n");
|
||||
art_free (vpath);
|
||||
art_free (vpath2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_render_gradient (art_u8 *buf)
|
||||
{
|
||||
ArtGradientLinear gradient;
|
||||
ArtGradientStop stops[3] = {
|
||||
{ 0.0, { 0x7fff, 0x0000, 0x0000, 0x7fff }},
|
||||
{ 0.5, { 0x0000, 0x0000, 0x0000, 0x1000 }},
|
||||
{ 1.0, { 0x0000, 0x7fff, 0x0000, 0x7fff }}
|
||||
};
|
||||
ArtVpath *vpath;
|
||||
ArtSVP *svp;
|
||||
ArtRender *render;
|
||||
|
||||
gradient.a = 0.003;
|
||||
gradient.b = -0.0015;
|
||||
gradient.c = 0.1;
|
||||
gradient.spread = ART_GRADIENT_PAD;
|
||||
gradient.n_stops = sizeof(stops) / sizeof(stops[0]);
|
||||
gradient.stops = stops;
|
||||
|
||||
vpath = randstar (50);
|
||||
svp = art_svp_from_vpath (vpath);
|
||||
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
|
||||
NULL);
|
||||
art_render_svp (render, svp);
|
||||
art_render_gradient_linear (render, &gradient, ART_FILTER_NEAREST);
|
||||
art_render_invoke (render);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_render_rad_gradient (art_u8 *buf)
|
||||
{
|
||||
ArtGradientRadial gradient;
|
||||
ArtGradientStop stops[3] = {
|
||||
{ 0.0, { 0xffff, 0x0000, 0x0000, 0xffff }},
|
||||
{ 0.5, { 0xe000, 0xe000, 0x0000, 0xe000 }},
|
||||
{ 1.0, { 0x0000, 0x0000, 0x0000, 0x0000 }}
|
||||
};
|
||||
ArtVpath *vpath;
|
||||
ArtSVP *svp;
|
||||
ArtRender *render;
|
||||
|
||||
gradient.affine[0] = 3.0 / 512;
|
||||
gradient.affine[1] = 0;
|
||||
gradient.affine[2] = 0;
|
||||
gradient.affine[3] = 3.0 / 512;
|
||||
gradient.affine[4] = -1.5;
|
||||
gradient.affine[5] = -1.5;
|
||||
gradient.fx = 0.9;
|
||||
gradient.fy = 0.1;
|
||||
|
||||
gradient.n_stops = sizeof(stops) / sizeof(stops[0]);
|
||||
gradient.stops = stops;
|
||||
|
||||
vpath = randstar (50);
|
||||
svp = art_svp_from_vpath (vpath);
|
||||
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
|
||||
NULL);
|
||||
art_render_svp (render, svp);
|
||||
art_render_gradient_radial (render, &gradient, ART_FILTER_NEAREST);
|
||||
art_render_invoke (render);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
test_gradient (void)
|
||||
{
|
||||
ArtVpath *vpath;
|
||||
ArtSVP *svp;
|
||||
art_u8 buf[512 * 512 * 3];
|
||||
ArtRender *render;
|
||||
ArtPixMaxDepth color[3] = {0x0000, 0x0000, 0x8000 };
|
||||
int i;
|
||||
const int n_iter = 1;
|
||||
|
||||
vpath = randstar (50);
|
||||
svp = art_svp_from_vpath (vpath);
|
||||
|
||||
for (i = 0; i < n_iter; i++)
|
||||
{
|
||||
#define USE_RENDER
|
||||
#ifdef USE_RENDER
|
||||
render = art_render_new (0, 0, 512, 512, buf, 512 * 3, 3, 8, ART_ALPHA_NONE,
|
||||
NULL);
|
||||
art_render_clear_rgb (render, 0xfff0c0);
|
||||
art_render_svp (render, svp);
|
||||
art_render_image_solid (render, color);
|
||||
art_render_invoke (render);
|
||||
#else
|
||||
art_rgb_svp_aa (svp, 0, 0, 512, 512, 0xfff0c0, 0x000080,
|
||||
buf, 512 * 3, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 1
|
||||
test_render_gradient (buf);
|
||||
#endif
|
||||
test_render_rad_gradient (buf);
|
||||
|
||||
printf ("P6\n512 512\n255\n");
|
||||
fwrite (buf, 1, 512 * 512 * 3, stdout);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
output_svp_ppm (const ArtSVP *svp)
|
||||
{
|
||||
art_u8 buf[512 * 512 * 3];
|
||||
art_rgb_svp_aa (svp, 0, 0, 512, 512, 0xfff0c0, 0x000080,
|
||||
buf, 512 * 3, NULL);
|
||||
printf ("P6\n512 512\n255\n");
|
||||
fwrite (buf, 1, 512 * 512 * 3, stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
test_intersect (void)
|
||||
{
|
||||
ArtVpath vpath[] = {
|
||||
|
||||
#if 0
|
||||
/* two triangles */
|
||||
{ ART_MOVETO, 100, 100 },
|
||||
{ ART_LINETO, 300, 400 },
|
||||
{ ART_LINETO, 400, 200 },
|
||||
{ ART_LINETO, 100, 100 },
|
||||
{ ART_MOVETO, 110, 110 },
|
||||
{ ART_LINETO, 310, 410 },
|
||||
{ ART_LINETO, 410, 210 },
|
||||
{ ART_LINETO, 110, 110 },
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* a bowtie */
|
||||
{ ART_MOVETO, 100, 100 },
|
||||
{ ART_LINETO, 400, 400 },
|
||||
{ ART_LINETO, 400, 100 },
|
||||
{ ART_LINETO, 100, 400 },
|
||||
{ ART_LINETO, 100, 100 },
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
/* a square */
|
||||
{ ART_MOVETO, 100, 100 },
|
||||
{ ART_LINETO, 100, 400 },
|
||||
{ ART_LINETO, 400, 400 },
|
||||
{ ART_LINETO, 400, 100 },
|
||||
{ ART_LINETO, 100, 100 },
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
/* another square */
|
||||
#define XOFF 10
|
||||
#define YOFF 10
|
||||
{ ART_MOVETO, 100 + XOFF, 100 + YOFF },
|
||||
{ ART_LINETO, 100 + XOFF, 400 + YOFF },
|
||||
{ ART_LINETO, 400 + XOFF, 400 + YOFF },
|
||||
{ ART_LINETO, 400 + XOFF, 100 + YOFF },
|
||||
{ ART_LINETO, 100 + XOFF, 100 + YOFF },
|
||||
#endif
|
||||
|
||||
{ ART_END, 0, 0}
|
||||
};
|
||||
ArtSVP *svp, *svp2;
|
||||
ArtSvpWriter *swr;
|
||||
|
||||
svp = art_svp_from_vpath (vpath);
|
||||
|
||||
#define RUN_INTERSECT
|
||||
#ifdef RUN_INTERSECT
|
||||
swr = art_svp_writer_rewind_new (ART_WIND_RULE_ODDEVEN);
|
||||
art_svp_intersector (svp, swr);
|
||||
|
||||
svp2 = art_svp_writer_rewind_reap (swr);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
output_svp_ppm (svp2);
|
||||
#else
|
||||
print_svp (svp2);
|
||||
#endif
|
||||
|
||||
art_svp_free (svp);
|
||||
|
||||
#ifdef RUN_INTERSECT
|
||||
art_svp_free (svp2);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
fprintf (stderr, "usage: testart <test>\n"
|
||||
" where <test> is one of:\n"
|
||||
" testpat -- make random star + gradients test pattern\n"
|
||||
" gradient -- test pattern for rendered gradients\n"
|
||||
" dash -- dash test (output is valid PostScript)\n"
|
||||
" dist -- distance test\n"
|
||||
" intersect -- softball test for intersector\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
usage ();
|
||||
|
||||
if (!strcmp (argv[1], "testpat"))
|
||||
make_testpat ();
|
||||
else if (!strcmp (argv[1], "gradient"))
|
||||
test_gradient ();
|
||||
else if (!strcmp (argv[1], "dist"))
|
||||
test_dist ();
|
||||
else if (!strcmp (argv[1], "dash"))
|
||||
test_dash ();
|
||||
else if (!strcmp (argv[1], "intersect"))
|
||||
test_intersect ();
|
||||
else
|
||||
usage ();
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
/* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "art_misc.h"
|
||||
#include "art_uta.h"
|
||||
#include "art_vpath.h"
|
||||
#include "art_uta_vpath.h"
|
||||
#include "art_rect.h"
|
||||
#include "art_rect_uta.h"
|
||||
#include "art_uta_rect.h"
|
||||
|
||||
#undef LIBART_COMPILATION
|
||||
#include "libart-features.h"
|
||||
|
||||
#define TEST_UTA
|
||||
#define noTEST_UTA_SPEED
|
||||
|
||||
#define XOFF 50
|
||||
#define YOFF 700
|
||||
|
||||
static void
|
||||
print_uta_ps (ArtUta *uta)
|
||||
{
|
||||
int x, y;
|
||||
int x0, y0, x1, y1;
|
||||
int width = uta->width;
|
||||
ArtUtaBbox ub;
|
||||
|
||||
for (y = 0; y < uta->height; y++)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
ub = uta->utiles[y * width + x];
|
||||
if (ub != 0)
|
||||
{
|
||||
x0 = (uta->x0 + x) * ART_UTILE_SIZE + ART_UTA_BBOX_X0(ub);
|
||||
x1 = (uta->x0 + x) * ART_UTILE_SIZE + ART_UTA_BBOX_X1(ub);
|
||||
y0 = (uta->y0 + y) * ART_UTILE_SIZE + ART_UTA_BBOX_Y0(ub);
|
||||
y1 = (uta->y0 + y) * ART_UTILE_SIZE + ART_UTA_BBOX_Y1(ub);
|
||||
printf ("%% tile %d, %d: %d %d %d %d\n",
|
||||
x, y,
|
||||
ART_UTA_BBOX_X0(ub),
|
||||
ART_UTA_BBOX_Y0(ub),
|
||||
ART_UTA_BBOX_X1(ub),
|
||||
ART_UTA_BBOX_Y1(ub));
|
||||
printf ("%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath fill\n",
|
||||
XOFF + x0, YOFF - y0, XOFF + x1, YOFF - y0,
|
||||
XOFF + x1, YOFF - y1, XOFF + x0, YOFF - y1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_rbuf_ps (int *rbuf, int width, int height)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
for (x = 0; x < width; x++)
|
||||
if (1 && rbuf[y * width + x] != 0)
|
||||
printf ("%d %d moveto (%d) show\n", x * ART_UTILE_SIZE, y * ART_UTILE_SIZE,
|
||||
rbuf[y * width + x]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
randline (ArtUta *uta, int *rbuf, int rbuf_rowstride)
|
||||
{
|
||||
double x0, y0, x1, y1;
|
||||
|
||||
x0 = rand () * (500.0 / RAND_MAX);
|
||||
y0 = rand () * (500.0 / RAND_MAX);
|
||||
x1 = rand () * (500.0 / RAND_MAX);
|
||||
y1 = rand () * (500.0 / RAND_MAX);
|
||||
|
||||
printf ("%g %g moveto %g %g lineto stroke\n", x0, y0, x1, y1);
|
||||
art_uta_add_line (uta, x0, y0, x1, y1, rbuf, rbuf_rowstride);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
print_ps_vpath (ArtVpath *vpath)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; vpath[i].code != ART_END; i++)
|
||||
{
|
||||
switch (vpath[i].code)
|
||||
{
|
||||
case ART_MOVETO:
|
||||
printf ("%g %g moveto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
|
||||
break;
|
||||
case ART_LINETO:
|
||||
printf ("%g %g lineto\n", XOFF + vpath[i].x, YOFF - vpath[i].y);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf ("stroke\n");
|
||||
}
|
||||
|
||||
static ArtVpath *
|
||||
randstar (int n)
|
||||
{
|
||||
ArtVpath *vec;
|
||||
int i;
|
||||
double r, th;
|
||||
|
||||
vec = art_new (ArtVpath, n + 2);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
vec[i].code = i ? ART_LINETO : ART_MOVETO;
|
||||
r = rand () * (250.0 / RAND_MAX);
|
||||
th = i * 2 * M_PI / n;
|
||||
vec[i].x = 250 + r * cos (th);
|
||||
vec[i].y = 250 - r * sin (th);
|
||||
}
|
||||
vec[i].code = ART_LINETO;
|
||||
vec[i].x = vec[0].x;
|
||||
vec[i].y = vec[0].y;
|
||||
i++;
|
||||
vec[i].code = ART_END;
|
||||
vec[i].x = 0;
|
||||
vec[i].y = 0;
|
||||
return vec;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
ArtUta *uta;
|
||||
int i;
|
||||
int *rbuf;
|
||||
ArtVpath *vec;
|
||||
ArtIRect *rects;
|
||||
int n_rects;
|
||||
|
||||
if (argc == 2)
|
||||
srand (atoi (argv[1]));
|
||||
|
||||
#ifdef TEST_UTA
|
||||
printf ("%%!PS-Adobe\n");
|
||||
printf ("%% libart version: %d.%d.%d\n",
|
||||
libart_major_version, libart_minor_version, libart_micro_version);
|
||||
printf ("/Helvetica findfont 12 scalefont setfont\n");
|
||||
printf ("0.5 setlinewidth\n");
|
||||
|
||||
printf ("0.5 setgray\n");
|
||||
for (i = 0; i < 500; i += ART_UTILE_SIZE)
|
||||
{
|
||||
printf ("%d %d moveto %d %d lineto stroke\n",
|
||||
XOFF, YOFF - i, XOFF + 500, YOFF - i);
|
||||
printf ("%d %d moveto %d %d lineto stroke\n",
|
||||
XOFF + i, YOFF, XOFF + i, YOFF - 500);
|
||||
}
|
||||
|
||||
printf ("/a {\n");
|
||||
|
||||
#if 1
|
||||
vec = randstar (50);
|
||||
print_ps_vpath (vec);
|
||||
uta = art_uta_from_vpath (vec);
|
||||
#ifdef TEST_UTA_RECT
|
||||
{
|
||||
ArtIRect bbox = {5, 5, 450, 450};
|
||||
uta = art_uta_from_irect (&bbox);
|
||||
}
|
||||
#endif
|
||||
rbuf = NULL;
|
||||
#else
|
||||
uta = art_uta_new_coords (0, 0, 500, 500);
|
||||
|
||||
rbuf = malloc (sizeof(int) * (500 >> ART_UTILE_SHIFT) * (500 >> ART_UTILE_SHIFT));
|
||||
for (i = 0; i < 10; i++)
|
||||
randline (uta, rbuf, 500 >> ART_UTILE_SHIFT);
|
||||
#endif
|
||||
|
||||
printf ("} def 1 0.5 0.5 setrgbcolor\n");
|
||||
|
||||
print_uta_ps (uta);
|
||||
|
||||
printf ("0 0 0.5 setrgbcolor\n");
|
||||
|
||||
if (rbuf)
|
||||
print_rbuf_ps (rbuf, 500 >> ART_UTILE_SHIFT, 500 >> ART_UTILE_SHIFT);
|
||||
|
||||
printf ("0 setgray a\n");
|
||||
|
||||
rects = art_rect_list_from_uta (uta, 256, 64, &n_rects);
|
||||
|
||||
printf ("%% %d rectangles:\n0 0 1 setrgbcolor\n", n_rects);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
printf ("%d %d moveto %d %d lineto %d %d lineto %d %d lineto closepath stroke\n",
|
||||
XOFF + rects[i].x0, YOFF - rects[i].y0,
|
||||
XOFF + rects[i].x1, YOFF - rects[i].y0,
|
||||
XOFF + rects[i].x1, YOFF - rects[i].y1,
|
||||
XOFF + rects[i].x0, YOFF - rects[i].y1);
|
||||
|
||||
printf ("showpage\n");
|
||||
#endif
|
||||
|
||||
#ifdef TEST_UTA_SPEED
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
vec = randstar (50);
|
||||
uta = art_uta_from_vpath (vec);
|
||||
art_free (vec);
|
||||
art_uta_free (uta);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in new issue