X11 Work Bench Toolkit  1.0
pixmap_helper.c
1 // _ _ _ //
3 // _ __ (_)__ __ _ __ ___ __ _ _ __ | |__ ___ | | _ __ ___ _ __ ___ //
4 // | '_ \ | |\ \/ /| '_ ` _ \ / _` || '_ \ | '_ \ / _ \| || '_ \ / _ \| '__|/ __| //
5 // | |_) || | > < | | | | | || (_| || |_) | | | | || __/| || |_) || __/| | _| (__ //
6 // | .__/ |_|/_/\_\|_| |_| |_| \__,_|| .__/_____|_| |_| \___||_|| .__/ \___||_|(_)\___| //
7 // |_| |_| |_____| |_| //
8 // //
9 // pixmap and icon helpers (ultimately providing universal support) //
10 // //
12 
13 /*****************************************************************************
14 
15  X11workbench - X11 programmer's 'work bench' application and toolkit
16  Copyright (c) 2010-2016 by Bob Frazier (aka 'Big Bad Bombastic Bob')
17  all rights reserved
18 
19  DISCLAIMER: The X11workbench application and toolkit software are supplied
20  'as-is', with no warranties, either implied or explicit.
21  Any claims to alleged functionality or features should be
22  considered 'preliminary', and might not function as advertised.
23 
24  BSD-like license:
25 
26  There is no restriction as to what you can do with this software, so long
27  as you include the above copyright notice and DISCLAIMER for any distributed
28  work that is equal to or derived from this one, along with this paragraph
29  that explains the terms of the license if the source is also being made
30  available. A "derived work" describes a work that uses a significant portion
31  of the source files or algorithms that are included with this one.
32  Specifically excluded from this are files that were generated by the software,
33  or anything that is included with the software that is part of another package
34  (such as files that were created or added during the 'configure' process).
35  Specifically included is the use of part or all of any of the X11 workbench
36  toolkit source or header files in your distributed application. If you do not
37  ship the source, the above copyright statement is still required to be placed
38  in a reasonably prominent place, such as documentation, splash screens, and/or
39  'about the application' dialog boxes.
40 
41  Use and distribution are in accordance with GPL, LGPL, and/or the above
42  BSD-like license. See COPYING and README files for more information.
43 
44 
45  Additional information at http://sourceforge.net/projects/X11workbench
46 
47 ******************************************************************************/
48 
49 
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <memory.h>
53 #include <string.h>
54 #include <strings.h>
55 #include <math.h> // and now I'll need -lm
56 
57 // application header file
58 #include "pixmap_helper.h" // this will include platform_helper.h and window_helper.h
59 
60 // include pixmap data
61 
62 #include "icon_ok.xpm"
63 #include "icon_stop.xpm"
64 #include "icon_warn.xpm"
65 #include "icon_what.xpm"
66 #include "icon_splat.xpm"
67 
68 // other pixmaps (some not entirely work safe)
69 #include "icon_bang.xpm"
70 #include "icon_barney.xpm"
71 #include "icon_bear.xpm"
72 #include "icon_death.xpm"
73 #include "icon_finger.xpm"
74 #include "icon_skull.xpm"
75 #include "icon_triangle.xpm"
76 #include "icon_what_bold.xpm"
77 #include "icon_wtf.xpm"
78 #include "icon_thumbup.xpm"
79 #include "icon_thumbdown.xpm"
80 
81 
82 
83 #ifdef NO_DEBUG
84 #define DEBUG_DUMP_XPM_ATTRIBUTES(X)
85 #define DEBUG_DUMP_COLORMAP(X)
86 #else
87 static void DebugDumpXpmAttributes(const char *szFunction, int nLine, XPM_ATTRIBUTES *pAttr);
88 static void DebugDumpColormap(const XStandardColormap *pMap);
89 #define DEBUG_DUMP_XPM_ATTRIBUTES(X) DebugDumpXpmAttributes(__FUNCTION__, __LINE__, X)
90 #define DEBUG_DUMP_COLORMAP(X) DebugDumpColormap(X)
91 #endif // NO_DEBUG
92 
93 
94 #define _PI_ 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 /* approximately */
95 
96 
97 #define MINIMUM_ATOM_RESOURCE_LIST_SIZE 256
98 
99 typedef struct __INTERNAL_ATOM_RESOURCE_LIST__
100 {
101  Atom aAtom;
102  char **ppResource;
103 } INTERNAL_ATOM_RESOURCE_LIST;
104 
105 static INTERNAL_ATOM_RESOURCE_LIST *pAtomResourceList = NULL;
106 static int nAtomResourceList = 0, nAtomResourceListMax = 0;
107 
108 static char **ppRegAppLarge_Internal = NULL;
109 static char **ppRegAppSmall_Internal = NULL;
110 
111 
112 //-------------------------
113 // RGB and YUV conversions
114 //-------------------------
115 
116 static int clip255(int iIn)
117 {
118  if(iIn < 0)
119  {
120  return 0;
121  }
122  else if(iIn > 255)
123  {
124  return 255;
125  }
126 
127  return iIn;
128 }
129 
130 void PXM_RGBToYUV(int iR, int iG, int iB, int *piY, int *piU, int *piV)
131 {
132 int iY, iU, iV;
133 
134  iR = clip255(iR);
135  iG = clip255(iG);
136  iB = clip255(iB);
137 
138  iY = clip255((( 66 * iR + 129 * iG + 25 * iB + 128) >> 8) + 16);
139  iU = clip255((( -38 * iR - 74 * iG + 112 * iB + 128) >> 8) + 128);
140  iV = clip255((( 112 * iR - 94 * iG - 18 * iB + 128) >> 8) + 128);
141 
142  if(piY)
143  {
144  *piY = iY;
145  }
146 
147  if(piU)
148  {
149  *piU = iU;
150  }
151 
152  if(piV)
153  {
154  *piV = iV;
155  }
156 }
157 
158 void PXM_YUVToRGB(int iY, int iU, int iV, int *piR, int *piG, int *piB)
159 {
160 int iR, iG, iB;
161 int iC = iY - 16;
162 int iD = iU - 128;
163 int iE = iV - 128;
164 
165  iR = clip255(( 298 * iC + 409 * iE + 128) >> 8);
166  iG = clip255(( 298 * iC - 100 * iD - 208 * iE + 128) >> 8);
167  iB = clip255(( 298 * iC + 516 * iD + 128) >> 8);
168 
169  if(piR)
170  {
171  *piR = iR;
172  }
173 
174  if(piG)
175  {
176  *piG = iG;
177  }
178 
179  if(piB)
180  {
181  *piB = iB;
182  }
183 }
184 
185 void PXM_HSVToRGB(int iH, int iS, int iV, int *piR, int *piG, int *piB)
186 {
187 int iR, iG, iB;
188 double dH = iH * _PI_ * 2.0 / 256;
189 
190  iR = clip255((int)floor(iV * (1.0 + iS * (cos(dH) - 1.0))));
191  iG = clip255((int)floor(iV * (1.0 + iS * (cos(dH - (_PI_ * 2.0 / 3.0)) - 1.0))));
192  iB = clip255((int)floor(iV * (1.0 + iS * (cos(dH + (_PI_ * 2.0 / 3.0)) - 1.0))));
193 
194 // function hsv.torgb(h,s,v)
195 // local r=v*(1+s*(cos(h)-1))
196 // local g=v*(1+s*(cos(h-2.09439)-1))
197 // local b=v*(1+s*(cos(h+2.09439)-1))
198 // return r,g,b
199 // end
200 
201  if(piR)
202  {
203  *piR = iR;
204  }
205 
206  if(piG)
207  {
208  *piG = iG;
209  }
210 
211  if(piB)
212  {
213  *piB = iB;
214  }
215 }
216 
217 void PXM_RGBToHSV(int iR, int iG, int iB, int *piH, int *piS, int *piV)
218 {
219 int iC = iR + iG + iB;
220 int iH=0, iS=0, iV=0;
221 
222  if(iC == 0) // black
223  {
224  iH = 0;
225  iS = 512 / 3; // red?
226  iV = 0;
227  }
228  else
229  {
230  int iP = 2*(iB * iB + iG * iG + iR * iR - iG * iR - iB * iG - iB * iR);
231 
232  if(iP < 0)
233  {
234  iP = 0; // added by bob, to prevent dividing by zero (evar)
235  }
236  iH = ((int)floor(256 * atan2(iB - iG, sqrt(fabs((2.0 * iR - iB - iG)/3.0))) / (_PI_ * 2.0)))
237  & 255; // this is calculating an angle, 0 to 2PI, which should rotate 0-255
238  iS = clip255(iP / (iC + iP)); // iC is never zero
239  iV = clip255((iC + iP) / 3);
240 
241 // function hsv.fromrgb(r,b,g)
242 // local c=r+g+b
243 // if c<1e-4 then
244 // return 0,2/3,0
245 // else
246 // local p=2*(b*b+g*g+r*r-g*r-b*g-b*r)^0.5
247 // local h=atan2(b-g,(2*r-b-g)/3^0.5)
248 // local s=p/(c+p)
249 // local v=(c+p)/3
250 // return h,s,v
251 // end
252 // end
253  }
254 
255  if(piH)
256  {
257  *piH = iH;
258  }
259 
260  if(piS)
261  {
262  *piS = iS;
263  }
264 
265  if(piV)
266  {
267  *piV = iV;
268  }
269 }
270 
271 
272 void PXM_PixelToRGB(XStandardColormap *pMap, XColor *pColor)
273 {
274 unsigned long long lColor, l2;
275 XStandardColormap map;
276 
277 
278  if(!pColor)
279  {
280  return;
281  }
282 
283  if(!pMap)
284  {
286  pMap = &map;
287 
288 // DEBUG_DUMP_COLORMAP(pMap);
289  }
290 
291  // 'nuking' this one out is a bit difficult. I have to sort the values properly
292 
293  lColor = pColor->pixel - pMap->base_pixel;
294 
295  if(!pMap->red_mult && !pMap->green_mult && !pMap->blue_mult)
296  {
297  return;
298  }
299 
300  pColor->flags = DoRed | DoGreen | DoBlue; // pre-assign this, re-assign as needed
301 
302  if(pMap->red_mult >= pMap->green_mult &&
303  pMap->red_mult >= pMap->blue_mult) // this includes monochrome I think
304  {
305  if(!pMap->green_mult && !pMap->blue_mult)
306  {
307  // it's monochrome, so I only use red
308 
309  if(pMap->red_mult == 1)
310  {
311  l2 = ((unsigned long long)65535 * lColor);
312  }
313  else
314  {
315  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
316  }
317 
318  if(l2 >= 65536 * pMap->red_max)
319  {
320  l2 = 65535;
321  }
322 // else if(lColor < 0)
323 // {
324 // l2 = 0;
325 // }
326  else
327  {
328  l2 /= pMap->red_max;
329  }
330 
331  pColor->red = l2;
332  pColor->green = l2;
333  pColor->blue = l2; // since it's monochrome, though only 'DoRed' is assigned
334 
335  pColor->flags = DoRed; // usually indicates 'monochrome'
336  }
337  else if(pMap->green_mult > pMap->blue_mult)
338  {
339  // red first
340 
341  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
342  lColor %= pMap->red_mult;
343 
344 
345  if(l2 >= 65536 * pMap->red_max)
346  {
347  l2 = 65535 * pMap->red_max;
348  }
349 // else if(lColor < 0) // won't happen
350 // {
351 // l2 = 0;
352 // }
353  else
354  {
355  l2 /= pMap->red_max;
356  }
357 
358  pColor->red = l2;
359 
360  // then green
361 
362  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
363  lColor %= pMap->green_mult;
364 
365  if(l2 >= 65536 * pMap->green_max)
366  {
367  l2 = 65535 * pMap->green_max;
368  }
369 // else if(lColor < 0) // won't happen
370 // {
371 // l2 = 0;
372 // }
373  else
374  {
375  l2 /= pMap->green_max;
376  }
377 
378  pColor->green = l2;
379 
380  // and then, blue
381 
382  if(!pMap->blue_mult)
383  {
384  l2 = 0;
385  }
386  else
387  {
388  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
389 
390  if(l2 >= 65536 * pMap->blue_max)
391  {
392  l2 = 65535 * pMap->blue_max;
393  }
394 // else if(lColor < 0)
395 // {
396 // l2 = 0;
397 // }
398  else
399  {
400  l2 /= pMap->blue_max;
401  }
402  }
403  pColor->blue = l2;
404  }
405  else // if(pMap->blue_mult > pMap->green_mult)
406  {
407  // red first
408 
409  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
410  lColor %= pMap->red_mult;
411 
412  if(l2 >= 65536 * pMap->red_max)
413  {
414  l2 = 65535 * pMap->red_max;
415  }
416 // else if(lColor < 0)
417 // {
418 // l2 = 0;
419 // }
420  else
421  {
422  l2 /= pMap->red_max;
423  }
424 
425  pColor->red = l2;
426 
427  // then blue
428 
429  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
430  lColor %= pMap->blue_mult;
431 
432  if(l2 >= 65536 * pMap->blue_max)
433  {
434  l2 = 65535 * pMap->blue_max;
435  }
436 // else if(lColor < 0)
437 // {
438 // l2 = 0;
439 // }
440  else
441  {
442  l2 /= pMap->blue_max;
443  }
444 
445  pColor->blue = l2;
446 
447  // and then, green
448 
449  if(!pMap->green_mult)
450  {
451  l2 = 0;
452  }
453  else
454  {
455  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
456 
457  if(l2 >= 65536 * pMap->green_max)
458  {
459  l2 = 65535 * pMap->green_max;
460  }
461 // else if(lColor < 0)
462 // {
463 // l2 = 0;
464 // }
465  else
466  {
467  l2 /= pMap->green_max;
468  }
469  }
470 
471  pColor->green = l2;
472  }
473  }
474  else if(pMap->green_mult >= pMap->red_mult &&
475  pMap->green_mult >= pMap->blue_mult)
476  {
477  if(pMap->red_mult > pMap->blue_mult)
478  {
479  // green first
480 
481  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
482  lColor %= pMap->green_mult;
483 
484  if(l2 >= 65536 * pMap->green_max)
485  {
486  l2 = 65535 * pMap->green_max;
487  }
488 // else if(lColor < 0)
489 // {
490 // l2 = 0;
491 // }
492  else
493  {
494  l2 /= pMap->green_max;
495  }
496 
497  pColor->green = l2;
498 
499  // then red
500 
501  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
502  lColor %= pMap->red_mult;
503 
504  if(l2 >= 65536 * pMap->red_max)
505  {
506  l2 = 65535 * pMap->red_max;
507  }
508 // else if(lColor < 0)
509 // {
510 // l2 = 0;
511 // }
512  else
513  {
514  l2 /= pMap->red_max;
515  }
516 
517  pColor->red = l2;
518 
519  // and then, blue
520 
521  if(!pMap->blue_mult)
522  {
523  l2 = 0;
524  }
525  else
526  {
527  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
528 
529  if(l2 >= 65536 * pMap->blue_max)
530  {
531  l2 = 65535 * pMap->blue_max;
532  }
533 // else if(lColor < 0)
534 // {
535 // l2 = 0;
536 // }
537  else
538  {
539  l2 /= pMap->blue_max;
540  }
541  }
542  pColor->blue = l2;
543  }
544  else // if(pMap->blue_mult > pMap->green_mult)
545  {
546  // green first
547 
548  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
549  lColor %= pMap->green_mult;
550 
551  if(l2 >= 65536 * pMap->green_max)
552  {
553  l2 = 65535 * pMap->green_max;
554  }
555 // else if(lColor < 0)
556 // {
557 // l2 = 0;
558 // }
559  else
560  {
561  l2 /= pMap->green_max;
562  }
563 
564  pColor->green = l2;
565 
566  // then blue
567 
568  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
569  lColor %= pMap->blue_mult;
570 
571  if(l2 >= 65536 * pMap->blue_max)
572  {
573  l2 = 65535 * pMap->blue_max;
574  }
575 // else if(lColor < 0)
576 // {
577 // l2 = 0;
578 // }
579  else
580  {
581  l2 /= pMap->blue_max;
582  }
583 
584  pColor->blue = l2;
585 
586  // and then, red
587 
588  if(!pMap->red_mult)
589  {
590  l2 = 0;
591  }
592  else
593  {
594  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
595 
596  if(l2 >= 65536 * pMap->red_max)
597  {
598  l2 = 65535 * pMap->red_max;
599  }
600 // else if(lColor < 0)
601 // {
602 // l2 = 0;
603 // }
604  else
605  {
606  l2 /= pMap->red_max;
607  }
608  }
609 
610  pColor->red = l2;
611  }
612  }
613  else //if(pMap->blue_mult >= pMap->red_mult &&
614  // pMap->blue_mult >= pMap->green_mult)
615  {
616  if(pMap->red_mult > pMap->green_mult)
617  {
618  // blue first
619 
620  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
621  lColor %= pMap->blue_mult;
622 
623  if(l2 >= 65536 * pMap->blue_max)
624  {
625  l2 = 65535 * pMap->blue_max;
626  }
627 // else if(lColor < 0)
628 // {
629 // l2 = 0;
630 // }
631  else
632  {
633  l2 /= pMap->blue_max;
634  }
635 
636  pColor->blue = l2;
637 
638  // then red
639 
640  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
641  lColor %= pMap->red_mult;
642 
643  if(l2 >= 65536 * pMap->red_max)
644  {
645  l2 = 65535 * pMap->red_max;
646  }
647 // else if(lColor < 0)
648 // {
649 // l2 = 0;
650 // }
651  else
652  {
653  l2 /= pMap->red_max;
654  }
655 
656  pColor->red = l2;
657 
658  // and then, green
659 
660  if(!pMap->green_mult)
661  {
662  l2 = 0;
663  }
664  else
665  {
666  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
667 
668  if(l2 >= 65536 * pMap->green_max)
669  {
670  l2 = 65535 * pMap->green_max;
671  }
672 // else if(lColor < 0)
673 // {
674 // l2 = 0;
675 // }
676  else
677  {
678  l2 /= pMap->green_max;
679  }
680  }
681  pColor->green = l2;
682  }
683  else // if(pMap->blue_mult > pMap->green_mult)
684  {
685  // blue first
686 
687  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
688  lColor %= pMap->blue_mult;
689 
690  if(l2 >= 65536 * pMap->blue_max)
691  {
692  l2 = 65535 * pMap->blue_max;
693  }
694 // else if(lColor < 0)
695 // {
696 // l2 = 0;
697 // }
698  else
699  {
700  l2 /= pMap->blue_max;
701  }
702 
703  pColor->blue = l2;
704 
705  // then green
706 
707  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
708  lColor %= pMap->green_mult;
709 
710  if(l2 >= 65536 * pMap->green_max)
711  {
712  l2 = 65535 * pMap->green_max;
713  }
714 // else if(lColor < 0)
715 // {
716 // l2 = 0;
717 // }
718  else
719  {
720  l2 /= pMap->green_max;
721  }
722 
723  pColor->green = l2;
724 
725 
726  // and then, red
727 
728  if(!pMap->red_mult)
729  {
730  l2 = 0;
731  }
732  else
733  {
734  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
735 
736  if(l2 >= 65536 * pMap->red_max)
737  {
738  l2 = 65535 * pMap->red_max;
739  }
740 // else if(lColor < 0)
741 // {
742 // l2 = 0;
743 // }
744  else
745  {
746  l2 /= pMap->red_max;
747  }
748  }
749 
750  pColor->red = l2;
751  }
752  }
753 }
754 
755 void PXM_RGBToPixel(XStandardColormap *pMap, XColor *pColor)
756 {
757 unsigned long lR, lG, lB;
758 XStandardColormap map;
759 
760 
761  if(!pColor)
762  {
763  return;
764  }
765 
766  if(!pMap)
767  {
769  pMap = &map;
770 
771 // DEBUG_DUMP_COLORMAP(pMap);
772  }
773 
774  // this one is straightforward, right out of the docs for the XStandardColormap structure
775 
776  lR = lG = lB = 0; // pre-assign
777 
778  if(!pColor->flags) // assume all 3 primaries, assign accordingly
779  {
780  pColor->flags = DoRed | DoGreen | DoBlue;
781  }
782 
783  if(pColor->flags & DoRed)
784  {
785  lR = (unsigned long)(pColor->red * pMap->red_max) / 65535;
786  }
787 
788 // if(lR < 0)
789 // {
790 // lR = 0;
791 // }
792 // else
793  if(lR > pMap->red_max)
794  {
795  lR = pMap->red_max;
796  }
797 
798  if(pColor->flags & DoGreen)
799  {
800  lG = (unsigned long)(pColor->green * pMap->green_max) / 65535;
801  }
802 
803 // if(lG < 0)
804 // {
805 // lG = 0;
806 // }
807 // else
808  if(lG > pMap->green_max)
809  {
810  lG = pMap->green_max;
811  }
812 
813  if(pColor->flags & DoBlue)
814  {
815  lB = (unsigned long)(pColor->blue * pMap->blue_max) / 65535;
816  }
817 
818 // if(lB < 0)
819 // {
820 // lB = 0;
821 // }
822 // else
823  if(lB > pMap->blue_max)
824  {
825  lB = pMap->blue_max;
826  }
827 
828  pColor->pixel = (pMap->base_pixel
829  + lR * pMap->red_mult
830  + lG * pMap->green_mult
831  + lB * pMap->blue_mult)
832  & 0xffffffffL;
833 }
834 
835 
836 void PXM_RegisterAppIcons(char *ppRegAppLarge[], char *ppRegAppSmall[])
837 {
838  ppRegAppLarge_Internal = ppRegAppLarge;
839  ppRegAppSmall_Internal = ppRegAppSmall;
840 }
841 
842 static char **GetPreDefinedIconResource(int idIcon)
843 {
844 char **pData = NULL;
845 
846  switch(idIcon)
847  {
848  case ID_APPLICATION:
849  if(ppRegAppSmall_Internal)
850  {
851  pData = ppRegAppSmall_Internal;
852  }
853  else
854  {
855  pData = icon_ok_xpm; // TODO: make a 19x19 version
856  }
857  break;
858  case ID_ICON_APP:
859  if(ppRegAppLarge_Internal)
860  {
861  pData = ppRegAppLarge_Internal;
862  }
863  else
864  {
865  pData = icon_ok_xpm;
866  }
867  break;
868  case ID_ICON_OK:
869  pData = icon_ok_xpm;
870  break;
871  case ID_ICON_STOP:
872  pData = icon_stop_xpm;
873  break;
874  case ID_ICON_WARN:
875  pData = icon_warn_xpm;
876  break;
877  case ID_ICON_WHAT:
878  pData = icon_what_xpm;
879  break;
880  case ID_ICON_SPLAT:
881  pData = icon_splat_xpm;
882  break;
883  case ID_ICON_BANG:
884  pData = icon_bang_xpm;
885  break;
886  case ID_ICON_TRIANGLE:
887  pData = icon_triangle_xpm;
888  break;
889  case ID_ICON_WHAT_BOLD:
890  pData = icon_what_bold_xpm;
891  break;
892  case ID_ICON_WTF:
893  pData = icon_wtf_xpm;
894  break;
895  case ID_ICON_DEATH:
896  pData = icon_death_xpm;
897  break;
898  case ID_ICON_FINGER:
899  pData = icon_finger_xpm;
900  break;
901  case ID_ICON_SKULL:
902  pData = icon_skull_xpm;
903  break;
904  case ID_ICON_THUMBUP:
905  pData = icon_thumbup_xpm;
906  break;
907  case ID_ICON_THUMBDOWN:
908  pData = icon_thumbdown_xpm;
909  break;
910  case ID_ICON_BEAR:
911  pData = icon_bear_xpm;
912  break;
913  case ID_ICON_BARNEY: // this is a joke. really.
914  pData = icon_barney_xpm;
915  break;
916  }
917 
918  return pData;
919 }
920 
921 static void RegisterIconResource(Atom aIcon, char **ppResource)
922 {
923 int i1;
924 
925  if(!pAtomResourceList)
926  {
927  pAtomResourceList = (INTERNAL_ATOM_RESOURCE_LIST *)
928  WBAlloc(MINIMUM_ATOM_RESOURCE_LIST_SIZE * sizeof(*pAtomResourceList));
929 
930  if(!pAtomResourceList)
931  {
932  WB_ERROR_PRINT("%s - not enough memoory for atom resource list\n", __FUNCTION__);
933  return;
934  }
935 
936  nAtomResourceList = 0;
937  nAtomResourceListMax = MINIMUM_ATOM_RESOURCE_LIST_SIZE;
938  }
939 
940  for(i1=0; i1 < nAtomResourceList; i1++)
941  {
942  if(pAtomResourceList[i1].aAtom == aIcon) // already there?
943  {
944  WB_ERROR_PRINT("%s - matching atom already in the list (ignoring)\n", __FUNCTION__);
945  return; // fow now I just leave. later I might allow editing
946  }
947  }
948 
949  if((nAtomResourceList + 1) >= nAtomResourceListMax)
950  {
951  int iNewSize = MINIMUM_ATOM_RESOURCE_LIST_SIZE / 2 + nAtomResourceListMax;
952 
953  void *pTemp = WBReAlloc(pAtomResourceList, iNewSize);
954  if(!pTemp)
955  {
956  WB_ERROR_PRINT("%s - not enough memoory for atom resource list re-alloc\n", __FUNCTION__);
957  return;
958  }
959 
960  pAtomResourceList = (INTERNAL_ATOM_RESOURCE_LIST *)pTemp;
961  nAtomResourceListMax += MINIMUM_ATOM_RESOURCE_LIST_SIZE / 2;
962  }
963 
964  pAtomResourceList[nAtomResourceList].aAtom = aIcon;
965  pAtomResourceList[nAtomResourceList].ppResource = ppResource;
966  nAtomResourceList++;
967 }
968 
969 static const char * const szPreDefinedIconResources[] =
970 {
971  "ID_APPLICATION",
972  "ID_ICON_OK",
973  "ID_ICON_STOP",
974  "ID_ICON_WARN",
975  "ID_ICON_WHAT",
976  "ID_ICON_QUESTION",
977  "ID_ICON_SPLAT",
978  "ID_ICON_ASTERISK",
979  "ID_ICON_BANG",
980  "ID_ICON_TRIANGLE",
981  "ID_ICON_WHAT_BOLD",
982  "ID_ICON_WTF",
983  "ID_ICON_DEATH",
984  "ID_ICON_FINGER",
985  "ID_ICON_SKULL",
986  "ID_ICON_THUMBUP",
987  "ID_ICON_THUMBDOWN",
988  "ID_ICON_BEAR",
989  "ID_ICON_BARNEY",
990  "ID_ICON_APP"
991 };
992 
993 static char **GetRegisteredIconResource(Atom aIcon)
994 {
995 static int iHasBeenRegistered = 0;
996 int i1, i2;
997 
998  // if the pre-defined atoms have not yet been registered, do it NOW
999 
1000  if(!iHasBeenRegistered)
1001  {
1002  for(i1=ID_ICON_FIRST, i2=0;
1003  i1 <= ID_ICON_LAST
1004  && i2 < sizeof(szPreDefinedIconResources)/sizeof(szPreDefinedIconResources[0]);
1005  i1++, i2++)
1006  {
1007  Atom aTemp = WBGetAtom(WBGetDefaultDisplay(), szPreDefinedIconResources[i2]);
1008 
1009  if(aTemp != None)
1010  {
1011  RegisterIconResource(aTemp, GetPreDefinedIconResource(i1));
1012  }
1013  }
1014 
1015  iHasBeenRegistered = 1;
1016  }
1017 
1018  for(i1=0; i1 < nAtomResourceList; i1++)
1019  {
1020  if(pAtomResourceList[i1].aAtom == aIcon) // already there?
1021  {
1022  return pAtomResourceList[i1].ppResource;
1023  }
1024  }
1025 
1026  return NULL;
1027 }
1028 
1029 
1030 
1031 Pixmap PXM_GetIconPixmap(int idIcon, XPM_ATTRIBUTES *pAttr, Pixmap *pMask)
1032 {
1033 char **pData;
1034 
1035 
1036  pData = GetPreDefinedIconResource(idIcon);
1037 
1038  if(!pData)
1039  {
1040  if(pAttr)
1041  {
1042  bzero(pAttr, sizeof(*pAttr));
1043  }
1044 
1045  if(pMask)
1046  {
1047  *pMask = None;
1048  }
1049 
1050  return None;
1051  }
1052 
1053  return PXM_LoadPixmap(pData, pAttr, pMask);
1054 }
1055 
1056 
1057 Pixmap PXM_GetIconPixmapFromAtom(Atom aIcon, XPM_ATTRIBUTES *pAttr, Pixmap *pMask /* = NULL*/)
1058 {
1059 char **pData;
1060 
1061 
1062  pData = GetRegisteredIconResource(aIcon);
1063 
1064  if(!pData)
1065  {
1066  if(pAttr)
1067  {
1068  bzero(pAttr, sizeof(*pAttr));
1069  }
1070 
1071  if(pMask)
1072  {
1073  *pMask = None;
1074  }
1075 
1076  return None;
1077  }
1078 
1079  return PXM_LoadPixmap(pData, pAttr, pMask);
1080 }
1081 
1082 
1083 Pixmap PXM_LoadPixmap(char *ppXPM[], XPM_ATTRIBUTES *pAttr, Pixmap *pMask /* = NULL*/)
1084 {
1085 Pixmap pixRval = None, pixRval2 = None;
1086 XPM_ATTRIBUTES xattr;
1087 //#ifndef NO_DEBUG
1088 //WB_UINT64 ullTime = WBGetTimeIndex();
1089 //#endif // NO_DEBUG
1090 
1091 
1092  if(!ppXPM)
1093  {
1094  if(pAttr)
1095  {
1096  bzero(pAttr, sizeof(*pAttr));
1097  }
1098 
1099  if(pMask)
1100  {
1101  *pMask = None;
1102  }
1103 
1104  return None;
1105  }
1106 
1107  bzero(&xattr, sizeof(xattr));
1108 
1109 // WB_ERROR_PRINT("TEMPORARY: %s line %d delta tick %lld\n", __FUNCTION__, __LINE__, (WBGetTimeIndex() - ullTime));
1110 
1111 #ifdef X11WORKBENCH_TOOLKIT_HAVE_XPM
1113 #endif // X11WORKBENCH_TOOLKIT_HAVE_XPM
1115  ppXPM, &pixRval, &pixRval2, &xattr);
1116 #ifdef X11WORKBENCH_TOOLKIT_HAVE_XPM
1118 #endif // X11WORKBENCH_TOOLKIT_HAVE_XPM
1119 
1120 // WB_ERROR_PRINT("TEMPORARY: %s line %d delta tick %lld\n", __FUNCTION__, __LINE__, (WBGetTimeIndex() - ullTime));
1121 
1122  if(pAttr)
1123  {
1124  memcpy(pAttr, &xattr, sizeof(xattr));
1125  }
1126  else
1127  {
1128  WB_IF_DEBUG_LEVEL(DebugLevel_Light | DebugSubSystem_Pixmap)
1129  {
1130  DEBUG_DUMP_XPM_ATTRIBUTES(&xattr);
1131  }
1132 
1133  XPM_FREE_ATTRIBUTES(&xattr);
1134  }
1135 
1136  if(pMask)
1137  {
1138  *pMask = pixRval2;
1139  }
1140  else if(pixRval2 != None) // free pixRval2 if it was allocated (it's the 'mask')
1141  {
1143  XFreePixmap(WBGetDefaultDisplay(), pixRval2);
1145  }
1146 
1147  return(pixRval);
1148 }
1149 
1150 Pixmap PXM_ImageToPixmap(Display *pDisplay, Drawable dw, XImage *pImage,
1151  unsigned long clrFGPixel, unsigned long clrBGPixel)
1152 {
1153 Pixmap pxRval;
1154 GC gc;
1155 XGCValues gcv;
1156 int iW, iH;
1157 
1158  if(!pDisplay)
1159  {
1160  pDisplay = WBGetDefaultDisplay();
1161  }
1162 
1163  if(!pImage)
1164  {
1165  WB_ERROR_PRINT("%s - pImage is NULL\n", __FUNCTION__);
1166  return None;
1167  }
1168 
1169  iW = pImage->width;
1170  iH = pImage->height;
1171 
1172  if(!iW || !iH)
1173  {
1174  WB_ERROR_PRINT("%s - Image width/height not valid, iW=%d,iH=%d\n", __FUNCTION__, iW, iH);
1175  return None;
1176  }
1177 
1179  pxRval = XCreatePixmap(pDisplay, dw, iW, iH, DefaultDepth(pDisplay, DefaultScreen(pDisplay)));
1181 
1182  if(pxRval == None)
1183  {
1184  WB_ERROR_PRINT("%s - XCreatePixmap failed\n", __FUNCTION__);
1185  return None;
1186  }
1187 
1188  // I will need to create a GC. Make it a simple one that only specifies FG and BG
1189 
1190  gcv.foreground = clrFGPixel;//BlackPixel(pDisplay, DefaultScreen(pDisplay));
1191  gcv.background = clrBGPixel;//WhitePixel(pDisplay, DefaultScreen(pDisplay));
1192 
1193  // NOTE: for monochrome masks I'd likely use '1' for foreground, '0' for background
1194 
1196  gc = XCreateGC(pDisplay, dw, (GCForeground | GCBackground), &gcv);
1198 
1199  if(gc == None)
1200  {
1201  WB_ERROR_PRINT("%s - XCreateGC failed\n", __FUNCTION__);
1202 
1204  XFreePixmap(pDisplay, pxRval);
1206  return None;
1207  }
1208  else
1209  {
1211  XPutImage(pDisplay, pxRval, gc, pImage, 0, 0, 0, 0, iW, iH); // and now I have a copy of it
1212 
1213  XFreeGC(pDisplay, gc);
1215  }
1216 
1217  return pxRval;
1218 }
1219 
1220 
1221 Pixmap PXM_ImageToPixmap0(Display *pDisplay, Drawable dw, XImage *pImage)
1222 {
1223  if(!pDisplay)
1224  {
1225  pDisplay = WBGetDefaultDisplay();
1226  }
1227 
1228  return PXM_ImageToPixmap(pDisplay, dw, pImage,
1229  BlackPixel(pDisplay, DefaultScreen(pDisplay)),
1230  WhitePixel(pDisplay, DefaultScreen(pDisplay)));
1231 }
1232 
1233 
1234 XImage *PXM_PixmapToImage(Display *pDisplay, Pixmap pxImage)
1235 {
1236 XImage *pRval;
1237 int iX=0, iY=0;
1238 Window winRoot; // not used, still needed?
1239 unsigned int iWidth=0, iHeight=0, iBorder;
1240 unsigned int uiDepth = 0;
1241 
1242 
1243  if(!pDisplay)
1244  {
1245  pDisplay = WBGetDefaultDisplay();
1246  }
1247 
1248  // TODO: special handling for pxImage == None ???
1249 
1250  if(pxImage == None)
1251  {
1252  return NULL;
1253  }
1254 
1256 
1257  // use XGetGeometry to obtain the characteristics of the pixmap. iX and iY SHOULD be zero...
1258  XGetGeometry(pDisplay, pxImage, &winRoot, &iX, &iY, &iWidth, &iHeight, &iBorder, &uiDepth);
1259 
1260  if(!iWidth || !iHeight)
1261  {
1262  pRval = NULL;
1263  }
1264  else
1265  {
1266  // TODO: do I still need iX and iY?
1267  pRval = XGetImage(pDisplay, pxImage, 0, 0, iWidth, iHeight, -1L, ZPixmap);
1268  }
1269 
1271 
1272  return pRval;
1273 }
1274 
1275 
1276 
1277 
1278 void PXM_OnExit(void)
1279 {
1280  if(pAtomResourceList)
1281  {
1282  WBFree(pAtomResourceList);
1283  pAtomResourceList = NULL;
1284  }
1285 
1286  nAtomResourceList = 0;
1287  nAtomResourceListMax = 0;
1288 
1289  ppRegAppLarge_Internal = NULL;
1290  ppRegAppSmall_Internal = NULL;
1291 }
1292 
1293 
1294 
1295 #ifndef NO_DEBUG
1296 static void DebugDumpXpmAttributes(const char *szFunction, int nLine, XPM_ATTRIBUTES *pAttr)
1297 {
1298  WBDebugPrint("%s line %d XPM_ATTRIBUTES contain:\n", szFunction, nLine);
1299 #if defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1300  WBDebugPrint(" valuemask: %ld\n", pAttr->valuemask);
1301  WBDebugPrint(" visual: %p\n", pAttr->visual);
1302  WBDebugPrint(" colormap: %p\n", (void *)pAttr->colormap);
1303 #endif // defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1304 
1305  WBDebugPrint(" depth: %u\n", pAttr->depth);
1306  WBDebugPrint(" width: %u\n", pAttr->width);
1307  WBDebugPrint(" height: %u\n", pAttr->height);
1308 
1309 #if defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1310  WBDebugPrint(" x_hotspot: %u\n", pAttr->x_hotspot);
1311  WBDebugPrint(" y_hotspot: %u\n", pAttr->y_hotspot);
1312  WBDebugPrint(" cpp: %u\n", pAttr->cpp);
1313  WBDebugPrint(" pixels: %p\n", pAttr->pixels);
1314  WBDebugPrint(" npixels: %u\n", pAttr->npixels);
1315  WBDebugPrint(" colorsymbols: %p\n", pAttr->colorsymbols);
1316  WBDebugPrint(" numsymbols: %u\n", pAttr->numsymbols);
1317  WBDebugPrint(" rgb_fname: %s\n", pAttr->rgb_fname);
1318  WBDebugPrint(" nextensions: %u\n", pAttr->nextensions);
1319  WBDebugPrint(" extensions: %p\n", pAttr->extensions);
1320  WBDebugPrint(" ncolors: %u\n", pAttr->ncolors);
1321  WBDebugPrint(" colorTable: %p\n", pAttr->colorTable);
1322  WBDebugPrint(" mask_pixel: %u\n", pAttr->mask_pixel);
1323  WBDebugPrint(" exactColors: %c\n", pAttr->exactColors ? 'T' : 'F');
1324  WBDebugPrint(" closeness: %u\n", pAttr->closeness);
1325  WBDebugPrint(" red_closeness: %u\n", pAttr->red_closeness);
1326  WBDebugPrint(" green_closeness: %u\n", pAttr->green_closeness);
1327  WBDebugPrint(" blue_closeness: %u\n", pAttr->blue_closeness);
1328  WBDebugPrint(" color_key: %d\n", pAttr->color_key);
1329  WBDebugPrint(" alloc_pixels: %p\n", pAttr->alloc_pixels);
1330  WBDebugPrint(" nalloc_pixels: %d\n", pAttr->nalloc_pixels);
1331  WBDebugPrint(" alloc_close_colors: %c\n", pAttr->alloc_close_colors ? 'T' : 'F');
1332  WBDebugPrint(" bitmap_format: %d\n", pAttr->bitmap_format);
1333  WBDebugPrint(" alloc_color: %p\n", pAttr->alloc_color);
1334  WBDebugPrint(" free_colors: %p\n", pAttr->free_colors);
1335  WBDebugPrint(" color_closure: %p\n", pAttr->color_closure);
1336 #endif // defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1337 }
1338 
1339 static void DebugDumpColormap(const XStandardColormap *pMap)
1340 {
1341  WBDebugPrint("XStandardColormap: %p\n", pMap);
1342  WBDebugPrint(" colormap = %lld\n", (WB_UINT64)pMap->colormap);
1343  WBDebugPrint(" red_max = %ld\n", pMap->red_max);
1344  WBDebugPrint(" red_mult = %ld\n", pMap->red_mult);
1345  WBDebugPrint(" green_max = %ld\n", pMap->green_max);
1346  WBDebugPrint(" green_mult = %ld\n", pMap->green_mult);
1347  WBDebugPrint(" blue_max = %ld\n", pMap->blue_max);
1348  WBDebugPrint(" blue_mult = %ld\n", pMap->blue_mult);
1349  WBDebugPrint(" base_pixel = %ld (%08lxH)\n", pMap->base_pixel, pMap->base_pixel);
1350 }
1351 
1352 
1353 #endif // !NO_DEBUG
1354 
Pixmap PXM_GetIconPixmap(int idIcon, XPM_ATTRIBUTES *pAttr, Pixmap *pMask)
Create Icon pixmap pair using pre-defined resource ID.
void PXM_RGBToYUV(int iR, int iG, int iB, int *piY, int *piU, int *piV)
Convert R, G, B values to Y, U, V with 0-255 range.
static __inline__ Display * WBGetDefaultDisplay(void)
Returns the default Display.
void WBDefaultStandardColormap(Display *pDisplay, XStandardColormap *pMap)
returns a default XStandardColormap structure for the default screen of the specified display ...
void PXM_YUVToRGB(int iY, int iU, int iV, int *piR, int *piG, int *piB)
Convert Y, U, V values to R, G, B with 0-255 range.
void PXM_RegisterAppIcons(char *ppRegAppLarge[], char *ppRegAppSmall[])
Icon Registration for application &#39;large&#39; and &#39;small&#39; icons.
Pixmap PXM_LoadPixmap(char *ppXPM[], XPM_ATTRIBUTES *pAttr, Pixmap *pMask)
Create pixmap or pixmap pair using an XPM array.
Window WBGetHiddenHelperWindow(void)
Returns a special &#39;hidden&#39; window used for information purposes.
#define XPM_FREE_ATTRIBUTES(pAttr)
Platform helper macro to free XPM_ATTRIBUTES filled in by XPM_CREATE_PIXMAP_FROM_DATA() ...
void PXM_OnExit(void)
Frees resources allocated by Pixmap utility functions.
void PXM_RGBToPixel(XStandardColormap *pMap, XColor *pColor)
Icon Registration for application &#39;large&#39; and &#39;small&#39; icons.
void PXM_PixelToRGB(XStandardColormap *pMap, XColor *pColor)
Convert the pixel menber of an XColor to RGB.
unsigned long long WB_UINT64
Platform abstract unsigned 64-bit integer.
Pixmap PXM_GetIconPixmapFromAtom(Atom aIcon, XPM_ATTRIBUTES *pAttr, Pixmap *pMask)
Create Icon pixmap pair using a registered or pre-defined resource ID.
void * WBReAlloc(void *pBuf, int nNewSize)
High performance memory sub-allocator &#39;re-allocate&#39;.
Pixmap PXM_ImageToPixmap(Display *pDisplay, Drawable dw, XImage *pImage, unsigned long clrFGPixel, unsigned long clrBGPixel)
Convert &#39;locally stored&#39; XImage to &#39;server object&#39; Pixmap.
int depth
depth of the returned &#39;image&#39; pixmap. The mask pixmap always has a depth of &#39;1&#39;.
void * WBAlloc(int nSize)
High performance memory sub-allocator &#39;allocate&#39;.
#define END_XCALL_DEBUG_WRAPPER
wrapper macro for calls into the X11 library. This macro follows the call(s)
#define WB_ERROR_PRINT(...)
Preferred method of implementing an &#39;error level&#39; debug message for all subsystems.
Definition: debug_helper.h:268
void WBFree(void *pBuf)
High performance memory sub-allocator &#39;free&#39;.
XImage * PXM_PixmapToImage(Display *pDisplay, Pixmap pxImage)
Convert pixmap to image (a wrapper for XGetImage on a pixmap)
void PXM_RGBToHSV(int iR, int iG, int iB, int *piH, int *piS, int *piV)
Convert R, G, B values to H, S, V with 0-255 range.
Pixmap PXM_ImageToPixmap0(Display *pDisplay, Drawable dw, XImage *pImage)
Convert &#39;locally stored&#39; XImage to &#39;server object&#39; Pixmap using default FG/BG colors for monochrome...
#define BEGIN_XCALL_DEBUG_WRAPPER
wrapper macro for calls into the X11 library. This macro precedes the call(s)
int height
height of the returned pixmaps
int width
The width of the returned pixmaps.
void WBDebugPrint(const char *pFmt,...) __attribute__((format(printf
conditional debug message output
#define WB_IF_DEBUG_LEVEL(L)
Preferred method of implementing conditional debug &#39;if block&#39; code.
Definition: debug_helper.h:249
#define XPM_CREATE_PIXMAP_FROM_DATA(A, B, C, D, E, F)
Platform helper macro to create a pixmap from data.
Compatibility structure for use with MyLoadPixmapFromData() whenever libXpm is not in use...
void PXM_HSVToRGB(int iH, int iS, int iV, int *piR, int *piG, int *piB)
Convert H, S, V values to R, G, B with 0-255 range.
Atom WBGetAtom(Display *pDisplay, const char *szAtomName)
Lookup and/or allocate an internal Atom for a named string (lookups include X11 atoms) ...