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