app/Makefile.am app/paint_core.c moved brush subsampling kernels into its

2000-05-29  Sven Neumann  <sven@gimp.org>

        * app/Makefile.am
        * app/paint_core.c
        * app/paint_core_kernels.h: moved brush subsampling kernels
        into its own header file and generated a slightly different
        kernel (using the new kernelgen tool, see below). The new
        kernel simulates a circular brush instead of a rectangular
        one and gives slightly different (lighter) results.

        * app/gimage_mask.c: when stroking a selection, offset the
        points by 0.5 to align the brushes with the pixel grid. This
        lets you create 1-pixel wide rectangles and ellipses.

        * tools/Makefile.am
        * tools/kernelgen.c: simple hack to generate subsampling
        kernels.
This commit is contained in:
Sven Neumann 2000-05-29 08:40:29 +00:00 committed by Sven Neumann
parent 2090f17620
commit 9529e1e696
11 changed files with 323 additions and 138 deletions

View file

@ -1,3 +1,21 @@
2000-05-29 Sven Neumann <sven@gimp.org>
* app/Makefile.am
* app/paint_core.c
* app/paint_core_kernels.h: moved brush subsampling kernels
into its own header file and generated a slightly different
kernel (using the new kernelgen tool, see below). The new
kernel simulates a circular brush instead of a rectangular
one and gives slightly different (lighter) results.
* app/gimage_mask.c: when stroking a selection, offset the
points by 0.5 to align the brushes with the pixel grid. This
lets you create 1-pixel wide rectangles and ellipses.
* tools/Makefile.am
* tools/kernelgen.c: simple hack to generate subsampling
kernels.
2000-05-29 Tor Lillqvist <tml@iki.fi>
* gimprc.win32: Update to match Unix version.

View file

@ -312,6 +312,7 @@ gimp_SOURCES = \
paletteP.h \
paint_core.c \
paint_core.h \
paint_core_kernels.h \
paint_funcs.c \
paint_funcs.h \
paint_options.h \

View file

@ -545,19 +545,19 @@ gboolean
gimage_mask_stroke (GImage *gimage,
GimpDrawable *drawable)
{
BoundSeg *bs_in;
BoundSeg *bs_out;
gint num_segs_in;
gint num_segs_out;
BoundSeg *stroke_segs;
gint num_strokes;
gint seg;
gint offx, offy;
gint i;
gdouble *stroke_points;
gint cpnt;
Argument *return_vals;
gint nreturn_vals;
BoundSeg *bs_in;
BoundSeg *bs_out;
gint num_segs_in;
gint num_segs_out;
BoundSeg *stroke_segs;
gint num_strokes;
gint seg;
gint offx, offy;
gint i;
gdouble *stroke_points;
gint cpnt;
Argument *return_vals;
gint nreturn_vals;
if (! gimage_mask_boundary (gimage, &bs_in, &bs_out,
&num_segs_in, &num_segs_out))
@ -582,8 +582,10 @@ gimage_mask_stroke (GImage *gimage,
/* Largest array required (may be used in segments!) */
stroke_points = g_malloc (sizeof (gdouble) * 2 * (num_segs_in + 4));
stroke_points[cpnt++] = (gdouble)(stroke_segs[0].x1 - offx);
stroke_points[cpnt++] = (gdouble)(stroke_segs[0].y1 - offy);
/* we offset all coordinates by 0.5 to align the brush with the path */
stroke_points[cpnt++] = (gdouble)(stroke_segs[0].x1 - offx + 0.5);
stroke_points[cpnt++] = (gdouble)(stroke_segs[0].y1 - offy + 0.5);
for (i = 0; i < num_strokes; i++)
{
@ -592,12 +594,12 @@ gimage_mask_stroke (GImage *gimage,
stroke_segs[seg].y1 != -1 ||
stroke_segs[seg].y2 != -1))
{
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x2 - offx);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y2 - offy);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x2 - offx + 0.5);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y2 - offy + 0.5);
seg ++;
}
/* Close the stroke poitns up */
/* Close the stroke points up */
stroke_points[cpnt++] = stroke_points[0];
stroke_points[cpnt++] = stroke_points[1];
@ -621,8 +623,8 @@ gimage_mask_stroke (GImage *gimage,
cpnt = 0;
seg ++;
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x1 - offx);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y1 - offy);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x1 - offx + 0.5);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y1 - offy + 0.5);
}
/* cleanup */
@ -635,3 +637,9 @@ gimage_mask_stroke (GImage *gimage,
return TRUE;
}

