1 /* pisa_preview_window.cc
2    Copyright (C) 2001, 2004, 2005, 2008  SEIKO EPSON Corporation
3 
4    This file is part of the `iscan' program.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 
20    As a special exception, the copyright holders give permission
21    to link the code of this program with the esmod library and
22    distribute linked combinations including the two.  You must obey
23    the GNU General Public License in all respects for all of the
24    code used other then esmod.
25 */
26 
27 /*------------------------------------------------------------*/
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 /*------------------------------------------------------------*/
33 #include "pisa_view_manager.h"
34 #include "pisa_preview_window.h"
35 #include "pisa_error.h"
36 #include "pisa_scan_tool.h"
37 #include "pisa_tool.h"
38 #include "pisa_default_val.h"
39 #include "pisa_aleart_dialog.h"
40 #include "pisa_change_unit.h"
41 
42 /*------------------------------------------------------------*/
43 long g_prev_max_x		= 320;
44 long g_prev_max_y		= 440;
45 
46 const double g_min_marq_size	= 0.4;
47 
48 /*------------------------------------------------------------*/
expose_event(GtkWidget * widget,GdkEventExpose * event)49 static gint expose_event ( GtkWidget * widget,
50 			   GdkEventExpose * event )
51 {
52   preview_window	* prev_cls;
53 
54   prev_cls = ( preview_window * ) ::g_view_manager->get_window_cls ( ID_WINDOW_PREV );
55 
56   return prev_cls->expose_event ( widget, event );
57 }
58 
59 
60 /*------------------------------------------------------------*/
event(GtkWidget * widget,GdkEvent * event)61 static gint event ( GtkWidget * widget,
62 		    GdkEvent * event )
63 {
64   preview_window	* prev_cls;
65 
66   prev_cls = ( preview_window * ) ::g_view_manager->get_window_cls ( ID_WINDOW_PREV );
67 
68   return prev_cls->event ( widget, event );
69 }
70 
71 /*------------------------------------------------------------*/
size_allocate(GtkWidget * widget)72 static void size_allocate ( GtkWidget * widget )
73 {
74   preview_window	* prev_cls;
75 
76   prev_cls = ( preview_window * ) ::g_view_manager->get_window_cls ( ID_WINDOW_PREV );
77 
78   prev_cls->size_allocate ( widget );
79 }
80 
81 /*------------------------------------------------------------*/
init(void)82 int preview_window::init ( void )
83 {
84   int	i;
85 
86   m_gc		= 0;
87 
88   m_img_width	= g_prev_max_x;
89   m_img_height	= g_prev_max_y;
90 
91   m_is_prev	= 0;
92   m_drag	= 0;
93 
94   m_img		= new unsigned char [ g_prev_max_x * g_prev_max_y * 3 ];
95 
96   if ( m_img == 0 )
97     return PISA_ERR_OUTOFMEMORY;
98 
99   m_img_org	= new unsigned char [ g_prev_max_x * g_prev_max_y * 3 ];
100 
101   if ( m_img_org == 0 )
102     {
103       delete [ ] m_img;
104       m_img = 0;
105       return PISA_ERR_OUTOFMEMORY;
106     }
107 
108   for ( i = 0; i < 11; i++ )
109     m_cursor [ i ] = 0;
110 
111   m_on_preview = false;
112   m_allocate_width = 0;
113   m_allocate_height = 0;
114 
115   return PISA_ERR_SUCCESS;
116 }
117 
118 /*------------------------------------------------------------*/
create_window(GtkWidget * parent)119 GtkWidget * preview_window::create_window ( GtkWidget * parent )
120 {
121   m_win = create_darea ( parent );
122 
123   create_cursor ( );
124 
125   return m_win;
126 }
127 
128 /*------------------------------------------------------------*/
close_window(int destroy)129 int preview_window::close_window ( int destroy )
130 {
131   destroy = destroy;
132 
133   if ( m_gc )
134     {
135       ::gdk_gc_destroy ( m_gc );
136       m_gc = 0;
137     }
138 
139   if ( m_img )
140     {
141       delete [ ] m_img;
142       m_img = 0;
143     }
144 
145   if ( m_img_org )
146     {
147       delete [ ] m_img_org;
148       m_img_org = 0;
149     }
150 
151   return PISA_ERR_SUCCESS;
152 }
153 
154 /*------------------------------------------------------------*/
resize_window(void)155 int preview_window::resize_window ( void )
156 {
157   get_preview_resolution ( );
158   resize_preview_window ( 0, 0 );
159 
160   clear_image ( );
161 
162   return 0;
163 }
164 
165 /*------------------------------------------------------------*/
auto_exposure(void)166 int preview_window::auto_exposure ( void )
167 {
168   pisa_image_info	info;
169   _rectL		region;
170   marquee		tmp_marq, * marq;
171   int			i, marq_num;
172 
173   scan_manager	*scan_mgr = g_view_manager->get_scan_manager ();
174 
175   if ( m_is_prev == 0 ||
176        g_view_manager->get_settings ().imgtype.pixeltype == PISA_PT_BW )
177     {
178       return PISA_ERR_SUCCESS;
179     }
180 
181   info.m_img	= m_img_org;
182   info.m_width	= m_img_width;
183   info.m_height	= m_img_height;
184   info.m_rowbytes = g_prev_max_x * 3;
185 
186   marq_num = g_view_manager->get_marquee_size ();
187   marq = & g_view_manager->get_marquee ();
188 
189   if ( marq_num < 2 )
190     {
191       region.left	= 0;
192       region.top	= 0;
193       region.right	= m_img_width - 1;
194       region.bottom	= m_img_height - 1;
195     }
196   else
197     {
198       _pointL pt_lt, pt_rb;
199 
200       get_marquee_point ( marq_num - 1, & pt_lt, & pt_rb );
201 
202       region.left	= pt_lt.x;
203       region.top	= pt_lt.y;
204       region.right	= pt_rb.x;
205       region.bottom	= pt_rb.y;
206     }
207 
208   settings set = g_view_manager->get_settings ();
209   iscan::auto_expose (set.option,
210 		      set.film,
211 		      & info,
212 		      & region,
213 		      & tmp_marq,
214 		      set.imgtype.ae_option != PISA_AE_DOC,
215 		      scan_mgr->is_dumb ());
216 
217   marq->gamma		= tmp_marq.gamma;
218   marq->highlight	= tmp_marq.highlight;
219   marq->shadow		= tmp_marq.shadow;
220   marq->graybalance	= tmp_marq.graybalance;
221 
222   for ( i = 0; i < 3; i++ )
223     {
224       marq->film_gamma [ i ]	= tmp_marq.film_gamma [ i ];
225       marq->film_yp [ i ]	= tmp_marq.film_yp [ i ];
226       marq->grayl [ i ]		= tmp_marq.grayl [ i ];
227     }
228 
229   ::g_view_manager->sensitive ( );
230   ::g_view_manager->update_lut ( );
231 
232   return PISA_ERR_SUCCESS;
233 }
234 
235 /*------------------------------------------------------------*/
update_img(bool left)236 int preview_window::update_img ( bool left )
237 {
238   int			i;
239   pisa_image_info	img_info;
240   marquee		* marq;
241   double                delta;
242   long                  curr_width, adj_width, resolution;
243 
244   if ( m_is_prev == 0 )
245     {
246       clear_image ( );
247       return PISA_ERR_SUCCESS;
248     }
249 
250   settings set = g_view_manager->get_settings ();
251   marq = & g_view_manager->get_marquee ();
252 
253   resolution = (set.resolution * (marq->scale)) / 100;
254   curr_width = ::inch2pixel ( marq->area.x, resolution );
255   adj_width  = ::inch2width ( marq->area.x, resolution );
256   delta      = marq->area.x - (marq->area.x) * adj_width /curr_width ;
257 
258   // Resize the area
259   marq -> area.x -= delta;
260   if ( left )
261     {
262       // If the left side -> increase the x offset
263       marq ->offset.x += delta;
264     }
265 
266   if ( m_img == 0 || m_img_org == 0 )
267     return PISA_ERR_OUTOFMEMORY;
268 
269   ::memcpy ( m_img, m_img_org, g_prev_max_x * g_prev_max_y * 3 );
270 
271   img_info.m_img	= m_img;
272   img_info.m_width	= m_img_width;
273   img_info.m_height	= m_img_height;
274   img_info.m_rowbytes	= g_prev_max_x * 3;
275 
276   ::tool_lut ( & img_info, & marq->lut );
277 
278   switch (set.imgtype.pixeltype)
279     {
280     case PISA_PT_RGB:
281       tool_matrix (&img_info, marq->saturation, set.coef);
282       if (set.usm)
283 	tool_usm (img_info);
284       break;
285 
286     case PISA_PT_GRAY:
287       build_gray (&img_info, set.imgtype.dropout);
288       if (set.usm)
289 	tool_usm (img_info);
290       break;
291 
292     case PISA_PT_BW:
293       build_bw (&img_info,
294 		set.imgtype.dropout,
295 		set.imgtype.halftone,
296 		marq->threshold);
297       break;
298     }
299 
300   for ( i = 0; i < m_img_height; i++ )
301     ::gtk_preview_draw_row ( GTK_PREVIEW ( m_prev ),
302 			     m_img + i * g_prev_max_x * 3,
303 			     0, i, m_img_width );
304 
305   ::gtk_widget_draw ( m_prev, 0 );
306   ::gdk_flush ( );
307 
308   return PISA_ERR_SUCCESS;
309 }
310 
311 /*--------------------------------------------------------------*/
start_preview(pisa_preview_type type)312 void preview_window::start_preview ( pisa_preview_type type )
313 {
314   scan_manager		* scan_mgr;
315   int			width, height;
316   int			cancel;
317 
318   cancel = 0;
319 
320   m_is_prev = 0;
321 
322   m_on_preview = true;
323   m_allocate_width = 0;
324   m_allocate_height = 0;
325 
326   progress_window feedback
327     (static_cast <main_window *> (g_view_manager
328 				  ->get_window_cls (ID_WINDOW_MAIN))
329      ->get_widget());
330   feedback.set_text (progress_window::WARMING_UP);
331   feedback.show ();
332 
333   while ( ::gtk_events_pending ( ) )
334     ::gtk_main_iteration ( );
335 
336   // preview
337   scan_mgr = g_view_manager->get_scan_manager ( );
338   set_preview_param (type);
339 
340   reset_settings ( type );
341   ::g_view_manager->sensitive ( );
342 
343   try
344     {
345       scan_mgr->init_scan (&width, &height);
346 
347       if ( type == PISA_PREV_WHOLE )
348 	{
349 	  change_max_scan_area ( width, height );
350 	  ::g_view_manager->sensitive ( );
351 	}
352 
353       resize_preview_window ( width, height );
354       clear_image ( );
355 
356       while ( ::gtk_events_pending ( ) )
357 	::gtk_main_iteration ( );
358 
359       for (int i = 0; i < height; i++ )
360 	{
361 	  scan_mgr->acquire_image ( m_img_org + i * g_prev_max_x * 3,
362 				    width * 3,
363 				    1,
364 				    cancel );
365 
366 	  if ( i == 0 )
367 	    feedback.set_text (progress_window::PREVIEWING);
368 
369 	  if (cancel)
370 	    break;
371 
372 	  feedback.set_progress (i, height);
373 	  cancel = feedback.is_cancelled ();
374 
375 	  ::gtk_preview_draw_row ( GTK_PREVIEW ( m_prev ),
376 				   m_img_org + i * g_prev_max_x * 3,
377 				   0, i, width );
378 	  if ( i % 20 == 0 )
379 	    {
380 	      ::gtk_preview_put ( GTK_PREVIEW ( m_prev ),
381 				  m_prev->window,
382 				  m_prev->style->black_gc,
383 				  0, 0, 0, 0, width, height );
384 	    }
385 
386 	  while ( ::gtk_events_pending ( ) )
387 	    ::gtk_main_iteration ( );
388 	}
389       feedback.set_progress (height, height);
390       cancel = feedback.is_cancelled ();
391       if (cancel)
392 	{
393 	  m_on_preview = false;
394 	  update_img ( );
395 	  change_max_disp_area ( m_allocate_width, m_allocate_height );
396 	  m_allocate_width = 0;
397 	  m_allocate_height = 0;
398 	}
399       else
400 	{
401 	  m_is_prev = 1;
402 	  ::gtk_widget_draw ( m_prev, 0 );
403 	  ::gdk_flush ( );
404 
405 	  m_on_preview = false;
406 
407 	  auto_exposure ( );
408 	  update_img ( );
409 	  change_max_disp_area ( m_allocate_width, m_allocate_height );
410 	  m_allocate_width = 0;
411 	  m_allocate_height = 0;
412 	}
413     }
414   catch ( const pisa_error & err )
415     {
416       main_window * main_cls;
417       aleart_dialog aleart_dlg;
418 
419       main_cls = ( main_window * ) ::g_view_manager->get_window_cls ( ID_WINDOW_MAIN );
420       aleart_dlg.message_box ( main_cls->get_widget ( ),
421 			      err.get_error_string ( ) );
422 
423       delete_marquee ( );
424 
425       m_on_preview = false;
426       update_img ( );
427       change_max_disp_area ( m_allocate_width, m_allocate_height );
428       m_allocate_width = 0;
429       m_allocate_height = 0;
430     }
431 
432   scan_mgr->finish_acquire ( );
433 
434   ::g_view_manager->sensitive ( );
435 
436   {
437     gint x, y;
438     ::gdk_window_get_pointer ( m_prev->window, & x, & y, 0 );
439     set_mouse_cursor ( x, y );
440     change_cursor ( );
441   }
442 }
443 
444 /*--------------------------------------------------------------*/
expose_event(GtkWidget * widget,GdkEventExpose * event)445 gint preview_window::expose_event ( GtkWidget * widget,
446 				    GdkEventExpose * event )
447 {
448   widget = widget;
449   event = event;
450 
451   draw_marquee ( );
452 
453   return FALSE;
454 }
455 
456 /*--------------------------------------------------------------*/
event(GtkWidget * widget,GdkEvent * event)457 gint preview_window::event ( GtkWidget * widget, GdkEvent * event )
458 {
459   gint	ret;
460 
461   widget = widget;
462 
463   switch ( event->type )
464     {
465     case GDK_EXPOSE:
466       if ( m_gc )
467 	{
468 	  draw_marquee ( );
469 	}
470       ret = FALSE;
471       break;
472 
473     case GDK_BUTTON_PRESS:
474       ret = mouse_down ( event );
475       ::gtk_grab_add ( widget );
476       break;
477 
478     case GDK_MOTION_NOTIFY:
479       ret = mouse_move ( event );
480       break;
481 
482     case GDK_BUTTON_RELEASE:
483       ret = mouse_up ( event );
484       ::gtk_grab_remove ( widget );
485       break;
486 
487     default:
488       ret = TRUE;
489       break;
490     }
491 
492   return ret;
493 }
494 
495 /*------------------------------------------------------------*/
size_allocate(GtkWidget * widget)496 void preview_window::size_allocate ( GtkWidget * widget )
497 {
498   int x, y;
499 
500   x = widget->allocation.width;
501   y = widget->allocation.height;
502 
503   if ( m_on_preview )
504     {
505       m_allocate_width = x;
506       m_allocate_height = y;
507       return;
508     }
509 
510   change_max_disp_area ( x, y );
511 }
512 
513 
514 /*------------------------------------------------------------*/
create_darea(GtkWidget * parent)515 GtkWidget * preview_window::create_darea ( GtkWidget * parent )
516 {
517   GtkWidget	* frame;
518 
519   parent = parent;
520 
521   frame = ::gtk_frame_new ( 0 );
522   ::gtk_frame_set_shadow_type ( GTK_FRAME ( frame ), GTK_SHADOW_IN );
523   ::gtk_container_border_width ( GTK_CONTAINER ( frame ), 3 );
524 
525   m_prev = ::gtk_preview_new ( GTK_PREVIEW_COLOR );
526   ::gtk_preview_set_expand ( GTK_PREVIEW ( m_prev ), TRUE );
527 
528   // set size of preview window
529   get_preview_resolution ( );
530   resize_preview_window ( m_img_width, m_img_height );
531 
532   ::gtk_container_add ( GTK_CONTAINER ( frame ), m_prev );
533   ::gtk_widget_show ( m_prev );
534 
535   clear_image ( );
536 
537   // signals
538   ::gtk_signal_connect ( GTK_OBJECT ( m_prev ), "event",
539 			 GTK_SIGNAL_FUNC ( ::event ), 0 );
540   ::gtk_signal_connect_after ( GTK_OBJECT ( m_prev ), "expose_event",
541 			       GTK_SIGNAL_FUNC ( ::expose_event ), 0 );
542   ::gtk_signal_connect_after ( GTK_OBJECT ( m_prev ), "size_allocate",
543 			       GTK_SIGNAL_FUNC ( ::size_allocate ), 0 );
544 
545   ::gtk_widget_set_events ( m_prev ,
546   			  GDK_EXPOSURE_MASK |
547   			  GDK_LEAVE_NOTIFY_MASK |
548   			  GDK_BUTTON_PRESS_MASK |
549   			  GDK_POINTER_MOTION_MASK |
550   			  GDK_POINTER_MOTION_HINT_MASK |
551 			  GDK_BUTTON_RELEASE_MASK );
552 
553   return frame;
554 }
555 
556 
557 /*------------------------------------------------------------*/
get_preview_resolution(const _rectD * img_rect)558 long preview_window::get_preview_resolution ( const _rectD * img_rect )
559 {
560   long		resolution;
561   _pointD	pt_scan_size;
562   double	aspect_max;
563   double	aspect_scan;
564 
565   if ( img_rect )
566     {
567       pt_scan_size.x = img_rect->right - img_rect->left;
568       pt_scan_size.y = img_rect->bottom - img_rect->top;
569       m_img_rect = * img_rect;
570     }
571   else
572     {
573       pt_scan_size.x = g_view_manager->get_settings ().max_area [ 0 ];
574       pt_scan_size.y = g_view_manager->get_settings ().max_area [ 1 ];
575 
576       m_img_rect.left	= 0.0;
577       m_img_rect.top	= 0.0;
578       m_img_rect.right	= pt_scan_size.x;
579       m_img_rect.bottom	= pt_scan_size.y;
580     }
581 
582   aspect_max = ( float ) g_prev_max_y / g_prev_max_x;
583   aspect_scan = ( float ) pt_scan_size.y / pt_scan_size.x;
584 
585   if ( aspect_max < aspect_scan )
586     resolution = ( long ) ( g_prev_max_y / pt_scan_size.y );
587   else
588     resolution = ( long ) ( g_prev_max_x / pt_scan_size.x );
589 
590   m_img_width	= ( long ) ( resolution * pt_scan_size.x );
591   m_img_height	= ( long ) ( resolution * pt_scan_size.y );
592 
593   return resolution;
594 }
595 
596 /*------------------------------------------------------------*/
resize_preview_window(long width,long height)597 void preview_window::resize_preview_window ( long width, long height )
598 {
599   if ( width != 0 && height != 0 )
600     {
601       m_img_width = width;
602       m_img_height = height;
603     }
604 
605   if ( m_img )
606     {
607       delete [ ] m_img;
608       m_img = new unsigned char [ g_prev_max_x * g_prev_max_y * 3 ];
609     }
610 
611   if ( m_img_org )
612     {
613       delete [ ] m_img_org;
614       m_img_org = new unsigned char [ g_prev_max_x * g_prev_max_y * 3 ];
615     }
616 
617   m_client_rect.left	= 0;
618   m_client_rect.top	= 0;
619   m_client_rect.right	= m_img_width - 1;
620   m_client_rect.bottom	= m_img_height - 1;
621 
622   modify_max_val ( );
623 }
624 
625 /*------------------------------------------------------------*/
change_max_scan_area(long width,long height)626 void preview_window::change_max_scan_area ( long width, long height )
627 {
628   _pointD	pt_scan_size;
629   marquee	* marq;
630 
631   if ( m_img_width < width || m_img_height < height )
632     return;
633 
634   marq = & g_view_manager->get_marquee ();
635 
636   pt_scan_size.x = g_view_manager->get_settings ().max_area [ 0 ];
637   pt_scan_size.y = g_view_manager->get_settings ().max_area [ 1 ];
638 
639   m_img_rect.left	= 0.0;
640   m_img_rect.top	= 0.0;
641   m_img_rect.right	= pt_scan_size.x * width / m_img_width;
642   m_img_rect.bottom	= pt_scan_size.y * height / m_img_height;
643 
644   marq->area.x = m_img_rect.right;
645   marq->area.y = m_img_rect.bottom;
646 }
647 
648 /*------------------------------------------------------------*/
change_max_disp_area(long width,long height)649 void preview_window::change_max_disp_area ( long width, long height )
650 {
651   long	save_prev_x, save_prev_y;
652   long	save_img_width, save_img_height;
653   unsigned char * save_img_org;
654   _rectD tmp_rect;
655 
656   if ( width < 1 && height < 1 )
657     return;
658 
659   if ( g_prev_max_x == width && g_prev_max_y == height )
660     return;
661 
662   tmp_rect = m_img_rect;
663 
664   if ( m_is_prev == 0 )
665     {
666       g_prev_max_x = width;
667       g_prev_max_y = height;
668 
669       get_preview_resolution ( & tmp_rect );
670       resize_preview_window ( 0, 0 );
671 
672       clear_image ( );
673 
674       return;
675     }
676 
677   // save old parameter and image
678   save_prev_x		= g_prev_max_x;
679   save_prev_y		= g_prev_max_y;
680   save_img_width	= m_img_width;
681   save_img_height	= m_img_height;
682   save_img_org = new unsigned char [ save_prev_x * save_prev_y * 3 ];
683 
684   if ( save_img_org )
685     {
686       ::memcpy ( save_img_org, m_img_org, save_prev_x * save_prev_y * 3 );
687     }
688 
689   // resize
690   g_prev_max_x = width;
691   g_prev_max_y = height;
692 
693   get_preview_resolution ( & tmp_rect );
694   resize_preview_window ( 0, 0 );
695 
696   clear_image ( );
697   m_is_prev = 1;
698 
699   // restore image
700   if ( save_img_org )
701     {
702       struct resize_img_info parms;
703 
704       parms.in_width = save_img_width;
705       parms.in_height = save_img_height;
706       parms.in_rowbytes = save_prev_x * 3;
707       parms.out_width = m_img_width;
708       parms.out_height = m_img_height;
709       parms.out_rowbytes = g_prev_max_x * 3;
710       parms.bits_per_pixel = 24;
711       parms.resize_flag = PISA_RS_BL;
712       parms.resolution = 0;	// just to make sure it's set
713 
714       iscan::scale f (parms);
715 
716       f.exec (save_img_org, parms.in_height  * parms.in_rowbytes,
717 	      m_img_org, parms.out_height * parms.out_rowbytes);
718 
719       delete [] save_img_org;
720     }
721 
722   update_img ( );
723 }
724 
725 /*------------------------------------------------------------*/
clear_image(void)726 void preview_window::clear_image ( void )
727 {
728   int	i;
729 
730   m_is_prev = 0;
731 
732   ::memset ( m_img, 0xff, m_img_width * 3 );
733   ::memset ( m_img + ( m_img_width * 3 ),
734 	     0xC4,
735 	     ( g_prev_max_x - m_img_width ) * 3 );
736 
737   for ( i = 0; i < m_img_height; i++ )
738     ::gtk_preview_draw_row ( GTK_PREVIEW ( m_prev ), m_img,
739   			     0, i, g_prev_max_x );
740 
741   ::memset ( m_img, 0xC4, g_prev_max_x * 3 );
742 
743   for ( ; i < g_prev_max_y; i++ )
744     ::gtk_preview_draw_row ( GTK_PREVIEW ( m_prev ), m_img,
745 			     0, i, g_prev_max_x );
746 
747   ::gtk_widget_draw ( m_prev, 0 );
748   ::gdk_flush ( );
749 }
750 
751 
752 /*--------------------------------------------------------------*/
draw_marquee(void)753 void preview_window::draw_marquee ( void )
754 {
755   long		i, marq_num;
756   _pointL	pt_lefttop, pt_rightbottom;
757 
758   if ( m_gc == 0 )
759     {
760       m_gc = ::gdk_gc_new ( m_prev->window );
761       ::gdk_gc_set_function ( m_gc, GDK_INVERT );
762       ::gdk_gc_set_line_attributes ( m_gc, 1, GDK_LINE_ON_OFF_DASH,
763 				     GDK_CAP_BUTT, GDK_JOIN_MITER );
764     }
765 
766   marq_num = g_view_manager->get_settings ().get_marquee_size ( );
767 
768   if ( marq_num < 2 || m_on_preview )
769     return;
770 
771   for ( i = 1; i < marq_num; i++ )
772     {
773       get_marquee_point ( i, & pt_lefttop, & pt_rightbottom );
774 
775       draw_rect ( pt_lefttop, pt_rightbottom );
776     }
777 }
778 
779 /*--------------------------------------------------------------*/
reset_settings(pisa_preview_type type)780 void preview_window::reset_settings ( pisa_preview_type type )
781 {
782   long		i, n, m, marq_num;
783   marquee	* marq;
784   gamma_correction * gamma_cls;
785   scan_manager	* scan_mgr;
786 
787   gamma_cls = ( gamma_correction * ) ::g_view_manager->get_window_cls ( ID_WINDOW_GAMMA );
788 
789   scan_mgr = g_view_manager->get_scan_manager ();
790   marq_num = g_view_manager->get_marquee_size ();
791 
792   if ( type == PISA_PREV_WHOLE )
793     {
794       while ( 1 < marq_num )
795 	{
796 	  g_view_manager->del_marquee (marq_num - 1);
797 	  marq_num = g_view_manager->get_marquee_size ();
798 	}
799 
800       gamma_cls->reset ( 1 );
801     }
802 
803   marq_num = g_view_manager->get_marquee_size ();
804 
805   for ( i = 0; i < marq_num; i++ )
806     {
807       marq = & g_view_manager->get_marquee (i);
808 
809       if ( type == PISA_PREV_WHOLE )
810 	{
811 	  marq->gamma		= ( long ) ( 100 * DEFGAMMA );
812 	  marq->highlight	= DEFHIGHLIGHT;
813 	  marq->shadow		= DEFSHADOW;
814 	  marq->threshold	= DEFTHRESHOLD;
815 
816 	  for ( n = 0; n < 4; n++ )
817 	    for ( m = 0; m < 256; m++ )
818 	      marq->gamma_table [ n ] [ m ] = m;
819 
820 	  marq->graybalance	= DEFGRAYBALANCE;
821 	  marq->saturation	= DEFSATURATION;
822 	}
823 
824       for ( n = 0; n < 3; n++ )
825 	{
826 	  marq->film_gamma [ n ]	= 1.0;
827 	  marq->film_yp [ n ]		= 0.0;
828 	  marq->grayl [ n ]		= 0.0;
829 	}
830 
831       iscan::build_LUT (const_cast <settings *> (&g_view_manager
832 						 ->get_settings ()),
833 			marq, scan_mgr->is_dumb ());
834     }
835 }
836 
837 int
set_preview_param(pisa_preview_type type)838 preview_window::set_preview_param (pisa_preview_type type)
839 {
840   settings set = g_view_manager->get_settings ();
841   marquee marq;
842 
843   if (PISA_PREV_WHOLE == type)
844     {
845       marq.offset.x	= 0.0;
846       marq.offset.y	= 0.0;
847       marq.area.x	= set.max_area[0];
848       marq.area.y	= set.max_area[1];
849     }
850   else
851     {
852       float rate = 0.1f;
853       _pointD pt_offset, pt_area, pt_max;
854 
855       marquee cur_marq = g_view_manager->get_marquee ();
856 
857       marq.focus = cur_marq.focus;
858 
859       pt_offset	= cur_marq.offset;
860       pt_area	= cur_marq.area;
861 
862       marquee whole_marq = g_view_manager->get_marquee (0);
863 
864       pt_max.x = whole_marq.area.x;
865       pt_max.y = whole_marq.area.y;
866 
867       zoom_boundary (pt_offset, pt_area, pt_max, rate);
868 
869       marq.offset.x	= pt_offset.x;
870       marq.offset.y	= pt_offset.y;
871       marq.area.x	= pt_area.x;
872       marq.area.y	= pt_area.y;
873     }
874 
875   _rectD	img_rect;
876   img_rect.left		= marq.offset.x;
877   img_rect.top		= marq.offset.y;
878   img_rect.right	= marq.offset.x + marq.area.x;
879   img_rect.bottom	= marq.offset.y + marq.area.y;
880 
881   long resolution = get_preview_resolution (&img_rect);
882 
883   pisa_error_id err = (g_view_manager->get_scan_manager ()
884 		       ->set_scan_parameters (set, marq, type, resolution));
885 
886   return err;
887 }
888 
889 /*------------------------------------------------------------*/
tool_usm(const pisa_image_info & info)890 void preview_window::tool_usm (const pisa_image_info& info)
891 {
892   iscan::focus f (info);
893 
894   f.exec (info.m_img, info.m_height * info.m_rowbytes,
895 	  info.m_img, info.m_height * info.m_rowbytes);
896 }
897 
898 void
zoom_boundary(_pointD & pt_offset,_pointD & pt_area,const _pointD & pt_max,float rate) const899 preview_window::zoom_boundary (_pointD& pt_offset, _pointD& pt_area,
900 			       const _pointD& pt_max, float rate) const
901 {
902   _pointD pt_result_offset, pt_result_area;
903   double bound_size;
904 
905   if (pt_area.x < pt_area.y)
906     bound_size = pt_area.y * rate;
907   else
908     bound_size = pt_area.x * rate;
909 
910   bound_size = (0.0 == bound_size) ? 0.01 : bound_size;
911 
912   // left
913   pt_result_offset.x = pt_offset.x - bound_size;
914   if (0.0 > pt_result_offset.x)
915     pt_result_offset.x = 0.0;
916 
917   // top
918   pt_result_offset.y = pt_offset.y - bound_size;
919   if (0.0 > pt_result_offset.y)
920     pt_result_offset.y = 0.0;
921 
922   // right
923   pt_result_area.x = ((pt_offset.x - pt_result_offset.x) +
924 		      pt_area.x + bound_size);
925   if (pt_max.x < pt_result_offset.x + pt_result_area.x)
926     pt_result_area.x = pt_max.x - pt_result_offset.x;
927 
928   // bottom
929   pt_result_area.y = ((pt_offset.y - pt_result_offset.y) +
930 		      pt_area.y + bound_size);
931   if (pt_max.y < pt_result_offset.y + pt_result_area.y)
932     pt_result_area.y = pt_max.y - pt_result_offset.y;
933 
934   pt_offset = pt_result_offset;
935   pt_area   = pt_result_area;
936 }
937 
938 /*--------------------------------------------------------------*/
create_cursor(void)939 void preview_window::create_cursor ( void )
940 {
941   m_cursor [ PISA_CS_ARROW       ] = ::gdk_cursor_new ( GDK_ARROW               );
942   m_cursor [ PISA_CS_HAND        ] = ::gdk_cursor_new ( GDK_HAND2               );
943   m_cursor [ PISA_CS_CROSS       ] = ::gdk_cursor_new ( GDK_CROSS               );
944   m_cursor [ PISA_CS_TOP         ] = ::gdk_cursor_new ( GDK_TOP_SIDE            );
945   m_cursor [ PISA_CS_BOTTOM      ] = ::gdk_cursor_new ( GDK_BOTTOM_SIDE         );
946   m_cursor [ PISA_CS_LEFT        ] = ::gdk_cursor_new ( GDK_LEFT_SIDE           );
947   m_cursor [ PISA_CS_RIGHT       ] = ::gdk_cursor_new ( GDK_RIGHT_SIDE          );
948   m_cursor [ PISA_CS_LEFTTOP     ] = ::gdk_cursor_new ( GDK_TOP_LEFT_CORNER     );
949   m_cursor [ PISA_CS_LEFTBOTTOM  ] = ::gdk_cursor_new ( GDK_BOTTOM_LEFT_CORNER  );
950   m_cursor [ PISA_CS_RIGHTTOP    ] = ::gdk_cursor_new ( GDK_TOP_RIGHT_CORNER    );
951   m_cursor [ PISA_CS_RIGHTBOTTOM ] = ::gdk_cursor_new ( GDK_BOTTOM_RIGHT_CORNER );
952 }
953 
954 
955 /*--------------------------------------------------------------*/
set_mouse_cursor(int x,int y)956 int preview_window::set_mouse_cursor ( int x, int y )
957 {
958   const	long ADDSIZE = 3;
959   long marq_num;
960   _pointL pt_lefttop, pt_rightbottom;
961   int cursor_state;
962   _pointL pt;
963   int pt_in_cur_marq;
964   _rectL judge_rect;
965   _pointL pt_lt, pt_rb;
966   int i;
967 
968   if ( m_drag == 1 )
969     return FALSE;
970 
971   pt.x = x;
972   pt.y = y;
973 
974   if ( 0 == ::pt_in_rect ( m_client_rect, pt ) )
975     {
976       m_cursor_state = PISA_CS_ARROW;
977       return FALSE;
978     }
979 
980   marq_num = g_view_manager->get_settings ().get_marquee_size ( );
981 
982   if ( marq_num < 2 )
983     {
984       m_cursor_state = PISA_CS_CROSS;
985       return FALSE;
986     }
987 
988   get_marquee_point ( marq_num - 1, & pt_lefttop, & pt_rightbottom );
989 
990   cursor_state = search_cursor_state ( pt_lefttop, pt_rightbottom, pt );
991   if ( cursor_state != PISA_CS_CROSS )
992     {
993       m_cursor_state = cursor_state;
994       return FALSE;
995     }
996 
997   judge_rect.left	= pt_lefttop.x;
998   judge_rect.right	= pt_rightbottom.x;
999   judge_rect.top	= pt_lefttop.y;
1000   judge_rect.bottom	= pt_rightbottom.y;
1001   if ( pt_in_rect ( judge_rect, pt ) )
1002     pt_in_cur_marq = 1;
1003   else
1004     pt_in_cur_marq = 0;
1005 
1006   for ( i = marq_num - 1; 0 < i; i-- )
1007     {
1008       if ( marq_num - 1 == i )
1009 	continue;
1010 
1011       get_marquee_point ( i, & pt_lt, & pt_rb );
1012 
1013       if ( pt_in_cur_marq )
1014 	{
1015 	  cursor_state = search_cursor_state ( pt_lt, pt_rb, pt );
1016 	  if ( PISA_CS_CROSS != cursor_state )
1017 	    {
1018 	      m_cursor_state = PISA_CS_ARROW;
1019 	      return i;
1020 	    }
1021 	}
1022       else
1023 	{
1024 	  judge_rect.left	= pt_lt.x - ADDSIZE;
1025 	  judge_rect.right	= pt_rb.x + ADDSIZE;
1026 	  judge_rect.top	= pt_lt.y - ADDSIZE;
1027 	  judge_rect.bottom	= pt_rb.y + ADDSIZE;
1028 	  if ( pt_in_rect ( judge_rect, pt ) )
1029 	    {
1030 	      m_cursor_state = PISA_CS_ARROW;
1031 	      return i;
1032 	    }
1033 	}
1034     }
1035 
1036   if ( pt_in_cur_marq )
1037     {
1038       m_cursor_state = PISA_CS_HAND;
1039       return 0;
1040     }
1041 
1042   m_cursor_state = PISA_CS_CROSS;
1043 
1044   return 0;
1045 }
1046 
1047 /*--------------------------------------------------------------*/
search_cursor_state(const _pointL & pt_lt,const _pointL & pt_rb,const _pointL & pt)1048 int preview_window::search_cursor_state ( const _pointL & pt_lt,
1049 					  const _pointL & pt_rb,
1050 					  const _pointL & pt )
1051 {
1052   const long ADDSIZE	= 3;
1053   _rectL judge_rect;
1054 
1055   // check left top
1056   judge_rect.left	= pt_lt.x - ADDSIZE;
1057   judge_rect.right	= pt_lt.x + ADDSIZE;
1058   judge_rect.top	= pt_lt.y - ADDSIZE;
1059   judge_rect.bottom	= pt_lt.y + ADDSIZE;
1060   if ( ::pt_in_rect ( judge_rect, pt ) )
1061     return PISA_CS_LEFTTOP;
1062 
1063   // check right bottom
1064   judge_rect.left	= pt_rb.x - ADDSIZE;
1065   judge_rect.right	= pt_rb.x + ADDSIZE;
1066   judge_rect.top	= pt_rb.y - ADDSIZE;
1067   judge_rect.bottom	= pt_rb.y + ADDSIZE;
1068   if ( ::pt_in_rect ( judge_rect, pt ) )
1069     return PISA_CS_RIGHTBOTTOM;
1070 
1071   // check right top
1072   judge_rect.left	= pt_rb.x - ADDSIZE;
1073   judge_rect.right	= pt_rb.x + ADDSIZE;
1074   judge_rect.top	= pt_lt.y - ADDSIZE;
1075   judge_rect.bottom	= pt_lt.y + ADDSIZE;
1076   if ( ::pt_in_rect ( judge_rect, pt ) )
1077     return PISA_CS_RIGHTTOP;
1078 
1079   // check left bottom
1080   judge_rect.left	= pt_lt.x - ADDSIZE;
1081   judge_rect.right	= pt_lt.x + ADDSIZE;
1082   judge_rect.top	= pt_rb.y - ADDSIZE;
1083   judge_rect.bottom	= pt_rb.y + ADDSIZE;
1084   if ( ::pt_in_rect ( judge_rect, pt ) )
1085     return PISA_CS_LEFTBOTTOM;
1086 
1087   // check left resizing
1088   judge_rect.left	= pt_lt.x - ADDSIZE;
1089   judge_rect.right	= pt_lt.x + ADDSIZE;
1090   judge_rect.top	= pt_lt.y;
1091   judge_rect.bottom	= pt_rb.y;
1092   if ( ::pt_in_rect ( judge_rect, pt ) )
1093     return PISA_CS_LEFT;
1094 
1095   // check right resizing
1096   judge_rect.left	= pt_rb.x - ADDSIZE;
1097   judge_rect.right	= pt_rb.x + ADDSIZE;
1098   judge_rect.top	= pt_lt.y;
1099   judge_rect.bottom	= pt_rb.y;
1100   if ( ::pt_in_rect ( judge_rect, pt ) )
1101     return PISA_CS_RIGHT;
1102 
1103   // check top resizing
1104   judge_rect.left	= pt_lt.x;
1105   judge_rect.right	= pt_rb.x;
1106   judge_rect.top	= pt_lt.y - ADDSIZE;
1107   judge_rect.bottom	= pt_lt.y + ADDSIZE;
1108   if ( ::pt_in_rect ( judge_rect, pt ) )
1109     return PISA_CS_TOP;
1110 
1111   // check bottom resizing
1112   judge_rect.left	= pt_lt.x;
1113   judge_rect.right	= pt_rb.x;
1114   judge_rect.top	= pt_rb.y - ADDSIZE;
1115   judge_rect.bottom	= pt_rb.y + ADDSIZE;
1116   if ( ::pt_in_rect ( judge_rect, pt ) )
1117     return PISA_CS_BOTTOM;
1118 
1119   return PISA_CS_CROSS;
1120 }
1121 
1122 /*--------------------------------------------------------------*/
change_cursor(void)1123 void preview_window::change_cursor ( void )
1124 {
1125   ::gdk_window_set_cursor ( m_prev->window,
1126 			    m_cursor [ m_cursor_state ] );
1127 }
1128 
1129 /*--------------------------------------------------------------*/
modify_max_val(void)1130 void preview_window::modify_max_val ( void )
1131 {
1132   marquee	* whole_marq;
1133   _pointD	pt_min_D, pt_max_D;
1134 
1135   whole_marq = & g_view_manager->get_marquee (0);
1136   m_max_img_rect.top	= 0.0;
1137   m_max_img_rect.left	= 0.0;
1138   m_max_img_rect.right	= whole_marq->area.x;
1139   m_max_img_rect.bottom	= whole_marq->area.y;
1140 
1141   pt_min_D.x	= m_max_img_rect.left;
1142   pt_min_D.y	= m_max_img_rect.top;
1143   pt_max_D.x	= m_max_img_rect.right;
1144   pt_max_D.y	= m_max_img_rect.bottom;
1145   m_pt_max_rb	= inches2clientpix ( pt_max_D );
1146   m_pt_max_lt.x = 0;
1147   m_pt_max_lt.y = 0;
1148   m_pt_max_rb.x = m_img_width - 1;
1149   m_pt_max_rb.y = m_img_height - 1;
1150 }
1151 
1152 /*--------------------------------------------------------------*/
mouse_down(GdkEvent * event)1153 gint preview_window::mouse_down ( GdkEvent * event )
1154 {
1155   marquee	* cur_marq;
1156   _pointL	pt_lefttop, pt_rightbottom;
1157   long		id_cur_marquee;
1158 
1159   if ( event->button.button != 1 )
1160     return TRUE;
1161 
1162   if ( m_img_width - 1 < ( int ) event->button.x || m_img_height - 1 < ( int ) event->button.y )
1163     return TRUE;
1164 
1165   m_pt_begin.x = ( int ) event->button.x;
1166   m_pt_begin.y = ( int ) event->button.y;
1167 
1168   m_drag = 1;
1169 
1170   m_pt_old = m_pt_begin;
1171 
1172   id_cur_marquee = g_view_manager->get_marquee_size () - 1;
1173   get_marquee_point ( id_cur_marquee, & pt_lefttop, & pt_rightbottom );
1174 
1175   cur_marq = & g_view_manager->get_marquee ();
1176 
1177   m_pt_save_offset	= cur_marq->offset;
1178   m_pt_save_area	= cur_marq->area;
1179 
1180   switch ( m_cursor_state )
1181     {
1182     case PISA_CS_CROSS:
1183       m_pt_old_lt = m_pt_old_rb = m_pt_begin;
1184       delete_marquee ( );
1185       create_marquee ( m_pt_old_lt, m_pt_old_rb );
1186       break;
1187     case PISA_CS_HAND:
1188     case PISA_CS_TOP:
1189     case PISA_CS_BOTTOM:
1190     case PISA_CS_LEFT:
1191     case PISA_CS_RIGHT:
1192     case PISA_CS_LEFTTOP:
1193     case PISA_CS_LEFTBOTTOM:
1194     case PISA_CS_RIGHTTOP:
1195     case PISA_CS_RIGHTBOTTOM:
1196       m_pt_old_lt = pt_lefttop;
1197       m_pt_old_rb = pt_rightbottom;
1198       break;
1199     }
1200 
1201   return FALSE;
1202 }
1203 
1204 /*--------------------------------------------------------------*/
mouse_move(GdkEvent * event)1205 gint preview_window::mouse_move ( GdkEvent * event )
1206 {
1207   int	x, y;
1208   GdkModifierType	state;
1209   _pointL pt_mouse, pt_move, pt_tmp_lt, pt_tmp_rb, pt_min_L;
1210   _pointD pt_lefttop, pt_rightbottom, pt_min_D, pt_zero_D;
1211 
1212   if ( event->motion.is_hint )
1213     {
1214       ::gdk_window_get_pointer ( m_prev->window, & x, & y, & state );
1215     }
1216   else
1217     return TRUE;
1218 
1219   if ( m_drag == 0 )
1220     {
1221       set_mouse_cursor ( x, y );
1222       change_cursor ( );
1223       return FALSE;
1224     }
1225 
1226   if ( x < 0 ) x = 0;
1227   if ( y < 0 ) y = 0;
1228   if ( m_client_rect.right  < x ) x = m_client_rect.right;
1229   if ( m_client_rect.bottom < y ) y = m_client_rect.bottom;
1230 
1231   pt_mouse.x	= x;
1232   pt_mouse.y	= y;
1233 
1234   // clear previous marquee
1235   draw_rect ( m_pt_old_lt, m_pt_old_rb );
1236 
1237   pt_lefttop		= m_pt_save_offset;
1238   pt_rightbottom	= m_pt_save_offset + m_pt_save_area;
1239 
1240   pt_tmp_lt	= inches2clientpix ( pt_lefttop );
1241   pt_tmp_rb	= inches2clientpix ( pt_rightbottom );
1242 
1243   pt_zero_D.x	= 0.0;
1244   pt_zero_D.y	= 0.0;
1245   pt_min_D.x	= g_min_marq_size;
1246   pt_min_D.y	= g_min_marq_size;
1247   pt_min_L	= inches2clientpix ( pt_min_D ) - inches2clientpix ( pt_zero_D );
1248 
1249   pt_move = pt_mouse - m_pt_begin;
1250 
1251   // initialize
1252   begin_mouse_move ( & pt_tmp_lt, & pt_tmp_rb );
1253 
1254   move_rect ( & pt_tmp_lt, & pt_tmp_rb, pt_move );
1255 
1256   switch ( m_cursor_state )
1257     {
1258     case PISA_CS_CROSS:
1259       m_pt_old_rb = pt_mouse;
1260       break;
1261     case PISA_CS_HAND:
1262       m_pt_old_rb = pt_tmp_lt + ( m_pt_old_rb - m_pt_old_lt );
1263       m_pt_old_lt = pt_tmp_lt;
1264       break;
1265     case PISA_CS_TOP:
1266       if ( m_pt_old_rb.y - pt_min_L.y > pt_tmp_lt.y )
1267 	m_pt_old_lt.y = pt_tmp_lt.y;
1268       else
1269 	m_pt_old_lt.y = m_pt_old_rb.y - pt_min_L.y;
1270       break;
1271     case PISA_CS_BOTTOM:
1272       if ( m_pt_old_lt.y + pt_min_L.y  < pt_tmp_rb.y )
1273 	m_pt_old_rb.y = pt_tmp_rb.y;
1274       else
1275 	m_pt_old_rb.y = m_pt_old_lt.y + pt_min_L.y;
1276       break;
1277     case PISA_CS_LEFT:
1278       if ( m_pt_old_rb.x - pt_min_L.x > pt_tmp_lt.x )
1279 	m_pt_old_lt.x = pt_tmp_lt.x;
1280       else
1281 	m_pt_old_lt.x = m_pt_old_rb.x - pt_min_L.x;
1282       break;
1283     case PISA_CS_RIGHT:
1284       if ( m_pt_old_lt.x + pt_min_L.x < pt_tmp_rb.x )
1285 	m_pt_old_rb.x = pt_tmp_rb.x;
1286       else
1287 	m_pt_old_rb.x = m_pt_old_lt.x + pt_min_L.x;
1288       break;
1289     case PISA_CS_LEFTTOP:
1290       if ( m_pt_old_rb.y - pt_min_L.y > pt_tmp_lt.y )
1291 	m_pt_old_lt.y = pt_tmp_lt.y;
1292       else
1293 	m_pt_old_lt.y = m_pt_old_rb.y - pt_min_L.y;
1294       if ( m_pt_old_rb.x - pt_min_L.x > pt_tmp_lt.x )
1295 	m_pt_old_lt.x = pt_tmp_lt.x;
1296       else
1297 	m_pt_old_lt.x = m_pt_old_rb.x - pt_min_L.x;
1298       break;
1299     case PISA_CS_LEFTBOTTOM:
1300       if ( m_pt_old_rb.x - pt_min_L.x > pt_tmp_lt.x )
1301 	m_pt_old_lt.x = pt_tmp_lt.x;
1302       else
1303 	m_pt_old_lt.x = m_pt_old_rb.x - pt_min_L.x;
1304       if ( m_pt_old_lt.y + pt_min_L.y  < pt_tmp_rb.y )
1305 	m_pt_old_rb.y = pt_tmp_rb.y;
1306       else
1307 	m_pt_old_rb.y = m_pt_old_lt.y + pt_min_L.y;
1308       break;
1309     case PISA_CS_RIGHTTOP:
1310       if ( m_pt_old_rb.y - pt_min_L.y > pt_tmp_lt.y )
1311 	m_pt_old_lt.y = pt_tmp_lt.y;
1312       else
1313 	m_pt_old_lt.y = m_pt_old_rb.y - pt_min_L.y;
1314       if ( m_pt_old_lt.x + pt_min_L.x < pt_tmp_rb.x )
1315 	m_pt_old_rb.x = pt_tmp_rb.x;
1316       else
1317 	m_pt_old_rb.x = m_pt_old_lt.x + pt_min_L.x;
1318       break;
1319     case PISA_CS_RIGHTBOTTOM:
1320       if ( m_pt_old_lt.y + pt_min_L.y  < pt_tmp_rb.y )
1321 	m_pt_old_rb.y = pt_tmp_rb.y;
1322       else
1323 	m_pt_old_rb.y = m_pt_old_lt.y + pt_min_L.y;
1324       if ( m_pt_old_lt.x + pt_min_L.x < pt_tmp_rb.x )
1325 	m_pt_old_rb.x = pt_tmp_rb.x;
1326       else
1327 	m_pt_old_rb.x = m_pt_old_lt.x + pt_min_L.x;
1328       break;
1329     }
1330 
1331   draw_rect ( m_pt_old_lt, m_pt_old_rb );
1332 
1333   if ( m_cursor_state != PISA_CS_HAND )
1334     resize_marquee ( m_pt_old_lt, m_pt_old_rb );
1335 
1336   m_pt_old = pt_mouse;
1337 
1338   return FALSE;
1339 }
1340 
1341 /*--------------------------------------------------------------*/
mouse_up(GdkEvent * event)1342 gint preview_window::mouse_up ( GdkEvent * event )
1343 {
1344   int min_check, move;
1345   _pointL pt_mouse;
1346   long	marq_num;
1347 
1348   if ( 0 == m_drag )
1349     return FALSE;
1350 
1351   pt_mouse.x = ( int ) event->button.x;
1352   pt_mouse.y = ( int ) event->button.y;
1353 
1354   move = ( m_pt_begin.x != pt_mouse.x ) || ( m_pt_begin.y != pt_mouse.y );
1355 
1356   // clear previous marquee
1357   marq_num = g_view_manager->get_marquee_size ();
1358   if ( 1 < marq_num )
1359     draw_rect ( m_pt_old_lt, m_pt_old_rb );
1360 
1361   switch ( m_cursor_state )
1362     {
1363     case PISA_CS_CROSS:
1364       min_check = check_min_size ( m_pt_old_lt, m_pt_old_rb );
1365       if ( min_check == 0 )
1366 	delete_marquee ( );
1367       update_img ( );
1368       break;
1369     case PISA_CS_ARROW:
1370       break;
1371     case PISA_CS_HAND:
1372       move_marquee ( m_pt_old_lt, m_pt_old_rb );
1373       update_img ( );
1374       break;
1375     case PISA_CS_LEFT:
1376     case PISA_CS_LEFTTOP:
1377     case PISA_CS_LEFTBOTTOM:
1378     case PISA_CS_RIGHT:
1379     case PISA_CS_RIGHTTOP:
1380     case PISA_CS_RIGHTBOTTOM:
1381     case PISA_CS_TOP:
1382     case PISA_CS_BOTTOM:
1383       if ( 0 == check_min_size ( m_pt_old_lt, m_pt_old_rb ) )
1384 	delete_marquee ( );
1385       update_img (   PISA_CS_LEFT       == m_cursor_state
1386 		  || PISA_CS_LEFTTOP    == m_cursor_state
1387 		  || PISA_CS_LEFTBOTTOM == m_cursor_state);
1388       break;
1389     }
1390 
1391   m_drag = 0;
1392 
1393   set_mouse_cursor ( pt_mouse.x, pt_mouse.y );
1394   change_cursor ( );
1395 
1396   return FALSE;
1397 }
1398 
1399 /*--------------------------------------------------------------*/
create_marquee(const _pointL & pt_lt,const _pointL & pt_rb)1400 int preview_window::create_marquee ( const _pointL & pt_lt, const _pointL & pt_rb )
1401 {
1402   _pointL	pt_lefttop_L, pt_rightbottom_L;
1403   _pointD	pt_lefttop_D, pt_rightbottom_D, pt_area_D;
1404   marquee	* new_marq, * whole_marq;
1405 
1406   pt_lefttop_L		= pt_lt;
1407   pt_rightbottom_L	= pt_rb;
1408   check_ltrb ( & pt_lefttop_L, & pt_rightbottom_L );
1409 
1410   pt_lefttop_D		= clientpix2inches ( pt_lefttop_L );
1411   pt_rightbottom_D	= clientpix2inches ( pt_rightbottom_L );
1412   pt_area_D		= pt_rightbottom_D - pt_lefttop_D;
1413 
1414   check_max_size ( & pt_lefttop_D, & pt_area_D, 0 );
1415 
1416   whole_marq = & g_view_manager->get_marquee (0);
1417   new_marq = new marquee;
1418   * new_marq = * whole_marq;
1419 
1420   new_marq->offset	= pt_lefttop_D;
1421   new_marq->area	= pt_area_D;
1422 
1423   g_view_manager->add_marquee (&new_marq);
1424 
1425   ::g_view_manager->sensitive ( );
1426 
1427   return 1;
1428 }
1429 
1430 /*--------------------------------------------------------------*/
delete_marquee(void)1431 int preview_window::delete_marquee ( void )
1432 {
1433   long		num_marq;
1434   int		i, j;
1435   marquee	* cur_marq, * whole_marq;
1436 
1437   num_marq = g_view_manager->get_marquee_size ();
1438 
1439   // no marquee
1440   if ( num_marq < 2 )
1441     return PISA_ERR_SUCCESS;
1442 
1443   whole_marq = & g_view_manager->get_marquee (0);
1444   cur_marq = & g_view_manager->get_marquee ();
1445 
1446   whole_marq->gamma		= cur_marq->gamma;
1447   whole_marq->highlight		= cur_marq->highlight;
1448   whole_marq->shadow		= cur_marq->shadow;
1449   whole_marq->threshold		= cur_marq->threshold;
1450 
1451   for ( i = 0; i < 4; i++ )
1452     for ( j = 0; j < 256; j++ )
1453       whole_marq->gamma_table [ i ] [ j ] = cur_marq->gamma_table [ i ] [ j ];
1454 
1455   whole_marq->graybalance	= cur_marq->graybalance;
1456   whole_marq->saturation	= cur_marq->saturation;
1457 
1458   whole_marq->scale		= cur_marq->scale;
1459 
1460   whole_marq->focus		= cur_marq->focus;
1461 
1462   for ( i = 0; i < 3; i++ )
1463     {
1464       whole_marq->film_gamma [ i ]	= cur_marq->film_gamma [ i ];
1465       whole_marq->film_yp [ i ]		= cur_marq->film_yp [ i ];
1466       whole_marq->grayl [ i ]		= cur_marq->grayl [ i ];
1467     }
1468 
1469   for ( i = 0; i < 256; i++ )
1470     {
1471       whole_marq->lut.gamma_r [ i ]	= cur_marq->lut.gamma_r [ i ];
1472       whole_marq->lut.gamma_g [ i ]	= cur_marq->lut.gamma_g [ i ];
1473       whole_marq->lut.gamma_b [ i ]	= cur_marq->lut.gamma_b [ i ];
1474     }
1475 
1476   g_view_manager->del_marquee ();
1477 
1478   ::g_view_manager->sensitive ( );
1479   update_img ( );
1480 
1481   return PISA_ERR_SUCCESS;
1482 }
1483 
1484 /*--------------------------------------------------------------*/
move_marquee(const _pointL & pt_lt,const _pointL & pt_rb)1485 void preview_window::move_marquee ( const _pointL & pt_lt,
1486 				    const _pointL & pt_rb )
1487 {
1488   _pointL pt_lefttop_L, pt_rightbottom_L, pt_tmp;
1489   _pointD pt_lefttop_D, pt_rightbottom_D, pt_offset, pt_area;
1490   marquee	* cur_marq;
1491 
1492   pt_tmp = pt_rb;
1493 
1494   pt_lefttop_L		= pt_lt;
1495   pt_lefttop_D		= clientpix2inches ( pt_lefttop_L );
1496   pt_rightbottom_D	= clientpix2inches ( pt_rightbottom_L );
1497 
1498   pt_offset	= pt_lefttop_D;
1499   pt_area	= pt_rightbottom_D - pt_lefttop_D;
1500 
1501   check_max_size ( & pt_offset, & pt_area, 1 );
1502 
1503   cur_marq = & g_view_manager->get_marquee ();
1504 
1505   cur_marq->offset	= pt_offset;
1506 
1507   ::g_view_manager->sensitive ( );
1508 }
1509 
1510 /*--------------------------------------------------------------*/
resize_marquee(const _pointL & pt_lt,const _pointL & pt_rb)1511 void preview_window::resize_marquee ( const _pointL & pt_lt,
1512 				      const _pointL & pt_rb )
1513 {
1514   _pointL pt_lefttop_L, pt_rightbottom_L;
1515   _pointD pt_lefttop_D, pt_rightbottom_D, pt_offset, pt_area;
1516   marquee	* cur_marq;
1517 
1518   pt_lefttop_L		= pt_lt;
1519   pt_rightbottom_L	= pt_rb;
1520 
1521   check_ltrb ( & pt_lefttop_L, & pt_rightbottom_L );
1522 
1523   pt_lefttop_D		= clientpix2inches ( pt_lefttop_L );
1524   pt_rightbottom_D	= clientpix2inches ( pt_rightbottom_L );
1525 
1526   pt_offset	= pt_lefttop_D;
1527   pt_area	= pt_rightbottom_D - pt_lefttop_D;
1528 
1529   check_max_size ( & pt_offset, & pt_area, 0 );
1530 
1531   cur_marq = & g_view_manager->get_marquee ();
1532 
1533   cur_marq->offset	= pt_offset;
1534   cur_marq->area	= pt_area;
1535 
1536   ::g_view_manager->sensitive ( );
1537 }
1538 
1539 /*--------------------------------------------------------------*/
begin_mouse_move(_pointL * pt_lt,_pointL * pt_rb)1540 void preview_window::begin_mouse_move ( _pointL * pt_lt, _pointL * pt_rb )
1541 {
1542   switch ( m_cursor_state )
1543     {
1544     case PISA_CS_CROSS:
1545     case PISA_CS_HAND:
1546       break;
1547     case PISA_CS_TOP:
1548       pt_lt->x = pt_rb->x;
1549       pt_rb->y = pt_lt->y;
1550       break;
1551     case PISA_CS_BOTTOM:
1552       * pt_lt = * pt_rb;
1553       break;
1554     case PISA_CS_LEFT:
1555       pt_lt->y = pt_rb->y;
1556       pt_rb->x = pt_lt->x;
1557       break;
1558     case PISA_CS_RIGHT:
1559       * pt_lt = * pt_rb;
1560       break;
1561     case PISA_CS_LEFTTOP:
1562       * pt_rb = * pt_lt;
1563       break;
1564     case PISA_CS_LEFTBOTTOM:
1565       pt_lt->y = pt_rb->y;
1566       pt_rb->x = pt_lt->x;
1567       break;
1568     case PISA_CS_RIGHTBOTTOM:
1569       * pt_lt = * pt_rb;
1570       break;
1571     case PISA_CS_RIGHTTOP:
1572       pt_lt->x = pt_rb->x;
1573       pt_rb->y = pt_lt->y;
1574       break;
1575     }
1576 }
1577 
1578 /*--------------------------------------------------------------*/
move_rect(_pointL * pt_lt,_pointL * pt_rb,const _pointL & pt_move)1579 void preview_window::move_rect ( _pointL * pt_lt, _pointL * pt_rb,
1580 				 const _pointL & pt_move )
1581 {
1582   // move direction
1583   typedef enum { DIR_LT, DIR_LB, DIR_RT, DIR_RB } MOVE_DIR;
1584   MOVE_DIR direction;
1585   _pointL pt_tmp, pt_tmp_move ( pt_move );
1586   _pointL pt_size;
1587   _pointD pt_lefttop_D, pt_rightbottom_D;
1588   _pointL pt_lefttop_L, pt_rightbottom_L;
1589 
1590   if ( pt_move.x < 0 )
1591     {
1592       if ( pt_move.y < 0 )
1593 	direction = DIR_LT;
1594       else
1595 	direction = DIR_LB;
1596     }
1597   else
1598     {
1599       if ( pt_move.y < 0 )
1600 	direction = DIR_RT;
1601       else
1602 	direction = DIR_RB;
1603     }
1604 
1605   pt_lefttop_D		= m_pt_save_offset;
1606   pt_rightbottom_D	= m_pt_save_offset + m_pt_save_area;
1607 
1608   pt_lefttop_L		= inches2clientpix ( pt_lefttop_D );
1609   pt_rightbottom_L	= inches2clientpix ( pt_rightbottom_D );
1610 
1611   pt_size.x	= pt_rightbottom_L.x - pt_lefttop_L.x + 1;
1612   pt_size.y	= pt_rightbottom_L.y - pt_lefttop_L.y + 1;
1613 
1614   switch ( direction )
1615     {
1616     case DIR_LT:
1617       pt_tmp.x = pt_lt->x + pt_tmp_move.x;
1618       if ( pt_tmp.x < m_pt_max_lt.x )
1619 	pt_tmp.x = m_pt_max_lt.x;
1620       pt_tmp.y = pt_lt->y + pt_tmp_move.y;
1621       if ( pt_tmp.y < m_pt_max_lt.y )
1622 	pt_tmp.y = m_pt_max_lt.y;
1623       * pt_rb = pt_tmp + ( * pt_rb - * pt_lt );
1624       * pt_lt = pt_tmp;
1625       break;
1626     case DIR_LB:
1627       pt_tmp.x = pt_lt->x + pt_tmp_move.x;
1628       if ( pt_tmp.x < m_pt_max_lt.x )
1629 	pt_tmp.x = m_pt_max_lt.x;
1630       pt_tmp.y = pt_rb->y + pt_tmp_move.y;
1631       if ( m_pt_max_rb.y < pt_tmp.y )
1632 	pt_tmp.y = m_pt_max_rb.y;
1633       pt_lt->y = pt_tmp.y - ( pt_rb->y - pt_lt->y );
1634       pt_rb->x = pt_tmp.x - ( pt_rb->x - pt_lt->x );
1635       pt_lt->x = pt_tmp.x;
1636       pt_rb->y = pt_tmp.y;
1637       break;
1638     case DIR_RT:
1639       pt_tmp.x = pt_rb->x + pt_tmp_move.x;
1640       if ( m_pt_max_rb.x < pt_tmp.x )
1641 	pt_tmp.x = m_pt_max_rb.x;
1642       pt_tmp.y = pt_lt->y + pt_tmp_move.y;
1643       if ( pt_tmp.y < m_pt_max_lt.y )
1644 	pt_tmp.y = m_pt_max_lt.y;
1645       pt_lt->x = pt_tmp.x - ( pt_rb->x - pt_lt->x );
1646       pt_rb->y = pt_tmp.y + ( pt_rb->y - pt_lt->y );
1647       pt_lt->y = pt_tmp.y;
1648       pt_rb->x = pt_tmp.x;
1649       break;
1650     case DIR_RB:
1651       pt_tmp.x = pt_rb->x + pt_tmp_move.x;
1652       if ( m_pt_max_rb.x < pt_tmp.x )
1653 	pt_tmp.x = m_pt_max_rb.x;
1654       pt_tmp.y = pt_rb->y + pt_tmp_move.y;
1655       if ( m_pt_max_rb.y < pt_tmp.y )
1656 	pt_tmp.y = m_pt_max_rb.y;
1657       * pt_lt = pt_tmp - ( * pt_rb - * pt_lt );
1658       * pt_rb = pt_tmp;
1659       break;
1660     }
1661 }
1662 
1663 /*--------------------------------------------------------------*/
clientpix2inches(_pointL & pt)1664 _pointD preview_window::clientpix2inches ( _pointL & pt )
1665 {
1666   _pointD	pt_result;
1667   _pointD	pt_tmp;
1668   double	da, db;
1669 
1670   da	= m_client_rect.right - m_client_rect.left;
1671   db	= m_img_rect.right - m_img_rect.left;
1672   pt_tmp.x = similarity ( ( double ) pt.x, da, db );
1673 
1674   da	= m_client_rect.bottom - m_client_rect.top;
1675   db	= m_img_rect.bottom - m_img_rect.top;
1676   pt_tmp.y = similarity ( ( double ) pt.y, da, db );
1677 
1678 
1679   pt_result.x = m_img_rect.left + pt_tmp.x;
1680   pt_result.y = m_img_rect.top  + pt_tmp.y;
1681 
1682   return pt_result;
1683 }
1684 
1685 /*--------------------------------------------------------------*/
inches2clientpix(_pointD & pt)1686 _pointL preview_window::inches2clientpix ( _pointD & pt )
1687 {
1688   _pointD	pt_tmp;
1689   _pointL	pt_result;
1690   double	da, db;
1691 
1692   pt_tmp.x = pt.x - m_img_rect.left;
1693   pt_tmp.y = pt.y - m_img_rect.top;
1694 
1695   da	= m_img_rect.right - m_img_rect.left;
1696   db	= m_client_rect.right - m_client_rect.left;
1697   pt_result.x = ( long ) similarity ( pt_tmp.x, da, db );
1698 
1699   da	= m_img_rect.bottom - m_img_rect.top;
1700   db	= m_client_rect.bottom - m_client_rect.top;
1701   pt_result.y = ( long ) similarity ( pt_tmp.y, da, db );
1702 
1703   return pt_result;
1704 }
1705 
1706 /*--------------------------------------------------------------*/
get_marquee_point(long i,_pointL * pt_lt,_pointL * pt_rb)1707 int preview_window::get_marquee_point ( long i, _pointL * pt_lt, _pointL * pt_rb )
1708 {
1709   marquee * marq;
1710   _pointD pt_tmp_lt, pt_tmp_rb;
1711 
1712   if (0 == (marq = & g_view_manager->get_marquee (i)))
1713     return 0;
1714 
1715   pt_tmp_lt = marq->offset;
1716   pt_tmp_rb = marq->offset + marq->area;
1717 
1718   * pt_lt = inches2clientpix ( pt_tmp_lt );
1719   * pt_rb = inches2clientpix ( pt_tmp_rb );
1720 
1721   return 1;
1722 }
1723 
1724 /*--------------------------------------------------------------*/
check_min_size(const _pointL & pt_lt,const _pointL & pt_rb)1725 int preview_window::check_min_size ( const _pointL & pt_lt, const _pointL & pt_rb )
1726 {
1727   _pointD pt_zero_D, pt_min_D;
1728   _pointL pt_min_L;
1729 
1730   pt_zero_D.x	= 0.0;
1731   pt_zero_D.y	= 0.0;
1732   pt_min_D.x	= g_min_marq_size;
1733   pt_min_D.y	= g_min_marq_size;
1734   pt_min_L	= inches2clientpix ( pt_min_D ) - inches2clientpix ( pt_zero_D );
1735 
1736   if ( ::abs ( pt_lt.x - pt_rb.x ) < pt_min_L.x ||
1737        ::abs ( pt_lt.y - pt_rb.y ) < pt_min_L.y )
1738     return 0;
1739   else
1740     return 1;
1741 }
1742 
1743 /*--------------------------------------------------------------*/
check_max_size(_pointD * pt_offset,_pointD * pt_area,int offset)1744 void preview_window::check_max_size ( _pointD * pt_offset, _pointD * pt_area,
1745 				      int offset )
1746 {
1747   if ( pt_offset->x < 0.0 ) pt_offset->x = 0.0;
1748   if ( pt_offset->y < 0.0 ) pt_offset->y = 0.0;
1749 
1750   if ( pt_area->x > m_max_img_rect.right  ) pt_area->x = m_max_img_rect.right;
1751   if ( pt_area->y > m_max_img_rect.bottom ) pt_area->y = m_max_img_rect.bottom;
1752 
1753   if ( offset )
1754     {
1755       if ( m_max_img_rect.right < pt_offset->x + pt_area->x )
1756 	pt_area->x = m_max_img_rect.right - pt_offset->x;
1757       if ( m_max_img_rect.bottom < pt_offset->y + pt_area->y )
1758 	pt_area->y = m_max_img_rect.bottom - pt_offset->y;
1759     }
1760   else
1761     {
1762       if ( m_max_img_rect.right < pt_offset->x + pt_area->x )
1763 	pt_offset->x = m_max_img_rect.right - pt_area->x;
1764       if ( m_max_img_rect.bottom < pt_offset->y + pt_area->y )
1765 	pt_offset->y = m_max_img_rect.bottom - pt_area->y;
1766     }
1767 }
1768 
1769 /*--------------------------------------------------------------*/
check_ltrb(_pointL * pt_lt,_pointL * pt_rb)1770 void preview_window::check_ltrb ( _pointL * pt_lt, _pointL * pt_rb )
1771 {
1772   _pointL pt_ret_lt, pt_ret_rb;
1773 
1774   pt_ret_lt.x = ( pt_lt->x < pt_rb->x ) ? pt_lt->x : pt_rb->x;
1775   pt_ret_lt.y = ( pt_lt->y < pt_rb->y ) ? pt_lt->y : pt_rb->y;
1776   pt_ret_rb.x = ( pt_lt->x > pt_rb->x ) ? pt_lt->x : pt_rb->x;
1777   pt_ret_rb.y = ( pt_lt->y > pt_rb->y ) ? pt_lt->y : pt_rb->y;
1778 
1779   * pt_lt = pt_ret_lt;
1780   * pt_rb = pt_ret_rb;
1781 }
1782 
1783 /*--------------------------------------------------------------*/
draw_rect(const _pointL & pt_lt,const _pointL & pt_rb)1784 void preview_window::draw_rect ( const _pointL & pt_lt,
1785 				 const _pointL & pt_rb )
1786 {
1787   int x, y, w, h;
1788 
1789   if ( m_gc == 0 )
1790     {
1791       m_gc = ::gdk_gc_new ( m_prev->window );
1792       ::gdk_gc_set_function ( m_gc, GDK_INVERT );
1793       ::gdk_gc_set_line_attributes ( m_gc, 1, GDK_LINE_ON_OFF_DASH,
1794 				     GDK_CAP_BUTT, GDK_JOIN_MITER );
1795     }
1796 
1797   x = ( pt_lt.x < pt_rb.x ) ? pt_lt.x : pt_rb.x;
1798   y = ( pt_lt.y < pt_rb.y ) ? pt_lt.y : pt_rb.y;
1799   w = ( pt_lt.x > pt_rb.x ) ? pt_lt.x - pt_rb.x : pt_rb.x - pt_lt.x;
1800   h = ( pt_lt.y > pt_rb.y ) ? pt_lt.y - pt_rb.y : pt_rb.y - pt_lt.y;
1801 
1802   ::gdk_draw_rectangle ( m_prev->window, m_gc, FALSE,
1803 			 x, y, w, h );
1804 }
1805 
1806 
1807