22af86aa02c69bd6c7a46b1e3f18b8672112ec3e
[oweals/cde.git] / cde / programs / dtinfo / dtinfo / src / Managers / GraphicsMgr.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*      Copyright (c) 1994 FUJITSU LIMITED      */
24 /*      All Rights Reserved                     */
25
26 /*
27  * $TOG: GraphicsMgr.C /main/29 1998/04/17 11:36:15 mgreess $
28  *
29  * Copyright (c) 1992 HaL Computer Systems, Inc.  All rights reserved.
30  * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
31  * States.  Use of a copyright notice is precautionary only and does not
32  * imply publication or disclosure.
33  * 
34  * This software contains confidential information and trade secrets of HaL
35  * Computer Systems, Inc.  Use, disclosure, or reproduction is prohibited
36  * without the prior express written permission of HaL Computer Systems, Inc.
37  * 
38  *                         RESTRICTED RIGHTS LEGEND
39  * Use, duplication, or disclosure by the Government is subject to
40  * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
41  * Technical Data and Computer Software clause at DFARS 252.227-7013.
42  *                        HaL Computer Systems, Inc.
43  *                  1315 Dell Avenue, Campbell, CA  95008
44  * 
45  */
46
47 #include <DtI/GraphicsP.h>
48
49 #define C_PixmapGraphic
50 #define L_Graphics
51
52 #define C_GraphicsMgr
53 #define C_MessageMgr
54 #define C_EnvMgr
55 #define L_Managers
56
57 #ifdef UseDlOpen
58 #define C_XpmLib
59 #endif
60 #define C_WindowSystem
61 #define L_Other
62
63 #define C_Database
64 #define C_OString
65 #define L_Basic
66
67 #define C_GraphicAgent
68 #define C_ViewportAgent
69 #define L_Agents
70
71 #include "Prelude.h"
72
73 #include <iostream.h>
74 extern "C"
75 {
76 #include "../cgm/spec.h"
77 }
78 #include "utility/funcs.h"
79
80 LONG_LIVED_CC(GraphicsMgr,graphics_mgr);
81
82 // ////////////////////////////////////////////////////////////
83 // class constructor
84 // ////////////////////////////////////////////////////////////
85
86 GraphicsMgr::GraphicsMgr ()
87 {
88 }
89
90 // ////////////////////////////////////////////////////////////
91 // class destructor
92 // ////////////////////////////////////////////////////////////
93
94 GraphicsMgr::~GraphicsMgr ()
95 {
96 }
97
98 // /////////////////////////////////////////////////////////////////
99 // get_graphic - get a pixmap given a locator and a scale factor
100 // /////////////////////////////////////////////////////////////////
101
102 PixmapGraphic *
103 GraphicsMgr::get_graphic (UAS_Pointer<Graphic> &gr)
104 {    
105     extern AppPrintData * l_AppPrintData;
106     int resolution = 0;
107     String string_resolution ;
108
109     // if printing, get print resolution from default-printer-resolution
110
111     if (window_system().printing()) {
112         string_resolution = XpGetOneAttribute(window_system().printDisplay(), 
113                                               l_AppPrintData->f_print_data->print_context,
114                                               XPDocAttr, "default-printer-resolution") ;
115         resolution = atoi(string_resolution);
116         XFree(string_resolution);       
117     }
118
119     // if not printing, or default-printer-resolution not defined, calcuate from 
120     // the X screen resolution
121
122     if (!resolution) {
123
124         // calculate the display (or printer) resolution in dots per inch.
125         // 25.4mm = 1 inch
126         resolution = 
127             (254 * WidthOfScreen(window_system().screen()) +
128              5 * WidthMMOfScreen(window_system().screen())) /
129             (10 * WidthMMOfScreen(window_system().screen())) ;
130
131         // cgm needs resolution to be 100--this is to fix
132         // fit_graphic_to_window problem.
133         UAS_String cgm_type("application/CGM");
134         if(cgm_type == gr->content_type())
135           resolution = 100;
136
137     }
138
139     return get_graphic(gr->data(), gr->data_length(), gr->content_type(), resolution);
140 }
141
142 // /////////////////////////////////////////////////////////////////
143 // get_graphic - get a pixmap given a locator
144 // /////////////////////////////////////////////////////////////////
145
146 PixmapGraphic *
147 GraphicsMgr::get_graphic (const UAS_String &imdata,
148                           unsigned int length,
149                           const UAS_String &imtype,
150                           unsigned short scale_factor)
151 {
152   //ON_DEBUG(cerr << "GraphicsMgr::get_graphic( "  << gr->locator() << " )" << endl);
153   //ON_DEBUG(cerr << "type = " << gr->content_type() << endl);
154   ON_DEBUG(cerr << "type = " << imtype << endl);
155
156   // made changes to the interface to allow the image data to be passed in instead
157   // of the graphic object. this is to allow the image data to be saved before
158   // it is passed to this method. when scaling is done, need to be able to scale
159   // the original data each time. this is why the image data is saved before calling
160   // this method. EAM - 6/27/96
161   static int initialized=0;
162
163   if(!initialized)
164   {
165     _DtGrRegisterConverter("CGM", processCGM, NULL, NULL, NULL);
166     initialized = 1;
167   }
168
169
170   UAS_String content_type(imtype);
171   char *image_type;
172   // if content_type is a NULL string, image type is unknown
173   if (content_type == "")
174   {
175     image_type = "unknown";
176   } 
177   else
178   {
179     image_type = content_type;
180     image_type = strchr(image_type, '/');
181
182     if (image_type)
183       image_type++;             // advance past the '/'
184   }
185
186   // this is called by a graphic to retrieve the pixmap 
187
188   PixmapGraphic *the_pixmap = NULL ;
189
190   Dimension width = 0 ;
191   Dimension height = 0;
192
193   //if (gr == (const int)NULL)
194   if ((char*)imdata == (char*)NULL)
195     {
196       fprintf (stderr, "*** Graphic not found in database ***\n");
197       throw (CASTEXCEPT Exception());
198     }
199
200   // setup the DtGrStream Buffer
201
202   _DtGrStream gr_stream ;
203   
204   UAS_String base(imdata);
205
206   gr_stream.type = _DtGrBUFFER ;
207   gr_stream.source.buffer.base = base ;
208   gr_stream.source.buffer.size = length;
209   gr_stream.source.buffer.current = (char*)gr_stream.source.buffer.base ;
210   gr_stream.source.buffer.end = (char *)(gr_stream.source.buffer.base + gr_stream.source.buffer.size) ;
211
212   // get some basic graphical info to pass to the routine
213
214   int depth ;
215   Screen   *screen ;
216   Visual   *visual ;
217   Colormap colormap ;
218
219   Pixel foreground, background ;
220
221
222   Arg arg[6] ;
223   unsigned n = 0;
224
225   XtSetArg(arg[n], XmNdepth,    &depth)    ; n++ ;
226   XtSetArg(arg[n], XmNcolormap, &colormap) ; n++ ;
227   XtSetArg(arg[n], XmNscreen,   &screen)   ; n++ ;
228   XtSetArg(arg[n], XmNvisual,   &visual)   ; n++ ;
229   XtSetArg(arg[n], XmNforeground, &foreground) ; n++ ;
230   XtSetArg(arg[n], XmNbackground, &background) ; n++ ;
231
232   XtGetValues(window_system().toplevel(), arg, n) ;
233
234   if (visual == CopyFromParent) {
235       visual= DefaultVisualOfScreen(screen);
236   }
237
238 #ifdef DEBUG
239   cerr << "depth: " << depth << "\tcolormap: " << colormap <<
240     "\tscreen: " << screen << "\tvisual: " << visual << endl;
241 #endif
242
243   // returned values - 
244   int   ret_num_colors = 0;
245   Pixel *ret_colors = 0;
246   Pixmap ret_pixmap = 0;
247   Pixmap ret_mask = 0;
248   
249   if (!strcasecmp (image_type, "unknown")) {
250     // If it is unknown at this point then it needs to be nulled out so the
251     // graphics api will determine the type.
252     image_type = NULL;
253   }
254
255   if (!strcasecmp (image_type, "XBM")) {
256     // match up infolib name for XBM to DtGr library
257     image_type = "BM";
258   }
259
260   if (!strcasecmp (image_type, "XPM")) {
261     // match up infolib name for XPM to DtGr library
262     image_type = "PM";
263   }
264
265 #ifdef XWD_TEST
266   if (!image_type || !strcasecmp (image_type, "unknown"))
267     image_type = "XWD" ;
268 #endif
269
270   // Context struct is required for TIFF data type only
271   _DtGrContext *ret_context = NULL ;
272   if (!strcasecmp (image_type, "TIFF")) {
273     ret_context = new _DtGrContext ;
274     ret_context->image_type = NULL ;
275     ret_context->context    = NULL ;
276   }
277
278
279   _DtGrLoadStatus status = 
280     _DtGrLoad(&gr_stream,       // image
281               &image_type,
282               screen,
283               depth,
284               colormap,
285               visual,
286               foreground,
287               background,
288               XDefaultGCOfScreen(screen),
289               _DtGrCOLOR,       // color_model
290               FALSE,            // don't allow reduced colors
291               &width,
292               &height,
293               scale_factor,     // media_resolution
294               &ret_pixmap,
295               &ret_mask,
296               &ret_colors,
297               &ret_num_colors,
298               ret_context);     
299
300
301   if (status == _DtGrCOLOR_FAILED)
302      {
303 #ifdef DEBUG
304         printf(
305        "Insufficient color cells for graphic. Retry with degraded colors.\n" );
306 #endif
307         _DtGrLoadStatus status =
308           _DtGrLoad(&gr_stream, // image
309               &image_type,
310               screen,
311               depth,
312               colormap,
313               visual,
314               foreground,
315               background,
316               XDefaultGCOfScreen(screen),
317               _DtGrCOLOR,       // color_model
318               TRUE,             // allow reduced colors
319               &width,
320               &height,
321               scale_factor,             // media_resolution
322               &ret_pixmap,
323               &ret_mask,
324               &ret_colors,
325               &ret_num_colors,
326               ret_context);
327      }
328
329               
330   if ((status == _DtGrSUCCESS) ||
331       (status == _DtGrCOLOR_REDUCE))
332   {
333       // get rid of memory the routine may have allocated for XPM,
334       // but which is not needed 
335       if (ret_mask) {
336           XFreePixmap (window_system().display(), ret_mask);
337       }
338       
339       // build our pixmap object
340       the_pixmap = new PixmapGraphic(ret_pixmap,
341                             width, height, PixmapGraphic::NORMAL);
342 #ifdef DEBUG
343       printf(
344       "pixmap %lx used to create PixmapGraphic %p\n", ret_pixmap, the_pixmap );
345 #endif
346
347       // set the associated colormap reservations so they can be freed later.
348       // Note static local struct ptr ret_context is used for TIFF.
349       the_pixmap->set_colormap( colormap, ret_num_colors, ret_colors,
350                                 ret_context );
351     }
352 #ifdef DEBUG
353   {
354     const char *statusv ;
355     switch (status)
356       {
357       case _DtGrSUCCESS:
358         statusv = " _DtGrSUCCESS";
359         break;
360       case _DtGrCOLOR_REDUCE:
361         statusv = "_DtGrCOLOR_REDUCE";
362         break;
363       case _DtGrCONVERT_FAILURE:
364         statusv = " _DtGrCONVERT_FAILURE";
365         break;
366       case _DtGrOPEN_FAILED:
367         statusv = "_DtGrOPEN_FAILED";
368         break;
369       case _DtGrFILE_INVALID:
370         statusv = "_DtGrFILE_INVALID";
371         break;
372       case _DtGrNO_MEMORY:
373         statusv = "_DtGrNO_MEMORY";
374         break ;
375       case _DtGrCOLOR_FAILED:
376         statusv = "_DtGrCOLOR_FAILED";
377         break;
378       default:
379         statusv = "Unknown"  ;
380       }
381     cerr << "status = " << statusv << " " << status << endl ;
382   }
383 #endif  
384
385
386   /* -------- Fallback by reading in default graphic. -------- */
387   if (the_pixmap == NULL)
388    {
389      Pixmap pixmap = window_system().default_pixmap(&width, &height); 
390
391      if (pixmap)
392        the_pixmap = new PixmapGraphic(pixmap,
393                                       width, height,
394                                       PixmapGraphic::DEFAULT_PIXMAP);
395    }
396
397   return the_pixmap ;
398 }
399
400
401
402 // /////////////////////////////////////////////////////////////////////////
403 // detach
404 // /////////////////////////////////////////////////////////////////////////
405
406 void
407 GraphicsMgr::detach (UAS_Pointer<UAS_Common> &node_ptr,
408                      UAS_Pointer<Graphic> &gr)
409 {
410   // called from ViewportAgent
411   // ViewportAgent will actually remove it from display
412
413   gr->set_detached(TRUE);
414   PixmapGraphic *pgraphic = gr->pixmap_graphic();
415   GraphicAgent *ga = new GraphicAgent(node_ptr, gr);
416
417   //gr->set_agent(ga);
418
419   // add graphic agent to list if not already there.
420   add_detached(ga);
421
422   DetachGraphic dg(gr, ga);
423   //pgraphic->UAS_Sender<DetachGraphic>::send_message(dg);
424   UAS_Sender<DetachGraphic>::send_message(dg);
425
426   ga->display() ;
427
428 }
429
430 PixmapGraphic *
431 GraphicsMgr::detached_graphic()
432 {
433     Dimension width, height;
434   
435     Pixmap pixmap = window_system().detached_pixmap (&width, &height); 
436     
437     return new PixmapGraphic(pixmap, width, height,
438                              PixmapGraphic::DETACHED_PIXMAP);
439
440 }
441
442 void
443 GraphicsMgr::reattach_graphic(UAS_Pointer<Graphic> &gr)
444 {
445   Wait_Cursor bob;
446   gr->set_detached(FALSE);
447   ReAttachGraphic rg(gr);
448   UAS_Sender<ReAttachGraphic>::send_message(rg);
449   UAS_String locator_str = gr->locator();
450   GraphicAgent *ga = get_agent(locator_str);
451   remove_detached(ga);
452
453   delete ga;
454 }
455
456 void
457 GraphicsMgr::uncache(Graphic *gr)
458 {
459   ON_DEBUG(cerr << "GraphicsMgr uncache: " << gr << endl);
460   List_Iterator<Graphic* > cursor(&f_graphic_cache) ;
461   for (; cursor; cursor++)
462     {
463       if (cursor.item() == gr)
464         {
465           ON_DEBUG(cerr << "found...uncache" << endl);
466           f_graphic_cache.remove(cursor);
467           break;                // exit, return 
468         }
469     }
470 }
471
472 UAS_Pointer<Graphic>
473 GraphicsMgr::get(UAS_Pointer<UAS_Common> &node_ptr, const char *locator)
474 {
475
476 #if 0
477   // iterate through the list looking for our graphic.
478
479   List_Iterator<Graphic * > cursor (&f_graphic_cache);
480
481   for (; cursor; cursor++)
482     if (cursor.item()->locator() == locator)
483       return cursor.item();
484 #endif
485
486   //Graphic *gr = new Graphic (node_ptr, locator);
487   UAS_Pointer<Graphic> gr(new Graphic (node_ptr, locator));
488
489 #if 0
490   f_graphic_cache.insert (gr);
491 #endif
492
493   if(is_detached(gr))
494   {
495     //init_gr(gr);
496     gr->set_detached(TRUE);
497   }
498
499   return gr;
500 }
501
502 GraphicAgent*
503 GraphicsMgr::get_agent(UAS_String &locator)
504 {
505   // iterate through the list looking for our graphic.
506   // if our graphic is in the list, return it.
507   // Otherwise, return NULL.
508   List_Iterator<GraphicAgent*> dgl (&f_detached_list);
509
510   for (; dgl; dgl++)
511   {
512     UAS_Pointer<Graphic> gr(dgl.item()->graphic());
513     if (gr->locator() == locator)
514       return dgl.item();
515   }
516   return NULL;
517 }
518
519 void
520 GraphicsMgr::add_detached(GraphicAgent *ga)
521 {
522   UAS_Pointer<Graphic> gr(ga->graphic());
523   if(!is_detached(gr))
524     f_detached_list.insert(ga);
525   
526 }
527
528 void
529 GraphicsMgr::remove_detached(GraphicAgent *ga)
530 {
531   // iterate through the list looking for our graphic.
532   // if our graphic is in the list, return it.
533   // Otherwise, return NULL.
534   List_Iterator<GraphicAgent*> dgl (&f_detached_list);
535   if (ga == NULL)
536   {
537     return;
538   }
539   UAS_Pointer<Graphic> oldgr = ga->graphic();
540
541   for (; dgl; dgl++)
542   {
543     UAS_Pointer<Graphic> gr(dgl.item()->graphic());
544     if (gr->locator() == oldgr->locator())
545     {
546       f_detached_list.remove(ga);
547       break;
548     }
549   }
550 }
551
552 bool
553 GraphicsMgr::is_detached(UAS_Pointer<Graphic> &gr)
554 {
555   // iterate through the list looking for our graphic.
556   // if our graphic is in the list, return True.
557   // Otherwise, return False.
558   List_Iterator<GraphicAgent*> dgl (&f_detached_list);
559
560   for (; dgl; dgl++)
561   {
562    UAS_Pointer<Graphic> g = dgl.item()->graphic();
563     if (gr->locator() == g->locator())
564     {
565       return True;
566     }
567   }
568   return False;
569 }
570
571 void
572 GraphicsMgr::init_gr(UAS_Pointer<Graphic> &gr)
573 {
574   //gr->detached_graphic();
575   //gr->pixmap_graphic();
576   gr->set_detached(TRUE);
577   //ga->set_graphic(gr);
578 }
579
580 ///////////////////////////////////////////////////////////////////////////////
581 ///////////////////////////////////////////////////////////////////////////////
582 //
583 //  Graphic implementation
584 //
585 ///////////////////////////////////////////////////////////////////////////////
586 ///////////////////////////////////////////////////////////////////////////////
587
588 Graphic::Graphic (UAS_Pointer<UAS_Common> &doc, const UAS_String &locator):
589         fPixmap (0),
590         fDetachedPixmap (0),
591         fDetached (0),
592         fObj (doc->create_embedded_object (locator)) {
593 }
594
595 Graphic::~Graphic () {
596     //graphics_mgr().uncache(this);
597     //graphics_mgr().remove_detached(this);
598 #ifdef DEBUG
599     printf( "for Graphic %p, delete PixmapGraphic %p\n", this, fPixmap );
600 #endif
601     delete fPixmap;
602     delete fDetachedPixmap;
603 }
604
605
606 // If this one is called instead of the null arg version, the resulting
607 // PixmapGraphic instance is not tracked nor recorded by this instance
608 PixmapGraphic *
609 Graphic::pixmap_graphic (UAS_String& imdata,
610                          unsigned int imlen,
611                          UAS_String& imtype, unsigned short scale) {
612     PixmapGraphic *the_pixmap;
613     //UAS_Pointer<Graphic> tmp(this);
614     //if (fPixmap)
615     //   delete fPixmap;
616
617     the_pixmap = graphics_mgr().get_graphic (imdata, imlen, imtype, scale);
618     return the_pixmap;
619 }
620
621 PixmapGraphic *
622 Graphic::pixmap_graphic () {
623     UAS_Pointer<Graphic> tmp(this);
624     // fPixmap records the PixmapGraphic & pixmap once created (and only
625     // if created via this method) for this instance of Graphic
626     if (!fPixmap)
627         fPixmap = graphics_mgr().get_graphic (tmp);
628     return fPixmap;
629 }
630
631 PixmapGraphic *
632 Graphic::detached_graphic () {
633     if (!fDetachedPixmap)
634         fDetachedPixmap = graphics_mgr().detached_graphic();
635     return fDetachedPixmap;
636 }
637
638 UAS_String Graphic::title()
639 {
640   return fObj->title();
641 }
642
643 UAS_String Graphic::content_type()
644 {
645   return fObj->content_type();
646 }
647
648 UAS_String Graphic::locator()
649 {
650   return fObj->locator() ;
651 }
652
653 UAS_String Graphic::id()
654 {
655   return fObj->id() ;
656 }