1 /* $Id: logosview.c,v 1.5 2007/12/10 15:24:29 dforsi Exp $ */
2 
3 #include <string.h>
4 #include <stdlib.h>
5 #include <gtk/gtk.h>
6 #include <glade/glade.h>
7 #include <gnokii.h>
8 
9 #include "gnocky.h"
10 #include "utils.h"
11 #include "logosview.h"
12 
13 
14 typedef struct _point {
15 	gint x;
16 	gint y;
17 } Point;
18 
19 //extern GMutex *pm.bitmap_mutex;
20 extern GnockyPhoneMonitor pm;
21 
22 static GladeXML *logos_xml;
23 
24 static GtkWidget *da = NULL;
25 static GtkWidget *dapreview = NULL;
26 static GdkPixmap *pixmap = NULL;
27 static GdkPixmap *preview = NULL;
28 static GdkGC *gc;
29 static GdkGC *grid;
30 static GdkGC *pgc;
31 
32 static gn_bmp buffer;
33 static gn_bmp_types current_bmp_type = GN_BMP_OperatorLogo;
34 static gint dm_set = DM_DEFAULT;
35 static gint dm_current = DM_POINT;
36 
37 static gint dm_x = 0, dm_y = 0;
38 static gint dm_last_x = 0, dm_last_y = 0;
39 static gboolean initialized = FALSE;
40 
41 /* prototypes of internal drawing routines */
42 void clearpixel_bool(gint x, gint y);
43 void putpixel(gint _x, gint _y, gboolean clear);
44 void putpixel_all(gint x, gint y, gboolean clear);
45 void clearpixel_bool(int x, int y);
46 void line_bool(int x0, int y0, int x1, int y1);
47 void line(int x0, int y0, int x1, int y1, int clear);
48 void rect_bool(int x0, int y0, int x1, int y1);
49 void rect(int x0, int y0, int x1, int y1, int clear);
50 void ellipse_bool(int cx, int cy, int xr, int yr);
51 void ellipse (int cx, int cy, int xr, int yr, int clear);
52 void resize(gn_bmp_types type);
53 void fill(int x, int y, int clear);
54 
gnocky_copy_bmp_to_screen(gn_bmp * bmp)55 void gnocky_copy_bmp_to_screen(gn_bmp *bmp)
56 {
57 	gint x,y;
58 	gboolean clear;
59 	GdkRectangle update_rect;
60 	g_print("copy to screen %d x %d\n", bmp->width, bmp->height);
61 	update_rect.width = TILE_SIZE - 1;
62 	update_rect.height = TILE_SIZE - 1;
63 
64 	for (x = 0;x<bmp->width;x++) {
65 		for (y = 0;y<bmp->height;y++) {
66 			if (gn_bmp_point(bmp, x, y))
67 				clear = 0;
68 			else
69 				clear = 1;
70 
71 			gdk_draw_point(preview, (clear) ? pgc : dapreview->style->black_gc, x, y);
72 
73 			update_rect.x = x * TILE_SIZE + 1;
74 			update_rect.y = y * TILE_SIZE + 1;
75 
76 			gdk_draw_rectangle(pixmap,
77 			   (clear) ? gc : da->style->black_gc,
78 			   TRUE,
79 			   update_rect.x, update_rect.y,
80 			   update_rect.width, update_rect.height);
81 		}
82 	}
83 
84 	update_rect.x = 0;
85 	update_rect.y = 0;
86 
87 	update_rect.width = da->allocation.width;
88 	update_rect.height = da->allocation.height;
89 	update_rect.width = bmp->width  * TILE_SIZE;
90 	update_rect.height = bmp->height * TILE_SIZE;
91 
92 	gdk_window_invalidate_rect(da->window, &update_rect, FALSE);
93 
94 	update_rect.width = bmp->width;
95 	update_rect.height = bmp->height;
96 
97 	gdk_window_invalidate_rect(dapreview->window, &update_rect, FALSE);
98 }
99 static
change_size(gint xsize,gint ysize)100 void change_size(gint xsize, gint ysize)
101 {
102 	g_print("%d %d\n", xsize, ysize);
103 
104 	gtk_widget_set_size_request(da, TILE_SIZE * xsize + 1,
105 				    TILE_SIZE * ysize + 1);
106 	gtk_widget_set_size_request(dapreview, xsize, ysize);
107 
108 	if (pixmap)
109 		g_object_unref(pixmap);
110 
111 	if (preview)
112 		g_object_unref(preview);
113 
114 	pixmap = gdk_pixmap_new(da->window,
115 				xsize * TILE_SIZE + 1,
116 				ysize * TILE_SIZE + 1, -1);
117 
118 	gdk_draw_rectangle(pixmap,
119 			   gc,
120 			   TRUE,
121 			   0, 0,
122 			   xsize * TILE_SIZE, ysize * TILE_SIZE);
123 
124 	preview = gdk_pixmap_new(dapreview->window,
125 				 xsize,
126 				 ysize, -1);
127 
128 	gdk_draw_rectangle(preview,
129 			   pgc,
130 			   TRUE,
131 			   0, 0,
132 			   xsize, ysize);
133 
134 }
135 
136 static gboolean
scribble_button_release_event(GtkWidget * widget,GdkEventButton * event,gpointer data)137 scribble_button_release_event(GtkWidget * widget,
138 			    GdkEventButton * event, gpointer data)
139 {
140 	if (pixmap == NULL)
141 		return FALSE;	/* paranoia check, in case we haven't gotten a configure event */
142 	g_print("release\n");
143 
144 	if (dm_set == DM_FILL) {
145 		gint x, y;
146 		gboolean clear = (event->button == 3);
147 
148 		x = (gint)event->x / TILE_SIZE;
149 		y = (gint)event->y / TILE_SIZE;
150 
151 		fill(x, y, clear);
152 	} else {
153 		dm_current = DM_DEFAULT;
154 	}
155 	return TRUE;
156 }
157 
158 
159 static gboolean
scribble_button_press_event(GtkWidget * widget,GdkEventButton * event,gpointer data)160 scribble_button_press_event(GtkWidget * widget,
161 			    GdkEventButton * event, gpointer data)
162 {
163 	gint x,y;
164 	if (pixmap == NULL)
165 		return FALSE;	/* paranoia check, in case we haven't gotten a configure event */
166 
167 	x = (gint)event->x / TILE_SIZE;
168 	y = (gint)event->y / TILE_SIZE;
169 
170 	if ((event->button == 1 || event->button == 3)) {
171 	    gboolean clear = (event->button == 3) ? TRUE : FALSE;
172 	    switch (dm_set) {
173 		case DM_LINE:
174 		    if (dm_set != dm_current) {
175 		    	dm_current = dm_set;
176 		    	dm_last_x = dm_x = x;
177 		    	dm_last_y = dm_y = y;
178 		    	memcpy(&buffer, &pm.bitmap, sizeof(buffer));
179 		    } else {
180 		    	dm_current = DM_DEFAULT;
181 		    	line(dm_x, dm_y, x, y, clear);
182 		    }
183 		    break;
184 		case DM_RECT:
185 		    if (dm_set != dm_current) {
186 		    	dm_current = dm_set;
187 		    	dm_last_x = dm_x = x;
188 		    	dm_last_y = dm_y = y;
189 		    	memcpy(&buffer, &pm.bitmap, sizeof(buffer));
190 		    } else {
191 		    	dm_current = DM_DEFAULT;
192 		    	rect(dm_x, dm_y, x, y, clear);
193 		    }
194 		    break;
195 		case DM_ELLIPSE:
196 		    if (dm_set != dm_current) {
197 		    	dm_current = dm_set;
198 		    	dm_last_x = dm_x = x;
199 		    	dm_last_y = dm_y = y;
200 		    	memcpy(&buffer, &pm.bitmap, sizeof(buffer));
201 		    } else {
202 		    	dm_current = DM_DEFAULT;
203 		    	ellipse(x, y, abs(x - dm_x), abs(y - dm_y), clear);
204 		    }
205 		    break;
206 		case DM_FILL:
207 			break;
208 		default:
209 		    putpixel_all(x, y, clear);
210 		    break;
211 	    }
212 	}
213 
214 	return TRUE;
215 }
216 
217 static gboolean
scribble_motion_notify_event(GtkWidget * widget,GdkEventMotion * event,gpointer data)218 scribble_motion_notify_event(GtkWidget * widget,
219 			     GdkEventMotion * event, gpointer data)
220 {
221 	gint x, y;
222 	GdkModifierType state;
223 	if (pixmap == NULL)
224 		return FALSE;
225 
226 	gdk_window_get_pointer(event->window, &x, &y, &state);
227 
228 	x = (gint)event->x / TILE_SIZE;
229 	y = (gint)event->y / TILE_SIZE;
230 
231 	if (state & GDK_BUTTON1_MASK || state & GDK_BUTTON3_MASK) {
232 	    gboolean clear = (state & GDK_BUTTON3_MASK) ? TRUE : FALSE;
233 		switch (dm_current) {
234 		    case DM_LINE:
235 			line_bool(dm_x, dm_y, dm_last_x, dm_last_y);
236 			line(dm_x, dm_y, x, y, clear);
237 			dm_set = DM_LINE;
238 			dm_last_x = x;
239 			dm_last_y = y;
240 			break;
241 		    case DM_RECT:
242 			rect_bool(dm_x, dm_y, dm_last_x, dm_last_y);
243 			rect(dm_x, dm_y, x, y, clear);
244 			dm_set = DM_RECT;
245 			dm_last_x = x;
246 			dm_last_y = y;
247 			break;
248 		    case DM_ELLIPSE:
249 			ellipse_bool(dm_last_x, dm_last_y, abs(dm_x - dm_last_x), abs(dm_y - dm_last_y));
250 		    	ellipse(x, y, abs(x - dm_x), abs(y - dm_y), clear);
251 			dm_set = DM_ELLIPSE;
252 			dm_last_x = x;
253 			dm_last_y = y;
254 			break;
255 		    case DM_FILL:
256 		    	break;
257 		    default:
258 			putpixel_all(x, y, clear);
259 			break;
260 
261 		}
262 	}
263 	return TRUE;
264 }
265 
266 /* Create a new pixmap of the appropriate size to store our scribbles */
267 static gboolean
scribble_configure_event(GtkWidget * da,GdkEventConfigure * event,gpointer data)268 scribble_configure_event(GtkWidget * da,
269 			 GdkEventConfigure * event, gpointer data)
270 {
271 	GdkColor color;
272 
273 	if (!gc) {
274 		gc = gdk_gc_new(da->window);
275 		gdk_color_parse("#00ff01", &color);
276 		gdk_gc_set_rgb_fg_color(gc, &color);
277 	}
278 	if (!grid) {
279 		grid = gdk_gc_new(da->window);
280 		gdk_color_parse("#808080", &color);
281 		gdk_gc_set_rgb_fg_color(grid, &color);
282 	}
283 
284 	if (pixmap)
285 		return TRUE;
286 
287 	pixmap = gdk_pixmap_new(da->window,
288 				da->allocation.width,
289 				da->allocation.height, -1);
290 
291 	gdk_draw_rectangle(pixmap,
292 			   gc,
293 			   TRUE,
294 			   0, 0,
295 			   da->allocation.width, da->allocation.height);
296 
297 	return TRUE;
298 }
299 
300 static gboolean
preview_configure_event(GtkWidget * da,GdkEventConfigure * event,gpointer data)301 preview_configure_event(GtkWidget * da,
302 			GdkEventConfigure * event, gpointer data)
303 {
304 	GdkColor color;
305 
306 	if (!pgc) {
307 		pgc = gdk_gc_new(da->window);
308 		gdk_color_parse("#7cc17c", &color);
309 		gdk_gc_set_rgb_fg_color(pgc, &color);
310 	}
311 
312 	if (preview)
313 		return TRUE;
314 
315 	preview = gdk_pixmap_new(da->window,
316 				 da->allocation.width,
317 				 da->allocation.height, -1);
318 
319 	gdk_draw_rectangle(preview,
320 			   pgc,
321 			   TRUE,
322 			   0, 0,
323 			   da->allocation.width, da->allocation.height);
324 
325 	return TRUE;
326 }
327 
328 /* Redraw the screen from the pixmap */
329 static gboolean
scribble_expose_event(GtkWidget * da,GdkEventExpose * event,gpointer data)330 scribble_expose_event(GtkWidget * da,
331 		      GdkEventExpose * event, gpointer data)
332 {
333 	gint i;
334 
335 	/* FIXME */
336 	if (!initialized) {
337 		resize(current_bmp_type);
338 		initialized = TRUE;
339 	}
340 	gdk_draw_drawable(da->window,
341 			  gc,
342 			  pixmap,
343 			  event->area.x, event->area.y,
344 			  event->area.x, event->area.y,
345 			  event->area.width, event->area.height);
346 
347 	for (i = 0; i < da->allocation.width; i += TILE_SIZE)
348 		gdk_draw_line(da->window, grid, i, 0, i,
349 			      da->allocation.height);
350 	for (i = 0; i < da->allocation.height; i += TILE_SIZE)
351 		gdk_draw_line(da->window, grid, 0, i, da->allocation.width,
352 			      i);
353 	return FALSE;
354 }
355 
356 static gboolean
preview_expose_event(GtkWidget * da,GdkEventExpose * event,gpointer data)357 preview_expose_event(GtkWidget * da, GdkEventExpose * event, gpointer data)
358 {
359 	gdk_draw_drawable(da->window,
360 			  pgc,
361 			  preview,
362 			  event->area.x, event->area.y,
363 			  event->area.x, event->area.y,
364 			  event->area.width, event->area.height);
365 
366 	return FALSE;
367 }
368 /* button callbacks */
369 
resize(gn_bmp_types type)370 void resize(gn_bmp_types type)
371 {
372 	gn_bmp_resize(&pm.bitmap, type, &pm.info);
373 	change_size(pm.bitmap.width, pm.bitmap.height);
374 	memcpy(&buffer, &pm.bitmap, sizeof(pm.bitmap));
375 	gnocky_copy_bmp_to_screen(&pm.bitmap);
376 	current_bmp_type = type;
377 }
378 
operator_logo_radio_toggled(GtkWidget * button,gpointer user_data)379 void operator_logo_radio_toggled(GtkWidget *button, gpointer user_data)
380 {
381 	resize(GN_BMP_OperatorLogo);
382 }
383 
picture_message_radio_toggled(GtkWidget * button,gpointer user_data)384 void picture_message_radio_toggled(GtkWidget *button, gpointer user_data)
385 {
386 	resize(GN_BMP_PictureMessage);
387 }
388 
caller_id_radio_toggled(GtkWidget * button,gpointer user_data)389 void caller_id_radio_toggled(GtkWidget *button, gpointer user_data)
390 {
391 	resize(GN_BMP_CallerLogo);
392 }
393 
startup_logo_radio_toggled(GtkWidget * button,gpointer user_data)394 void startup_logo_radio_toggled(GtkWidget *button, gpointer user_data)
395 {
396 	resize(GN_BMP_StartupLogo);
397 }
398 
change_dm(gint dm)399 void change_dm(gint dm)
400 {
401 	dm_set = dm;
402 	dm_current = DM_DEFAULT;
403 }
404 
pencil_radio_toggled(GtkWidget * button,gpointer user_data)405 void pencil_radio_toggled(GtkWidget * button, gpointer user_data)
406 {
407 	change_dm(DM_POINT);
408 }
409 
line_radio_toggled(GtkWidget * button,gpointer user_data)410 void line_radio_toggled(GtkWidget * button, gpointer user_data)
411 {
412 	change_dm(DM_LINE);
413 }
414 
rect_radio_toggled(GtkWidget * button,gpointer user_data)415 void rect_radio_toggled(GtkWidget * button, gpointer user_data)
416 {
417 	change_dm(DM_RECT);
418 }
419 
ellipse_radio_toggled(GtkWidget * button,gpointer user_data)420 void ellipse_radio_toggled(GtkWidget * button, gpointer user_data)
421 {
422 	change_dm(DM_ELLIPSE);
423 }
424 
fill_radio_toggled(GtkWidget * button,gpointer user_data)425 void fill_radio_toggled(GtkWidget * button, gpointer user_data)
426 {
427 	change_dm(DM_FILL);
428 	dm_current = DM_FILL;
429 }
430 
download_button_clicked(GtkWidget * button,gpointer user_data)431 void download_button_clicked(GtkWidget * button, gpointer user_data)
432 {
433 	gnocky_event_push(GNOCKY_EVENT_READ_BITMAP, (gpointer)pm.bitmap.type);
434 }
435 
upload_button_clicked(GtkWidget * button,gpointer user_data)436 void upload_button_clicked(GtkWidget * button, gpointer user_data)
437 {
438 	gnocky_event_push(GNOCKY_EVENT_WRITE_BITMAP, (gpointer)pm.bitmap.type);
439 }
440 
441 static
clear_button_clicked(GtkWidget * button,gpointer user_data)442 void clear_button_clicked(GtkWidget * button, gpointer user_data)
443 {
444 	GdkRectangle update_rect;
445 
446 	update_rect.x = 0;
447 	update_rect.y = 0;
448 	update_rect.width = da->allocation.width;
449 	update_rect.height = da->allocation.height;
450 
451 	gdk_draw_rectangle(pixmap,
452 			   gc,
453 			   TRUE,
454 			   0, 0,
455 			   da->allocation.width, da->allocation.height);
456 
457 	gdk_window_invalidate_rect(da->window, &update_rect, FALSE);
458 
459 	update_rect.x = 0;
460 	update_rect.y = 0;
461 	update_rect.width = dapreview->allocation.width;
462 	update_rect.height = dapreview->allocation.height;
463 
464 	gdk_draw_rectangle(preview,
465 			   pgc,
466 			   TRUE,
467 			   0, 0,
468 			   dapreview->allocation.width,
469 			   dapreview->allocation.height);
470 
471 	gdk_window_invalidate_rect(dapreview->window, &update_rect, FALSE);
472 	gn_bmp_clear(&pm.bitmap);
473 	memcpy(&buffer, &pm.bitmap, sizeof(pm.bitmap));
474 }
475 
476 
open_button_clicked(GtkWidget * button,gpointer user_data)477 void open_button_clicked(GtkWidget * button, gpointer user_data)
478 {
479 	GtkWidget *file_selector;
480 	gint response;
481 	gchar *filename = NULL;
482 
483 	file_selector = gtk_file_selection_new(_("Open file"));
484 	response = gtk_dialog_run(GTK_DIALOG(file_selector));
485 
486 	if (response == GTK_RESPONSE_OK) {
487 		filename = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector));
488 		gn_bmp_clear(&pm.bitmap);
489 		gn_file_bitmap_read(filename, &pm.bitmap, &pm.info);
490 		change_size(pm.bitmap.width, pm.bitmap.height);
491 		gnocky_copy_bmp_to_screen(&pm.bitmap);
492 	}
493     	gtk_widget_destroy(file_selector);
494 	resize(current_bmp_type);
495 }
496 
save_button_clicked(GtkWidget * button,gpointer user_data)497 void save_button_clicked(GtkWidget * button, gpointer user_data)
498 {
499 	GtkWidget *file_selector;
500 	gint response;
501 	gchar *filename = NULL;
502 
503 	file_selector = gtk_file_selection_new(_("Save file"));
504 	response = gtk_dialog_run(GTK_DIALOG(file_selector));
505 
506 	if (response == GTK_RESPONSE_OK) {
507 		filename = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector));
508 		gn_file_bitmap_save(filename, &pm.bitmap, &pm.info);
509 	}
510 
511 	gtk_widget_destroy(file_selector);
512 }
513 
gnocky_logos_view_destroy(GtkWidget * logos_view)514 void gnocky_logos_view_destroy(GtkWidget *logos_view)
515 {
516 	if (logos_view)
517 		gtk_widget_destroy(logos_view);
518 	if (logos_xml)
519 		g_object_unref(logos_xml);
520 }
521 
gnocky_logos_view_create()522 GtkWidget *gnocky_logos_view_create()
523 {
524 	GtkWidget *lv;
525 	GtkWidget *hbox;
526 	GtkWidget *left_vbox;
527 	GtkWidget *frame;
528 	GtkWidget *right_vbox;
529 	GtkWidget *button;
530 
531 	logos_xml = create_gladexml("gnocky-logos-view.glade", "logos_view");
532 
533 	if (!logos_xml)
534 		g_error("Cannot create logos view!\n");
535 
536 	glade_xml_signal_autoconnect(logos_xml);
537 
538 	lv = glade_xml_get_widget(logos_xml, "logos_view");
539 
540 	if (lv == NULL)
541 		g_error("Wrong glade data!\n");
542 
543 	hbox = gtk_hbox_new(FALSE, 0);
544 	gtk_box_pack_start(GTK_BOX(lv), hbox, TRUE, TRUE, 0);
545 
546 	left_vbox = gtk_vbox_new(FALSE, 0);
547 	gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0);
548 
549 	frame = gtk_frame_new(NULL);
550 	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
551 
552 	dapreview = gtk_drawing_area_new();
553 	gtk_widget_set_size_request(dapreview, DEFAULT_XSIZE,
554 				    DEFAULT_YSIZE);
555 	gtk_container_add(GTK_CONTAINER(frame), dapreview);
556 	gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
557 	gtk_box_pack_start(GTK_BOX(left_vbox), frame, FALSE, FALSE, 0);
558 
559 	frame = gtk_frame_new(NULL);
560 	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
561 
562 	da = gtk_drawing_area_new();
563 	gtk_widget_set_size_request(da, TILE_SIZE * DEFAULT_XSIZE + 1,
564 				    TILE_SIZE * DEFAULT_YSIZE + 1);
565 
566 	right_vbox = gtk_vbox_new(FALSE, 8);
567 	gtk_box_pack_start(GTK_BOX(hbox), right_vbox, FALSE, FALSE, 0);
568 	gtk_container_add(GTK_CONTAINER(frame), da);
569 	gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
570 	gtk_box_pack_start(GTK_BOX(right_vbox), frame, FALSE, FALSE, 0);
571 
572 	/* Signals used to handle backing pixmap */
573 
574 	g_signal_connect(da, "expose_event",
575 			 G_CALLBACK(scribble_expose_event), NULL);
576 	g_signal_connect(da, "configure_event",
577 			 G_CALLBACK(scribble_configure_event), NULL);
578 
579 	g_signal_connect(dapreview, "configure_event",
580 			 G_CALLBACK(preview_configure_event), NULL);
581 	g_signal_connect(dapreview, "expose_event",
582 			 G_CALLBACK(preview_expose_event), NULL);
583 
584 	/* Event signals */
585 	g_signal_connect(da, "motion_notify_event",
586 			 G_CALLBACK(scribble_motion_notify_event), NULL);
587 	g_signal_connect(da, "button_press_event",
588 			 G_CALLBACK(scribble_button_press_event), NULL);
589 	g_signal_connect(da, "button_release_event",
590 			 G_CALLBACK(scribble_button_release_event), NULL);
591 
592 	gtk_widget_set_events(da, gtk_widget_get_events(da)
593 			      | GDK_LEAVE_NOTIFY_MASK
594 			      | GDK_BUTTON_PRESS_MASK
595 			      | GDK_BUTTON_RELEASE_MASK
596 			      | GDK_POINTER_MOTION_MASK
597 			      | GDK_POINTER_MOTION_HINT_MASK);
598 
599 	button = gtk_button_new_with_label(_("Clear"));
600 	g_signal_connect(button, "clicked",
601 			 G_CALLBACK(clear_button_clicked), NULL);
602 	gtk_box_pack_end(GTK_BOX(left_vbox), button, FALSE, FALSE, 0);
603 
604 	gtk_widget_show_all(lv);
605 
606 	return lv;
607 }
608 
gnocky_logos_view_update(GnockyPhoneMonitor pm)609 void gnocky_logos_view_update(GnockyPhoneMonitor pm)
610 {
611 
612 }
613 
614 /* drawing routines */
clearpixel_bool(gint x,gint y)615 void clearpixel_bool(gint x, gint y)
616 {
617     if (x < 0 || y < 0)
618 	return;
619     if (x > pm.bitmap.width || y > pm.bitmap.height)
620 	return;
621 
622 	putpixel_all(x, y, !gn_bmp_point(&buffer, x, y));
623 }
624 
putpixel(gint _x,gint _y,gboolean clear)625 void putpixel(gint _x, gint _y, gboolean clear)
626 {
627 	GdkRectangle update_rect;
628 
629 	update_rect.x = _x * TILE_SIZE + 1;
630 	update_rect.y = _y * TILE_SIZE + 1;
631 	update_rect.width = TILE_SIZE - 1;
632 	update_rect.height = TILE_SIZE - 1;
633 
634 	gdk_draw_rectangle(da->window,
635 			   (clear) ? gc : da->style->black_gc,
636 			   TRUE,
637 			   update_rect.x, update_rect.y,
638 			   update_rect.width, update_rect.height);
639 	gdk_draw_rectangle(pixmap,
640 			   (clear) ? gc : da->style->black_gc,
641 			   TRUE,
642 			   update_rect.x, update_rect.y,
643 			   update_rect.width, update_rect.height);
644 	gdk_draw_point(dapreview->window,
645 		       (clear) ? pgc : dapreview->style->black_gc, _x, _y);
646 	gdk_draw_point(preview,
647 		       (clear) ? pgc : dapreview->style->black_gc, _x, _y);
648 }
649 
putpixel_all(gint x,gint y,gboolean clear)650 void putpixel_all(gint x, gint y, gboolean clear)
651 {
652 //	g_print("pp %d %d\n", x, y);
653 
654 	if (x < 0 || y < 0)
655 	    return;
656 
657 	if (x > pm.bitmap.width || y > pm.bitmap.height)
658 	    return;
659 
660 	putpixel(x,y, clear);
661 
662 	if (clear)
663 		gn_bmp_point_clear(&pm.bitmap, x, y);
664 	else
665 		gn_bmp_point_set(&pm.bitmap, x, y);
666 
667 }
668 
is_point_set(gint x,gint y,gboolean clear)669 gboolean is_point_set(gint x, gint y, gboolean clear)
670 {
671 	if (x < 0 || y < 0)
672 	    return TRUE;
673 
674 	if (x > pm.bitmap.width || y > pm.bitmap.height)
675 	    return TRUE;
676 
677 	return gn_bmp_point(&pm.bitmap, x, y) != clear;
678 }
679 
line_bool(int x0,int y0,int x1,int y1)680 void line_bool(int x0, int y0, int x1, int y1)
681 {
682 	int dy, dx;
683 	float t = (float) 0.5;
684 
685 	dy = y1 - y0;
686 	dx = x1 - x0;
687 	clearpixel_bool(x0, y0);
688         if (abs(dx) > abs(dy)) {
689             float m = (float) dy / (float) dx;
690             t += y0;
691             dx = (dx < 0) ? -1 : 1;
692             m *= dx;
693             while (x0 != x1) {
694                 x0 += dx;
695                 t += m;
696 		clearpixel_bool(x0, (int)t);
697             }
698 	} else {
699             float m = (float) dx / (float) dy;
700             t += x0;
701             dy = (dy < 0) ? -1 : 1;
702             m *= dy;
703             while (y0 != y1) {
704                 y0 += dy;
705                 t += m;
706 		clearpixel_bool((int) t, y0);
707 	    }
708 	}
709 }
710 
line(int x0,int y0,int x1,int y1,int clear)711 void line(int x0, int y0, int x1, int y1, int clear)
712 {
713     int dy, dx;
714     float t = (float) 0.5;
715 
716     dy = y1 - y0;
717     dx = x1 - x0;
718 
719     putpixel_all((gdouble) x0, (gdouble)y0, clear);
720 
721     if (abs(dx) > abs(dy)) {
722 	float m = (float) dy / (float) dx;
723         t += y0;
724         dx = (dx < 0) ? -1 : 1;
725         m *= dx;
726         while (x0 != x1) {
727             x0 += dx;
728             t += m;
729 	    putpixel_all(x0, (int) t, clear);
730         }
731     } else {
732         float m = (float) dx / (float) dy;
733         t += x0;
734         dy = (dy < 0) ? -1 : 1;
735         m *= dy;
736 	while (y0 != y1) {
737             y0 += dy;
738             t += m;
739 	    putpixel_all((int) t, y0, clear);
740 	}
741     }
742 }
743 
rect_bool(int x0,int y0,int x1,int y1)744 void rect_bool(int x0, int y0, int x1, int y1)
745 {
746 	line_bool(x0, y0, x0, y1);
747 	line_bool(x0, y1, x1, y1);
748 	line_bool(x1, y1, x1, y0);
749 	line_bool(x0, y0, x1, y0);
750 
751 /*    if (!filled) {
752 	line_bool(x0, y0, x0, y1);
753 	line_bool(x0, y1, x1, y1);
754 	line_bool(x1, y1, x1, y0);
755 	line_bool(x0, y0, x1, y0);
756     } else {
757 	int x, y;
758 	int _x, _y;
759 
760 	if (y1 < y0) {
761 	    _y = y1;
762 	    y1 = y0;
763 	    y0 = _y;
764 	}
765 
766 	if (x1 < x0) {
767 	    _x = x1;
768 	    x1 = x0;
769 	    x0 = _x;
770 	}
771 
772 	for (y = y0; y < y1; y++) {
773 	    for (x = x0;x < x1; x++) {
774 		clearpixel_bool(x, y);
775 	    }
776 	}
777     }*/
778 }
779 
rect(int x0,int y0,int x1,int y1,int clear)780 void rect(int x0, int y0, int x1, int y1, int clear)
781 {
782 	line(x0, y0, x0, y1, clear);
783 	line(x0, y1, x1, y1, clear);
784 	line(x1, y1, x1, y0, clear);
785 	line(x0, y0, x1, y0, clear);
786 
787     /*if (!filled) {
788 	line(x0, y0, x0, y1, clear);
789 	line(x0, y1, x1, y1, clear);
790 	line(x1, y1, x1, y0, clear);
791 	line(x0, y0, x1, y0, clear);
792     }
793     else {
794 	int x, y;
795 	int _x, _y;
796 
797 	if (y1 < y0) {
798 	    _y = y1;
799 	    y1 = y0;
800 	    y0 = _y;
801 	}
802 
803 	if (x1 < x0) {
804 	    _x = x1;
805 	    x1 = x0;
806 	    x0 = _x;
807 	}
808 
809 	for (y = y0; y < y1; y++) {
810 	    for (x = x0;x < x1; x++) {
811 		putpixel_all(x, y, clear);
812 	    }
813 	}
814     }*/
815 }
816 
ellipse_bool(int cx,int cy,int xr,int yr)817 void ellipse_bool(int cx, int cy, int xr, int yr)
818 {
819     int x,y;
820     int xc, yc;
821     int ee;
822     int tas, tbs;
823     int stx, sty;
824 
825     if (!xr || !yr) {
826 	return;
827     }
828 
829     printf("radius %d %d\n", xr, yr);
830 
831     tas = 2 * xr * xr;
832     tbs = 2 * yr * yr;
833 
834     x = xr;
835     y = 0;
836 
837     xc = yr * yr * ( 1 - 2 * xr);
838     yc = xr * xr;
839     ee = 0;
840 
841     stx = tbs * xr;
842     sty = 0;
843 
844     while (stx >= sty) {
845 	clearpixel_bool(cx + x, cy + y);
846 	clearpixel_bool(cx - x, cy + y);
847 	clearpixel_bool(cx + x, cy - y);
848 	clearpixel_bool(cx - x, cy - y);
849 	y++;
850 	sty += tas;
851 	ee += yc;
852 	yc += tas;
853 	if ((2 * ee + xc) > 0) {
854 	    x--;
855 	    stx -= tbs;
856 	    ee += xc;
857 	    xc += tbs;
858 	}
859     }
860 
861     x = 0;
862     y = yr;
863     xc = yr * yr;
864     yc = xr * xr * (1 - 2 * yr);
865     ee = 0;
866     stx = 0;
867     sty = tas * yr;
868 
869     while (stx <= sty) {
870 	clearpixel_bool(cx + x, cy + y);
871 	clearpixel_bool(cx - x, cy + y);
872 	clearpixel_bool(cx + x, cy - y);
873 	clearpixel_bool(cx - x, cy - y);
874 	x++;
875 	stx += tbs;
876 	ee += xc;
877 	xc += tbs;
878 
879 	if ((2 * ee + xc) > 0) {
880 	    y--;
881 	    sty -= tas;
882 	    ee += yc;
883 	    yc += tas;
884 	}
885     }
886 }
887 
ellipse(int cx,int cy,int xr,int yr,int clear)888 void ellipse (int cx, int cy, int xr, int yr, int clear)
889 {
890     int x,y;
891     int xc, yc;
892     int ee;
893     int tas, tbs;
894     int stx, sty;
895 
896 
897     if (!xr || !yr) {
898 	return;
899     }
900 
901     printf("radius %d %d\n", xr, yr);
902 
903     tas = 2 * xr * xr;
904     tbs = 2 * yr * yr;
905 
906     x = xr;
907     y = 0;
908 
909     xc = yr * yr * ( 1 - 2 * xr);
910     yc = xr * xr;
911     ee = 0;
912 
913     stx = tbs * xr;
914     sty = 0;
915 
916     while (stx >= sty) {
917 	putpixel_all(cx + x, cy + y, clear);
918 	putpixel_all(cx - x, cy + y, clear);
919 	putpixel_all(cx + x, cy - y, clear);
920 	putpixel_all(cx - x, cy - y, clear);
921 	y++;
922 	sty += tas;
923 	ee += yc;
924 	yc += tas;
925 	if ((2 * ee + xc) > 0) {
926 	    x--;
927 	    stx -= tbs;
928 	    ee += xc;
929 	    xc += tbs;
930 	}
931     }
932 
933     x = 0;
934     y = yr;
935     xc = yr * yr;
936     yc = xr * xr * (1 - 2 * yr);
937     ee = 0;
938     stx = 0;
939     sty = tas * yr;
940 
941     while (stx <= sty) {
942 	putpixel_all(cx + x, cy + y, clear);
943 	putpixel_all(cx - x, cy + y, clear);
944 	putpixel_all(cx + x, cy - y, clear);
945 	putpixel_all(cx - x, cy - y, clear);
946 	x++;
947 	stx += tbs;
948 	ee += xc;
949 	xc += tbs;
950 
951 	if ((2 * ee + xc) > 0) {
952 	    y--;
953 	    sty -= tas;
954 	    ee += yc;
955 	    yc += tas;
956 	}
957     }
958 }
959 
fill(int x,int y,int clear)960 void fill(int x, int y, int clear)
961 {
962 
963 	g_print("FILL\n");
964 
965 	if (is_point_set(x, y, clear)) {
966 		return;
967 	} else {
968 		GQueue *q = g_queue_new();
969 		Point *p;
970 
971 		p = g_new0(Point, 1);
972 		p->x = x;
973 		p->y = y;
974 		g_queue_push_tail(q, p);
975 
976 		while (!g_queue_is_empty(q)) {
977 			Point *_p;
978 
979 			_p = g_queue_pop_tail(q);
980 
981 			x = _p->x;
982 			y = _p->y;
983 
984 			g_free(_p);
985 
986 			if (is_point_set(x, y, clear))
987 				continue;
988 
989 			putpixel_all(x, y, clear);
990 
991 			_p = g_new0(Point, 1);
992 			_p->x = x + 1;
993 			_p->y = y;
994 			g_queue_push_tail(q, _p);
995 
996 			_p = g_new0(Point, 1);
997 			_p->x = x;
998 			_p->y = y + 1;
999 			g_queue_push_tail(q, _p);
1000 
1001 			_p = g_new0(Point, 1);
1002 			_p->x = x - 1;
1003 			_p->y = y;
1004 			g_queue_push_tail(q, _p);
1005 
1006 			_p = g_new0(Point, 1);
1007 			_p->x = x;
1008 			_p->y = y - 1;
1009 			g_queue_push_tail(q, _p);
1010 		}
1011 	}
1012 }
1013