1 /* vim:expandtab:ts=2 sw=2:
2 */
3 /*  Grafx2 - The Ultimate 256-color bitmap paint program
4 
5 	Copyright owned by various GrafX2 authors, see COPYRIGHT.txt for details.
6 
7     Grafx2 is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; version 2
10     of the License.
11 
12     Grafx2 is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with Grafx2; if not, see <http://www.gnu.org/licenses/>
19 */
20 #include <stdlib.h>
21 #include <string.h>
22 #include "const.h"
23 #include "struct.h"
24 #include "global.h"
25 #include "graph.h"
26 #include "engine.h"
27 #include "windows.h"
28 #include "special.h"
29 #include "pages.h"
30 #include "misc.h"
31 #include "osdep.h"
32 #include "buttons.h"
33 
34 
35 
36 
37 
38 //---------------------- Modifier le pinceau spécial -------------------------
39 
Set_paintbrush_size(int width,int height)40 void Set_paintbrush_size(int width, int height)
41 {
42   int x_pos,y_pos;
43   int x,y;
44   int radius2;
45 
46   if (width<1) width=1;
47   if (height<1) height=1;
48   if (width>MAX_PAINTBRUSH_SIZE) width=MAX_PAINTBRUSH_SIZE;
49   if (height>MAX_PAINTBRUSH_SIZE) height=MAX_PAINTBRUSH_SIZE;
50   Paintbrush_width=width;
51   Paintbrush_height=height;
52   Paintbrush_offset_X=Paintbrush_width>>1;
53   Paintbrush_offset_Y=Paintbrush_height>>1;
54   switch (Paintbrush_shape)
55   {
56     case PAINTBRUSH_SHAPE_ROUND :
57       radius2=Circle_squared_diameter(Paintbrush_width);
58 
59       for (y_pos=0, y=1-Paintbrush_height; y_pos<Paintbrush_height; y_pos++,y+=2)
60         for (x_pos=0, x=1-Paintbrush_width; x_pos<Paintbrush_width; x_pos++,x+=2)
61         {
62           Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=( ((x*x)+(y*y)) <= radius2 );
63         }
64       break;
65     case PAINTBRUSH_SHAPE_SQUARE :
66       for (x_pos=0,y_pos=0; x_pos<Paintbrush_height; x_pos++,y_pos+=MAX_PAINTBRUSH_SIZE)
67         memset(Paintbrush_sprite+y_pos,1,Paintbrush_width);
68       break;
69     case PAINTBRUSH_SHAPE_SIEVE_ROUND :
70     {
71       int reminder=0;
72       if (Paintbrush_width==1)
73         reminder = 1;
74 
75       radius2=Circle_squared_diameter(Paintbrush_width);
76 
77       for (y_pos=0, y=1-Paintbrush_height; y_pos<Paintbrush_height; y_pos++,y+=2)
78         for (x_pos=0, x=1-Paintbrush_width; x_pos<Paintbrush_width; x_pos++,x+=2)
79         {
80           Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=( ((x_pos+y_pos+reminder)&1) && (((x*x)+(y*y)) < radius2));
81         }
82       break;
83     }
84     case PAINTBRUSH_SHAPE_SIEVE_SQUARE:
85       for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
86         for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
87           Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=!((x_pos+y_pos)&1);
88       break;
89     case PAINTBRUSH_SHAPE_PLUS:
90       x=Paintbrush_width>>1;
91       for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
92         for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
93           Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=((x_pos==x) || (y_pos==x));
94       break;
95     case PAINTBRUSH_SHAPE_SLASH:
96       x=Paintbrush_width>>1;
97       for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
98         for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
99           Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=(x_pos==(Paintbrush_width-(y_pos+1)));
100       break;
101     case PAINTBRUSH_SHAPE_ANTISLASH:
102       x=Paintbrush_width>>1;
103       for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
104         for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
105           Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=(x_pos==y_pos);
106       break;
107     case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
108       memset(Paintbrush_sprite,1,Paintbrush_width);
109       break;
110     case PAINTBRUSH_SHAPE_VERTICAL_BAR:
111       for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
112         Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)]=1;
113       break;
114     case PAINTBRUSH_SHAPE_CROSS:
115       x=Paintbrush_width>>1;
116       for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
117         for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
118           Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=( (x_pos==y_pos) || (x_pos==(Paintbrush_height-(y_pos+1))) );
119       break;
120     case PAINTBRUSH_SHAPE_DIAMOND:
121       x=Paintbrush_width>>1;
122       for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
123         for (x_pos=0; x_pos<Paintbrush_width; x_pos++)
124         {
125           if (x_pos<=x)
126             y=x-x_pos;
127           else
128             y=x_pos-x;
129           if (y_pos<=x)
130             y+=x-y_pos;
131           else
132             y+=y_pos-x;
133           Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=(y<=x);
134         }
135       break;
136     case PAINTBRUSH_SHAPE_RANDOM:
137       // Init with blank
138       for (y_pos=0; y_pos<Paintbrush_height; y_pos++)
139         memset(Paintbrush_sprite+y_pos*MAX_PAINTBRUSH_SIZE,0,Paintbrush_width);
140 
141       radius2=Circle_squared_diameter(Paintbrush_width);
142 
143       for (y_pos=0, y=1-Paintbrush_height; y_pos<Paintbrush_height; y_pos++,y+=2)
144         for (x_pos=0, x=1-Paintbrush_width; x_pos<Paintbrush_width; x_pos++,x+=2)
145         {
146           if ((x*x)+(y*y) < radius2 && !(rand()&7))
147           {
148               Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos]=1;
149               // This prevents having a pixels that touch each other.
150               if (x_pos>0)
151                 Paintbrush_sprite[(y_pos*MAX_PAINTBRUSH_SIZE)+x_pos-1]=0;
152               if (y_pos>0)
153                 Paintbrush_sprite[((y_pos-1)*MAX_PAINTBRUSH_SIZE)+x_pos]=0;
154           }
155         }
156   }
157 }
158 
Smaller_paintbrush(void)159 void Smaller_paintbrush(void)
160 {
161   if ( (Paintbrush_shape<PAINTBRUSH_SHAPE_MISC)
162     && ( (Paintbrush_width>1)
163       || (Paintbrush_height>1) ) )
164   {
165     Hide_cursor();
166     switch (Paintbrush_shape)
167     {
168       case PAINTBRUSH_SHAPE_CROSS:
169       case PAINTBRUSH_SHAPE_PLUS:
170       case PAINTBRUSH_SHAPE_DIAMOND:
171         if (Paintbrush_width&1)
172           Set_paintbrush_size(Paintbrush_width-2,Paintbrush_height-2);
173         else
174           Set_paintbrush_size(Paintbrush_width-1,Paintbrush_height-1);
175         break;
176       case PAINTBRUSH_SHAPE_SQUARE:
177       case PAINTBRUSH_SHAPE_SLASH:
178       case PAINTBRUSH_SHAPE_ANTISLASH:
179       case PAINTBRUSH_SHAPE_SIEVE_SQUARE:
180       case PAINTBRUSH_SHAPE_ROUND:
181       case PAINTBRUSH_SHAPE_SIEVE_ROUND:
182       case PAINTBRUSH_SHAPE_RANDOM:
183         Set_paintbrush_size(Paintbrush_width-1,Paintbrush_height-1);
184         break;
185       case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
186         Set_paintbrush_size(Paintbrush_width-1,1);
187         break;
188       case PAINTBRUSH_SHAPE_VERTICAL_BAR:
189         Set_paintbrush_size(1,Paintbrush_height-1);
190     }
191     Display_paintbrush_in_menu();
192     Display_cursor();
193   }
194 }
195 
Bigger_paintbrush(void)196 void Bigger_paintbrush(void)
197 {
198   if ( (Paintbrush_shape<PAINTBRUSH_SHAPE_MISC)
199     && ( (Paintbrush_width<MAX_PAINTBRUSH_SIZE)
200       || (Paintbrush_height<MAX_PAINTBRUSH_SIZE) ) )
201   {
202     Hide_cursor();
203     switch (Paintbrush_shape)
204     {
205       case PAINTBRUSH_SHAPE_CROSS:
206       case PAINTBRUSH_SHAPE_PLUS:
207       case PAINTBRUSH_SHAPE_DIAMOND:
208         if (Paintbrush_width&1)
209           Set_paintbrush_size(Paintbrush_width+2,Paintbrush_height+2);
210         else
211           Set_paintbrush_size(Paintbrush_width+1,Paintbrush_height+1);
212         break;
213       case PAINTBRUSH_SHAPE_SQUARE:
214       case PAINTBRUSH_SHAPE_SLASH:
215       case PAINTBRUSH_SHAPE_ANTISLASH:
216       case PAINTBRUSH_SHAPE_SIEVE_SQUARE:
217       case PAINTBRUSH_SHAPE_ROUND:
218       case PAINTBRUSH_SHAPE_SIEVE_ROUND:
219       case PAINTBRUSH_SHAPE_RANDOM:
220         Set_paintbrush_size(Paintbrush_width+1,Paintbrush_height+1);
221         break;
222       case PAINTBRUSH_SHAPE_HORIZONTAL_BAR:
223         Set_paintbrush_size(Paintbrush_width+1,1);
224         break;
225       case PAINTBRUSH_SHAPE_VERTICAL_BAR:
226         Set_paintbrush_size(1,Paintbrush_height+1);
227     }
228     Display_paintbrush_in_menu();
229     Display_cursor();
230   }
231 }
232 
233 
234 //--------------------- Increase the ForeColor -----------------------
Special_next_forecolor(void)235 void Special_next_forecolor(void)
236 {
237   Hide_cursor();
238   Set_fore_color(Fore_color+1);
239   Display_cursor();
240 }
241 
242 //--------------------- Decrease the ForeColor -----------------------
Special_previous_forecolor(void)243 void Special_previous_forecolor(void)
244 {
245   Hide_cursor();
246   Set_fore_color(Fore_color-1);
247   Display_cursor();
248 }
249 
250 //--------------------- Increase the BackColor -----------------------
Special_next_backcolor(void)251 void Special_next_backcolor(void)
252 {
253   Hide_cursor();
254   Set_back_color(Back_color+1);
255   Display_cursor();
256 }
257 
258 //--------------------- Decrease the BackColor -----------------------
Special_previous_backcolor(void)259 void Special_previous_backcolor(void)
260 {
261   Hide_cursor();
262   Set_back_color(Back_color-1);
263   Display_cursor();
264 }
265 
266 /// Picks the next foreground color, according to current shade table
Special_next_user_forecolor(void)267 void Special_next_user_forecolor(void)
268 {
269   Hide_cursor();
270   Set_fore_color(Shade_table_left[Fore_color]);
271   Display_cursor();
272 }
273 
274 /// Picks the previous foreground color, according to current shade table
Special_previous_user_forecolor(void)275 void Special_previous_user_forecolor(void)
276 {
277   Hide_cursor();
278   Set_fore_color(Shade_table_right[Fore_color]);
279   Display_cursor();
280 }
281 
282 /// Picks the next background color, according to current shade table
Special_next_user_backcolor(void)283 void Special_next_user_backcolor(void)
284 {
285   Hide_cursor();
286   Set_back_color(Shade_table_left[Back_color]);
287   Display_cursor();
288 }
289 
290 /// Picks the previous background color, according to current shade table
Special_previous_user_backcolor(void)291 void Special_previous_user_backcolor(void)
292 {
293   Hide_cursor();
294   Set_back_color(Shade_table_right[Back_color]);
295   Display_cursor();
296 }
297 
298 // ------------------- Scroller l'écran (pas en mode loupe) ------------------
Scroll_screen(short delta_x,short delta_y)299 void Scroll_screen(short delta_x,short delta_y)
300 {
301   short temp_x_offset;
302   short temp_y_offset;
303 
304   temp_x_offset=Main.offset_X+delta_x;
305   temp_y_offset=Main.offset_Y+delta_y;
306 
307   if (temp_x_offset+Screen_width>Main.image_width)
308     temp_x_offset=Main.image_width-Screen_width;
309   if (temp_y_offset+Menu_Y>Main.image_height)
310     temp_y_offset=Main.image_height-Menu_Y;
311   if (temp_x_offset<0)
312     temp_x_offset=0;
313   if (temp_y_offset<0)
314     temp_y_offset=0;
315 
316   if ( (Main.offset_X!=temp_x_offset) ||
317        (Main.offset_Y!=temp_y_offset) )
318   {
319     Hide_cursor();
320     Main.offset_X=temp_x_offset;
321     Main.offset_Y=temp_y_offset;
322 
323     Compute_limits();
324     Compute_paintbrush_coordinates();
325 
326     Display_all_screen();  // <=> Display_screen + Display_image_limits
327     Display_cursor();
328   }
329 }
330 
331 
332 // ---------------------- Scroller la fenêtre de la loupe --------------------
Scroll_magnifier(short delta_x,short delta_y)333 void Scroll_magnifier(short delta_x,short delta_y)
334 {
335   short temp_x_offset;
336   short temp_y_offset;
337 
338   temp_x_offset=Main.magnifier_offset_X+delta_x;
339   temp_y_offset=Main.magnifier_offset_Y+delta_y;
340 
341   Clip_magnifier_offsets(&temp_x_offset, &temp_y_offset);
342 
343   if ( (Main.magnifier_offset_X!=temp_x_offset) ||
344        (Main.magnifier_offset_Y!=temp_y_offset) )
345   {
346     Hide_cursor();
347     Main.magnifier_offset_X=temp_x_offset;
348     Main.magnifier_offset_Y=temp_y_offset;
349 
350     Position_screen_according_to_zoom();
351 
352     Compute_limits();
353     Compute_paintbrush_coordinates();
354 
355     Display_all_screen();
356     Display_cursor();
357   }
358 }
359 
360 
361 // -------------- Changer le Zoom (grâce aux touches [+] et [-]) -------------
Zoom(short delta)362 void Zoom(short delta)
363 {
364   short index;
365   for (index=0; ZOOM_FACTOR[index]!=Main.magnifier_factor; index++);
366   index+=delta;
367 
368   if ( (index>=0) && (index<NB_ZOOM_FACTORS) )
369   {
370     Hide_cursor();
371     Change_magnifier_factor(index,1);
372     if (Main.magnifier_mode)
373       Display_all_screen();
374     Display_cursor();
375   }
376 }
377 
378 /**
379   Set zoom value. Negative value means no zoom.
380 */
Zoom_set(int index)381 void Zoom_set(int index)
382 {
383   Hide_cursor();
384   if (index<0)
385   {
386     /* Zoom 1:1 */
387     if (Main.magnifier_mode)
388       Unselect_button(BUTTON_MAGNIFIER);
389   }
390   else
391   {
392     Change_magnifier_factor(index,1);
393     if (!Main.magnifier_mode)
394       Select_button(BUTTON_MAGNIFIER,1);
395     Display_all_screen();
396   }
397   Display_cursor();
398 }
399 
Transparency_set(byte amount)400 void Transparency_set(byte amount)
401 {
402   const int doubleclick_delay = Config.Double_key_speed;
403   static long time_click = 0;
404   long time_previous;
405 
406   if (!Colorize_mode)
407   {
408     // Activate mode
409     switch(Colorize_current_mode)
410     {
411       case 0 :
412         Effect_function=Effect_interpolated_colorize;
413         break;
414       case 1 :
415         Effect_function=Effect_additive_colorize;
416         break;
417       case 2 :
418         Effect_function=Effect_substractive_colorize;
419         break;
420       case 3 :
421         Effect_function=Effect_alpha_colorize;
422     }
423     Shade_mode=0;
424     Quick_shade_mode=0;
425     Smooth_mode=0;
426     Tiling_mode=0;
427 
428     Colorize_mode=1;
429   }
430 
431   time_previous = time_click;
432   time_click = GFX2_GetTicks();
433 
434   // Check if it's a quick re-press
435   if (time_click - time_previous < doubleclick_delay)
436   {
437     // Use the typed amount as units, keep the tens.
438     Colorize_opacity = ((Colorize_opacity%100) /10 *10) + amount;
439     if (Colorize_opacity == 0)
440       Colorize_opacity = 100;
441   }
442   else
443   {
444     // Use 10% units: "1"=10%, ... "0"=100%
445     if (amount == 0)
446       Colorize_opacity = 100;
447     else
448       Colorize_opacity = amount*10;
449   }
450   Compute_colorize_table();
451 }
452 
453 
454