View file

@ -545,19 +545,19 @@ gboolean
gimage_mask_stroke (GImage *gimage,
GimpDrawable *drawable)
{
BoundSeg *bs_in;
BoundSeg *bs_out;
gint num_segs_in;
gint num_segs_out;
BoundSeg *stroke_segs;
gint num_strokes;
gint seg;
gint offx, offy;
gint i;
gdouble *stroke_points;
gint cpnt;
Argument *return_vals;
gint nreturn_vals;
BoundSeg *bs_in;
BoundSeg *bs_out;
gint num_segs_in;
gint num_segs_out;
BoundSeg *stroke_segs;
gint num_strokes;
gint seg;
gint offx, offy;
gint i;
gdouble *stroke_points;
gint cpnt;
Argument *return_vals;
gint nreturn_vals;
if (! gimage_mask_boundary (gimage, &bs_in, &bs_out,
&num_segs_in, &num_segs_out))
@ -582,8 +582,10 @@ gimage_mask_stroke (GImage *gimage,
/* Largest array required (may be used in segments!) */
stroke_points = g_malloc (sizeof (gdouble) * 2 * (num_segs_in + 4));
stroke_points[cpnt++] = (gdouble)(stroke_segs[0].x1 - offx);
stroke_points[cpnt++] = (gdouble)(stroke_segs[0].y1 - offy);
/* we offset all coordinates by 0.5 to align the brush with the path */
stroke_points[cpnt++] = (gdouble)(stroke_segs[0].x1 - offx + 0.5);
stroke_points[cpnt++] = (gdouble)(stroke_segs[0].y1 - offy + 0.5);
for (i = 0; i < num_strokes; i++)
{
@ -592,12 +594,12 @@ gimage_mask_stroke (GImage *gimage,
stroke_segs[seg].y1 != -1 ||
stroke_segs[seg].y2 != -1))
{
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x2 - offx);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y2 - offy);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x2 - offx + 0.5);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y2 - offy + 0.5);
seg ++;
}
/* Close the stroke poitns up */
/* Close the stroke points up */
stroke_points[cpnt++] = stroke_points[0];
stroke_points[cpnt++] = stroke_points[1];
@ -621,8 +623,8 @@ gimage_mask_stroke (GImage *gimage,
cpnt = 0;
seg ++;
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x1 - offx);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y1 - offy);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].x1 - offx + 0.5);
stroke_points[cpnt++] = (gdouble)(stroke_segs[seg].y1 - offy + 0.5);
}
/* cleanup */
@ -635,3 +637,9 @@ gimage_mask_stroke (GImage *gimage,
return TRUE;
}

View file

