1 /*
2  *     gtkatlantic - the gtk+ monopd client, enjoy network monopoly games
3  *
4  *
5  *  Copyright © 2002-2015 Sylvain Rochet
6  *
7  *  gtkatlantic is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program 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 this program; see the file COPYING. If not, see
19  *  <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <glib.h>
28 #include <string.h>
29 
30 #include "eng_main.h"
31 
32 /* Global handler */
33 _eng *eng;
34 
35 /* ---- initialise engine */
eng_init()36 void eng_init()  {
37 	guint32 alpha, bright;
38 
39 #if ENG_DEBUG
40 	fprintf(stdout, "Initializing engine...\n");
41 #endif
42 
43 	eng = g_malloc0( sizeof(_eng) );
44 	eng->obj = eng_list_new();
45 	eng->frame = eng_list_new();
46 
47 	/* init alpha tables */
48 	eng->alpha = g_malloc( sizeof(eng_alpha) );
49 	for(alpha = 0 ; alpha < 256 ; alpha++) {
50 		for(bright = 0 ; bright < 256 ; bright++)  {
51 			guint8 v = (bright * (alpha+1)) >> 8;  /* alpha+1: 255*256 >> 8 = 255 */
52 			eng->alpha->fg[alpha][bright] = v;
53 			eng->alpha->bg[alpha][bright] = bright - v;
54 		}
55 	}
56 }
57 
58 /* ---- close engine */
eng_close()59 void eng_close()  {
60 
61 	if(!eng) return;
62 
63 	eng_frame_destroy_all();
64 	eng_list_destroy(eng->obj);
65 	eng_list_destroy(eng->frame);
66 	if(eng->alpha) g_free(eng->alpha);
67 	g_free(eng);
68 
69 #if ENG_DEBUG
70 	fprintf(stdout, "Closing engine...\n");
71 #endif
72 }
73 
74 /* ---- create a new frame */
eng_frame_create()75 eng_frame* eng_frame_create()  {
76 
77 	eng_frame *f;
78 
79 	f = g_malloc0( sizeof(eng_frame) );
80 	eng_frame_reset(f);
81 	f->compute = 1;
82 	f->obj = eng_list_new();
83 	f->zone_upd = eng_list_new();
84 	f->entry = eng_list_append(eng->frame, f);
85 
86 #if ENG_DEBUG
87 	fprintf(stdout, "New Frame\n");
88 #endif
89 
90 	return(f);
91 }
92 
93 
94 /* ---- destroy a frame
95  *
96  *    close also all pics
97  */
eng_frame_destroy(eng_frame * f)98 void eng_frame_destroy(eng_frame *f)  {
99 
100 	eng_list_e *lst;
101 
102 	if(!f)  return;
103 	eng_list_remove_fast(f->entry);
104 	while( (lst = eng_list_first(f->obj)))
105 		eng_pic_free(lst->data);
106 	eng_frame_reset(f);
107 	eng_list_destroy(f->obj);
108 	eng_list_destroy(f->zone_upd);
109 	g_free(f);
110 
111 #if ENG_DEBUG
112 	fprintf(stdout, "Destroy frame\n");
113 #endif
114 }
115 
116 
117 /* ---- destroy all frames */
eng_frame_destroy_all()118 void eng_frame_destroy_all()  {
119 
120 	eng_list_e *lst;
121 
122 	while( (lst = eng_list_first(eng->frame)))
123 		eng_frame_destroy(lst->data);
124 }
125 
126 
127 /* ---- set to 0 all elements in struct */
eng_frame_reset(eng_frame * f)128 void eng_frame_reset(eng_frame *f)  {
129 
130 	if(!f)  return;
131 
132 	f->compute = 0;
133 	f->width = 0;
134 	f->height = 0;
135 	if(f->memalloc > 0)
136 		g_free(f->bufout);
137 
138 	f->memalloc = 0;
139 
140 	eng_frame_free_zoneupd(f);
141 
142 	f->num_zone = 0;
143 	f->x_min = 0;
144 	f->y_min = 0;
145 	f->x_max = 0;
146 	f->y_max = 0;
147 }
148 
149 
150 /* ---- free all zone update */
eng_frame_free_zoneupd(eng_frame * f)151 void eng_frame_free_zoneupd(eng_frame *f)  {
152 
153 	eng_list_e *lst;
154 
155 	if(!f)  return;
156 	if(!f->zone_upd)  return;
157 
158 	for(lst = eng_list_first(f->zone_upd) ; lst ; lst=lst->next)
159 		g_free(lst->data);
160 	eng_list_clean(f->zone_upd);
161 }
162 
163 
164 /* ---- compute yes this frame (for eng_create_frame_all() ) */
eng_frame_set_compute(eng_frame * f)165 void eng_frame_set_compute(eng_frame *f) {
166 
167 	if(!f)  return;
168 
169 	f->compute = 1;
170 }
171 
172 
173 /* ---- compute no this frame (for eng_create_frame_all() ) */
eng_frame_unset_compute(eng_frame * f)174 void eng_frame_unset_compute(eng_frame *f)  {
175 
176 	if(!f)  return;
177 
178 	f->compute = 0;
179 }
180 
181 
182 /* ---- clean this frame                              *
183  *                                                    *
184  *  In the same concept of minimizing memory usage,   *
185  *  with this function you can clean all memory       *
186  *  used for out buffer.                              *
187  *                                                    *
188  *  Don't use between frame often drawed,             *
189  *  because engine do remake all frame, and not       *
190  *  just update this, finally engine can become       *
191  *  extremely slow.                                   *
192  *                                                    *
193  *  This is not dependant with minimizing memory mode *
194  *                                                    */
eng_frame_clean(eng_frame * f)195 void eng_frame_clean(eng_frame *f)  {
196 
197 	if(!f)  return;
198 
199 	if(f->memalloc > 0)
200 		g_free(f->bufout);
201 
202 	f->memalloc = 0;
203 
204 	eng_frame_free_zoneupd(f);
205 /*
206 	for(i = 1 ; i <= frame[frame_id]->lastpic ; i++ )  {
207 
208 		if(engine->active_frame[i])
209 			frame[frame_id]->obj[i]->change = 1;
210 	}
211 */
212 }
213 
214 
215 /* ---- set HEIGHT of a frame */
eng_frame_set_height(eng_frame * f,guint16 height)216 void eng_frame_set_height(eng_frame *f, guint16 height)  {
217 
218 	if(!f)  return;
219 
220 	f->height = height;
221 }
222 
223 
224 /* ---- set WIDTH of a frame */
eng_frame_set_width(eng_frame * f,guint16 width)225 void eng_frame_set_width(eng_frame *f, guint16 width)  {
226 
227 	if(!f)  return;
228 
229 	f->width = width;
230 }
231 
232 /* ---- put in terminal all arguments of a frame */
eng_frame_showarg(eng_frame * f)233 void eng_frame_showarg(eng_frame *f)  {
234 
235 	if(!f)  return;
236 
237 	fprintf(stdout, "====== FRAME ======\n");
238 	fprintf(stdout, "  compute      -> %d\n", f->compute);
239 	fprintf(stdout, "  width        -> %d\n", f->width);
240 	fprintf(stdout, "  height       -> %d\n", f->height);
241 	fprintf(stdout, "  ------\n");
242 	fprintf(stdout, "  memalloc     -> %d bytes\n", f->memalloc);
243 	fprintf(stdout, "  num_zone     -> %d\n", f->num_zone);
244 	fprintf(stdout, "====================\n");
245 }
246 
247 
248 /* ---- create a new pic */
eng_pic_create(eng_frame * f)249 eng_obj* eng_pic_create(eng_frame *f)  {
250 
251 	eng_obj *o;
252 
253 	o = g_malloc0( sizeof(eng_obj) );
254 	eng_pic_reset(o);
255 	o->show = 1;
256 	o->frame = f;
257 
258 	o->entry_main = eng_list_append(eng->obj, o);
259 	o->entry = eng_list_append(f->obj, o);
260 
261 #if ENG_DEBUG
262 	fprintf(stdout, "New Pic\n");
263 #endif
264 
265 	return(o);
266 }
267 
268 
269 /* ---- sent a call to destroy pic */
eng_pic_destroy(eng_obj * o)270 void eng_pic_destroy(eng_obj *o)  {
271 
272 	if(!o)  return;
273 
274 	o->destroy = 1;
275 	o->change = 1;
276 }
277 
278 
279 /* ---- destroy pic */
eng_pic_free(eng_obj * o)280 void eng_pic_free(eng_obj *o)  {
281 
282 	if(!o)  return;
283 
284 	eng_list_remove_fast(o->entry);
285 	eng_list_remove_fast(o->entry_main);
286 
287 	eng_pic_reset(o);
288 	g_free(o);
289 	o = NULL;
290 
291 #if ENG_DEBUG
292 	fprintf(stdout, "Destroy pic\n");
293 #endif
294 }
295 
296 
297 /* ---- set to 0 all elements in struct */
eng_pic_reset(eng_obj * o)298 void eng_pic_reset(eng_obj *o)  {
299 
300 	if(!o)  return;
301 
302 	o->show = 0;
303 	o->destroy = 0;
304 	o->x = 0;
305 	o->y = 0;
306 	o->z = 0;
307 	o->width = 0;
308 	o->height = 0;
309 	o->have_alpha = 0;
310 	o->have_bgcolor = 0;
311 	o->alpha = 0;
312 	o->bgcolor[0] = 0;
313 	o->bgcolor[1] = 0;
314 	o->bgcolor[2] = 0;
315 	o->change = 0;
316 	o->x_old = 0;
317 	o->y_old = 0;
318 	o->height_old = 0;
319 	o->width_old = 0;
320 }
321 
322 
323 /* ---- show this pic */
eng_pic_show(eng_obj * o)324 void eng_pic_show(eng_obj *o) {
325 
326 	if(!o)  return;
327 
328 	if(!o->show)  {
329 
330 		o->show = 1;
331 		o->change = 1;
332 	}
333 }
334 
335 
336 /* ---- unshow this pic */
eng_pic_unshow(eng_obj * o)337 void eng_pic_unshow(eng_obj *o) {
338 
339 	if(!o)  return;
340 
341 	if(o->show)  {
342 
343 		o->show = 0;
344 		o->change = 1;
345 	}
346 }
347 
348 
349 /* ---- redraw this pic */
eng_pic_redraw(eng_obj * o)350 void eng_pic_redraw(eng_obj *o) {
351 
352 	if(!o)  return;
353 
354 	o->change = 1;
355 }
356 
357 
358 /* ---- set X pos of pic */
eng_pic_set_x(eng_obj * o,guint16 x)359 void eng_pic_set_x(eng_obj *o, guint16 x)  {
360 
361 	if(!o)  return;
362 
363 	if(x != o->x) {
364 
365 		o->x = x;
366 		o->change = 1;
367 	}
368 }
369 
370 
371 /* ---- set Y pos of pic */
eng_pic_set_y(eng_obj * o,guint16 y)372 void eng_pic_set_y(eng_obj *o, guint16 y)  {
373 
374 	if(!o)  return;
375 
376 	if(y != o->y) {
377 
378 		o->y = y;
379 		o->change = 1;
380 	}
381 }
382 
383 
384 /* ---- set Z pos of pic */
eng_pic_set_z(eng_obj * o,guint16 z)385 void eng_pic_set_z(eng_obj *o, guint16 z)  {
386 
387 	if(!o)  return;
388 
389 	if(z != o->z) {
390 
391 		o->z = z;
392 		o->change = 1;
393 	}
394 }
395 
396 
397 /* ---- set HEIGHT of pic */
eng_pic_set_height(eng_obj * o,guint16 height)398 void eng_pic_set_height(eng_obj *o, guint16 height)  {
399 
400 	if(!o)  return;
401 
402 	if(height != o->height) {
403 
404 		o->height = height;
405 		o->change = 1;
406 	 }
407 }
408 
409 
410 /* ---- set WIDTH of pic */
eng_pic_set_width(eng_obj * o,guint16 width)411 void eng_pic_set_width(eng_obj *o, guint16 width)  {
412 
413 	if(!o)  return;
414 
415 	if(width != o->width) {
416 
417 		o->width = width;
418 		o->change = 1;
419 	}
420 }
421 
422 
423 /* ---- set ALPHA value */
eng_pic_set_alpha(eng_obj * o,guint8 alpha)424 void eng_pic_set_alpha(eng_obj *o, guint8 alpha)  {
425 
426 	if(!o)  return;
427 
428 	if( !o->have_alpha  ||  alpha !=  o->alpha)  {
429 
430 		if(alpha == 0xff)  {  /* 100% opacity */
431 
432 			eng_pic_unset_alpha(o);
433 			return;
434 		}
435 		o->alpha = alpha;
436 		o->have_alpha = 1;
437 		o->change = 1;
438 	}
439 }
440 
441 
442 /* ---- UNset ALPHA value */
eng_pic_unset_alpha(eng_obj * o)443 void eng_pic_unset_alpha(eng_obj *o)  {
444 
445 	if(!o)  return;
446 
447 	if(o->have_alpha)  {
448 
449 		o->alpha = 0;
450 		o->have_alpha = 0;
451 		o->change = 1;
452 	}
453 }
454 
455 
456 /* ---- set BGCOLOR value */
eng_pic_set_bgcolor(eng_obj * o,guint32 bgcolor)457 void eng_pic_set_bgcolor(eng_obj *o, guint32 bgcolor)  {
458 
459 	guint8 rgb[3];
460 
461 	if(!o)  return;
462 
463 	rgb[0] = (bgcolor >> 16) & 0xff; // red
464 	rgb[1] = (bgcolor >> 8) & 0xff;  // green
465 	rgb[2] = bgcolor & 0xff;         // blue
466 
467 	if( !o->have_bgcolor  ||  memcmp(&rgb, o->bgcolor, 3) )  {
468 
469 		memcpy(o->bgcolor, &rgb, 3);
470 		o->have_bgcolor = 1;
471 		o->change = 1;
472 	}
473 }
474 
475 
476 /* ---- UNset BGCOLOR value */
eng_pic_unset_bgcolor(eng_obj * o)477 void eng_pic_unset_bgcolor(eng_obj *o)  {
478 
479 	if(!o)  return;
480 
481 	if(o->have_bgcolor)  {
482 
483 		o->bgcolor[0] = 0;
484 		o->bgcolor[1] = 0;
485 		o->bgcolor[2] = 0;
486 		o->have_bgcolor = 0;
487 		o->change = 1;
488 	}
489 }
490 
491 
492 /* ---- set pic buffer */
eng_pic_set_pixbuf(eng_obj * o,GdkPixbuf * pixbuff)493 void eng_pic_set_pixbuf(eng_obj *o, GdkPixbuf *pixbuff)  {
494 
495 	if(!o)  return;
496 	if(!pixbuff)  return;
497 
498 	o->pixbuf = pixbuff;
499 	o->change = 1;
500 }
501 
502 
503 /* ---- put in terminal all arguments of a pic */
eng_pic_showarg(eng_obj * o)504 void eng_pic_showarg(eng_obj *o)  {
505 
506 	if(!o)  return;
507 
508 	fprintf(stdout, "== PIC ==\n");
509 	fprintf(stdout, "  show          -> %d\n", o->show);
510 	fprintf(stdout, "  x             -> %d\n", o->x);
511 	fprintf(stdout, "  y             -> %d\n", o->y);
512 	fprintf(stdout, "  z             -> %d\n", o->z);
513 	fprintf(stdout, "  width         -> %d\n", o->width);
514 	fprintf(stdout, "  height        -> %d\n", o->height);
515 	fprintf(stdout, "  have_alpha    -> %d\n", o->have_alpha);
516 	fprintf(stdout, "  have_bgcolor  -> %d\n", o->have_bgcolor);
517 	fprintf(stdout, "  alpha         -> %d\n", o->alpha);
518 	fprintf(stdout, "  bgcolor[R]    -> 0x%.2X\n", o->bgcolor[0]);
519 	fprintf(stdout, "  bgcolor[G]    -> 0x%.2X\n", o->bgcolor[1]);
520 	fprintf(stdout, "  bgcolor[B]    -> 0x%.2X\n", o->bgcolor[2]);
521 	fprintf(stdout, "  ------\n");
522 	fprintf(stdout, "  change        -> %d\n", o->change);
523 	fprintf(stdout, "  x old         -> %d\n", o->x_old);
524 	fprintf(stdout, "  y old         -> %d\n", o->y_old);
525 	fprintf(stdout, "  width old     -> %d\n", o->width_old);
526 	fprintf(stdout, "  height old    -> %d\n", o->height_old);
527 	fprintf(stdout, "  ------\n");
528 	if(eng_pic_test(o) )
529 	fprintf(stdout, "  test      -> SUCCESS\n");
530 	else
531 	fprintf(stdout, "  test      -> ERROR\n");
532 	fprintf(stdout, "====================\n");
533 }
534 
535 
536 /* ---- test if pic is good */
eng_pic_test(eng_obj * o)537 gboolean eng_pic_test(eng_obj *o)  {
538 
539 	if(!o)  return(FALSE);
540 
541 	/* test x & width */
542 	if(o->x > o->frame->width - o->width) return(FALSE);
543 
544 	/* test y & height */
545 	if(o->y > o->frame->height - o->height) return(FALSE);
546 
547 	return(TRUE);
548 }
549