1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
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 <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <string.h>
21 
22 #include <gtk/gtk.h>
23 
24 #include <libgimp/gimp.h>
25 #include <libgimp/gimpui.h>
26 
27 #include "gimpressionist.h"
28 #include "ppmtool.h"
29 #include "infile.h"
30 #include "preview.h"
31 
32 #include "libgimp/stdplugins-intl.h"
33 
34 
35 static GtkWidget *preview       = NULL;
36 static GtkWidget *previewbutton = NULL;
37 
38 void
preview_set_button_label(const gchar * text)39 preview_set_button_label (const gchar *text)
40 {
41   g_object_set (previewbutton,
42                 "label",         text,
43                 "use-underline", TRUE,
44                 NULL);
45 }
46 
47 static void
drawalpha(ppm_t * p,ppm_t * a)48 drawalpha (ppm_t *p, ppm_t *a)
49 {
50   int    x, y, g;
51   double v;
52   int    gridsize = 16;
53   int     rowstride = p->width * 3;
54 
55   for (y = 0; y < p->height; y++)
56     {
57       for (x = 0; x < p->width; x++)
58         {
59           int k = y * rowstride + x * 3;
60 
61           if (!a->col[k])
62             continue;
63 
64           v = 1.0 - a->col[k] / 255.0;
65           g = ((x / gridsize + y / gridsize) % 2) * 60 + 100;
66           p->col[k+0] *= v;
67           p->col[k+1] *= v;
68           p->col[k+2] *= v;
69           v = 1.0 - v;
70           p->col[k+0] += g*v;
71           p->col[k+1] += g*v;
72           p->col[k+2] += g*v;
73         }
74     }
75 }
76 
77 static ppm_t preview_ppm      = {0, 0, NULL};
78 static ppm_t alpha_ppm        = {0, 0, NULL};
79 static ppm_t backup_ppm       = {0, 0, NULL};
80 static ppm_t alpha_backup_ppm = {0, 0, NULL};
81 
82 void
preview_free_resources(void)83 preview_free_resources (void)
84 {
85   ppm_kill (&preview_ppm);
86   ppm_kill (&alpha_ppm);
87   ppm_kill (&backup_ppm);
88   ppm_kill (&alpha_backup_ppm);
89 }
90 
91 void
updatepreview(GtkWidget * wg,gpointer d)92 updatepreview (GtkWidget *wg, gpointer d)
93 {
94   if (!PPM_IS_INITED (&backup_ppm))
95     {
96       infile_copy_to_ppm (&backup_ppm);
97       if ((backup_ppm.width != PREVIEWSIZE) ||
98           (backup_ppm.height != PREVIEWSIZE))
99         resize_fast (&backup_ppm, PREVIEWSIZE, PREVIEWSIZE);
100       if (img_has_alpha)
101         {
102           infile_copy_alpha_to_ppm (&alpha_backup_ppm);
103           if ((alpha_backup_ppm.width != PREVIEWSIZE) ||
104               (alpha_backup_ppm.height != PREVIEWSIZE))
105             resize_fast (&alpha_backup_ppm, PREVIEWSIZE, PREVIEWSIZE);
106         }
107     }
108 
109   if (!PPM_IS_INITED (&preview_ppm))
110     {
111       ppm_copy (&backup_ppm, &preview_ppm);
112 
113       if (img_has_alpha)
114         ppm_copy (&alpha_backup_ppm, &alpha_ppm);
115     }
116 
117   if (d)
118     {
119       store_values ();
120 
121       if (GPOINTER_TO_INT (d) != 2)
122         repaint (&preview_ppm, &alpha_ppm);
123     }
124 
125   if (img_has_alpha)
126     drawalpha (&preview_ppm, &alpha_ppm);
127 
128   gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
129                           0, 0, PREVIEWSIZE, PREVIEWSIZE,
130                           GIMP_RGB_IMAGE,
131                           preview_ppm.col,
132                           PREVIEWSIZE * 3);
133 
134   ppm_kill (&preview_ppm);
135   if (img_has_alpha)
136     ppm_kill (&alpha_ppm);
137 }
138 
139 static void
preview_size_allocate(GtkWidget * preview)140 preview_size_allocate (GtkWidget *preview)
141 {
142   updatepreview (preview, GINT_TO_POINTER (0));
143 }
144 
145 GtkWidget *
create_preview(void)146 create_preview (void)
147 {
148   GtkWidget *hbox;
149   GtkWidget *vbox;
150   GtkWidget *frame;
151   GtkWidget *button;
152 
153   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
154 
155   frame = gtk_frame_new (NULL);
156   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
157   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 5);
158   gtk_widget_show (frame);
159 
160   preview = gimp_preview_area_new ();
161   gtk_widget_set_size_request (preview, PREVIEWSIZE, PREVIEWSIZE);
162 
163   gtk_container_add (GTK_CONTAINER (frame), preview);
164   gtk_widget_show (preview);
165   /* This is so the preview will be displayed when the dialog is invoked. */
166   g_signal_connect (preview, "size-allocate",
167                     G_CALLBACK (preview_size_allocate), NULL);
168 
169   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
170   gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
171   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
172   gtk_widget_show (hbox);
173 
174   previewbutton = button = gtk_button_new_with_mnemonic (_("_Update"));
175   g_signal_connect (button, "clicked",
176                     G_CALLBACK (updatepreview), (gpointer) 1);
177   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
178   gtk_widget_show (button);
179   gimp_help_set_help_data (button,
180                            _("Refresh the Preview window"), NULL);
181 
182   button = gtk_button_new_with_mnemonic (_("_Reset"));
183   g_signal_connect (button, "clicked",
184                     G_CALLBACK (updatepreview), (gpointer) 2);
185   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
186   gtk_widget_show (button);
187   gimp_help_set_help_data (button,
188                            _("Revert to the original image"), NULL);
189 
190   return vbox;
191 }
192