mirror of https://github.com/GNOME/gimp.git
2709 lines
74 KiB
C
2709 lines
74 KiB
C
/*
|
|
* jigsaw - a plug-in for the GIMP
|
|
*
|
|
* Copyright (C) Nigel Wetten
|
|
*
|
|
* 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.
|
|
*
|
|
* Contact info: nigel@cs.nwu.edu
|
|
*
|
|
* Version: 1.0.0
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
#include "libgimp/gimp.h"
|
|
|
|
typedef enum {BEZIER_1, BEZIER_2} style_t;
|
|
typedef enum {LEFT, RIGHT, UP, DOWN} bump_t;
|
|
|
|
|
|
static void query(void);
|
|
static void run(gchar *name, gint nparams, GParam *param,
|
|
gint *nreturn_vals, GParam **return_vals);
|
|
static gint jigsaw(void);
|
|
static void run_callback(GtkWidget *widget, gpointer data);
|
|
static void dialog_box(void);
|
|
static void dialog_close_callback(GtkWidget *widget, gpointer data);
|
|
static void entry_callback(GtkWidget *widget, gpointer data);
|
|
static void entry_double_callback(GtkWidget *widget, gpointer data);
|
|
static void radio_button_primitive_callback(GtkWidget *widget, gpointer data);
|
|
static void adjustment_callback(GtkAdjustment *adjustment, gpointer data);
|
|
static void adjustment_double_callback(GtkAdjustment *adjustment,
|
|
gpointer data);
|
|
static void check_button_callback(GtkWidget *widget, gpointer data);
|
|
|
|
static void draw_jigsaw(guchar *buffer, gint width, gint height, gint bytes);
|
|
static void draw_vertical_border(guchar *buffer, gint width, gint height,
|
|
gint bytes, gint x_offset, gint ytiles,
|
|
gint blend_lines, gdouble blend_amount);
|
|
static void draw_horizontal_border(guchar *buffer, gint width,
|
|
gint bytes, gint y_offset, gint xtiles,
|
|
gint blend_lines, gdouble blend_amount);
|
|
static void draw_vertical_line(guchar *buffer, gint width, gint bytes,
|
|
gint px[2], gint py[2]);
|
|
static void draw_horizontal_line(guchar *buffer, gint width, gint bytes,
|
|
gint px[2], gint py[2]);
|
|
static void darken_vertical_line(guchar *buffer, gint width, gint bytes,
|
|
gint *px, gint *py, gdouble delta);
|
|
static void lighten_vertical_line(guchar *buffer, gint width, gint bytes,
|
|
gint *px, gint *py, gdouble delta);
|
|
static void darken_horizontal_line(guchar *buffer, gint width, gint bytes,
|
|
gint *px, gint *py, gdouble delta);
|
|
static void lighten_horizontal_line(guchar *buffer, gint width, gint bytes,
|
|
gint *px, gint *py, gdouble delta);
|
|
static void draw_right_bump(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint curve_start_offset,
|
|
gint steps);
|
|
static void draw_left_bump(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint curve_start_offset,
|
|
gint steps);
|
|
static void draw_up_bump(guchar *buffer, gint width, gint bytes,
|
|
gint y_offset, gint curve_start_offset,
|
|
gint steps);
|
|
static void draw_down_bump(guchar *buffer, gint width, gint bytes,
|
|
gint y_offset, gint curve_start_offset,
|
|
gint steps);
|
|
static void darken_right_bump(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint curve_start_offset,
|
|
gint steps, gdouble delta, gint counter);
|
|
static void lighten_right_bump(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint curve_start_offset,
|
|
gint steps, gdouble delta, gint counter);
|
|
static void darken_left_bump(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint curve_start_offset,
|
|
gint steps, gdouble delta, gint counter);
|
|
static void lighten_left_bump(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint curve_start_offset,
|
|
gint steps, gdouble delta, gint counter);
|
|
static void darken_up_bump(guchar *buffer, gint width, gint bytes,
|
|
gint y_offset, gint curve_start_offest,
|
|
gint steps, gdouble delta, gint counter);
|
|
static void lighten_up_bump(guchar *buffer, gint width, gint bytes,
|
|
gint y_offset, gint curve_start_offset,
|
|
gint steps, gdouble delta, gint counter);
|
|
static void darken_down_bump(guchar *buffer, gint width, gint bytes,
|
|
gint y_offset, gint curve_start_offset,
|
|
gint steps, gdouble delta, gint counter);
|
|
static void lighten_down_bump(guchar *buffer, gint width, gint bytes,
|
|
gint y_offset, gint curve_start_offset,
|
|
gint steps, gdouble delta, gint counter);
|
|
static void generate_grid(gint width, gint height, gint xtiles, gint ytiles,
|
|
gint *x, gint *y);
|
|
static void generate_bezier(gint px[4], gint py[4], gint steps,
|
|
gint *cachex, gint *cachey);
|
|
static void malloc_cache(void);
|
|
static void free_cache(void);
|
|
static void init_right_bump(gint width, gint height);
|
|
static void init_left_bump(gint width, gint height);
|
|
static void init_up_bump(gint width, gint height);
|
|
static void init_down_bump(gint width, gint height);
|
|
static void draw_bezier_line(guchar *buffer, gint width, gint bytes,
|
|
gint steps, gint *cx, gint *cy);
|
|
static void darken_bezier_line(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint y_offset, gint steps,
|
|
gint *cx, gint *cy, gdouble delta);
|
|
static void lighten_bezier_line(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint y_offset, gint steps,
|
|
gint *cx, gint *cy, gdouble delta);
|
|
static void draw_bezier_vertical_border(guchar *buffer, gint width,
|
|
gint height, gint bytes,
|
|
gint x_offset, gint xtiles,
|
|
gint ytiles, gint blend_lines,
|
|
gdouble blend_amount, gint steps);
|
|
static void draw_bezier_horizontal_border(guchar *buffer, gint width,
|
|
gint height, gint bytes,
|
|
gint x_offset, gint xtiles,
|
|
gint ytiles, gint blend_lines,
|
|
gdouble blend_amount, gint steps);
|
|
static void check_config(gint width, gint height);
|
|
|
|
|
|
|
|
#define PLUG_IN_NAME "jigsaw"
|
|
#define PLUG_IN_STORAGE "jigsaw-storage"
|
|
|
|
#define XFACTOR2 0.0833
|
|
#define XFACTOR3 0.2083
|
|
#define XFACTOR4 0.2500
|
|
|
|
#define XFACTOR5 0.2500
|
|
#define XFACTOR6 0.2083
|
|
#define XFACTOR7 0.0833
|
|
|
|
#define YFACTOR2 0.1000
|
|
#define YFACTOR3 0.2200
|
|
#define YFACTOR4 0.1000
|
|
|
|
#define YFACTOR5 0.1000
|
|
#define YFACTOR6 0.4666
|
|
#define YFACTOR7 0.1000
|
|
#define YFACTOR8 0.2000
|
|
|
|
#define MAX_VALUE 255
|
|
#define MIN_VALUE 0
|
|
#define DELTA 0.15
|
|
|
|
#define BLACK_R 30
|
|
#define BLACK_G 30
|
|
#define BLACK_B 30
|
|
|
|
#define WALL_XFACTOR2 0.05
|
|
#define WALL_XFACTOR3 0.05
|
|
#define WALL_YFACTOR2 0.05
|
|
#define WALL_YFACTOR3 0.05
|
|
|
|
#define WALL_XCONS2 0.2
|
|
#define WALL_XCONS3 0.3
|
|
#define WALL_YCONS2 0.2
|
|
#define WALL_YCONS3 0.3
|
|
|
|
#define FUDGE 1.2
|
|
|
|
#define MIN_XTILES 1
|
|
#define MAX_XTILES 20
|
|
#define MIN_YTILES 1
|
|
#define MAX_YTILES 20
|
|
#define MIN_BLEND_LINES 0
|
|
#define MAX_BLEND_LINES 10
|
|
#define MIN_BLEND_AMOUNT 0
|
|
#define MAX_BLEND_AMOUNT 1.0
|
|
|
|
#define SCALE_WIDTH 200
|
|
#define ENTRY_WIDTH 40
|
|
|
|
#define XTILES_TEXT "Number of pieces going across"
|
|
#define YTILES_TEXT "Number of pieces going down"
|
|
#define BLEND_LINES_TEXT "Degree of slope of each piece's edge"
|
|
#define BLEND_AMOUNT_TEXT "The amount of highlighting on the edges of each piece"
|
|
#define SQUARE_TEXT "Each piece has straight sides"
|
|
#define CURVE_TEXT "Each piece has curved sides"
|
|
#define DISABLE_TEXT "Toggle Tooltips on/off"
|
|
|
|
#define DRAW_POINT(buffer, index) \
|
|
do { \
|
|
buffer[index] = BLACK_R; \
|
|
buffer[index+1] = BLACK_G; \
|
|
buffer[index+2] = BLACK_B; \
|
|
} while (0)
|
|
|
|
#define DARKEN_POINT(buffer, index, delta, temp) \
|
|
do { \
|
|
temp = buffer[index]; \
|
|
temp -= buffer[index] * delta; \
|
|
if (temp < MIN_VALUE) temp = MIN_VALUE; \
|
|
buffer[index] = temp; \
|
|
temp = buffer[index+1]; \
|
|
temp -= buffer[index+1] * delta; \
|
|
if (temp < MIN_VALUE) temp = MIN_VALUE; \
|
|
buffer[index+1] = temp; \
|
|
temp = buffer[index+2]; \
|
|
temp -= buffer[index+2] * delta; \
|
|
if (temp < MIN_VALUE) temp = MIN_VALUE; \
|
|
buffer[index+2] = temp; \
|
|
} while (0)
|
|
|
|
#define LIGHTEN_POINT(buffer, index, delta, temp) \
|
|
do { \
|
|
temp = buffer[index] * delta; \
|
|
temp += buffer[index]; \
|
|
if (temp > MAX_VALUE) temp = MAX_VALUE; \
|
|
buffer[index] = temp; \
|
|
temp = buffer[index+1] * delta; \
|
|
temp += buffer[index+1]; \
|
|
if (temp > MAX_VALUE) temp = MAX_VALUE; \
|
|
buffer[index+1] = temp; \
|
|
temp = buffer[index+2] * delta; \
|
|
temp += buffer[index+2]; \
|
|
if (temp > MAX_VALUE) temp = MAX_VALUE; \
|
|
buffer[index+2] = temp; \
|
|
} while (0)
|
|
|
|
|
|
GPlugInInfo PLUG_IN_INFO =
|
|
{
|
|
NULL,
|
|
NULL,
|
|
query,
|
|
run
|
|
};
|
|
|
|
struct config_tag
|
|
{
|
|
gint x;
|
|
gint y;
|
|
style_t style;
|
|
gint blend_lines;
|
|
gdouble blend_amount;
|
|
};
|
|
|
|
|
|
typedef struct config_tag config_t;
|
|
|
|
static config_t config =
|
|
{
|
|
5,
|
|
5,
|
|
BEZIER_1,
|
|
3,
|
|
0.5
|
|
};
|
|
|
|
struct globals_tag
|
|
{
|
|
GDrawable *drawable;
|
|
gint *cachex1[4];
|
|
gint *cachex2[4];
|
|
gint *cachey1[4];
|
|
gint *cachey2[4];
|
|
gint steps[4];
|
|
gint *gridx;
|
|
gint *gridy;
|
|
gint **blend_outer_cachex1[4];
|
|
gint **blend_outer_cachex2[4];
|
|
gint **blend_outer_cachey1[4];
|
|
gint **blend_outer_cachey2[4];
|
|
gint **blend_inner_cachex1[4];
|
|
gint **blend_inner_cachex2[4];
|
|
gint **blend_inner_cachey1[4];
|
|
gint **blend_inner_cachey2[4];
|
|
gint dialog_result;
|
|
gint tooltips;
|
|
};
|
|
|
|
typedef struct globals_tag globals_t;
|
|
|
|
static globals_t globals =
|
|
{
|
|
0,
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
0,
|
|
0,
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
{0, 0, 0, 0},
|
|
-1,
|
|
1
|
|
};
|
|
|
|
MAIN()
|
|
|
|
static void
|
|
query(void)
|
|
{
|
|
static GParamDef args[] =
|
|
{
|
|
{ PARAM_INT32, "run_mode", "Interactive, Non-interactive, Last-Vals"},
|
|
{ PARAM_IMAGE, "image", "Input image"},
|
|
{ PARAM_DRAWABLE, "drawable", "Input drawable"},
|
|
{ PARAM_INT32, "x", "Number of tiles across > 0"},
|
|
{ PARAM_INT32, "y", "Number of tiles down > 0"},
|
|
{ PARAM_INT32, "style", "The style/shape of the jigsaw puzzle, 0 or 1"},
|
|
{ PARAM_INT32, "blend_lines", "Number of lines for shading bevels >= 0"},
|
|
{ PARAM_FLOAT, "blend_amount", "The power of the light highlights 0 =< 5"}
|
|
};
|
|
static GParamDef *return_vals = NULL;
|
|
static gint nargs = sizeof(args) / sizeof(args[0]);
|
|
static gint nreturn_vals = 0;
|
|
|
|
gimp_install_procedure("plug_in_jigsaw",
|
|
"Renders a jigsaw puzzle look",
|
|
"Jigsaw puzzle look",
|
|
"Nigel Wetten",
|
|
"Nigel Wetten",
|
|
"1998",
|
|
"<Image>/Filters/Render/Jigsaw",
|
|
"RGB*",
|
|
PROC_PLUG_IN,
|
|
nargs, nreturn_vals,
|
|
args, return_vals);
|
|
|
|
return;
|
|
} /* query */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
run(gchar *name, gint nparams, GParam *param, gint *nreturn_vals,
|
|
GParam **return_vals)
|
|
{
|
|
static GParam values[1];
|
|
GDrawable *drawable;
|
|
GRunModeType run_mode;
|
|
GStatusType status = STATUS_SUCCESS;
|
|
|
|
run_mode = param[0].data.d_int32;
|
|
drawable = gimp_drawable_get(param[2].data.d_drawable);
|
|
globals.drawable = drawable;
|
|
gimp_tile_cache_ntiles(drawable->width / gimp_tile_width() + 1);
|
|
switch (run_mode)
|
|
{
|
|
case RUN_NONINTERACTIVE:
|
|
if (nparams == 8)
|
|
{
|
|
config.x = param[3].data.d_int32;
|
|
config.y = param[4].data.d_int32;
|
|
config.style = param[5].data.d_int32;
|
|
config.blend_lines = param[6].data.d_int32;
|
|
config.blend_amount = param[7].data.d_float;
|
|
if (jigsaw() == -1)
|
|
{
|
|
status = STATUS_EXECUTION_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_CALLING_ERROR;
|
|
}
|
|
break;
|
|
|
|
case RUN_INTERACTIVE:
|
|
gimp_get_data("plug_in_jigsaw", &config);
|
|
gimp_get_data(PLUG_IN_STORAGE, &globals.tooltips);
|
|
dialog_box();
|
|
if (globals.dialog_result == -1)
|
|
{
|
|
status = STATUS_EXECUTION_ERROR;
|
|
break;
|
|
}
|
|
gimp_progress_init("Assembling Jigsaw");
|
|
if (jigsaw() == -1)
|
|
{
|
|
status = STATUS_CALLING_ERROR;
|
|
break;
|
|
}
|
|
gimp_set_data("plug_in_jigsaw", &config, sizeof(config_t));
|
|
gimp_set_data(PLUG_IN_STORAGE, &globals.tooltips,
|
|
sizeof(globals.tooltips));
|
|
gimp_displays_flush();
|
|
break;
|
|
|
|
case RUN_WITH_LAST_VALS:
|
|
gimp_get_data("plug_in_jigsaw", &config);
|
|
if (jigsaw() == -1)
|
|
{
|
|
status = STATUS_EXECUTION_ERROR;
|
|
gimp_message("An execution error occured.");
|
|
}
|
|
else
|
|
{
|
|
gimp_displays_flush();
|
|
}
|
|
|
|
} /* switch */
|
|
|
|
gimp_drawable_detach(drawable);
|
|
|
|
*nreturn_vals = 1;
|
|
*return_vals = values;
|
|
values[0].type = PARAM_STATUS;
|
|
values[0].data.d_status = status;
|
|
|
|
return;
|
|
} /* run */
|
|
|
|
/*****/
|
|
|
|
static gint
|
|
jigsaw(void)
|
|
{
|
|
GPixelRgn src_pr, dest_pr;
|
|
guchar *buffer;
|
|
GDrawable *drawable = globals.drawable;
|
|
gint width = drawable->width;
|
|
gint height = drawable->height;
|
|
gint bytes = drawable->bpp;
|
|
gint buffer_size = bytes * width * height;
|
|
|
|
srand((gint)NULL);
|
|
|
|
|
|
/* setup image buffer */
|
|
gimp_pixel_rgn_init(&src_pr, drawable, 0, 0, width, height, FALSE, FALSE);
|
|
gimp_pixel_rgn_init(&dest_pr, drawable, 0, 0, width, height, TRUE, TRUE);
|
|
buffer = g_malloc(buffer_size);
|
|
gimp_pixel_rgn_get_rect(&src_pr, buffer, 0, 0, width, height);
|
|
|
|
check_config(width, height);
|
|
globals.steps[LEFT] = globals.steps[RIGHT] = globals.steps[UP]
|
|
= globals.steps[DOWN] = (config.x < config.y) ?
|
|
(width / config.x * 2) : (height / config.y * 2);
|
|
|
|
malloc_cache();
|
|
draw_jigsaw(buffer, width, height, bytes);
|
|
free_cache();
|
|
/* cleanup */
|
|
gimp_pixel_rgn_set_rect(&dest_pr, buffer, 0, 0, width, height);
|
|
gimp_drawable_flush(drawable);
|
|
gimp_drawable_merge_shadow(drawable->id, TRUE);
|
|
gimp_drawable_update(drawable->id, 0, 0, width, height);
|
|
g_free(buffer);
|
|
|
|
return 0;
|
|
} /* jigsaw */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
generate_bezier(gint px[4], gint py[4], gint steps,
|
|
gint *cachex, gint *cachey)
|
|
{
|
|
gdouble t = 0.0;
|
|
gdouble sigma = 1.0 / steps;
|
|
gint i;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
gdouble t2, t3, x, y, t_1;
|
|
|
|
t += sigma;
|
|
t2 = t * t;
|
|
t3 = t2 * t;
|
|
t_1 = 1 - t;
|
|
x = t_1 * t_1 * t_1 * px[0]
|
|
+ 3 * t * t_1 * t_1 * px[1]
|
|
+ 3 * t2 * t_1 * px[2]
|
|
+ t3 * px[3];
|
|
y = t_1 * t_1 * t_1 * py[0]
|
|
+ 3 * t * t_1 * t_1 * py[1]
|
|
+ 3 * t2 * t_1 * py[2]
|
|
+ t3 * py[3];
|
|
cachex[i] = (gint) (x + 0.2);
|
|
cachey[i] = (gint) (y + 0.2);
|
|
} /* for */
|
|
return;
|
|
} /* generate_bezier */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_jigsaw(guchar *buffer, gint width, gint height, gint bytes)
|
|
{
|
|
gint i;
|
|
gint *x, *y;
|
|
gint xtiles = config.x;
|
|
gint ytiles = config.y;
|
|
gint xlines = xtiles - 1;
|
|
gint ylines = ytiles - 1;
|
|
gint blend_lines = config.blend_lines;
|
|
gdouble blend_amount = config.blend_amount;
|
|
gint steps = globals.steps[RIGHT];
|
|
style_t style = config.style;
|
|
gint progress_total = xlines + ylines - 1;
|
|
|
|
globals.gridx = g_malloc(sizeof(gint) * xtiles);
|
|
globals.gridy = g_malloc(sizeof(gint) * ytiles);
|
|
x = globals.gridx;
|
|
y = globals.gridy;
|
|
|
|
generate_grid(width, height, xtiles, ytiles, globals.gridx, globals.gridy);
|
|
|
|
init_right_bump(width, height);
|
|
init_left_bump(width, height);
|
|
init_up_bump(width, height);
|
|
init_down_bump(width, height);
|
|
|
|
if (style == BEZIER_1)
|
|
{
|
|
for (i = 0; i < xlines; i++)
|
|
{
|
|
draw_vertical_border(buffer, width, height, bytes, x[i], ytiles,
|
|
blend_lines, blend_amount);
|
|
gimp_progress_update((gdouble) i / (gdouble) progress_total);
|
|
}
|
|
for (i = 0; i < ylines; i++)
|
|
{
|
|
draw_horizontal_border(buffer, width, bytes, y[i], xtiles,
|
|
blend_lines, blend_amount);
|
|
gimp_progress_update((gdouble) (i + xlines)
|
|
/ (gdouble) progress_total);
|
|
}
|
|
}
|
|
else if (style == BEZIER_2)
|
|
{
|
|
for (i = 0; i < xlines; i++)
|
|
{
|
|
draw_bezier_vertical_border(buffer, width, height, bytes, x[i],
|
|
xtiles, ytiles, blend_lines,
|
|
blend_amount, steps);
|
|
gimp_progress_update((gdouble) i / (gdouble) progress_total);
|
|
}
|
|
for (i = 0; i < ylines; i++)
|
|
{
|
|
draw_bezier_horizontal_border(buffer, width, height, bytes, y[i],
|
|
xtiles, ytiles, blend_lines,
|
|
blend_amount, steps);
|
|
gimp_progress_update((gdouble) (i + xlines)
|
|
/ (gdouble) progress_total);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("draw_jigsaw: bad style\n");
|
|
exit(1);
|
|
}
|
|
g_free(globals.gridx);
|
|
g_free(globals.gridy);
|
|
|
|
return;
|
|
} /* draw_jigsaw */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_vertical_border(guchar *buffer, gint width, gint height, gint bytes,
|
|
gint x_offset, gint ytiles, gint blend_lines,
|
|
gdouble blend_amount)
|
|
{
|
|
gint i, j;
|
|
gint tile_height = height / ytiles;
|
|
gint tile_height_eighth = tile_height / 8;
|
|
gint curve_start_offset = 3 * tile_height_eighth;
|
|
gint curve_end_offset = curve_start_offset + 2 * tile_height_eighth;
|
|
gint px[2], py[2];
|
|
gint ly[2], dy[2];
|
|
gint y_offset = 0;
|
|
gdouble delta;
|
|
gdouble sigma = blend_amount / blend_lines;
|
|
gint right;
|
|
bump_t style_index;
|
|
|
|
for (i = 0; i < ytiles; i++)
|
|
{
|
|
right = rand() & 1;
|
|
if (right)
|
|
{
|
|
style_index = RIGHT;
|
|
}
|
|
else
|
|
{
|
|
style_index = LEFT;
|
|
}
|
|
|
|
/* first straight line from top downwards */
|
|
px[0] = px[1] = x_offset;
|
|
py[0] = y_offset; py[1] = y_offset + curve_start_offset - 1;
|
|
draw_vertical_line(buffer, width, bytes, px, py);
|
|
delta = blend_amount;
|
|
dy[0] = ly[0] = py[0]; dy[1] = ly[1] = py[1];
|
|
if (!right)
|
|
{
|
|
ly[1] += blend_lines + 2;
|
|
}
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
dy[0]++; dy[1]--; ly[0]++; ly[1]--;
|
|
px[0] = x_offset - j - 1;
|
|
darken_vertical_line(buffer, width, bytes, px, dy, delta);
|
|
px[0] = x_offset + j + 1;
|
|
lighten_vertical_line(buffer, width, bytes, px, ly, delta);
|
|
delta -= sigma;
|
|
}
|
|
|
|
/* top half of curve */
|
|
if (right)
|
|
{
|
|
draw_right_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[RIGHT]);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
/* use to be -j -1 */
|
|
darken_right_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[RIGHT], delta, j);
|
|
/* use to be +j + 1 */
|
|
lighten_right_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[RIGHT], delta, j);
|
|
delta -= sigma;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
draw_left_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[LEFT]);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
/* use to be -j -1 */
|
|
darken_left_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[LEFT], delta, j);
|
|
/* use to be -j - 1 */
|
|
lighten_left_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[LEFT], delta, j);
|
|
delta -= sigma;
|
|
}
|
|
}
|
|
/* bottom straight line of a tile wall */
|
|
px[0] = px[1] = x_offset;
|
|
py[0] = y_offset + curve_end_offset;
|
|
py[1] = globals.gridy[i];
|
|
draw_vertical_line(buffer, width, bytes, px, py);
|
|
delta = blend_amount;
|
|
dy[0] = ly[0] = py[0]; dy[1] = ly[1] = py[1];
|
|
if (right)
|
|
{
|
|
dy[0] -= blend_lines + 2;
|
|
}
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
dy[0]++; dy[1]--; ly[0]++; ly[1]--;
|
|
px[0] = x_offset - j - 1;
|
|
darken_vertical_line(buffer, width, bytes, px, dy, delta);
|
|
px[0] = x_offset + j + 1;
|
|
lighten_vertical_line(buffer, width, bytes, px, ly, delta);
|
|
delta -= sigma;
|
|
}
|
|
|
|
y_offset = globals.gridy[i];
|
|
} /* for */
|
|
|
|
return;
|
|
} /* draw_vertical_border */
|
|
|
|
/*****/
|
|
|
|
/* assumes RGB* */
|
|
static void
|
|
draw_horizontal_border(guchar *buffer, gint width, gint bytes,
|
|
gint y_offset, gint xtiles, gint blend_lines,
|
|
gdouble blend_amount)
|
|
{
|
|
gint i, j;
|
|
gint tile_width = width / xtiles;
|
|
gint tile_width_eighth = tile_width / 8;
|
|
gint curve_start_offset = 3 * tile_width_eighth;
|
|
gint curve_end_offset = curve_start_offset + 2 * tile_width_eighth;
|
|
gint px[2], py[2];
|
|
gint dx[2], lx[2];
|
|
gint x_offset = 0;
|
|
gdouble delta;
|
|
gdouble sigma = blend_amount / blend_lines;
|
|
gint up;
|
|
|
|
for (i = 0; i < xtiles; i++)
|
|
{
|
|
up = rand() & 1;
|
|
/* first horizontal line across */
|
|
px[0] = x_offset; px[1] = x_offset + curve_start_offset - 1;
|
|
py[0] = py[1] = y_offset;
|
|
draw_horizontal_line(buffer, width, bytes, px, py);
|
|
delta = blend_amount;
|
|
dx[0] = lx[0] = px[0]; dx[1] = lx[1] = px[1];
|
|
if (up)
|
|
{
|
|
lx[1] += blend_lines + 2;
|
|
}
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
dx[0]++; dx[1]--; lx[0]++; lx[1]--;
|
|
py[0] = y_offset - j - 1;
|
|
darken_horizontal_line(buffer, width, bytes, dx, py, delta);
|
|
py[0] = y_offset + j + 1;
|
|
lighten_horizontal_line(buffer, width, bytes, lx, py, delta);
|
|
delta -= sigma;
|
|
}
|
|
|
|
if (up)
|
|
{
|
|
draw_up_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[UP]);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
/* use to be -j -1 */
|
|
darken_up_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[UP], delta, j);
|
|
/* use to be +j + 1 */
|
|
lighten_up_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[UP], delta, j);
|
|
delta -= sigma;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
draw_down_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[DOWN]);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
/* use to be +j + 1 */
|
|
darken_down_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[DOWN], delta, j);
|
|
/* use to be -j -1 */
|
|
lighten_down_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[DOWN], delta, j);
|
|
delta -= sigma;
|
|
}
|
|
}
|
|
/* right horizontal line of tile */
|
|
px[0] = x_offset + curve_end_offset;
|
|
px[1] = globals.gridx[i];
|
|
py[0] = py[1] = y_offset;
|
|
draw_horizontal_line(buffer, width, bytes, px, py);
|
|
delta = blend_amount;
|
|
dx[0] = lx[0] = px[0]; dx[1] = lx[1] = px[1];
|
|
if (!up)
|
|
{
|
|
dx[0] -= blend_lines + 2;
|
|
}
|
|
for (j = 0;j < blend_lines; j++)
|
|
{
|
|
dx[0]++; dx[1]--; lx[0]++; lx[1]--;
|
|
py[0] = y_offset - j - 1;
|
|
darken_horizontal_line(buffer, width, bytes, dx, py, delta);
|
|
py[0] = y_offset + j + 1;
|
|
lighten_horizontal_line(buffer, width, bytes, lx, py, delta);
|
|
delta -= sigma;
|
|
}
|
|
x_offset = globals.gridx[i];
|
|
} /* for */
|
|
|
|
return;
|
|
} /* draw_horizontal_border */
|
|
|
|
/*****/
|
|
|
|
/* assumes going top to bottom */
|
|
static void
|
|
draw_vertical_line(guchar *buffer, gint width, gint bytes,
|
|
gint px[2], gint py[2])
|
|
{
|
|
gint i;
|
|
gint rowstride = bytes * width;
|
|
gint index = px[0] * bytes + rowstride * py[0];
|
|
gint length = py[1] - py[0] + 1;
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
DRAW_POINT(buffer, index);
|
|
index += rowstride;
|
|
}
|
|
return;
|
|
} /* draw_vertical_line */
|
|
|
|
/*****/
|
|
|
|
/* assumes going left to right */
|
|
static void
|
|
draw_horizontal_line(guchar *buffer, gint width, gint bytes,
|
|
gint px[2], gint py[2])
|
|
{
|
|
gint i;
|
|
gint rowstride = bytes * width;
|
|
gint index = px[0] * bytes + py[0] * rowstride;
|
|
gint length = px[1] - px[0] + 1;
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
DRAW_POINT(buffer, index);
|
|
index += bytes;
|
|
}
|
|
return;
|
|
} /* draw_horizontal_line */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_right_bump(guchar *buffer, gint width, gint bytes, gint x_offset,
|
|
gint curve_start_offset, gint steps)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint rowstride = width * bytes;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = *(globals.cachex1[RIGHT] + i) + x_offset;
|
|
y = *(globals.cachey1[RIGHT] + i) + curve_start_offset;
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
|
|
x = *(globals.cachex2[RIGHT] + i) + x_offset;
|
|
y = *(globals.cachey2[RIGHT] + i) + curve_start_offset;
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
}
|
|
return;
|
|
} /* draw_right_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_left_bump(guchar *buffer, gint width, gint bytes, gint x_offset,
|
|
gint curve_start_offset, gint steps)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint rowstride = width * bytes;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = *(globals.cachex1[LEFT] + i) + x_offset;
|
|
y = *(globals.cachey1[LEFT] + i) + curve_start_offset;
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
|
|
x = *(globals.cachex2[LEFT] + i) + x_offset;
|
|
y = *(globals.cachey2[LEFT] + i) + curve_start_offset;
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
}
|
|
return;
|
|
} /* draw_left_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_up_bump(guchar *buffer, gint width, gint bytes, gint y_offset,
|
|
gint curve_start_offset, gint steps)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint rowstride = width * bytes;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = *(globals.cachex1[UP] + i) + curve_start_offset;
|
|
y = *(globals.cachey1[UP] + i) + y_offset;
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
|
|
x = *(globals.cachex2[UP] + i) + curve_start_offset;
|
|
y = *(globals.cachey2[UP] + i) + y_offset;
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
}
|
|
return;
|
|
} /* draw_up_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_down_bump(guchar *buffer, gint width, gint bytes, gint y_offset,
|
|
gint curve_start_offset, gint steps)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint rowstride = width * bytes;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = *(globals.cachex1[DOWN] + i) + curve_start_offset;
|
|
y = *(globals.cachey1[DOWN] + i) + y_offset;
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
|
|
x = *(globals.cachex2[DOWN] + i) + curve_start_offset;
|
|
y = *(globals.cachey2[DOWN] + i) + y_offset;
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
}
|
|
return;
|
|
} /* draw_down_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
malloc_cache(void)
|
|
{
|
|
gint i, j;
|
|
gint blend_lines = config.blend_lines;
|
|
gint length = blend_lines * sizeof(gint *);
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
gint steps_length = globals.steps[i] * sizeof(gint);
|
|
|
|
globals.cachex1[i] = g_malloc(steps_length);
|
|
globals.cachex2[i] = g_malloc(steps_length);
|
|
globals.cachey1[i] = g_malloc(steps_length);
|
|
globals.cachey2[i] = g_malloc(steps_length);
|
|
globals.blend_outer_cachex1[i] = g_malloc(length);
|
|
globals.blend_outer_cachex2[i] = g_malloc(length);
|
|
globals.blend_outer_cachey1[i] = g_malloc(length);
|
|
globals.blend_outer_cachey2[i] = g_malloc(length);
|
|
globals.blend_inner_cachex1[i] = g_malloc(length);
|
|
globals.blend_inner_cachex2[i] = g_malloc(length);
|
|
globals.blend_inner_cachey1[i] = g_malloc(length);
|
|
globals.blend_inner_cachey2[i] = g_malloc(length);
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
*(globals.blend_outer_cachex1[i] + j) = g_malloc(steps_length);
|
|
*(globals.blend_outer_cachex2[i] + j) = g_malloc(steps_length);
|
|
*(globals.blend_outer_cachey1[i] + j) = g_malloc(steps_length);
|
|
*(globals.blend_outer_cachey2[i] + j) = g_malloc(steps_length);
|
|
*(globals.blend_inner_cachex1[i] + j) = g_malloc(steps_length);
|
|
*(globals.blend_inner_cachex2[i] + j) = g_malloc(steps_length);
|
|
*(globals.blend_inner_cachey1[i] + j) = g_malloc(steps_length);
|
|
*(globals.blend_inner_cachey2[i] + j) = g_malloc(steps_length);
|
|
}
|
|
} /* for */
|
|
return;
|
|
} /* malloc_cache() */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
free_cache(void)
|
|
{
|
|
gint i, j;
|
|
gint blend_lines = config.blend_lines;
|
|
|
|
for (i = 0; i < 4; i ++)
|
|
{
|
|
g_free(globals.cachex1[i]);
|
|
g_free(globals.cachex2[i]);
|
|
g_free(globals.cachey1[i]);
|
|
g_free(globals.cachey2[i]);
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
g_free(*(globals.blend_outer_cachex1[i] + j));
|
|
g_free(*(globals.blend_outer_cachex2[i] + j));
|
|
g_free(*(globals.blend_outer_cachey1[i] + j));
|
|
g_free(*(globals.blend_outer_cachey2[i] + j));
|
|
g_free(*(globals.blend_inner_cachex1[i] + j));
|
|
g_free(*(globals.blend_inner_cachex2[i] + j));
|
|
g_free(*(globals.blend_inner_cachey1[i] + j));
|
|
g_free(*(globals.blend_inner_cachey2[i] + j));
|
|
}
|
|
g_free(globals.blend_outer_cachex1[i]);
|
|
g_free(globals.blend_outer_cachex2[i]);
|
|
g_free(globals.blend_outer_cachey1[i]);
|
|
g_free(globals.blend_outer_cachey2[i]);
|
|
g_free(globals.blend_inner_cachex1[i]);
|
|
g_free(globals.blend_inner_cachex2[i]);
|
|
g_free(globals.blend_inner_cachey1[i]);
|
|
g_free(globals.blend_inner_cachey2[i]);
|
|
} /* for */
|
|
return;
|
|
} /* free_cache */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
init_right_bump(gint width, gint height)
|
|
{
|
|
gint i;
|
|
gint xtiles = config.x;
|
|
gint ytiles = config.y;
|
|
gint steps = globals.steps[RIGHT];
|
|
gint px[4], py[4];
|
|
gint x_offset = 0;
|
|
gint tile_width = width / xtiles;
|
|
gint tile_height = height/ ytiles;
|
|
gint tile_height_eighth = tile_height / 8;
|
|
gint curve_start_offset = 0;
|
|
gint curve_end_offset = curve_start_offset + 2 * tile_height_eighth;
|
|
gint blend_lines = config.blend_lines;
|
|
|
|
px[0] = x_offset;
|
|
px[1] = x_offset + XFACTOR2 * tile_width;
|
|
px[2] = x_offset + XFACTOR3 * tile_width;
|
|
px[3] = x_offset + XFACTOR4 * tile_width;
|
|
py[0] = curve_start_offset;
|
|
py[1] = curve_start_offset + YFACTOR2 * tile_height;
|
|
py[2] = curve_start_offset - YFACTOR3 * tile_height;
|
|
py[3] = curve_start_offset + YFACTOR4 * tile_height;
|
|
generate_bezier(px, py, steps, globals.cachex1[RIGHT],
|
|
globals.cachey1[RIGHT]);
|
|
/* outside right bump */
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
py[0]--; py[1]--; py[2]--; px[3]++;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_outer_cachex1[RIGHT] + i),
|
|
*(globals.blend_outer_cachey1[RIGHT] + i));
|
|
}
|
|
/* inside right bump */
|
|
py[0] += blend_lines; py[1] += blend_lines; py[2] += blend_lines;
|
|
px[3] -= blend_lines;
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
py[0]++; py[1]++; py[2]++; px[3]--;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_inner_cachex1[RIGHT] + i),
|
|
*(globals.blend_inner_cachey1[RIGHT] + i));
|
|
}
|
|
|
|
/* bottom half of bump */
|
|
px[0] = x_offset + XFACTOR5 * tile_width;
|
|
px[1] = x_offset + XFACTOR6 * tile_width;
|
|
px[2] = x_offset + XFACTOR7 * tile_width;
|
|
px[3] = x_offset;
|
|
py[0] = curve_start_offset + YFACTOR5 * tile_height;
|
|
py[1] = curve_start_offset + YFACTOR6 * tile_height;
|
|
py[2] = curve_start_offset + YFACTOR7 * tile_height;
|
|
py[3] = curve_end_offset;
|
|
generate_bezier(px, py, steps, globals.cachex2[RIGHT],
|
|
globals.cachey2[RIGHT]);
|
|
/* outer right bump */
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
py[1]++; py[2]++; py[3]++; px[0]++;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_outer_cachex2[RIGHT] + i),
|
|
*(globals.blend_outer_cachey2[RIGHT] + i));
|
|
}
|
|
/* inner right bump */
|
|
py[1] -= blend_lines; py[2] -= blend_lines; py[3] -= blend_lines;
|
|
px[0] -= blend_lines;
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
py[1]--; py[2]--; py[3]--; px[0]--;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_inner_cachex2[RIGHT] + i),
|
|
*(globals.blend_inner_cachey2[RIGHT] + i));
|
|
}
|
|
return;
|
|
} /* init_right_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
init_left_bump(gint width, gint height)
|
|
{
|
|
gint i;
|
|
gint xtiles = config.x;
|
|
gint ytiles = config.y;
|
|
gint steps = globals.steps[LEFT];
|
|
gint px[4], py[4];
|
|
gint x_offset = 0;
|
|
gint tile_width = width / xtiles;
|
|
gint tile_height = height / ytiles;
|
|
gint tile_height_eighth = tile_height / 8;
|
|
gint curve_start_offset = 0;
|
|
gint curve_end_offset = curve_start_offset + 2 * tile_height_eighth;
|
|
gint blend_lines = config.blend_lines;
|
|
|
|
px[0] = x_offset;
|
|
px[1] = x_offset - XFACTOR2 * tile_width;
|
|
px[2] = x_offset - XFACTOR3 * tile_width;
|
|
px[3] = x_offset - XFACTOR4 * tile_width;
|
|
py[0] = curve_start_offset;
|
|
py[1] = curve_start_offset + YFACTOR2 * tile_height;
|
|
py[2] = curve_start_offset - YFACTOR3 * tile_height;
|
|
py[3] = curve_start_offset + YFACTOR4 * tile_height;
|
|
generate_bezier(px, py, steps, globals.cachex1[LEFT],
|
|
globals.cachey1[LEFT]);
|
|
/* outer left bump */
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
py[0]--; py[1]--; py[2]--; px[3]--;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_outer_cachex1[LEFT] + i),
|
|
*(globals.blend_outer_cachey1[LEFT] + i));
|
|
}
|
|
/* inner left bump */
|
|
py[0] += blend_lines; py[1] += blend_lines; py[2] += blend_lines;
|
|
px[3] += blend_lines;
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
py[0]++; py[1]++; py[2]++; px[3]++;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_inner_cachex1[LEFT] + i),
|
|
*(globals.blend_inner_cachey1[LEFT] + i));
|
|
}
|
|
|
|
/* bottom half of bump */
|
|
px[0] = x_offset - XFACTOR5 * tile_width;
|
|
px[1] = x_offset - XFACTOR6 * tile_width;
|
|
px[2] = x_offset - XFACTOR7 * tile_width;
|
|
px[3] = x_offset;
|
|
py[0] = curve_start_offset + YFACTOR5 * tile_height;
|
|
py[1] = curve_start_offset + YFACTOR6 * tile_height;
|
|
py[2] = curve_start_offset + YFACTOR7 * tile_height;
|
|
py[3] = curve_end_offset;
|
|
generate_bezier(px, py, steps, globals.cachex2[LEFT],
|
|
globals.cachey2[LEFT]);
|
|
/* outer left bump */
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
py[1]++; py[2]++; py[3]++; px[0]--;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_outer_cachex2[LEFT] + i),
|
|
*(globals.blend_outer_cachey2[LEFT] + i));
|
|
}
|
|
/* inner left bump */
|
|
py[1] -= blend_lines; py[2] -= blend_lines; py[3] -= blend_lines;
|
|
px[0] += blend_lines;
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
py[1]--; py[2]--; py[3]--; px[0]++;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_inner_cachex2[LEFT] + i),
|
|
*(globals.blend_inner_cachey2[LEFT] + i));
|
|
}
|
|
return;
|
|
} /* init_left_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
init_up_bump(gint width, gint height)
|
|
{
|
|
gint i;
|
|
gint xtiles = config.x;
|
|
gint ytiles = config.y;
|
|
gint steps = globals.steps[UP];
|
|
gint px[4], py[4];
|
|
gint y_offset = 0;
|
|
gint tile_width = width / xtiles;
|
|
gint tile_height = height/ ytiles;
|
|
gint tile_width_eighth = tile_width / 8;
|
|
gint curve_start_offset = 0;
|
|
gint curve_end_offset = curve_start_offset + 2 * tile_width_eighth;
|
|
gint blend_lines = config.blend_lines;
|
|
|
|
px[0] = curve_start_offset;
|
|
px[1] = curve_start_offset + YFACTOR2 * tile_width;
|
|
px[2] = curve_start_offset - YFACTOR3 * tile_width;
|
|
px[3] = curve_start_offset + YFACTOR4 * tile_width;
|
|
py[0] = y_offset;
|
|
py[1] = y_offset - XFACTOR2 * tile_height;
|
|
py[2] = y_offset - XFACTOR3 * tile_height;
|
|
py[3] = y_offset - XFACTOR4 * tile_height;
|
|
generate_bezier(px, py, steps, globals.cachex1[UP],
|
|
globals.cachey1[UP]);
|
|
/* outer up bump */
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
px[0]--; px[1]--; px[2]--; py[3]--;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_outer_cachex1[UP] + i),
|
|
*(globals.blend_outer_cachey1[UP] + i));
|
|
}
|
|
/* inner up bump */
|
|
px[0] += blend_lines; px[1] += blend_lines; px[2] += blend_lines;
|
|
py[3] += blend_lines;
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
px[0]++; px[1]++; px[2]++; py[3]++;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_inner_cachex1[UP] + i),
|
|
*(globals.blend_inner_cachey1[UP] + i));
|
|
}
|
|
|
|
/* bottom half of bump */
|
|
px[0] = curve_start_offset + YFACTOR5 * tile_width;
|
|
px[1] = curve_start_offset + YFACTOR6 * tile_width;
|
|
px[2] = curve_start_offset + YFACTOR7 * tile_width;
|
|
px[3] = curve_end_offset;
|
|
py[0] = y_offset - XFACTOR5 * tile_height;
|
|
py[1] = y_offset - XFACTOR6 * tile_height;
|
|
py[2] = y_offset - XFACTOR7 * tile_height;
|
|
py[3] = y_offset;
|
|
generate_bezier(px, py, steps, globals.cachex2[UP],
|
|
globals.cachey2[UP]);
|
|
/* outer up bump */
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
px[1]++; px[2]++; px[3]++; py[0]--;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_outer_cachex2[UP] + i),
|
|
*(globals.blend_outer_cachey2[UP] + i));
|
|
}
|
|
/* inner up bump */
|
|
px[1] -= blend_lines; px[2] -= blend_lines; px[3] -= blend_lines;
|
|
py[0] += blend_lines;
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
px[1]--; px[2]--; px[3]--; py[0]++;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_inner_cachex2[UP] + i),
|
|
*(globals.blend_inner_cachey2[UP] + i));
|
|
}
|
|
return;
|
|
} /* init_top_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
init_down_bump(gint width, gint height)
|
|
{
|
|
gint i;
|
|
gint xtiles = config.x;
|
|
gint ytiles = config.y;
|
|
gint steps = globals.steps[DOWN];
|
|
gint px[4], py[4];
|
|
gint y_offset = 0;
|
|
gint tile_width = width / xtiles;
|
|
gint tile_height = height/ ytiles;
|
|
gint tile_width_eighth = tile_width / 8;
|
|
gint curve_start_offset = 0;
|
|
gint curve_end_offset = curve_start_offset + 2 * tile_width_eighth;
|
|
gint blend_lines = config.blend_lines;
|
|
|
|
px[0] = curve_start_offset;
|
|
px[1] = curve_start_offset + YFACTOR2 * tile_width;
|
|
px[2] = curve_start_offset - YFACTOR3 * tile_width;
|
|
px[3] = curve_start_offset + YFACTOR4 * tile_width;
|
|
py[0] = y_offset;
|
|
py[1] = y_offset + XFACTOR2 * tile_height;
|
|
py[2] = y_offset + XFACTOR3 * tile_height;
|
|
py[3] = y_offset + XFACTOR4 * tile_height;
|
|
generate_bezier(px, py, steps, globals.cachex1[DOWN],
|
|
globals.cachey1[DOWN]);
|
|
/* outer down bump */
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
px[0]--; px[1]--; px[2]--; py[3]++;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_outer_cachex1[DOWN] + i),
|
|
*(globals.blend_outer_cachey1[DOWN] + i));
|
|
}
|
|
/* inner down bump */
|
|
px[0] += blend_lines; px[1] += blend_lines; px[2] += blend_lines;
|
|
py[3] -= blend_lines;
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
px[0]++; px[1]++; px[2]++; py[3]--;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_inner_cachex1[DOWN] + i),
|
|
*(globals.blend_inner_cachey1[DOWN] + i));
|
|
}
|
|
|
|
/* bottom half of bump */
|
|
px[0] = curve_start_offset + YFACTOR5 * tile_width;
|
|
px[1] = curve_start_offset + YFACTOR6 * tile_width;
|
|
px[2] = curve_start_offset + YFACTOR7 * tile_width;
|
|
px[3] = curve_end_offset;
|
|
py[0] = y_offset + XFACTOR5 * tile_height;
|
|
py[1] = y_offset + XFACTOR6 * tile_height;
|
|
py[2] = y_offset + XFACTOR7 * tile_height;
|
|
py[3] = y_offset;
|
|
generate_bezier(px, py, steps, globals.cachex2[DOWN],
|
|
globals.cachey2[DOWN]);
|
|
/* outer down bump */
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
px[1]++; px[2]++; px[3]++; py[0]++;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_outer_cachex2[DOWN] + i),
|
|
*(globals.blend_outer_cachey2[DOWN] + i));
|
|
}
|
|
/* inner down bump */
|
|
px[1] -= blend_lines; px[2] -= blend_lines; px[3] -= blend_lines;
|
|
py[0] -= blend_lines;
|
|
for (i = 0; i < blend_lines; i++)
|
|
{
|
|
px[1]--; px[2]--; px[3]--; py[0]--;
|
|
generate_bezier(px, py, steps,
|
|
*(globals.blend_inner_cachex2[DOWN] + i),
|
|
*(globals.blend_inner_cachey2[DOWN] + i));
|
|
}
|
|
return;
|
|
} /* init_down_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
generate_grid(gint width, gint height, gint xtiles, gint ytiles,
|
|
gint *x, gint *y)
|
|
{
|
|
gint i;
|
|
gint xlines = xtiles - 1;
|
|
gint ylines = ytiles - 1;
|
|
gint tile_width = width / xtiles;
|
|
gint tile_height = height / ytiles;
|
|
gint tile_width_leftover = width % xtiles;
|
|
gint tile_height_leftover = height % ytiles;
|
|
gint x_offset = tile_width;
|
|
gint y_offset = tile_height;
|
|
gint carry;
|
|
|
|
for (i = 0; i < xlines; i++)
|
|
{
|
|
x[i] = x_offset;
|
|
x_offset += tile_width;
|
|
}
|
|
carry = 0;
|
|
while (tile_width_leftover)
|
|
{
|
|
for (i = carry; i < xlines; i++)
|
|
{
|
|
x[i] += 1;
|
|
}
|
|
tile_width_leftover--;
|
|
carry++;
|
|
}
|
|
x[xlines] = width - 1; /* padding for draw_horizontal_border */
|
|
|
|
for (i = 0; i < ytiles; i++)
|
|
{
|
|
y[i] = y_offset;
|
|
y_offset += tile_height;
|
|
}
|
|
carry = 0;
|
|
while (tile_height_leftover)
|
|
{
|
|
for (i = carry; i < ylines; i++)
|
|
{
|
|
y[i] += 1;
|
|
}
|
|
tile_height_leftover--;
|
|
carry++;
|
|
}
|
|
y[ylines] = height - 1; /* padding for draw_vertical_border */
|
|
return;
|
|
} /* generate_grid */
|
|
|
|
/*****/
|
|
|
|
/* assumes RGB* */
|
|
/* assumes py[1] > py[0] and px[0] = px[1] */
|
|
static void
|
|
darken_vertical_line(guchar *buffer, gint width, gint bytes,
|
|
gint px[2], gint py[2], gdouble delta )
|
|
{
|
|
gint i;
|
|
gint rowstride = width * bytes;
|
|
gint index = px[0] * bytes + py[0] * rowstride;
|
|
gint length = py[1] - py[0] + 1;
|
|
gint temp;
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
index += rowstride;
|
|
}
|
|
return;
|
|
} /* darken_vertical_line */
|
|
|
|
/*****/
|
|
|
|
/* assumes RGB* */
|
|
/* assumes py[1] > py[0] and px[0] = px[1] */
|
|
static void
|
|
lighten_vertical_line(guchar *buffer, gint width, gint bytes,
|
|
gint px[2], gint py[2], gdouble delta)
|
|
{
|
|
gint i;
|
|
gint rowstride = width * bytes;
|
|
gint index = px[0] * bytes + py[0] * rowstride;
|
|
gint length = py[1] - py[0] + 1;
|
|
gint temp;
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
index += rowstride;
|
|
}
|
|
return;
|
|
} /* lighten_vertical_line */
|
|
|
|
/*****/
|
|
|
|
/* assumes RGB* */
|
|
/* assumes px[1] > px[0] and py[0] = py[1] */
|
|
static void
|
|
darken_horizontal_line(guchar *buffer, gint width, gint bytes,
|
|
gint px[2], gint py[2], gdouble delta)
|
|
{
|
|
gint i;
|
|
gint rowstride = width * bytes;
|
|
gint index = px[0] * bytes + py[0] * rowstride;
|
|
gint length = px[1] - px[0] + 1;
|
|
gint temp;
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
index += bytes;
|
|
}
|
|
return;
|
|
} /* darken_horizontal_line */
|
|
|
|
/*****/
|
|
|
|
/* assumes RGB* */
|
|
/* assumes px[1] > px[0] and py[0] = py[1] */
|
|
static void
|
|
lighten_horizontal_line(guchar *buffer, gint width, gint bytes,
|
|
gint px[2], gint py[2], gdouble delta)
|
|
{
|
|
gint i;
|
|
gint rowstride = width * bytes;
|
|
gint index = px[0] * bytes + py[0] * rowstride;
|
|
gint length = px[1] - px[0] + 1;
|
|
gint temp;
|
|
|
|
for (i = 0; i < length; i++)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
index += bytes;
|
|
}
|
|
return;
|
|
} /* lighten_horizontal_line */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
darken_right_bump(guchar *buffer, gint width, gint bytes, gint x_offset,
|
|
gint curve_start_offset, gint steps, gdouble delta,
|
|
gint counter)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index1 = -1;
|
|
gint last_index2 = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
gint j = counter;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = x_offset
|
|
+ *(*(globals.blend_inner_cachex1[RIGHT] + j) + i);
|
|
y = curve_start_offset
|
|
+ *(*(globals.blend_inner_cachey1[RIGHT] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index1)
|
|
{
|
|
if (i < steps / 1.3)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
else
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
last_index1 = index;
|
|
}
|
|
|
|
x = x_offset
|
|
+ *(*(globals.blend_inner_cachex2[RIGHT] + j) + i);
|
|
y = curve_start_offset
|
|
+ *(*(globals.blend_inner_cachey2[RIGHT] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index2)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
last_index2 = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* darken_right_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
lighten_right_bump(guchar *buffer, gint width, gint bytes, gint x_offset,
|
|
gint curve_start_offset, gint steps, gdouble delta,
|
|
gint counter)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index1 = -1;
|
|
gint last_index2 = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
gint j = counter;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = x_offset
|
|
+ *(*(globals.blend_outer_cachex1[RIGHT] + j) + i);
|
|
y = curve_start_offset
|
|
+ *(*(globals.blend_outer_cachey1[RIGHT] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index1)
|
|
{
|
|
if (i < steps / 1.3)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
else
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
last_index1 = index;
|
|
}
|
|
|
|
x = x_offset
|
|
+ *(*(globals.blend_outer_cachex2[RIGHT] + j) + i);
|
|
y = curve_start_offset
|
|
+ *(*(globals.blend_outer_cachey2[RIGHT] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index2)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
last_index2 = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* lighten_right_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
darken_left_bump(guchar *buffer, gint width, gint bytes, gint x_offset,
|
|
gint curve_start_offset, gint steps, gdouble delta,
|
|
gint counter)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index1 = -1;
|
|
gint last_index2 = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
gint j = counter;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = x_offset
|
|
+ *(*(globals.blend_outer_cachex1[LEFT] + j) + i);
|
|
y = curve_start_offset
|
|
+ *(*(globals.blend_outer_cachey1[LEFT] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index1)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
last_index1 = index;
|
|
}
|
|
|
|
x = x_offset
|
|
+ *(*(globals.blend_outer_cachex2[LEFT] + j) + i);
|
|
y = curve_start_offset
|
|
+ *(*(globals.blend_outer_cachey2[LEFT] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index2)
|
|
{
|
|
if (i < steps / 4)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
else
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
last_index2 = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* darken_left_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
lighten_left_bump(guchar *buffer, gint width, gint bytes, gint x_offset,
|
|
gint curve_start_offset, gint steps, gdouble delta,
|
|
gint counter)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index1 = -1;
|
|
gint last_index2 = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
gint j = counter;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = x_offset
|
|
+ *(*(globals.blend_inner_cachex1[LEFT] + j) + i);
|
|
y = curve_start_offset
|
|
+ *(*(globals.blend_inner_cachey1[LEFT] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index1)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
last_index1 = index;
|
|
}
|
|
|
|
x = x_offset
|
|
+ *(*(globals.blend_inner_cachex2[LEFT] + j) + i);
|
|
y = curve_start_offset
|
|
+ *(*(globals.blend_inner_cachey2[LEFT] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index2)
|
|
{
|
|
if (i < steps / 4)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
else
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
last_index2 = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* lighten_left_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
darken_up_bump(guchar *buffer, gint width, gint bytes, gint y_offset,
|
|
gint curve_start_offset, gint steps, gdouble delta,
|
|
gint counter)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index1 = -1;
|
|
gint last_index2 = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
gint j = counter;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = curve_start_offset
|
|
+ *(*(globals.blend_outer_cachex1[UP] + j) + i);
|
|
y = y_offset
|
|
+ *(*(globals.blend_outer_cachey1[UP] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index1)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
last_index1 = index;
|
|
}
|
|
|
|
x = curve_start_offset
|
|
+ *(*(globals.blend_outer_cachex2[UP] + j) + i);
|
|
y = y_offset
|
|
+ *(*(globals.blend_outer_cachey2[UP] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index2)
|
|
{
|
|
if (i < steps / 4)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
else
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
last_index2 = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* darken_up_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
lighten_up_bump(guchar *buffer, gint width, gint bytes, gint y_offset,
|
|
gint curve_start_offset, gint steps, gdouble delta,
|
|
gint counter)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index1 = -1;
|
|
gint last_index2 = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
gint j = counter;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = curve_start_offset
|
|
+ *(*(globals.blend_inner_cachex1[UP] + j) + i);
|
|
y = y_offset
|
|
+ *(*(globals.blend_inner_cachey1[UP] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index1)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
last_index1 = index;
|
|
}
|
|
|
|
x = curve_start_offset
|
|
+ *(*(globals.blend_inner_cachex2[UP] + j) + i);
|
|
y = y_offset
|
|
+ *(*(globals.blend_inner_cachey2[UP] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index2)
|
|
{
|
|
if (i < steps / 4)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
else
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
last_index2 = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* lighten_up_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
darken_down_bump(guchar *buffer, gint width, gint bytes, gint y_offset,
|
|
gint curve_start_offset, gint steps, gdouble delta,
|
|
gint counter)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index1 = -1;
|
|
gint last_index2 = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
gint j = counter;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = curve_start_offset
|
|
+ *(*(globals.blend_inner_cachex1[DOWN] + j) + i);
|
|
y = y_offset
|
|
+ *(*(globals.blend_inner_cachey1[DOWN] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index1)
|
|
{
|
|
if (i < steps / 1.2)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
else
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
last_index1 = index;
|
|
}
|
|
|
|
x = curve_start_offset
|
|
+ *(*(globals.blend_inner_cachex2[DOWN] + j) + i);
|
|
y = y_offset
|
|
+ *(*(globals.blend_inner_cachey2[DOWN] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index2)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
last_index2 = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* darken_down_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
lighten_down_bump(guchar *buffer, gint width, gint bytes, gint y_offset,
|
|
gint curve_start_offset, gint steps, gdouble delta,
|
|
gint counter)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index1 = -1;
|
|
gint last_index2 = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
gint j = counter;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = curve_start_offset
|
|
+ *(*(globals.blend_outer_cachex1[DOWN] + j) + i);
|
|
y = y_offset
|
|
+ *(*(globals.blend_outer_cachey1[DOWN] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index1)
|
|
{
|
|
if (i < steps / 1.2)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
else
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
}
|
|
last_index1 = index;
|
|
}
|
|
|
|
x = curve_start_offset
|
|
+ *(*(globals.blend_outer_cachex2[DOWN] + j) + i);
|
|
y = y_offset
|
|
+ *(*(globals.blend_outer_cachey2[DOWN] + j) + i);
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index2)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
last_index2 = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* lighten_down_bump */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_bezier_line(guchar *buffer, gint width, gint bytes,
|
|
gint steps, gint *cx, gint *cy)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint rowstride = width * bytes;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = cx[i];
|
|
y = cy[i];
|
|
index = y * rowstride + x * bytes;
|
|
DRAW_POINT(buffer, index);
|
|
}
|
|
return;
|
|
} /* draw_bezier_line */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
darken_bezier_line(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint y_offset, gint steps,
|
|
gint *cx, gint *cy, gdouble delta)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = cx[i] + x_offset;
|
|
y = cy[i] + y_offset;
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index)
|
|
{
|
|
DARKEN_POINT(buffer, index, delta, temp);
|
|
last_index = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* darken_bezier_line */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
lighten_bezier_line(guchar *buffer, gint width, gint bytes,
|
|
gint x_offset, gint y_offset, gint steps,
|
|
gint *cx, gint *cy, gdouble delta)
|
|
{
|
|
gint i;
|
|
gint x, y;
|
|
gint index;
|
|
gint last_index = -1;
|
|
gint rowstride = width * bytes;
|
|
gint temp;
|
|
|
|
for (i = 0; i < steps; i++)
|
|
{
|
|
x = cx[i] + x_offset;
|
|
y = cy[i] + y_offset;
|
|
index = y * rowstride + x * bytes;
|
|
if (index != last_index)
|
|
{
|
|
LIGHTEN_POINT(buffer, index, delta, temp);
|
|
last_index = index;
|
|
}
|
|
}
|
|
return;
|
|
} /* lighten_bezier_line */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_bezier_vertical_border(guchar *buffer, gint width, gint height,
|
|
gint bytes, gint x_offset, gint xtiles,
|
|
gint ytiles, gint blend_lines,
|
|
gdouble blend_amount, gint steps)
|
|
{
|
|
gint i, j;
|
|
gint tile_width = width / xtiles;
|
|
gint tile_height = height / ytiles;
|
|
gint tile_height_eighth = tile_height / 8;
|
|
gint curve_start_offset = 3 * tile_height_eighth;
|
|
gint curve_end_offset = curve_start_offset + 2 * tile_height_eighth;
|
|
gint px[4], py[4];
|
|
gint y_offset = 0;
|
|
gdouble delta;
|
|
gdouble sigma = blend_amount / blend_lines;
|
|
gint right;
|
|
bump_t style_index;
|
|
gint *cachex, *cachey;
|
|
|
|
cachex = g_malloc(steps * sizeof(gint));
|
|
cachey = g_malloc(steps * sizeof(gint));
|
|
|
|
for (i = 0; i < ytiles; i++)
|
|
{
|
|
right = rand() & 1;
|
|
if (right)
|
|
{
|
|
style_index = RIGHT;
|
|
}
|
|
else
|
|
{
|
|
style_index = LEFT;
|
|
}
|
|
px[0] = px[3] = x_offset;
|
|
px[1] = x_offset + WALL_XFACTOR2 * tile_width * FUDGE;
|
|
px[2] = x_offset + WALL_XFACTOR3 * tile_width * FUDGE;
|
|
py[0] = y_offset;
|
|
py[1] = y_offset + WALL_YCONS2 * tile_height;
|
|
py[2] = y_offset + WALL_YCONS3 * tile_height;
|
|
py[3] = y_offset + curve_start_offset;
|
|
|
|
if (right)
|
|
{
|
|
px[1] = x_offset - WALL_XFACTOR2 * tile_width;
|
|
px[2] = x_offset - WALL_XFACTOR3 * tile_width;
|
|
}
|
|
generate_bezier(px, py, steps, cachex, cachey);
|
|
draw_bezier_line(buffer, width, bytes, steps, cachex, cachey);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
px[0] = -j - 1;
|
|
darken_bezier_line(buffer, width, bytes, px[0], 0,
|
|
steps, cachex, cachey, delta);
|
|
px[0] = j + 1;
|
|
lighten_bezier_line(buffer, width, bytes, px[0], 0,
|
|
steps, cachex, cachey, delta);
|
|
delta -= sigma;
|
|
}
|
|
if (right)
|
|
{
|
|
draw_right_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[RIGHT]);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
/* use to be -j -1 */
|
|
darken_right_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[RIGHT], delta, j);
|
|
/* use to be +j + 1 */
|
|
lighten_right_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[RIGHT], delta, j);
|
|
delta -= sigma;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
draw_left_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[LEFT]);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
/* use to be -j -1 */
|
|
darken_left_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[LEFT], delta, j);
|
|
/* use to be -j - 1 */
|
|
lighten_left_bump(buffer, width, bytes, x_offset,
|
|
y_offset + curve_start_offset,
|
|
globals.steps[LEFT], delta, j);
|
|
delta -= sigma;
|
|
}
|
|
}
|
|
px[0] = px[3] = x_offset;
|
|
px[1] = x_offset + WALL_XFACTOR2 * tile_width * FUDGE;
|
|
px[2] = x_offset + WALL_XFACTOR3 * tile_width * FUDGE;
|
|
py[0] = y_offset + curve_end_offset;
|
|
py[1] = y_offset + curve_end_offset + WALL_YCONS2 * tile_height;
|
|
py[2] = y_offset + curve_end_offset + WALL_YCONS3 * tile_height;
|
|
py[3] = globals.gridy[i];
|
|
if (right)
|
|
{
|
|
px[1] = x_offset - WALL_XFACTOR2 * tile_width;
|
|
px[2] = x_offset - WALL_XFACTOR3 * tile_width;
|
|
}
|
|
generate_bezier(px, py, steps, cachex, cachey);
|
|
draw_bezier_line(buffer, width, bytes, steps, cachex, cachey);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
px[0] = -j - 1;
|
|
darken_bezier_line(buffer, width, bytes, px[0], 0,
|
|
steps, cachex, cachey, delta);
|
|
px[0] = j + 1;
|
|
lighten_bezier_line(buffer, width, bytes, px[0], 0,
|
|
steps, cachex, cachey, delta);
|
|
delta -= sigma;
|
|
}
|
|
y_offset = globals.gridy[i];
|
|
} /* for */
|
|
g_free(cachex);
|
|
g_free(cachey);
|
|
|
|
return;
|
|
} /* draw_bezier_vertical_border */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
draw_bezier_horizontal_border(guchar *buffer, gint width, gint height,
|
|
gint bytes, gint y_offset, gint xtiles,
|
|
gint ytiles, gint blend_lines,
|
|
gdouble blend_amount, gint steps)
|
|
{
|
|
gint i, j;
|
|
gint tile_width = width / xtiles;
|
|
gint tile_height = height / ytiles;
|
|
gint tile_width_eighth = tile_width / 8;
|
|
gint curve_start_offset = 3 * tile_width_eighth;
|
|
gint curve_end_offset = curve_start_offset + 2 * tile_width_eighth;
|
|
gint px[4], py[4];
|
|
gint x_offset = 0;
|
|
gdouble delta;
|
|
gdouble sigma = blend_amount / blend_lines;
|
|
gint up;
|
|
style_t style_index;
|
|
gint *cachex, *cachey;
|
|
|
|
cachex = g_malloc(steps * sizeof(gint));
|
|
cachey = g_malloc(steps * sizeof(gint));
|
|
|
|
for (i = 0; i < xtiles; i++)
|
|
{
|
|
up = rand() & 1;
|
|
if (up)
|
|
{
|
|
style_index = UP;
|
|
}
|
|
else
|
|
{
|
|
style_index = DOWN;
|
|
}
|
|
px[0] = x_offset;
|
|
px[1] = x_offset + WALL_XCONS2 * tile_width;
|
|
px[2] = x_offset + WALL_XCONS3 * tile_width;
|
|
px[3] = x_offset + curve_start_offset;
|
|
py[0] = py[3] = y_offset;
|
|
py[1] = y_offset + WALL_YFACTOR2 * tile_height * FUDGE;
|
|
py[2] = y_offset + WALL_YFACTOR3 * tile_height * FUDGE;
|
|
if (!up)
|
|
{
|
|
py[1] = y_offset - WALL_YFACTOR2 * tile_height;
|
|
py[2] = y_offset - WALL_YFACTOR3 * tile_height;
|
|
}
|
|
generate_bezier(px, py, steps, cachex, cachey);
|
|
draw_bezier_line(buffer, width, bytes, steps, cachex, cachey);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
py[0] = -j - 1;
|
|
darken_bezier_line(buffer, width, bytes, 0, py[0],
|
|
steps, cachex, cachey, delta);
|
|
py[0] = j + 1;
|
|
lighten_bezier_line(buffer, width, bytes, 0, py[0],
|
|
steps, cachex, cachey, delta);
|
|
delta -= sigma;
|
|
}
|
|
/* bumps */
|
|
if (up)
|
|
{
|
|
draw_up_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[UP]);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
/* use to be -j -1 */
|
|
darken_up_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[UP], delta, j);
|
|
/* use to be +j + 1 */
|
|
lighten_up_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[UP], delta, j);
|
|
delta -= sigma;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
draw_down_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[DOWN]);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
/* use to be +j + 1 */
|
|
darken_down_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[DOWN], delta, j);
|
|
/* use to be -j -1 */
|
|
lighten_down_bump(buffer, width, bytes, y_offset,
|
|
x_offset + curve_start_offset,
|
|
globals.steps[DOWN], delta, j);
|
|
delta -= sigma;
|
|
}
|
|
}
|
|
/* ending side wall line */
|
|
px[0] = x_offset + curve_end_offset;
|
|
px[1] = x_offset + curve_end_offset + WALL_XCONS2 * tile_width;
|
|
px[2] = x_offset + curve_end_offset + WALL_XCONS3 * tile_width;
|
|
px[3] = globals.gridx[i];
|
|
py[0] = py[3] = y_offset;
|
|
py[1] = y_offset + WALL_YFACTOR2 * tile_height * FUDGE;
|
|
py[2] = y_offset + WALL_YFACTOR3 * tile_height * FUDGE;
|
|
if (!up)
|
|
{
|
|
py[1] = y_offset - WALL_YFACTOR2 * tile_height;
|
|
py[2] = y_offset - WALL_YFACTOR3 * tile_height;
|
|
}
|
|
generate_bezier(px, py, steps, cachex, cachey);
|
|
draw_bezier_line(buffer, width, bytes, steps, cachex, cachey);
|
|
delta = blend_amount;
|
|
for (j = 0; j < blend_lines; j++)
|
|
{
|
|
py[0] = -j - 1;
|
|
darken_bezier_line(buffer, width, bytes, 0, py[0],
|
|
steps, cachex, cachey, delta);
|
|
py[0] = j + 1;
|
|
lighten_bezier_line(buffer, width, bytes, 0, py[0],
|
|
steps, cachex, cachey, delta);
|
|
delta -= sigma;
|
|
}
|
|
x_offset = globals.gridx[i];
|
|
} /* for */
|
|
g_free(cachex);
|
|
g_free(cachey);
|
|
|
|
return;
|
|
} /* draw_bezier_horizontal_border */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
check_config(gint width, gint height)
|
|
{
|
|
gint tile_width, tile_height;
|
|
gint tile_width_limit, tile_height_limit;
|
|
|
|
if (config.x < 1)
|
|
{
|
|
config.x = 1;
|
|
}
|
|
if (config.y < 1)
|
|
{
|
|
config.y = 1;
|
|
}
|
|
if (config.blend_amount < 0)
|
|
{
|
|
config.blend_amount = 0;
|
|
}
|
|
if (config.blend_amount > 5)
|
|
{
|
|
config.blend_amount = 5;
|
|
}
|
|
tile_width = width / config.x;
|
|
tile_height = height / config.y;
|
|
tile_width_limit = 0.4 * tile_width;
|
|
tile_height_limit = 0.4 * tile_height;
|
|
if ((config.blend_lines > tile_width_limit)
|
|
|| (config.blend_lines > tile_height_limit))
|
|
{
|
|
config.blend_lines = MIN(tile_width_limit, tile_height_limit);
|
|
}
|
|
return;
|
|
} /*check_config */
|
|
|
|
/*****/
|
|
|
|
/********************************************************
|
|
GUI
|
|
********************************************************/
|
|
|
|
static void
|
|
dialog_box(void)
|
|
{
|
|
GtkWidget *dlg;
|
|
GtkWidget *button;
|
|
GtkWidget *rbutton;
|
|
GtkWidget *cbutton;
|
|
GSList *list;
|
|
GtkWidget *hbox;
|
|
GtkWidget *frame;
|
|
GtkWidget *label;
|
|
GtkWidget *entry;
|
|
GtkWidget *table;
|
|
GtkWidget *scale;
|
|
GtkObject *adjustment;
|
|
GtkTooltips *tooltips;
|
|
GdkColor tips_fg, tips_bg;
|
|
|
|
gchar buffer[12];
|
|
|
|
gchar **argv;
|
|
gint argc;
|
|
|
|
argc = 1;
|
|
argv = g_new(gchar *, 1);
|
|
argv[0] = g_strdup(PLUG_IN_NAME);
|
|
|
|
gtk_init(&argc, &argv);
|
|
gtk_rc_parse(gimp_gtkrc());
|
|
|
|
/* Create the dialog box */
|
|
|
|
dlg = gtk_dialog_new();
|
|
gtk_window_set_title(GTK_WINDOW(dlg), PLUG_IN_NAME);
|
|
gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
|
|
gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
|
|
(GtkSignalFunc) dialog_close_callback, NULL);
|
|
|
|
/* Action Area */
|
|
|
|
button = gtk_button_new_with_label("OK");
|
|
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
|
|
gtk_signal_connect(GTK_OBJECT(button), "clicked",
|
|
(GtkSignalFunc) run_callback, dlg);
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button,
|
|
TRUE, TRUE, 0);
|
|
gtk_widget_grab_default(button);
|
|
gtk_widget_show(button);
|
|
|
|
button = gtk_button_new_with_label("Cancel");
|
|
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
|
|
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
|
|
(GtkSignalFunc) gtk_widget_destroy,
|
|
GTK_OBJECT(dlg));
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button,
|
|
TRUE, TRUE, 0);
|
|
gtk_widget_show(button);
|
|
|
|
/* init tooltips */
|
|
tooltips = gtk_tooltips_new();
|
|
tips_fg.red = 0;
|
|
tips_fg.green = 0;
|
|
tips_fg.blue = 0;
|
|
gdk_color_alloc(gtk_widget_get_colormap(dlg), &tips_fg);
|
|
tips_bg.red = 61669;
|
|
tips_bg.green = 59113;
|
|
tips_bg.blue = 35979;
|
|
gdk_color_alloc(gtk_widget_get_colormap(dlg), &tips_bg);
|
|
gtk_tooltips_set_colors(tooltips, &tips_bg, &tips_fg);
|
|
if (globals.tooltips == 0)
|
|
{
|
|
gtk_tooltips_disable(tooltips);
|
|
}
|
|
/* paramters frame */
|
|
frame = gtk_frame_new("Number of Tiles");
|
|
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
|
|
gtk_container_border_width(GTK_CONTAINER(frame), 10);
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
|
|
|
|
table = gtk_table_new(3, 2, FALSE);
|
|
gtk_container_border_width (GTK_CONTAINER(table), 10);
|
|
gtk_container_add(GTK_CONTAINER(frame), table);
|
|
|
|
/* xtiles */
|
|
label = gtk_label_new("Horizontal:");
|
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
|
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 5, 0);
|
|
gtk_widget_show(label);
|
|
|
|
adjustment = gtk_adjustment_new(config.x, MIN_XTILES, MAX_XTILES,
|
|
1.0, 1.0, 0);
|
|
gtk_signal_connect(GTK_OBJECT(adjustment), "value_changed",
|
|
(GtkSignalFunc) adjustment_callback,
|
|
&config.x);
|
|
scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment));
|
|
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
|
|
gtk_table_attach(GTK_TABLE(table), scale, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);
|
|
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE);
|
|
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
|
|
gtk_widget_show(scale);
|
|
gtk_tooltips_set_tip(tooltips, scale, XTILES_TEXT, NULL);
|
|
|
|
entry = gtk_entry_new();
|
|
gtk_object_set_user_data(GTK_OBJECT(entry), adjustment);
|
|
gtk_object_set_user_data(GTK_OBJECT(adjustment), entry);
|
|
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
|
|
sprintf(buffer, "%i", config.x);
|
|
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
|
|
gtk_signal_connect(GTK_OBJECT(entry), "changed",
|
|
GTK_SIGNAL_FUNC(entry_callback),
|
|
(gpointer) &config.x);
|
|
gtk_table_attach(GTK_TABLE(table), entry, 2, 3, 0, 1, GTK_FILL, 0, 0, 0);
|
|
gtk_widget_show(entry);
|
|
gtk_tooltips_set_tip(tooltips, entry, XTILES_TEXT, NULL);
|
|
|
|
/* ytiles */
|
|
label = gtk_label_new("Vertical:");
|
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
|
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 5, 0);
|
|
gtk_widget_show(label);
|
|
|
|
adjustment = gtk_adjustment_new(config.y, MIN_YTILES, MAX_YTILES,
|
|
1.0, 1.0, 0 );
|
|
gtk_signal_connect(GTK_OBJECT(adjustment), "value_changed",
|
|
(GtkSignalFunc) adjustment_callback,
|
|
&config.y);
|
|
scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment));
|
|
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
|
|
gtk_table_attach(GTK_TABLE(table), scale, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);
|
|
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE);
|
|
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
|
|
gtk_widget_show(scale);
|
|
gtk_tooltips_set_tip(tooltips, scale, YTILES_TEXT, NULL);
|
|
|
|
entry = gtk_entry_new();
|
|
gtk_object_set_user_data(GTK_OBJECT(entry), adjustment);
|
|
gtk_object_set_user_data(GTK_OBJECT(adjustment), entry);
|
|
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
|
|
sprintf(buffer, "%i", config.y);
|
|
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
|
|
gtk_signal_connect(GTK_OBJECT(entry), "changed",
|
|
GTK_SIGNAL_FUNC(entry_callback),
|
|
(gpointer) &config.y);
|
|
gtk_table_attach(GTK_TABLE(table), entry, 2, 3, 1, 2, GTK_FILL, 0, 0, 0);
|
|
gtk_widget_show(entry);
|
|
gtk_tooltips_set_tip(tooltips, entry, YTILES_TEXT, NULL);
|
|
|
|
gtk_widget_show(table);
|
|
gtk_widget_show(frame);
|
|
|
|
/* frame for bevel blending */
|
|
|
|
frame = gtk_frame_new("Bevel Edges");
|
|
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
|
|
gtk_container_border_width(GTK_CONTAINER(frame), 10);
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
|
|
|
|
table = gtk_table_new(3, 2, FALSE);
|
|
gtk_container_border_width(GTK_CONTAINER(table), 10);
|
|
gtk_container_add(GTK_CONTAINER(frame), table);
|
|
|
|
/* number of blending lines */
|
|
label = gtk_label_new("Bevel width:");
|
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
|
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 5, 0);
|
|
gtk_widget_show(label);
|
|
|
|
adjustment = gtk_adjustment_new(config.blend_lines, MIN_BLEND_LINES,
|
|
MAX_BLEND_LINES, 1.0, 1.0, 0);
|
|
gtk_signal_connect(GTK_OBJECT(adjustment), "value_changed",
|
|
(GtkSignalFunc) adjustment_callback,
|
|
&config.blend_lines);
|
|
scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment));
|
|
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
|
|
gtk_table_attach(GTK_TABLE(table), scale, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);
|
|
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE);
|
|
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
|
|
gtk_widget_show(scale);
|
|
gtk_tooltips_set_tip(tooltips, scale, BLEND_LINES_TEXT, NULL);
|
|
|
|
entry = gtk_entry_new();
|
|
gtk_object_set_user_data(GTK_OBJECT(entry), adjustment);
|
|
gtk_object_set_user_data(GTK_OBJECT(adjustment), entry);
|
|
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
|
|
sprintf(buffer, "%i", config.blend_lines);
|
|
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
|
|
gtk_signal_connect(GTK_OBJECT(entry), "changed",
|
|
GTK_SIGNAL_FUNC(entry_callback),
|
|
(gpointer) &config.blend_lines);
|
|
gtk_table_attach(GTK_TABLE(table), entry, 2, 3, 0, 1, GTK_FILL, 0, 0, 0);
|
|
gtk_widget_show(entry);
|
|
gtk_tooltips_set_tip(tooltips, entry, BLEND_LINES_TEXT, NULL);
|
|
|
|
/* blending amount */
|
|
label = gtk_label_new("Highlight:");
|
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
|
|
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 5, 0);
|
|
gtk_widget_show(label);
|
|
|
|
adjustment = gtk_adjustment_new(config.blend_amount, MIN_BLEND_AMOUNT,
|
|
MAX_BLEND_AMOUNT, 1.0, 0.05, 0.0);
|
|
gtk_signal_connect(GTK_OBJECT(adjustment), "value_changed",
|
|
(GtkSignalFunc) adjustment_double_callback,
|
|
&config.blend_amount);
|
|
scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment));
|
|
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
|
|
gtk_table_attach(GTK_TABLE(table), scale, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);
|
|
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE);
|
|
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
|
|
gtk_widget_show(scale);
|
|
gtk_tooltips_set_tip(tooltips, scale, BLEND_AMOUNT_TEXT, NULL);
|
|
|
|
entry = gtk_entry_new();
|
|
gtk_object_set_user_data(GTK_OBJECT(entry), adjustment);
|
|
gtk_object_set_user_data(GTK_OBJECT(adjustment), entry);
|
|
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
|
|
sprintf(buffer, "%0.2f", config.blend_amount);
|
|
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
|
|
gtk_signal_connect(GTK_OBJECT(entry), "changed",
|
|
GTK_SIGNAL_FUNC(entry_double_callback),
|
|
(gpointer) &config.blend_amount);
|
|
gtk_table_attach(GTK_TABLE(table), entry, 2, 3, 1, 2, GTK_FILL, 0, 0, 0);
|
|
gtk_widget_show(entry);
|
|
gtk_tooltips_set_tip(tooltips, entry, BLEND_AMOUNT_TEXT, NULL);
|
|
|
|
gtk_widget_show(table);
|
|
gtk_widget_show(frame);
|
|
|
|
/* frame for primitive radio buttons */
|
|
|
|
hbox = gtk_hbox_new(FALSE, 5);
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox, FALSE, FALSE, 0);
|
|
|
|
frame = gtk_frame_new("Jigsaw Style");
|
|
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
|
|
gtk_container_border_width(GTK_CONTAINER(frame), 10);
|
|
gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
|
|
|
|
table = gtk_table_new(2, 1, FALSE);
|
|
gtk_container_border_width(GTK_CONTAINER(table), 5);
|
|
gtk_container_add(GTK_CONTAINER(frame), table);
|
|
|
|
rbutton = gtk_radio_button_new_with_label(NULL, "Square");
|
|
list = gtk_radio_button_group((GtkRadioButton *) rbutton);
|
|
gtk_toggle_button_set_active((GtkToggleButton *) rbutton,
|
|
config.style == BEZIER_1 ? TRUE : FALSE);
|
|
gtk_signal_connect(GTK_OBJECT(rbutton), "toggled",
|
|
GTK_SIGNAL_FUNC(radio_button_primitive_callback),
|
|
(gpointer) BEZIER_1);
|
|
gtk_table_attach(GTK_TABLE(table), rbutton, 0, 1, 0, 1, GTK_FILL, 0, 10, 0);
|
|
gtk_widget_show(rbutton);
|
|
gtk_tooltips_set_tip(tooltips, rbutton, SQUARE_TEXT, NULL);
|
|
|
|
rbutton = gtk_radio_button_new_with_label(list, "Curved");
|
|
list = gtk_radio_button_group((GtkRadioButton *) rbutton);
|
|
gtk_toggle_button_set_active((GtkToggleButton *) rbutton,
|
|
config.style == BEZIER_2 ? TRUE : FALSE);
|
|
gtk_signal_connect(GTK_OBJECT(rbutton), "toggled",
|
|
GTK_SIGNAL_FUNC(radio_button_primitive_callback),
|
|
(gpointer) BEZIER_2);
|
|
gtk_table_attach(GTK_TABLE(table), rbutton, 1, 2, 0, 1, GTK_FILL, 0, 10, 0);
|
|
gtk_widget_show(rbutton);
|
|
gtk_tooltips_set_tip(tooltips, rbutton, CURVE_TEXT, NULL);
|
|
|
|
gtk_widget_show(table);
|
|
gtk_widget_show(frame);
|
|
|
|
table = gtk_table_new(1, 3, FALSE);
|
|
gtk_container_border_width(GTK_CONTAINER(table), 3);
|
|
gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 0);
|
|
|
|
cbutton = gtk_check_button_new_with_label("Disable Tooltips");
|
|
gtk_toggle_button_set_active((GtkToggleButton *) cbutton,
|
|
globals.tooltips ? FALSE : TRUE);
|
|
gtk_signal_connect(GTK_OBJECT(cbutton), "toggled",
|
|
(GtkSignalFunc) check_button_callback,
|
|
(gpointer) tooltips);
|
|
gtk_table_attach(GTK_TABLE(table), cbutton, 0, 1, 1, 2, 0, 0, 0, 20);
|
|
gtk_widget_show(cbutton);
|
|
gtk_tooltips_set_tip(tooltips, cbutton, DISABLE_TEXT, NULL);
|
|
|
|
gtk_widget_show(table);
|
|
gtk_widget_show(hbox);
|
|
gtk_widget_show(dlg);
|
|
|
|
gtk_main();
|
|
gdk_flush();
|
|
|
|
return;
|
|
}
|
|
|
|
/***************************************************
|
|
callbacks
|
|
***************************************************/
|
|
|
|
static void
|
|
run_callback(GtkWidget *widget, gpointer data)
|
|
{
|
|
globals.dialog_result = 1;
|
|
gtk_widget_destroy(GTK_WIDGET(data));
|
|
return;
|
|
}
|
|
|
|
/*****/
|
|
|
|
static void
|
|
dialog_close_callback(GtkWidget *widget, gpointer data)
|
|
{
|
|
gtk_main_quit();
|
|
return;
|
|
} /* dialog_close_callback */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
entry_callback(GtkWidget *widget, gpointer data)
|
|
{
|
|
GtkAdjustment *adjustment;
|
|
gint new_value;
|
|
|
|
new_value = atoi(gtk_entry_get_text(GTK_ENTRY(widget)));
|
|
|
|
if (*(gint *)data != new_value)
|
|
{
|
|
*(gint *)data = new_value;
|
|
adjustment = gtk_object_get_user_data(GTK_OBJECT(widget));
|
|
if ((new_value >= adjustment->lower)
|
|
&& (new_value <= adjustment->upper))
|
|
{
|
|
adjustment->value = new_value;
|
|
gtk_signal_handler_block_by_data(GTK_OBJECT(adjustment), data);
|
|
gtk_signal_emit_by_name(GTK_OBJECT(adjustment), "value_changed");
|
|
gtk_signal_handler_unblock_by_data(GTK_OBJECT(adjustment), data);
|
|
}
|
|
}
|
|
return;
|
|
} /* entry_callback */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
radio_button_primitive_callback(GtkWidget *widget, gpointer data)
|
|
{
|
|
if (GTK_TOGGLE_BUTTON (widget)->active) /* button just got checked */
|
|
{
|
|
if (data == (gpointer) BEZIER_1)
|
|
{
|
|
config.style = BEZIER_1;
|
|
}
|
|
else if (data == (gpointer) BEZIER_2)
|
|
{
|
|
config.style = BEZIER_2;
|
|
}
|
|
else
|
|
{
|
|
printf("radio_button_callback: bad data\n");
|
|
}
|
|
}
|
|
return;
|
|
} /* radio_button_primitive_callback */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
check_button_callback(GtkWidget *widget, gpointer data)
|
|
{
|
|
if (GTK_TOGGLE_BUTTON (widget)->active)
|
|
{
|
|
gtk_tooltips_disable((GtkTooltips *) data);
|
|
globals.tooltips = 0;
|
|
}
|
|
else
|
|
{
|
|
gtk_tooltips_enable((GtkTooltips *) data);
|
|
globals.tooltips = 1;
|
|
}
|
|
return;
|
|
} /* check_button_callback */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
adjustment_callback(GtkAdjustment *adjustment, gpointer data)
|
|
{
|
|
GtkWidget *entry;
|
|
gchar buffer[50];
|
|
|
|
if (*(gint *)data != adjustment->value)
|
|
{
|
|
*(gint *)data = adjustment->value;
|
|
entry = gtk_object_get_user_data(GTK_OBJECT(adjustment));
|
|
sprintf(buffer, "%d", *(gint *)data);
|
|
|
|
gtk_signal_handler_block_by_data(GTK_OBJECT(entry), data);
|
|
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
|
|
gtk_signal_handler_unblock_by_data(GTK_OBJECT(entry), data);
|
|
}
|
|
return;
|
|
} /* adjustment_callback */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
adjustment_double_callback(GtkAdjustment *adjustment, gpointer data)
|
|
{
|
|
GtkWidget *entry;
|
|
gchar buffer[50];
|
|
|
|
if (*(gdouble *)data != adjustment->value)
|
|
{
|
|
*(gdouble *)data = adjustment->value;
|
|
entry = gtk_object_get_user_data(GTK_OBJECT(adjustment));
|
|
sprintf(buffer, "%0.2f", *(gdouble *)data);
|
|
|
|
gtk_signal_handler_block_by_data(GTK_OBJECT(entry), data);
|
|
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
|
|
gtk_signal_handler_unblock_by_data(GTK_OBJECT(entry), data);
|
|
}
|
|
return;
|
|
} /* adjustment_double_callback */
|
|
|
|
/*****/
|
|
|
|
static void
|
|
entry_double_callback(GtkWidget *widget, gpointer data)
|
|
{
|
|
GtkAdjustment *adjustment;
|
|
gdouble new_value;
|
|
|
|
new_value = atof(gtk_entry_get_text(GTK_ENTRY(widget)));
|
|
|
|
if (*(gdouble *)data != new_value)
|
|
{
|
|
*(gdouble *)data = new_value;
|
|
adjustment = gtk_object_get_user_data(GTK_OBJECT(widget));
|
|
if ((new_value >= adjustment->lower)
|
|
&& (new_value <= adjustment->upper))
|
|
{
|
|
adjustment->value = new_value;
|
|
gtk_signal_handler_block_by_data(GTK_OBJECT(adjustment), data);
|
|
gtk_signal_emit_by_name(GTK_OBJECT(adjustment), "value_changed");
|
|
gtk_signal_handler_unblock_by_data(GTK_OBJECT(adjustment), data);
|
|
}
|
|
}
|
|
return;
|
|
} /* entry_double_callback */
|