#include "config.h" #include #include #include #include #ifdef __GNUC__ #warning GTK_DISABLE_DEPRECATED #endif #undef GTK_DISABLE_DEPRECATED #include #include #include #include "gimpressionist.h" #include "ppmtool.h" #include "libgimp/stdplugins-intl.h" #define MAPFILE "data.out" static GtkWidget *smwindow; static GtkWidget *smvectorprev; static GtkWidget *smpreviewprev; static GtkWidget *prev_button; static GtkWidget *next_button; static GtkWidget *add_button; static GtkWidget *kill_button; GtkObject *smvectprevbrightadjust = NULL; GtkObject *sizadjust = NULL; GtkObject *smstradjust = NULL; GtkObject *smstrexpadjust = NULL; GtkWidget *sizevoronoi = NULL; #define OMWIDTH 150 #define OMHEIGHT 150 static smvector_t smvector[MAXSIZEVECT]; static int numsmvect = 0; double dist(double x, double y, double dx, double dy); double getsiz(double x, double y, int from) { int i; int n; int voronoi; double sum, ssum, dst; smvector_t *vec; double smstrexp; int first = 0, last; if((x < 0.0) || (x > 1.0)) printf("HUH? x = %f\n",x); if(from == 0) { n = numsmvect; vec = smvector; smstrexp = GTK_ADJUSTMENT(smstrexpadjust)->value; voronoi = GTK_TOGGLE_BUTTON(sizevoronoi)->active; } else { n = pcvals.numsizevector; vec = pcvals.sizevector; smstrexp = pcvals.sizestrexp; voronoi = pcvals.sizevoronoi; } if(voronoi) { double bestdist = -1.0; for(i = 0; i < n; i++) { dst = dist(x,y,vec[i].x,vec[i].y); if((bestdist < 0.0) || (dst < bestdist)) { bestdist = dst; first = i; } } last = first+1; } else { first = 0; last = n; } sum = ssum = 0.0; for(i = first; i < last; i++) { double s = vec[i].str; dst = dist(x,y,vec[i].x,vec[i].y); dst = pow(dst, smstrexp); if(dst < 0.0001) dst = 0.0001; s = s / dst; sum += vec[i].siz * s; ssum += 1.0/dst; } sum = sum / ssum / 100.0; return CLAMP(sum, 0.0, 1.0); } void updatesmpreviewprev(void) { int x, y; static ppm_t nsbuffer = {0,0,NULL}; guchar black[3] = {0,0,0}; guchar gray[3] = {120,120,120}; if(!nsbuffer.col) { newppm(&nsbuffer,OMWIDTH,OMHEIGHT); } fill(&nsbuffer, black); for(y = 6; y < OMHEIGHT-4; y += 10) for(x = 6; x < OMWIDTH-4; x += 10) { double siz = 5 * getsiz(x/(double)OMWIDTH,y/(double)OMHEIGHT,0); drawline(&nsbuffer, x-siz, y-siz, x+siz, y-siz, gray); drawline(&nsbuffer, x+siz, y-siz, x+siz, y+siz, gray); drawline(&nsbuffer, x+siz, y+siz, x-siz, y+siz, gray); drawline(&nsbuffer, x-siz, y+siz, x-siz, y-siz, gray); } for(y = 0; y < OMHEIGHT; y++) gtk_preview_draw_row(GTK_PREVIEW(smpreviewprev), &nsbuffer.col[y*nsbuffer.width*3], 0, y, OMWIDTH); gtk_widget_draw(smpreviewprev,NULL); } static gint selectedsmvector = 0; void updatesmvectorprev(void) { static ppm_t backup = {0,0,NULL}; static ppm_t sbuffer = {0,0,NULL}; static int ok = 0; int i, x, y; double val; static double lastval = 0.0; guchar gray[3] = {120,120,120}; guchar red[3] = {255,0,0}; guchar white[3] = {255,255,255}; if (smvectprevbrightadjust) val = 1.0 - GTK_ADJUSTMENT(smvectprevbrightadjust)->value / 100.0; else val = 0.5; if(!ok || (val != lastval)) { if(!infile.col) updatepreviewprev(NULL, (void *)2); /* Force grabarea() */ copyppm(&infile, &backup); ppmbrightness(&backup, val, 1,1,1); if((backup.width != OMWIDTH) || (backup.height != OMHEIGHT)) resize_fast(&backup, OMWIDTH, OMHEIGHT); ok = 1; } copyppm(&backup, &sbuffer); for(i = 0; i < numsmvect; i++) { x = smvector[i].x * OMWIDTH; y = smvector[i].y * OMHEIGHT; if(i == selectedsmvector) { drawline(&sbuffer, x-5, y, x+5, y, red); drawline(&sbuffer, x, y-5, x, y+5, red); } else { drawline(&sbuffer, x-5, y, x+5, y, gray); drawline(&sbuffer, x, y-5, x, y+5, gray); } putrgb(&sbuffer, x, y, white); } for(y = 0; y < OMHEIGHT; y++) gtk_preview_draw_row(GTK_PREVIEW(smvectorprev), &sbuffer.col[y*sbuffer.width*3], 0, y, OMWIDTH); gtk_widget_draw(smvectorprev,NULL); gtk_widget_set_sensitive (prev_button, (numsmvect > 1)); gtk_widget_set_sensitive (next_button, (numsmvect > 1)); gtk_widget_set_sensitive (add_button, (numsmvect < MAXORIENTVECT)); gtk_widget_set_sensitive (kill_button, (numsmvect > 1)); } static gboolean smadjignore = FALSE; void updatesmsliders(void) { smadjignore = TRUE; gtk_adjustment_set_value(GTK_ADJUSTMENT(sizadjust), smvector[selectedsmvector].siz); gtk_adjustment_set_value(GTK_ADJUSTMENT(smstradjust), smvector[selectedsmvector].str); smadjignore = FALSE; } void smprevclick(GtkWidget *w, gpointer data) { selectedsmvector--; if(selectedsmvector < 0) selectedsmvector = numsmvect-1; updatesmsliders(); updatesmvectorprev(); } void smnextclick(GtkWidget *w, gpointer data) { selectedsmvector++; if(selectedsmvector == numsmvect) selectedsmvector = 0; updatesmsliders(); updatesmvectorprev(); } static void smaddclick(GtkWidget *w, gpointer data) { smvector[numsmvect].x = 0.5; smvector[numsmvect].y = 0.5; smvector[numsmvect].siz = 50.0; smvector[numsmvect].str = 1.0; selectedsmvector = numsmvect; numsmvect++; updatesmsliders(); updatesmvectorprev(); updatesmpreviewprev(); } static void smdeleteclick(GtkWidget *w, gpointer data) { int i; for (i = selectedsmvector; i < numsmvect-1; i++) { smvector[i] = smvector[i+1]; } numsmvect--; if(selectedsmvector >= numsmvect) selectedsmvector = 0; updatesmsliders(); updatesmvectorprev(); updatesmpreviewprev(); } static void smmapclick(GtkWidget *w, GdkEventButton *event) { if(event->button == 1) { smvector[selectedsmvector].x = event->x / (double)OMWIDTH; smvector[selectedsmvector].y = event->y / (double)OMHEIGHT; } else if(event->button == 2) { if(numsmvect + 1 == MAXSIZEVECT) return; smvector[numsmvect].x = event->x / (double)OMWIDTH; smvector[numsmvect].y = event->y / (double)OMHEIGHT; smvector[numsmvect].siz = 0.0; smvector[numsmvect].str = 1.0; selectedsmvector = numsmvect; numsmvect++; updatesmsliders(); /* } else if(event->button == 3) { double d; d = atan2(OMWIDTH * smvector[selectedsmvector].x - event->x, OMHEIGHT * smvector[selectedsmvector].y - event->y); smvector[selectedsmvector].dir = radtodeg(d); updatesmsliders(); */ } updatesmvectorprev(); updatesmpreviewprev(); } static void angsmadjmove(GtkWidget *w, gpointer data) { if (!smadjignore) { smvector[selectedsmvector].siz = GTK_ADJUSTMENT(sizadjust)->value; updatesmvectorprev(); updatesmpreviewprev(); } } static void strsmadjmove(GtkWidget *w, gpointer data) { if (!smadjignore) { smvector[selectedsmvector].str = GTK_ADJUSTMENT(smstradjust)->value; updatesmvectorprev(); updatesmpreviewprev(); } } static void smstrexpsmadjmove(GtkWidget *w, gpointer data) { if (!smadjignore) { updatesmvectorprev(); updatesmpreviewprev(); } } static void smapplyclick(GtkWidget *w, GtkWidget *win) { int i; for (i = 0; i < numsmvect; i++) { pcvals.sizevector[i] = smvector[i]; } pcvals.numsizevector = numsmvect; pcvals.sizestrexp = GTK_ADJUSTMENT(smstrexpadjust)->value; pcvals.sizevoronoi = GTK_TOGGLE_BUTTON(sizevoronoi)->active; } static void smokclick(GtkWidget *w, GtkWidget *win) { smapplyclick(NULL, NULL); gtk_widget_hide(w); } void initsmvectors(void) { if (pcvals.numsizevector) { int i; numsmvect = pcvals.numsizevector; for(i = 0; i < numsmvect; i++) { smvector[i] = pcvals.sizevector[i]; } } else { /* Shouldn't happen */ numsmvect = 1; smvector[0].x = 0.5; smvector[0].y = 0.5; smvector[0].siz = 0.0; smvector[0].str = 1.0; } if(selectedsmvector >= numsmvect) selectedsmvector = numsmvect-1; } static void update_sizemap_dialog(void) { if (smwindow) { initsmvectors(); gtk_adjustment_set_value(GTK_ADJUSTMENT(smstrexpadjust), pcvals.sizestrexp); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sizevoronoi), pcvals.sizevoronoi); updatesmvectorprev(); updatesmpreviewprev(); } } void create_sizemap_dialog(void) { GtkWidget *tmpw, *tmpw2; GtkWidget *table1; GtkWidget *table2; GtkWidget *hbox; gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sizeradio[7]), TRUE); initsmvectors(); if(smwindow) { updatesmvectorprev(); updatesmpreviewprev(); gtk_widget_show(smwindow); return; } smwindow = gimp_dialog_new (_("Size Map Editor"), "gimpressionist", gimp_standard_help_func, "filters/gimpressionst.html", GTK_WIN_POS_MOUSE, FALSE, TRUE, FALSE, GTK_STOCK_APPLY, smapplyclick, NULL, NULL, NULL, FALSE, FALSE, GTK_STOCK_CANCEL, gtk_widget_hide, NULL, 1, NULL, FALSE, FALSE, GTK_STOCK_OK, smokclick, NULL, 1, NULL, TRUE, FALSE, NULL); g_signal_connect (smwindow, "destroy", G_CALLBACK(gtk_widget_destroyed), &smwindow); g_signal_connect (smwindow, "delete_event", G_CALLBACK(gtk_widget_hide_on_delete), &smwindow); table1 = gtk_table_new(2, 5, FALSE); gtk_container_set_border_width (GTK_CONTAINER (table1), 6); gtk_container_add (GTK_CONTAINER (GTK_DIALOG (smwindow)->vbox), table1); gtk_widget_show(table1); tmpw2 = tmpw = gtk_frame_new( _("Smvectors")); gtk_container_set_border_width (GTK_CONTAINER (tmpw), 2); gtk_table_attach(GTK_TABLE(table1), tmpw, 0,1,0,1,GTK_EXPAND,GTK_EXPAND,0,0); gtk_widget_show(tmpw); tmpw = hbox = gtk_hbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(tmpw2), tmpw); gtk_widget_show(tmpw); tmpw = gtk_event_box_new(); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), tmpw, _("The smvector-field. Left-click to move selected smvector, Right-click to point it towards mouse, Middle-click to add a new smvector."), NULL); gtk_box_pack_start(GTK_BOX(hbox), tmpw, FALSE, FALSE, 0); tmpw2 = tmpw; tmpw = smvectorprev = gtk_preview_new(GTK_PREVIEW_COLOR); gtk_preview_size(GTK_PREVIEW(tmpw), OMWIDTH, OMHEIGHT); gtk_container_add(GTK_CONTAINER(tmpw2), tmpw); gtk_widget_show(tmpw); gtk_widget_add_events (tmpw2, GDK_BUTTON_PRESS_MASK); g_signal_connect(tmpw2, "button_press_event", G_CALLBACK (smmapclick), NULL); gtk_widget_show(tmpw2); smvectprevbrightadjust = gtk_adjustment_new(50.0, 0.0, 100.0, 1.0, 1.0, 1.0); tmpw = gtk_vscale_new(GTK_ADJUSTMENT(smvectprevbrightadjust)); gtk_scale_set_draw_value (GTK_SCALE (tmpw), FALSE); gtk_box_pack_start(GTK_BOX(hbox), tmpw,FALSE,FALSE,0); gtk_widget_show(tmpw); g_signal_connect (smvectprevbrightadjust, "value_changed", G_CALLBACK (updatesmvectorprev), NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), tmpw, _("Adjust the preview's brightness"), NULL); tmpw2 = tmpw = gtk_frame_new( _("Preview")); gtk_container_set_border_width (GTK_CONTAINER (tmpw), 2); gtk_table_attach(GTK_TABLE(table1), tmpw, 1,2,0,1,GTK_EXPAND,GTK_EXPAND,0,0); gtk_widget_show(tmpw); tmpw = smpreviewprev = gtk_preview_new(GTK_PREVIEW_COLOR); gtk_preview_size(GTK_PREVIEW(tmpw), OMWIDTH, OMHEIGHT); gtk_container_add(GTK_CONTAINER(tmpw2), tmpw); gtk_widget_show(tmpw); hbox = gtk_hbox_new(TRUE,0); gtk_container_set_border_width (GTK_CONTAINER (hbox), 2); gtk_table_attach_defaults(GTK_TABLE(table1), hbox, 0, 1, 1, 2); gtk_widget_show(hbox); prev_button = tmpw = gtk_button_new_with_mnemonic("_<<"); gtk_box_pack_start(GTK_BOX(hbox),tmpw,FALSE,TRUE,0); gtk_widget_show(tmpw); g_signal_connect (tmpw, "clicked", G_CALLBACK (smprevclick), NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), tmpw, _("Select previous smvector"), NULL); next_button = tmpw = gtk_button_new_with_mnemonic("_>>"); gtk_box_pack_start(GTK_BOX(hbox),tmpw,FALSE,TRUE,0); gtk_widget_show(tmpw); g_signal_connect (tmpw, "clicked", G_CALLBACK(smnextclick), NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), tmpw, _("Select next smvector"), NULL); add_button = tmpw = gtk_button_new_with_mnemonic( _("A_dd")); gtk_box_pack_start(GTK_BOX(hbox),tmpw,FALSE,TRUE,0); gtk_widget_show(tmpw); g_signal_connect (tmpw, "clicked", G_CALLBACK(smaddclick), NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), tmpw, _("Add new smvector"), NULL); kill_button = tmpw = gtk_button_new_with_mnemonic( _("_Kill")); gtk_box_pack_start(GTK_BOX(hbox),tmpw,FALSE,TRUE,0); gtk_widget_show(tmpw); g_signal_connect (tmpw, "clicked", G_CALLBACK(smdeleteclick), NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), tmpw, _("Delete selected smvector"), NULL); table2 = gtk_table_new(3, 4, FALSE); gtk_table_set_col_spacings (GTK_TABLE(table2), 4); gtk_table_attach_defaults(GTK_TABLE(table1), table2, 0, 2, 2, 3); gtk_widget_show(table2); sizadjust = gimp_scale_entry_new (GTK_TABLE(table2), 0, 0, _("_Size:"), 150, 6, 50.0, 0.0, 100.0, 1.0, 10.0, 1, TRUE, 0, 0, _("Change the angle of the selected smvector"), NULL); g_signal_connect (sizadjust, "value_changed", G_CALLBACK(angsmadjmove), NULL); smstradjust = gimp_scale_entry_new (GTK_TABLE(table2), 0, 1, _("S_trength:"), 150, 6, 1.0, 0.1, 5.0, 0.1, 0.5, 1, TRUE, 0, 0, _("Change the strength of the selected smvector"), NULL); g_signal_connect (smstradjust, "value_changed", G_CALLBACK(strsmadjmove), NULL); smstrexpadjust = gimp_scale_entry_new (GTK_TABLE(table2), 0, 2, _("St_rength exp.:"), 150, 6, 1.0, 0.1, 10.9, 0.1, 0.5, 1, TRUE, 0, 0, _("Change the exponent of the strength"), NULL); g_signal_connect (smstrexpadjust, "value_changed", G_CALLBACK(smstrexpsmadjmove), NULL); sizevoronoi = tmpw = gtk_check_button_new_with_mnemonic( _("_Voronoi")); gtk_table_attach_defaults(GTK_TABLE(table2), tmpw, 3, 4, 0, 1); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmpw), FALSE); gtk_widget_show (tmpw); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tmpw), pcvals.sizevoronoi); g_signal_connect(tmpw, "clicked", G_CALLBACK(smstrexpsmadjmove), NULL); gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), tmpw, _("Voronoi-mode makes only the smvector closest to the given point have any influence"), NULL); gtk_widget_show(smwindow); updatesmvectorprev(); updatesmpreviewprev(); }