1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software 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  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Image display.
33  *
34  * Authors:
35  * Fabien Spindler
36  * Anthony Saunier
37  *
38  *****************************************************************************/
39 
40 /*!
41   \file vpDisplayX.cpp
42   \brief Define the X11 console to display images.
43 */
44 
45 #include <visp3/core/vpConfig.h>
46 #ifdef VISP_HAVE_X11
47 
48 #include <cmath> // std::fabs
49 #include <iostream>
50 #include <limits> // numeric_limits
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 // Display stuff
55 #include <visp3/core/vpDisplay.h>
56 #include <visp3/gui/vpDisplayX.h>
57 
58 // debug / exception
59 #include <visp3/core/vpDebug.h>
60 #include <visp3/core/vpDisplayException.h>
61 
62 // math
63 #include <visp3/core/vpMath.h>
64 
65 /*!
66   Constructor : initialize a display to visualize a gray level image
67   (8 bits).
68 
69   \param I : Image to be displayed (not that image has to be initialized)
70   \param scaleType : If this parameter is set to:
71   - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
72     is fully displayed in the screen;
73   - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
74   same than the image size.
75   - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
76   and the columns.
77   - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
78   and the columns.
79   - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
80   and the columns.
81   - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
82   and the columns.
83 */
vpDisplayX(vpImage<unsigned char> & I,vpScaleType scaleType)84 vpDisplayX::vpDisplayX(vpImage<unsigned char> &I, vpScaleType scaleType)
85   : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
86     screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
87     BShift(0)
88 {
89   setScale(scaleType, I.getWidth(), I.getHeight());
90 
91   init(I);
92 }
93 
94 /*!
95   Constructor : initialize a display to visualize a gray level image
96   (8 bits).
97 
98   \param I : Image to be displayed (not that image has to be initialized)
99   \param x, y : The window is set at position x,y (column index, row index).
100   \param title : Window title.
101   \param scaleType : If this parameter is set to:
102   - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
103     is fully displayed in the screen;
104   - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
105   same than the image size.
106   - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
107   and the columns.
108   - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
109   and the columns.
110   - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
111   and the columns.
112   - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
113   and the columns.
114 */
vpDisplayX(vpImage<unsigned char> & I,int x,int y,const std::string & title,vpScaleType scaleType)115 vpDisplayX::vpDisplayX(vpImage<unsigned char> &I, int x, int y, const std::string &title, vpScaleType scaleType)
116   : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
117     screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
118     BShift(0)
119 {
120   setScale(scaleType, I.getWidth(), I.getHeight());
121   init(I, x, y, title);
122 }
123 
124 /*!
125   Constructor : initialize a display to visualize a RGBa image
126   (32 bits).
127 
128   \param I : Image to be displayed (not that image has to be initialized).
129   \param scaleType : If this parameter is set to:
130   - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
131     is fully displayed in the screen;
132   - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
133   same than the image size.
134   - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
135   and the columns.
136   - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
137   and the columns.
138   - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
139   and the columns.
140   - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
141   and the columns.
142 */
vpDisplayX(vpImage<vpRGBa> & I,vpScaleType scaleType)143 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, vpScaleType scaleType)
144   : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
145     screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
146     BShift(0)
147 {
148   setScale(scaleType, I.getWidth(), I.getHeight());
149   init(I);
150 }
151 
152 /*!
153   Constructor : initialize a display to visualize a RGBa image
154   (32 bits).
155 
156   \param I : Image to be displayed (not that image has to be initialized).
157   \param x, y : The window is set at position x,y (column index, row index).
158   \param title : Window title.
159   \param scaleType : If this parameter is set to:
160   - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
161     is fully displayed in the screen;
162   - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
163   same than the image size.
164   - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
165   and the columns.
166   - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
167   and the columns.
168   - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
169   and the columns.
170   - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
171   and the columns.
172 */
vpDisplayX(vpImage<vpRGBa> & I,int x,int y,const std::string & title,vpScaleType scaleType)173 vpDisplayX::vpDisplayX(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
174   : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
175     screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
176     BShift(0)
177 {
178   setScale(scaleType, I.getWidth(), I.getHeight());
179   init(I, x, y, title);
180 }
181 
182 /*!
183   Constructor that just initialize the display position in the screen
184   and the display title.
185 
186   \param x, y : The window is set at position x,y (column index, row index).
187   \param title : Window title.
188 
189   To initialize the display size, you need to call init().
190 
191   \code
192 #include <visp3/core/vpImage.h>
193 #include <visp3/gui/vpDisplayX.h>
194 
195 int main()
196 {
197   vpDisplayX d(100, 200, "My display");
198   vpImage<unsigned char> I(240, 384);
199   d.init(I);
200 }
201   \endcode
202 */
vpDisplayX(int x,int y,const std::string & title)203 vpDisplayX::vpDisplayX(int x, int y, const std::string &title)
204   : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
205     screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
206     BShift(0)
207 {
208   m_windowXPosition = x;
209   m_windowYPosition = y;
210 
211   m_title = title;
212 }
213 
214 /*!
215   Basic constructor.
216 
217   To initialize the window position, title and size you may call
218   init(vpImage<unsigned char> &, int, int, const std::string &) or
219   init(vpImage<vpRGBa> &, int, int, const std::string &).
220 
221   \code
222 #include <visp3/core/vpImage.h>
223 #include <visp3/gui/vpDisplayX.h>
224 
225 int main()
226 {
227   vpDisplayX d;
228   vpImage<unsigned char> I(240, 384);
229   d.init(I, 100, 200, "My display");
230 }
231   \endcode
232 */
vpDisplayX()233 vpDisplayX::vpDisplayX()
234   : display(NULL), window(), Ximage(NULL), lut(), context(), screen(0), event(), pixmap(), x_color(NULL),
235     screen_depth(8), xcolor(), values(), ximage_data_init(false), RMask(0), GMask(0), BMask(0), RShift(0), GShift(0),
236     BShift(0)
237 {
238 }
239 
240 /*!
241   Destructor.
242 */
~vpDisplayX()243 vpDisplayX::~vpDisplayX() { closeDisplay(); }
244 
245 /*!
246   Initialize the display (size, position and title) of a gray level image.
247 
248   \param I : Image to be displayed (not that image has to be initialized)
249   \param x, y : The window is set at position x,y (column index, row index).
250   \param title : Window title.
251 */
init(vpImage<unsigned char> & I,int x,int y,const std::string & title)252 void vpDisplayX::init(vpImage<unsigned char> &I, int x, int y, const std::string &title)
253 {
254   setScale(m_scaleType, I.getWidth(), I.getHeight());
255 
256   if (x_color == NULL) {
257     // id_unknown = number of predefined colors
258     x_color = new unsigned long[vpColor::id_unknown];
259   }
260 
261   XSizeHints hints;
262   if (x != -1)
263     m_windowXPosition = x;
264   if (y != -1)
265     m_windowYPosition = y;
266 
267   if (!title.empty())
268     m_title = title;
269 
270   // Positionnement de la fenetre dans l'ecran.
271   if ((m_windowXPosition < 0) || (m_windowYPosition < 0)) {
272     hints.flags = 0;
273   } else {
274     hints.flags = USPosition;
275     hints.x = m_windowXPosition;
276     hints.y = m_windowYPosition;
277   }
278 
279   // setup X11 --------------------------------------------------
280   m_width = I.getWidth() / m_scale;
281   m_height = I.getHeight() / m_scale;
282   display = XOpenDisplay(NULL);
283   if (display == NULL) {
284     vpERROR_TRACE("Can't connect display on server %s.\n", XDisplayName(NULL));
285     throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server."));
286   }
287 
288   screen = DefaultScreen(display);
289   lut = DefaultColormap(display, screen);
290   screen_depth = (unsigned int)DefaultDepth(display, screen);
291 
292   if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), m_windowXPosition, m_windowYPosition, m_width,
293                                     m_height, 1, BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
294     vpERROR_TRACE("Can't create window.");
295     throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
296   }
297 
298   //
299   // Create color table for 8 and 16 bits screen
300   //
301   if (screen_depth == 8) {
302     lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
303     xcolor.flags = DoRed | DoGreen | DoBlue;
304 
305     for (unsigned int i = 0; i < 256; i++) {
306       xcolor.pixel = i;
307       xcolor.red = 256 * i;
308       xcolor.green = 256 * i;
309       xcolor.blue = 256 * i;
310       XStoreColor(display, lut, &xcolor);
311     }
312 
313     XSetWindowColormap(display, window, lut);
314     XInstallColormap(display, lut);
315   }
316 
317   else if (screen_depth == 16) {
318     for (unsigned int i = 0; i < 256; i++) {
319       xcolor.pad = 0;
320       xcolor.red = xcolor.green = xcolor.blue = 256 * i;
321       if (XAllocColor(display, lut, &xcolor) == 0) {
322         vpERROR_TRACE("Can't allocate 256 colors. Only %d allocated.", i);
323         throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors."));
324       }
325       colortable[i] = xcolor.pixel;
326     }
327 
328     XSetWindowColormap(display, window, lut);
329     XInstallColormap(display, lut);
330 
331     Visual *visual = DefaultVisual(display, screen);
332     RMask = visual->red_mask;
333     GMask = visual->green_mask;
334     BMask = visual->blue_mask;
335 
336     RShift = 15 - getMsb(RMask); /* these are right-shifts */
337     GShift = 15 - getMsb(GMask);
338     BShift = 15 - getMsb(BMask);
339   }
340 
341   //
342   // Create colors for overlay
343   //
344   switch (screen_depth) {
345   case 8:
346     // Color BLACK and WHITE are set properly by default.
347 
348     // Color LIGHT GRAY.
349     x_color[vpColor::id_lightGray] = 254;
350     xcolor.pixel = x_color[vpColor::id_lightGray];
351     xcolor.red = 256 * 192;
352     xcolor.green = 256 * 192;
353     xcolor.blue = 256 * 192;
354     XStoreColor(display, lut, &xcolor);
355 
356     // Color GRAY.
357     x_color[vpColor::id_gray] = 253;
358     xcolor.pixel = x_color[vpColor::id_gray];
359     xcolor.red = 256 * 128;
360     xcolor.green = 256 * 128;
361     xcolor.blue = 256 * 128;
362     XStoreColor(display, lut, &xcolor);
363 
364     // Color DARK GRAY.
365     x_color[vpColor::id_darkGray] = 252;
366     xcolor.pixel = x_color[vpColor::id_darkGray];
367     xcolor.red = 256 * 64;
368     xcolor.green = 256 * 64;
369     xcolor.blue = 256 * 64;
370     XStoreColor(display, lut, &xcolor);
371 
372     // Color LIGHT RED.
373     x_color[vpColor::id_lightRed] = 251;
374     xcolor.pixel = x_color[vpColor::id_lightRed];
375     xcolor.red = 256 * 255;
376     xcolor.green = 256 * 140;
377     xcolor.blue = 256 * 140;
378     XStoreColor(display, lut, &xcolor);
379 
380     // Color RED.
381     x_color[vpColor::id_red] = 250;
382     xcolor.pixel = x_color[vpColor::id_red];
383     xcolor.red = 256 * 255;
384     xcolor.green = 0;
385     xcolor.blue = 0;
386     XStoreColor(display, lut, &xcolor);
387 
388     // Color DARK RED.
389     x_color[vpColor::id_darkRed] = 249;
390     xcolor.pixel = x_color[vpColor::id_darkRed];
391     xcolor.red = 256 * 128;
392     xcolor.green = 0;
393     xcolor.blue = 0;
394     XStoreColor(display, lut, &xcolor);
395 
396     // Color LIGHT GREEN.
397     x_color[vpColor::id_lightGreen] = 248;
398     xcolor.pixel = x_color[vpColor::id_lightGreen];
399     xcolor.red = 256 * 140;
400     xcolor.green = 256 * 255;
401     xcolor.blue = 256 * 140;
402     XStoreColor(display, lut, &xcolor);
403 
404     // Color GREEN.
405     x_color[vpColor::id_green] = 247;
406     xcolor.pixel = x_color[vpColor::id_green];
407     xcolor.red = 0;
408     xcolor.green = 256 * 255;
409     xcolor.blue = 0;
410     XStoreColor(display, lut, &xcolor);
411 
412     // Color DARK GREEN.
413     x_color[vpColor::id_darkGreen] = 246;
414     xcolor.pixel = x_color[vpColor::id_darkGreen];
415     xcolor.red = 0;
416     xcolor.green = 256 * 128;
417     xcolor.blue = 0;
418     XStoreColor(display, lut, &xcolor);
419 
420     // Color LIGHT BLUE.
421     x_color[vpColor::id_lightBlue] = 245;
422     xcolor.pixel = x_color[vpColor::id_lightBlue];
423     xcolor.red = 256 * 140;
424     xcolor.green = 256 * 140;
425     xcolor.blue = 256 * 255;
426     XStoreColor(display, lut, &xcolor);
427 
428     // Color BLUE.
429     x_color[vpColor::id_blue] = 244;
430     xcolor.pixel = x_color[vpColor::id_blue];
431     xcolor.red = 0;
432     xcolor.green = 0;
433     xcolor.blue = 256 * 255;
434     XStoreColor(display, lut, &xcolor);
435 
436     // Color DARK BLUE.
437     x_color[vpColor::id_darkBlue] = 243;
438     xcolor.pixel = x_color[vpColor::id_darkBlue];
439     xcolor.red = 0;
440     xcolor.green = 0;
441     xcolor.blue = 256 * 128;
442     XStoreColor(display, lut, &xcolor);
443 
444     // Color YELLOW.
445     x_color[vpColor::id_yellow] = 242;
446     xcolor.pixel = x_color[vpColor::id_yellow];
447     xcolor.red = 256 * 255;
448     xcolor.green = 256 * 255;
449     xcolor.blue = 0;
450     XStoreColor(display, lut, &xcolor);
451 
452     // Color ORANGE.
453     x_color[vpColor::id_orange] = 241;
454     xcolor.pixel = x_color[vpColor::id_orange];
455     xcolor.red = 256 * 255;
456     xcolor.green = 256 * 165;
457     xcolor.blue = 0;
458     XStoreColor(display, lut, &xcolor);
459 
460     // Color CYAN.
461     x_color[vpColor::id_cyan] = 240;
462     xcolor.pixel = x_color[vpColor::id_cyan];
463     xcolor.red = 0;
464     xcolor.green = 256 * 255;
465     xcolor.blue = 256 * 255;
466     XStoreColor(display, lut, &xcolor);
467 
468     // Color PURPLE.
469     x_color[vpColor::id_purple] = 239;
470     xcolor.pixel = x_color[vpColor::id_purple];
471     xcolor.red = 256 * 128;
472     xcolor.green = 0;
473     xcolor.blue = 256 * 128;
474     XStoreColor(display, lut, &xcolor);
475 
476     break;
477 
478   case 16:
479   case 24:
480   case 32: {
481     xcolor.flags = DoRed | DoGreen | DoBlue;
482 
483     // Couleur BLACK.
484     xcolor.pad = 0;
485     xcolor.red = 0;
486     xcolor.green = 0;
487     xcolor.blue = 0;
488     XAllocColor(display, lut, &xcolor);
489     x_color[vpColor::id_black] = xcolor.pixel;
490 
491     // Couleur WHITE.
492     xcolor.pad = 0;
493     xcolor.red = 256 * 255;
494     xcolor.green = 256 * 255;
495     xcolor.blue = 256 * 255;
496     XAllocColor(display, lut, &xcolor);
497     x_color[vpColor::id_white] = xcolor.pixel;
498 
499     // Couleur LIGHT GRAY.
500     xcolor.pad = 0;
501     xcolor.red = 256 * 192;
502     xcolor.green = 256 * 192;
503     xcolor.blue = 256 * 192;
504     XAllocColor(display, lut, &xcolor);
505     x_color[vpColor::id_lightGray] = xcolor.pixel;
506 
507     // Couleur GRAY.
508     xcolor.pad = 0;
509     xcolor.red = 256 * 128;
510     xcolor.green = 256 * 128;
511     xcolor.blue = 256 * 128;
512     XAllocColor(display, lut, &xcolor);
513     x_color[vpColor::id_gray] = xcolor.pixel;
514 
515     // Couleur DARK GRAY.
516     xcolor.pad = 0;
517     xcolor.red = 256 * 64;
518     xcolor.green = 256 * 64;
519     xcolor.blue = 256 * 64;
520     XAllocColor(display, lut, &xcolor);
521     x_color[vpColor::id_darkGray] = xcolor.pixel;
522 
523     // Couleur LIGHT RED.
524     xcolor.pad = 0;
525     xcolor.red = 256 * 255;
526     xcolor.green = 256 * 140;
527     xcolor.blue = 256 * 140;
528     XAllocColor(display, lut, &xcolor);
529     x_color[vpColor::id_lightRed] = xcolor.pixel;
530 
531     // Couleur RED.
532     xcolor.pad = 0;
533     xcolor.red = 256 * 255;
534     xcolor.green = 0;
535     xcolor.blue = 0;
536     XAllocColor(display, lut, &xcolor);
537     x_color[vpColor::id_red] = xcolor.pixel;
538 
539     // Couleur DARK RED.
540     xcolor.pad = 0;
541     xcolor.red = 256 * 128;
542     xcolor.green = 0;
543     xcolor.blue = 0;
544     XAllocColor(display, lut, &xcolor);
545     x_color[vpColor::id_darkRed] = xcolor.pixel;
546 
547     // Couleur LIGHT GREEN.
548     xcolor.pad = 0;
549     xcolor.red = 256 * 140;
550     xcolor.green = 256 * 255;
551     xcolor.blue = 256 * 140;
552     XAllocColor(display, lut, &xcolor);
553     x_color[vpColor::id_lightGreen] = xcolor.pixel;
554 
555     // Couleur GREEN.
556     xcolor.pad = 0;
557     xcolor.red = 0;
558     xcolor.green = 256 * 255;
559     xcolor.blue = 0;
560     XAllocColor(display, lut, &xcolor);
561     x_color[vpColor::id_green] = xcolor.pixel;
562 
563     // Couleur DARK GREEN.
564     xcolor.pad = 0;
565     xcolor.red = 0;
566     xcolor.green = 256 * 128;
567     xcolor.blue = 0;
568     XAllocColor(display, lut, &xcolor);
569     x_color[vpColor::id_darkGreen] = xcolor.pixel;
570 
571     // Couleur LIGHT Blue.
572     xcolor.pad = 0;
573     xcolor.red = 256 * 140;
574     xcolor.green = 256 * 140;
575     xcolor.blue = 256 * 255;
576     XAllocColor(display, lut, &xcolor);
577     x_color[vpColor::id_lightBlue] = xcolor.pixel;
578 
579     // Couleur BLUE.
580     xcolor.pad = 0;
581     xcolor.red = 0;
582     xcolor.green = 0;
583     xcolor.blue = 256 * 255;
584     XAllocColor(display, lut, &xcolor);
585     x_color[vpColor::id_blue] = xcolor.pixel;
586 
587     // Couleur DARK BLUE.
588     xcolor.pad = 0;
589     xcolor.red = 0;
590     xcolor.green = 0;
591     xcolor.blue = 256 * 128;
592     XAllocColor(display, lut, &xcolor);
593     x_color[vpColor::id_darkBlue] = xcolor.pixel;
594 
595     // Couleur YELLOW.
596     xcolor.pad = 0;
597     xcolor.red = 256 * 255;
598     xcolor.green = 256 * 255;
599     xcolor.blue = 0;
600     XAllocColor(display, lut, &xcolor);
601     x_color[vpColor::id_yellow] = xcolor.pixel;
602 
603     // Couleur ORANGE.
604     xcolor.pad = 0;
605     xcolor.red = 256 * 255;
606     xcolor.green = 256 * 165;
607     xcolor.blue = 0;
608     XAllocColor(display, lut, &xcolor);
609     x_color[vpColor::id_orange] = xcolor.pixel;
610 
611     // Couleur CYAN.
612     xcolor.pad = 0;
613     xcolor.red = 0;
614     xcolor.green = 256 * 255;
615     xcolor.blue = 256 * 255;
616     XAllocColor(display, lut, &xcolor);
617     x_color[vpColor::id_cyan] = xcolor.pixel;
618 
619     // Couleur PURPLE.
620     xcolor.pad = 0;
621     xcolor.red = 256 * 128;
622     xcolor.green = 0;
623     xcolor.blue = 256 * 128;
624     XAllocColor(display, lut, &xcolor);
625     x_color[vpColor::id_purple] = xcolor.pixel;
626     break;
627   }
628   }
629 
630   XSetStandardProperties(display, window, this->m_title.c_str(), this->m_title.c_str(), None, 0, 0, &hints);
631   XMapWindow(display, window);
632   // Selection des evenements.
633   XSelectInput(display, window,
634                ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
635                    StructureNotifyMask | PointerMotionMask);
636 
637   // graphic context creation
638   values.plane_mask = AllPlanes;
639   values.fill_style = FillSolid;
640   values.foreground = WhitePixel(display, screen);
641   values.background = BlackPixel(display, screen);
642   context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
643 
644   if (context == NULL) {
645     vpERROR_TRACE("Can't create graphics context.");
646     throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
647   }
648 
649   // Pixmap creation.
650   pixmap = XCreatePixmap(display, window, m_width, m_height, screen_depth);
651 
652   // Hangs when forward X11 is used to send the display to an other computer
653   //  do
654   //    XNextEvent ( display, &event );
655   //  while ( event.xany.type != Expose );
656 
657   {
658     Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, NULL, m_width, m_height,
659                           XBitmapPad(display), 0);
660 
661     Ximage->data = (char *)malloc(m_height * (unsigned int)Ximage->bytes_per_line);
662     ximage_data_init = true;
663   }
664   m_displayHasBeenInitialized = true;
665 
666   XStoreName(display, window, m_title.c_str());
667 
668   XSync(display, 1);
669 
670   I.display = this;
671 }
672 
673 /*!
674   Initialize the display (size, position and title) of a color
675   image in RGBa format.
676 
677   \param I : Image to be displayed (note that image has to be initialized)
678   \param x, y : The window is set at position x,y (column index, row index).
679   \param title : Window title.
680 */
init(vpImage<vpRGBa> & I,int x,int y,const std::string & title)681 void vpDisplayX::init(vpImage<vpRGBa> &I, int x, int y, const std::string &title)
682 {
683   setScale(m_scaleType, I.getWidth(), I.getHeight());
684 
685   XSizeHints hints;
686   if (x != -1)
687     m_windowXPosition = x;
688   if (y != -1)
689     m_windowYPosition = y;
690 
691   if (x_color == NULL) {
692     // id_unknown = number of predefined colors
693     x_color = new unsigned long[vpColor::id_unknown];
694   }
695 
696   if (!title.empty())
697     m_title = title;
698 
699   // Positionnement de la fenetre dans l'ecran.
700   if ((m_windowXPosition < 0) || (m_windowYPosition < 0)) {
701     hints.flags = 0;
702   } else {
703     hints.flags = USPosition;
704     hints.x = m_windowXPosition;
705     hints.y = m_windowYPosition;
706   }
707 
708   // setup X11 --------------------------------------------------
709   m_width = I.getWidth() / m_scale;
710   m_height = I.getHeight() / m_scale;
711 
712   if ((display = XOpenDisplay(NULL)) == NULL) {
713     vpERROR_TRACE("Can't connect display on server %s.\n", XDisplayName(NULL));
714     throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server."));
715   }
716 
717   screen = DefaultScreen(display);
718   lut = DefaultColormap(display, screen);
719   screen_depth = (unsigned int)DefaultDepth(display, screen);
720 
721   vpDEBUG_TRACE(1, "Screen depth: %d\n", screen_depth);
722 
723   if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), m_windowXPosition, m_windowYPosition, m_width,
724                                     m_height, 1, BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
725     vpERROR_TRACE("Can't create window.");
726     throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
727   }
728 
729   //
730   // Create color table for 8 and 16 bits screen
731   //
732   if (screen_depth == 8) {
733     lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
734     xcolor.flags = DoRed | DoGreen | DoBlue;
735 
736     for (unsigned int i = 0; i < 256; i++) {
737       xcolor.pixel = i;
738       xcolor.red = 256 * i;
739       xcolor.green = 256 * i;
740       xcolor.blue = 256 * i;
741       XStoreColor(display, lut, &xcolor);
742     }
743 
744     XSetWindowColormap(display, window, lut);
745     XInstallColormap(display, lut);
746   }
747 
748   else if (screen_depth == 16) {
749     for (unsigned int i = 0; i < 256; i++) {
750       xcolor.pad = 0;
751       xcolor.red = xcolor.green = xcolor.blue = 256 * i;
752       if (XAllocColor(display, lut, &xcolor) == 0) {
753         vpERROR_TRACE("Can't allocate 256 colors. Only %d allocated.", i);
754         throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors."));
755       }
756       colortable[i] = xcolor.pixel;
757     }
758 
759     Visual *visual = DefaultVisual(display, screen);
760     RMask = visual->red_mask;
761     GMask = visual->green_mask;
762     BMask = visual->blue_mask;
763 
764     RShift = 15 - getMsb(RMask); /* these are right-shifts */
765     GShift = 15 - getMsb(GMask);
766     BShift = 15 - getMsb(BMask);
767 
768     XSetWindowColormap(display, window, lut);
769     XInstallColormap(display, lut);
770   }
771 
772   //
773   // Create colors for overlay
774   //
775   switch (screen_depth) {
776 
777   case 8:
778     // Color BLACK and WHITE are set properly.
779 
780     // Color LIGHT GRAY.
781     x_color[vpColor::id_lightGray] = 254;
782     xcolor.pixel = x_color[vpColor::id_lightGray];
783     xcolor.red = 256 * 192;
784     xcolor.green = 256 * 192;
785     xcolor.blue = 256 * 192;
786     XStoreColor(display, lut, &xcolor);
787 
788     // Color GRAY.
789     x_color[vpColor::id_gray] = 253;
790     xcolor.pixel = x_color[vpColor::id_gray];
791     xcolor.red = 256 * 128;
792     xcolor.green = 256 * 128;
793     xcolor.blue = 256 * 128;
794     XStoreColor(display, lut, &xcolor);
795 
796     // Color DARK GRAY.
797     x_color[vpColor::id_darkGray] = 252;
798     xcolor.pixel = x_color[vpColor::id_darkGray];
799     xcolor.red = 256 * 64;
800     xcolor.green = 256 * 64;
801     xcolor.blue = 256 * 64;
802     XStoreColor(display, lut, &xcolor);
803 
804     // Color LIGHT RED.
805     x_color[vpColor::id_lightRed] = 251;
806     xcolor.pixel = x_color[vpColor::id_lightRed];
807     xcolor.red = 256 * 255;
808     xcolor.green = 256 * 140;
809     xcolor.blue = 256 * 140;
810     XStoreColor(display, lut, &xcolor);
811 
812     // Color RED.
813     x_color[vpColor::id_red] = 250;
814     xcolor.pixel = x_color[vpColor::id_red];
815     xcolor.red = 256 * 255;
816     xcolor.green = 0;
817     xcolor.blue = 0;
818     XStoreColor(display, lut, &xcolor);
819 
820     // Color DARK RED.
821     x_color[vpColor::id_darkRed] = 249;
822     xcolor.pixel = x_color[vpColor::id_darkRed];
823     xcolor.red = 256 * 128;
824     xcolor.green = 0;
825     xcolor.blue = 0;
826     XStoreColor(display, lut, &xcolor);
827 
828     // Color LIGHT GREEN.
829     x_color[vpColor::id_lightGreen] = 248;
830     xcolor.pixel = x_color[vpColor::id_lightGreen];
831     xcolor.red = 256 * 140;
832     xcolor.green = 256 * 255;
833     xcolor.blue = 256 * 140;
834     XStoreColor(display, lut, &xcolor);
835 
836     // Color GREEN.
837     x_color[vpColor::id_green] = 247;
838     xcolor.pixel = x_color[vpColor::id_green];
839     xcolor.red = 0;
840     xcolor.green = 256 * 255;
841     xcolor.blue = 0;
842     XStoreColor(display, lut, &xcolor);
843 
844     // Color DARK GREEN.
845     x_color[vpColor::id_darkGreen] = 246;
846     xcolor.pixel = x_color[vpColor::id_darkGreen];
847     xcolor.red = 0;
848     xcolor.green = 256 * 128;
849     xcolor.blue = 0;
850     XStoreColor(display, lut, &xcolor);
851 
852     // Color LIGHT BLUE.
853     x_color[vpColor::id_lightBlue] = 245;
854     xcolor.pixel = x_color[vpColor::id_lightBlue];
855     xcolor.red = 256 * 140;
856     xcolor.green = 256 * 140;
857     xcolor.blue = 256 * 255;
858     XStoreColor(display, lut, &xcolor);
859 
860     // Color BLUE.
861     x_color[vpColor::id_blue] = 244;
862     xcolor.pixel = x_color[vpColor::id_blue];
863     xcolor.red = 0;
864     xcolor.green = 0;
865     xcolor.blue = 256 * 255;
866     XStoreColor(display, lut, &xcolor);
867 
868     // Color DARK BLUE.
869     x_color[vpColor::id_darkBlue] = 243;
870     xcolor.pixel = x_color[vpColor::id_darkBlue];
871     xcolor.red = 0;
872     xcolor.green = 0;
873     xcolor.blue = 256 * 128;
874     XStoreColor(display, lut, &xcolor);
875 
876     // Color YELLOW.
877     x_color[vpColor::id_yellow] = 242;
878     xcolor.pixel = x_color[vpColor::id_yellow];
879     xcolor.red = 256 * 255;
880     xcolor.green = 256 * 255;
881     xcolor.blue = 0;
882     XStoreColor(display, lut, &xcolor);
883 
884     // Color ORANGE.
885     x_color[vpColor::id_orange] = 241;
886     xcolor.pixel = x_color[vpColor::id_orange];
887     xcolor.red = 256 * 255;
888     xcolor.green = 256 * 165;
889     xcolor.blue = 0;
890     XStoreColor(display, lut, &xcolor);
891 
892     // Color CYAN.
893     x_color[vpColor::id_cyan] = 240;
894     xcolor.pixel = x_color[vpColor::id_cyan];
895     xcolor.red = 0;
896     xcolor.green = 256 * 255;
897     xcolor.blue = 256 * 255;
898     XStoreColor(display, lut, &xcolor);
899 
900     // Color PURPLE.
901     x_color[vpColor::id_purple] = 239;
902     xcolor.pixel = x_color[vpColor::id_purple];
903     xcolor.red = 256 * 128;
904     xcolor.green = 0;
905     xcolor.blue = 256 * 128;
906     XStoreColor(display, lut, &xcolor);
907 
908     break;
909 
910   case 16:
911   case 24:
912   case 32: {
913     xcolor.flags = DoRed | DoGreen | DoBlue;
914 
915     // Couleur BLACK.
916     xcolor.pad = 0;
917     xcolor.red = 0;
918     xcolor.green = 0;
919     xcolor.blue = 0;
920     XAllocColor(display, lut, &xcolor);
921     x_color[vpColor::id_black] = xcolor.pixel;
922 
923     // Couleur WHITE.
924     xcolor.pad = 0;
925     xcolor.red = 256 * 255;
926     xcolor.green = 256 * 255;
927     xcolor.blue = 256 * 255;
928     XAllocColor(display, lut, &xcolor);
929     x_color[vpColor::id_white] = xcolor.pixel;
930 
931     // Couleur LIGHT GRAY.
932     xcolor.pad = 0;
933     xcolor.red = 256 * 192;
934     xcolor.green = 256 * 192;
935     xcolor.blue = 256 * 192;
936     XAllocColor(display, lut, &xcolor);
937     x_color[vpColor::id_lightGray] = xcolor.pixel;
938 
939     // Couleur GRAY.
940     xcolor.pad = 0;
941     xcolor.red = 256 * 128;
942     xcolor.green = 256 * 128;
943     xcolor.blue = 256 * 128;
944     XAllocColor(display, lut, &xcolor);
945     x_color[vpColor::id_gray] = xcolor.pixel;
946 
947     // Couleur DARK GRAY.
948     xcolor.pad = 0;
949     xcolor.red = 256 * 64;
950     xcolor.green = 256 * 64;
951     xcolor.blue = 256 * 64;
952     XAllocColor(display, lut, &xcolor);
953     x_color[vpColor::id_darkGray] = xcolor.pixel;
954 
955     // Couleur LIGHT RED.
956     xcolor.pad = 0;
957     xcolor.red = 256 * 255;
958     xcolor.green = 256 * 140;
959     xcolor.blue = 256 * 140;
960     XAllocColor(display, lut, &xcolor);
961     x_color[vpColor::id_lightRed] = xcolor.pixel;
962 
963     // Couleur RED.
964     xcolor.pad = 0;
965     xcolor.red = 256 * 255;
966     xcolor.green = 0;
967     xcolor.blue = 0;
968     XAllocColor(display, lut, &xcolor);
969     x_color[vpColor::id_red] = xcolor.pixel;
970 
971     // Couleur DARK RED.
972     xcolor.pad = 0;
973     xcolor.red = 256 * 128;
974     xcolor.green = 0;
975     xcolor.blue = 0;
976     XAllocColor(display, lut, &xcolor);
977     x_color[vpColor::id_darkRed] = xcolor.pixel;
978 
979     // Couleur LIGHT GREEN.
980     xcolor.pad = 0;
981     xcolor.red = 256 * 140;
982     xcolor.green = 256 * 255;
983     xcolor.blue = 256 * 140;
984     XAllocColor(display, lut, &xcolor);
985     x_color[vpColor::id_lightGreen] = xcolor.pixel;
986 
987     // Couleur GREEN.
988     xcolor.pad = 0;
989     xcolor.red = 0;
990     xcolor.green = 256 * 255;
991     xcolor.blue = 0;
992     XAllocColor(display, lut, &xcolor);
993     x_color[vpColor::id_green] = xcolor.pixel;
994 
995     // Couleur DARK GREEN.
996     xcolor.pad = 0;
997     xcolor.red = 0;
998     xcolor.green = 256 * 128;
999     xcolor.blue = 0;
1000     XAllocColor(display, lut, &xcolor);
1001     x_color[vpColor::id_darkGreen] = xcolor.pixel;
1002 
1003     // Couleur LIGHT Blue.
1004     xcolor.pad = 0;
1005     xcolor.red = 256 * 140;
1006     xcolor.green = 256 * 140;
1007     xcolor.blue = 256 * 255;
1008     XAllocColor(display, lut, &xcolor);
1009     x_color[vpColor::id_lightBlue] = xcolor.pixel;
1010 
1011     // Couleur BLUE.
1012     xcolor.pad = 0;
1013     xcolor.red = 0;
1014     xcolor.green = 0;
1015     xcolor.blue = 256 * 255;
1016     XAllocColor(display, lut, &xcolor);
1017     x_color[vpColor::id_blue] = xcolor.pixel;
1018 
1019     // Couleur DARK BLUE.
1020     xcolor.pad = 0;
1021     xcolor.red = 0;
1022     xcolor.green = 0;
1023     xcolor.blue = 256 * 128;
1024     XAllocColor(display, lut, &xcolor);
1025     x_color[vpColor::id_darkBlue] = xcolor.pixel;
1026 
1027     // Couleur YELLOW.
1028     xcolor.pad = 0;
1029     xcolor.red = 256 * 255;
1030     xcolor.green = 256 * 255;
1031     xcolor.blue = 0;
1032     XAllocColor(display, lut, &xcolor);
1033     x_color[vpColor::id_yellow] = xcolor.pixel;
1034 
1035     // Couleur ORANGE.
1036     xcolor.pad = 0;
1037     xcolor.red = 256 * 255;
1038     xcolor.green = 256 * 165;
1039     xcolor.blue = 0;
1040     XAllocColor(display, lut, &xcolor);
1041     x_color[vpColor::id_orange] = xcolor.pixel;
1042 
1043     // Couleur CYAN.
1044     xcolor.pad = 0;
1045     xcolor.red = 0;
1046     xcolor.green = 256 * 255;
1047     xcolor.blue = 256 * 255;
1048     XAllocColor(display, lut, &xcolor);
1049     x_color[vpColor::id_cyan] = xcolor.pixel;
1050 
1051     // Couleur PURPLE.
1052     xcolor.pad = 0;
1053     xcolor.red = 256 * 128;
1054     xcolor.green = 0;
1055     xcolor.blue = 256 * 128;
1056     XAllocColor(display, lut, &xcolor);
1057     x_color[vpColor::id_purple] = xcolor.pixel;
1058     break;
1059   }
1060   }
1061 
1062   XSetStandardProperties(display, window, this->m_title.c_str(), this->m_title.c_str(), None, 0, 0, &hints);
1063   XMapWindow(display, window);
1064   // Selection des evenements.
1065   XSelectInput(display, window,
1066                ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
1067                    StructureNotifyMask | PointerMotionMask);
1068 
1069   // Creation du contexte graphique
1070   values.plane_mask = AllPlanes;
1071   values.fill_style = FillSolid;
1072   values.foreground = WhitePixel(display, screen);
1073   values.background = BlackPixel(display, screen);
1074   context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
1075 
1076   if (context == NULL) {
1077     vpERROR_TRACE("Can't create graphics context.");
1078     throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
1079   }
1080 
1081   // Pixmap creation.
1082   pixmap = XCreatePixmap(display, window, m_width, m_height, screen_depth);
1083 
1084   // Hangs when forward X11 is used to send the display to an other computer
1085   //  do
1086   //    XNextEvent ( display, &event );
1087   //  while ( event.xany.type != Expose );
1088 
1089   {
1090     Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, NULL, m_width, m_height,
1091                           XBitmapPad(display), 0);
1092 
1093     Ximage->data = (char *)malloc(m_height * (unsigned int)Ximage->bytes_per_line);
1094     ximage_data_init = true;
1095   }
1096   m_displayHasBeenInitialized = true;
1097 
1098   XSync(display, true);
1099 
1100   XStoreName(display, window, m_title.c_str());
1101 
1102   I.display = this;
1103 }
1104 
1105 /*!
1106   Initialize the display size, position and title.
1107 
1108   \param w, h : Width and height of the window.
1109   \param x, y : The window is set at position x,y (column index, row index).
1110   \param title : Window title.
1111 */
init(unsigned int w,unsigned int h,int x,int y,const std::string & title)1112 void vpDisplayX::init(unsigned int w, unsigned int h, int x, int y, const std::string &title)
1113 {
1114   setScale(m_scaleType, w, h);
1115 
1116   if (x_color == NULL) {
1117     // id_unknown = number of predefined colors
1118     x_color = new unsigned long[vpColor::id_unknown];
1119   }
1120   /* setup X11 -------------------------------------------------------------
1121    */
1122   this->m_width = w / m_scale;
1123   this->m_height = h / m_scale;
1124 
1125   XSizeHints hints;
1126 
1127   if (x != -1)
1128     m_windowXPosition = x;
1129   if (y != -1)
1130     m_windowYPosition = y;
1131   // Positionnement de la fenetre dans l'ecran.
1132   if ((m_windowXPosition < 0) || (m_windowYPosition < 0)) {
1133     hints.flags = 0;
1134   } else {
1135     hints.flags = USPosition;
1136     hints.x = m_windowXPosition;
1137     hints.y = m_windowYPosition;
1138   }
1139 
1140   m_title = title;
1141 
1142   if ((display = XOpenDisplay(NULL)) == NULL) {
1143     vpERROR_TRACE("Can't connect display on server %s.\n", XDisplayName(NULL));
1144     throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server."));
1145   }
1146 
1147   screen = DefaultScreen(display);
1148   lut = DefaultColormap(display, screen);
1149   screen_depth = (unsigned int)DefaultDepth(display, screen);
1150 
1151   vpTRACE("Screen depth: %d\n", screen_depth);
1152 
1153   if ((window = XCreateSimpleWindow(display, RootWindow(display, screen), m_windowXPosition, m_windowYPosition, m_width,
1154                                     m_height, 1, BlackPixel(display, screen), WhitePixel(display, screen))) == 0) {
1155     vpERROR_TRACE("Can't create window.");
1156     throw(vpDisplayException(vpDisplayException::cannotOpenWindowError, "Can't create window."));
1157   }
1158 
1159   //
1160   // Create color table for 8 and 16 bits screen
1161   //
1162   if (screen_depth == 8) {
1163     lut = XCreateColormap(display, window, DefaultVisual(display, screen), AllocAll);
1164     xcolor.flags = DoRed | DoGreen | DoBlue;
1165 
1166     for (unsigned int i = 0; i < 256; i++) {
1167       xcolor.pixel = i;
1168       xcolor.red = 256 * i;
1169       xcolor.green = 256 * i;
1170       xcolor.blue = 256 * i;
1171       XStoreColor(display, lut, &xcolor);
1172     }
1173 
1174     XSetWindowColormap(display, window, lut);
1175     XInstallColormap(display, lut);
1176   }
1177 
1178   else if (screen_depth == 16) {
1179     for (unsigned int i = 0; i < 256; i++) {
1180       xcolor.pad = 0;
1181       xcolor.red = xcolor.green = xcolor.blue = 256 * i;
1182       if (XAllocColor(display, lut, &xcolor) == 0) {
1183         vpERROR_TRACE("Can't allocate 256 colors. Only %d allocated.", i);
1184         throw(vpDisplayException(vpDisplayException::colorAllocError, "Can't allocate 256 colors."));
1185       }
1186       colortable[i] = xcolor.pixel;
1187     }
1188 
1189     XSetWindowColormap(display, window, lut);
1190     XInstallColormap(display, lut);
1191 
1192     Visual *visual = DefaultVisual(display, screen);
1193     RMask = visual->red_mask;
1194     GMask = visual->green_mask;
1195     BMask = visual->blue_mask;
1196 
1197     RShift = 15 - getMsb(RMask); /* these are right-shifts */
1198     GShift = 15 - getMsb(GMask);
1199     BShift = 15 - getMsb(BMask);
1200   }
1201 
1202   vpColor pcolor; // predefined colors
1203 
1204   //
1205   // Create colors for overlay
1206   //
1207   switch (screen_depth) {
1208 
1209   case 8:
1210     // Color BLACK: default set to 0
1211 
1212     // Color WHITE: default set to 255
1213 
1214     // Color LIGHT GRAY.
1215     pcolor = vpColor::lightGray;
1216     xcolor.pixel = 254; // affected to 254
1217     xcolor.red = 256 * pcolor.R;
1218     xcolor.green = 256 * pcolor.G;
1219     xcolor.blue = 256 * pcolor.B;
1220     XStoreColor(display, lut, &xcolor);
1221 
1222     // Color GRAY.
1223     pcolor = vpColor::gray;
1224     xcolor.pixel = 253; // affected to 253
1225     xcolor.red = 256 * pcolor.R;
1226     xcolor.green = 256 * pcolor.G;
1227     xcolor.blue = 256 * pcolor.B;
1228     XStoreColor(display, lut, &xcolor);
1229 
1230     // Color DARK GRAY.
1231     pcolor = vpColor::darkGray;
1232     xcolor.pixel = 252; // affected to 252
1233     xcolor.red = 256 * pcolor.R;
1234     xcolor.green = 256 * pcolor.G;
1235     xcolor.blue = 256 * pcolor.B;
1236     XStoreColor(display, lut, &xcolor);
1237 
1238     // Color LIGHT RED.
1239     pcolor = vpColor::lightRed;
1240     xcolor.pixel = 251; // affected to 251
1241     xcolor.red = 256 * pcolor.R;
1242     xcolor.green = 256 * pcolor.G;
1243     xcolor.blue = 256 * pcolor.B;
1244     XStoreColor(display, lut, &xcolor);
1245 
1246     // Color RED.
1247     pcolor = vpColor::red;
1248     xcolor.pixel = 250; // affected to 250
1249     xcolor.red = 256 * pcolor.R;
1250     xcolor.green = 256 * pcolor.G;
1251     xcolor.blue = 256 * pcolor.B;
1252     XStoreColor(display, lut, &xcolor);
1253 
1254     // Color DARK RED.
1255     pcolor = vpColor::darkRed;
1256     xcolor.pixel = 249; // affected to 249
1257     xcolor.red = 256 * pcolor.R;
1258     xcolor.green = 256 * pcolor.G;
1259     xcolor.blue = 256 * pcolor.B;
1260     XStoreColor(display, lut, &xcolor);
1261 
1262     // Color LIGHT GREEN.
1263     pcolor = vpColor::lightGreen;
1264     xcolor.pixel = 248; // affected to 248
1265     xcolor.red = 256 * pcolor.R;
1266     xcolor.green = 256 * pcolor.G;
1267     xcolor.blue = 256 * pcolor.B;
1268     XStoreColor(display, lut, &xcolor);
1269 
1270     // Color GREEN.
1271     pcolor = vpColor::green;
1272     xcolor.pixel = 247; // affected to 247
1273     xcolor.red = 256 * pcolor.R;
1274     xcolor.green = 256 * pcolor.G;
1275     xcolor.blue = 256 * pcolor.B;
1276     XStoreColor(display, lut, &xcolor);
1277 
1278     // Color DARK GREEN.
1279     pcolor = vpColor::darkGreen;
1280     xcolor.pixel = 246; // affected to 246
1281     xcolor.red = 256 * pcolor.R;
1282     xcolor.green = 256 * pcolor.G;
1283     xcolor.blue = 256 * pcolor.B;
1284     XStoreColor(display, lut, &xcolor);
1285 
1286     // Color LIGHT BLUE.
1287     pcolor = vpColor::lightBlue;
1288     xcolor.pixel = 245; // affected to 245
1289     xcolor.red = 256 * pcolor.R;
1290     xcolor.green = 256 * pcolor.G;
1291     xcolor.blue = 256 * pcolor.B;
1292     XStoreColor(display, lut, &xcolor);
1293 
1294     // Color BLUE.
1295     pcolor = vpColor::blue;
1296     xcolor.pixel = 244; // affected to 244
1297     xcolor.red = 256 * pcolor.R;
1298     xcolor.green = 256 * pcolor.G;
1299     xcolor.blue = 256 * pcolor.B;
1300     XStoreColor(display, lut, &xcolor);
1301 
1302     // Color DARK BLUE.
1303     pcolor = vpColor::darkBlue;
1304     xcolor.pixel = 243; // affected to 243
1305     xcolor.red = 256 * pcolor.R;
1306     xcolor.green = 256 * pcolor.G;
1307     xcolor.blue = 256 * pcolor.B;
1308     XStoreColor(display, lut, &xcolor);
1309 
1310     // Color YELLOW.
1311     pcolor = vpColor::yellow;
1312     xcolor.pixel = 242; // affected to 242
1313     xcolor.red = 256 * pcolor.R;
1314     xcolor.green = 256 * pcolor.G;
1315     xcolor.blue = 256 * pcolor.B;
1316     XStoreColor(display, lut, &xcolor);
1317 
1318     // Color ORANGE.
1319     pcolor = vpColor::orange;
1320     xcolor.pixel = 241; // affected to 241
1321     xcolor.red = 256 * pcolor.R;
1322     xcolor.green = 256 * pcolor.G;
1323     xcolor.blue = 256 * pcolor.B;
1324     XStoreColor(display, lut, &xcolor);
1325 
1326     // Color CYAN.
1327     pcolor = vpColor::cyan;
1328     xcolor.pixel = 240; // affected to 240
1329     xcolor.red = 256 * pcolor.R;
1330     xcolor.green = 256 * pcolor.G;
1331     xcolor.blue = 256 * pcolor.B;
1332     XStoreColor(display, lut, &xcolor);
1333 
1334     // Color PURPLE.
1335     pcolor = vpColor::purple;
1336     xcolor.pixel = 239; // affected to 239
1337     xcolor.red = 256 * pcolor.R;
1338     xcolor.green = 256 * pcolor.G;
1339     xcolor.blue = 256 * pcolor.B;
1340     XStoreColor(display, lut, &xcolor);
1341 
1342     break;
1343 
1344   case 16:
1345   case 24: {
1346     xcolor.flags = DoRed | DoGreen | DoBlue;
1347 
1348     // Couleur BLACK.
1349     pcolor = vpColor::black;
1350     xcolor.pad = 0;
1351     xcolor.red = 256 * pcolor.R;
1352     xcolor.green = 256 * pcolor.G;
1353     xcolor.blue = 256 * pcolor.B;
1354     XAllocColor(display, lut, &xcolor);
1355     x_color[vpColor::id_black] = xcolor.pixel;
1356 
1357     // Color WHITE.
1358     pcolor = vpColor::white;
1359     xcolor.pad = 0;
1360     xcolor.red = 256 * pcolor.R;
1361     xcolor.green = 256 * pcolor.G;
1362     xcolor.blue = 256 * pcolor.B;
1363     XAllocColor(display, lut, &xcolor);
1364     x_color[vpColor::id_white] = xcolor.pixel;
1365 
1366     // Color LIGHT GRAY.
1367     pcolor = vpColor::lightGray;
1368     xcolor.pad = 0;
1369     xcolor.red = 256 * pcolor.R;
1370     xcolor.green = 256 * pcolor.G;
1371     xcolor.blue = 256 * pcolor.B;
1372     XAllocColor(display, lut, &xcolor);
1373     x_color[vpColor::id_lightGray] = xcolor.pixel;
1374 
1375     // Color GRAY.
1376     pcolor = vpColor::gray;
1377     xcolor.pad = 0;
1378     xcolor.red = 256 * pcolor.R;
1379     xcolor.green = 256 * pcolor.G;
1380     xcolor.blue = 256 * pcolor.B;
1381     XAllocColor(display, lut, &xcolor);
1382     x_color[vpColor::id_gray] = xcolor.pixel;
1383 
1384     // Color DARK GRAY.
1385     pcolor = vpColor::darkGray;
1386     xcolor.pad = 0;
1387     xcolor.red = 256 * pcolor.R;
1388     xcolor.green = 256 * pcolor.G;
1389     xcolor.blue = 256 * pcolor.B;
1390     XAllocColor(display, lut, &xcolor);
1391     x_color[vpColor::id_darkGray] = xcolor.pixel;
1392 
1393     // Color LIGHT RED.
1394     pcolor = vpColor::lightRed;
1395     xcolor.pad = 0;
1396     xcolor.red = 256 * pcolor.R;
1397     xcolor.green = 256 * pcolor.G;
1398     xcolor.blue = 256 * pcolor.B;
1399     XAllocColor(display, lut, &xcolor);
1400     x_color[vpColor::id_lightRed] = xcolor.pixel;
1401 
1402     // Color RED.
1403     pcolor = vpColor::red;
1404     xcolor.pad = 0;
1405     xcolor.red = 256 * pcolor.R;
1406     xcolor.green = 256 * pcolor.G;
1407     xcolor.blue = 256 * pcolor.B;
1408     XAllocColor(display, lut, &xcolor);
1409     x_color[vpColor::id_red] = xcolor.pixel;
1410 
1411     // Color DARK RED.
1412     pcolor = vpColor::darkRed;
1413     xcolor.pad = 0;
1414     xcolor.red = 256 * pcolor.R;
1415     xcolor.green = 256 * pcolor.G;
1416     xcolor.blue = 256 * pcolor.B;
1417     XAllocColor(display, lut, &xcolor);
1418     x_color[vpColor::id_darkRed] = xcolor.pixel;
1419 
1420     // Color LIGHT GREEN.
1421     pcolor = vpColor::lightGreen;
1422     xcolor.pad = 0;
1423     xcolor.red = 256 * pcolor.R;
1424     xcolor.green = 256 * pcolor.G;
1425     xcolor.blue = 256 * pcolor.B;
1426     XAllocColor(display, lut, &xcolor);
1427     x_color[vpColor::id_lightGreen] = xcolor.pixel;
1428 
1429     // Color GREEN.
1430     pcolor = vpColor::green;
1431     xcolor.pad = 0;
1432     xcolor.red = 256 * pcolor.R;
1433     xcolor.green = 256 * pcolor.G;
1434     xcolor.blue = 256 * pcolor.B;
1435     XAllocColor(display, lut, &xcolor);
1436     x_color[vpColor::id_green] = xcolor.pixel;
1437 
1438     // Color DARK GREEN.
1439     pcolor = vpColor::darkGreen;
1440     xcolor.pad = 0;
1441     xcolor.red = 256 * pcolor.R;
1442     xcolor.green = 256 * pcolor.G;
1443     xcolor.blue = 256 * pcolor.B;
1444     XAllocColor(display, lut, &xcolor);
1445     x_color[vpColor::id_darkGreen] = xcolor.pixel;
1446 
1447     // Color LIGHT BLUE.
1448     pcolor = vpColor::lightBlue;
1449     xcolor.pad = 0;
1450     xcolor.red = 256 * pcolor.R;
1451     xcolor.green = 256 * pcolor.G;
1452     xcolor.blue = 256 * pcolor.B;
1453     XAllocColor(display, lut, &xcolor);
1454     x_color[vpColor::id_lightBlue] = xcolor.pixel;
1455 
1456     // Color BLUE.
1457     pcolor = vpColor::blue;
1458     xcolor.pad = 0;
1459     xcolor.red = 256 * pcolor.R;
1460     xcolor.green = 256 * pcolor.G;
1461     xcolor.blue = 256 * pcolor.B;
1462     XAllocColor(display, lut, &xcolor);
1463     x_color[vpColor::id_blue] = xcolor.pixel;
1464 
1465     // Color DARK BLUE.
1466     pcolor = vpColor::darkBlue;
1467     xcolor.pad = 0;
1468     xcolor.red = 256 * pcolor.R;
1469     xcolor.green = 256 * pcolor.G;
1470     xcolor.blue = 256 * pcolor.B;
1471     XAllocColor(display, lut, &xcolor);
1472     x_color[vpColor::id_darkBlue] = xcolor.pixel;
1473 
1474     // Color YELLOW.
1475     pcolor = vpColor::yellow;
1476     xcolor.pad = 0;
1477     xcolor.red = 256 * pcolor.R;
1478     xcolor.green = 256 * pcolor.G;
1479     xcolor.blue = 256 * pcolor.B;
1480     XAllocColor(display, lut, &xcolor);
1481     x_color[vpColor::id_yellow] = xcolor.pixel;
1482 
1483     // Color ORANGE.
1484     pcolor = vpColor::orange;
1485     xcolor.pad = 0;
1486     xcolor.red = 256 * pcolor.R;
1487     xcolor.green = 256 * pcolor.G;
1488     xcolor.blue = 256 * pcolor.B;
1489     XAllocColor(display, lut, &xcolor);
1490     x_color[vpColor::id_orange] = xcolor.pixel;
1491 
1492     // Color CYAN.
1493     pcolor = vpColor::cyan;
1494     xcolor.pad = 0;
1495     xcolor.red = 256 * pcolor.R;
1496     xcolor.green = 256 * pcolor.G;
1497     xcolor.blue = 256 * pcolor.B;
1498     XAllocColor(display, lut, &xcolor);
1499     x_color[vpColor::id_cyan] = xcolor.pixel;
1500 
1501     // Color PURPLE.
1502     pcolor = vpColor::purple;
1503     xcolor.pad = 0;
1504     xcolor.red = 256 * pcolor.R;
1505     xcolor.green = 256 * pcolor.G;
1506     xcolor.blue = 256 * pcolor.B;
1507     XAllocColor(display, lut, &xcolor);
1508     x_color[vpColor::id_purple] = xcolor.pixel;
1509     break;
1510   }
1511   }
1512 
1513   XSetStandardProperties(display, window, this->m_title.c_str(), this->m_title.c_str(), None, 0, 0, &hints);
1514   XMapWindow(display, window);
1515   // Selection des evenements.
1516   XSelectInput(display, window,
1517                ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
1518                    StructureNotifyMask | PointerMotionMask);
1519 
1520   /* Creation du contexte graphique */
1521   values.plane_mask = AllPlanes;
1522   values.fill_style = FillSolid;
1523   values.foreground = WhitePixel(display, screen);
1524   values.background = BlackPixel(display, screen);
1525   context = XCreateGC(display, window, GCPlaneMask | GCFillStyle | GCForeground | GCBackground, &values);
1526 
1527   if (context == NULL) {
1528     vpERROR_TRACE("Can't create graphics context.");
1529     throw(vpDisplayException(vpDisplayException::XWindowsError, "Can't create graphics context"));
1530   }
1531 
1532   // Pixmap creation.
1533   pixmap = XCreatePixmap(display, window, m_width, m_height, screen_depth);
1534 
1535   // Hangs when forward X11 is used to send the display to an other computer
1536   //  do
1537   //    XNextEvent ( display, &event );
1538   //  while ( event.xany.type != Expose );
1539 
1540   {
1541     Ximage = XCreateImage(display, DefaultVisual(display, screen), screen_depth, ZPixmap, 0, NULL, m_width, m_height,
1542                           XBitmapPad(display), 0);
1543 
1544     Ximage->data = (char *)malloc(m_height * (unsigned int)Ximage->bytes_per_line);
1545     ximage_data_init = true;
1546   }
1547   m_displayHasBeenInitialized = true;
1548 
1549   XSync(display, true);
1550 
1551   XStoreName(display, window, m_title.c_str());
1552 }
1553 
1554 /*!
1555 
1556   Set the font used to display a text in overlay. The display is
1557   performed using displayCharString().
1558 
1559   \param font : The expected font name. The available fonts are given by
1560   the "xlsfonts" binary. To choose a font you can also use the
1561   "xfontsel" binary.
1562 
1563   \note Under UNIX, to know all the available fonts, use the
1564   "xlsfonts" binary in a terminal. You can also use the "xfontsel" binary.
1565 
1566   \sa displayCharString()
1567 */
setFont(const std::string & font)1568 void vpDisplayX::setFont(const std::string &font)
1569 {
1570   if (m_displayHasBeenInitialized) {
1571     if (!font.empty()) {
1572       try {
1573         Font stringfont;
1574         stringfont = XLoadFont(display, font.c_str()); //"-adobe-times-bold-r-normal--18*");
1575         XSetFont(display, context, stringfont);
1576       } catch (...) {
1577         throw(vpDisplayException(vpDisplayException::notInitializedError, "Bad font"));
1578       }
1579     }
1580   } else {
1581     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1582   }
1583 }
1584 
1585 /*!
1586   Set the window title.
1587   \param title : Window title.
1588 */
setTitle(const std::string & title)1589 void vpDisplayX::setTitle(const std::string &title)
1590 {
1591   if (m_displayHasBeenInitialized) {
1592     m_title = title;
1593     if (!title.empty())
1594       XStoreName(display, window, m_title.c_str());
1595   } else {
1596     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1597   }
1598 }
1599 
1600 /*!
1601   Set the window position in the screen.
1602 
1603   \param winx, winy : Position of the upper-left window's border in the
1604   screen.
1605 
1606   \exception vpDisplayException::notInitializedError : If the video
1607   device is not initialized.
1608 */
setWindowPosition(int winx,int winy)1609 void vpDisplayX::setWindowPosition(int winx, int winy)
1610 {
1611   if (m_displayHasBeenInitialized) {
1612     XMoveWindow(display, window, winx, winy);
1613   } else {
1614     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1615   }
1616 }
1617 
1618 /*!
1619   Display the gray level image \e I (8bits).
1620 
1621   \warning Display has to be initialized.
1622 
1623   \warning Suppress the overlay drawing.
1624 
1625   \param I : Image to display.
1626 
1627   \sa init(), closeDisplay()
1628 */
displayImage(const vpImage<unsigned char> & I)1629 void vpDisplayX::displayImage(const vpImage<unsigned char> &I)
1630 {
1631   if (m_displayHasBeenInitialized) {
1632     switch (screen_depth) {
1633     case 8: {
1634       // Correction de l'image de facon a liberer les niveaux de gris
1635       // ROUGE, VERT, BLEU, JAUNE
1636       unsigned char nivGrisMax = 255 - vpColor::id_unknown;
1637       if (m_scale == 1) {
1638         unsigned char *src_8 = (unsigned char *)I.bitmap;
1639         unsigned char *dst_8 = (unsigned char *)Ximage->data;
1640         unsigned int i = 0;
1641         unsigned int size = m_width * m_height;
1642 
1643         while (i < size) {
1644           unsigned char nivGris = src_8[i];
1645           if (nivGris > nivGrisMax)
1646             dst_8[i] = 255;
1647           else
1648             dst_8[i] = nivGris;
1649           i++;
1650         }
1651       } else {
1652         // Correction de l'image de facon a liberer les niveaux de gris
1653         // ROUGE, VERT, BLEU, JAUNE
1654         unsigned char *dst_8 = (unsigned char *)Ximage->data;
1655         unsigned int k = 0;
1656         for (unsigned int i = 0; i < m_height; i++) {
1657           for (unsigned int j = 0; j < m_width; j++) {
1658             unsigned char nivGris = I[i * m_scale][j * m_scale];
1659             if (nivGris > nivGrisMax)
1660               dst_8[k++] = 255;
1661             else
1662               dst_8[k++] = nivGris;
1663           }
1664         }
1665       }
1666 
1667       // Affichage de l'image dans la Pixmap.
1668       XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1669       XSetWindowBackgroundPixmap(display, window, pixmap);
1670       break;
1671     }
1672     case 16: {
1673       unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
1674       if (m_scale == 1) {
1675         for (unsigned int i = 0; i < m_height; i++) {
1676           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
1677           unsigned short *dst_16 = (unsigned short *)dst_8;
1678           for (unsigned int j = 0; j < m_width; j++) {
1679             *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
1680           }
1681         }
1682       } else {
1683         for (unsigned int i = 0; i < m_height; i++) {
1684           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
1685           unsigned short *dst_16 = (unsigned short *)dst_8;
1686           for (unsigned int j = 0; j < m_width; j++) {
1687             *(dst_16 + j) = (unsigned short)colortable[I[i * m_scale][j * m_scale]];
1688           }
1689         }
1690       }
1691 
1692       // Affichage de l'image dans la Pixmap.
1693       XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1694       XSetWindowBackgroundPixmap(display, window, pixmap);
1695       break;
1696     }
1697 
1698     case 24:
1699     default: {
1700       unsigned char *dst_32 = (unsigned char *)Ximage->data;
1701       if (m_scale == 1) {
1702         unsigned int size_ = m_width * m_height;
1703         unsigned char *bitmap = I.bitmap;
1704         unsigned char *n = I.bitmap + size_;
1705         // for (unsigned int i = 0; i < size; i++) // suppression de
1706         // l'iterateur i
1707         if (XImageByteOrder(display) == 1) {
1708           // big endian
1709           while (bitmap < n) {
1710             unsigned char val = *(bitmap++);
1711             *(dst_32++) = vpRGBa::alpha_default;
1712             *(dst_32++) = val; // Red
1713             *(dst_32++) = val; // Green
1714             *(dst_32++) = val; // Blue
1715           }
1716         } else {
1717           // little endian
1718           while (bitmap < n) {
1719             unsigned char val = *(bitmap++);
1720             *(dst_32++) = val; // Blue
1721             *(dst_32++) = val; // Green
1722             *(dst_32++) = val; // Red
1723             *(dst_32++) = vpRGBa::alpha_default;
1724           }
1725         }
1726       } else {
1727         if (XImageByteOrder(display) == 1) {
1728           // big endian
1729           for (unsigned int i = 0; i < m_height; i++) {
1730             for (unsigned int j = 0; j < m_width; j++) {
1731               unsigned char val = I[i * m_scale][j * m_scale];
1732               *(dst_32++) = vpRGBa::alpha_default;
1733               *(dst_32++) = val; // Red
1734               *(dst_32++) = val; // Green
1735               *(dst_32++) = val; // Blue
1736             }
1737           }
1738         } else {
1739           // little endian
1740           for (unsigned int i = 0; i < m_height; i++) {
1741             for (unsigned int j = 0; j < m_width; j++) {
1742               unsigned char val = I[i * m_scale][j * m_scale];
1743               *(dst_32++) = val; // Blue
1744               *(dst_32++) = val; // Green
1745               *(dst_32++) = val; // Red
1746               *(dst_32++) = vpRGBa::alpha_default;
1747             }
1748           }
1749         }
1750       }
1751 
1752       // Affichage de l'image dans la Pixmap.
1753       XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1754       XSetWindowBackgroundPixmap(display, window, pixmap);
1755       break;
1756     }
1757     }
1758   } else {
1759     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1760   }
1761 }
1762 /*!
1763   Display the color image \e I in RGBa format (32bits).
1764 
1765   \warning Display has to be initialized.
1766 
1767   \warning Suppress the overlay drawing.
1768 
1769   \param I : Image to display.
1770 
1771   \sa init(), closeDisplay()
1772 */
displayImage(const vpImage<vpRGBa> & I)1773 void vpDisplayX::displayImage(const vpImage<vpRGBa> &I)
1774 {
1775   if (m_displayHasBeenInitialized) {
1776     switch (screen_depth) {
1777     case 16: {
1778       vpRGBa *bitmap = I.bitmap;
1779       unsigned int r, g, b;
1780       unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
1781 
1782       if (m_scale == 1) {
1783         for (unsigned int i = 0; i < m_height; i++) {
1784           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
1785           unsigned short *dst_16 = (unsigned short *)dst_8;
1786           for (unsigned int j = 0; j < m_width; j++) {
1787             r = bitmap->R;
1788             g = bitmap->G;
1789             b = bitmap->B;
1790             *(dst_16 + j) =
1791                 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
1792             bitmap++;
1793           }
1794         }
1795       } else {
1796         for (unsigned int i = 0; i < m_height; i++) {
1797           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
1798           unsigned short *dst_16 = (unsigned short *)dst_8;
1799           for (unsigned int j = 0; j < m_width; j++) {
1800             vpRGBa val = I[i * m_scale][j * m_scale];
1801             r = val.R;
1802             g = val.G;
1803             b = val.B;
1804             *(dst_16 + j) =
1805                 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
1806             bitmap++;
1807           }
1808         }
1809       }
1810 
1811       XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1812       XSetWindowBackgroundPixmap(display, window, pixmap);
1813 
1814       break;
1815     }
1816     case 24:
1817     case 32: {
1818       /*
1819        * 32-bit source, 24/32-bit destination
1820        */
1821       unsigned char *dst_32 = NULL;
1822       dst_32 = (unsigned char *)Ximage->data;
1823       if (m_scale == 1) {
1824         vpRGBa *bitmap = I.bitmap;
1825         unsigned int sizeI = m_width * m_height;
1826         if (XImageByteOrder(display) == 1) {
1827           // big endian
1828           for (unsigned int i = 0; i < sizeI; i++) {
1829             *(dst_32++) = bitmap->A;
1830             *(dst_32++) = bitmap->R;
1831             *(dst_32++) = bitmap->G;
1832             *(dst_32++) = bitmap->B;
1833             bitmap++;
1834           }
1835         } else {
1836           // little endian
1837           for (unsigned int i = 0; i < sizeI; i++) {
1838             *(dst_32++) = bitmap->B;
1839             *(dst_32++) = bitmap->G;
1840             *(dst_32++) = bitmap->R;
1841             *(dst_32++) = bitmap->A;
1842             bitmap++;
1843           }
1844         }
1845       } else {
1846         if (XImageByteOrder(display) == 1) {
1847           // big endian
1848           for (unsigned int i = 0; i < m_height; i++) {
1849             for (unsigned int j = 0; j < m_width; j++) {
1850               vpRGBa val = I[i * m_scale][j * m_scale];
1851               *(dst_32++) = val.A;
1852               *(dst_32++) = val.R;
1853               *(dst_32++) = val.G;
1854               *(dst_32++) = val.B;
1855             }
1856           }
1857         } else {
1858           // little endian
1859           for (unsigned int i = 0; i < m_height; i++) {
1860             for (unsigned int j = 0; j < m_width; j++) {
1861               vpRGBa val = I[i * m_scale][j * m_scale];
1862               *(dst_32++) = val.B;
1863               *(dst_32++) = val.G;
1864               *(dst_32++) = val.R;
1865               *(dst_32++) = val.A;
1866             }
1867           }
1868         }
1869       }
1870 
1871       // Affichage de l'image dans la Pixmap.
1872       XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1873       XSetWindowBackgroundPixmap(display, window, pixmap);
1874       break;
1875     }
1876     default:
1877       throw(vpDisplayException(vpDisplayException::depthNotSupportedError,
1878                                "Unsupported depth (%d bpp) for color display", screen_depth));
1879     }
1880   } else {
1881     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1882   }
1883 }
1884 
1885 /*!
1886   Display an image with a reference to the bitmap.
1887 
1888   \warning Display has to be initialized.
1889 
1890   \warning Suppress the overlay drawing.
1891 
1892   \param bitmap : Pointer to the image bitmap.
1893 
1894   \sa init(), closeDisplay()
1895 */
displayImage(const unsigned char * bitmap)1896 void vpDisplayX::displayImage(const unsigned char *bitmap)
1897 {
1898 
1899   if (m_displayHasBeenInitialized) {
1900     unsigned char *dst_32 = (unsigned char *)Ximage->data;
1901     for (unsigned int i = 0; i < m_width * m_height; i++) {
1902       *(dst_32++) = *bitmap; // red component.
1903       *(dst_32++) = *bitmap; // green component.
1904       *(dst_32++) = *bitmap; // blue component.
1905       *(dst_32++) = *bitmap; // luminance component.
1906       bitmap++;
1907     }
1908 
1909     // Affichage de l'image dans la Pixmap.
1910     XPutImage(display, pixmap, context, Ximage, 0, 0, 0, 0, m_width, m_height);
1911     XSetWindowBackgroundPixmap(display, window, pixmap);
1912   } else {
1913     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
1914   }
1915 }
1916 
1917 /*!
1918   Display a selection of the gray level image \e I (8bits).
1919 
1920   \warning Display has to be initialized.
1921 
1922   \warning Suppress the overlay drawing in the region of interest.
1923 
1924   \param I : Image to display.
1925 
1926   \param iP : Top left corner of the region of interest
1927 
1928   \param w, h : Width and height of the region of interest
1929 
1930   \sa init(), closeDisplay()
1931 */
displayImageROI(const vpImage<unsigned char> & I,const vpImagePoint & iP,unsigned int w,unsigned int h)1932 void vpDisplayX::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
1933                                  unsigned int h)
1934 {
1935   if (m_displayHasBeenInitialized) {
1936     switch (screen_depth) {
1937     case 8: {
1938       // Correction de l'image de facon a liberer les niveaux de gris
1939       // ROUGE, VERT, BLEU, JAUNE
1940       unsigned char nivGrisMax = 255 - vpColor::id_unknown;
1941       if (m_scale == 1) {
1942         unsigned char *src_8 = (unsigned char *)I.bitmap;
1943         unsigned char *dst_8 = (unsigned char *)Ximage->data;
1944         unsigned int iwidth = I.getWidth();
1945 
1946         src_8 = src_8 + (int)(iP.get_i() * iwidth + iP.get_j());
1947         dst_8 = dst_8 + (int)(iP.get_i() * m_width + iP.get_j());
1948 
1949         unsigned int i = 0;
1950         while (i < h) {
1951           unsigned int j = 0;
1952           while (j < w) {
1953             unsigned char nivGris = *(src_8 + j);
1954             if (nivGris > nivGrisMax)
1955               *(dst_8 + j) = 255;
1956             else
1957               *(dst_8 + j) = nivGris;
1958             j++;
1959           }
1960           src_8 = src_8 + iwidth;
1961           dst_8 = dst_8 + m_width;
1962           i++;
1963         }
1964 
1965         XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
1966                   w, h);
1967       } else {
1968         // Correction de l'image de facon a liberer les niveaux de gris
1969         // ROUGE, VERT, BLEU, JAUNE
1970         int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
1971         int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
1972         int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
1973         int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
1974 
1975         unsigned int i_min_ = (unsigned int)i_min;
1976         unsigned int i_max_ = (unsigned int)i_max;
1977         unsigned int j_min_ = (unsigned int)j_min;
1978         unsigned int j_max_ = (unsigned int)j_max;
1979 
1980         for (unsigned int i = i_min_; i < i_max_; i++) {
1981           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * m_width;
1982           for (unsigned int j = j_min_; j < j_max_; j++) {
1983             unsigned char nivGris = I[i * m_scale][j * m_scale];
1984             if (nivGris > nivGrisMax)
1985               dst_8[j] = 255;
1986             else
1987               dst_8[j] = nivGris;
1988           }
1989         }
1990         XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
1991       }
1992 
1993       // Affichage de l'image dans la Pixmap.
1994       XSetWindowBackgroundPixmap(display, window, pixmap);
1995       break;
1996     }
1997     case 16: {
1998       unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
1999       if (m_scale == 1) {
2000         for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
2001           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
2002           unsigned short *dst_16 = (unsigned short *)dst_8;
2003           for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
2004             *(dst_16 + j) = (unsigned short)colortable[I[i][j]];
2005           }
2006         }
2007 
2008         XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
2009                   w, h);
2010       } else {
2011         int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
2012         int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
2013         int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
2014         int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
2015 
2016         unsigned int i_min_ = (unsigned int)i_min;
2017         unsigned int i_max_ = (unsigned int)i_max;
2018         unsigned int j_min_ = (unsigned int)j_min;
2019         unsigned int j_max_ = (unsigned int)j_max;
2020 
2021         for (unsigned int i = i_min_; i < i_max_; i++) {
2022           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
2023           unsigned short *dst_16 = (unsigned short *)dst_8;
2024           for (unsigned int j = j_min_; j < j_max_; j++) {
2025             *(dst_16 + j) = (unsigned short)colortable[I[i * m_scale][j * m_scale]];
2026           }
2027         }
2028 
2029         XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
2030       }
2031 
2032       XSetWindowBackgroundPixmap(display, window, pixmap);
2033       break;
2034     }
2035 
2036     case 24:
2037     default: {
2038       if (m_scale == 1) {
2039         unsigned int iwidth = I.getWidth();
2040         unsigned char *src_8 = I.bitmap + (int)(iP.get_i() * iwidth + iP.get_j());
2041         unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(iP.get_i() * 4 * m_width + iP.get_j() * 4);
2042 
2043         if (XImageByteOrder(display) == 1) {
2044           // big endian
2045           unsigned int i = 0;
2046           while (i < h) {
2047             unsigned int j = 0;
2048             while (j < w) {
2049               unsigned char val = *(src_8 + j);
2050               *(dst_32 + 4 * j) = vpRGBa::alpha_default;
2051               *(dst_32 + 4 * j + 1) = val;
2052               *(dst_32 + 4 * j + 2) = val;
2053               *(dst_32 + 4 * j + 3) = val;
2054               j++;
2055             }
2056             src_8 = src_8 + iwidth;
2057             dst_32 = dst_32 + 4 * m_width;
2058             i++;
2059           }
2060         } else {
2061           // little endian
2062           unsigned int i = 0;
2063           while (i < h) {
2064             unsigned int j = 0;
2065             while (j < w) {
2066               unsigned char val = *(src_8 + j);
2067               *(dst_32 + 4 * j) = val;
2068               *(dst_32 + 4 * j + 1) = val;
2069               *(dst_32 + 4 * j + 2) = val;
2070               *(dst_32 + 4 * j + 3) = vpRGBa::alpha_default;
2071               j++;
2072             }
2073             src_8 = src_8 + iwidth;
2074             dst_32 = dst_32 + 4 * m_width;
2075             i++;
2076           }
2077         }
2078 
2079         XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
2080                   w, h);
2081       } else {
2082         int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
2083         int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
2084         int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
2085         int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
2086 
2087         unsigned int i_min_ = (unsigned int)i_min;
2088         unsigned int i_max_ = (unsigned int)i_max;
2089         unsigned int j_min_ = (unsigned int)j_min;
2090         unsigned int j_max_ = (unsigned int)j_max;
2091 
2092         if (XImageByteOrder(display) == 1) {
2093           // big endian
2094           for (unsigned int i = i_min_; i < i_max_; i++) {
2095             unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * m_width + j_min_ * 4);
2096             for (unsigned int j = j_min_; j < j_max_; j++) {
2097               unsigned char val = I[i * m_scale][j * m_scale];
2098               *(dst_32++) = vpRGBa::alpha_default;
2099               *(dst_32++) = val;
2100               *(dst_32++) = val;
2101               *(dst_32++) = val;
2102             }
2103           }
2104         } else {
2105           // little endian
2106           for (unsigned int i = i_min_; i < i_max_; i++) {
2107             unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * m_width + j_min_ * 4);
2108             for (unsigned int j = j_min_; j < j_max_; j++) {
2109               unsigned char val = I[i * m_scale][j * m_scale];
2110               *(dst_32++) = val;
2111               *(dst_32++) = val;
2112               *(dst_32++) = val;
2113               *(dst_32++) = vpRGBa::alpha_default;
2114             }
2115           }
2116         }
2117 
2118         XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
2119       }
2120 
2121       XSetWindowBackgroundPixmap(display, window, pixmap);
2122       break;
2123     }
2124     }
2125   } else {
2126     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2127   }
2128 }
2129 
2130 /*!
2131   Display a selection of the color image \e I in RGBa format (32bits).
2132 
2133   \warning Display has to be initialized.
2134 
2135   \warning Suppress the overlay drawing in the region of interest.
2136 
2137   \param I : Image to display.
2138 
2139   \param iP : Top left corner of the region of interest
2140 
2141   \param w, h : Width and height of the region of interest
2142 
2143   \sa init(), closeDisplay()
2144 */
displayImageROI(const vpImage<vpRGBa> & I,const vpImagePoint & iP,unsigned int w,unsigned int h)2145 void vpDisplayX::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w,
2146                                  unsigned int h)
2147 {
2148   if (m_displayHasBeenInitialized) {
2149     switch (screen_depth) {
2150     case 16: {
2151       if (m_scale == 1) {
2152         unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
2153         for (unsigned int i = (unsigned int)iP.get_i(); i < (unsigned int)(iP.get_i() + h); i++) {
2154           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
2155           unsigned short *dst_16 = (unsigned short *)dst_8;
2156           for (unsigned int j = (unsigned int)iP.get_j(); j < (unsigned int)(iP.get_j() + w); j++) {
2157             vpRGBa val = I[i][j];
2158             unsigned int r = val.R;
2159             unsigned int g = val.G;
2160             unsigned int b = val.B;
2161             *(dst_16 + j) =
2162                 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
2163           }
2164         }
2165         XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
2166                   w, h);
2167       } else {
2168         unsigned int bytes_per_line = (unsigned int)Ximage->bytes_per_line;
2169         int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
2170         int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
2171         int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
2172         int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
2173 
2174         unsigned int i_min_ = (unsigned int)i_min;
2175         unsigned int i_max_ = (unsigned int)i_max;
2176         unsigned int j_min_ = (unsigned int)j_min;
2177         unsigned int j_max_ = (unsigned int)j_max;
2178 
2179         for (unsigned int i = i_min_; i < i_max_; i++) {
2180           unsigned char *dst_8 = (unsigned char *)Ximage->data + i * bytes_per_line;
2181           unsigned short *dst_16 = (unsigned short *)dst_8;
2182           for (unsigned int j = j_min_; j < j_max_; j++) {
2183             vpRGBa val = I[i * m_scale][j * m_scale];
2184             unsigned int r = val.R;
2185             unsigned int g = val.G;
2186             unsigned int b = val.B;
2187             *(dst_16 + j) =
2188                 (((r << 8) >> RShift) & RMask) | (((g << 8) >> GShift) & GMask) | (((b << 8) >> BShift) & BMask);
2189           }
2190         }
2191         XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
2192       }
2193 
2194       XSetWindowBackgroundPixmap(display, window, pixmap);
2195 
2196       break;
2197     }
2198     case 24:
2199     case 32: {
2200       /*
2201        * 32-bit source, 24/32-bit destination
2202        */
2203 
2204       if (m_scale == 1) {
2205         unsigned char *dst_32 = (unsigned char *)Ximage->data;
2206         vpRGBa *src_32 = I.bitmap;
2207 
2208         unsigned int iwidth = I.getWidth();
2209 
2210         src_32 = src_32 + (int)(iP.get_i() * iwidth + iP.get_j());
2211         dst_32 = dst_32 + (int)(iP.get_i() * 4 * m_width + iP.get_j() * 4);
2212 
2213         unsigned int i = 0;
2214 
2215         if (XImageByteOrder(display) == 1) {
2216           // big endian
2217           while (i < h) {
2218             unsigned int j = 0;
2219             while (j < w) {
2220               *(dst_32 + 4 * j) = (src_32 + j)->A;
2221               *(dst_32 + 4 * j + 1) = (src_32 + j)->R;
2222               *(dst_32 + 4 * j + 2) = (src_32 + j)->G;
2223               *(dst_32 + 4 * j + 3) = (src_32 + j)->B;
2224 
2225               j++;
2226             }
2227             src_32 = src_32 + iwidth;
2228             dst_32 = dst_32 + 4 * m_width;
2229             i++;
2230           }
2231 
2232         } else {
2233           // little endian
2234           while (i < h) {
2235             unsigned int j = 0;
2236             while (j < w) {
2237               *(dst_32 + 4 * j) = (src_32 + j)->B;
2238               *(dst_32 + 4 * j + 1) = (src_32 + j)->G;
2239               *(dst_32 + 4 * j + 2) = (src_32 + j)->R;
2240               *(dst_32 + 4 * j + 3) = (src_32 + j)->A;
2241 
2242               j++;
2243             }
2244             src_32 = src_32 + iwidth;
2245             dst_32 = dst_32 + 4 * m_width;
2246             i++;
2247           }
2248         }
2249 
2250         XPutImage(display, pixmap, context, Ximage, (int)iP.get_u(), (int)iP.get_v(), (int)iP.get_u(), (int)iP.get_v(),
2251                   w, h);
2252       } else {
2253         int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
2254         int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
2255         int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
2256         int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
2257 
2258         unsigned int i_min_ = (unsigned int)i_min;
2259         unsigned int i_max_ = (unsigned int)i_max;
2260         unsigned int j_min_ = (unsigned int)j_min;
2261         unsigned int j_max_ = (unsigned int)j_max;
2262 
2263         if (XImageByteOrder(display) == 1) {
2264           // big endian
2265           for (unsigned int i = i_min_; i < i_max_; i++) {
2266             unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * m_width + j_min_ * 4);
2267             for (unsigned int j = j_min_; j < j_max_; j++) {
2268               vpRGBa val = I[i * m_scale][j * m_scale];
2269               *(dst_32++) = val.A;
2270               *(dst_32++) = val.R;
2271               *(dst_32++) = val.G;
2272               *(dst_32++) = val.B;
2273             }
2274           }
2275         } else {
2276           // little endian
2277           for (unsigned int i = i_min_; i < i_max_; i++) {
2278             unsigned char *dst_32 = (unsigned char *)Ximage->data + (int)(i * 4 * m_width + j_min_ * 4);
2279             for (unsigned int j = j_min_; j < j_max_; j++) {
2280               vpRGBa val = I[i * m_scale][j * m_scale];
2281               *(dst_32++) = val.B;
2282               *(dst_32++) = val.G;
2283               *(dst_32++) = val.R;
2284               *(dst_32++) = val.A;
2285             }
2286           }
2287         }
2288         XPutImage(display, pixmap, context, Ximage, j_min, i_min, j_min, i_min, j_max_ - j_min_, i_max_ - i_min_);
2289       }
2290 
2291       XSetWindowBackgroundPixmap(display, window, pixmap);
2292       break;
2293     }
2294     default:
2295       throw(vpDisplayException(vpDisplayException::depthNotSupportedError,
2296                                "Unsupported depth (%d bpp) for color display", screen_depth));
2297     }
2298   } else {
2299     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2300   }
2301 }
2302 
2303 /*!
2304 
2305   Close the window.
2306 
2307   \sa init()
2308 
2309 */
closeDisplay()2310 void vpDisplayX::closeDisplay()
2311 {
2312   if (m_displayHasBeenInitialized) {
2313     if (ximage_data_init == true)
2314       free(Ximage->data);
2315 
2316     Ximage->data = NULL;
2317     XDestroyImage(Ximage);
2318 
2319     XFreePixmap(display, pixmap);
2320 
2321     XFreeGC(display, context);
2322     XDestroyWindow(display, window);
2323     XCloseDisplay(display);
2324 
2325     m_displayHasBeenInitialized = false;
2326 
2327     if (x_color != NULL) {
2328       delete[] x_color;
2329       x_color = NULL;
2330     }
2331   }
2332 }
2333 
2334 /*!
2335   Flushes the X buffer.
2336   It's necessary to use this function to see the results of any drawing.
2337 
2338 */
flushDisplay()2339 void vpDisplayX::flushDisplay()
2340 {
2341   if (m_displayHasBeenInitialized) {
2342     XClearWindow(display, window);
2343     XFlush(display);
2344   } else {
2345     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2346   }
2347 }
2348 
2349 /*!
2350   Flushes a part of the X buffer.
2351   It's necessary to use this function to see the results of any drawing.
2352 
2353   \param iP : Top left corner of the region of interest
2354   \param w,h  : Width and height of the region of interest
2355 */
flushDisplayROI(const vpImagePoint & iP,unsigned int w,unsigned int h)2356 void vpDisplayX::flushDisplayROI(const vpImagePoint &iP, unsigned int w, unsigned int h)
2357 {
2358   if (m_displayHasBeenInitialized) {
2359     XClearArea(display, window, (int)(iP.get_u() / m_scale), (int)(iP.get_v() / m_scale), w / m_scale, h / m_scale, 0);
2360     XFlush(display);
2361   } else {
2362     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2363   }
2364 }
2365 
2366 /*!
2367   Set the window backgroud to \e color.
2368   \param color : Background color.
2369 */
clearDisplay(const vpColor & color)2370 void vpDisplayX::clearDisplay(const vpColor &color)
2371 {
2372   if (m_displayHasBeenInitialized) {
2373 
2374     if (color.id < vpColor::id_unknown)
2375       XSetWindowBackground(display, window, x_color[color.id]);
2376     else {
2377       xcolor.pad = 0;
2378       xcolor.red = 256 * color.R;
2379       xcolor.green = 256 * color.G;
2380       xcolor.blue = 256 * color.B;
2381       XAllocColor(display, lut, &xcolor);
2382       XSetForeground(display, context, xcolor.pixel);
2383     }
2384 
2385     XClearWindow(display, window);
2386 
2387     XFreePixmap(display, pixmap);
2388     // Pixmap creation.
2389     pixmap = XCreatePixmap(display, window, m_width, m_height, screen_depth);
2390   } else {
2391     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2392   }
2393 }
2394 
2395 /*!
2396   Display an arrow from image point \e ip1 to image point \e ip2.
2397   \param ip1,ip2 : Initial and final image point.
2398   \param color : Arrow color.
2399   \param w,h : Width and height of the arrow.
2400   \param thickness : Thickness of the lines used to display the arrow.
2401 */
displayArrow(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int w,unsigned int h,unsigned int thickness)2402 void vpDisplayX::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
2403                               unsigned int h, unsigned int thickness)
2404 {
2405   if (m_displayHasBeenInitialized) {
2406     double a = ip2.get_i() - ip1.get_i();
2407     double b = ip2.get_j() - ip1.get_j();
2408     double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
2409 
2410     // if ( ( a==0 ) && ( b==0 ) )
2411     if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
2412         (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
2413       // DisplayCrossLarge(i1,j1,3,col) ;
2414     } else {
2415       a /= lg;
2416       b /= lg;
2417 
2418       vpImagePoint ip3;
2419       ip3.set_i(ip2.get_i() - w * a);
2420       ip3.set_j(ip2.get_j() - w * b);
2421 
2422       vpImagePoint ip4;
2423       ip4.set_i(ip3.get_i() - b * h);
2424       ip4.set_j(ip3.get_j() + a * h);
2425 
2426       if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2427         displayLine(ip2, ip4, color, thickness);
2428 
2429       ip4.set_i(ip3.get_i() + b * h);
2430       ip4.set_j(ip3.get_j() - a * h);
2431 
2432       if (lg > 2 * vpImagePoint::distance(ip2, ip4))
2433         displayLine(ip2, ip4, color, thickness);
2434 
2435       displayLine(ip1, ip2, color, thickness);
2436     }
2437   } else {
2438     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2439   }
2440 }
2441 
2442 /*!
2443   Display a string at the image point \e ip location.
2444 
2445   To select the font used to display the string, use setFont().
2446 
2447   \param ip : Upper left image point location of the string in the display.
2448   \param text : String to display in overlay.
2449   \param color : String color.
2450 
2451   \sa setFont()
2452 */
displayCharString(const vpImagePoint & ip,const char * text,const vpColor & color)2453 void vpDisplayX::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
2454 {
2455   if (m_displayHasBeenInitialized) {
2456     if (color.id < vpColor::id_unknown)
2457       XSetForeground(display, context, x_color[color.id]);
2458     else {
2459       xcolor.pad = 0;
2460       xcolor.red = 256 * color.R;
2461       xcolor.green = 256 * color.G;
2462       xcolor.blue = 256 * color.B;
2463       XAllocColor(display, lut, &xcolor);
2464       XSetForeground(display, context, xcolor.pixel);
2465     }
2466     XDrawString(display, pixmap, context, (int)(ip.get_u() / m_scale), (int)(ip.get_v() / m_scale), text,
2467                 (int)strlen(text));
2468   } else {
2469     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2470   }
2471 }
2472 
2473 /*!
2474   Display a circle.
2475   \param center : Circle center position.
2476   \param radius : Circle radius.
2477   \param color : Circle color.
2478   \param fill : When set to true fill the circle.
2479   \param thickness : Thickness of the circle. This parameter is only useful
2480   when \e fill is set to false.
2481 */
displayCircle(const vpImagePoint & center,unsigned int radius,const vpColor & color,bool fill,unsigned int thickness)2482 void vpDisplayX::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
2483                                unsigned int thickness)
2484 {
2485   if (m_displayHasBeenInitialized) {
2486     if (thickness == 1)
2487       thickness = 0;
2488     if (color.id < vpColor::id_unknown)
2489       XSetForeground(display, context, x_color[color.id]);
2490     else {
2491       xcolor.pad = 0;
2492       xcolor.red = 256 * color.R;
2493       xcolor.green = 256 * color.G;
2494       xcolor.blue = 256 * color.B;
2495       XAllocColor(display, lut, &xcolor);
2496       XSetForeground(display, context, xcolor.pixel);
2497     }
2498 
2499     XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2500 
2501     if (fill == false) {
2502       XDrawArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / m_scale),
2503                vpMath::round((center.get_v() - radius) / m_scale), radius * 2 / m_scale, radius * 2 / m_scale, 0,
2504                23040); /* 23040 = 360*64 */
2505     } else {
2506       XFillArc(display, pixmap, context, vpMath::round((center.get_u() - radius) / m_scale),
2507                vpMath::round((center.get_v() - radius) / m_scale), radius * 2 / m_scale, radius * 2 / m_scale, 0,
2508                23040); /* 23040 = 360*64 */
2509     }
2510   } else {
2511     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2512   }
2513 }
2514 
2515 /*!
2516   Display a cross at the image point \e ip location.
2517   \param ip : Cross location.
2518   \param cross_size : Size (width and height) of the cross.
2519   \param color : Cross color.
2520   \param thickness : Thickness of the lines used to display the cross.
2521 */
displayCross(const vpImagePoint & ip,unsigned int cross_size,const vpColor & color,unsigned int thickness)2522 void vpDisplayX::displayCross(const vpImagePoint &ip, unsigned int cross_size, const vpColor &color,
2523                               unsigned int thickness)
2524 {
2525   if (m_displayHasBeenInitialized) {
2526     double i = ip.get_i();
2527     double j = ip.get_j();
2528     vpImagePoint ip1, ip2;
2529 
2530     ip1.set_i(i - cross_size / 2);
2531     ip1.set_j(j);
2532     ip2.set_i(i + cross_size / 2);
2533     ip2.set_j(j);
2534     displayLine(ip1, ip2, color, thickness);
2535 
2536     ip1.set_i(i);
2537     ip1.set_j(j - cross_size / 2);
2538     ip2.set_i(i);
2539     ip2.set_j(j + cross_size / 2);
2540 
2541     displayLine(ip1, ip2, color, thickness);
2542   } else {
2543     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2544   }
2545 }
2546 /*!
2547   Display a dashed line from image point \e ip1 to image point \e ip2.
2548   \param ip1,ip2 : Initial and final image points.
2549   \param color : Line color.
2550   \param thickness : Line thickness.
2551 */
displayDotLine(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int thickness)2552 void vpDisplayX::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2553                                 unsigned int thickness)
2554 {
2555   if (m_displayHasBeenInitialized) {
2556     if (thickness == 1)
2557       thickness = 0;
2558 
2559     if (color.id < vpColor::id_unknown)
2560       XSetForeground(display, context, x_color[color.id]);
2561     else {
2562       xcolor.pad = 0;
2563       xcolor.red = 256 * color.R;
2564       xcolor.green = 256 * color.G;
2565       xcolor.blue = 256 * color.B;
2566       XAllocColor(display, lut, &xcolor);
2567       XSetForeground(display, context, xcolor.pixel);
2568     }
2569 
2570     XSetLineAttributes(display, context, thickness, LineOnOffDash, CapButt, JoinBevel);
2571 
2572     XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale),
2573               vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale));
2574   } else {
2575     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2576   }
2577 }
2578 
2579 /*!
2580   Display a line from image point \e ip1 to image point \e ip2.
2581   \param ip1,ip2 : Initial and final image points.
2582   \param color : Line color.
2583   \param thickness : Line thickness.
2584 */
displayLine(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int thickness)2585 void vpDisplayX::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
2586                              unsigned int thickness)
2587 {
2588   if (m_displayHasBeenInitialized) {
2589     if (thickness == 1)
2590       thickness = 0;
2591 
2592     if (color.id < vpColor::id_unknown)
2593       XSetForeground(display, context, x_color[color.id]);
2594     else {
2595       xcolor.pad = 0;
2596       xcolor.red = 256 * color.R;
2597       xcolor.green = 256 * color.G;
2598       xcolor.blue = 256 * color.B;
2599       XAllocColor(display, lut, &xcolor);
2600       XSetForeground(display, context, xcolor.pixel);
2601     }
2602 
2603     XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2604 
2605     XDrawLine(display, pixmap, context, vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale),
2606               vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale));
2607   } else {
2608     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2609   }
2610 }
2611 
2612 /*!
2613   Display a point at the image point \e ip location.
2614   \param ip : Point location.
2615   \param color : Point color.
2616   \param thickness : Point thickness.
2617 */
displayPoint(const vpImagePoint & ip,const vpColor & color,unsigned int thickness)2618 void vpDisplayX::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
2619 {
2620   if (m_displayHasBeenInitialized) {
2621     if (color.id < vpColor::id_unknown)
2622       XSetForeground(display, context, x_color[color.id]);
2623     else {
2624       xcolor.pad = 0;
2625       xcolor.red = 256 * color.R;
2626       xcolor.green = 256 * color.G;
2627       xcolor.blue = 256 * color.B;
2628       XAllocColor(display, lut, &xcolor);
2629       XSetForeground(display, context, xcolor.pixel);
2630     }
2631 
2632     if (thickness == 1) {
2633       XDrawPoint(display, pixmap, context, vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale));
2634     } else {
2635       XFillRectangle(display, pixmap, context, vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale),
2636                      thickness, thickness);
2637     }
2638 
2639   } else {
2640     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2641   }
2642 }
2643 
2644 /*!
2645   Display a rectangle with \e topLeft as the top-left corner and \e
2646   width and \e height the rectangle size.
2647 
2648   \param topLeft : Top-left corner of the rectangle.
2649   \param w,h : Rectangle size in terms of width and height.
2650   \param color : Rectangle color.
2651   \param fill : When set to true fill the rectangle.
2652 
2653   \param thickness : Thickness of the four lines used to display the
2654   rectangle. This parameter is only useful when \e fill is set to
2655   false.
2656 */
displayRectangle(const vpImagePoint & topLeft,unsigned int w,unsigned int h,const vpColor & color,bool fill,unsigned int thickness)2657 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h, const vpColor &color,
2658                                   bool fill, unsigned int thickness)
2659 {
2660   if (m_displayHasBeenInitialized) {
2661     if (thickness == 1)
2662       thickness = 0;
2663     if (color.id < vpColor::id_unknown)
2664       XSetForeground(display, context, x_color[color.id]);
2665     else {
2666       xcolor.pad = 0;
2667       xcolor.red = 256 * color.R;
2668       xcolor.green = 256 * color.G;
2669       xcolor.blue = 256 * color.B;
2670       XAllocColor(display, lut, &xcolor);
2671       XSetForeground(display, context, xcolor.pixel);
2672     }
2673     XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2674     if (fill == false) {
2675       XDrawRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / m_scale),
2676                      vpMath::round(topLeft.get_v() / m_scale), w / m_scale, h / m_scale);
2677     } else {
2678       XFillRectangle(display, pixmap, context, vpMath::round(topLeft.get_u() / m_scale),
2679                      vpMath::round(topLeft.get_v() / m_scale), w / m_scale, h / m_scale);
2680     }
2681   } else {
2682     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2683   }
2684 }
2685 
2686 /*!
2687   Display a rectangle.
2688 
2689   \param topLeft : Top-left corner of the rectangle.
2690   \param bottomRight : Bottom-right corner of the rectangle.
2691   \param color : Rectangle color.
2692   \param fill : When set to true fill the rectangle.
2693 
2694   \param thickness : Thickness of the four lines used to display the
2695   rectangle. This parameter is only useful when \e fill is set to
2696   false.
2697 */
displayRectangle(const vpImagePoint & topLeft,const vpImagePoint & bottomRight,const vpColor & color,bool fill,unsigned int thickness)2698 void vpDisplayX::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight, const vpColor &color,
2699                                   bool fill, unsigned int thickness)
2700 {
2701   if (m_displayHasBeenInitialized) {
2702     if (thickness == 1)
2703       thickness = 0;
2704     if (color.id < vpColor::id_unknown)
2705       XSetForeground(display, context, x_color[color.id]);
2706     else {
2707       xcolor.pad = 0;
2708       xcolor.red = 256 * color.R;
2709       xcolor.green = 256 * color.G;
2710       xcolor.blue = 256 * color.B;
2711       XAllocColor(display, lut, &xcolor);
2712       XSetForeground(display, context, xcolor.pixel);
2713     }
2714 
2715     XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2716 
2717     vpImagePoint topLeft_ = topLeft / m_scale;
2718     vpImagePoint bottomRight_ = bottomRight / m_scale;
2719     unsigned int w = (unsigned int)vpMath::round(std::fabs(bottomRight_.get_u() - topLeft_.get_u()));
2720     unsigned int h = (unsigned int)vpMath::round(std::fabs(bottomRight_.get_v() - topLeft_.get_v()));
2721     if (fill == false) {
2722 
2723       XDrawRectangle(display, pixmap, context,
2724                      vpMath::round(topLeft_.get_u() < bottomRight_.get_u() ? topLeft_.get_u() : bottomRight_.get_u()),
2725                      vpMath::round(topLeft_.get_v() < bottomRight_.get_v() ? topLeft_.get_v() : bottomRight_.get_v()),
2726                      w > 0 ? w : 1, h > 0 ? h : 1);
2727     } else {
2728       XFillRectangle(display, pixmap, context,
2729                      vpMath::round(topLeft_.get_u() < bottomRight_.get_u() ? topLeft_.get_u() : bottomRight_.get_u()),
2730                      vpMath::round(topLeft_.get_v() < bottomRight_.get_v() ? topLeft_.get_v() : bottomRight_.get_v()),
2731                      w, h);
2732     }
2733   } else {
2734     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2735   }
2736 }
2737 
2738 /*!
2739   Display a rectangle.
2740 
2741   \param rectangle : Rectangle characteristics.
2742   \param color : Rectangle color.
2743   \param fill : When set to true fill the rectangle.
2744 
2745   \param thickness : Thickness of the four lines used to display the
2746   rectangle. This parameter is only useful when \e fill is set to
2747   false.
2748 
2749 */
displayRectangle(const vpRect & rectangle,const vpColor & color,bool fill,unsigned int thickness)2750 void vpDisplayX::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
2751 {
2752   if (m_displayHasBeenInitialized) {
2753     if (thickness == 1)
2754       thickness = 0;
2755     if (color.id < vpColor::id_unknown)
2756       XSetForeground(display, context, x_color[color.id]);
2757     else {
2758       xcolor.pad = 0;
2759       xcolor.red = 256 * color.R;
2760       xcolor.green = 256 * color.G;
2761       xcolor.blue = 256 * color.B;
2762       XAllocColor(display, lut, &xcolor);
2763       XSetForeground(display, context, xcolor.pixel);
2764     }
2765 
2766     XSetLineAttributes(display, context, thickness, LineSolid, CapButt, JoinBevel);
2767 
2768     if (fill == false) {
2769       XDrawRectangle(display, pixmap, context, vpMath::round(rectangle.getLeft() / m_scale),
2770                      vpMath::round(rectangle.getTop() / m_scale),
2771                      (unsigned int)vpMath::round(rectangle.getWidth() / m_scale - 1),
2772                      (unsigned int)vpMath::round(rectangle.getHeight() / m_scale - 1));
2773     } else {
2774       XFillRectangle(display, pixmap, context, vpMath::round(rectangle.getLeft() / m_scale),
2775                      vpMath::round(rectangle.getTop() / m_scale),
2776                      (unsigned int)vpMath::round(rectangle.getWidth() / m_scale),
2777                      (unsigned int)vpMath::round(rectangle.getHeight() / m_scale));
2778     }
2779 
2780   } else {
2781     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2782   }
2783 }
2784 
2785 /*!
2786 
2787   Wait for a click from one of the mouse button.
2788 
2789   \param blocking [in] : Blocking behavior.
2790   - When set to true, this method waits until a mouse button is
2791     pressed and then returns always true.
2792   - When set to false, returns true only if a mouse button is
2793     pressed, otherwise returns false.
2794 
2795   \return
2796   - true if a button was clicked. This is always the case if blocking is set
2797     to \e true.
2798   - false if no button was clicked. This can occur if blocking is set
2799     to \e false.
2800 */
getClick(bool blocking)2801 bool vpDisplayX::getClick(bool blocking)
2802 {
2803 
2804   bool ret = false;
2805 
2806   if (m_displayHasBeenInitialized) {
2807     Window rootwin, childwin;
2808     int root_x, root_y, win_x, win_y;
2809     unsigned int modifier;
2810 
2811     // Event testing
2812     if (blocking) {
2813       XCheckMaskEvent(display, ButtonPressMask, &event);
2814       XCheckMaskEvent(display, ButtonReleaseMask, &event);
2815       XMaskEvent(display, ButtonPressMask, &event);
2816       ret = true;
2817     } else {
2818       ret = XCheckMaskEvent(display, ButtonPressMask, &event);
2819     }
2820 
2821     if (ret) {
2822       /* Recuperation de la coordonnee du pixel clique. */
2823       if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
2824       }
2825     }
2826   } else {
2827     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2828   }
2829   return ret;
2830 }
2831 
2832 /*!
2833 
2834   Wait for a click from one of the mouse button and get the position
2835   of the clicked image point.
2836 
2837   \param ip [out] : The coordinates of the clicked image point.
2838 
2839   \param blocking [in] : true for a blocking behaviour waiting a mouse
2840   button click, false for a non blocking behaviour.
2841 
2842   \return
2843   - true if a button was clicked. This is always the case if blocking is set
2844     to \e true.
2845   - false if no button was clicked. This can occur if blocking is set
2846     to \e false.
2847 */
getClick(vpImagePoint & ip,bool blocking)2848 bool vpDisplayX::getClick(vpImagePoint &ip, bool blocking)
2849 {
2850 
2851   bool ret = false;
2852   if (m_displayHasBeenInitialized) {
2853 
2854     Window rootwin, childwin;
2855     int root_x, root_y, win_x, win_y;
2856     unsigned int modifier;
2857     // Event testing
2858     if (blocking) {
2859       XCheckMaskEvent(display, ButtonPressMask, &event);
2860       XCheckMaskEvent(display, ButtonReleaseMask, &event);
2861       XMaskEvent(display, ButtonPressMask, &event);
2862       ret = true;
2863     } else {
2864       ret = XCheckMaskEvent(display, ButtonPressMask, &event);
2865     }
2866 
2867     if (ret) {
2868       // Get mouse position
2869       if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
2870         ip.set_u((double)event.xbutton.x * m_scale);
2871         ip.set_v((double)event.xbutton.y * m_scale);
2872       }
2873     }
2874   } else {
2875     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2876   }
2877   return ret;
2878 }
2879 
2880 /*!
2881 
2882   Wait for a mouse button click and get the position of the clicked
2883   pixel. The button used to click is also set.
2884 
2885   \param ip [out] : The coordinates of the clicked image point.
2886 
2887   \param button [out] : The button used to click.
2888 
2889   \param blocking [in] :
2890   - When set to true, this method waits until a mouse button is
2891     pressed and then returns always true.
2892   - When set to false, returns true only if a mouse button is
2893     pressed, otherwise returns false.
2894 
2895   \return true if a mouse button is pressed, false otherwise. If a
2896   button is pressed, the location of the mouse pointer is updated in
2897   \e ip.
2898 */
getClick(vpImagePoint & ip,vpMouseButton::vpMouseButtonType & button,bool blocking)2899 bool vpDisplayX::getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking)
2900 {
2901 
2902   bool ret = false;
2903   if (m_displayHasBeenInitialized) {
2904 
2905     Window rootwin, childwin;
2906     int root_x, root_y, win_x, win_y;
2907     unsigned int modifier;
2908 
2909     // Event testing
2910     if (blocking) {
2911       XCheckMaskEvent(display, ButtonPressMask, &event);
2912       XCheckMaskEvent(display, ButtonReleaseMask, &event);
2913       XMaskEvent(display, ButtonPressMask, &event);
2914       ret = true;
2915     } else {
2916       ret = XCheckMaskEvent(display, ButtonPressMask, &event);
2917     }
2918 
2919     if (ret) {
2920       // Get mouse position
2921       if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
2922         ip.set_u((double)event.xbutton.x * m_scale);
2923         ip.set_v((double)event.xbutton.y * m_scale);
2924         switch (event.xbutton.button) {
2925         case Button1:
2926           button = vpMouseButton::button1;
2927           break;
2928         case Button2:
2929           button = vpMouseButton::button2;
2930           break;
2931         case Button3:
2932           button = vpMouseButton::button3;
2933           break;
2934         }
2935       }
2936     }
2937   } else {
2938     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
2939   }
2940   return ret;
2941 }
2942 
2943 /*!
2944 
2945   Wait for a mouse button click release and get the position of the
2946   image point were the click release occurs.  The button used to click is
2947   also set. Same method as getClick(unsigned int&, unsigned int&,
2948   vpMouseButton::vpMouseButtonType &, bool).
2949 
2950   \param ip [out] : Position of the clicked image point.
2951 
2952   \param button [in] : Button used to click.
2953 
2954   \param blocking [in] : true for a blocking behaviour waiting a mouse
2955   button click, false for a non blocking behaviour.
2956 
2957   \return
2958   - true if a button was clicked. This is always the case if blocking is set
2959     to \e true.
2960   - false if no button was clicked. This can occur if blocking is set
2961     to \e false.
2962 
2963   \sa getClick(vpImagePoint &, vpMouseButton::vpMouseButtonType &, bool)
2964 
2965 */
getClickUp(vpImagePoint & ip,vpMouseButton::vpMouseButtonType & button,bool blocking)2966 bool vpDisplayX::getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking)
2967 {
2968 
2969   bool ret = false;
2970   if (m_displayHasBeenInitialized) {
2971     Window rootwin, childwin;
2972     int root_x, root_y, win_x, win_y;
2973     unsigned int modifier;
2974 
2975     // Event testing
2976     if (blocking) {
2977       XCheckMaskEvent(display, ButtonPressMask, &event);
2978       XCheckMaskEvent(display, ButtonReleaseMask, &event);
2979       XMaskEvent(display, ButtonReleaseMask, &event);
2980       ret = true;
2981     } else {
2982       ret = XCheckMaskEvent(display, ButtonReleaseMask, &event);
2983     }
2984 
2985     if (ret) {
2986       /* Recuperation de la coordonnee du pixel clique. */
2987       if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
2988         ip.set_u((double)event.xbutton.x * m_scale);
2989         ip.set_v((double)event.xbutton.y * m_scale);
2990         switch (event.xbutton.button) {
2991         case Button1:
2992           button = vpMouseButton::button1;
2993           break;
2994         case Button2:
2995           button = vpMouseButton::button2;
2996           break;
2997         case Button3:
2998           button = vpMouseButton::button3;
2999           break;
3000         }
3001       }
3002     }
3003   } else {
3004     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3005   }
3006   return ret;
3007 }
3008 
3009 /*
3010   Gets the displayed image (including the overlay plane)
3011   and returns an RGBa image. If a scale factor is set using setScale(), the
3012   size of the image is the size of the downscaled image.
3013 
3014   \param I : Image to get.
3015 */
getImage(vpImage<vpRGBa> & I)3016 void vpDisplayX::getImage(vpImage<vpRGBa> &I)
3017 {
3018   if (m_displayHasBeenInitialized) {
3019     XImage *xi;
3020 
3021     XCopyArea(display, window, pixmap, context, 0, 0, m_width, m_height, 0, 0);
3022 
3023     xi = XGetImage(display, pixmap, 0, 0, m_width, m_height, AllPlanes, ZPixmap);
3024 
3025     I.resize(m_height, m_width);
3026 
3027     unsigned char *src_32 = NULL;
3028     src_32 = (unsigned char *)xi->data;
3029 
3030     if (screen_depth == 16) {
3031       for (unsigned int i = 0; i < I.getHeight(); i++) {
3032         size_t i_ = i * m_width;
3033         for (unsigned int j = 0; j < m_height; j++) {
3034           size_t ij_ = i_ + j;
3035           unsigned long pixel = XGetPixel(xi, (int)j, (int)i);
3036           I.bitmap[ij_].R = (((pixel & RMask) << RShift) >> 8);
3037           I.bitmap[ij_].G = (((pixel & GMask) << GShift) >> 8);
3038           I.bitmap[ij_].B = (((pixel & BMask) << BShift) >> 8);
3039           // On OSX the bottom/right corner (arround the resizing icon) has
3040           // alpha component with different values than 255. That's why we
3041           // force alpha to vpRGBa::alpha_default
3042           I.bitmap[ij_].A = vpRGBa::alpha_default;
3043         }
3044       }
3045 
3046     } else {
3047       if (XImageByteOrder(display) == 1) {
3048         // big endian
3049         for (unsigned int i = 0; i < m_width * m_height; i++) {
3050           // On OSX the bottom/right corner (arround the resizing icon) has
3051           // alpha component with different values than 255. That's why we
3052           // force alpha to vpRGBa::alpha_default
3053           I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4] ;
3054           I.bitmap[i].R = src_32[i * 4 + 1];
3055           I.bitmap[i].G = src_32[i * 4 + 2];
3056           I.bitmap[i].B = src_32[i * 4 + 3];
3057         }
3058       } else {
3059         // little endian
3060         for (unsigned int i = 0; i < m_width * m_height; i++) {
3061           I.bitmap[i].B = src_32[i * 4];
3062           I.bitmap[i].G = src_32[i * 4 + 1];
3063           I.bitmap[i].R = src_32[i * 4 + 2];
3064           // On OSX the bottom/right corner (arround the resizing icon) has
3065           // alpha component with different values than 255. That's why we
3066           // force alpha to vpRGBa::alpha_default
3067           I.bitmap[i].A = vpRGBa::alpha_default; // src_32[i*4 + 3];
3068         }
3069       }
3070     }
3071     XDestroyImage(xi);
3072   } else {
3073     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3074   }
3075 }
3076 
3077 /*!
3078   Gets the window depth (8, 16, 24, 32).
3079 */
getScreenDepth()3080 unsigned int vpDisplayX::getScreenDepth()
3081 {
3082   Display *display_;
3083   int screen_;
3084   unsigned int depth;
3085 
3086   if ((display_ = XOpenDisplay(NULL)) == NULL) {
3087     throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
3088                              XDisplayName(NULL)));
3089   }
3090   screen_ = DefaultScreen(display_);
3091   depth = (unsigned int)DefaultDepth(display_, screen_);
3092 
3093   XCloseDisplay(display_);
3094 
3095   return (depth);
3096 }
3097 
3098 /*!
3099   Gets screen resolution in pixels.
3100   \param w, h : Horizontal and vertical screen resolution.
3101  */
getScreenSize(unsigned int & w,unsigned int & h)3102 void vpDisplayX::getScreenSize(unsigned int &w, unsigned int &h)
3103 {
3104   Display *display_;
3105   int screen_;
3106 
3107   if ((display_ = XOpenDisplay(NULL)) == NULL) {
3108     throw(vpDisplayException(vpDisplayException::connexionError, "Can't connect display on server %s.",
3109                              XDisplayName(NULL)));
3110   }
3111   screen_ = DefaultScreen(display_);
3112   w = (unsigned int)DisplayWidth(display_, screen_);
3113   h = (unsigned int)DisplayHeight(display_, screen_);
3114 
3115   XCloseDisplay(display_);
3116 }
3117 
3118 /*!
3119   Gets the screen horizontal resolution in pixels.
3120  */
getScreenWidth()3121 unsigned int vpDisplayX::getScreenWidth()
3122 {
3123   unsigned int width, height;
3124   getScreenSize(width, height);
3125   return width;
3126 }
3127 
3128 /*!
3129   Gets the screen vertical resolution in pixels.
3130  */
getScreenHeight()3131 unsigned int vpDisplayX::getScreenHeight()
3132 {
3133   unsigned int width, height;
3134   getScreenSize(width, height);
3135   return height;
3136 }
3137 
3138 /*!
3139 
3140   Get a keyboard event.
3141 
3142   \param blocking [in] : Blocking behavior.
3143   - When set to true, this method waits until a key is
3144     pressed and then returns always true.
3145   - When set to false, returns true only if a key is
3146     pressed, otherwise returns false.
3147 
3148   \return
3149   - true if a key was pressed. This is always the case if blocking is set
3150     to \e true.
3151   - false if no key was pressed. This can occur if blocking is set
3152     to \e false.
3153 
3154   \exception vpDisplayException::notInitializedError : If the display
3155   was not initialized.
3156 
3157 */
getKeyboardEvent(bool blocking)3158 bool vpDisplayX::getKeyboardEvent(bool blocking)
3159 {
3160 
3161   bool ret = false;
3162 
3163   if (m_displayHasBeenInitialized) {
3164     // Event testing
3165     if (blocking) {
3166       XMaskEvent(display, KeyPressMask, &event);
3167       ret = true;
3168     } else {
3169       ret = XCheckMaskEvent(display, KeyPressMask, &event);
3170     }
3171   } else {
3172     vpERROR_TRACE("X not initialized ");
3173     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3174   }
3175   return ret;
3176 }
3177 /*!
3178 
3179   Get a keyboard event.
3180 
3181   \param blocking [in] : Blocking behavior.
3182   - When set to true, this method waits until a key is
3183     pressed and then returns always true.
3184   - When set to false, returns true only if a key is
3185     pressed, otherwise returns false.
3186 
3187   \param key [out]: If possible, an ISO Latin-1 character
3188   corresponding to the keyboard key.
3189 
3190   \return
3191   - true if a key was pressed. This is always the case if blocking is set
3192     to \e true.
3193   - false if no key was pressed. This can occur if blocking is set
3194     to \e false.
3195 
3196   \exception vpDisplayException::notInitializedError : If the display
3197   was not initialized.
3198 
3199 */
getKeyboardEvent(std::string & key,bool blocking)3200 bool vpDisplayX::getKeyboardEvent(std::string &key, bool blocking)
3201 {
3202   bool ret = false;
3203   KeySym keysym;
3204   //   int     count;
3205   XComposeStatus compose_status;
3206   char buffer;
3207 
3208   if (m_displayHasBeenInitialized) {
3209     // Event testing
3210     if (blocking) {
3211       XMaskEvent(display, KeyPressMask, &event);
3212       /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
3213       key = buffer;
3214       ret = true;
3215     } else {
3216       ret = XCheckMaskEvent(display, KeyPressMask, &event);
3217       if (ret) {
3218         /* count = */ XLookupString((XKeyEvent *)&event, &buffer, 1, &keysym, &compose_status);
3219         key = buffer;
3220       }
3221     }
3222   } else {
3223     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3224   }
3225   return ret;
3226 }
3227 /*!
3228 
3229   Get the coordinates of the mouse pointer.
3230 
3231   \param ip [out] : The coordinates of the mouse pointer.
3232 
3233   \return true if a pointer motion event was received, false otherwise.
3234 
3235   \exception vpDisplayException::notInitializedError : If the display
3236   was not initialized.
3237 
3238 */
getPointerMotionEvent(vpImagePoint & ip)3239 bool vpDisplayX::getPointerMotionEvent(vpImagePoint &ip)
3240 {
3241 
3242   bool ret = false;
3243   if (m_displayHasBeenInitialized) {
3244 
3245     Window rootwin, childwin;
3246     int root_x, root_y, win_x, win_y;
3247     unsigned int modifier;
3248     // Event testing
3249     ret = XCheckMaskEvent(display, PointerMotionMask, &event);
3250 
3251     if (ret) {
3252       // Get mouse position
3253       if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
3254         ip.set_u((double)event.xbutton.x * m_scale);
3255         ip.set_v((double)event.xbutton.y * m_scale);
3256       }
3257     }
3258   } else {
3259     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3260   }
3261   return ret;
3262 }
3263 
3264 /*!
3265   Get the coordinates of the mouse pointer.
3266 
3267   \param ip [out] : The coordinates of the mouse pointer.
3268 
3269   \return true.
3270 
3271   \exception vpDisplayException::notInitializedError : If the display
3272   was not initialized.
3273 */
getPointerPosition(vpImagePoint & ip)3274 bool vpDisplayX::getPointerPosition(vpImagePoint &ip)
3275 {
3276 
3277   bool ret = false;
3278   if (m_displayHasBeenInitialized) {
3279 
3280     Window rootwin, childwin;
3281     int root_x, root_y, win_x, win_y;
3282     unsigned int modifier;
3283     // Event testing
3284     ret = true;
3285 
3286     if (ret) {
3287       // Get mouse position
3288       if (XQueryPointer(display, window, &rootwin, &childwin, &root_x, &root_y, &win_x, &win_y, &modifier)) {
3289         ip.set_u((double)win_x * m_scale);
3290         ip.set_v((double)win_y * m_scale);
3291       }
3292     }
3293   } else {
3294     throw(vpDisplayException(vpDisplayException::notInitializedError, "X not initialized"));
3295   }
3296   return ret;
3297 }
3298 
3299 /*!
3300   Get the position of the most significant bit.
3301 */
getMsb(unsigned int u32val)3302 int vpDisplayX::getMsb(unsigned int u32val)
3303 {
3304   int i;
3305 
3306   for (i = 31; i >= 0; --i) {
3307     if (u32val & 0x80000000L)
3308       break;
3309     u32val <<= 1;
3310   }
3311   return i;
3312 }
3313 
3314 #elif !defined(VISP_BUILD_SHARED_LIBS)
3315 // Work arround to avoid warning: libvisp_core.a(vpDisplayX.cpp.o) has no
3316 // symbols
dummy_vpDisplayX()3317 void dummy_vpDisplayX(){};
3318 #endif
3319