1 /**
2 * Copyright (C) 2012 hejian <hejian.he@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <libgimp/gimp.h>
19 #include <libgimp/gimpui.h>
20
21 #include "border-textures.h"
22
23 #define RIP_BORDER_PROC "plug-in-rip-border"
24 #define TEXTURE_BORDER_PROC "plug-in-texture-border"
25 #define PLUG_IN_BINARY "border"
26 #define PLUG_IN_ROLE "gimp-border"
27
28 #define RIP_BORDER_TEXTURE_PATH "rip-border"
29 #define TEXTURE_BORDER_TEXTURE_PATH "texture-border"
30
31 #define PREVIEW_SIZE 480
32 #define THUMBNAIL_SIZE 80
33
34 typedef struct
35 {
36 const guint8* texture;
37 GimpRGB color;
38 gdouble opacity;
39 const gchar *custom_texture;
40 } BorderValues;
41
42 static void query (void);
43 static void run (const gchar *name,
44 gint nparams,
45 const GimpParam *param,
46 gint *nreturn_vals,
47 GimpParam **return_vals);
48
49 static void border (gint32 image_ID);
50
51 static gboolean border_dialog (const gchar *title, const gchar *help_id, const guint8** textures, guint n_textures, const gchar *texture_path);
52
53 static void create_texture_page (GtkNotebook *notebook, const gchar *category, const guint8** textures, guint n_textures);
54 static gboolean create_custom_texture_pages (GtkNotebook *notebook, const gchar *texture_path);
55 static void create_custom_texture_page (GtkNotebook *notebook, const gchar *category, const gchar *path);
56 static void textures_switch_page (GtkNotebook *notebook, GtkWidget *page, guint page_num, const gchar *texture_path);
57
58 static gboolean texture_press (GtkWidget *event_box, GdkEventButton *event, const guint8 *texture);
59 static gboolean custom_texture_press (GtkWidget *event_box, GdkEventButton *event, const gchar *texture);
60 static void do_texture_press ();
61
62 static inline gboolean
is_hidden(const gchar * filename)63 is_hidden (const gchar *filename)
64 {
65 /* skip files starting with '.' so we don't try to parse
66 * stuff like .DS_Store or other metadata storage files
67 */
68 return (filename[0] == '.');
69 }
70
71 const GimpPlugInInfo PLUG_IN_INFO =
72 {
73 NULL, /* init_proc */
74 NULL, /* quit_proc */
75 query, /* query_proc */
76 run, /* run_proc */
77 };
78
79 static BorderValues bvals =
80 {
81 NULL, /* texture */
82 {1.0, 1.0, 1.0, 1.0}, /* color */
83 100, /* opacity */
84 NULL, /* custom_texture */
85 };
86
87 static gint32 image_ID = 0;
88 static gint width;
89 static gint height;
90
91 static GtkWidget *preview = NULL;
92 static gint32 preview_image = 0;
93 static gint32 color_layer = 0;
94 static gint32 texture_mask = 0;
95
96 static const guint8* rip_border_textures[] =
97 {
98 texture_14911,
99 texture_12847,
100 texture_201301,
101 texture_201185,
102 texture_111601,
103 texture_201072,
104 texture_15614,
105 texture_201106,
106 texture_12858,
107 texture_200836,
108 texture_15618,
109 texture_200773,
110 texture_200623,
111 texture_200549,
112 texture_200442,
113 };
114
115 static const guint8* texture_border_textures[] =
116 {
117 texture_12854,
118 texture_200542,
119 texture_15315,
120 texture_13039,
121 texture_201367,
122 texture_15311,
123 texture_200835,
124 texture_201122,
125 texture_114549,
126 texture_200650,
127 texture_15319,
128 texture_200622,
129 texture_200763,
130 texture_200285,
131 texture_200543,
132 };
133
134 static GArray *textures_timestamps = NULL;
135
136 /* compatable with gtk2 */
137 #if GTK_MAJOR_VERSION < 3
138 GtkWidget *
gtk_box_new(GtkOrientation orientation,gint spacing)139 gtk_box_new (GtkOrientation orientation,
140 gint spacing)
141 {
142 if (orientation == GTK_ORIENTATION_HORIZONTAL)
143 return gtk_hbox_new (FALSE, spacing);
144 else
145 return gtk_vbox_new (FALSE, spacing);
146 }
147 #endif
148
MAIN()149 MAIN ()
150
151 static void
152 query (void)
153 {
154 static const GimpParamDef args[] =
155 {
156 { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
157 { GIMP_PDB_IMAGE, "image", "Input image" },
158 { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
159 };
160
161 gimp_install_procedure (RIP_BORDER_PROC,
162 "Create an rip border effect",
163 "Rip border is one of the beautify serial plugin.",
164 "Hejian <hejian.he@gmail.com>",
165 "Hejian <hejian.he@gmail.com>",
166 "2012",
167 "_Rip Border...",
168 "RGB*, GRAY*",
169 GIMP_PLUGIN,
170 G_N_ELEMENTS (args), 0,
171 args, NULL);
172
173 gimp_install_procedure (TEXTURE_BORDER_PROC,
174 "Create an texture border effect",
175 "Texture border is one of the beautify serial plugin.",
176 "Hejian <hejian.he@gmail.com>",
177 "Hejian <hejian.he@gmail.com>",
178 "2012",
179 "_Texture Border...",
180 "RGB*, GRAY*",
181 GIMP_PLUGIN,
182 G_N_ELEMENTS (args), 0,
183 args, NULL);
184
185 gimp_plugin_menu_register (RIP_BORDER_PROC, "<Image>/Filters/Beautify/Border");
186 gimp_plugin_menu_register (TEXTURE_BORDER_PROC, "<Image>/Filters/Beautify/Border");
187 }
188
189 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)190 run (const gchar *name,
191 gint nparams,
192 const GimpParam *param,
193 gint *nreturn_vals,
194 GimpParam **return_vals)
195 {
196 static GimpParam values[2];
197 GimpDrawable *drawable;
198 GimpRunMode run_mode;
199 GimpPDBStatusType status = GIMP_PDB_SUCCESS;
200
201 run_mode = param[0].data.d_int32;
202
203 *nreturn_vals = 1;
204 *return_vals = values;
205
206 values[0].type = GIMP_PDB_STATUS;
207 values[0].data.d_status = status;
208
209 image_ID = param[1].data.d_image;
210 drawable = gimp_drawable_get (param[2].data.d_drawable);
211
212 width = gimp_image_width (image_ID);
213 height = gimp_image_height (image_ID);
214
215 if (strcmp (name, RIP_BORDER_PROC) == 0)
216 {
217 switch (run_mode)
218 {
219 case GIMP_RUN_INTERACTIVE:
220 if (! border_dialog ("Rip Border", RIP_BORDER_PROC, rip_border_textures, G_N_ELEMENTS (rip_border_textures), RIP_BORDER_TEXTURE_PATH))
221 return;
222 break;
223
224 case GIMP_RUN_NONINTERACTIVE:
225 break;
226
227 case GIMP_RUN_WITH_LAST_VALS:
228 break;
229
230 default:
231 break;
232 }
233 }
234 else if (strcmp (name, TEXTURE_BORDER_PROC) == 0)
235 {
236 switch (run_mode)
237 {
238 case GIMP_RUN_INTERACTIVE:
239 if (! border_dialog ("Texture Border", TEXTURE_BORDER_PROC, texture_border_textures, G_N_ELEMENTS (texture_border_textures), TEXTURE_BORDER_TEXTURE_PATH))
240 return;
241 break;
242
243 case GIMP_RUN_NONINTERACTIVE:
244 break;
245
246 case GIMP_RUN_WITH_LAST_VALS:
247 break;
248
249 default:
250 break;
251 }
252 }
253
254 if ((status == GIMP_PDB_SUCCESS) &&
255 (gimp_drawable_is_rgb(drawable->drawable_id) ||
256 gimp_drawable_is_gray(drawable->drawable_id)))
257 {
258 /* Run! */
259 gimp_image_undo_group_start (image_ID);
260 border (image_ID);
261 gimp_image_undo_group_end (image_ID);
262
263 /* If run mode is interactive, flush displays */
264 if (run_mode != GIMP_RUN_NONINTERACTIVE)
265 gimp_displays_flush ();
266
267 /* Store data */
268 /*if (run_mode == GIMP_RUN_INTERACTIVE)
269 gimp_set_data (PLUG_IN_PROC, &rbvals, sizeof (BorderValues));*/
270
271 }
272
273 gimp_drawable_detach (drawable);
274 }
275
276 static void
border(gint32 image_ID)277 border (gint32 image_ID)
278 {
279 GdkPixbuf *pixbuf = NULL;
280
281 if (bvals.texture)
282 pixbuf = gdk_pixbuf_new_from_inline (-1, bvals.texture, FALSE, NULL);
283 else if (bvals.custom_texture)
284 pixbuf = gdk_pixbuf_new_from_file (bvals.custom_texture, NULL);
285
286 if (pixbuf)
287 {
288 gint32 color_layer = gimp_layer_new (image_ID, "color",
289 width, height,
290 GIMP_RGBA_IMAGE,
291 bvals.opacity,
292 GIMP_NORMAL_MODE);
293 gimp_image_add_layer (image_ID, color_layer, -1);
294
295 gimp_context_set_foreground (&bvals.color);
296 gimp_edit_fill (color_layer, GIMP_FOREGROUND_FILL);
297
298 gint32 texture_mask = gimp_layer_create_mask (color_layer,
299 GIMP_ADD_WHITE_MASK);
300 gimp_layer_add_mask (color_layer, texture_mask);
301
302 gint32 texture = gimp_layer_new_from_pixbuf (image_ID, "texture", pixbuf, bvals.opacity, GIMP_NORMAL_MODE, 0, 0);
303 gimp_image_add_layer (image_ID, texture, -1);
304 gimp_layer_scale (texture, width, height, FALSE);
305 gimp_invert (texture);
306 gimp_edit_copy (texture);
307 gint32 floating_sel_ID = gimp_edit_paste (texture_mask, TRUE);
308 gimp_image_remove_layer (image_ID, texture);
309
310 gimp_floating_sel_anchor (floating_sel_ID);
311
312 gimp_image_merge_down(image_ID, color_layer, GIMP_CLIP_TO_BOTTOM_LAYER);
313 }
314 }
315
316 static void
preview_update(GtkWidget * preview)317 preview_update (GtkWidget *preview)
318 {
319 gint preview_size = PREVIEW_SIZE;
320 gint max_size = height;
321 if (height < width)
322 max_size = width;
323 if (preview_size > max_size)
324 preview_size = max_size;
325 GdkPixbuf *pixbuf = gimp_image_get_thumbnail (preview_image, preview_size, preview_size, GIMP_PIXBUF_SMALL_CHECKS);
326 gtk_image_set_from_pixbuf (GTK_IMAGE(preview), pixbuf);
327 }
328
329 static void
color_update(GtkWidget * preview)330 color_update (GtkWidget *preview)
331 {
332 gimp_context_set_foreground (&bvals.color);
333 gimp_edit_fill (color_layer, GIMP_FOREGROUND_FILL);
334
335 preview_update (preview);
336 }
337
338 static void
opacity_update(GtkRange * range,gpointer data)339 opacity_update (GtkRange *range, gpointer data) {
340 bvals.opacity = gtk_range_get_value (range);
341 gimp_layer_set_opacity (color_layer, bvals.opacity);
342 preview_update (preview);
343 }
344
345 static gboolean
border_dialog(const gchar * title,const gchar * help_id,const guint8 ** textures,guint n_textures,const gchar * texture_path)346 border_dialog (const gchar *title, const gchar *help_id, const guint8** textures, guint n_textures, const gchar *texture_path)
347 {
348 GtkWidget *dialog;
349 GtkWidget *main_hbox;
350 GtkWidget *left_vbox;
351 GtkWidget *middle_vbox;
352 GtkWidget *right_vbox;
353 GtkWidget *label;
354
355 gboolean run;
356
357 gimp_ui_init (PLUG_IN_BINARY, FALSE);
358
359 dialog = gimp_dialog_new (title, PLUG_IN_ROLE,
360 NULL, 0,
361 gimp_standard_help_func, help_id,
362
363 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
364 GTK_STOCK_OK, GTK_RESPONSE_OK,
365
366 NULL);
367
368 gimp_window_set_transient (GTK_WINDOW (dialog));
369
370 gtk_widget_show (dialog);
371
372 main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
373 gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
374 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
375 main_hbox, TRUE, TRUE, 0);
376 gtk_widget_show (main_hbox);
377
378 left_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
379 gtk_container_set_border_width (GTK_CONTAINER (left_vbox), 12);
380 gtk_box_pack_start (GTK_BOX (main_hbox), left_vbox, TRUE, TRUE, 0);
381 gtk_widget_show (left_vbox);
382
383 middle_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
384 gtk_container_set_border_width (GTK_CONTAINER (middle_vbox), 12);
385 gtk_box_pack_start (GTK_BOX (main_hbox), middle_vbox, TRUE, TRUE, 0);
386 gtk_widget_show (middle_vbox);
387
388 right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
389 gtk_container_set_border_width (GTK_CONTAINER (right_vbox), 12);
390 gtk_widget_set_size_request (right_vbox, 320, -1);
391 gtk_box_pack_start (GTK_BOX (main_hbox), right_vbox, TRUE, TRUE, 0);
392 gtk_widget_show (right_vbox);
393
394 /* color select */
395 label = gtk_label_new ("Border color");
396 gtk_box_pack_start (GTK_BOX (left_vbox), label, FALSE, FALSE, 0);
397 gtk_widget_show (label);
398
399 GtkWidget *button = gimp_color_button_new ("Border color", 40, 20, &bvals.color, GIMP_COLOR_AREA_FLAT);
400 gimp_color_button_set_update (GIMP_COLOR_BUTTON (button), TRUE);
401 gtk_box_pack_start (GTK_BOX (left_vbox), button, FALSE, FALSE, 0);
402 gtk_widget_show (button);
403
404 g_signal_connect (button, "color-changed",
405 G_CALLBACK (gimp_color_button_get_color),
406 &bvals.color);
407
408 /* opacity */
409 label = gtk_label_new ("Border opacity");
410 gtk_box_pack_start (GTK_BOX (left_vbox), label, FALSE, FALSE, 0);
411 gtk_widget_show (label);
412
413 GtkWidget *hscale = gtk_hscale_new_with_range (0, 100, 1);
414 gtk_range_set_value (GTK_RANGE (hscale), bvals.opacity);
415 gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_BOTTOM);
416 gtk_box_pack_start (GTK_BOX (left_vbox), hscale, FALSE, FALSE, 0);
417 gtk_widget_show (hscale);
418
419 g_signal_connect (hscale, "value-changed",
420 G_CALLBACK (opacity_update),
421 NULL);
422
423 /* preview */
424 label = gtk_label_new ("Preview");
425 gtk_box_pack_start (GTK_BOX (middle_vbox), label, FALSE, FALSE, 0);
426 gtk_widget_show (label);
427
428 preview_image = gimp_image_duplicate(image_ID);
429 color_layer = gimp_layer_new (preview_image, "color",
430 width, height,
431 GIMP_RGBA_IMAGE,
432 bvals.opacity,
433 GIMP_NORMAL_MODE);
434 gimp_image_add_layer (preview_image, color_layer, -1);
435
436 gimp_context_set_foreground (&bvals.color);
437 gimp_edit_fill (color_layer, GIMP_FOREGROUND_FILL);
438
439 texture_mask = gimp_layer_create_mask (color_layer,
440 GIMP_ADD_BLACK_MASK);
441 gimp_layer_add_mask (color_layer, texture_mask);
442
443 preview = gtk_image_new();
444 preview_update (preview);
445
446 gtk_box_pack_start (GTK_BOX (middle_vbox), preview, TRUE, TRUE, 0);
447 gtk_widget_show (preview);
448
449 g_signal_connect_swapped (button, "color-changed",
450 G_CALLBACK (color_update),
451 preview);
452
453 /* textures */
454 label = gtk_label_new ("Textures");
455 gtk_box_pack_start (GTK_BOX (right_vbox), label, FALSE, FALSE, 0);
456 gtk_widget_show (label);
457
458 GtkWidget *notebook = gtk_notebook_new ();
459 gtk_box_pack_start (GTK_BOX (right_vbox), notebook, FALSE, FALSE, 0);
460 gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
461 gtk_widget_show (notebook);
462
463 create_texture_page (GTK_NOTEBOOK (notebook), "Top", textures, n_textures);
464
465 if (create_custom_texture_pages (GTK_NOTEBOOK (notebook), texture_path))
466 {
467 textures_timestamps = g_array_new (FALSE, TRUE, sizeof (time_t));
468 g_array_set_size (textures_timestamps, gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)));
469 g_signal_connect (notebook, "switch-page", G_CALLBACK (textures_switch_page), (gpointer) texture_path);
470 }
471 else
472 {
473 label = gtk_label_new ("You can download more textures at https://github.com/hejiann/beautify/wiki/Textures-Download");
474 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
475 gtk_box_pack_start (GTK_BOX (right_vbox), label, FALSE, FALSE, 0);
476 gtk_widget_show (label);
477 }
478
479 run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
480
481 gtk_widget_destroy (dialog);
482
483 return run;
484 }
485
486 static void
create_texture_page(GtkNotebook * notebook,const gchar * category,const guint8 ** textures,guint n_textures)487 create_texture_page (GtkNotebook *notebook, const gchar* category, const guint8** textures, guint n_textures) {
488 GtkWidget *label = gtk_label_new (category);
489
490 GtkWidget *thispage = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
491 gtk_container_set_border_width (GTK_CONTAINER (thispage), 12);
492 gtk_widget_show (thispage);
493
494 /* table */
495 gint rows = 5;
496 gint cols = 3;
497 GtkWidget *table = gtk_table_new (rows, cols, FALSE);
498 gtk_table_set_col_spacings (GTK_TABLE (table), 6);
499 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
500 gtk_box_pack_start (GTK_BOX (thispage), table, FALSE, FALSE, 0);
501 gtk_widget_show (table);
502
503 gint row = 1;
504 gint col = 1;
505
506 gint i;
507 for (i = 0; i < n_textures; i++)
508 {
509 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_inline (-1, textures[i], FALSE, NULL);
510 pixbuf = gdk_pixbuf_scale_simple (pixbuf, THUMBNAIL_SIZE, THUMBNAIL_SIZE, GDK_INTERP_BILINEAR);
511 GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
512 GtkWidget *event_box = gtk_event_box_new ();
513 gtk_container_add (GTK_CONTAINER (event_box), image);
514 gtk_widget_show (image);
515 gtk_table_attach_defaults (GTK_TABLE (table), event_box, col - 1, col, row - 1, row);
516 gtk_widget_show (event_box);
517
518 col++;
519 if (col > cols)
520 {
521 row++;
522 col = 1;
523 }
524
525 g_signal_connect (event_box, "button_press_event", G_CALLBACK (texture_press), (gpointer)textures[i]);
526 }
527
528 gtk_notebook_append_page_menu (notebook, thispage, label, NULL);
529 }
530
531 static gboolean
create_custom_texture_pages(GtkNotebook * notebook,const gchar * texture_path)532 create_custom_texture_pages (GtkNotebook *notebook, const gchar *texture_path)
533 {
534 gboolean has_custom_texture = FALSE;
535
536 const gchar *gimp_dir = gimp_directory ();
537 const gchar *texture_dir = g_build_filename (gimp_dir, texture_path, NULL);
538 GDir *dir = g_dir_open (texture_dir, 0, NULL);
539 if (dir)
540 {
541 const gchar *dir_ent;
542 while (dir_ent = g_dir_read_name (dir))
543 {
544 if (is_hidden (dir_ent))
545 continue;
546
547 gchar *filename = g_build_filename (texture_dir, dir_ent, NULL);
548 if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
549 create_custom_texture_page (GTK_NOTEBOOK (notebook), dir_ent, filename);
550 has_custom_texture = TRUE;
551 }
552 }
553 }
554
555 return has_custom_texture;
556 }
557
558 static void
create_custom_texture_page(GtkNotebook * notebook,const gchar * category,const gchar * path)559 create_custom_texture_page (GtkNotebook *notebook, const gchar* category, const gchar* path) {
560 GtkWidget *label = gtk_label_new (category);
561
562 GtkWidget *thispage = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
563 gtk_container_set_border_width (GTK_CONTAINER (thispage), 12);
564 gtk_widget_show (thispage);
565
566 gtk_notebook_append_page_menu (notebook, thispage, label, NULL);
567 }
568
569 static void
textures_switch_page(GtkNotebook * notebook,GtkWidget * page,guint page_num,const gchar * texture_path)570 textures_switch_page (GtkNotebook *notebook, GtkWidget *page, guint page_num, const gchar *texture_path)
571 {
572 if (page_num == 0 || g_array_index (textures_timestamps, time_t, page_num) > 0)
573 return;
574
575 // fix gtk2
576 page = gtk_notebook_get_nth_page (notebook, page_num);
577
578 gtk_container_set_border_width (GTK_CONTAINER (page), 0);
579 gtk_widget_set_size_request (page, -1, 480);
580
581 const gchar *category = gtk_notebook_get_tab_label_text(notebook, page);
582
583 /* scrolled window */
584 GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
585 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
586 gtk_box_pack_start (GTK_BOX (page), scrolled_window, TRUE, TRUE, 0);
587 gtk_widget_show (scrolled_window);
588
589 /* table */
590 gint rows = 5;
591 gint cols = 3;
592 GtkWidget *table = gtk_table_new (rows, cols, FALSE);
593 gtk_table_set_col_spacings (GTK_TABLE (table), 6);
594 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
595 gtk_container_set_border_width (GTK_CONTAINER (table), 10);
596 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
597 gtk_widget_show (table);
598
599 gint row = 1;
600 gint col = 1;
601
602 const gchar *gimp_dir = gimp_directory ();
603 const gchar *texture_dir = g_build_filename (gimp_dir, texture_path, NULL);
604 const gchar *path = g_build_filename (texture_dir, category, NULL);
605
606 GDir *dir = g_dir_open (path, 0, NULL);
607 if (dir)
608 {
609 const gchar *dir_ent;
610 while (dir_ent = g_dir_read_name (dir))
611 {
612 if (is_hidden (dir_ent))
613 continue;
614
615 gchar *filename = g_build_filename (path, dir_ent, NULL);
616 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
617 pixbuf = gdk_pixbuf_scale_simple (pixbuf, THUMBNAIL_SIZE, THUMBNAIL_SIZE, GDK_INTERP_BILINEAR);
618 GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
619 GtkWidget *event_box = gtk_event_box_new ();
620 gtk_container_add (GTK_CONTAINER (event_box), image);
621 gtk_widget_show (image);
622 gtk_table_attach_defaults (GTK_TABLE (table), event_box, col - 1, col, row - 1, row);
623 gtk_widget_show (event_box);
624
625 col++;
626 if (col > cols)
627 {
628 row++;
629 col = 1;
630 }
631
632 g_signal_connect (event_box, "button_press_event", G_CALLBACK (custom_texture_press), filename);
633 }
634 }
635
636 g_array_index (textures_timestamps, time_t, page_num) = time (NULL);
637 }
638
639 static gboolean
texture_press(GtkWidget * event_box,GdkEventButton * event,const guint8 * texture)640 texture_press (GtkWidget *event_box, GdkEventButton *event, const guint8* texture)
641 {
642 bvals.texture = texture;
643 bvals.custom_texture = NULL;
644
645 do_texture_press ();
646 }
647
648 static gboolean
custom_texture_press(GtkWidget * event_box,GdkEventButton * event,const gchar * texture)649 custom_texture_press (GtkWidget *event_box, GdkEventButton *event, const gchar *texture)
650 {
651 bvals.texture = NULL;
652 bvals.custom_texture = texture;
653
654 do_texture_press ();
655 }
656
657 static void
do_texture_press()658 do_texture_press ()
659 {
660 GdkPixbuf *pixbuf;
661 if (bvals.texture)
662 pixbuf = gdk_pixbuf_new_from_inline (-1, bvals.texture, FALSE, NULL);
663 else
664 pixbuf = gdk_pixbuf_new_from_file (bvals.custom_texture, NULL);
665
666 gint32 texture_layer = gimp_layer_new_from_pixbuf (preview_image,
667 "texture",
668 pixbuf,
669 bvals.opacity,
670 GIMP_NORMAL_MODE, 0, 0);
671 gimp_image_add_layer (preview_image, texture_layer, -1);
672 gimp_layer_scale (texture_layer, width, height, FALSE);
673 gimp_invert (texture_layer);
674 gimp_edit_copy (texture_layer);
675 gimp_edit_paste (texture_mask, TRUE);
676 gimp_image_remove_layer (preview_image, texture_layer);
677
678 preview_update (preview);
679 }
680
681