X11workbench 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-2018 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 #define DEBUG_DUMP_XPM_ATTRIBUTES(X) DebugDumpXpmAttributes(__FUNCTION__, __LINE__, X)
89 #define DEBUG_DUMP_COLORMAP(X) WBDebugDumpColormap("Called from " __FUNCTION__, X)
90 #endif // NO_DEBUG
91 
92 
93 #define _PI_ 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 /* approximately */
94 
95 
96 #define MINIMUM_ATOM_RESOURCE_LIST_SIZE 256
97 
98 typedef struct __INTERNAL_ATOM_RESOURCE_LIST__
99 {
100  Atom aAtom;
101  char **ppResource;
102 } INTERNAL_ATOM_RESOURCE_LIST;
103 
104 static INTERNAL_ATOM_RESOURCE_LIST *pAtomResourceList = NULL;
105 static int nAtomResourceList = 0, nAtomResourceListMax = 0;
106 
107 static char **ppRegAppLarge_Internal = NULL;
108 static char **ppRegAppSmall_Internal = NULL;
109 
110 XStandardColormap PXM_StandardColormapFromColormap_rval; // storage for static var for PXM_StandardColormapFromColormap()
111 
112 
113 //--------------------
114 // STARTUP AND CLEANUP
115 //--------------------
116 
117 void PXM_OnExit(void)
118 {
119  if(pAtomResourceList)
120  {
121  WBFree(pAtomResourceList);
122  pAtomResourceList = NULL;
123  }
124 
125  nAtomResourceList = 0;
126  nAtomResourceListMax = 0;
127 
128  ppRegAppLarge_Internal = NULL;
129  ppRegAppSmall_Internal = NULL;
130 }
131 
132 
133 //---------------
134 // MATH UTILITIES
135 //---------------
136 
137 unsigned char WB_isqrt(unsigned char iVal)
138 {
139 static const unsigned char aAnswers[256] =
140 {
141  0,1,1,2,2,2,2,3,3,3,3,3,3,4,4,4,
142  4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,6,
143  6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,
144  7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,
145  8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,
146  9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,
147  10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,
148  11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
149  11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,
150  12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,
151  13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
152  13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,
153  14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
154  14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,
155  15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
156  15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
157 };
158 
159 
160  return aAnswers[iVal & 0xff];
161 }
162 
163 unsigned char WB_icos0(unsigned char iVal)
164 {
165 static const unsigned char aAnswers[256] =
166 {
167 255,255,255,255,255,255,255,255,255,255,255,254,254,254,254,254,
168 254,254,253,253,253,253,253,252,252,252,252,252,251,251,251,250,
169 250,250,249,249,249,248,248,248,247,247,247,246,246,245,245,244,
170 244,244,243,243,242,242,241,241,240,240,239,238,238,237,237,236,
171 236,235,234,234,233,232,232,231,231,230,229,228,228,227,226,226,
172 225,224,223,223,222,221,220,220,219,218,217,216,215,215,214,213,
173 212,211,210,209,208,208,207,206,205,204,203,202,201,200,199,198,
174 197,196,195,194,193,192,191,190,189,188,187,186,185,184,183,181,
175 180,179,178,177,176,175,174,172,171,170,169,168,167,165,164,163,
176 162,161,159,158,157,156,154,153,152,151,149,148,147,146,144,143,
177 142,140,139,138,136,135,134,132,131,130,128,127,126,124,123,122,
178 120,119,117,116,115,113,112,110,109,108,106,105,103,102,100,99,
179 98,96,95,93,92,90,89,87,86,84,83,81,80,79,77,76,
180 74,73,71,70,68,67,65,63,62,60,59,57,56,54,53,51,
181 50,48,47,45,44,42,41,39,37,36,34,33,31,30,28,27,
182 25,23,22,20,19,17,16,14,13,11,9,8,6,5,3,2
183 };
184 
185 
186  return aAnswers[iVal & 0xff];
187 }
188 
189 static const char aCosAnswers[0x400] = // 1024 of them
190 {
191  127, 127, 127, 127, 127, 127, 127, 127,
192  127, 127, 127, 127, 127, 127, 127, 126,
193  126, 126, 126, 126, 126, 126, 126, 126,
194  126, 126, 125, 125, 125, 125, 125, 125,
195  125, 124, 124, 124, 124, 124, 124, 123,
196  123, 123, 123, 123, 122, 122, 122, 122,
197  122, 121, 121, 121, 121, 120, 120, 120,
198  120, 119, 119, 119, 118, 118, 118, 118,
199  117, 117, 117, 116, 116, 116, 115, 115,
200  115, 114, 114, 114, 113, 113, 113, 112,
201  112, 112, 111, 111, 111, 110, 110, 109,
202  109, 109, 108, 108, 107, 107, 106, 106,
203  106, 105, 105, 104, 104, 103, 103, 102,
204  102, 102, 101, 101, 100, 100, 99, 99,
205  98, 98, 97, 97, 96, 96, 95, 95,
206  94, 94, 93, 93, 92, 91, 91, 90,
207  90, 89, 89, 88, 88, 87, 86, 86,
208  85, 85, 84, 84, 83, 82, 82, 81,
209  81, 80, 79, 79, 78, 78, 77, 76,
210  76, 75, 74, 74, 73, 72, 72, 71,
211  71, 70, 69, 69, 68, 67, 67, 66,
212  65, 65, 64, 63, 63, 62, 61, 61,
213  60, 59, 58, 58, 57, 56, 56, 55,
214  54, 54, 53, 52, 51, 51, 50, 49,
215  49, 48, 47, 46, 46, 45, 44, 44,
216  43, 42, 41, 41, 40, 39, 38, 38,
217  37, 36, 35, 35, 34, 33, 32, 32,
218  31, 30, 29, 29, 28, 27, 26, 26,
219  25, 24, 23, 22, 22, 21, 20, 19,
220  19, 18, 17, 16, 16, 15, 14, 13,
221  12, 12, 11, 10, 9, 9, 8, 7,
222  6, 5, 5, 4, 3, 2, 2, 1,
223  0, -1, -2, -2, -3, -4, -5, -5,
224  -6, -7, -8, -9, -9, -10, -11, -12,
225  -12, -13, -14, -15, -16, -16, -17, -18,
226  -19, -19, -20, -21, -22, -22, -23, -24,
227  -25, -26, -26, -27, -28, -29, -29, -30,
228  -31, -32, -32, -33, -34, -35, -35, -36,
229  -37, -38, -38, -39, -40, -41, -41, -42,
230  -43, -44, -44, -45, -46, -46, -47, -48,
231  -49, -49, -50, -51, -51, -52, -53, -54,
232  -54, -55, -56, -56, -57, -58, -58, -59,
233  -60, -61, -61, -62, -63, -63, -64, -65,
234  -65, -66, -67, -67, -68, -69, -69, -70,
235  -71, -71, -72, -72, -73, -74, -74, -75,
236  -76, -76, -77, -78, -78, -79, -79, -80,
237  -81, -81, -82, -82, -83, -84, -84, -85,
238  -85, -86, -86, -87, -88, -88, -89, -89,
239  -90, -90, -91, -91, -92, -93, -93, -94,
240  -94, -95, -95, -96, -96, -97, -97, -98,
241  -98, -99, -99, -100, -100, -101, -101, -102,
242  -102, -102, -103, -103, -104, -104, -105, -105,
243  -106, -106, -106, -107, -107, -108, -108, -109,
244  -109, -109, -110, -110, -111, -111, -111, -112,
245  -112, -112, -113, -113, -113, -114, -114, -114,
246  -115, -115, -115, -116, -116, -116, -117, -117,
247  -117, -118, -118, -118, -118, -119, -119, -119,
248  -120, -120, -120, -120, -121, -121, -121, -121,
249  -122, -122, -122, -122, -122, -123, -123, -123,
250  -123, -123, -124, -124, -124, -124, -124, -124,
251  -125, -125, -125, -125, -125, -125, -125, -126,
252  -126, -126, -126, -126, -126, -126, -126, -126,
253  -126, -126, -127, -127, -127, -127, -127, -127,
254  -127, -127, -127, -127, -127, -127, -127, -127,
255  -127, -127, -127, -127, -127, -127, -127, -127,
256  -127, -127, -127, -127, -127, -127, -127, -126,
257  -126, -126, -126, -126, -126, -126, -126, -126,
258  -126, -126, -125, -125, -125, -125, -125, -125,
259  -125, -124, -124, -124, -124, -124, -124, -123,
260  -123, -123, -123, -123, -122, -122, -122, -122,
261  -122, -121, -121, -121, -121, -120, -120, -120,
262  -120, -119, -119, -119, -118, -118, -118, -118,
263  -117, -117, -117, -116, -116, -116, -115, -115,
264  -115, -114, -114, -114, -113, -113, -113, -112,
265  -112, -112, -111, -111, -111, -110, -110, -109,
266  -109, -109, -108, -108, -107, -107, -106, -106,
267  -106, -105, -105, -104, -104, -103, -103, -102,
268  -102, -102, -101, -101, -100, -100, -99, -99,
269  -98, -98, -97, -97, -96, -96, -95, -95,
270  -94, -94, -93, -93, -92, -91, -91, -90,
271  -90, -89, -89, -88, -88, -87, -86, -86,
272  -85, -85, -84, -84, -83, -82, -82, -81,
273  -81, -80, -79, -79, -78, -78, -77, -76,
274  -76, -75, -74, -74, -73, -72, -72, -71,
275  -71, -70, -69, -69, -68, -67, -67, -66,
276  -65, -65, -64, -63, -63, -62, -61, -61,
277  -60, -59, -58, -58, -57, -56, -56, -55,
278  -54, -54, -53, -52, -51, -51, -50, -49,
279  -49, -48, -47, -46, -46, -45, -44, -44,
280  -43, -42, -41, -41, -40, -39, -38, -38,
281  -37, -36, -35, -35, -34, -33, -32, -32,
282  -31, -30, -29, -29, -28, -27, -26, -26,
283  -25, -24, -23, -22, -22, -21, -20, -19,
284  -19, -18, -17, -16, -16, -15, -14, -13,
285  -12, -12, -11, -10, -9, -9, -8, -7,
286  -6, -5, -5, -4, -3, -2, -2, -1,
287  0, 1, 2, 2, 3, 4, 5, 5,
288  6, 7, 8, 9, 9, 10, 11, 12,
289  12, 13, 14, 15, 16, 16, 17, 18,
290  19, 19, 20, 21, 22, 22, 23, 24,
291  25, 26, 26, 27, 28, 29, 29, 30,
292  31, 32, 32, 33, 34, 35, 35, 36,
293  37, 38, 38, 39, 40, 41, 41, 42,
294  43, 44, 44, 45, 46, 46, 47, 48,
295  49, 49, 50, 51, 51, 52, 53, 54,
296  54, 55, 56, 56, 57, 58, 58, 59,
297  60, 61, 61, 62, 63, 63, 64, 65,
298  65, 66, 67, 67, 68, 69, 69, 70,
299  71, 71, 72, 72, 73, 74, 74, 75,
300  76, 76, 77, 78, 78, 79, 79, 80,
301  81, 81, 82, 82, 83, 84, 84, 85,
302  85, 86, 86, 87, 88, 88, 89, 89,
303  90, 90, 91, 91, 92, 93, 93, 94,
304  94, 95, 95, 96, 96, 97, 97, 98,
305  98, 99, 99, 100, 100, 101, 101, 102,
306  102, 102, 103, 103, 104, 104, 105, 105,
307  106, 106, 106, 107, 107, 108, 108, 109,
308  109, 109, 110, 110, 111, 111, 111, 112,
309  112, 112, 113, 113, 113, 114, 114, 114,
310  115, 115, 115, 116, 116, 116, 117, 117,
311  117, 118, 118, 118, 118, 119, 119, 119,
312  120, 120, 120, 120, 121, 121, 121, 121,
313  122, 122, 122, 122, 122, 123, 123, 123,
314  123, 123, 124, 124, 124, 124, 124, 124,
315  125, 125, 125, 125, 125, 125, 125, 126,
316  126, 126, 126, 126, 126, 126, 126, 126,
317  126, 126, 127, 127, 127, 127, 127, 127,
318  127, 127, 127, 127, 127, 127, 127, 127 //,
319 // 127
320 };
321 
322 char WB_icos(int iVal)
323 {
324  return aCosAnswers[iVal & 0x3ff];
325 }
326 
327 unsigned int WB_iatan(int iX, int iY)
328 {
329 
330  return 0; // for now...
331 }
332 
333 
334 
335 
336 
337 //-------------------------
338 // RGB and YUV conversions
339 //-------------------------
340 
341 static int clip255(int iIn)
342 {
343  if(iIn < 0)
344  {
345  return 0;
346  }
347  else if(iIn > 255)
348  {
349  return 255;
350  }
351 
352  return iIn;
353 }
354 
355 void PXM_RGBToYUV(int iR, int iG, int iB, int *piY, int *piU, int *piV)
356 {
357 int iY, iU, iV;
358 
359  iR = clip255(iR);
360  iG = clip255(iG);
361  iB = clip255(iB);
362 
363  iY = clip255((( 66 * iR + 129 * iG + 25 * iB + 128) >> 8) + 16);
364  iU = clip255((( -38 * iR - 74 * iG + 112 * iB + 128) >> 8) + 128);
365  iV = clip255((( 112 * iR - 94 * iG - 18 * iB + 128) >> 8) + 128);
366 
367  if(piY)
368  {
369  *piY = iY;
370  }
371 
372  if(piU)
373  {
374  *piU = iU;
375  }
376 
377  if(piV)
378  {
379  *piV = iV;
380  }
381 }
382 
383 void PXM_YUVToRGB(int iY, int iU, int iV, int *piR, int *piG, int *piB)
384 {
385 int iR, iG, iB;
386 int iC = iY - 16;
387 int iD = iU - 128;
388 int iE = iV - 128;
389 
390  iR = clip255(( 298 * iC + 409 * iE + 128) >> 8);
391  iG = clip255(( 298 * iC - 100 * iD - 208 * iE + 128) >> 8);
392  iB = clip255(( 298 * iC + 516 * iD + 128) >> 8);
393 
394  if(piR)
395  {
396  *piR = iR;
397  }
398 
399  if(piG)
400  {
401  *piG = iG;
402  }
403 
404  if(piB)
405  {
406  *piB = iB;
407  }
408 }
409 
410 void PXM_HSVToRGB(int iH, int iS, int iV, int *piR, int *piG, int *piB)
411 {
412 // this algorithm is similar to what Microsoft uses in their MFC classes, and
413 // what wxWidgets uses in their classes. As such, it's an "open" algorithm,
414 // as the licensing of these two code bases appears to be otherwise incompatible.
415 // The algorithm has been attributed to A. R. Smith . It appears to be "a standard"
416 // (NOTE: I shall research to make sure it's use here is not stomping on ownership)
417 int iR, iG, iB;
418 
419 double dH, dS, dV, dFracH, dR, dG, dB;
420 int iQuadrant;
421 double dUnSat, dLinDn, dLinUp;
422 
423 
424  if(!iS) // a simple optimization for B&W
425  {
426  iR = iG = iB = iV; // RGB is equal to the brightness when no color
427  }
428  else
429  {
430  dH = (6.0 / 256.0) * iH; // convert 0-255 angle to 0-360 angle [for the algorithm] and divide by 60
431  iQuadrant = (int)floor(dH); // quadrant 0 through 5 for 0-360 angle
432  dFracH = dH - iQuadrant; // the fractional part of 'dH'
433 
434  dS = iS / 255.0; // convert 0-255 saturation to 0-1.0 value
435  dV = iV / 255.0; // convert 0-255 'Volume' (brightness, luminocity) to 0-1.0 value
436 
437  dUnSat = dV * (1.0 - dS); // linear delta based on saturation value
438  dLinDn = dV * (1.0 - dS * dFracH); // NOTE: an improved algorithm would use a cos/sin function
439  dLinUp = dV * (1.0 - dS * (1.0 - dFracH)); // NOTE: an improved algorithm would use a cos/sin function
440 
441  // switch/case is typically slower - using 'if' block instead
442  if(iQuadrant < 3) // bottom half
443  {
444  if(iQuadrant == 0)
445  {
446  dR = dV; // red is essentially 'saturated' for +/-60 degrees... (this seems wrong to me)
447  dG = dLinUp; // linear slope increasing
448  dB = dUnSat; // 'un-saturated' value (as dS increases, this goes down, based on dV)
449  }
450  else if(iQuadrant == 1)
451  {
452  dR = dLinDn; // linear slope decreasing
453  dG = dV; // now green is 'saturated'
454  dB = dUnSat; // still 'un-saturated'
455  }
456  else // 2
457  {
458  dR = dUnSat; // now red is 'un-saturated'
459  dG = dV; // green still 'saturated'
460  dB = dLinUp; // blue is 'on the rise' now
461  }
462  }
463  else
464  {
465  if(iQuadrant == 3)
466  {
467  dR = dUnSat; // red is 'un-saturated' still
468  dG = dLinDn; // green is on the way down
469  dB = dV; // now blue is 'saturated'
470  }
471  else if(iQuadrant == 4)
472  {
473  dR = dLinUp; // red is 'on the rise' now
474  dG = dUnSat; // green is 'unsaturated'
475  dB = dV; // blue is 'saturated' again
476  }
477  else // 5
478  {
479  dR = dV; // red is 'saturated' again
480  dG = dUnSat; // green is still 'unsaturated'
481  dB = dLinDn; // blue is 'on the way down'
482  }
483  }
484 
485  iR = clip255((int)floor(256 * dR)); // using 256 rather than 255 gives me some 'rounding up'
486  iG = clip255((int)floor(256 * dG));
487  iB = clip255((int)floor(256 * dB));
488  }
489 
490  if(piR)
491  {
492  *piR = iR;
493  }
494 
495  if(piG)
496  {
497  *piG = iG;
498  }
499 
500  if(piB)
501  {
502  *piB = iB;
503  }
504 }
505 
506 void PXM_RGBToHSV(int iR, int iG, int iB, int *piH, int *piS, int *piV)
507 {
508 // this algorithm is similar to what Microsoft uses in their MFC classes, and
509 // what wxWidgets uses in their classes. As such, it's an "open" algorithm,
510 // as the licensing of these two code bases appears to be otherwise incompatible.
511 // The algorithm has been attributed to A. R. Smith . It appears to be "a standard"
512 // (NOTE: I shall research to make sure it's use here is not stomping on ownership)
513 
514 double dH, dS, dV, dDelta;
515 int iMinRGB, iMaxRGB;
516 
517 
518  iMinRGB = (iR <= iG)
519  ? (iR <= iB)
520  ? iR : iB
521  : (iG <= iB)
522  ? iG : iB;
523 
524  iMaxRGB = (iR >= iG)
525  ? (iR >= iB)
526  ? iR : iB
527  : (iG >= iB)
528  ? iG : iB;
529 
530  if(piV)
531  {
532  *piV = iMaxRGB; // use the max RGB value as my 'volume' (aka brightness, luminocity)
533  }
534 
535  dV = iMaxRGB / 255.0; // convert to value between 0 and 1 for rest of algorithm
536 
537  if(!iMaxRGB) // black
538  {
539  if(piH)
540  {
541  *piH = 0; // the color red
542  }
543  if(piS)
544  {
545  *piS = 0; // zero saturation
546  }
547 
548  return; // I am done here. 'V' is already equal to the RGB values (which must be the same if I get here)
549  }
550 
551  dS = 1.0 * (iMaxRGB - iMinRGB) // the delta
552  / (double)iMaxRGB; // ratio of delta to max = saturation (a value from 0 to 1.0)
553 
554  if(piS) // store it
555  {
556  *piS = clip255((int)floor(256.0 * dS)); // using 256 rather than 255 gives me some 'rounding up'
557  }
558 
559  // calculating 'H'
560 
561  if(!piH) // if not asking for H, bail out now
562  {
563  return;
564  }
565 
566  if(iMaxRGB == iMinRGB)
567  {
568  dH = 0.0; // the color 'red'
569  }
570  else
571  {
572  // NOTE: this infers the quadrants based on which color is maximum
573 
574  dDelta = iMaxRGB - iMinRGB;
575 
576  if(iR == iMaxRGB) // maxed out red?
577  {
578  // quadrants 5 and 0 (note quadrant 5 goes negative)
579  dH = (iG - iB) / dDelta; // calculate diff between yellow and magenta as +/- 1.0
580  }
581  else if(iG == iMaxRGB) // maxed out green?
582  {
583  dH = 2.0 + (iB - iR) / dDelta; // calculate diff between cyan and yellow as +/- 1.0
584  }
585  else // if(iB == iMaxRGB) maxed out blue
586  {
587  dH = 4.0 + (iR - iG) / dDelta; // calculate diff between magenta and cyan as +/- 1.0
588  }
589  }
590 
591  // dH is a value from -1 to 5. If it's less than zero, add 6 to it
592  if(dH < 0.0)
593  {
594  dH += 6.0;
595  }
596 
597  // now dH is a value from 0 to 6, corresponding to values of 0-256.
598 
599  if(dH >= 6.0)
600  {
601  dH = 0.0; // so it converts correctly
602  }
603 
604  *piH = clip255((int)floor((256.0 / 6.0) * dH)); // using 256 rather than 255 gives me some 'rounding up'
605 }
606 
607 
608 static unsigned short internal_get_rgb_from_pixel(long lPixel, int iMult, int iMax)
609 {
610 unsigned long lVal;
611 
612 
613  if(WB_LIKELY(iMult == 65536)) // a typical value for 8-bit colors in the pixel
614  {
615  lVal = lPixel / 65536; // this should compile as a fast bit shift
616  }
617  else if(WB_LIKELY(iMult == 256)) // a typical value for 8-bit colors in the pixel
618  {
619  lVal = lPixel / 256; // this should compile as a fast bit shift
620  }
621  else if(WB_LIKELY(iMult == 1)) // a typical value for 8-bit colors in the pixel
622  {
623  lVal = lPixel;
624  }
625  else // other values are possible, deal with them here
626  {
627  lVal = lPixel / iMult; // an arbitrary multiplier - slower, but functional
628  }
629 
630  if(WB_LIKELY(iMax == 65535 || iMax == 255))
631  {
632  lVal = lVal & iMax;
633 
634  if(WB_LIKELY(iMax == 255))
635  {
636  if(lVal == iMax) // so that white is always ffffH
637  {
638  lVal = 65535;
639  }
640  else
641  {
642  lVal *= 256; // to convert it to 0-65535 value
643  }
644  }
645  }
646  else // unlikely, but possible - slower code but functional
647  {
648  lVal %= (iMax + 1);
649 
650  if(lVal == iMax) // so that white is always ffffH
651  {
652  lVal = 65535;
653  }
654  else
655  {
656 #ifdef HAS_WB_UINT64_BUILTIN
657  lVal = (unsigned long)((WB_UINT64)65536 // do math as 'long long' to avoid overflows on 32-bit
658  * (WB_UINT64)lVal
659  / (WB_UINT64)(iMax + 1));
660 #else // !HAS_WB_UINT64_BUILTIN
661  // NOTE: some values could cause math overflow (but are not likely)
662 
663  lVal = 65536L * lVal
664  / (iMax + 1);
665 #endif // HAS_WB_UINT64_BUILTIN
666  }
667  }
668 
669  return (unsigned short)lVal;
670 }
671 
672 void PXM_PixelToRGB(XStandardColormap *pMap, XColor *pColor)
673 {
674 unsigned long lColor;
675 XStandardColormap map;
676 
677 
678  if(!pColor)
679  {
680  return;
681  }
682 
683  if(!pMap)
684  {
686  pMap = &map;
687 
688 // DEBUG_DUMP_COLORMAP(pMap);
689  }
690 
691  // 'nuking' this one out is a bit difficult. I have to sort the values properly
692 
693  lColor = pColor->pixel - pMap->base_pixel;
694 
695  if(!pMap->red_mult && !pMap->green_mult && !pMap->blue_mult)
696  {
697  return;
698  }
699 
700  pColor->flags = DoRed | DoGreen | DoBlue; // pre-assign this, re-assign as needed
701 
702  if(!pMap->green_mult && !pMap->blue_mult)
703  {
704  // monochrome
705 
706  pColor->red = internal_get_rgb_from_pixel(lColor, pMap->red_mult, pMap->red_max);
707  pColor->green = pColor->blue = pColor->red; // make them the same (by convention for now)
708 
709  pColor->flags = DoRed; // usually indicates 'monochrome' - only use 'red'
710  }
711  else
712  {
713  pColor->red = internal_get_rgb_from_pixel(lColor, pMap->red_mult, pMap->red_max);
714  pColor->green = internal_get_rgb_from_pixel(lColor, pMap->green_mult, pMap->green_max);
715  pColor->blue = internal_get_rgb_from_pixel(lColor, pMap->blue_mult, pMap->blue_max);
716  }
717 }
718 
719 void PXM_RGBToPixel(XStandardColormap *pMap, XColor *pColor)
720 {
721 unsigned long lR, lG, lB;
722 XStandardColormap map;
723 
724 
725  if(!pColor)
726  {
727  return;
728  }
729 
730  if(!pMap)
731  {
733  pMap = &map;
734 
735 // DEBUG_DUMP_COLORMAP(pMap);
736  }
737 
738  // this one is straightforward, right out of the docs for the XStandardColormap structure
739 
740  lR = lG = lB = 0; // pre-assign
741 
742  if(!pColor->flags) // assume all 3 primaries, assign accordingly
743  {
744  pColor->flags = DoRed | DoGreen | DoBlue;
745  }
746 
747  if(pColor->flags & DoRed)
748  {
749  lR = ((unsigned long)(pColor->red) * (unsigned long)(pMap->red_max + 1))
750  / (unsigned long)65536L;
751  }
752 
753 // if(lR < 0)
754 // {
755 // lR = 0;
756 // }
757 // else
758  if(lR > pMap->red_max)
759  {
760  lR = pMap->red_max;
761  }
762 
763  if(pColor->flags & DoGreen)
764  {
765  lG = ((unsigned long)(pColor->green) * (unsigned long)(pMap->green_max + 1))
766  / (unsigned long)65536L;
767  }
768 
769 // if(lG < 0)
770 // {
771 // lG = 0;
772 // }
773 // else
774  if(lG > pMap->green_max)
775  {
776  lG = pMap->green_max;
777  }
778 
779  if(pColor->flags & DoBlue)
780  {
781  lB = (((unsigned long)pColor->blue) * (unsigned long)(pMap->blue_max + 1))
782  / (unsigned long)65536L;
783  }
784 
785 // if(lB < 0)
786 // {
787 // lB = 0;
788 // }
789 // else
790  if(lB > pMap->blue_max)
791  {
792  lB = pMap->blue_max;
793  }
794 
795  pColor->pixel = (pMap->base_pixel
796  + lR * pMap->red_mult
797  + lG * pMap->green_mult
798  + lB * pMap->blue_mult)
799  & 0xffffffffL;
800 
801 // WB_ERROR_PRINT("TEMPORARY: %s - pixel=%lX %d,%d,%d %ld,%ld,%ld %ld,%ld,%ld %ld,%ld,%ld %ld\n",
802 // __FUNCTION__,
803 // pColor->pixel, pColor->red, pColor->green, pColor->blue,
804 // lR, lG, lB, pMap->red_mult, pMap->green_mult, pMap->blue_mult,
805 // pMap->red_max, pMap->green_max, pMap->blue_max, pMap->base_pixel);
806 }
807 
808 
809 void PXM_RegisterAppIcons(char *ppRegAppLarge[], char *ppRegAppSmall[])
810 {
811  ppRegAppLarge_Internal = ppRegAppLarge;
812  ppRegAppSmall_Internal = ppRegAppSmall;
813 }
814 
815 static char **GetPreDefinedIconResource(int idIcon)
816 {
817 char **pData = NULL;
818 
819  switch(idIcon)
820  {
821  case ID_APPLICATION:
822  if(ppRegAppSmall_Internal)
823  {
824  pData = ppRegAppSmall_Internal;
825  }
826  else
827  {
828  pData = icon_ok_xpm; // TODO: make a 19x19 version
829  }
830  break;
831  case ID_ICON_APP:
832  if(ppRegAppLarge_Internal)
833  {
834  pData = ppRegAppLarge_Internal;
835  }
836  else
837  {
838  pData = icon_ok_xpm;
839  }
840  break;
841  case ID_ICON_OK:
842  pData = icon_ok_xpm;
843  break;
844  case ID_ICON_STOP:
845  pData = icon_stop_xpm;
846  break;
847  case ID_ICON_WARN:
848  pData = icon_warn_xpm;
849  break;
850  case ID_ICON_WHAT:
851  pData = icon_what_xpm;
852  break;
853  case ID_ICON_SPLAT:
854  pData = icon_splat_xpm;
855  break;
856  case ID_ICON_BANG:
857  pData = icon_bang_xpm;
858  break;
859  case ID_ICON_TRIANGLE:
860  pData = icon_triangle_xpm;
861  break;
862  case ID_ICON_WHAT_BOLD:
863  pData = icon_what_bold_xpm;
864  break;
865  case ID_ICON_WTF:
866  pData = icon_wtf_xpm;
867  break;
868  case ID_ICON_DEATH:
869  pData = icon_death_xpm;
870  break;
871  case ID_ICON_FINGER:
872  pData = icon_finger_xpm;
873  break;
874  case ID_ICON_SKULL:
875  pData = icon_skull_xpm;
876  break;
877  case ID_ICON_THUMBUP:
878  pData = icon_thumbup_xpm;
879  break;
880  case ID_ICON_THUMBDOWN:
881  pData = icon_thumbdown_xpm;
882  break;
883  case ID_ICON_BEAR:
884  pData = icon_bear_xpm;
885  break;
886  case ID_ICON_BARNEY: // this is a joke. really.
887  pData = icon_barney_xpm;
888  break;
889  }
890 
891  return pData;
892 }
893 
894 static void RegisterIconResource(Atom aIcon, char **ppResource)
895 {
896 int i1;
897 
898  if(!pAtomResourceList)
899  {
900  pAtomResourceList = (INTERNAL_ATOM_RESOURCE_LIST *)
901  WBAlloc(MINIMUM_ATOM_RESOURCE_LIST_SIZE * sizeof(*pAtomResourceList));
902 
903  if(!pAtomResourceList)
904  {
905  WB_ERROR_PRINT("%s - not enough memoory for atom resource list\n", __FUNCTION__);
906  return;
907  }
908 
909  nAtomResourceList = 0;
910  nAtomResourceListMax = MINIMUM_ATOM_RESOURCE_LIST_SIZE;
911  }
912 
913  for(i1=0; i1 < nAtomResourceList; i1++)
914  {
915  if(pAtomResourceList[i1].aAtom == aIcon) // already there?
916  {
917  WB_ERROR_PRINT("%s - matching atom already in the list (ignoring)\n", __FUNCTION__);
918  return; // fow now I just leave. later I might allow editing
919  }
920  }
921 
922  if((nAtomResourceList + 1) >= nAtomResourceListMax)
923  {
924  int iNewSize = MINIMUM_ATOM_RESOURCE_LIST_SIZE / 2 + nAtomResourceListMax;
925 
926  void *pTemp = WBReAlloc(pAtomResourceList, iNewSize);
927  if(!pTemp)
928  {
929  WB_ERROR_PRINT("%s - not enough memoory for atom resource list re-alloc\n", __FUNCTION__);
930  return;
931  }
932 
933  pAtomResourceList = (INTERNAL_ATOM_RESOURCE_LIST *)pTemp;
934  nAtomResourceListMax += MINIMUM_ATOM_RESOURCE_LIST_SIZE / 2;
935  }
936 
937  pAtomResourceList[nAtomResourceList].aAtom = aIcon;
938  pAtomResourceList[nAtomResourceList].ppResource = ppResource;
939  nAtomResourceList++;
940 }
941 
942 static const char * const szPreDefinedIconResources[] =
943 {
944  "ID_APPLICATION",
945  "ID_ICON_OK",
946  "ID_ICON_STOP",
947  "ID_ICON_WARN",
948  "ID_ICON_WHAT",
949  "ID_ICON_QUESTION",
950  "ID_ICON_SPLAT",
951  "ID_ICON_ASTERISK",
952  "ID_ICON_BANG",
953  "ID_ICON_TRIANGLE",
954  "ID_ICON_WHAT_BOLD",
955  "ID_ICON_WTF",
956  "ID_ICON_DEATH",
957  "ID_ICON_FINGER",
958  "ID_ICON_SKULL",
959  "ID_ICON_THUMBUP",
960  "ID_ICON_THUMBDOWN",
961  "ID_ICON_BEAR",
962  "ID_ICON_BARNEY",
963  "ID_ICON_APP"
964 };
965 
966 static char **GetRegisteredIconResource(Atom aIcon)
967 {
968 static int iHasBeenRegistered = 0;
969 int i1, i2;
970 
971  // if the pre-defined atoms have not yet been registered, do it NOW
972 
973  if(!iHasBeenRegistered)
974  {
975  for(i1=ID_ICON_FIRST, i2=0;
976  i1 <= ID_ICON_LAST
977  && i2 < sizeof(szPreDefinedIconResources)/sizeof(szPreDefinedIconResources[0]);
978  i1++, i2++)
979  {
980  Atom aTemp = WBGetAtom(WBGetDefaultDisplay(), szPreDefinedIconResources[i2]);
981 
982  if(aTemp != None)
983  {
984  RegisterIconResource(aTemp, GetPreDefinedIconResource(i1));
985  }
986  }
987 
988  iHasBeenRegistered = 1;
989  }
990 
991  for(i1=0; i1 < nAtomResourceList; i1++)
992  {
993  if(pAtomResourceList[i1].aAtom == aIcon) // already there?
994  {
995  return pAtomResourceList[i1].ppResource;
996  }
997  }
998 
999  return NULL;
1000 }
1001 
1002 
1003 
1004 Pixmap PXM_GetIconPixmap(int idIcon, XPM_ATTRIBUTES *pAttr, Pixmap *pMask)
1005 {
1006 char **pData;
1007 
1008 
1009  pData = GetPreDefinedIconResource(idIcon);
1010 
1011  if(!pData)
1012  {
1013  if(pAttr)
1014  {
1015  bzero(pAttr, sizeof(*pAttr));
1016  }
1017 
1018  if(pMask)
1019  {
1020  *pMask = None;
1021  }
1022 
1023  return None;
1024  }
1025 
1026  return PXM_LoadPixmap(pData, pAttr, pMask);
1027 }
1028 
1029 
1030 Pixmap PXM_GetIconPixmapFromAtom(Atom aIcon, XPM_ATTRIBUTES *pAttr, Pixmap *pMask /* = NULL*/)
1031 {
1032 char **pData;
1033 
1034 
1035  pData = GetRegisteredIconResource(aIcon);
1036 
1037  if(!pData)
1038  {
1039  if(pAttr)
1040  {
1041  bzero(pAttr, sizeof(*pAttr));
1042  }
1043 
1044  if(pMask)
1045  {
1046  *pMask = None;
1047  }
1048 
1049  return None;
1050  }
1051 
1052  return PXM_LoadPixmap(pData, pAttr, pMask);
1053 }
1054 
1055 
1056 Pixmap PXM_LoadPixmap(char *ppXPM[], XPM_ATTRIBUTES *pAttr, Pixmap *pMask /* = NULL*/)
1057 {
1058 Pixmap pixRval = None, pixRval2 = None;
1059 XPM_ATTRIBUTES xattr;
1060 //#ifndef NO_DEBUG
1061 //WB_UINT64 ullTime = WBGetTimeIndex();
1062 //#endif // NO_DEBUG
1063 
1064 
1065  if(!ppXPM)
1066  {
1067  if(pAttr)
1068  {
1069  bzero(pAttr, sizeof(*pAttr));
1070  }
1071 
1072  if(pMask)
1073  {
1074  *pMask = None;
1075  }
1076 
1077  return None;
1078  }
1079 
1080  bzero(&xattr, sizeof(xattr));
1081 
1082 // WB_ERROR_PRINT("TEMPORARY: %s line %d delta tick %lld\n", __FUNCTION__, __LINE__, (WBGetTimeIndex() - ullTime));
1083 
1084 #ifdef X11WORKBENCH_TOOLKIT_HAVE_XPM
1086 #endif // X11WORKBENCH_TOOLKIT_HAVE_XPM
1088  ppXPM, &pixRval, &pixRval2, &xattr);
1089 #ifdef X11WORKBENCH_TOOLKIT_HAVE_XPM
1091 #endif // X11WORKBENCH_TOOLKIT_HAVE_XPM
1092 
1093 // WB_ERROR_PRINT("TEMPORARY: %s line %d delta tick %lld\n", __FUNCTION__, __LINE__, (WBGetTimeIndex() - ullTime));
1094 
1095  if(pAttr)
1096  {
1097  memcpy(pAttr, &xattr, sizeof(xattr));
1098  }
1099  else
1100  {
1101  WB_IF_DEBUG_LEVEL(DebugLevel_Light | DebugSubSystem_Pixmap)
1102  {
1103  DEBUG_DUMP_XPM_ATTRIBUTES(&xattr);
1104  }
1105 
1106  XPM_FREE_ATTRIBUTES(&xattr);
1107  }
1108 
1109  if(pMask)
1110  {
1111  *pMask = pixRval2;
1112  }
1113  else if(pixRval2 != None) // free pixRval2 if it was allocated (it's the 'mask')
1114  {
1116  XFreePixmap(WBGetDefaultDisplay(), pixRval2);
1118  }
1119 
1120  return(pixRval);
1121 }
1122 
1123 Pixmap PXM_ImageToPixmap(Display *pDisplay, Drawable dw, XImage *pImage,
1124  unsigned long clrFGPixel, unsigned long clrBGPixel)
1125 {
1126 Pixmap pxRval;
1127 GC gc;
1128 XGCValues gcv;
1129 int iW, iH;
1130 
1131  if(!pDisplay)
1132  {
1133  pDisplay = WBGetDefaultDisplay();
1134  }
1135 
1136  if(!pImage)
1137  {
1138  WB_ERROR_PRINT("%s - pImage is NULL\n", __FUNCTION__);
1139  return None;
1140  }
1141 
1142  iW = pImage->width;
1143  iH = pImage->height;
1144 
1145  if(!iW || !iH)
1146  {
1147  WB_ERROR_PRINT("%s - Image width/height not valid, iW=%d,iH=%d\n", __FUNCTION__, iW, iH);
1148  return None;
1149  }
1150 
1152  pxRval = XCreatePixmap(pDisplay, dw, iW, iH, DefaultDepth(pDisplay, DefaultScreen(pDisplay)));
1154 
1155  if(pxRval == None)
1156  {
1157  WB_ERROR_PRINT("%s - XCreatePixmap failed\n", __FUNCTION__);
1158  return None;
1159  }
1160 
1161  // I will need to create a GC. Make it a simple one that only specifies FG and BG
1162 
1163  memset(&gcv, 0, sizeof(gcv));
1164  gcv.foreground = clrFGPixel;//BlackPixel(pDisplay, DefaultScreen(pDisplay));
1165  gcv.background = clrBGPixel;//WhitePixel(pDisplay, DefaultScreen(pDisplay));
1166 
1167  // NOTE: for monochrome masks I'd likely use '1' for foreground, '0' for background
1168 
1170  gc = XCreateGC(pDisplay, dw, (GCForeground | GCBackground), &gcv);
1172 
1173  if(gc == None)
1174  {
1175  WB_ERROR_PRINT("%s - XCreateGC failed\n", __FUNCTION__);
1176 
1178  XFreePixmap(pDisplay, pxRval);
1180  return None;
1181  }
1182  else
1183  {
1185  XPutImage(pDisplay, pxRval, gc, pImage, 0, 0, 0, 0, iW, iH); // and now I have a copy of it
1186 
1187  XFreeGC(pDisplay, gc);
1189  }
1190 
1191  return pxRval;
1192 }
1193 
1194 
1195 Pixmap PXM_ImageToPixmap0(Display *pDisplay, Drawable dw, XImage *pImage)
1196 {
1197  if(!pDisplay)
1198  {
1199  pDisplay = WBGetDefaultDisplay();
1200  }
1201 
1202  return PXM_ImageToPixmap(pDisplay, dw, pImage,
1203  BlackPixel(pDisplay, DefaultScreen(pDisplay)),
1204  WhitePixel(pDisplay, DefaultScreen(pDisplay)));
1205 }
1206 
1207 
1208 XImage *PXM_PixmapToImage(Display *pDisplay, Pixmap pxImage)
1209 {
1210 XImage *pRval;
1211 Window winRoot; // not used, still needed?
1212 int iX=0, iY=0;
1213 unsigned int iWidth=0, iHeight=0, iBorder;
1214 unsigned int uiDepth = 0;
1215 
1216 
1217  if(!pDisplay)
1218  {
1219  pDisplay = WBGetDefaultDisplay();
1220  }
1221 
1222  // TODO: special handling for pxImage == None ???
1223 
1224  if(pxImage == None)
1225  {
1226  return NULL;
1227  }
1228 
1230 
1231  // use XGetGeometry to obtain the characteristics of the pixmap. iX and iY SHOULD be zero...
1232  XGetGeometry(pDisplay, pxImage, &winRoot, &iX, &iY, &iWidth, &iHeight, &iBorder, &uiDepth);
1233 
1234  if(!iWidth || !iHeight)
1235  {
1236  pRval = NULL;
1237  }
1238  else
1239  {
1240  // TODO: do I still need iX and iY?
1241  pRval = XGetImage(pDisplay, pxImage, 0, 0, iWidth, iHeight, -1L, ZPixmap);
1242  }
1243 
1245 
1246  return pRval;
1247 }
1248 
1249 void WBSimpleAntiAliasPixmap(Display *pDisplay, const XStandardColormap *pMap, Pixmap pxImage, unsigned long lPixel, WB_GEOM *pGeom)
1250 {
1251 WB_GEOM geom;
1252 XImage *pImage = NULL;
1253 GC gc;
1254 XGCValues gcv;
1255 XStandardColormap map;
1256 
1257 
1258  if(!pDisplay)
1259  {
1260  pDisplay = WBGetDefaultDisplay();
1261  }
1262 
1263  if(pxImage == None)
1264  {
1265  return;
1266  }
1267 
1268  if(!pMap)
1269  {
1270  WBDefaultStandardColormap(pDisplay, &map);
1271  pMap = &map;
1272  }
1273 
1274  if(pGeom)
1275  {
1276  memcpy(&geom, pGeom, sizeof(geom));
1277  }
1278  else
1279  {
1280  Window winRoot; // unused, but I still need it
1281 
1282  int iX=0, iY=0;
1283  unsigned int iWidth=0, iHeight=0, iBorder;
1284  unsigned int uiDepth = 0;
1285 
1286  // use XGetGeometry to obtain the characteristics of the pixmap. iX and iY SHOULD be zero...
1288  XGetGeometry(pDisplay, pxImage, &winRoot, &iX, &iY, &iWidth, &iHeight, &iBorder, &uiDepth);
1290 
1291  geom.x = 0;
1292  geom.y = 0;
1293  geom.width = iWidth;
1294  geom.height = iHeight;
1295  }
1296 
1297  if(!geom.width || !geom.height)
1298  {
1299  return;
1300  }
1301 
1302  // create an XImage, and perform the operation on that
1304  pImage = XGetImage(pDisplay, pxImage, geom.x, geom.y, geom.width, geom.height, 0xffffffff, ZPixmap);
1305  // NOTE: 'ZPixmap' is WAY faster than XYPixmap, but takes up more RAM
1307 
1308  if(!pImage)
1309  {
1310  WB_ERROR_PRINT("ERROR: %s - unable to create image via XGetImage()\n", __FUNCTION__);
1311  return;
1312  }
1313 
1314  WBSimpleAntiAliasImage(pMap, pImage, lPixel, &geom);
1315 
1316  memset(&gcv, 0, sizeof(gcv));
1317  gcv.foreground = lPixel;
1318  gcv.background = lPixel; // for now just do this
1319 
1321  gc = XCreateGC(pDisplay, pxImage, (GCForeground | GCBackground), &gcv);
1323 
1324  if(gc == None)
1325  {
1326  WB_ERROR_PRINT("%s - XCreateGC failed\n", __FUNCTION__);
1327  }
1328  else
1329  {
1331  XPutImage(pDisplay, pxImage, gc, pImage, 0, 0, geom.x, geom.y, geom.width, geom.height);
1332 
1333  XFreeGC(pDisplay, gc);
1335  }
1336 
1337  // I can destroy the image now
1339  XDestroyImage(pImage);
1341 }
1342 
1343 static unsigned long __internal_grey_the_pixel(XStandardColormap *pMap, unsigned long lPixel,
1344  int iR0, int iG0, int iB0) // note 16-bit RGB here
1345 {
1346 XColor clr;
1347 int iR, iG, iB;
1348 
1349  clr.pixel = lPixel;
1350  PXM_PixelToRGB(pMap, &clr);
1351  RGB_FROM_XCOLOR(clr, iR, iG, iB); // 16-bit RGB values
1352 
1353  iR = (3 * iR + iR0 + 1) / 4; // create 'average' colors (this works the best, 3/4 original, 1/4 background)
1354  iG = (3 * iG + iG0 + 1) / 4;
1355  iB = (3 * iB + iB0 + 1) / 4;
1356 
1357  RGB_TO_XCOLOR(iR, iG, iB, clr);
1358  PXM_RGBToPixel(pMap, &clr);
1359 
1360  return clr.pixel; // yeah that was a lot of stuff to do
1361 }
1362 
1363 void WBSimpleAntiAliasImage(const XStandardColormap *pMap, XImage *pImage, unsigned long lPixel, WB_GEOM *pGeom)
1364 {
1365 WB_GEOM geom;
1366 XStandardColormap map;
1367 int nX, nY, iR, iG, iB;
1368 XColor clr;
1369 
1370 
1371  // TODO: do I want to operate directly on the memory? for now, use the 'XGetPixel' and 'XPutPixel' utilities
1372 
1373  if(!pImage)
1374  {
1375  return;
1376  }
1377 
1378  if(!pMap)
1379  {
1381  }
1382  else
1383  {
1384  memcpy(&map, pMap, sizeof(map));
1385  }
1386 
1387  if(pGeom)
1388  {
1389  memcpy(&geom, pGeom, sizeof(geom));
1390  }
1391  else
1392  {
1393  geom.x = 0;
1394  geom.y = 0;
1395  geom.width = pImage->width;
1396  geom.height = pImage->height;
1397  }
1398 
1399  clr.pixel = lPixel;
1400  PXM_PixelToRGB(&map, &clr);
1401  RGB_FROM_XCOLOR(clr, iR, iG, iB);
1402 
1403  for(nX = geom.x; nX < (geom.x + geom.width - 1); nX++)
1404  {
1405  for(nY = geom.y; nY < (geom.y + geom.height - 1); nY++)
1406  {
1407  // detect the 'inside pixel' or 'outside pixel' on a corner
1408  // the idea is to look for one of these and put 'greyed'
1409  // pixels in between
1410  //
1411  // X. Xo .X oX
1412  // .X becomes oX and X. becomes Xo
1413  //
1414  // where 'o' represents a color between . and X
1415  //
1416 
1417  unsigned long lPixel1 = XGetPixel(pImage, nX, nY);
1418  unsigned long lPixel2 = XGetPixel(pImage, nX + 1, nY);
1419  unsigned long lPixel3 = XGetPixel(pImage, nX, nY + 1);
1420  unsigned long lPixel4 = XGetPixel(pImage, nX + 1, nY + 1);
1421 
1422  if(lPixel1 == lPixel && lPixel4 == lPixel)
1423  {
1424  if(lPixel2 != lPixel) // grey it
1425  {
1426  lPixel2 = __internal_grey_the_pixel(&map, lPixel2, iR, iG, iB);
1427  if(lPixel2 != lPixel) // make sure it's not because if it is, it's a problem
1428  {
1429  XPutPixel(pImage, nX + 1, nY, lPixel2);
1430  }
1431  }
1432 
1433  if(lPixel3 != lPixel) // grey it
1434  {
1435  lPixel3 = __internal_grey_the_pixel(&map, lPixel3, iR, iG, iB);
1436  if(lPixel3 != lPixel) // make sure it's not because if it is, it's a problem
1437  {
1438  XPutPixel(pImage, nX, nY + 1, lPixel3);
1439  }
1440  }
1441  }
1442 
1443  if(lPixel2 == lPixel && lPixel3 == lPixel)
1444  {
1445  if(lPixel1 != lPixel) // grey it
1446  {
1447  lPixel1 = __internal_grey_the_pixel(&map, lPixel1, iR, iG, iB);
1448  if(lPixel1 != lPixel) // make sure it's not because if it is, it's a problem
1449  {
1450  XPutPixel(pImage, nX, nY, lPixel1);
1451  }
1452  }
1453 
1454  if(lPixel4 != lPixel) // grey it
1455  {
1456  lPixel4 = __internal_grey_the_pixel(&map, lPixel4, iR, iG, iB);
1457  if(lPixel4 != lPixel) // make sure it's not because if it is, it's a problem
1458  {
1459  XPutPixel(pImage, nX + 1, nY + 1, lPixel4);
1460  }
1461  }
1462  }
1463 
1464  }
1465  }
1466 
1467 }
1468 
1469 
1470 
1471 #ifndef NO_DEBUG
1472 static void DebugDumpXpmAttributes(const char *szFunction, int nLine, XPM_ATTRIBUTES *pAttr)
1473 {
1474  WBDebugPrint("%s line %d XPM_ATTRIBUTES contain:\n", szFunction, nLine);
1475 #if defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1476  WBDebugPrint(" valuemask: %ld\n", pAttr->valuemask);
1477  WBDebugPrint(" visual: %p\n", pAttr->visual);
1478  WBDebugPrint(" colormap: %p\n", (void *)pAttr->colormap);
1479 #endif // defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1480 
1481  WBDebugPrint(" depth: %u\n", pAttr->depth);
1482  WBDebugPrint(" width: %u\n", pAttr->width);
1483  WBDebugPrint(" height: %u\n", pAttr->height);
1484 
1485 // if I'm using libXpm then I have some additional data members...
1486 #if defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1487  WBDebugPrint(" x_hotspot: %u\n", pAttr->x_hotspot);
1488  WBDebugPrint(" y_hotspot: %u\n", pAttr->y_hotspot);
1489  WBDebugPrint(" cpp: %u\n", pAttr->cpp);
1490  WBDebugPrint(" pixels: %p\n", pAttr->pixels);
1491  WBDebugPrint(" npixels: %u\n", pAttr->npixels);
1492  WBDebugPrint(" colorsymbols: %p\n", pAttr->colorsymbols);
1493  WBDebugPrint(" numsymbols: %u\n", pAttr->numsymbols);
1494  WBDebugPrint(" rgb_fname: %s\n", pAttr->rgb_fname);
1495  WBDebugPrint(" nextensions: %u\n", pAttr->nextensions);
1496  WBDebugPrint(" extensions: %p\n", pAttr->extensions);
1497  WBDebugPrint(" ncolors: %u\n", pAttr->ncolors);
1498  WBDebugPrint(" colorTable: %p\n", pAttr->colorTable);
1499  WBDebugPrint(" mask_pixel: %u\n", pAttr->mask_pixel);
1500  WBDebugPrint(" exactColors: %c\n", pAttr->exactColors ? 'T' : 'F');
1501  WBDebugPrint(" closeness: %u\n", pAttr->closeness);
1502  WBDebugPrint(" red_closeness: %u\n", pAttr->red_closeness);
1503  WBDebugPrint(" green_closeness: %u\n", pAttr->green_closeness);
1504  WBDebugPrint(" blue_closeness: %u\n", pAttr->blue_closeness);
1505  WBDebugPrint(" color_key: %d\n", pAttr->color_key);
1506  WBDebugPrint(" alloc_pixels: %p\n", pAttr->alloc_pixels);
1507  WBDebugPrint(" nalloc_pixels: %d\n", pAttr->nalloc_pixels);
1508  WBDebugPrint(" alloc_close_colors: %c\n", pAttr->alloc_close_colors ? 'T' : 'F');
1509  WBDebugPrint(" bitmap_format: %d\n", pAttr->bitmap_format);
1510  WBDebugPrint(" alloc_color: %p\n", pAttr->alloc_color);
1511  WBDebugPrint(" free_colors: %p\n", pAttr->free_colors);
1512  WBDebugPrint(" color_closure: %p\n", pAttr->color_closure);
1513 #endif // defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1514 }
1515 #endif // !NO_DEBUG
1516 
1517 
1518 void WBDebugDumpColormap(const char *szTitle, const XStandardColormap *pMap)
1519 {
1520 #ifndef NO_DEBUG
1521  WBDebugPrint("WBDebugDumpColormap - %s\n", szTitle);
1522  WBDebugPrint(" XStandardColormap: %p\n", pMap);
1523  if(pMap)
1524  {
1525  WBDebugPrint(" colormap = %lld\n", (WB_UINT64)pMap->colormap);
1526  WBDebugPrint(" red_max = %ld\n", pMap->red_max);
1527  WBDebugPrint(" red_mult = %ld\n", pMap->red_mult);
1528  WBDebugPrint(" green_max = %ld\n", pMap->green_max);
1529  WBDebugPrint(" green_mult = %ld\n", pMap->green_mult);
1530  WBDebugPrint(" blue_max = %ld\n", pMap->blue_max);
1531  WBDebugPrint(" blue_mult = %ld\n", pMap->blue_mult);
1532  WBDebugPrint(" base_pixel = %ld (%08lxH)\n", pMap->base_pixel, pMap->base_pixel);
1533  }
1534 #endif // !NO_DEBUG
1535 }
1536 
1537 
1538 void WBDebugDumpXColor(const char *szTitle, const XColor *pColor)
1539 {
1540 #ifndef NO_DEBUG
1541 char tbuf[32];
1542 
1543  WBDebugPrint("DebugDumpXColor - %s\n", szTitle);
1544  WBDebugPrint(" XColor: %p\n", pColor);
1545  if(pColor)
1546  {
1547  WBDebugPrint(" pixel = %lu \"#%6.6lX\"\n", pColor->pixel, pColor->pixel);
1548  WBDebugPrint(" red = %d\n", pColor->red);
1549  WBDebugPrint(" green = %d\n", pColor->green);
1550  WBDebugPrint(" blue = %d\n", pColor->blue);
1551 
1552  tbuf[0] = 0;
1553  if(pColor->flags & DoRed)
1554  {
1555 // if(tbuf[0])
1556 // {
1557 // strcat(tbuf, " | ");
1558 // }
1559 
1560  strcat(tbuf, "DoRed");
1561  }
1562 
1563  if(pColor->flags & DoGreen)
1564  {
1565  if(tbuf[0])
1566  {
1567  strcat(tbuf, " | ");
1568  }
1569 
1570  strcat(tbuf, "DoGreen");
1571  }
1572 
1573  if(pColor->flags & DoBlue)
1574  {
1575  if(tbuf[0])
1576  {
1577  strcat(tbuf, " | ");
1578  }
1579 
1580  strcat(tbuf, "DoBlue");
1581  }
1582 
1583  if(tbuf[0])
1584  {
1585  WBDebugPrint(" flags = %d %s\n", pColor->flags, tbuf);
1586  }
1587  else
1588  {
1589  WBDebugPrint(" flags = %d (%XH)\n", pColor->flags, pColor->flags);
1590  }
1591  }
1592 #endif // !NO_DEBUG
1593 }
1594 
1595 
#define WB_LIKELY(x)
optimization for code branching when condition is &#39;likely&#39;. use within conditionals ...
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 ...
unsigned char WB_isqrt(unsigned char iVal)
integer square root of a value 0-255
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.
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 WBDebugDumpColormap(const char *szTitle, const XStandardColormap *pMap)
Dump XStandardColormap members for debugging.
unsigned char WB_icos0(unsigned char iVal)
integer 255 * cos(iVal * pi / 512) calculation via lookup table (legacy, to be removed?)
void * WBAlloc(int nSize)
High performance memory sub-allocator &#39;allocate&#39;.
unsigned int width
#define END_XCALL_DEBUG_WRAPPER
wrapper macro for calls into the X11 library. This macro follows the call(s)
void WBDebugDumpXColor(const char *szTitle, const XColor *pColor)
Dump XColor members for debugging.
unsigned long long WB_UINT64
Platform abstract unsigned 64-bit integer.
unsigned int height
#define WB_ERROR_PRINT(...)
Preferred method of implementing an &#39;error level&#39; debug message for all subsystems.
Definition: debug_helper.h:356
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)
Atom WBGetAtom(Display *pDisplay, const char *szAtomName)
Lookup and/or allocate an internal Atom for a named string (lookups include X11 atoms) ...
void WBSimpleAntiAliasImage(const XStandardColormap *pMap, XImage *pImage, unsigned long lPixel, WB_GEOM *pGeom)
Simple anti-alias of an XImage using foreground pixel color.
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.
char WB_icos(int iVal)
integer 127 * cos(iVal * pi / 512) calculation via lookup table
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 RGB_FROM_XCOLOR(X, R, G, B)
Simple RGB assignment from pixel, 0-65535 RGB.
#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:339
#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.
internal wrapper struct for X11 &#39;geometry&#39; definition
void WBSimpleAntiAliasPixmap(Display *pDisplay, const XStandardColormap *pMap, Pixmap pxImage, unsigned long lPixel, WB_GEOM *pGeom)
Simple anti-alias of a Pixmap using foreground pixel color.
#define RGB_TO_XCOLOR(R, G, B, X)
Simple RGB assignment to pixel, 0-65535 RGB.