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