source: gs2-extensions/music-stand/trunk/src/scribble-simple/scribble-simple.c

Last change on this file was 22581, checked in by davidb, 14 years ago

page loads smaller chunks, fixed bugs

File size: 20.0 KB
Line 
1
2/* GTK - The GIMP Toolkit
3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <gtk/gtk.h>
24#include <gdk/gdkkeysyms.h>
25#include <glib/gstdio.h>
26#include <string.h>
27
28/* Backing pixmap for drawing area */
29static GdkPixmap *pixmap = NULL;
30
31//buffer pixmap which will be drawn into the pixmap drawn on screen
32static GdkPixmap *buffer_pixmap = NULL;
33
34//point data to be added to an appropriate file upon leaving the relevant page [or exiting?]
35static GList *points_list = NULL;
36
37//static char *folder_name = "chopin_prelude_op45-a4";
38static int current_page = 0;
39static int prev_page = 0;
40
41static int vert_page_progress = 0;
42static int hori_page_progress = 0;
43
44//percentage of height at which we change from uncovering vertically to horizontally
45static int change_height_percent=80;
46
47static GdkPixbuf *pp_pbuf_image = NULL;
48static GdkGC* pp_gc = NULL;
49
50static int pp_width = 0;
51static int pp_height = 0;
52
53static int page_width = 0;
54static int page_height = 0;
55
56//for tracking mouse movement
57static int last_x_pos = -1;
58static int last_y_pos = -1;
59
60
61static gboolean in_progress = FALSE;
62
63static gboolean load_show_page( GtkWidget *widget,
64 char *folder_name,
65 int page_number);
66
67static gboolean load_show_page_immediate( GtkWidget *widget,
68 char *folder_name,
69 int page_number);
70
71static gboolean read_point_data_from_file (GtkWidget *widget,
72 GdkPixmap *drawing_pixmap,
73 char *filename);
74
75
76static guint timeout_id = 0;
77
78
79static gboolean update_progress_page(gpointer data)
80{
81 GtkWidget* widget = (GtkWidget*)data;
82
83 g_print("updating page progress = %d\n", vert_page_progress);
84
85 if (vert_page_progress < 100)
86 {
87 if (vert_page_progress < change_height_percent)
88 {
89
90 int prev_height = (int)(pp_height * (vert_page_progress / 100.0));
91 vert_page_progress+=10;
92 int update_height = (int)(pp_height * (vert_page_progress / 100.0));
93
94// gdk_draw_pixbuf (pixmap, pp_gc, pp_pbuf_image,
95// 0, 0, 0, 0, -1, update_height, GDK_RGB_DITHER_NONE, 0, 0);
96
97 gdk_draw_drawable (pixmap, pp_gc, buffer_pixmap,
98 0, 0, 0, 0, -1, update_height);
99
100 gtk_widget_queue_draw_area (widget,
101 0, prev_height,
102 pp_width, update_height - prev_height);
103 return TRUE;
104 }
105 else
106 {
107 //update horizontally
108 if (hori_page_progress < 100)
109 {
110
111 hori_page_progress+=10;
112
113 int update_height = (int)(pp_height * (vert_page_progress / 100.0));
114 int update_width = (int)(pp_width * (hori_page_progress / 100.0));
115
116// gdk_draw_pixbuf (pixmap, pp_gc, pp_pbuf_image,
117// 0, update_height, 0, update_height, update_width, pp_height - update_height, GDK_RGB_DITHER_NONE, 0, 0);
118
119 gdk_draw_drawable (pixmap, pp_gc, buffer_pixmap,
120 0, update_height, 0, update_height, update_width, pp_height - update_height);
121
122 gtk_widget_queue_draw_area (widget,
123 0, update_height,
124 update_width, pp_height);
125
126 return TRUE;
127
128 }
129 else
130 {
131 //reset values
132// vert_page_progress = 0;
133// hori_page_progress = 0;
134 in_progress = FALSE;
135
136
137
138 return FALSE;
139 }
140 }
141 }
142
143 else
144 {
145
146 //reset values
147// vert_page_progress = 0;
148// hori_page_progress = 0;
149 in_progress = FALSE;
150 return FALSE;
151 }
152
153}
154
155
156/* Create a new backing pixmap of the appropriate size */
157static gboolean configure_event( GtkWidget *widget,
158 GdkEventConfigure *event,
159 gpointer folder_name )
160{
161
162// char *filename = "chopin_prelude_op45-a4/chopin_prelude_op45-a4-page00.tif";
163// char *filename = "page1.tif";
164
165 if (pixmap)
166 g_object_unref (pixmap);
167
168 pixmap = gdk_pixmap_new (widget->window,
169 widget->allocation.width,
170 widget->allocation.height,
171 -1);
172
173 buffer_pixmap = gdk_pixmap_new (widget->window,
174 widget->allocation.width,
175 widget->allocation.height,
176 -1);
177
178
179 gdk_draw_rectangle (pixmap,
180 widget->style->black_gc,
181 TRUE,
182 0, 0,
183 widget->allocation.width,
184 widget->allocation.height);
185
186
187 pp_gc = gdk_gc_new (pixmap);
188
189 //reset values
190 vert_page_progress = 0;
191 hori_page_progress = 0;
192 in_progress = TRUE;
193 load_show_page_immediate (widget, (char*)folder_name, 0);
194
195 return TRUE;
196}
197
198/* Redraw the screen from the backing pixmap */
199static gboolean expose_event( GtkWidget *widget,
200 GdkEventExpose *event )
201{
202 gdk_draw_drawable (widget->window,
203 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
204 pixmap,
205 event->area.x, event->area.y,
206 event->area.x, event->area.y,
207 event->area.width, event->area.height);
208
209 return FALSE;
210}
211
212
213
214
215#define min2(x,y) (x<y)?x:y
216#define max2(x,y) (x>y)?x:y
217//connecting line
218static void draw_connecting_line (GtkWidget *widget,
219 GdkPixmap *drawing_pixmap,
220 gdouble last_x,
221 gdouble last_y,
222 gdouble x,
223 gdouble y)
224{
225 //we are going to draw a line between two points instead of just drawing the next point
226 gdk_gc_set_line_attributes ( widget->style->black_gc,
227 2, GDK_LINE_SOLID,
228 GDK_CAP_BUTT, GDK_JOIN_ROUND);
229
230 gdk_draw_line ( drawing_pixmap,
231 widget->style->black_gc,
232 last_x, last_y,
233 x, y);
234
235 int x_min = min2(x, last_x);
236 int y_min = min2(y, last_y);
237 int x_max = max2(x, last_x);
238 int y_max = max2(y, last_y);
239
240 gtk_widget_queue_draw_area ( widget,
241 x_min - 2, y_min - 2,
242 x_max - x_min + 5, y_max - y_min + 5);
243}
244
245/* Draw a rectangle on the screen */
246static void draw_brush( GtkWidget *widget,
247 GdkPixmap *drawing_pixmap,
248 gdouble x,
249 gdouble y)
250{
251 GdkRectangle update_rect;
252
253 update_rect.x = x - 2;
254 update_rect.y = y - 2;
255 update_rect.width = 4;
256 update_rect.height = 4;
257 gdk_draw_rectangle (drawing_pixmap,
258 widget->style->black_gc,
259 TRUE,
260 update_rect.x, update_rect.y,
261 update_rect.width, update_rect.height);
262 gtk_widget_queue_draw_area (widget,
263 update_rect.x, update_rect.y,
264 update_rect.width, update_rect.height);
265}
266
267
268
269static gboolean file_exists (char *filename)
270{
271 //if NULL is returned then the file probably does not exist; return false
272 if (g_fopen(filename, "r") == NULL) return FALSE;
273 return TRUE;
274}
275
276static gboolean load_show_page( GtkWidget *widget,
277 char *folder_name,
278 int page_number)
279{
280
281
282 char filename[512];
283 sprintf(filename, "%s/%s-page%02d.tif", folder_name, folder_name, page_number);
284
285
286 g_print("%s\n\n", filename);
287
288
289// filename = "chopin_prelude_op45-a4/chopin_prelude_op45-a4-page01.tif";
290
291
292 if (!file_exists(filename)) return FALSE;
293
294
295 //get the percentage of page to load/display before swapping from vertical loading to horizontal loading
296 char filename_pagebreak[512];
297 sprintf (filename_pagebreak, "%s.pagebreak", filename);
298 if (file_exists(filename_pagebreak)) {
299 FILE *file = fopen(filename_pagebreak, "r");
300 char line_buf[10]; //shouldn't be longer than 2 characters, really
301 fgets(line_buf, 10, file);
302 change_height_percent = atoi ( line_buf );
303 }
304 else
305 {
306 change_height_percent = 80; //defaults to 80% if there is no pagebreak file
307 }
308 g_print("change_height_percent: %d\n", change_height_percent);
309
310
311
312 // Get the origial image size.
313 gdk_pixbuf_get_file_info(filename, &pp_width, &pp_height);
314 page_width = widget->allocation.width;
315 page_height = widget->allocation.height;
316
317 gdk_drawable_get_size(pixmap, &page_width, &page_height);
318
319//getting the scaled sizes to load the image in at fullscreen
320 int w = pp_width;
321 int h = pp_height;
322 double scale = 1;
323 if (pp_width >= pp_height)
324 {
325 if (pp_width != page_width)
326 {
327 scale = (double)pp_width / (double)page_width;
328 }
329 }
330 else if (pp_height > pp_width)
331 {
332 if (pp_height != page_height)
333 {
334 scale = (double)pp_height / (double)page_height;
335 }
336 }
337 w = (int)((double)pp_width / scale);
338 h = (int)((double)pp_height / scale)- 1;
339 pp_width = w;
340 pp_height = h;
341
342 pp_pbuf_image = gdk_pixbuf_new_from_file_at_size(filename, pp_width, pp_height, 0);
343
344 gdk_draw_pixbuf (buffer_pixmap, pp_gc, pp_pbuf_image,
345 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
346
347//drawing the point/scribble data onto the buffer pixmap
348 char point_filename[512];
349 sprintf(point_filename, "%s/%s-page%02d.tif.pointdata", folder_name, folder_name, page_number);
350 read_point_data_from_file(widget, buffer_pixmap, point_filename);
351
352
353
354
355 //pp_gc = gdk_gc_new (pixmap);
356
357
358
359
360 //reset values
361 vert_page_progress = 0;
362 hori_page_progress = 0;
363 timeout_id = g_timeout_add (1000, update_progress_page, widget);
364
365 return TRUE;
366
367}
368
369
370
371static gboolean load_show_page_immediate( GtkWidget *widget,
372 char *folder_name,
373 int page_number)
374{
375
376
377 char filename[512];
378 sprintf(filename, "%s/%s-page%02d.tif", folder_name, folder_name, page_number);
379
380
381 g_print("%s\n\n", filename);
382
383
384// filename = "chopin_prelude_op45-a4/chopin_prelude_op45-a4-page01.tif";
385
386
387 if (!file_exists(filename)) return FALSE;
388
389
390
391 // Get the origial image size.
392 gdk_pixbuf_get_file_info(filename, &pp_width, &pp_height);
393 page_width = widget->allocation.width;
394 page_height = widget->allocation.height;
395
396 gdk_drawable_get_size(pixmap, &page_width, &page_height);
397
398//getting the scaled sizes to load the image in at fullscreen
399 int w = pp_width;
400 int h = pp_height;
401 double scale = 1;
402 if (pp_width >= pp_height)
403 {
404 if (pp_width != page_width)
405 {
406 scale = (double)pp_width / (double)page_width;
407 }
408 }
409 else if (pp_height > pp_width)
410 {
411 if (pp_height != page_height)
412 {
413 scale = (double)pp_height / (double)page_height;
414 }
415 }
416 w = (int)((double)pp_width / scale);
417 h = (int)((double)pp_height / scale)- 1;
418 pp_width = w;
419 pp_height = h;
420
421 pp_pbuf_image = gdk_pixbuf_new_from_file_at_size(filename, pp_width, pp_height, 0);
422
423 //pp_gc = gdk_gc_new (pixmap);
424
425
426
427 //reset values
428 vert_page_progress = 0;
429 hori_page_progress = 0;
430
431
432
433
434
435 gdk_draw_pixbuf (buffer_pixmap, pp_gc, pp_pbuf_image,
436 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
437
438//drawing the point/scribble data onto the buffer pixmap
439 char point_filename[512];
440 sprintf(point_filename, "%s/%s-page%02d.tif.pointdata", folder_name, folder_name, page_number);
441 read_point_data_from_file(widget, buffer_pixmap, point_filename);
442
443
444
445//current
446
447
448 gdk_draw_drawable (pixmap, pp_gc, buffer_pixmap,
449 0, 0, 0, 0, -1, -1);
450
451// gdk_draw_pixbuf (pixmap, pp_gc, pp_pbuf_image, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
452
453 gtk_widget_queue_draw_area (widget,
454 0, 0,
455 pp_width, pp_height);
456
457
458
459
460
461// g_timeout_add (1000, update_progress_page, widget);
462
463 in_progress = FALSE;
464
465 return TRUE;
466
467}
468
469
470
471
472
473static gboolean write_point_data_to_file ( char *filename)
474{
475 FILE *file;
476 file = fopen(filename, "w+");
477
478 GList *curr = points_list;
479 while (curr != NULL)
480 {
481 g_print("writing: %s\n", (char*)curr->data);
482 fprintf(file, "%s\n", (char*)curr->data);
483 curr = g_list_next(curr);
484 }
485
486 fclose(file);
487
488 return TRUE;
489}
490
491static gboolean read_point_data_from_file (GtkWidget *widget,
492 GdkPixmap *drawing_pixmap,
493 char *filename)
494{
495 //reset points list
496 points_list = NULL;
497
498 FILE *file;
499 file = fopen(filename, "r+");
500 if (file == NULL)
501 {
502 g_print ("no point file data\n");
503 return FALSE;
504 }
505 int old_x_val, old_y_val, x_val, y_val;
506 gboolean start_line = TRUE;
507// while (feof(file) == 0)
508 g_print("gonna scan us some file: %s\n", filename);
509
510 while (fscanf(file, "%d %d\n", &x_val, &y_val) != EOF)
511 {
512 //add this data to the list of point data, ...
513 char *data = malloc(16);
514 if (data == NULL)
515 {
516 fprintf(stderr, "error (failed to allocate memory in button_press_event");
517 exit(-1);
518 }
519 sprintf (data, "%d %d", x_val, y_val);
520 points_list = g_list_append(points_list, data);
521
522 g_print("%s\n", data);
523//break;
524// fscanf(file, "%d %d\n", &x_val, &y_val);
525 if (x_val == -1) //then continue;
526 {
527 start_line = TRUE;
528 continue;
529 }
530 else if (start_line)
531 {
532 draw_brush(widget, drawing_pixmap, x_val, y_val);
533 old_x_val = x_val;
534 old_y_val = y_val;
535 }
536 else
537 {
538 draw_connecting_line (widget, drawing_pixmap, old_x_val, old_y_val, x_val, y_val);
539 old_x_val = x_val;
540 old_y_val = y_val;
541 }
542
543 start_line = FALSE;
544 }
545 fclose(file);
546 return TRUE;
547}
548
549
550static gboolean button_release_event( GtkWidget *widget,
551 GdkEventButton *event)
552{
553 g_print("mouse released\n");
554 last_x_pos = -1;
555 last_y_pos = -1;
556
557 //add this gap to the list of point data, ...
558 points_list = g_list_append(points_list, "-1 -1");
559
560 return TRUE;
561}
562
563
564static gboolean button_press_event( GtkWidget *widget,
565 GdkEventButton *event,
566 gpointer folder_name)
567{
568
569
570 if (event->button == 1 && pixmap != NULL)
571 {
572 if (!in_progress)
573 {
574 draw_brush (widget, pixmap, event->x, event->y);
575 last_x_pos = event->x;
576 last_y_pos = event->y;
577
578 //add this data to the list of point data, ...
579 char *data = malloc(16);
580 if (data == NULL)
581 {
582 fprintf(stderr, "error (failed to allocate memory in button_press_event");
583 exit(-1);
584 }
585 sprintf (data, "%d %d", (int)event->x, (int)event->y);
586 points_list = g_list_append(points_list, data);
587
588 //g_print("%x\n", folder_name);
589
590 //in_progress = TRUE;
591
592 //current_page += 1;
593 //load_show_page (widget, (char*)folder_name, current_page);
594 }
595 else
596 {
597 g_print("in progress so can't draw\n");
598 }
599 }
600
601 return TRUE;
602}
603
604
605static gboolean key_press_event( GtkWidget *widget,
606 GdkEventKey *event,
607 gpointer data_list)
608{
609
610if (event->type == GDK_KEY_RELEASE) return TRUE;
611
612GtkWidget *drawing_area = (GtkWidget*)g_list_nth_data(data_list, 0);
613char *folder_name = (char*)g_list_nth_data(data_list, 1);
614
615g_print("called keypress event\n");
616 if (!in_progress)
617 {
618 g_print("NOT inprogress\n");
619 //write the point data for this page to a file
620 char filename[512];
621 sprintf(filename, "%s/%s-page%02d.tif.pointdata", folder_name, folder_name, current_page);
622 g_print("writing to file: %s", filename);
623 write_point_data_to_file (filename);
624
625 switch (event->keyval)
626 {
627 case GDK_Right:
628 printf("right!\n");
629 prev_page = current_page;
630 current_page += 1;
631 break;
632 case GDK_Left:
633 printf("left!\n");
634 prev_page = current_page;
635 current_page -= 1;
636 break;
637 default:
638 return TRUE;
639 }
640 in_progress = TRUE;
641 load_show_page (drawing_area, folder_name, current_page);
642 }
643 else //in progress, so speed up that progress: load page immediately
644 {
645 g_print("in progress\n");
646 switch (event->keyval)
647 {
648 case GDK_Right:
649 g_source_remove(timeout_id);
650 if (current_page != prev_page+1)
651 {
652 current_page = prev_page;
653 }
654 load_show_page_immediate(drawing_area, folder_name, current_page);
655// printf("right!\n");
656// current_page += 1;
657 break;
658 case GDK_Left:
659 g_source_remove(timeout_id);
660 if (current_page != prev_page-1)
661 {
662 current_page = prev_page;
663 }
664 load_show_page_immediate(drawing_area, folder_name, current_page);
665// printf("left!\n");
666// current_page -= 1;
667 break;
668 default:
669 return TRUE;
670 }
671
672// load_show_page_immediate(drawing_area, folder_name, current_page);
673 }
674
675 return TRUE;
676}
677
678static gboolean motion_notify_event( GtkWidget *widget,
679 GdkEventMotion *event )
680{
681 int x, y;
682 GdkModifierType state;
683
684 if (event->is_hint)
685 gdk_window_get_pointer (event->window, &x, &y, &state);
686 else
687 {
688 x = event->x;
689 y = event->y;
690 state = event->state;
691 }
692
693 if (state & GDK_BUTTON1_MASK && pixmap != NULL)
694 {
695 if (!in_progress)
696 {
697 //if we haven't set x yet, don't do this
698 if (last_x_pos == -1) return TRUE;
699
700 draw_connecting_line (widget, pixmap, last_x_pos, last_y_pos, x, y);
701
702 last_x_pos = x;
703 last_y_pos = y;
704
705
706
707 //add this data to the list of point data, ...
708 char *data = malloc(16);
709 if (data == NULL)
710 {
711 fprintf(stderr, "error (failed to allocate memory in button_press_event");
712 exit(-1);
713 }
714 sprintf (data, "%d %d", (int)event->x, (int)event->y);
715 points_list = g_list_append(points_list, data);
716
717
718// draw_brush (widget, x, y);
719 }
720
721 }
722
723 return TRUE;
724}
725
726void quit ()
727{
728 exit (0);
729}
730
731int main( int argc,
732 char *argv[] )
733{
734
735char *folder_name;
736
737 if (argc == 1)
738 {
739 //default
740 folder_name = "chopin_prelude_op45-a4";
741 }
742 else
743 {
744 folder_name = argv[1];
745 }
746
747
748//************************************
749/*
750FILE *writing;
751//int buffer = 256;
752int value = 6;
753char *filename;
754filename = "file.txt";
755writing = fopen(filename, "w+");
756fprintf(writing, "%d\n", value);
757value = 7;
758fprintf(writing, "%d\n", value);
759value = 8;
760fprintf(writing, "%d\n", value);
761fclose(writing);
762
763int blah = 0;
764writing = fopen(filename, "r+");
765fscanf(writing, "%d\n", &blah);
766g_print("%d\n", blah);
767fscanf(writing, "%d\n", &blah);
768g_print("%d\n", blah);
769fscanf(writing, "%d\n", &blah);
770g_print("%d\n", blah);
771fclose(writing);
772*/
773//************************************
774
775
776 GtkWidget *window;
777 GtkWidget *drawing_area;
778 GtkWidget *vbox;
779
780 GtkWidget *button;
781
782 gtk_init (&argc, &argv);
783
784 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
785 gtk_widget_set_name (window, "Test Input");
786
787 vbox = gtk_vbox_new (FALSE, 0);
788 gtk_container_add (GTK_CONTAINER (window), vbox);
789 gtk_widget_show (vbox);
790
791 g_signal_connect (window, "destroy",
792 G_CALLBACK (quit), NULL);
793
794 /* Create the drawing area */
795
796 drawing_area = gtk_drawing_area_new ();
797 gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
798 gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
799
800 gtk_widget_show (drawing_area);
801
802 /* Signals used to handle backing pixmap */
803
804 g_signal_connect (drawing_area, "expose-event",
805 G_CALLBACK (expose_event), NULL);
806 g_signal_connect (drawing_area,"configure-event",
807 G_CALLBACK (configure_event), folder_name);
808
809 /* Event signals */
810
811 g_signal_connect (drawing_area, "motion-notify-event",
812 G_CALLBACK (motion_notify_event), NULL);
813 g_signal_connect (drawing_area, "button-press-event",
814 G_CALLBACK (button_press_event), folder_name);
815 g_signal_connect (drawing_area, "button-release-event",
816 G_CALLBACK (button_release_event), NULL);
817
818 //needs to be passed both the drawing_area, and the folder_name, so create a glist and pass a pointer to that
819 GList *key_press_data = NULL;
820 key_press_data = g_list_append(key_press_data, drawing_area);
821 key_press_data = g_list_append(key_press_data, folder_name);
822
823 g_signal_connect (window, "key-press-event",
824 G_CALLBACK (key_press_event), key_press_data);
825
826
827 gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
828 | GDK_LEAVE_NOTIFY_MASK
829 | GDK_BUTTON_PRESS_MASK
830 | GDK_BUTTON_RELEASE_MASK
831 | GDK_POINTER_MOTION_MASK
832 | GDK_POINTER_MOTION_HINT_MASK);
833
834 /* .. And a quit button */
835 button = gtk_button_new_with_label ("Quit");
836 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
837
838 g_signal_connect_swapped (button, "clicked",
839 G_CALLBACK (gtk_widget_destroy),
840 window);
841 gtk_widget_show (button);
842
843 gtk_widget_show (window);
844
845 gtk_main ();
846
847 return 0;
848}
Note: See TracBrowser for help on using the repository browser.