@ -42,6 +42,8 @@
#include "libgimp/gimpmath.h"
#include "libgimp/gimpintl.h"
#include "paint_core_kernels.h"
/* target size */
#define TARGET_HEIGHT 15
#define TARGET_WIDTH 15
@ -96,7 +98,7 @@ static MaskBuf * pressure_brush;
static MaskBuf * solid_brush;
static MaskBuf * scale_brush = NULL;
static MaskBuf * scale_pixmap = NULL;
static MaskBuf * kernel_brushes[5][5];
static MaskBuf * kernel_brushes[SUBSAMPLE + 1][SUBSAMPLE + 1];
/* paint buffers utility functions */
@ -110,47 +112,6 @@ static void paint_line_pixmap_mask (GImage *, GimpDrawable *,
/***********************************************************************/
#define KERNEL_WIDTH 3
#define KERNEL_HEIGHT 3
/* Brush pixel subsampling kernels */
static const int subsample[5][5][9] = {
{
{ 64, 64, 0, 64, 64, 0, 0, 0, 0, },
{ 32, 96, 0, 32, 96, 0, 0, 0, 0, },
{ 0, 128, 0, 0, 128, 0, 0, 0, 0, },
{ 0, 96, 32, 0, 96, 32, 0, 0, 0, },
{ 0, 64, 64, 0, 64, 64, 0, 0, 0, },
},
{
{ 32, 32, 0, 96, 96, 0, 0, 0, 0, },
{ 16, 48, 0, 48, 144, 0, 0, 0, 0, },
{ 0, 64, 0, 0, 192, 0, 0, 0, 0, },
{ 0, 48, 16, 0, 144, 48, 0, 0, 0, },
{ 0, 32, 32, 0, 96, 96, 0, 0, 0, },
},
{
{ 0, 0, 0, 128, 128, 0, 0, 0, 0, },
{ 0, 0, 0, 64, 192, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 256, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 192, 64, 0, 0, 0, },
{ 0, 0, 0, 0, 128, 128, 0, 0, 0, },
},
{
{ 0, 0, 0, 96, 96, 0, 32, 32, 0, },
{ 0, 0, 0, 48, 144, 0, 16, 48, 0, },
{ 0, 0, 0, 0, 192, 0, 0, 64, 0, },
{ 0, 0, 0, 0, 144, 48, 0, 48, 16, },
{ 0, 0, 0, 0, 96, 96, 0, 32, 32, },
},
{
{ 0, 0, 0, 64, 64, 0, 64, 64, 0, },
{ 0, 0, 0, 32, 96, 0, 32, 96, 0, },
{ 0, 0, 0, 0, 128, 0, 0, 128, 0, },
{ 0, 0, 0, 0, 96, 32, 0, 96, 32, },
{ 0, 0, 0, 0, 64, 64, 0, 64, 64, },
},
};
static void
paint_core_sample_color (GimpDrawable *drawable,
@ -1196,12 +1157,12 @@ paint_core_subsample_mask (MaskBuf *mask,
gint r, s;
x += (x < 0) ? mask->width : 0;
left = x - floor(x) + 0.125;
index1 = (int) (left * 4);
left = x - floor(x);
index1 = (int) (left * (gdouble)(SUBSAMPLE + 1));
y += (y < 0) ? mask->height : 0;
left = y - floor(y) + 0.125;
index2 = (int) (left * 4);
left = y - floor(y);
index2 = (int) (left * (gdouble)(SUBSAMPLE + 1));
kernel = subsample[index2][index1];
@ -1209,8 +1170,8 @@ paint_core_subsample_mask (MaskBuf *mask,
!cache_invalid)
return kernel_brushes[index2][index1];
else if (mask != last_brush_mask || cache_invalid)
for (i = 0; i < 5; i++)
for (j = 0; j < 5; j++)
for (i = 0; i <= SUBSAMPLE; i++)
for (j = 0; j <= SUBSAMPLE; j++)
{
if (kernel_brushes[i][j])
mask_buf_free (kernel_brushes[i][j]);
@ -1219,7 +1180,8 @@ paint_core_subsample_mask (MaskBuf *mask,
last_brush_mask = mask;
cache_invalid = FALSE;
kernel_brushes[index2][index1] = mask_buf_new (mask->width + 2, mask->height + 2);
kernel_brushes[index2][index1] =
mask_buf_new (mask->width + 2, mask->height + 2);
dest = kernel_brushes[index2][index1];
m = mask_buf_data (mask);

49
app/paint_core_kernels.h Normal file
View file

@ -0,0 +1,49 @@
/* paint_core_kernels.h
*
* This file was generated using kernelgen as found in the tools dir.
* (threshold = 0.25)
*/
#define KERNEL_WIDTH 3
#define KERNEL_HEIGHT 3
#define SUBSAMPLE 4
/* Brush pixel subsampling kernels */
static const int subsample[5][5][9] = {
{
{ 64, 64, 0, 64, 64, 0, 0, 0, 0, },
{ 25, 102, 0, 25, 102, 0, 0, 0, 0, },
{ 0, 128, 0, 0, 128, 0, 0, 0, 0, },
{ 0, 102, 25, 0, 102, 25, 0, 0, 0, },
{ 0, 64, 64, 0, 64, 64, 0, 0, 0, }
},
{
{ 25, 25, 0, 102, 102, 0, 0, 0, 0, },
{ 6, 43, 0, 43, 162, 0, 0, 0, 0, },
{ 0, 50, 0, 0, 205, 0, 0, 0, 0, },
{ 0, 43, 6, 0, 162, 43, 0, 0, 0, },
{ 0, 25, 25, 0, 102, 102, 0, 0, 0, }
},
{
{ 0, 0, 0, 128, 128, 0, 0, 0, 0, },
{ 0, 0, 0, 50, 205, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 256, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 205, 50, 0, 0, 0, },
{ 0, 0, 0, 0, 128, 128, 0, 0, 0, }
},
{
{ 0, 0, 0, 102, 102, 0, 25, 25, 0, },
{ 0, 0, 0, 43, 162, 0, 6, 43, 0, },
{ 0, 0, 0, 0, 205, 0, 0, 50, 0, },
{ 0, 0, 0, 0, 162, 43, 0, 43, 6, },
{ 0, 0, 0, 0, 102, 102, 0, 25, 25, }
},
{
{ 0, 0, 0, 64, 64, 0, 64, 64, 0, },
{ 0, 0, 0, 25, 102, 0, 25, 102, 0, },
{ 0, 0, 0, 0, 128, 0, 0, 128, 0, },
{ 0, 0, 0, 0, 102, 25, 0, 102, 25, },
{ 0, 0, 0, 0, 64, 64, 0, 64, 64, }
}
};

View file

@ -42,6 +42,8 @@
#include "libgimp/gimpmath.h"
#include "libgimp/gimpintl.h"
#include "paint_core_kernels.h"
/* target size */
#define TARGET_HEIGHT 15
#define TARGET_WIDTH 15
@ -96,7 +98,7 @@ static MaskBuf * pressure_brush;
static MaskBuf * solid_brush;
static MaskBuf * scale_brush = NULL;
static MaskBuf * scale_pixmap = NULL;
static MaskBuf * kernel_brushes[5][5];
static MaskBuf * kernel_brushes[SUBSAMPLE + 1][SUBSAMPLE + 1];
/* paint buffers utility functions */
@ -110,47 +112,6 @@ static void paint_line_pixmap_mask (GImage *, GimpDrawable *,
/***********************************************************************/
#define KERNEL_WIDTH 3
#define KERNEL_HEIGHT 3
/* Brush pixel subsampling kernels */
static const int subsample[5][5][9] = {
{
{ 64, 64, 0, 64, 64, 0, 0, 0, 0, },
{ 32, 96, 0, 32, 96, 0, 0, 0, 0, },
{ 0, 128, 0, 0, 128, 0, 0, 0, 0, },
{ 0, 96, 32, 0, 96, 32, 0, 0, 0, },
{ 0, 64, 64, 0, 64, 64, 0, 0, 0, },
},
{
{ 32, 32, 0, 96, 96, 0, 0, 0, 0, },
{ 16, 48, 0, 48, 144, 0, 0, 0, 0, },
{ 0, 64, 0, 0, 192, 0, 0, 0, 0, },
{ 0, 48, 16, 0, 144, 48, 0, 0, 0, },
{ 0, 32, 32, 0, 96, 96, 0, 0, 0, },
},
{
{ 0, 0, 0, 128, 128, 0, 0, 0, 0, },
{ 0, 0, 0, 64, 192, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 256, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 192, 64, 0, 0, 0, },
{ 0, 0, 0, 0, 128, 128, 0, 0, 0, },
},
{
{ 0, 0, 0, 96, 96, 0, 32, 32, 0, },
{ 0, 0, 0, 48, 144, 0, 16, 48, 0, },
{ 0, 0, 0, 0, 192, 0, 0, 64, 0, },
{ 0, 0, 0, 0, 144, 48, 0, 48, 16, },
{ 0, 0, 0, 0, 96, 96, 0, 32, 32, },
},
{
{ 0, 0, 0, 64, 64, 0, 64, 64, 0, },
{ 0, 0, 0, 32, 96, 0, 32, 96, 0, },
{ 0, 0, 0, 0, 128, 0, 0, 128, 0, },
{ 0, 0, 0, 0, 96, 32, 0, 96, 32, },
{ 0, 0, 0, 0, 64, 64, 0, 64, 64, },
},
};
static void
paint_core_sample_color (GimpDrawable *drawable,
@ -1196,12 +1157,12 @@ paint_core_subsample_mask (MaskBuf *mask,
gint r, s;
x += (x < 0) ? mask->width : 0;
left = x - floor(x) + 0.125;
index1 = (int) (left * 4);
left = x - floor(x);
index1 = (int) (left * (gdouble)(SUBSAMPLE + 1));
y += (y < 0) ? mask->height : 0;
left = y - floor(y) + 0.125;
index2 = (int) (left * 4);
left = y - floor(y);
index2 = (int) (left * (gdouble)(SUBSAMPLE + 1));
kernel = subsample[index2][index1];
@ -1209,8 +1170,8 @@ paint_core_subsample_mask (MaskBuf *mask,
!cache_invalid)
return kernel_brushes[index2][index1];
else if (mask != last_brush_mask || cache_invalid)
for (i = 0; i < 5; i++)
for (j = 0; j < 5; j++)
for (i = 0; i <= SUBSAMPLE; i++)
for (j = 0; j <= SUBSAMPLE; j++)
{
if (kernel_brushes[i][j])
mask_buf_free (kernel_brushes[i][j]);
@ -1219,7 +1180,8 @@ paint_core_subsample_mask (MaskBuf *mask,
last_brush_mask = mask;
cache_invalid = FALSE;
kernel_brushes[index2][index1] = mask_buf_new (mask->width + 2, mask->height + 2);
kernel_brushes[index2][index1] =
mask_buf_new (mask->width + 2, mask->height + 2);
dest = kernel_brushes[index2][index1];
m = mask_buf_data (mask);

View file

@ -0,0 +1,49 @@
/* paint_core_kernels.h
*
* This file was generated using kernelgen as found in the tools dir.
* (threshold = 0.25)
*/
#define KERNEL_WIDTH 3
#define KERNEL_HEIGHT 3
#define SUBSAMPLE 4
/* Brush pixel subsampling kernels */
static const int subsample[5][5][9] = {
{
{ 64, 64, 0, 64, 64, 0, 0, 0, 0, },
{ 25, 102, 0, 25, 102, 0, 0, 0, 0, },
{ 0, 128, 0, 0, 128, 0, 0, 0, 0, },
{ 0, 102, 25, 0, 102, 25, 0, 0, 0, },
{ 0, 64, 64, 0, 64, 64, 0, 0, 0, }
},
{
{ 25, 25, 0, 102, 102, 0, 0, 0, 0, },
{ 6, 43, 0, 43, 162, 0, 0, 0, 0, },
{ 0, 50, 0, 0, 205, 0, 0, 0, 0, },
{ 0, 43, 6, 0, 162, 43, 0, 0, 0, },
{ 0, 25, 25, 0, 102, 102, 0, 0, 0, }
},
{
{ 0, 0, 0, 128, 128, 0, 0, 0, 0, },
{ 0, 0, 0, 50, 205, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 256, 0, 0, 0, 0, },
{ 0, 0, 0, 0, 205, 50, 0, 0, 0, },
{ 0, 0, 0, 0, 128, 128, 0, 0, 0, }
},
{
{ 0, 0, 0, 102, 102, 0, 25, 25, 0, },
{ 0, 0, 0, 43, 162, 0, 6, 43, 0, },
{ 0, 0, 0, 0, 205, 0, 0, 50, 0, },
{ 0, 0, 0, 0, 162, 43, 0, 43, 6, },
{ 0, 0, 0, 0, 102, 102, 0, 25, 25, }
},
{
{ 0, 0, 0, 64, 64, 0, 64, 64, 0, },
{ 0, 0, 0, 25, 102, 0, 25, 102, 0, },
{ 0, 0, 0, 0, 128, 0, 0, 128, 0, },
{ 0, 0, 0, 0, 102, 25, 0, 102, 25, },
{ 0, 0, 0, 0, 64, 64, 0, 64, 64, }
}
};

View file

@ -1,2 +1,3 @@
Makefile
Makefile.in
kernelgen

View file

@ -11,3 +11,5 @@ endif
#endif
SUBDIRS = $(D_pdbgen) #$(D_gcg)
EXTRA_DIST = kernelgen.c

125
tools/kernelgen.c Normal file
View file

@ -0,0 +1,125 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* kernel_gen -- Copyright (C) 2000 Sven Neumann <sven@gimp.org>
* Simple hack to create subsampling kernels for the brushes
* as used in app/paint_core.c.
* If you want to play with it, change some of the #defines at the
* top and copy the output to apps/paint_core_kernels.h.
*
* 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 of the License, 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include <stdio.h>
#define STEPS 64
#define KERNEL_WIDTH 3 /* changing these makes no sense */
#define KERNEL_HEIGHT 3 /* changing these makes no sense */
#define SUBSAMPLE 4
#define THRESHOLD 0.25 /* try to change this one */
#define SQR(x) ((x) * (x))
static void
create_kernel (double x,
double y)
{
double value[KERNEL_WIDTH][KERNEL_HEIGHT];
double dist_x;
double dist_y;
double sum;
double w;
int i, j;
memset (value, 0, KERNEL_WIDTH * KERNEL_HEIGHT * sizeof (double));
sum = 0.0;
x += 1.0;
y += 1.0;
for (j = 0; j < STEPS * KERNEL_HEIGHT; j++)
{
dist_y = y - (((double)j + 0.5) / (double)STEPS);
for (i = 0; i < STEPS * KERNEL_WIDTH; i++)
{
dist_x = x - (((double)i + 0.5) / (double)STEPS);
/* I've tried to use a gauss function here instead of a
threshold, but the result was not that impressive. */
w = (SQR (dist_x) + SQR (dist_y)) < THRESHOLD ? 1.0 : 0.0;
value[i / STEPS][j / STEPS] += w;
sum += w;
}
}
for (j = 0; j < KERNEL_HEIGHT; j++)
{
for (i = 0; i < KERNEL_WIDTH; i++)
{
w = 256.0 * (value[i][j] / sum);
printf (" %3d,", (int)w);
}
}
}
int
main (int argc,
char **argv)
{
int i, j;
double x, y;
printf ("/* paint_core_kernels.h\n"
" *\n"
" * This file was generated using kernelgen as found in the tools dir.\n");
printf (" * (threshold = %g)\n", THRESHOLD);
printf (" */\n\n");
printf ("#define KERNEL_WIDTH %d\n", KERNEL_WIDTH);
printf ("#define KERNEL_HEIGHT %d\n", KERNEL_HEIGHT);
printf ("#define SUBSAMPLE %d\n", SUBSAMPLE);
printf ("\n\n");
printf ("/* Brush pixel subsampling kernels */\n");
printf ("static const int subsample[%d][%d][%d] = {\n",
SUBSAMPLE + 1, SUBSAMPLE + 1, KERNEL_WIDTH * KERNEL_HEIGHT);
for (j = 0; j <= SUBSAMPLE; j++)
{
y = (double)j / (double)(SUBSAMPLE);
printf (" {\n");
for (i = 0; i <= SUBSAMPLE; i++)
{
x = (double)i / (double)(SUBSAMPLE);
printf (" {");
create_kernel (x, y);
printf (" }%c\n", i < SUBSAMPLE ? ',' : ' ');
}
printf (" }%c\n", j < SUBSAMPLE ? ',' : ' ');
}
printf ("};\n");
}