1997-11-25 06:05:25 +08:00
/* The GIMP -- an image manipulation program
* Copyright ( C ) 1995 Spencer Kimball and Peter Mattis
*
* MathMap plug - in - - - generate an image by means of a mathematical expression
* Copyright ( C ) 1997 Mark Probst
* schani @ unix . cslab . tuwien . ac . at
*
* Plug - In structure based on :
* Whirl plug - in - - - distort an image into a whirlpool
* Copyright ( C ) 1997 Federico Mena Quintero
* federico @ nuclecu . unam . mx
*
1998-01-25 17:29:29 +08:00
* Version 0.4
1997-12-09 13:57:33 +08:00
*
1997-11-25 06:05:25 +08:00
* 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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <math.h>
# include <stdlib.h>
# include <stdio.h>
1997-12-09 13:57:33 +08:00
# include <assert.h>
1998-01-25 17:29:29 +08:00
# include <string.h>
1997-11-25 06:05:25 +08:00
# include <gtk/gtk.h>
# include <libgimp/gimp.h>
# include "exprtree.h"
# include "builtins.h"
# include "postfix.h"
1997-12-09 13:57:33 +08:00
# include "scanner.h"
1997-11-25 06:05:25 +08:00
/***** Macros *****/
# define MIN(a, b) (((a) < (b)) ? (a) : (b))
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
/***** Magic numbers *****/
# define PREVIEW_SIZE 128
# define SCALE_WIDTH 200
# define ENTRY_WIDTH 60
# define DEFAULT_EXPRESSION "origValXY(x+sin(y*10)*3,y+sin(x*10)*3)"
1998-01-25 17:29:29 +08:00
# define DEFAULT_NUMBER_FRAMES 10
1997-11-25 06:05:25 +08:00
# define FLAG_INTERSAMPLING 1
# define FLAG_OVERSAMPLING 2
1998-01-25 17:29:29 +08:00
# define FLAG_ANIMATION 4
1997-11-25 06:05:25 +08:00
1998-01-25 17:29:29 +08:00
# define MAX_EXPRESSION_LENGTH 8192
1997-11-25 06:05:25 +08:00
/***** Types *****/
typedef struct {
gchar expression [ MAX_EXPRESSION_LENGTH ] ;
gint flags ;
1998-01-25 17:29:29 +08:00
gint frames ;
1997-11-25 06:05:25 +08:00
} mathmap_vals_t ;
typedef struct {
GtkWidget * preview ;
guchar * image ;
guchar * wimage ;
gint run ;
} mathmap_interface_t ;
/***** Prototypes *****/
static void query ( void ) ;
static void run ( char * name ,
int nparams ,
GParam * param ,
int * nreturn_vals ,
GParam * * return_vals ) ;
static void expression_copy ( gchar * dest , gchar * src ) ;
static void mathmap ( void ) ;
void mathmap_get_pixel ( int x , int y , guchar * pixel ) ;
1998-01-25 17:29:29 +08:00
static gint32 mathmap_layer_copy ( gint32 layerID ) ;
extern int yyparse ( void ) ;
1997-11-25 06:05:25 +08:00
static void build_preview_source_image ( void ) ;
static gint mathmap_dialog ( void ) ;
static void dialog_update_preview ( void ) ;
1998-01-25 17:29:29 +08:00
/*
1997-11-25 06:05:25 +08:00
static void dialog_create_value ( char * title , GtkTable * table , int row , gdouble * value ,
double left , double right ) ;
1998-01-25 17:29:29 +08:00
*/
static void dialog_scale_update ( GtkAdjustment * adjustment , gint * value ) ;
static void dialog_entry_update ( GtkWidget * widget , gpointer value ) ;
1997-11-25 06:05:25 +08:00
static void dialog_intersampling_update ( GtkWidget * widget , gpointer data ) ;
static void dialog_oversampling_update ( GtkWidget * widget , gpointer data ) ;
1998-01-25 17:29:29 +08:00
static void dialog_animation_update ( GtkWidget * widget , gpointer data ) ;
1997-11-25 06:05:25 +08:00
static void dialog_preview_callback ( GtkWidget * widget , gpointer data ) ;
static void dialog_example_callback ( GtkWidget * widget , char * expression ) ;
static void dialog_close_callback ( GtkWidget * widget , gpointer data ) ;
static void dialog_ok_callback ( GtkWidget * widget , gpointer data ) ;
static void dialog_cancel_callback ( GtkWidget * widget , gpointer data ) ;
/***** Variables *****/
GPlugInInfo PLUG_IN_INFO = {
NULL , /* init_proc */
NULL , /* quit_proc */
query , /* query_proc */
run /* run_proc */
} ; /* PLUG_IN_INFO */
static mathmap_vals_t mmvals = {
DEFAULT_EXPRESSION , /* expression */
1998-01-25 17:29:29 +08:00
FLAG_INTERSAMPLING , /* flags */
DEFAULT_NUMBER_FRAMES /* frames */
1997-11-25 06:05:25 +08:00
} ; /* mmvals */
static mathmap_interface_t wint = {
NULL , /* preview */
NULL , /* image */
NULL , /* wimage */
FALSE /* run */
} ; /* wint */
1998-01-25 17:29:29 +08:00
static gint32 image_id ;
static gint32 layer_id ;
static GDrawable * input_drawable ;
static GDrawable * output_drawable ;
1997-11-25 06:05:25 +08:00
static gint tile_width , tile_height ;
1998-01-25 17:29:29 +08:00
static gint img_width , img_height ;
1997-11-25 06:05:25 +08:00
static gint sel_x1 , sel_y1 , sel_x2 , sel_y2 ;
static gint sel_width , sel_height ;
static gint preview_width , preview_height ;
static GTile * the_tile = NULL ;
static double cen_x , cen_y ;
static double scale_x , scale_y ;
static double radius , radius2 ;
1998-01-25 17:29:29 +08:00
GtkWidget * expression_entry = 0 ,
* animate_table ;
1997-11-25 06:05:25 +08:00
exprtree * theExprtree = 0 ;
int imageWidth ,
imageHeight ,
wholeImageWidth ,
wholeImageHeight ,
originX ,
1998-01-25 17:29:29 +08:00
originY ,
inputBPP ,
outputBPP ;
1997-11-25 06:05:25 +08:00
int usesRA = 0 ;
double currentX ,
currentY ,
currentR ,
currentA ,
1998-01-25 17:29:29 +08:00
currentT ,
1997-11-25 06:05:25 +08:00
imageR ,
imageX ,
imageY ,
middleX ,
middleY ;
int intersamplingEnabled ,
1998-01-25 17:29:29 +08:00
oversamplingEnabled ,
animationEnabled = 1 ;
1997-11-25 06:05:25 +08:00
char * examples [ ] [ 2 ] = {
1998-01-25 17:29:29 +08:00
{ " wave " , " origValXY(x+sin(y*10+t*360)*3,y+sin(x*10+t*360)*3) " } ,
1997-11-25 06:05:25 +08:00
{ " square " , " origValXY(sign(x)*x*x/50,sign(y)*y*y/50) " } ,
{ " mosaic " , " origValXY(x-x%5,y-y%5) " } ,
1998-01-25 17:29:29 +08:00
{ " slice " , " q=t*360;origValXY(x+5*sign(cos(9*y+q)),y+5*sign(cos(9*x+q))) " } ,
{ " mercator " , " origValXY(x*cos(90/Y*y+t*360),y) " } ,
{ " pond " , " origValRA(r+sin(r*20+t*360)*3,a) " } ,
{ " enhanced pond " , " origValRA(r+(sin(500000/(r+100)+t*360)*7),a) " } ,
{ " sea 1 " , " origValXY(x+10*sin(t*360+2000*Y*pow(y+Y+60,-1)),y) " } ,
{ " sea 2 " , " origValXY(x,y+5*sin(t*360+2000*Y*pow(y+Y+60,-1))) " } ,
{ " sea 3 " , " s=sin(t*360+2000*Y*pow(y+Y+60,-1));origValXY(x+10*s,y+5*s) " } ,
1997-11-25 06:05:25 +08:00
{ " twirl 90 " , " origValRA(r,a+(r/R-1)*45) " } ,
1997-12-09 13:57:33 +08:00
{ " sphere " , " p=r/(X*2);origValRA(r*(1-inintv(p,-0.5,0.5))+X/90*asin(inintv(p,-0.5,0.5)*r/X),a) " } ,
1998-01-25 17:29:29 +08:00
{ " jitter " , " origValRA(r,a+(a+t*8)%8-4) " } ,
1997-11-25 06:05:25 +08:00
{ " radial mosaic " , " origValRA(r-r%5,a-a%5) " } ,
1998-01-25 17:29:29 +08:00
{ " circular slice " , " origValRA(r,a+(r+t*6)%6-3) " } ,
{ " fisheye " , " origValRA(pow(r,2-t)/pow(R,1-t),a) " } ,
1997-11-25 06:05:25 +08:00
{ " center shake " , " origValXY(x+max(0,cos(x*2))*5*max(0,cos(y*2))*cos(y*10),y+max(0,cos(x*2))*5*max(0,cos(y*2))*cos(x*10)) " } ,
1998-01-25 17:29:29 +08:00
{ " spiral " , " p=origValXY(x,y);q=sin((r-a*0.1)*10+t*360)*0.5+0.5;rgbColor(q*red(p),q*green(p),q*blue(p)) " } ,
{ " alpha spiral " , " p=origValXY(x,y);rgbaColor(red(p),green(p),blue(p),sin((r-a*0.1)*10+t*360)*0.5+0.5) " } ,
1997-11-25 06:05:25 +08:00
{ " scatter " , " origValXY(x+rand(-3,3),y+rand(-3,3)) " } ,
1998-01-25 17:29:29 +08:00
{ " desaturate " , " p=origValXY(x,y);grayaColor(gray(p),alpha(p)) " } ,
1997-12-09 13:57:33 +08:00
{ " darts " , " p=origValXY(x,y);p=if inintv((a-9)%36,0,18) then p else rgbColor(1-red(p),1-green(p),1-blue(p)) end;if inintv(r%80,68,80) then p else rgbColor(1-red(p),1-green(p),1-blue(p)) end " } ,
1998-01-25 17:29:29 +08:00
{ " tile " , " origValXY((x+X)*2%W-X,(y+Y)*2%H-Y) " } ,
1997-11-25 06:05:25 +08:00
{ " ? " , " origValRA(r,a+sin(a*10)*20) " } ,
{ " ? " , " origValRA(r+r%20,a) " } ,
{ " sine wave " , " grayColor(sin(r*10)*0.5+0.5) " } ,
1997-12-09 13:57:33 +08:00
{ " grid " , " grayColor(if (x%20)*(y%20) then 1 else 0 end) " } ,
1998-01-25 17:29:29 +08:00
{ " moire1 " , " q=t*360;rgbColor(abs(sin(15*r+q)+sin(15*a+q))*0.5,abs(sin(17*r+q)+sin(17*a+q))*0.5,abs(sin(19*r+q)+sin(19*a+q))*0.5) " } ,
{ " moire2 " , " grayColor(sin(x*y+t*360)*0.5+0.5) " } ,
1997-12-09 13:57:33 +08:00
{ " mandelbrot " ,
" tx=1.5*x/X-0.5; "
" ty=1.5*y/X-0; "
" iter=0; "
" xr=0; "
" xi=0; "
" xrsq=0; "
" xisq=0; "
1998-01-25 17:29:29 +08:00
" while xrsq+xisq<4 && iter<31 "
1997-12-09 13:57:33 +08:00
" do "
" xrsq=xr*xr; "
" xisq=xi*xi; "
" xi=2*xr*xi+ty; "
" xr=xrsq-xisq+tx; "
" iter=iter+1 "
" end; "
" grayColor(iter/32) " } ,
1997-11-25 06:05:25 +08:00
{ 0 , 0 }
} ;
/***** Functions *****/
/*****/
static void
expression_copy ( gchar * dest , gchar * src )
{
strncpy ( dest , src , MAX_EXPRESSION_LENGTH ) ;
dest [ MAX_EXPRESSION_LENGTH - 1 ] = 0 ;
}
/*****/
MAIN ( ) ;
/*****/
static void
query ( void )
{
static GParamDef args [ ] = {
{ PARAM_INT32 , " run_mode " , " Interactive, non-interactive " } ,
{ PARAM_IMAGE , " image " , " Input image " } ,
{ PARAM_DRAWABLE , " drawable " , " Input drawable " } ,
{ PARAM_STRING , " expression " , " MathMap expression " } ,
1998-01-25 17:29:29 +08:00
{ PARAM_INT32 , " flags " , " 1: Intersampling 2: Oversampling 4: Animate " } ,
{ PARAM_INT32 , " frames " , " Number of Frames " }
1997-11-25 06:05:25 +08:00
} ; /* args */
static GParamDef * return_vals = NULL ;
static int nargs = sizeof ( args ) / sizeof ( args [ 0 ] ) ;
static int nreturn_vals = 0 ;
gimp_install_procedure ( " plug_in_mathmap " ,
" Generate an image using a mathematical expression. " ,
" Generates an image by means of a mathematical expression. The expression "
" can also refer to the data of an original image. Thus, arbitrary "
1998-01-25 17:29:29 +08:00
" distortions can be constructed. Even animations can be generated. " ,
1997-11-25 06:05:25 +08:00
" Mark Probst " ,
" Mark Probst " ,
1998-01-25 17:29:29 +08:00
" January 1998, 0.4 " ,
" <Image>/Filters/Distorts/MathMap " ,
" RGB*, GRAY* " ,
1997-11-25 06:05:25 +08:00
PROC_PLUG_IN ,
nargs ,
nreturn_vals ,
args ,
return_vals ) ;
} /* query */
/*****/
static void
run ( char * name ,
int nparams ,
GParam * param ,
int * nreturn_vals ,
GParam * * return_vals )
{
static GParam values [ 1 ] ;
GRunModeType run_mode ;
GStatusType status ;
double xhsiz , yhsiz ;
int pwidth , pheight ;
status = STATUS_SUCCESS ;
run_mode = param [ 0 ] . data . d_int32 ;
1998-01-25 17:29:29 +08:00
image_id = param [ 1 ] . data . d_int32 ;
layer_id = gimp_image_get_active_layer ( image_id ) ;
1997-11-25 06:05:25 +08:00
values [ 0 ] . type = PARAM_STATUS ;
values [ 0 ] . data . d_status = status ;
* nreturn_vals = 1 ;
* return_vals = values ;
/* Get the active drawable info */
1998-01-25 17:29:29 +08:00
input_drawable = gimp_drawable_get ( param [ 2 ] . data . d_drawable ) ;
1997-11-25 06:05:25 +08:00
tile_width = gimp_tile_width ( ) ;
tile_height = gimp_tile_height ( ) ;
1998-01-25 17:29:29 +08:00
img_width = gimp_drawable_width ( input_drawable - > id ) ;
img_height = gimp_drawable_height ( input_drawable - > id ) ;
inputBPP = gimp_drawable_bpp ( input_drawable - > id ) ;
1997-11-25 06:05:25 +08:00
1998-01-25 17:29:29 +08:00
gimp_drawable_mask_bounds ( input_drawable - > id , & sel_x1 , & sel_y1 , & sel_x2 , & sel_y2 ) ;
1997-11-25 06:05:25 +08:00
originX = sel_x1 ;
originY = sel_y1 ;
sel_width = sel_x2 - sel_x1 ;
sel_height = sel_y2 - sel_y1 ;
cen_x = ( double ) ( sel_x2 - 1 + sel_x1 ) / 2.0 ;
cen_y = ( double ) ( sel_y2 - 1 + sel_y1 ) / 2.0 ;
xhsiz = ( double ) ( sel_width - 1 ) / 2.0 ;
yhsiz = ( double ) ( sel_height - 1 ) / 2.0 ;
if ( xhsiz < yhsiz ) {
scale_x = yhsiz / xhsiz ;
scale_y = 1.0 ;
} else if ( xhsiz > yhsiz ) {
scale_x = 1.0 ;
scale_y = xhsiz / yhsiz ;
} else {
scale_x = 1.0 ;
scale_y = 1.0 ;
} /* else */
radius = MAX ( xhsiz , yhsiz ) ;
radius2 = radius * radius ;
/* Calculate preview size */
if ( sel_width > sel_height ) {
pwidth = MIN ( sel_width , PREVIEW_SIZE ) ;
pheight = sel_height * pwidth / sel_width ;
} else {
pheight = MIN ( sel_height , PREVIEW_SIZE ) ;
pwidth = sel_width * pheight / sel_height ;
} /* else */
preview_width = MAX ( pwidth , 2 ) ; /* Min size is 2 */
preview_height = MAX ( pheight , 2 ) ;
1998-01-25 17:29:29 +08:00
init_builtins ( ) ;
1997-11-25 06:05:25 +08:00
/* See how we will run */
switch ( run_mode ) {
case RUN_INTERACTIVE :
/* Possibly retrieve data */
gimp_get_data ( " plug_in_mathmap " , & mmvals ) ;
/* Get information from the dialog */
if ( ! mathmap_dialog ( ) )
return ;
break ;
case RUN_NONINTERACTIVE :
/* Make sure all the arguments are present */
if ( nparams ! = 5 )
status = STATUS_CALLING_ERROR ;
if ( status = = STATUS_SUCCESS )
{
expression_copy ( mmvals . expression , param [ 3 ] . data . d_string ) ;
mmvals . flags = param [ 4 ] . data . d_int32 ;
}
break ;
case RUN_WITH_LAST_VALS :
/* Possibly retrieve data */
gimp_get_data ( " plug_in_mathmap " , & mmvals ) ;
break ;
default :
break ;
} /* switch */
/* Mathmap the image */
1998-01-25 17:29:29 +08:00
if ( ( status = = STATUS_SUCCESS )
& & ( gimp_drawable_color ( input_drawable - > id )
| | gimp_drawable_gray ( input_drawable - > id ) ) )
{
1997-11-25 06:05:25 +08:00
intersamplingEnabled = mmvals . flags & FLAG_INTERSAMPLING ;
oversamplingEnabled = mmvals . flags & FLAG_OVERSAMPLING ;
1998-01-25 17:29:29 +08:00
animationEnabled = mmvals . flags & FLAG_ANIMATION ;
1997-11-25 06:05:25 +08:00
/* Set the tile cache size */
1998-01-25 17:29:29 +08:00
gimp_tile_cache_ntiles ( ( input_drawable - > width + gimp_tile_width ( ) - 1 )
/ gimp_tile_width ( ) ) ;
1997-11-25 06:05:25 +08:00
/* Run! */
1998-01-25 17:29:29 +08:00
if ( animationEnabled )
{
int frameNum ;
for ( frameNum = 0 ; frameNum < mmvals . frames ; + + frameNum )
{
gint32 layer ;
char layerName [ 100 ] ;
currentT = ( double ) frameNum / ( double ) mmvals . frames ;
layer = mathmap_layer_copy ( layer_id ) ;
sprintf ( layerName , " kurdenlayer %d " , frameNum ) ;
gimp_layer_set_name ( layer , layerName ) ;
output_drawable = gimp_drawable_get ( layer ) ;
mathmap ( ) ;
gimp_image_add_layer ( image_id , layer , 0 ) ;
}
}
else
{
currentT = 0.0 ;
output_drawable = input_drawable ;
mathmap ( ) ;
}
1997-11-25 06:05:25 +08:00
/* If run mode is interactive, flush displays */
if ( run_mode ! = RUN_NONINTERACTIVE )
gimp_displays_flush ( ) ;
/* Store data */
if ( run_mode = = RUN_INTERACTIVE )
gimp_set_data ( " plug_in_mathmap " , & mmvals , sizeof ( mathmap_vals_t ) ) ;
} else if ( status = = STATUS_SUCCESS )
status = STATUS_EXECUTION_ERROR ;
values [ 0 ] . data . d_status = status ;
1998-01-25 17:29:29 +08:00
gimp_drawable_detach ( input_drawable ) ;
1997-11-25 06:05:25 +08:00
} /* run */
/*****/
inline void
calc_ra ( void )
{
if ( usesRA )
{
double x = currentX ,
y = currentY ;
currentR = sqrt ( x * x + y * y ) ;
if ( currentR = = 0.0 )
currentA = 0.0 ;
else
currentA = acos ( x / currentR ) * 180 / M_PI ;
if ( y < 0 )
currentA = 360 - currentA ;
}
}
1998-01-25 17:29:29 +08:00
static gint32
mathmap_layer_copy ( gint32 layerID )
{
GParam * return_vals ;
int nreturn_vals ;
gint32 nlayer ;
return_vals = gimp_run_procedure ( " gimp_layer_copy " ,
& nreturn_vals ,
PARAM_LAYER , layerID ,
PARAM_INT32 , TRUE ,
PARAM_END ) ;
if ( return_vals [ 0 ] . data . d_status = = STATUS_SUCCESS )
nlayer = return_vals [ 1 ] . data . d_layer ;
else
nlayer = - 1 ;
gimp_destroy_params ( return_vals , nreturn_vals ) ;
return nlayer ;
}
1997-11-25 06:05:25 +08:00
static void
mathmap ( void )
{
GPixelRgn dest_rgn ;
gpointer pr ;
gint progress , max_progress ;
guchar * dest_row ;
guchar * dest ;
gint row , col ;
double cx , cy ;
int ix , iy ;
double result ;
int red ,
green ,
1998-01-25 17:29:29 +08:00
blue ,
alpha ;
outputBPP = gimp_drawable_bpp ( output_drawable - > id ) ;
1997-11-25 06:05:25 +08:00
theExprtree = 0 ;
1997-12-09 13:57:33 +08:00
scanFromString ( mmvals . expression ) ;
1997-11-25 06:05:25 +08:00
yyparse ( ) ;
1997-12-09 13:57:33 +08:00
endScanningFromString ( ) ;
1997-11-25 06:05:25 +08:00
if ( theExprtree = = 0 )
return ;
make_postfix ( theExprtree ) ;
1997-12-09 13:57:33 +08:00
/* output_postfix(); */
1997-11-25 06:05:25 +08:00
/* Initialize pixel region */
1998-01-25 17:29:29 +08:00
gimp_pixel_rgn_init ( & dest_rgn , output_drawable , sel_x1 , sel_y1 , sel_width , sel_height ,
1997-11-25 06:05:25 +08:00
TRUE , TRUE ) ;
imageWidth = sel_width ;
imageHeight = sel_height ;
wholeImageWidth = img_width ;
wholeImageHeight = img_height ;
middleX = imageWidth / 2.0 ;
middleY = imageHeight / 2.0 ;
if ( middleX > imageWidth - middleX )
imageX = middleX ;
else
imageX = imageWidth - middleX ;
if ( middleY > imageHeight - middleY )
imageY = middleY ;
else
imageY = imageHeight - middleY ;
imageR = sqrt ( imageX * imageX + imageY * imageY ) ;
progress = 0 ;
max_progress = sel_width * sel_height ;
1998-01-25 17:29:29 +08:00
gimp_progress_init ( " Mathmapping... " ) ;
1997-11-25 06:05:25 +08:00
for ( pr = gimp_pixel_rgns_register ( 1 , & dest_rgn ) ;
pr ! = NULL ; pr = gimp_pixel_rgns_process ( pr ) )
{
if ( oversamplingEnabled )
{
unsigned char * line1 ,
* line2 ,
* line3 ;
dest_row = dest_rgn . data ;
line1 = ( unsigned char * ) malloc ( ( sel_width + 1 ) * 3 ) ;
line2 = ( unsigned char * ) malloc ( sel_width * 3 ) ;
line3 = ( unsigned char * ) malloc ( ( sel_width + 1 ) * 3 ) ;
for ( col = 0 ; col < = dest_rgn . w ; + + col )
{
currentX = col + dest_rgn . x - sel_x1 - middleX ;
currentY = 0.0 + dest_rgn . y - sel_y1 - middleY ;
calc_ra ( ) ; result = eval_postfix ( ) ;
1998-01-25 17:29:29 +08:00
double_to_color ( result , & red , & green , & blue , & alpha ) ;
1997-11-25 06:05:25 +08:00
line1 [ col * 3 + 0 ] = red ;
line1 [ col * 3 + 1 ] = green ;
line1 [ col * 3 + 2 ] = blue ;
}
for ( row = 0 ; row < dest_rgn . h ; + + row )
{
dest = dest_row ;
for ( col = 0 ; col < dest_rgn . w ; + + col )
{
currentX = col + dest_rgn . x - sel_x1 + 0.5 - middleX ;
currentY = row + dest_rgn . y - sel_y1 + 0.5 - middleY ;
calc_ra ( ) ; result = eval_postfix ( ) ;
1998-01-25 17:29:29 +08:00
double_to_color ( result , & red , & green , & blue , & alpha ) ;
1997-11-25 06:05:25 +08:00
line2 [ col * 3 + 0 ] = red ;
line2 [ col * 3 + 1 ] = green ;
line2 [ col * 3 + 2 ] = blue ;
}
for ( col = 0 ; col < = dest_rgn . w ; + + col )
{
currentX = col + dest_rgn . x - sel_x1 - middleX ;
currentY = row + dest_rgn . y - sel_y1 + 1.0 - middleY ;
calc_ra ( ) ; result = eval_postfix ( ) ;
1998-01-25 17:29:29 +08:00
double_to_color ( result , & red , & green , & blue , & alpha ) ;
1997-11-25 06:05:25 +08:00
line3 [ col * 3 + 0 ] = red ;
line3 [ col * 3 + 1 ] = green ;
line3 [ col * 3 + 2 ] = blue ;
}
for ( col = 0 ; col < dest_rgn . w ; + + col )
{
red = line1 [ col * 3 + 0 ]
+ line1 [ ( col + 1 ) * 3 + 0 ]
+ 2 * line2 [ col * 3 + 0 ]
+ line3 [ col * 3 + 0 ]
+ line3 [ ( col + 1 ) * 3 + 0 ] ;
green = line1 [ col * 3 + 1 ]
+ line1 [ ( col + 1 ) * 3 + 1 ]
+ 2 * line2 [ col * 3 + 1 ]
+ line3 [ col * 3 + 1 ]
+ line3 [ ( col + 1 ) * 3 + 1 ] ;
blue = line1 [ col * 3 + 2 ]
+ line1 [ ( col + 1 ) * 3 + 2 ]
+ 2 * line2 [ col * 3 + 2 ]
+ line3 [ col * 3 + 2 ]
+ line3 [ ( col + 1 ) * 3 + 2 ] ;
dest [ 0 ] = red / 6 ;
dest [ 1 ] = green / 6 ;
dest [ 2 ] = blue / 6 ;
1998-01-25 17:29:29 +08:00
dest + = outputBPP ;
1997-11-25 06:05:25 +08:00
}
memcpy ( line1 , line3 , ( imageWidth + 1 ) * 3 ) ;
dest_row + = dest_rgn . rowstride ;
}
}
else
{
dest_row = dest_rgn . data ;
for ( row = dest_rgn . y ; row < ( dest_rgn . y + dest_rgn . h ) ; row + + )
{
dest = dest_row ;
for ( col = dest_rgn . x ; col < ( dest_rgn . x + dest_rgn . w ) ; col + + )
{
ix = ( int ) cx ;
iy = ( int ) cy ;
currentX = col - sel_x1 - middleX ; currentY = row - sel_y1 - middleY ;
calc_ra ( ) ; result = eval_postfix ( ) ;
1998-01-25 17:29:29 +08:00
double_to_color ( result , & red , & green , & blue , & alpha ) ;
1997-11-25 06:05:25 +08:00
dest [ 0 ] = red ;
1998-01-25 17:29:29 +08:00
if ( outputBPP = = 2 )
dest [ 1 ] = alpha ;
else if ( outputBPP > = 3 )
{
dest [ 1 ] = green ;
dest [ 2 ] = blue ;
if ( outputBPP = = 4 )
dest [ 3 ] = alpha ;
}
dest + = outputBPP ;
1997-11-25 06:05:25 +08:00
}
dest_row + = dest_rgn . rowstride ;
}
}
/* Update progress */
progress + = dest_rgn . w * dest_rgn . h ;
gimp_progress_update ( ( double ) progress / max_progress ) ;
}
if ( the_tile ! = NULL ) {
gimp_tile_unref ( the_tile , FALSE ) ;
the_tile = NULL ;
} /* if */
1998-01-25 17:29:29 +08:00
gimp_drawable_flush ( output_drawable ) ;
gimp_drawable_merge_shadow ( output_drawable - > id , TRUE ) ;
gimp_drawable_update ( output_drawable - > id , sel_x1 , sel_y1 , sel_width , sel_height ) ;
1997-11-25 06:05:25 +08:00
} /* mathmap */
/*****/
void
mathmap_get_pixel ( int x , int y , guchar * pixel )
{
static gint row = - 1 ;
static gint col = - 1 ;
gint newcol , newrow ;
gint newcoloff , newrowoff ;
guchar * p ;
int i ;
if ( ( x < 0 ) | | ( x > = img_width ) | | ( y < 0 ) | | ( y > = img_height ) ) {
pixel [ 0 ] = 0 ;
pixel [ 1 ] = 0 ;
pixel [ 2 ] = 0 ;
pixel [ 3 ] = 0 ;
return ;
} /* if */
newcol = x / tile_width ; /* The compiler should optimize this */
newcoloff = x % tile_width ;
newrow = y / tile_height ;
newrowoff = y % tile_height ;
if ( ( col ! = newcol ) | | ( row ! = newrow ) | | ( the_tile = = NULL ) ) {
if ( the_tile ! = NULL )
gimp_tile_unref ( the_tile , FALSE ) ;
1998-01-25 17:29:29 +08:00
the_tile = gimp_drawable_get_tile ( input_drawable , FALSE , newrow , newcol ) ;
1997-12-09 13:57:33 +08:00
assert ( the_tile ! = 0 ) ;
1997-11-25 06:05:25 +08:00
gimp_tile_ref ( the_tile ) ;
col = newcol ;
row = newrow ;
} /* if */
p = the_tile - > data + the_tile - > bpp * ( the_tile - > ewidth * newrowoff + newcoloff ) ;
1998-01-25 17:29:29 +08:00
for ( i = inputBPP ; i ; i - - )
1997-11-25 06:05:25 +08:00
* pixel + + = * p + + ;
}
/*****/
static void
build_preview_source_image ( void )
{
double left , right , bottom , top ;
double px , py ;
double dx , dy ;
int x , y ;
guchar * p ;
guchar pixel [ 4 ] ;
wint . image = g_malloc ( preview_width * preview_height * 3 * sizeof ( guchar ) ) ;
wint . wimage = g_malloc ( preview_width * preview_height * 3 * sizeof ( guchar ) ) ;
left = sel_x1 ;
right = sel_x2 - 1 ;
bottom = sel_y2 - 1 ;
top = sel_y1 ;
dx = ( right - left ) / ( preview_width - 1 ) ;
dy = ( bottom - top ) / ( preview_height - 1 ) ;
py = top ;
p = wint . image ;
for ( y = 0 ; y < preview_height ; y + + )
{
px = left ;
for ( x = 0 ; x < preview_width ; x + + )
{
mathmap_get_pixel ( ( int ) px , ( int ) py , pixel ) ;
1998-01-25 17:29:29 +08:00
if ( inputBPP < 3 )
1997-11-25 06:05:25 +08:00
{
pixel [ 1 ] = pixel [ 0 ] ;
pixel [ 2 ] = pixel [ 0 ] ;
} /* if */
* p + + = pixel [ 0 ] ;
* p + + = pixel [ 1 ] ;
* p + + = pixel [ 2 ] ;
px + = dx ;
} /* for */
py + = dy ;
} /* for */
} /* build_preview_source_image */
/*****/
static gint
mathmap_dialog ( void )
{
GtkWidget * dialog ;
1998-01-25 17:29:29 +08:00
GtkWidget * top_table ,
* middle_table ;
1997-11-25 06:05:25 +08:00
GtkWidget * frame ;
GtkWidget * table ;
GtkWidget * button ;
GtkWidget * label ;
GtkWidget * toggle ;
GtkWidget * arrow ;
GtkWidget * alignment ;
GtkWidget * menubox ;
GtkWidget * menubar ;
GtkWidget * menubaritem ;
GtkWidget * menu ;
GtkWidget * item ;
1998-01-25 17:29:29 +08:00
GtkWidget * scale ;
GtkObject * adjustment ;
1997-11-25 06:05:25 +08:00
int i ;
gint argc ;
gchar * * argv ;
guchar * color_cube ;
/*
printf ( " Waiting... (pid %d) \n " , getpid ( ) ) ;
kill ( getpid ( ) , SIGSTOP ) ;
*/
argc = 1 ;
argv = g_new ( gchar * , 1 ) ;
argv [ 0 ] = g_strdup ( " mathmap " ) ;
gtk_init ( & argc , & argv ) ;
gtk_preview_set_gamma ( gimp_gamma ( ) ) ;
gtk_preview_set_install_cmap ( gimp_install_cmap ( ) ) ;
color_cube = gimp_color_cube ( ) ;
gtk_preview_set_color_cube ( color_cube [ 0 ] , color_cube [ 1 ] , color_cube [ 2 ] , color_cube [ 3 ] ) ;
gtk_widget_set_default_visual ( gtk_preview_get_visual ( ) ) ;
gtk_widget_set_default_colormap ( gtk_preview_get_cmap ( ) ) ;
build_preview_source_image ( ) ;
dialog = gtk_dialog_new ( ) ;
gtk_window_set_title ( GTK_WINDOW ( dialog ) , " MathMap " ) ;
gtk_window_position ( GTK_WINDOW ( dialog ) , GTK_WIN_POS_MOUSE ) ;
gtk_container_border_width ( GTK_CONTAINER ( dialog ) , 0 ) ;
gtk_signal_connect ( GTK_OBJECT ( dialog ) , " destroy " ,
( GtkSignalFunc ) dialog_close_callback ,
NULL ) ;
1998-01-25 17:29:29 +08:00
top_table = gtk_table_new ( 5 , 3 , FALSE ) ;
1997-11-25 06:05:25 +08:00
gtk_container_border_width ( GTK_CONTAINER ( top_table ) , 6 ) ;
gtk_table_set_row_spacings ( GTK_TABLE ( top_table ) , 4 ) ;
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( dialog ) - > vbox ) , top_table , FALSE , FALSE , 0 ) ;
gtk_widget_show ( top_table ) ;
1998-01-25 17:29:29 +08:00
/* Preview */
1997-11-25 06:05:25 +08:00
frame = gtk_frame_new ( NULL ) ;
gtk_frame_set_shadow_type ( GTK_FRAME ( frame ) , GTK_SHADOW_IN ) ;
gtk_table_attach ( GTK_TABLE ( top_table ) , frame , 1 , 2 , 0 , 1 , 0 , 0 , 0 , 0 ) ;
gtk_widget_show ( frame ) ;
wint . preview = gtk_preview_new ( GTK_PREVIEW_COLOR ) ;
gtk_preview_size ( GTK_PREVIEW ( wint . preview ) , preview_width , preview_height ) ;
gtk_container_add ( GTK_CONTAINER ( frame ) , wint . preview ) ;
gtk_widget_show ( wint . preview ) ;
button = gtk_button_new_with_label ( " Preview " ) ;
gtk_signal_connect ( GTK_OBJECT ( button ) , " clicked " , ( GtkSignalFunc ) dialog_preview_callback , 0 ) ;
gtk_table_attach ( GTK_TABLE ( top_table ) , button , 1 , 2 , 1 , 2 , GTK_FILL , GTK_FILL , 0 , 0 ) ;
gtk_widget_show ( button ) ;
1998-01-25 17:29:29 +08:00
middle_table = gtk_table_new ( 1 , 2 , FALSE ) ;
gtk_container_border_width ( GTK_CONTAINER ( middle_table ) , 6 ) ;
gtk_table_set_col_spacings ( GTK_TABLE ( middle_table ) , 4 ) ;
gtk_table_attach ( GTK_TABLE ( top_table ) , middle_table , 0 , 3 , 2 , 3 , GTK_FILL , 0 , 0 , 0 ) ;
gtk_widget_show ( middle_table ) ;
1997-11-25 06:05:25 +08:00
1998-01-25 17:29:29 +08:00
/* Sampling */
table = gtk_table_new ( 2 , 1 , FALSE ) ;
gtk_container_border_width ( GTK_CONTAINER ( table ) , 6 ) ;
gtk_table_set_row_spacings ( GTK_TABLE ( table ) , 4 ) ;
frame = gtk_frame_new ( NULL ) ;
gtk_frame_set_shadow_type ( GTK_FRAME ( frame ) , GTK_SHADOW_ETCHED_IN ) ;
gtk_container_add ( GTK_CONTAINER ( frame ) , table ) ;
alignment = gtk_alignment_new ( 0 , 0 , 0 , 0 ) ;
gtk_container_add ( GTK_CONTAINER ( alignment ) , frame ) ;
gtk_table_attach ( GTK_TABLE ( middle_table ) , alignment , 0 , 1 , 0 , 1 , GTK_FILL , 0 , 0 , 0 ) ;
gtk_widget_show ( table ) ;
gtk_widget_show ( frame ) ;
gtk_widget_show ( alignment ) ;
/* Intersampling */
alignment = gtk_alignment_new ( 0 , 0 , 0 , 0 ) ;
toggle = gtk_check_button_new_with_label ( " Intersampling " ) ;
gtk_container_add ( GTK_CONTAINER ( alignment ) , toggle ) ;
gtk_toggle_button_set_state ( GTK_TOGGLE_BUTTON ( toggle ) ,
mmvals . flags & FLAG_INTERSAMPLING ) ;
gtk_table_attach ( GTK_TABLE ( table ) , alignment , 0 , 1 , 0 , 1 , GTK_FILL , 0 , 0 , 0 ) ;
gtk_signal_connect ( GTK_OBJECT ( toggle ) , " toggled " ,
( GtkSignalFunc ) dialog_intersampling_update , 0 ) ;
gtk_widget_show ( toggle ) ;
gtk_widget_show ( alignment ) ;
/* Oversampling */
alignment = gtk_alignment_new ( 0 , 0 , 0 , 0 ) ;
toggle = gtk_check_button_new_with_label ( " Oversampling " ) ;
gtk_container_add ( GTK_CONTAINER ( alignment ) , toggle ) ;
gtk_toggle_button_set_state ( GTK_TOGGLE_BUTTON ( toggle ) ,
mmvals . flags & FLAG_OVERSAMPLING ) ;
gtk_table_attach ( GTK_TABLE ( table ) , alignment , 0 , 1 , 1 , 2 , GTK_FILL , 0 , 0 , 0 ) ;
gtk_signal_connect ( GTK_OBJECT ( toggle ) , " toggled " ,
( GtkSignalFunc ) dialog_oversampling_update , 0 ) ;
gtk_widget_show ( toggle ) ;
gtk_widget_show ( alignment ) ;
/* Animation */
table = gtk_table_new ( 2 , 1 , FALSE ) ;
gtk_container_border_width ( GTK_CONTAINER ( table ) , 6 ) ;
gtk_table_set_row_spacings ( GTK_TABLE ( table ) , 4 ) ;
gtk_table_set_col_spacings ( GTK_TABLE ( table ) , 4 ) ;
frame = gtk_frame_new ( NULL ) ;
gtk_frame_set_shadow_type ( GTK_FRAME ( frame ) , GTK_SHADOW_ETCHED_IN ) ;
gtk_container_add ( GTK_CONTAINER ( frame ) , table ) ;
alignment = gtk_alignment_new ( 0 , 0 , 0 , 0 ) ;
gtk_container_add ( GTK_CONTAINER ( alignment ) , frame ) ;
gtk_table_attach ( GTK_TABLE ( middle_table ) , alignment , 1 , 2 , 0 , 1 , GTK_FILL , 0 , 0 , 0 ) ;
gtk_widget_show ( table ) ;
gtk_widget_show ( frame ) ;
gtk_widget_show ( alignment ) ;
/* Animation Toggle */
alignment = gtk_alignment_new ( 0 , 0 , 0 , 0 ) ;
toggle = gtk_check_button_new_with_label ( " Animate " ) ;
gtk_container_add ( GTK_CONTAINER ( alignment ) , toggle ) ;
gtk_toggle_button_set_state ( GTK_TOGGLE_BUTTON ( toggle ) ,
mmvals . flags & FLAG_ANIMATION ) ;
gtk_table_attach ( GTK_TABLE ( table ) , alignment , 0 , 1 , 0 , 1 , GTK_FILL , 0 , 0 , 0 ) ;
gtk_signal_connect ( GTK_OBJECT ( toggle ) , " toggled " ,
( GtkSignalFunc ) dialog_animation_update , 0 ) ;
gtk_widget_show ( toggle ) ;
gtk_widget_show ( alignment ) ;
/* Number of Frames */
animate_table = gtk_table_new ( 1 , 2 , FALSE ) ;
gtk_table_set_col_spacings ( GTK_TABLE ( animate_table ) , 4 ) ;
gtk_table_attach ( GTK_TABLE ( table ) , animate_table , 0 , 1 , 1 , 2 , GTK_FILL , 0 , 0 , 0 ) ;
label = gtk_label_new ( " Frames " ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( animate_table ) , label , 0 , 1 , 0 , 1 , GTK_FILL , 0 , 0 , 0 ) ;
adjustment = gtk_adjustment_new ( mmvals . frames , 2 , 100 , 1.0 , 1.0 , 0.0 ) ;
scale = gtk_hscale_new ( GTK_ADJUSTMENT ( adjustment ) ) ;
gtk_widget_set_usize ( scale , 100 , 0 ) ;
gtk_table_attach ( GTK_TABLE ( animate_table ) , scale , 1 , 2 , 0 , 1 , GTK_FILL , 0 , 0 , 0 ) ;
gtk_scale_set_value_pos ( GTK_SCALE ( scale ) , GTK_POS_TOP ) ;
gtk_scale_set_digits ( GTK_SCALE ( scale ) , 0 ) ;
gtk_range_set_update_policy ( GTK_RANGE ( scale ) , GTK_UPDATE_DELAYED ) ;
gtk_signal_connect ( GTK_OBJECT ( adjustment ) , " value_changed " ,
( GtkSignalFunc ) dialog_scale_update ,
& mmvals . frames ) ;
gtk_widget_show ( label ) ;
gtk_widget_show ( scale ) ;
gtk_widget_show ( animate_table ) ;
gtk_widget_set_sensitive ( animate_table , mmvals . flags & FLAG_ANIMATION ) ;
1997-11-25 06:05:25 +08:00
/* Menu */
menu = gtk_menu_new ( ) ;
for ( i = 0 ; examples [ i ] [ 0 ] ! = 0 ; + + i )
{
item = gtk_menu_item_new_with_label ( examples [ i ] [ 0 ] ) ;
gtk_menu_append ( GTK_MENU ( menu ) , item ) ;
1998-01-25 17:29:29 +08:00
gtk_signal_connect ( GTK_OBJECT ( item ) , " activate " ,
( GtkSignalFunc ) dialog_example_callback , examples [ i ] [ 1 ] ) ;
1997-11-25 06:05:25 +08:00
gtk_widget_show ( item ) ;
}
alignment = gtk_alignment_new ( 0 , 0 , 0 , 0 ) ;
menubar = gtk_menu_bar_new ( ) ;
gtk_container_add ( GTK_CONTAINER ( alignment ) , menubar ) ;
menubaritem = gtk_menu_item_new ( ) ;
menubox = gtk_hbox_new ( FALSE , 2 ) ;
label = gtk_label_new ( " Examples " ) ;
arrow = gtk_arrow_new ( GTK_ARROW_DOWN , GTK_SHADOW_OUT ) ;
gtk_box_pack_start ( GTK_BOX ( menubox ) , arrow , FALSE , FALSE , 0 ) ;
gtk_box_pack_start ( GTK_BOX ( menubox ) , label , FALSE , FALSE , 4 ) ;
gtk_container_add ( GTK_CONTAINER ( menubaritem ) , menubox ) ;
gtk_container_add ( GTK_CONTAINER ( menubar ) , menubaritem ) ;
gtk_menu_item_set_submenu ( GTK_MENU_ITEM ( menubaritem ) , menu ) ;
1998-01-25 17:29:29 +08:00
gtk_table_attach ( GTK_TABLE ( top_table ) , alignment , 0 , 3 , 3 , 4 , GTK_FILL , 0 , 0 , 0 ) ;
1997-11-25 06:05:25 +08:00
gtk_widget_show ( arrow ) ;
gtk_widget_show ( label ) ;
gtk_widget_show ( menubox ) ;
gtk_widget_show ( menubaritem ) ;
gtk_widget_show ( menubar ) ;
gtk_widget_show ( alignment ) ;
/* Expression */
table = gtk_table_new ( 1 , 2 , FALSE ) ;
gtk_container_border_width ( GTK_CONTAINER ( table ) , 0 ) ;
1998-01-25 17:29:29 +08:00
gtk_table_attach ( GTK_TABLE ( top_table ) , table , 0 , 3 , 4 , 5 , GTK_EXPAND | GTK_FILL , 0 , 0 , 0 ) ;
1997-11-25 06:05:25 +08:00
gtk_widget_show ( table ) ;
label = gtk_label_new ( " Expression " ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
gtk_table_attach ( GTK_TABLE ( table ) , label , 0 , 1 , 0 , 1 , GTK_FILL , GTK_FILL , 4 , 0 ) ;
gtk_widget_show ( label ) ;
1998-01-25 17:29:29 +08:00
expression_entry = gtk_entry_new ( ) ;
1997-11-25 06:05:25 +08:00
/*
gtk_object_set_user_data ( GTK_OBJECT ( entry ) , scale_data ) ;
gtk_object_set_user_data ( scale_data , entry ) ;
*/
1998-01-25 17:29:29 +08:00
gtk_widget_set_usize ( expression_entry , ENTRY_WIDTH , 0 ) ;
gtk_entry_set_text ( GTK_ENTRY ( expression_entry ) , mmvals . expression ) ;
gtk_signal_connect ( GTK_OBJECT ( expression_entry ) , " changed " ,
1997-11-25 06:05:25 +08:00
( GtkSignalFunc ) dialog_entry_update ,
0 ) ;
1998-01-25 17:29:29 +08:00
gtk_table_attach ( GTK_TABLE ( table ) , expression_entry , 1 , 2 , 0 , 1 ,
1997-11-25 06:05:25 +08:00
GTK_EXPAND | GTK_FILL , GTK_FILL , 4 , 0 ) ;
1998-01-25 17:29:29 +08:00
gtk_widget_show ( expression_entry ) ;
1997-11-25 06:05:25 +08:00
/* Buttons */
gtk_container_border_width ( GTK_CONTAINER ( GTK_DIALOG ( dialog ) - > action_area ) , 6 ) ;
button = gtk_button_new_with_label ( " OK " ) ;
GTK_WIDGET_SET_FLAGS ( button , GTK_CAN_DEFAULT ) ;
gtk_signal_connect ( GTK_OBJECT ( button ) , " clicked " ,
( GtkSignalFunc ) dialog_ok_callback ,
dialog ) ;
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( dialog ) - > 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 ( GTK_OBJECT ( button ) , " clicked " ,
( GtkSignalFunc ) dialog_cancel_callback ,
dialog ) ;
gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG ( dialog ) - > action_area ) , button , TRUE , TRUE , 0 ) ;
gtk_widget_show ( button ) ;
/* Done */
gtk_widget_show ( dialog ) ;
/* dialog_update_preview(); */
gtk_main ( ) ;
gdk_flush ( ) ;
if ( the_tile ! = NULL ) {
gimp_tile_unref ( the_tile , FALSE ) ;
the_tile = NULL ;
} /* if */
g_free ( wint . image ) ;
g_free ( wint . wimage ) ;
return wint . run ;
} /* mathmap_dialog */
/*****/
static void
dialog_update_preview ( void )
{
double left , right , bottom , top ;
double dx , dy ;
int x , y ;
double scale_x , scale_y ;
1998-01-25 17:29:29 +08:00
guchar * p_ul , * p_lr , * p ;
1997-11-25 06:05:25 +08:00
intersamplingEnabled = mmvals . flags & FLAG_INTERSAMPLING ;
oversamplingEnabled = mmvals . flags & FLAG_OVERSAMPLING ;
left = sel_x1 ;
right = sel_x2 - 1 ;
bottom = sel_y2 - 1 ;
top = sel_y1 ;
dx = ( right - left ) / ( preview_width - 1 ) ;
dy = ( bottom - top ) / ( preview_height - 1 ) ;
scale_x = ( double ) ( preview_width - 1 ) / ( right - left ) ;
scale_y = ( double ) ( preview_height - 1 ) / ( bottom - top ) ;
p_ul = wint . wimage ;
p_lr = wint . wimage + 3 * ( preview_width * preview_height - 1 ) ;
1997-12-09 13:57:33 +08:00
scanFromString ( mmvals . expression ) ;
1997-11-25 06:05:25 +08:00
yyparse ( ) ;
1997-12-09 13:57:33 +08:00
endScanningFromString ( ) ;
1997-11-25 06:05:25 +08:00
if ( theExprtree = = 0 )
return ;
1997-12-09 13:57:33 +08:00
1997-11-25 06:05:25 +08:00
make_postfix ( theExprtree ) ;
imageWidth = sel_width ;
imageHeight = sel_height ;
wholeImageWidth = img_width ;
wholeImageHeight = img_height ;
middleX = imageWidth / 2.0 ;
middleY = imageHeight / 2.0 ;
if ( middleX > imageWidth - middleX )
imageX = middleX ;
else
imageX = imageWidth - middleX ;
if ( middleY > imageHeight - middleY )
imageY = middleY ;
else
imageY = imageHeight - middleY ;
imageR = sqrt ( imageX * imageX + imageY * imageY ) ;
1997-12-09 13:57:33 +08:00
for ( y = 0 ; y < preview_height ; y + + )
1997-11-25 06:05:25 +08:00
{
for ( x = 0 ; x < preview_width ; x + + )
{
double result ;
int red ,
green ,
1998-01-25 17:29:29 +08:00
blue ,
alpha ;
1997-11-25 06:05:25 +08:00
currentX = x * imageWidth / preview_width - middleX ;
currentY = y * imageHeight / preview_height - middleY ;
calc_ra ( ) ; result = eval_postfix ( ) ;
1998-01-25 17:29:29 +08:00
double_to_color ( result , & red , & green , & blue , & alpha ) ;
1997-11-25 06:05:25 +08:00
p_ul [ 0 ] = red ;
p_ul [ 1 ] = green ;
p_ul [ 2 ] = blue ;
p_ul + = 3 ;
}
}
p = wint . wimage ;
for ( y = 0 ; y < preview_height ; y + + )
{
gtk_preview_draw_row ( GTK_PREVIEW ( wint . preview ) , p , 0 , y , preview_width ) ;
p + = preview_width * 3 ;
1997-12-09 13:57:33 +08:00
}
1997-11-25 06:05:25 +08:00
gtk_widget_draw ( wint . preview , NULL ) ;
gdk_flush ( ) ;
} /* dialog_update_preview */
/*****/
1998-01-25 17:29:29 +08:00
/*
1997-11-25 06:05:25 +08:00
static void
dialog_create_value ( char * title , GtkTable * table , int row , gdouble * value ,
double left , double right )
{
GtkWidget * label ;
GtkWidget * scale ;
GtkWidget * entry ;
GtkObject * scale_data ;
char buf [ 256 ] ;
label = gtk_label_new ( title ) ;
gtk_misc_set_alignment ( GTK_MISC ( label ) , 0.0 , 0.5 ) ;
gtk_table_attach ( table , label , 0 , 1 , row , row + 1 , GTK_FILL , GTK_FILL , 4 , 0 ) ;
gtk_widget_show ( label ) ;
scale_data = gtk_adjustment_new ( * value , left , right ,
( right - left ) / 360.0 ,
( right - left ) / 360.0 ,
0.0 ) ;
gtk_signal_connect ( GTK_OBJECT ( scale_data ) , " value_changed " ,
( GtkSignalFunc ) dialog_scale_update ,
value ) ;
scale = gtk_hscale_new ( GTK_ADJUSTMENT ( scale_data ) ) ;
gtk_widget_set_usize ( scale , SCALE_WIDTH , 0 ) ;
gtk_table_attach ( table , scale , 1 , 2 , row , row + 1 , GTK_EXPAND | GTK_FILL , GTK_FILL , 0 , 0 ) ;
gtk_scale_set_draw_value ( GTK_SCALE ( scale ) , FALSE ) ;
gtk_scale_set_digits ( GTK_SCALE ( scale ) , 3 ) ;
gtk_range_set_update_policy ( GTK_RANGE ( scale ) , GTK_UPDATE_CONTINUOUS ) ;
gtk_widget_show ( scale ) ;
entry = gtk_entry_new ( ) ;
gtk_object_set_user_data ( GTK_OBJECT ( entry ) , scale_data ) ;
gtk_object_set_user_data ( scale_data , entry ) ;
gtk_widget_set_usize ( entry , ENTRY_WIDTH , 0 ) ;
sprintf ( buf , " %0.2f " , * value ) ;
gtk_entry_set_text ( GTK_ENTRY ( entry ) , buf ) ;
gtk_signal_connect ( GTK_OBJECT ( entry ) , " changed " ,
( GtkSignalFunc ) dialog_entry_update ,
value ) ;
gtk_table_attach ( GTK_TABLE ( table ) , entry , 2 , 3 , row , row + 1 , GTK_FILL , GTK_FILL , 4 , 0 ) ;
gtk_widget_show ( entry ) ;
1998-01-25 17:29:29 +08:00
}
*/
1997-11-25 06:05:25 +08:00
/*****/
static void
1998-01-25 17:29:29 +08:00
dialog_scale_update ( GtkAdjustment * adjustment , gint * value )
1997-11-25 06:05:25 +08:00
{
1998-01-25 17:29:29 +08:00
* value = ( gint ) adjustment - > value ;
1997-11-25 06:05:25 +08:00
} /* dialog_scale_update */
/*****/
static void
1998-01-25 17:29:29 +08:00
dialog_entry_update ( GtkWidget * widget , gpointer value )
1997-11-25 06:05:25 +08:00
{
expression_copy ( mmvals . expression , gtk_entry_get_text ( GTK_ENTRY ( widget ) ) ) ;
} /* dialog_entry_update */
/*****/
static void
dialog_oversampling_update ( GtkWidget * widget , gpointer data )
{
mmvals . flags & = ~ FLAG_OVERSAMPLING ;
if ( GTK_TOGGLE_BUTTON ( widget ) - > active )
mmvals . flags | = FLAG_OVERSAMPLING ;
}
/*****/
static void
dialog_intersampling_update ( GtkWidget * widget , gpointer data )
{
mmvals . flags & = ~ FLAG_INTERSAMPLING ;
if ( GTK_TOGGLE_BUTTON ( widget ) - > active )
mmvals . flags | = FLAG_INTERSAMPLING ;
}
/*****/
1998-01-25 17:29:29 +08:00
static void
dialog_animation_update ( GtkWidget * widget , gpointer data )
{
mmvals . flags & = ~ FLAG_ANIMATION ;
if ( GTK_TOGGLE_BUTTON ( widget ) - > active )
mmvals . flags | = FLAG_ANIMATION ;
gtk_widget_set_sensitive ( animate_table , mmvals . flags & FLAG_ANIMATION ) ;
}
/*****/
1997-11-25 06:05:25 +08:00
static void
dialog_example_callback ( GtkWidget * widget , char * expression )
{
1998-01-25 17:29:29 +08:00
gtk_entry_set_text ( GTK_ENTRY ( expression_entry ) , expression ) ;
1997-11-25 06:05:25 +08:00
}
/*****/
static void
dialog_preview_callback ( GtkWidget * widget , gpointer data )
{
dialog_update_preview ( ) ;
}
/*****/
static void
dialog_close_callback ( GtkWidget * widget , gpointer data )
{
gtk_main_quit ( ) ;
} /* dialog_close_callback */
/*****/
static void
dialog_ok_callback ( GtkWidget * widget , gpointer data )
{
wint . run = TRUE ;
gtk_widget_destroy ( GTK_WIDGET ( data ) ) ;
} /* dialog_ok_callback */
/*****/
static void
dialog_cancel_callback ( GtkWidget * widget , gpointer data )
{
gtk_widget_destroy ( GTK_WIDGET ( data ) ) ;
} /* dialog_cancel_callback */