Skip to content
Commits on Source (43)
image: fedora:28
job:
script:
- dnf -y install dnf-plugins-core
- dnf -y groupinstall buildsys-build
- dnf -y builddep pixman
- ./autogen.sh
- make -sj4 check
\ No newline at end of file
This diff is collapsed.
...@@ -124,7 +124,7 @@ release-publish-message: $(HASHFILES) ensure-prev ...@@ -124,7 +124,7 @@ release-publish-message: $(HASHFILES) ensure-prev
@echo " (signed by`gpg --list-keys $(GPGKEY) | grep uid | cut -b4- | tr -s " "`)" @echo " (signed by`gpg --list-keys $(GPGKEY) | grep uid | cut -b4- | tr -s " "`)"
@echo "" @echo ""
@echo "Git:" @echo "Git:"
@echo " git://git.freedesktop.org/git/pixman" @echo " https://gitlab.freedesktop.org/pixman/pixman.git"
@echo " tag: $(PACKAGE)-$(VERSION)" @echo " tag: $(PACKAGE)-$(VERSION)"
@echo "" @echo ""
@echo "Log:" @echo "Log:"
......
...@@ -5,6 +5,10 @@ LD = link ...@@ -5,6 +5,10 @@ LD = link
AR = lib AR = lib
PERL = perl PERL = perl
ifneq ($(shell echo ""),)
RM = del
endif
ifeq ($(top_builddir),) ifeq ($(top_builddir),)
top_builddir = $(top_srcdir) top_builddir = $(top_srcdir)
endif endif
...@@ -45,12 +49,13 @@ endif ...@@ -45,12 +49,13 @@ endif
endif endif
endif endif
$(CFG_VAR):
@mkdir $@
$(CFG_VAR)/%.obj: %.c $(libpixman_headers) $(CFG_VAR)/%.obj: %.c $(libpixman_headers) | $(CFG_VAR)
@mkdir -p $(CFG_VAR)
@$(CC) -c $(PIXMAN_CFLAGS) -Fo"$@" $< @$(CC) -c $(PIXMAN_CFLAGS) -Fo"$@" $<
clean: inform clean: inform $(CFG_VAR)
@$(RM) $(CFG_VAR)/*.{exe,ilk,lib,obj,pdb} $(BUILT_SOURCES) || exit 0 @cd $(CFG_VAR) && echo > silence_error.exe && $(RM) *.exe *.ilk *.lib *.obj *.pdb
.PHONY: inform clean .PHONY: inform clean
...@@ -53,7 +53,7 @@ AC_PREREQ([2.57]) ...@@ -53,7 +53,7 @@ AC_PREREQ([2.57])
# #
m4_define([pixman_major], 0) m4_define([pixman_major], 0)
m4_define([pixman_minor], 34) m4_define([pixman_minor], 36)
m4_define([pixman_micro], 0) m4_define([pixman_micro], 0)
m4_define([pixman_version],[pixman_major.pixman_minor.pixman_micro]) m4_define([pixman_version],[pixman_major.pixman_minor.pixman_micro])
...@@ -833,6 +833,19 @@ if test $enable_timers = yes ; then ...@@ -833,6 +833,19 @@ if test $enable_timers = yes ; then
fi fi
AC_SUBST(PIXMAN_TIMERS) AC_SUBST(PIXMAN_TIMERS)
dnl ===================================
dnl gnuplot
AC_ARG_ENABLE(gnuplot,
[AC_HELP_STRING([--enable-gnuplot],
[enable output of filters that can be piped to gnuplot [default=no]])],
[enable_gnuplot=$enableval], [enable_gnuplot=no])
if test $enable_gnuplot = yes ; then
AC_DEFINE(PIXMAN_GNUPLOT, 1, [enable output that can be piped to gnuplot])
fi
AC_SUBST(PIXMAN_GNUPLOT)
dnl =================================== dnl ===================================
dnl GTK+ dnl GTK+
......
#!/bin/sh
set -ex
./autogen.sh
make -sj4 check
pixman (0.36.0-1) unstable; urgency=medium
* New upstream release.
* Update to my Debian address.
* Update Vcs-* URLs to point to salsa.debian.org.
* Use https URL in debian/copyright.
* Set source format to 1.0.
* Bump debhelper compat to 11.
* Bump standards version to 4.2.1.
-- Andreas Boll <aboll@debian.org> Wed, 12 Dec 2018 22:02:44 +0100
pixman (0.34.0-2) unstable; urgency=medium pixman (0.34.0-2) unstable; urgency=medium
* Declare Multi-Arch: same for libpixman-1-dev (Closes: #884166). * Declare Multi-Arch: same for libpixman-1-dev (Closes: #884166).
......
...@@ -2,15 +2,14 @@ Source: pixman ...@@ -2,15 +2,14 @@ Source: pixman
Section: devel Section: devel
Priority: optional Priority: optional
Maintainer: Debian X Strike Force <debian-x@lists.debian.org> Maintainer: Debian X Strike Force <debian-x@lists.debian.org>
Uploaders: Andreas Boll <andreas.boll.dev@gmail.com> Uploaders: Andreas Boll <aboll@debian.org>
Build-Depends: Build-Depends:
debhelper (>= 9), debhelper (>= 11),
dh-autoreconf,
pkg-config, pkg-config,
quilt, quilt,
Standards-Version: 4.1.2 Standards-Version: 4.2.1
Vcs-Git: https://anonscm.debian.org/git/pkg-xorg/lib/pixman.git Vcs-Git: https://salsa.debian.org/xorg-team/lib/pixman.git
Vcs-Browser: https://anonscm.debian.org/cgit/pkg-xorg/lib/pixman.git Vcs-Browser: https://salsa.debian.org/xorg-team/lib/pixman
Homepage: http://pixman.org/ Homepage: http://pixman.org/
Package: libpixman-1-0 Package: libpixman-1-0
......
This package was downloaded from This package was downloaded from
http://xorg.freedesktop.org/releases/individual/lib/ https://xorg.freedesktop.org/releases/individual/lib/
Debian packaging by Julien Cristau <jcristau@debian.org>, 18 May 2007. Debian packaging by Julien Cristau <jcristau@debian.org>, 18 May 2007.
......
...@@ -34,4 +34,4 @@ override_dh_auto_test: ...@@ -34,4 +34,4 @@ override_dh_auto_test:
dh_auto_test -- VERBOSE=1 dh_auto_test -- VERBOSE=1
%: %:
dh $@ --with quilt,autoreconf --builddirectory=build/ --parallel dh $@ --with quilt --builddirectory=build/
...@@ -55,50 +55,70 @@ get_widget (app_t *app, const char *name) ...@@ -55,50 +55,70 @@ get_widget (app_t *app, const char *name)
return widget; return widget;
} }
static double /* Figure out the boundary of a diameter=1 circle transformed into an ellipse
min4 (double a, double b, double c, double d) * by trans. Proof that this is the correct calculation:
{ *
double m1, m2; * Transform x,y to u,v by this matrix calculation:
*
m1 = MIN (a, b); * |u| |a c| |x|
m2 = MIN (c, d); * |v| = |b d|*|y|
return MIN (m1, m2); *
} * Horizontal component:
*
static double * u = ax+cy (1)
max4 (double a, double b, double c, double d) *
{ * For each x,y on a radius-1 circle (p is angle to the point):
double m1, m2; *
* x^2+y^2 = 1
m1 = MAX (a, b); * x = cos(p)
m2 = MAX (c, d); * y = sin(p)
return MAX (m1, m2); * dx/dp = -sin(p) = -y
} * dy/dp = cos(p) = x
*
* Figure out derivative of (1) relative to p:
*
* du/dp = a(dx/dp) + c(dy/dp)
* = -ay + cx
*
* The min and max u are when du/dp is zero:
*
* -ay + cx = 0
* cx = ay
* c = ay/x (2)
* y = cx/a (3)
*
* Substitute (2) into (1) and simplify:
*
* u = ax + ay^2/x
* = a(x^2+y^2)/x
* = a/x (because x^2+y^2 = 1)
* x = a/u (4)
*
* Substitute (4) into (3) and simplify:
*
* y = c(a/u)/a
* y = c/u (5)
*
* Square (4) and (5) and add:
*
* x^2+y^2 = (a^2+c^2)/u^2
*
* But x^2+y^2 is 1:
*
* 1 = (a^2+c^2)/u^2
* u^2 = a^2+c^2
* u = hypot(a,c)
*
* Similarily the max/min of v is at:
*
* v = hypot(b,d)
*
*/
static void static void
compute_extents (pixman_f_transform_t *trans, double *sx, double *sy) compute_extents (pixman_f_transform_t *trans, double *sx, double *sy)
{ {
double min_x, max_x, min_y, max_y; *sx = hypot (trans->m[0][0], trans->m[0][1]) / trans->m[2][2];
pixman_f_vector_t v[4] = *sy = hypot (trans->m[1][0], trans->m[1][1]) / trans->m[2][2];
{
{ { 1, 1, 1 } },
{ { -1, 1, 1 } },
{ { -1, -1, 1 } },
{ { 1, -1, 1 } },
};
pixman_f_transform_point (trans, &v[0]);
pixman_f_transform_point (trans, &v[1]);
pixman_f_transform_point (trans, &v[2]);
pixman_f_transform_point (trans, &v[3]);
min_x = min4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
max_x = max4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]);
min_y = min4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
max_y = max4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]);
*sx = (max_x - min_x) / 2.0;
*sy = (max_y - min_y) / 2.0;
} }
typedef struct typedef struct
......
...@@ -177,6 +177,7 @@ ...@@ -177,6 +177,7 @@
id="lock_checkbutton"> id="lock_checkbutton">
<property name="label" translatable="yes">Lock X and Y Dimensions</property> <property name="label" translatable="yes">Lock X and Y Dimensions</property>
<property name="xalign">0.0</property> <property name="xalign">0.0</property>
<property name="active">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
...@@ -301,6 +302,7 @@ ...@@ -301,6 +302,7 @@
<object class="GtkSpinButton" id="subsample_spin_button"> <object class="GtkSpinButton" id="subsample_spin_button">
<property name="visible">True</property> <property name="visible">True</property>
<property name="adjustment">subsample_adjustment</property> <property name="adjustment">subsample_adjustment</property>
<property name="value">4</property>
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
......
...@@ -642,6 +642,48 @@ fetch_scanline_a2r10g10b10_float (bits_image_t * image, ...@@ -642,6 +642,48 @@ fetch_scanline_a2r10g10b10_float (bits_image_t * image,
} }
/* Expects a float buffer */ /* Expects a float buffer */
#ifndef PIXMAN_FB_ACCESSORS
static void
fetch_scanline_rgbf_float (bits_image_t *image,
int x,
int y,
int width,
uint32_t * b,
const uint32_t *mask)
{
const float *bits = (float *)image->bits + y * image->rowstride;
const float *pixel = bits + x * 3;
argb_t *buffer = (argb_t *)b;
for (; width--; buffer++) {
buffer->r = *pixel++;
buffer->g = *pixel++;
buffer->b = *pixel++;
buffer->a = 1.f;
}
}
static void
fetch_scanline_rgbaf_float (bits_image_t *image,
int x,
int y,
int width,
uint32_t * b,
const uint32_t *mask)
{
const float *bits = (float *)image->bits + y * image->rowstride;
const float *pixel = bits + x * 4;
argb_t *buffer = (argb_t *)b;
for (; width--; buffer++) {
buffer->r = *pixel++;
buffer->g = *pixel++;
buffer->b = *pixel++;
buffer->a = *pixel++;
}
}
#endif
static void static void
fetch_scanline_x2r10g10b10_float (bits_image_t *image, fetch_scanline_x2r10g10b10_float (bits_image_t *image,
int x, int x,
...@@ -805,6 +847,40 @@ fetch_scanline_yv12 (bits_image_t *image, ...@@ -805,6 +847,40 @@ fetch_scanline_yv12 (bits_image_t *image,
/**************************** Pixel wise fetching *****************************/ /**************************** Pixel wise fetching *****************************/
#ifndef PIXMAN_FB_ACCESSORS
static argb_t
fetch_pixel_rgbf_float (bits_image_t *image,
int offset,
int line)
{
float *bits = (float *)image->bits + line * image->rowstride;
argb_t argb;
argb.r = bits[offset * 3];
argb.g = bits[offset * 3 + 1];
argb.b = bits[offset * 3 + 2];
argb.a = 1.f;
return argb;
}
static argb_t
fetch_pixel_rgbaf_float (bits_image_t *image,
int offset,
int line)
{
float *bits = (float *)image->bits + line * image->rowstride;
argb_t argb;
argb.r = bits[offset * 4];
argb.g = bits[offset * 4 + 1];
argb.b = bits[offset * 4 + 2];
argb.a = bits[offset * 4 + 3];
return argb;
}
#endif
static argb_t static argb_t
fetch_pixel_x2r10g10b10_float (bits_image_t *image, fetch_pixel_x2r10g10b10_float (bits_image_t *image,
int offset, int offset,
...@@ -962,6 +1038,45 @@ fetch_pixel_yv12 (bits_image_t *image, ...@@ -962,6 +1038,45 @@ fetch_pixel_yv12 (bits_image_t *image,
/*********************************** Store ************************************/ /*********************************** Store ************************************/
#ifndef PIXMAN_FB_ACCESSORS
static void
store_scanline_rgbaf_float (bits_image_t * image,
int x,
int y,
int width,
const uint32_t *v)
{
float *bits = (float *)image->bits + image->rowstride * y + 4 * x;
const argb_t *values = (argb_t *)v;
for (; width; width--, values++)
{
*bits++ = values->r;
*bits++ = values->g;
*bits++ = values->b;
*bits++ = values->a;
}
}
static void
store_scanline_rgbf_float (bits_image_t * image,
int x,
int y,
int width,
const uint32_t *v)
{
float *bits = (float *)image->bits + image->rowstride * y + 3 * x;
const argb_t *values = (argb_t *)v;
for (; width; width--, values++)
{
*bits++ = values->r;
*bits++ = values->g;
*bits++ = values->b;
}
}
#endif
static void static void
store_scanline_a2r10g10b10_float (bits_image_t * image, store_scanline_a2r10g10b10_float (bits_image_t * image,
int x, int x,
...@@ -1351,6 +1466,17 @@ static const format_info_t accessors[] = ...@@ -1351,6 +1466,17 @@ static const format_info_t accessors[] =
FORMAT_INFO (g1), FORMAT_INFO (g1),
/* Wide formats */ /* Wide formats */
#ifndef PIXMAN_FB_ACCESSORS
{ PIXMAN_rgba_float,
NULL, fetch_scanline_rgbaf_float,
fetch_pixel_generic_lossy_32, fetch_pixel_rgbaf_float,
NULL, store_scanline_rgbaf_float },
{ PIXMAN_rgb_float,
NULL, fetch_scanline_rgbf_float,
fetch_pixel_generic_lossy_32, fetch_pixel_rgbf_float,
NULL, store_scanline_rgbf_float },
#endif
{ PIXMAN_a2r10g10b10, { PIXMAN_a2r10g10b10,
NULL, fetch_scanline_a2r10g10b10_float, NULL, fetch_scanline_a2r10g10b10_float,
......
...@@ -948,6 +948,9 @@ _pixman_bits_image_init (pixman_image_t * image, ...@@ -948,6 +948,9 @@ _pixman_bits_image_init (pixman_image_t * image,
{ {
uint32_t *free_me = NULL; uint32_t *free_me = NULL;
if (PIXMAN_FORMAT_BPP (format) == 128)
return_val_if_fail(!(rowstride % 4), FALSE);
if (!bits && width && height) if (!bits && width && height)
{ {
int rowstride_bytes; int rowstride_bytes;
......
...@@ -3258,9 +3258,9 @@ static const pixman_iter_info_t fast_iters[] = ...@@ -3258,9 +3258,9 @@ static const pixman_iter_info_t fast_iters[] =
}, },
#define AFFINE_FAST_PATHS(name, format, repeat) \ #define AFFINE_FAST_PATHS(name, format, repeat) \
SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ NEAREST_AFFINE_FAST_PATH(name, format, repeat) \
BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \
NEAREST_AFFINE_FAST_PATH(name, format, repeat) SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat)
AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD) AFFINE_FAST_PATHS (pad_a8r8g8b8, a8r8g8b8, PAD)
AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE) AFFINE_FAST_PATHS (none_a8r8g8b8, a8r8g8b8, NONE)
......
...@@ -109,14 +109,16 @@ general_cubic (double x, double B, double C) ...@@ -109,14 +109,16 @@ general_cubic (double x, double B, double C)
if (ax < 1) if (ax < 1)
{ {
return ((12 - 9 * B - 6 * C) * ax * ax * ax + return (((12 - 9 * B - 6 * C) * ax +
(-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6; (-18 + 12 * B + 6 * C)) * ax * ax +
(6 - 2 * B)) / 6;
} }
else if (ax >= 1 && ax < 2) else if (ax < 2)
{ {
return ((-B - 6 * C) * ax * ax * ax + return ((((-B - 6 * C) * ax +
(6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) * (6 * B + 30 * C)) * ax +
ax + (8 * B + 24 * C)) / 6; (-12 * B - 48 * C)) * ax +
(8 * B + 24 * C)) / 6;
} }
else else
{ {
...@@ -141,7 +143,7 @@ static const filter_info_t filters[] = ...@@ -141,7 +143,7 @@ static const filter_info_t filters[] =
{ PIXMAN_KERNEL_BOX, box_kernel, 1.0 }, { PIXMAN_KERNEL_BOX, box_kernel, 1.0 },
{ PIXMAN_KERNEL_LINEAR, linear_kernel, 2.0 }, { PIXMAN_KERNEL_LINEAR, linear_kernel, 2.0 },
{ PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 }, { PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 },
{ PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 6 * SIGMA }, { PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 5.0 },
{ PIXMAN_KERNEL_LANCZOS2, lanczos2_kernel, 4.0 }, { PIXMAN_KERNEL_LANCZOS2, lanczos2_kernel, 4.0 },
{ PIXMAN_KERNEL_LANCZOS3, lanczos3_kernel, 6.0 }, { PIXMAN_KERNEL_LANCZOS3, lanczos3_kernel, 6.0 },
{ PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel, 8.0 }, { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel, 8.0 },
...@@ -160,18 +162,21 @@ integral (pixman_kernel_t kernel1, double x1, ...@@ -160,18 +162,21 @@ integral (pixman_kernel_t kernel1, double x1,
pixman_kernel_t kernel2, double scale, double x2, pixman_kernel_t kernel2, double scale, double x2,
double width) double width)
{ {
/* If the integration interval crosses zero, break it into if (kernel1 == PIXMAN_KERNEL_BOX && kernel2 == PIXMAN_KERNEL_BOX)
* two separate integrals. This ensures that filters such {
* as LINEAR that are not differentiable at 0 will still return width;
* integrate properly. }
/* The LINEAR filter is not differentiable at 0, so if the
* integration interval crosses zero, break it into two
* separate integrals.
*/ */
if (x1 < 0 && x1 + width > 0) else if (kernel1 == PIXMAN_KERNEL_LINEAR && x1 < 0 && x1 + width > 0)
{ {
return return
integral (kernel1, x1, kernel2, scale, x2, - x1) + integral (kernel1, x1, kernel2, scale, x2, - x1) +
integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1); integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1);
} }
else if (x2 < 0 && x2 + width > 0) else if (kernel2 == PIXMAN_KERNEL_LINEAR && x2 < 0 && x2 + width > 0)
{ {
return return
integral (kernel1, x1, kernel2, scale, x2, - x2) + integral (kernel1, x1, kernel2, scale, x2, - x2) +
...@@ -189,13 +194,19 @@ integral (pixman_kernel_t kernel1, double x1, ...@@ -189,13 +194,19 @@ integral (pixman_kernel_t kernel1, double x1,
} }
else else
{ {
/* Integration via Simpson's rule */ /* Integration via Simpson's rule
#define N_SEGMENTS 128 * See http://www.intmath.com/integration/6-simpsons-rule.php
* 12 segments (6 cubic approximations) seems to produce best
* result for lanczos3.linear, which was the combination that
* showed the most errors. This makes sense as the lanczos3
* filter is 6 wide.
*/
#define N_SEGMENTS 12
#define SAMPLE(a1, a2) \ #define SAMPLE(a1, a2) \
(filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale)) (filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale))
double s = 0.0; double s = 0.0;
double h = width / (double)N_SEGMENTS; double h = width / N_SEGMENTS;
int i; int i;
s = SAMPLE (x1, x2); s = SAMPLE (x1, x2);
...@@ -204,11 +215,14 @@ integral (pixman_kernel_t kernel1, double x1, ...@@ -204,11 +215,14 @@ integral (pixman_kernel_t kernel1, double x1,
{ {
double a1 = x1 + h * i; double a1 = x1 + h * i;
double a2 = x2 + h * i; double a2 = x2 + h * i;
s += 4 * SAMPLE (a1, a2);
}
for (i = 2; i < N_SEGMENTS; i += 2)
{
double a1 = x1 + h * i;
double a2 = x2 + h * i;
s += 2 * SAMPLE (a1, a2); s += 2 * SAMPLE (a1, a2);
if (i >= 2 && i < N_SEGMENTS - 1)
s += 4 * SAMPLE (a1, a2);
} }
s += SAMPLE (x1 + width, x2 + width); s += SAMPLE (x1 + width, x2 + width);
...@@ -217,25 +231,17 @@ integral (pixman_kernel_t kernel1, double x1, ...@@ -217,25 +231,17 @@ integral (pixman_kernel_t kernel1, double x1,
} }
} }
static pixman_fixed_t * static void
create_1d_filter (int *width, create_1d_filter (int width,
pixman_kernel_t reconstruct, pixman_kernel_t reconstruct,
pixman_kernel_t sample, pixman_kernel_t sample,
double scale, double scale,
int n_phases) int n_phases,
pixman_fixed_t *p)
{ {
pixman_fixed_t *params, *p;
double step; double step;
double size;
int i; int i;
size = scale * filters[sample].width + filters[reconstruct].width;
*width = ceil (size);
p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t));
if (!params)
return NULL;
step = 1.0 / n_phases; step = 1.0 / n_phases;
for (i = 0; i < n_phases; ++i) for (i = 0; i < n_phases; ++i)
...@@ -243,15 +249,15 @@ create_1d_filter (int *width, ...@@ -243,15 +249,15 @@ create_1d_filter (int *width,
double frac = step / 2.0 + i * step; double frac = step / 2.0 + i * step;
pixman_fixed_t new_total; pixman_fixed_t new_total;
int x, x1, x2; int x, x1, x2;
double total; double total, e;
/* Sample convolution of reconstruction and sampling /* Sample convolution of reconstruction and sampling
* filter. See rounding.txt regarding the rounding * filter. See rounding.txt regarding the rounding
* and sample positions. * and sample positions.
*/ */
x1 = ceil (frac - *width / 2.0 - 0.5); x1 = ceil (frac - width / 2.0 - 0.5);
x2 = x1 + *width; x2 = x1 + width;
total = 0; total = 0;
for (x = x1; x < x2; ++x) for (x = x1; x < x2; ++x)
...@@ -274,29 +280,154 @@ create_1d_filter (int *width, ...@@ -274,29 +280,154 @@ create_1d_filter (int *width,
ihigh - ilow); ihigh - ilow);
} }
total += c; *p = (pixman_fixed_t)floor (c * 65536.0 + 0.5);
*p++ = (pixman_fixed_t)(c * 65536.0 + 0.5); total += *p;
p++;
} }
/* Normalize */ /* Normalize, with error diffusion */
p -= *width; p -= width;
total = 1 / total; total = 65536.0 / total;
new_total = 0; new_total = 0;
e = 0.0;
for (x = x1; x < x2; ++x) for (x = x1; x < x2; ++x)
{ {
pixman_fixed_t t = (*p) * total + 0.5; double v = (*p) * total + e;
pixman_fixed_t t = floor (v + 0.5);
e = v - t;
new_total += t; new_total += t;
*p++ = t; *p++ = t;
} }
if (new_total != pixman_fixed_1) /* pixman_fixed_e's worth of error may remain; put it
*(p - *width / 2) += (pixman_fixed_1 - new_total); * at the first sample, since that is the only one that
* hasn't had any error diffused into it.
*/
*(p - width) += pixman_fixed_1 - new_total;
}
} }
return params;
static int
filter_width (pixman_kernel_t reconstruct, pixman_kernel_t sample, double size)
{
return ceil (filters[reconstruct].width + size * filters[sample].width);
} }
#ifdef PIXMAN_GNUPLOT
/* If enable-gnuplot is configured, then you can pipe the output of a
* pixman-using program to gnuplot and get a continuously-updated plot
* of the horizontal filter. This works well with demos/scale to test
* the filter generation.
*
* The plot is all the different subposition filters shuffled
* together. This is misleading in a few cases:
*
* IMPULSE.BOX - goes up and down as the subfilters have different
* numbers of non-zero samples
* IMPULSE.TRIANGLE - somewhat crooked for the same reason
* 1-wide filters - looks triangular, but a 1-wide box would be more
* accurate
*/
static void
gnuplot_filter (int width, int n_phases, const pixman_fixed_t* p)
{
double step;
int i, j;
int first;
step = 1.0 / n_phases;
printf ("set style line 1 lc rgb '#0060ad' lt 1 lw 0.5 pt 7 pi 1 ps 0.5\n");
printf ("plot [x=%g:%g] '-' with linespoints ls 1\n", -width*0.5, width*0.5);
/* Print a point at the origin so that y==0 line is included: */
printf ("0 0\n\n");
/* The position of the first sample of the phase corresponding to
* frac is given by:
*
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
*
* We have to find the frac that minimizes this expression.
*
* For odd widths, we have
*
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
* = ceil (frac) + K - frac
* = 1 + K - frac
*
* for some K, so this is minimized when frac is maximized and
* strictly growing with frac. So for odd widths, we can simply
* start at the last phase and go backwards.
*
* For even widths, we have
*
* ceil (frac - width / 2.0 - 0.5) + 0.5 - frac
* = ceil (frac - 0.5) + K - frac
*
* The graph for this function (ignoring K) looks like this:
*
* 0.5
* | |\
* | | \
* | | \
* 0 | | \
* |\ |
* | \ |
* | \ |
* -0.5 | \|
* ---------------------------------
* 0 0.5 1
*
* So in this case we need to start with the phase whose frac is
* less than, but as close as possible to 0.5, then go backwards
* until we hit the first phase, then wrap around to the last
* phase and continue backwards.
*
* Which phase is as close as possible 0.5? The locations of the
* sampling point corresponding to the kth phase is given by
* 1/(2 * n_phases) + k / n_phases:
*
* 1/(2 * n_phases) + k / n_phases = 0.5
*
* from which it follows that
*
* k = (n_phases - 1) / 2
*
* rounded down is the phase in question.
*/
if (width & 1)
first = n_phases - 1;
else
first = (n_phases - 1) / 2;
for (j = 0; j < width; ++j)
{
for (i = 0; i < n_phases; ++i)
{
int phase = first - i;
double frac, pos;
if (phase < 0)
phase = n_phases + phase;
frac = step / 2.0 + phase * step;
pos = ceil (frac - width / 2.0 - 0.5) + 0.5 - frac + j;
printf ("%g %g\n",
pos,
pixman_fixed_to_double (*(p + phase * width + j)));
}
}
printf ("e\n");
fflush (stdout);
}
#endif
/* Create the parameter list for a SEPARABLE_CONVOLUTION filter /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
* with the given kernels and scale parameters * with the given kernels and scale parameters
*/ */
...@@ -313,38 +444,35 @@ pixman_filter_create_separable_convolution (int *n_values, ...@@ -313,38 +444,35 @@ pixman_filter_create_separable_convolution (int *n_values,
{ {
double sx = fabs (pixman_fixed_to_double (scale_x)); double sx = fabs (pixman_fixed_to_double (scale_x));
double sy = fabs (pixman_fixed_to_double (scale_y)); double sy = fabs (pixman_fixed_to_double (scale_y));
pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL; pixman_fixed_t *params;
int subsample_x, subsample_y; int subsample_x, subsample_y;
int width, height; int width, height;
width = filter_width (reconstruct_x, sample_x, sx);
subsample_x = (1 << subsample_bits_x); subsample_x = (1 << subsample_bits_x);
subsample_y = (1 << subsample_bits_y);
horz = create_1d_filter (&width, reconstruct_x, sample_x, sx, subsample_x); height = filter_width (reconstruct_y, sample_y, sy);
vert = create_1d_filter (&height, reconstruct_y, sample_y, sy, subsample_y); subsample_y = (1 << subsample_bits_y);
if (!horz || !vert)
goto out;
*n_values = 4 + width * subsample_x + height * subsample_y; *n_values = 4 + width * subsample_x + height * subsample_y;
params = malloc (*n_values * sizeof (pixman_fixed_t)); params = malloc (*n_values * sizeof (pixman_fixed_t));
if (!params) if (!params)
goto out; return NULL;
params[0] = pixman_int_to_fixed (width); params[0] = pixman_int_to_fixed (width);
params[1] = pixman_int_to_fixed (height); params[1] = pixman_int_to_fixed (height);
params[2] = pixman_int_to_fixed (subsample_bits_x); params[2] = pixman_int_to_fixed (subsample_bits_x);
params[3] = pixman_int_to_fixed (subsample_bits_y); params[3] = pixman_int_to_fixed (subsample_bits_y);
memcpy (params + 4, horz, create_1d_filter (width, reconstruct_x, sample_x, sx, subsample_x,
width * subsample_x * sizeof (pixman_fixed_t)); params + 4);
memcpy (params + 4 + width * subsample_x, vert, create_1d_filter (height, reconstruct_y, sample_y, sy, subsample_y,
height * subsample_y * sizeof (pixman_fixed_t)); params + 4 + width * subsample_x);
out: #ifdef PIXMAN_GNUPLOT
free (horz); gnuplot_filter(width, subsample_x, params + 4);
free (vert); #endif
return params; return params;
} }
...@@ -335,23 +335,32 @@ compute_image_info (pixman_image_t *image) ...@@ -335,23 +335,32 @@ compute_image_info (pixman_image_t *image)
{ {
flags |= FAST_PATH_NEAREST_FILTER; flags |= FAST_PATH_NEAREST_FILTER;
} }
else if ( else if (flags & FAST_PATH_AFFINE_TRANSFORM)
/* affine and integer translation components in matrix ... */ {
((flags & FAST_PATH_AFFINE_TRANSFORM) && /* Suppose the transform is
!pixman_fixed_frac (image->common.transform->matrix[0][2] | *
image->common.transform->matrix[1][2])) && * [ t00, t01, t02 ]
( * [ t10, t11, t12 ]
/* ... combined with a simple rotation */ * [ 0, 0, 1 ]
(flags & (FAST_PATH_ROTATE_90_TRANSFORM | *
FAST_PATH_ROTATE_180_TRANSFORM | * and the destination coordinates are (n + 0.5, m + 0.5). Then
FAST_PATH_ROTATE_270_TRANSFORM)) || * the transformed x coordinate is:
/* ... or combined with a simple non-rotated translation */ *
(image->common.transform->matrix[0][0] == pixman_fixed_1 && * tx = t00 * (n + 0.5) + t01 * (m + 0.5) + t02
image->common.transform->matrix[1][1] == pixman_fixed_1 && * = t00 * n + t01 * m + t02 + (t00 + t01) * 0.5
image->common.transform->matrix[0][1] == 0 && *
image->common.transform->matrix[1][0] == 0) * which implies that if t00, t01 and t02 are all integers
) * and (t00 + t01) is odd, then tx will be an integer plus 0.5,
) * which means a BILINEAR filter will reduce to NEAREST. The same
* applies in the y direction
*/
pixman_fixed_t (*t)[3] = image->common.transform->matrix;
if ((pixman_fixed_frac (
t[0][0] | t[0][1] | t[0][2] |
t[1][0] | t[1][1] | t[1][2]) == 0) &&
(pixman_fixed_to_int (
(t[0][0] + t[0][1]) & (t[1][0] + t[1][1])) % 2) == 1)
{ {
/* FIXME: there are some affine-test failures, showing that /* FIXME: there are some affine-test failures, showing that
* handling of BILINEAR and NEAREST filter is not quite * handling of BILINEAR and NEAREST filter is not quite
...@@ -368,6 +377,7 @@ compute_image_info (pixman_image_t *image) ...@@ -368,6 +377,7 @@ compute_image_info (pixman_image_t *image)
flags |= FAST_PATH_NEAREST_FILTER; flags |= FAST_PATH_NEAREST_FILTER;
} }
} }
}
break; break;
case PIXMAN_FILTER_CONVOLUTION: case PIXMAN_FILTER_CONVOLUTION:
...@@ -832,6 +842,10 @@ pixman_image_set_accessors (pixman_image_t * image, ...@@ -832,6 +842,10 @@ pixman_image_set_accessors (pixman_image_t * image,
if (image->type == BITS) if (image->type == BITS)
{ {
/* Accessors only work for <= 32 bpp. */
if (PIXMAN_FORMAT_BPP(image->bits.format) > 32)
return_if_fail (!read_func && !write_func);
image->bits.read_func = read_func; image->bits.read_func = read_func;
image->bits.write_func = write_func; image->bits.write_func = write_func;
......
#include <float.h>
#ifndef PIXMAN_PRIVATE_H #ifndef PIXMAN_PRIVATE_H
#define PIXMAN_PRIVATE_H #define PIXMAN_PRIVATE_H
...@@ -30,6 +28,7 @@ ...@@ -30,6 +28,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stddef.h> #include <stddef.h>
#include <float.h>
#include "pixman-compiler.h" #include "pixman-compiler.h"
......