not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / ksplash / ksplashx / qcolor_x11.cpp
blobb743bdef9ce635a655b0676d7c32fa70aaa349bb
1 /****************************************************************************
2 **
3 ** This file is based on sources of the Qt GUI Toolkit, used under the terms
4 ** of the GNU General Public License version 2 (see the original copyright
5 ** notice below).
6 ** All further contributions to this file are (and are required to be)
7 ** licensed 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.
11 ** The original Qt license header follows:
12 **
14 ** Implementation of QColor class for X11
16 ** Created : 940112
18 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
20 ** This file is part of the kernel module of the Qt GUI Toolkit.
22 ** This file may be distributed under the terms of the Q Public License
23 ** as defined by Trolltech AS of Norway and appearing in the file
24 ** LICENSE.QPL included in the packaging of this file.
26 ** This file may be distributed and/or modified under the terms of the
27 ** GNU General Public License version 2 as published by the Free Software
28 ** Foundation and appearing in the file LICENSE.GPL included in the
29 ** packaging of this file.
31 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
32 ** licenses for Unix/X11 may use this file in accordance with the Qt Commercial
33 ** License Agreement provided with the Software.
35 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
36 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
38 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
39 ** information about Qt Commercial License Agreements.
40 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
41 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
43 ** Contact info@trolltech.com if any conditions of this licensing are
44 ** not clear to you.
46 **********************************************************************/
48 #include "qcolor.h"
49 #include "qcolor_p.h"
50 //#include "string.h"
51 //#include "qpaintdevice.h"
52 //#include "qapplication.h"
53 //#include "qapplication_p.h"
54 //#include "qt_x11_p.h"
55 #include "x11_defs.h"
56 #include "string.h"
58 int qt_ncols_option = 216; // used in qcolor_x11.cpp
60 // NOT REVISED
62 /*****************************************************************************
63 The color dictionary speeds up color allocation significantly for X11.
64 When there are no more colors, QColor::alloc() will set the colors_avail
65 flag to FALSE and try to find the nearest color.
66 NOTE: From deep within the event loop, the colors_avail flag is reset to
67 TRUE (calls the function qt_reset_color_avail()), because some other
68 application might free its colors, thereby making them available for
69 this Qt application.
70 *****************************************************************************/
72 //#include "qintdict.h"
74 struct QColorData {
75 uint pix; // allocated pixel value
76 int context; // allocation context
79 #if 0
80 typedef QIntDict<QColorData> QColorDict;
81 typedef QIntDictIterator<QColorData> QColorDictIt;
82 #endif
83 static int current_alloc_context = 0; // current color alloc context
84 static const uint col_std_dict = 419;
85 static const uint col_large_dict = 18397;
87 class QColorScreenData {
88 public:
89 QColorScreenData()
91 //# colorDict = 0;
92 colors_avail = true;
93 g_vis = 0;
94 g_carr = 0;
95 g_carr_fetch = true;
96 g_cells = 0;
97 g_our_alloc = 0;
98 color_reduce = false;
101 //# QColorDict *colorDict; // dict of allocated colors
102 bool colors_avail; // X colors available
103 bool g_truecolor; // truecolor visual
104 Visual *g_vis; // visual
105 XColor *g_carr; // color array
106 bool g_carr_fetch; // perform XQueryColors?
107 int g_cells; // number of entries in g_carr
108 bool *g_our_alloc; // our allocated colors
109 uint red_mask , green_mask , blue_mask;
110 int red_shift, green_shift, blue_shift;
111 bool color_reduce;
112 int col_div_r;
113 int col_div_g;
114 int col_div_b;
117 static int screencount = 0;
118 static QColorScreenData **screendata = 0; // array of screendata pointers
122 This function is called from the event loop. It resets the colors_avail
123 flag so that the application can retry to allocate read-only colors
124 that other applications may have deallocated lately.
126 The g_our_alloc and g_carr are global arrays that optimize color
127 approximation when there are no more colors left to allocate.
130 void qt_reset_color_avail()
132 int i;
133 for ( i = 0; i < screencount; i++ ) {
134 screendata[i]->colors_avail = true;
135 screendata[i]->g_carr_fetch = true; // do XQueryColors if !colors_avail
141 Finds the nearest color.
144 static int find_nearest_color( int r, int g, int b, int* mindist_out,
145 QColorScreenData *sd )
147 int mincol = -1;
148 int mindist = 200000;
149 int rx, gx, bx, dist;
150 XColor *xc = &sd->g_carr[0];
151 for ( int i=0; i<sd->g_cells; i++ ) {
152 rx = r - (xc->red >> 8);
153 gx = g - (xc->green >> 8);
154 bx = b - (xc->blue>> 8);
155 dist = rx*rx + gx*gx + bx*bx; // calculate distance
156 if ( dist < mindist ) { // minimal?
157 mindist = dist;
158 mincol = i;
160 xc++;
162 *mindist_out = mindist;
163 return mincol;
167 /*****************************************************************************
168 QColor misc internal functions
169 *****************************************************************************/
171 static int highest_bit( uint v )
173 int i;
174 uint b = (uint)1 << 31; // get pos of highest bit in v
175 for ( i=31; ((b & v) == 0) && i>=0; i-- )
176 b >>= 1;
177 return i;
181 /*****************************************************************************
182 QColor static member functions
183 *****************************************************************************/
186 Returns the maximum number of colors supported by the underlying
187 window system if the window system uses a palette.
189 Otherwise returns -1. Use numBitPlanes() to calculate the available
190 colors in that case.
193 int QColor::maxColors()
195 Visual *visual = (Visual *) QPaintDevice::x11AppVisual();
196 if (visual->c_class & 1)
197 return QPaintDevice::x11AppCells();
198 return -1;
202 Returns the number of color bit planes for the underlying window
203 system.
205 The returned value is equal to the default pixmap depth.
207 \sa QPixmap::defaultDepth()
210 int QColor::numBitPlanes()
212 return QPaintDevice::x11AppDepth();
217 Internal initialization required for QColor.
218 This function is called from the QApplication constructor.
220 \sa cleanup()
223 void QColor::initialize()
225 static const int blackIdx = 2;
226 static const int whiteIdx = 3;
228 if ( color_init ) // already initialized
229 return;
230 color_init = true;
232 Display *dpy = QPaintDevice::x11AppDisplay();
233 int spec = QApplication::colorSpec();
235 screencount = ScreenCount( dpy );
236 screendata = new QColorScreenData*[ screencount ];
238 int scr = QPaintDevice::x11AppScreen();
240 for ( scr = 0; scr < screencount; ++scr ) {
241 screendata[scr] = new QColorScreenData;
242 screendata[scr]->g_vis = (Visual *) QPaintDevice::x11AppVisual( scr );
243 screendata[scr]->g_truecolor = screendata[scr]->g_vis->c_class == TrueColor;
245 int ncols= QPaintDevice::x11AppCells( scr );
247 if ( screendata[scr]->g_truecolor ) {
248 colormodel = d32;
249 } else {
250 colormodel = d8;
251 // Create the g_our_alloc array, which remembers which color pixels
252 // we allocated.
253 screendata[scr]->g_cells = qMin(ncols,256);
254 screendata[scr]->g_carr = new XColor[screendata[scr]->g_cells];
255 Q_CHECK_PTR( screendata[scr]->g_carr );
256 memset( screendata[scr]->g_carr, 0,
257 screendata[scr]->g_cells*sizeof(XColor) );
258 screendata[scr]->g_carr_fetch = true; // run XQueryColors on demand
259 screendata[scr]->g_our_alloc = new bool[screendata[scr]->g_cells];
260 Q_CHECK_PTR( screendata[scr]->g_our_alloc );
261 memset( screendata[scr]->g_our_alloc, false,
262 screendata[scr]->g_cells*sizeof(bool) );
263 XColor *xc = &screendata[scr]->g_carr[0];
264 for ( int i=0; i<screendata[scr]->g_cells; i++ ) {
265 xc->pixel = i; // g_carr[i] = color i
266 xc++;
270 int dictsize;
271 if ( screendata[scr]->g_truecolor ) { // truecolor
272 dictsize = 1; // will not need color dict
273 screendata[scr]->red_mask = (uint)screendata[scr]->g_vis->red_mask;
274 screendata[scr]->green_mask = (uint)screendata[scr]->g_vis->green_mask;
275 screendata[scr]->blue_mask = (uint)screendata[scr]->g_vis->blue_mask;
276 screendata[scr]->red_shift =
277 highest_bit( screendata[scr]->red_mask ) - 7;
278 screendata[scr]->green_shift =
279 highest_bit( screendata[scr]->green_mask ) - 7;
280 screendata[scr]->blue_shift =
281 highest_bit( screendata[scr]->blue_mask ) - 7;
282 } else {
283 dictsize = col_std_dict;
285 #if 0
286 screendata[scr]->colorDict = new QColorDict(dictsize); // create dictionary
287 Q_CHECK_PTR( screendata[scr]->colorDict );
288 #endif
290 if ( spec == (int)QApplication::ManyColor ) {
291 screendata[scr]->color_reduce = true;
293 switch ( qt_ncols_option ) {
294 case 216:
295 // 6:6:6
296 screendata[scr]->col_div_r = screendata[scr]->col_div_g =
297 screendata[scr]->col_div_b = (255/(6-1));
298 break;
299 default: {
300 // 2:3:1 proportions, solved numerically
301 if ( qt_ncols_option > 255 ) qt_ncols_option = 255;
302 if ( qt_ncols_option < 1 ) qt_ncols_option = 1;
303 int nr = 2;
304 int ng = 2;
305 int nb = 2;
306 for (;;) {
307 if ( nb*2 < nr && (nb+1)*nr*ng < qt_ncols_option )
308 nb++;
309 else if ( nr*3 < ng*2 && nb*(nr+1)*ng < qt_ncols_option )
310 nr++;
311 else if ( nb*nr*(ng+1) < qt_ncols_option )
312 ng++;
313 else break;
315 qt_ncols_option = nr*ng*nb;
316 screendata[scr]->col_div_r = (255/(nr-1));
317 screendata[scr]->col_div_g = (255/(ng-1));
318 screendata[scr]->col_div_b = (255/(nb-1));
324 scr = QPaintDevice::x11AppScreen();
326 // Initialize global color objects
327 if ( QPaintDevice::x11AppDefaultVisual(scr) &&
328 QPaintDevice::x11AppDefaultColormap(scr) ) {
329 globalColors()[blackIdx].setPixel((uint) BlackPixel(dpy, scr));
330 globalColors()[whiteIdx].setPixel((uint) WhitePixel(dpy, scr));
331 } else {
332 globalColors()[blackIdx].alloc(scr);
333 globalColors()[whiteIdx].alloc(scr);
336 #if 0 /* 0 == allocate colors on demand */
337 setLazyAlloc( false ); // allocate global colors
338 ((QColor*)(&darkGray))-> alloc();
339 ((QColor*)(&gray))-> alloc();
340 ((QColor*)(&lightGray))-> alloc();
341 ((QColor*)(&::red))-> alloc();
342 ((QColor*)(&::green))-> alloc();
343 ((QColor*)(&::blue))-> alloc();
344 ((QColor*)(&cyan))-> alloc();
345 ((QColor*)(&magenta))-> alloc();
346 ((QColor*)(&yellow))-> alloc();
347 ((QColor*)(&darkRed))-> alloc();
348 ((QColor*)(&darkGreen))-> alloc();
349 ((QColor*)(&darkBlue))-> alloc();
350 ((QColor*)(&darkCyan))-> alloc();
351 ((QColor*)(&darkMagenta))-> alloc();
352 ((QColor*)(&darkYellow))-> alloc();
353 setLazyAlloc( true );
354 #endif
358 Internal clean up required for QColor.
359 This function is called from the QApplication destructor.
361 \sa initialize()
364 void QColor::cleanup()
366 if ( !color_init )
367 return;
368 color_init = false;
369 int scr;
370 for ( scr = 0; scr < screencount; scr++ ) {
371 if ( screendata[scr]->g_carr ) {
372 delete [] screendata[scr]->g_carr;
373 screendata[scr]->g_carr = 0;
375 if ( screendata[scr]->g_our_alloc ) {
376 delete [] screendata[scr]->g_our_alloc;
377 screendata[scr]->g_our_alloc = 0;
379 #if 0
380 if ( screendata[scr]->colorDict ) {
381 screendata[scr]->colorDict->setAutoDelete( true );
382 screendata[scr]->colorDict->clear();
383 delete screendata[scr]->colorDict;
384 screendata[scr]->colorDict = 0;
386 #endif
387 delete screendata[scr];
388 screendata[scr] = 0;
390 delete [] screendata;
391 screendata = 0;
392 screencount = 0;
396 /*****************************************************************************
397 QColor member functions
398 *****************************************************************************/
401 \internal
402 Allocates the color on screen \a screen. Only used in X11.
404 \sa alloc(), pixel()
406 uint QColor::alloc( int screen )
408 Display *dpy = QPaintDevice::x11AppDisplay();
409 if ( screen < 0 )
410 screen = QPaintDevice::x11AppScreen();
411 if ( !color_init )
412 return dpy ? (uint)BlackPixel(dpy, screen) : 0;
413 int r = qRed(d.argb);
414 int g = qGreen(d.argb);
415 int b = qBlue(d.argb);
416 uint pix = 0;
417 QColorScreenData *sd = screendata[screen];
418 if ( sd->g_truecolor ) { // truecolor: map to pixel
419 r = sd->red_shift > 0 ? r << sd->red_shift : r >> -sd->red_shift;
420 g = sd->green_shift > 0 ? g << sd->green_shift : g >> -sd->green_shift;
421 b = sd->blue_shift > 0 ? b << sd->blue_shift : b >> -sd->blue_shift;
422 pix = (b & sd->blue_mask) | (g & sd->green_mask) | (r & sd->red_mask)
423 | ~(sd->blue_mask | sd->green_mask | sd->red_mask);
424 if ( screen == QPaintDevice::x11AppScreen() )
425 d.d32.pix = pix;
426 return pix;
428 #if 0
429 QColorData *c = sd->colorDict->find( (long)(d.argb) );
430 if ( c ) { // found color in dictionary
431 pix = c->pix;
432 if ( screen == QPaintDevice::x11AppScreen() ) {
433 d.d8.invalid = false; // color ok
434 d.d8.dirty = false;
435 d.d8.pix = pix; // use same pixel value
436 if ( c->context != current_alloc_context ) {
437 c->context = 0; // convert to default context
438 sd->g_our_alloc[pix] = true; // reuse without XAllocColor
441 return pix;
443 #endif
445 XColor col;
446 col.red = r << 8;
447 col.green = g << 8;
448 col.blue = b << 8;
450 bool try_again = false;
451 bool try_alloc = !sd->color_reduce;
452 int try_count = 0;
454 do {
455 // This loop is run until we manage to either allocate or
456 // find an approximate color, it stops after a few iterations.
458 try_again = false;
460 if ( try_alloc && sd->colors_avail &&
461 XAllocColor(dpy, QPaintDevice::x11AppColormap( screen ),&col) ) {
462 // We could allocate the color
463 pix = (uint) col.pixel;
464 if ( screen == QPaintDevice::x11AppScreen() ) {
465 d.d8.pix = pix;
466 d.d8.invalid = false;
467 d.d8.dirty = false;
468 sd->g_carr[d.d8.pix] = col; // update color array
469 if ( current_alloc_context == 0 )
470 sd->g_our_alloc[d.d8.pix] = true; // reuse without XAllocColor
472 } else {
473 // No available colors, or we did not want to allocate one
474 int i;
475 sd->colors_avail = false; // no more available colors
476 if ( sd->g_carr_fetch ) { // refetch color array
477 sd->g_carr_fetch = false;
478 XQueryColors( dpy, QPaintDevice::x11AppColormap( screen ), sd->g_carr,
479 sd->g_cells );
481 int mindist;
482 i = find_nearest_color( r, g, b, &mindist, sd );
484 if ( mindist != 0 && !try_alloc ) {
485 // Not an exact match with an existing color
486 int rr = ((r+sd->col_div_r/2)/sd->col_div_r)*sd->col_div_r;
487 int rg = ((g+sd->col_div_g/2)/sd->col_div_g)*sd->col_div_g;
488 int rb = ((b+sd->col_div_b/2)/sd->col_div_b)*sd->col_div_b;
489 int rx = rr - r;
490 int gx = rg - g;
491 int bx = rb - b;
492 int dist = rx*rx + gx*gx + bx*bx; // calculate distance
493 if ( dist < mindist ) {
494 // reduced color is closer - try to alloc it
495 r = rr;
496 g = rg;
497 b = rb;
498 col.red = r << 8;
499 col.green = g << 8;
500 col.blue = b << 8;
501 try_alloc = true;
502 try_again = true;
503 sd->colors_avail = true;
504 continue; // Try alloc reduced color
508 if ( i == -1 ) { // no nearest color?!
509 int unused, value;
510 hsv(&unused, &unused, &value);
511 if (value < 128) { // dark, use black
512 d.argb = qRgb(0,0,0);
513 pix = (uint)BlackPixel( dpy, screen );
514 if ( screen == QPaintDevice::x11AppScreen() ) {
515 d.d8.invalid = false;
516 d.d8.dirty = false;
517 d.d8.pix = pix;
519 } else { // light, use white
520 d.argb = qRgb(0xff,0xff,0xff);
521 pix = (uint)WhitePixel( dpy, screen );
522 if ( screen == QPaintDevice::x11AppScreen() ) {
523 d.d8.invalid = false;
524 d.d8.dirty = false;
525 d.d8.pix = pix;
528 return pix;
530 if ( sd->g_our_alloc[i] ) { // we've already allocated it
531 ; // i == g_carr[i].pixel
532 } else {
533 // Try to allocate existing color
534 col = sd->g_carr[i];
535 if ( XAllocColor(dpy, QPaintDevice::x11AppColormap( screen ), &col) ) {
536 i = (uint)col.pixel;
537 sd->g_carr[i] = col; // update color array
538 if ( screen == QPaintDevice::x11AppScreen() ) {
539 if ( current_alloc_context == 0 )
540 sd->g_our_alloc[i] = true; // only in the default context
542 } else {
543 // Oops, it's gone again
544 try_count++;
545 try_again = true;
546 sd->colors_avail = true;
547 sd->g_carr_fetch = true;
550 if ( !try_again ) { // got it
551 pix = (uint)sd->g_carr[i].pixel;
552 if ( screen == QPaintDevice::x11AppScreen() ) {
553 d.d8.invalid = false;
554 d.d8.dirty = false;
555 d.d8.pix = pix; // allocated X11 color
560 } while ( try_again && try_count < 2 );
562 if ( try_again ) { // no hope of allocating color
563 int unused, value;
564 hsv(&unused, &unused, &value);
565 if (value < 128) { // dark, use black
566 d.argb = qRgb(0,0,0);
567 pix = (uint)BlackPixel( dpy, screen );
568 if ( screen == QPaintDevice::x11AppScreen() ) {
569 d.d8.invalid = false;
570 d.d8.dirty = false;
571 d.d8.pix = pix;
573 } else { // light, use white
574 d.argb = qRgb(0xff,0xff,0xff);
575 pix = (uint)WhitePixel( dpy, screen );
576 if ( screen == QPaintDevice::x11AppScreen() ) {
577 d.d8.invalid = false;
578 d.d8.dirty = false;
579 d.d8.pix = pix;
582 return pix;
584 #if 0
585 // All colors outside context 0 must go into the dictionary
586 bool many = sd->colorDict->count() >= sd->colorDict->size() * 8;
587 if ( many && sd->colorDict->size() == col_std_dict ) {
588 sd->colorDict->resize( col_large_dict );
590 if ( !many || current_alloc_context != 0 ) {
591 c = new QColorData; // insert into color dict
592 Q_CHECK_PTR( c );
593 c->pix = pix;
594 c->context = current_alloc_context;
595 sd->colorDict->insert( (long)d.argb, c ); // store color in dict
597 #endif
598 return pix;
602 Allocates the RGB color and returns the pixel value.
604 Allocating a color means to obtain a pixel value from the RGB
605 specification. The pixel value is an index into the global color
606 table, but should be considered an arbitrary platform-dependent value.
608 The pixel() function calls alloc() if necessary, so in general you
609 don't need to call this function.
611 \sa enterAllocContext()
613 // ### 4.0 - remove me?
614 uint QColor::alloc()
616 return alloc( -1 );
620 \overload
622 Returns the pixel value for screen \a screen.
624 This value is used by the underlying window system to refer to a color.
625 It can be thought of as an index into the display hardware's color table,
626 but the value is an arbitrary 32-bit value.
628 \sa alloc()
630 uint QColor::pixel( int screen ) const
632 if (screen != QPaintDevice::x11AppScreen() &&
633 // don't allocate color0 or color1, they have fixed pixel
634 // values for all screens
635 d.argb != qRgba(255, 255, 255, 1) && d.argb != qRgba(0, 0, 0, 1))
636 return ((QColor*)this)->alloc( screen );
637 return pixel();
640 #if 0
641 void QColor::setSystemNamedColor( const QString& name )
642 #else
643 void QColor::setSystemNamedColor( const char* name )
644 #endif
646 // setSystemNamedColor should look up rgb values from the built in
647 // color tables first (see qcolor_p.cpp), and failing that, use
648 // the window system's interface for translating names to rgb values...
649 // we do this so that things like uic can load an XPM file with named colors
650 // and convert it to a png without having to use window system functions...
651 #if 0
652 d.argb = qt_get_rgb_val( name.latin1() );
653 #else
654 d.argb = qt_get_rgb_val( name );
655 #endif
656 QRgb rgb;
657 #if 0
658 if ( qt_get_named_rgb( name.latin1(), &rgb ) ) {
659 #else
660 if ( qt_get_named_rgb( name, &rgb ) ) {
661 #endif
662 setRgb( qRed(rgb), qGreen(rgb), qBlue(rgb) );
663 if ( colormodel == d8 ) {
664 d.d8.invalid = false;
665 d.d8.dirty = true;
666 d.d8.pix = 0;
667 } else {
668 alloc();
670 } else if ( !color_init ) {
671 #if defined(QT_CHECK_STATE)
672 qWarning( "QColor::setSystemNamedColor: Cannot perform this operation "
673 "because QApplication does not exist" );
674 #endif
675 // set color to invalid
676 *this = QColor();
677 } else {
678 XColor col, hw_col;
679 if ( XLookupColor(QPaintDevice::x11AppDisplay(),
680 #if 0
681 QPaintDevice::x11AppColormap(), name.latin1(),
682 #else
683 QPaintDevice::x11AppColormap(), name,
684 #endif
685 &col, &hw_col) ) {
686 setRgb( col.red>>8, col.green>>8, col.blue>>8 );
687 } else {
688 // set color to invalid
689 *this = QColor();
694 #define MAX_CONTEXTS 16
695 static int context_stack[MAX_CONTEXTS];
696 static int context_ptr = 0;
698 static void init_context_stack()
700 static bool did_init = false;
701 if ( !did_init ) {
702 did_init = true;
703 context_stack[0] = current_alloc_context = 0;
709 Enters a color allocation context and returns a non-zero unique
710 identifier.
712 Color allocation contexts are useful for programs that need to
713 allocate many colors and throw them away later, like image
714 viewers. The allocation context functions work for true color
715 displays as well as for colormap displays, except that
716 QColor::destroyAllocContext() does nothing for true color.
718 Example:
719 \code
720 QPixmap loadPixmap( QString fileName )
722 static int alloc_context = 0;
723 if ( alloc_context )
724 QColor::destroyAllocContext( alloc_context );
725 alloc_context = QColor::enterAllocContext();
726 QPixmap pm( fileName );
727 QColor::leaveAllocContext();
728 return pm;
730 \endcode
732 The example code loads a pixmap from file. It frees up all colors
733 that were allocated the last time loadPixmap() was called.
735 The initial/default context is 0. Qt keeps a list of colors
736 associated with their allocation contexts. You can call
737 destroyAllocContext() to get rid of all colors that were allocated
738 in a specific context.
740 Calling enterAllocContext() enters an allocation context. The
741 allocation context lasts until you call leaveAllocContext().
742 QColor has an internal stack of allocation contexts. Each call to
743 enterAllocContex() must have a corresponding leaveAllocContext().
745 \code
746 // context 0 active
747 int c1 = QColor::enterAllocContext(); // enter context c1
748 // context c1 active
749 int c2 = QColor::enterAllocContext(); // enter context c2
750 // context c2 active
751 QColor::leaveAllocContext(); // leave context c2
752 // context c1 active
753 QColor::leaveAllocContext(); // leave context c1
754 // context 0 active
755 // Now, free all colors that were allocated in context c2
756 QColor::destroyAllocContext( c2 );
757 \endcode
759 You may also want to set the application's color specification.
760 See QApplication::setColorSpec() for more information.
762 \sa leaveAllocContext(), currentAllocContext(), destroyAllocContext(),
763 QApplication::setColorSpec()
766 int QColor::enterAllocContext()
768 static int context_seq_no = 0;
769 init_context_stack();
770 if ( context_ptr+1 == MAX_CONTEXTS ) {
771 #if defined(QT_CHECK_STATE)
772 qWarning( "QColor::enterAllocContext: Context stack overflow" );
773 #endif
774 return 0;
776 current_alloc_context = context_stack[++context_ptr] = ++context_seq_no;
777 return current_alloc_context;
782 Leaves a color allocation context.
784 See enterAllocContext() for a detailed explanation.
786 \sa enterAllocContext(), currentAllocContext()
789 void QColor::leaveAllocContext()
791 init_context_stack();
792 if ( context_ptr == 0 ) {
793 #if defined(QT_CHECK_STATE)
794 qWarning( "QColor::leaveAllocContext: Context stack underflow" );
795 #endif
796 return;
798 current_alloc_context = context_stack[--context_ptr];
803 Returns the current color allocation context.
805 The default context is 0.
807 \sa enterAllocContext(), leaveAllocContext()
810 int QColor::currentAllocContext()
812 return current_alloc_context;
817 Destroys a color allocation context, \e context.
819 This function deallocates all colors that were allocated in the
820 specified \a context. If \a context == -1, it frees up all colors
821 that the application has allocated. If \a context == -2, it frees
822 up all colors that the application has allocated, except those in
823 the default context.
825 The function does nothing for true color displays.
827 \sa enterAllocContext(), alloc()
830 void QColor::destroyAllocContext( int context )
832 init_context_stack();
833 if ( !color_init )
834 return;
836 int screen;
837 for ( screen = 0; screen < screencount; ++screen ) {
838 if ( screendata[screen]->g_truecolor )
839 continue;
841 #if 1
842 Q_UNUSED(context);
843 #else
844 ulong pixels[256];
845 bool freeing[256];
846 memset( freeing, false, screendata[screen]->g_cells*sizeof(bool) );
847 QColorData *d;
848 QColorDictIt it( *screendata[screen]->colorDict );
849 int i = 0;
850 uint rgbv;
851 while ( (d=it.current()) ) {
852 rgbv = (uint)it.currentKey();
853 if ( (d->context || context==-1) &&
854 (d->context == context || context < 0) ) {
855 if ( !screendata[screen]->g_our_alloc[d->pix] && !freeing[d->pix] ) {
856 // will free this color
857 pixels[i++] = d->pix;
858 freeing[d->pix] = true;
860 // remove from dict
861 screendata[screen]->colorDict->remove( (long)rgbv );
863 ++it;
865 if ( i )
866 XFreeColors( QPaintDevice::x11AppDisplay(),
867 QPaintDevice::x11AppColormap( screen ),
868 pixels, i, 0 );
869 #endif