Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / ksplash / ksplashx / pixmap.cpp
blob7f39d8672132ee85cceb01738abee351d3dbe2c8
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:
14 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
16 ** This file is part of the kernel module of the Qt GUI Toolkit.
18 ** This file may be distributed under the terms of the Q Public License
19 ** as defined by Trolltech AS of Norway and appearing in the file
20 ** LICENSE.QPL included in the packaging of this file.
22 ** This file may be distributed and/or modified under the terms of the
23 ** GNU General Public License version 2 as published by the Free Software
24 ** Foundation and appearing in the file LICENSE.GPL included in the
25 ** packaging of this file.
27 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
28 ** licenses may use this file in accordance with the Qt Commercial License
29 ** Agreement provided with the Software.
31 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
32 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
34 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
35 ** information about Qt Commercial License Agreements.
36 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
37 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
39 ** Contact info@trolltech.com if any conditions of this licensing are
40 ** not clear to you.
42 **********************************************************************/
44 #include <config-X11.h>
46 #ifdef HAVE_XSHM
47 #define QT_MITSHM_CONVERSIONS
48 #endif
50 #include "qimage.h"
51 #include "qnamespace.h"
52 #include "qcolor.h"
54 #include <stdlib.h>
55 #include <string.h>
57 #include "pixmap.h"
59 #include "x11_defs.h"
61 #ifdef QT_MITSHM_CONVERSIONS
62 #include <sys/types.h>
63 #include <sys/ipc.h>
64 #include <sys/shm.h>
65 #include <X11/extensions/XShm.h>
66 #endif
68 // Returns position of highest bit set or -1 if none
69 static int highest_bit( uint v )
71 int i;
72 uint b = (uint)1 << 31;
73 for ( i=31; ((b & v) == 0) && i>=0; i-- )
74 b >>= 1;
75 return i;
78 // Returns position of lowest set bit in 'v' as an integer (0-31), or -1
79 static int lowest_bit( uint v )
81 int i;
82 unsigned long lb;
83 lb = 1;
84 for (i=0; ((v & lb) == 0) && i<32; i++, lb<<=1);
85 return i==32 ? -1 : i;
88 // Counts the number of bits set in 'v'
89 static uint n_bits( uint v )
91 int i = 0;
92 while ( v ) {
93 v = v & (v - 1);
94 i++;
96 return i;
99 inline static void qSafeXDestroyImage( XImage *x )
101 if ( x->data ) {
102 free( x->data );
103 x->data = 0;
105 XDestroyImage( x );
108 #ifdef QT_MITSHM_CONVERSIONS
110 static bool qt_mitshm_error = false;
111 static int qt_mitshm_errorhandler( Display*, XErrorEvent* )
113 qt_mitshm_error = true;
114 return 0;
117 static XImage* qt_XShmCreateImage( Display* dpy, Visual* visual, unsigned int depth,
118 int format, int /*offset*/, char* /*data*/, unsigned int width, unsigned int height,
119 int /*bitmap_pad*/, int /*bytes_per_line*/, XShmSegmentInfo* shminfo )
121 if( width * height * depth < 100*100*32 )
122 return NULL;
123 static int shm_inited = -1;
124 if( shm_inited == -1 ) {
125 if( XShmQueryExtension( dpy ))
126 shm_inited = 1;
127 else
128 shm_inited = 0;
130 if( shm_inited == 0 )
131 return NULL;
132 XImage* xi = XShmCreateImage( dpy, visual, depth, format, NULL, shminfo, width,
133 height );
134 if( xi == NULL )
135 return NULL;
136 shminfo->shmid = shmget( IPC_PRIVATE, xi->bytes_per_line * xi->height,
137 IPC_CREAT|0600);
138 if( shminfo->shmid < 0 ) {
139 XDestroyImage( xi );
140 return NULL;
142 shminfo->readOnly = False;
143 shminfo->shmaddr = (char*)shmat( shminfo->shmid, 0, 0 );
144 if( shminfo->shmaddr == (char*)-1 ) {
145 XDestroyImage( xi );
146 shmctl( shminfo->shmid, IPC_RMID, 0 );
147 return NULL;
149 xi->data = shminfo->shmaddr;
150 #ifndef QT_MITSHM_RMID_IGNORES_REFCOUNT
151 // mark as deleted to automatically free the memory in case
152 // of a crash (but this doesn't work e.g. on Solaris)
153 shmctl( shminfo->shmid, IPC_RMID, 0 );
154 #endif
155 if( shm_inited == 1 ) { // first time
156 XErrorHandler old_h = XSetErrorHandler( qt_mitshm_errorhandler );
157 XShmAttach( dpy, shminfo );
158 shm_inited = 2;
159 XSync( dpy, False );
160 XSetErrorHandler( old_h );
161 if( qt_mitshm_error ) { // oops ... perhaps we are remote?
162 shm_inited = 0;
163 XDestroyImage( xi );
164 shmdt( shminfo->shmaddr );
165 #ifdef QT_MITSHM_RMID_IGNORES_REFCOUNT
166 shmctl( shminfo->shmid, IPC_RMID, 0 );
167 #endif
168 return NULL;
170 } else
171 XShmAttach( dpy, shminfo );
172 return xi;
175 static void qt_XShmDestroyImage( XImage* xi, XShmSegmentInfo* shminfo )
177 XShmDetach( QPaintDevice::x11AppDisplay(), shminfo );
178 XDestroyImage( xi );
179 shmdt( shminfo->shmaddr );
180 #ifdef QT_MITSHM_RMID_IGNORES_REFCOUNT
181 shmctl( shminfo->shmid, IPC_RMID, 0 );
182 #endif
185 #endif // QT_MITSHM_CONVERSIONS
188 PixmapData PP::convertFromImage( const QImage &img, int conversion_flags )
190 if ( img.isNull() ) {
191 #if defined(QT_CHECK_NULL)
192 qWarning( "QPixmap::convertFromImage: Cannot convert a null image" );
193 #endif
194 return PixmapData();
196 //# detach(); // detach other references
197 QImage image = img;
198 const uint w = image.width();
199 const uint h = image.height();
200 int d = image.depth();
201 const int dd = x11Depth();
202 bool force_mono = (dd == 1 || //#*isQBitmap() ||
203 (conversion_flags & Qt::ColorMode_Mask)==MonoOnly );
205 #if 0
206 // get rid of the mask
207 delete data->mask;
208 data->mask = 0;
210 // get rid of alpha pixmap
211 delete data->alphapm;
212 data->alphapm = 0;
213 #endif
215 // must be monochrome
216 if ( force_mono ) {
217 if ( d != 1 ) {
218 // dither
219 image = image.convertDepth( 1, conversion_flags );
220 d = 1;
222 } else { // can be both
223 bool conv8 = false;
224 if ( d > 8 && dd <= 8 ) { // convert to 8 bit
225 if ( (conversion_flags & DitherMode_Mask) == AutoDither )
226 conversion_flags = (conversion_flags & ~DitherMode_Mask)
227 | PreferDither;
228 conv8 = true;
229 } else if ( (conversion_flags & ColorMode_Mask) == ColorOnly ) {
230 conv8 = d == 1; // native depth wanted
231 } else if ( d == 1 ) {
232 if ( image.numColors() == 2 ) {
233 QRgb c0 = image.color(0); // Auto: convert to best
234 QRgb c1 = image.color(1);
235 conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255);
236 } else {
237 // eg. 1-color monochrome images (they do exist).
238 conv8 = true;
241 if ( conv8 ) {
242 image = image.convertDepth( 8, conversion_flags );
243 d = 8;
247 if ( d == 1 ) { // 1 bit pixmap (bitmap)
248 abort();
249 #if 0
250 if ( hd ) { // delete old X pixmap
252 #ifndef QT_NO_XFTFREETYPE
253 if (rendhd) {
254 XftDrawDestroy( (XftDraw *) rendhd );
255 rendhd = 0;
257 #endif // QT_NO_XFTFREETYPE
259 XFreePixmap( x11Display(), hd );
262 // make sure image.color(0) == color0 (white) and image.color(1) == color1 (black)
263 if (image.color(0) == Qt::black.rgb() && image.color(1) == Qt::white.rgb()) {
264 image.invertPixels();
265 image.setColor(0, Qt::white.rgb());
266 image.setColor(1, Qt::black.rgb());
269 char *bits;
270 uchar *tmp_bits;
271 int bpl = (w+7)/8;
272 int ibpl = image.bytesPerLine();
273 if ( image.bitOrder() == QImage::BigEndian || bpl != ibpl ) {
274 tmp_bits = new uchar[bpl*h];
275 Q_CHECK_PTR( tmp_bits );
276 bits = (char *)tmp_bits;
277 uchar *p, *b, *end;
278 uint y, count;
279 if ( image.bitOrder() == QImage::BigEndian ) {
280 const uchar *f = qt_get_bitflip_array();
281 b = tmp_bits;
282 for ( y=0; y<h; y++ ) {
283 p = image.scanLine( y );
284 end = p + bpl;
285 count = bpl;
286 while ( count > 4 ) {
287 *b++ = f[*p++];
288 *b++ = f[*p++];
289 *b++ = f[*p++];
290 *b++ = f[*p++];
291 count -= 4;
293 while ( p < end )
294 *b++ = f[*p++];
296 } else { // just copy
297 b = tmp_bits;
298 p = image.scanLine( 0 );
299 for ( y=0; y<h; y++ ) {
300 memcpy( b, p, bpl );
301 b += bpl;
302 p += ibpl;
305 } else {
306 bits = (char *)image.bits();
307 tmp_bits = 0;
309 hd = (HANDLE)XCreateBitmapFromData( x11Display(),
310 RootWindow(x11Display(), x11Screen() ),
311 bits, w, h );
313 #ifndef QT_NO_XFTFREETYPE
314 if ( qt_has_xft )
315 rendhd = (HANDLE) XftDrawCreateBitmap( x11Display(), hd );
316 #endif // QT_NO_XFTFREETYPE
318 if ( tmp_bits ) // Avoid purify complaint
319 delete [] tmp_bits;
320 data->w = w; data->h = h; data->d = 1;
322 if ( image.hasAlphaBuffer() ) {
323 QBitmap m;
324 m = image.createAlphaMask( conversion_flags );
325 setMask( m );
327 return true;
328 #endif
331 Display *dpy = x11Display();
332 Visual *visual = (Visual *)x11Visual();
333 XImage *xi = 0;
334 bool trucol = (visual->c_class == TrueColor);
335 int nbytes = image.numBytes();
336 uchar *newbits= 0;
337 int newbits_size = 0;
338 #ifdef QT_MITSHM_CONVERSIONS
339 bool mitshm_ximage = false;
340 XShmSegmentInfo shminfo;
341 #endif
343 if ( trucol ) { // truecolor display
344 QRgb pix[256]; // pixel translation table
345 const bool d8 = d == 8;
346 const uint red_mask = (uint)visual->red_mask;
347 const uint green_mask = (uint)visual->green_mask;
348 const uint blue_mask = (uint)visual->blue_mask;
349 const int red_shift = highest_bit( red_mask ) - 7;
350 const int green_shift = highest_bit( green_mask ) - 7;
351 const int blue_shift = highest_bit( blue_mask ) - 7;
352 const uint rbits = highest_bit(red_mask) - lowest_bit(red_mask) + 1;
353 const uint gbits = highest_bit(green_mask) - lowest_bit(green_mask) + 1;
354 const uint bbits = highest_bit(blue_mask) - lowest_bit(blue_mask) + 1;
356 if ( d8 ) { // setup pixel translation
357 QRgb *ctable = image.colorTable();
358 for ( int i=0; i<image.numColors(); i++ ) {
359 int r = qRed (ctable[i]);
360 int g = qGreen(ctable[i]);
361 int b = qBlue (ctable[i]);
362 r = red_shift > 0 ? r << red_shift : r >> -red_shift;
363 g = green_shift > 0 ? g << green_shift : g >> -green_shift;
364 b = blue_shift > 0 ? b << blue_shift : b >> -blue_shift;
365 pix[i] = (b & blue_mask) | (g & green_mask) | (r & red_mask)
366 | ~(blue_mask | green_mask | red_mask);
370 #ifdef QT_MITSHM_CONVERSIONS
371 xi = qt_XShmCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0, &shminfo );
372 if( xi != NULL ) {
373 mitshm_ximage = true;
374 newbits = (uchar*)xi->data;
376 else
377 #endif
378 xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 );
379 Q_CHECK_PTR( xi );
380 if( newbits == NULL )
381 newbits = (uchar *)malloc( xi->bytes_per_line*h );
382 Q_CHECK_PTR( newbits );
383 if ( !newbits ) // no memory
384 return PixmapData();
385 int bppc = xi->bits_per_pixel;
387 bool contig_bits = n_bits(red_mask) == rbits &&
388 n_bits(green_mask) == gbits &&
389 n_bits(blue_mask) == bbits;
390 bool dither_tc =
391 // Want it?
392 (conversion_flags & Dither_Mask) != ThresholdDither &&
393 (conversion_flags & DitherMode_Mask) != AvoidDither &&
394 // Need it?
395 bppc < 24 && !d8 &&
396 // Can do it? (Contiguous bits?)
397 contig_bits;
399 static bool init=false;
400 static int D[16][16];
401 if ( dither_tc && !init ) {
402 // I also contributed this code to XV - WWA.
404 The dither matrix, D, is obtained with this formula:
406 D2 = [ 0 2 ]
407 [ 3 1 ]
410 D2*n = [ 4*Dn 4*Dn+2*Un ]
411 [ 4*Dn+3*Un 4*Dn+1*Un ]
413 int n,i,j;
414 init=1;
416 /* Set D2 */
417 D[0][0]=0;
418 D[1][0]=2;
419 D[0][1]=3;
420 D[1][1]=1;
422 /* Expand using recursive definition given above */
423 for (n=2; n<16; n*=2) {
424 for (i=0; i<n; i++) {
425 for (j=0; j<n; j++) {
426 D[i][j]*=4;
427 D[i+n][j]=D[i][j]+2;
428 D[i][j+n]=D[i][j]+3;
429 D[i+n][j+n]=D[i][j]+1;
433 init=true;
436 enum { BPP8,
437 BPP16_8_3_M3, BPP16_7_2_M3, BPP16_MSB, BPP16_LSB,
438 BPP24_MSB, BPP24_LSB,
439 BPP32_16_8_0, BPP32_MSB, BPP32_LSB
440 } mode = BPP8;
442 if ( bppc > 8 && xi->byte_order == LSBFirst )
443 bppc++;
445 int wordsize;
446 bool bigendian;
447 qSysInfo( &wordsize, &bigendian );
448 bool same_msb_lsb = ( xi->byte_order == MSBFirst ) == ( bigendian );
450 if( bppc == 8 ) // 8 bit
451 mode = BPP8;
452 else if( bppc == 16 || bppc == 17 ) { // 16 bit MSB/LSB
453 if( red_shift == 8 && green_shift == 3 && blue_shift == -3
454 && !d8 && same_msb_lsb )
455 mode = BPP16_8_3_M3;
456 else if( red_shift == 7 && green_shift == 2 && blue_shift == -3
457 && !d8 && same_msb_lsb )
458 mode = BPP16_7_2_M3;
459 else
460 mode = bppc == 17 ? BPP16_LSB : BPP16_MSB;
461 } else if( bppc == 24 || bppc == 25 ) { // 24 bit MSB/LSB
462 mode = bppc == 25 ? BPP24_LSB : BPP24_MSB;
463 } else if( bppc == 32 || bppc == 33 ) { // 32 bit MSB/LSB
464 if( red_shift == 16 && green_shift == 8 && blue_shift == 0
465 && !d8 && same_msb_lsb )
466 mode = BPP32_16_8_0;
467 else
468 mode = bppc == 33 ? BPP32_LSB : BPP32_MSB;
469 } else
470 qFatal("Logic error 3");
472 #define GET_PIXEL \
473 int pixel; \
474 if ( d8 ) pixel = pix[*src++]; \
475 else { \
476 int r = qRed ( *p ); \
477 int g = qGreen( *p ); \
478 int b = qBlue ( *p++ ); \
479 r = red_shift > 0 \
480 ? r << red_shift : r >> -red_shift; \
481 g = green_shift > 0 \
482 ? g << green_shift : g >> -green_shift; \
483 b = blue_shift > 0 \
484 ? b << blue_shift : b >> -blue_shift; \
485 pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \
486 | ~(blue_mask | green_mask | red_mask); \
489 // optimized case - no d8 case, shift only once instead of twice, mask only once instead of twice,
490 // use direct values instead of variables, and use only one statement
491 // (*p >> 16), (*p >> 8 ) and (*p) are qRed(),qGreen() and qBlue() without masking
492 // shifts have to be passed including the shift operator (e.g. '>>3'), because of the direction
493 #define GET_PIXEL_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask) \
494 int pixel = ((( *p >> 16 ) red_shift ) & red_mask ) \
495 | ((( *p >> 8 ) green_shift ) & green_mask ) \
496 | ((( *p ) blue_shift ) & blue_mask ); \
497 ++p;
499 #define GET_PIXEL_DITHER_TC \
500 int r = qRed ( *p ); \
501 int g = qGreen( *p ); \
502 int b = qBlue ( *p++ ); \
503 const int thres = D[x%16][y%16]; \
504 if ( r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
505 > thres) \
506 r += (1<<(8-rbits)); \
507 if ( g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
508 > thres) \
509 g += (1<<(8-gbits)); \
510 if ( b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
511 > thres) \
512 b += (1<<(8-bbits)); \
513 r = red_shift > 0 \
514 ? r << red_shift : r >> -red_shift; \
515 g = green_shift > 0 \
516 ? g << green_shift : g >> -green_shift; \
517 b = blue_shift > 0 \
518 ? b << blue_shift : b >> -blue_shift; \
519 int pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask);
521 // again, optimized case
522 // can't be optimized that much :(
523 #define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \
524 rbits,gbits,bbits) \
525 const int thres = D[x%16][y%16]; \
526 int r = qRed ( *p ); \
527 if ( r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
528 > thres) \
529 r += (1<<(8-rbits)); \
530 int g = qGreen( *p ); \
531 if ( g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
532 > thres) \
533 g += (1<<(8-gbits)); \
534 int b = qBlue ( *p++ ); \
535 if ( b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
536 > thres) \
537 b += (1<<(8-bbits)); \
538 int pixel = (( r red_shift ) & red_mask ) \
539 | (( g green_shift ) & green_mask ) \
540 | (( b blue_shift ) & blue_mask );
542 #define CYCLE(body) \
543 for ( uint y=0; y<h; y++ ) { \
544 uchar* src = image.scanLine( y ); \
545 uchar* dst = newbits + xi->bytes_per_line*y; \
546 QRgb* p = (QRgb *)src; \
547 body \
550 if ( dither_tc ) {
551 switch ( mode ) {
552 case BPP16_8_3_M3:
553 CYCLE(
554 Q_INT16* dst16 = (Q_INT16*)dst;
555 for ( uint x=0; x<w; x++ ) {
556 GET_PIXEL_DITHER_TC_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f,5,6,5)
557 *dst16++ = pixel;
560 break;
561 case BPP16_7_2_M3:
562 CYCLE(
563 Q_INT16* dst16 = (Q_INT16*)dst;
564 for ( uint x=0; x<w; x++ ) {
565 GET_PIXEL_DITHER_TC_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f,5,5,5)
566 *dst16++ = pixel;
569 break;
570 case BPP16_MSB: // 16 bit MSB
571 CYCLE(
572 for ( uint x=0; x<w; x++ ) {
573 GET_PIXEL_DITHER_TC
574 *dst++ = (pixel >> 8);
575 *dst++ = pixel;
578 break;
579 case BPP16_LSB: // 16 bit LSB
580 CYCLE(
581 for ( uint x=0; x<w; x++ ) {
582 GET_PIXEL_DITHER_TC
583 *dst++ = pixel;
584 *dst++ = pixel >> 8;
587 break;
588 default:
589 qFatal("Logic error");
591 } else {
592 switch ( mode ) {
593 case BPP8: // 8 bit
594 CYCLE(
595 Q_UNUSED(p);
596 for ( uint x=0; x<w; x++ ) {
597 int pixel = pix[*src++];
598 *dst++ = pixel;
601 break;
602 case BPP16_8_3_M3:
603 CYCLE(
604 Q_INT16* dst16 = (Q_INT16*)dst;
605 for ( uint x=0; x<w; x++ ) {
606 GET_PIXEL_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f)
607 *dst16++ = pixel;
610 break;
611 case BPP16_7_2_M3:
612 CYCLE(
613 Q_INT16* dst16 = (Q_INT16*)dst;
614 for ( uint x=0; x<w; x++ ) {
615 GET_PIXEL_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f)
616 *dst16++ = pixel;
619 break;
620 case BPP16_MSB: // 16 bit MSB
621 CYCLE(
622 for ( uint x=0; x<w; x++ ) {
623 GET_PIXEL
624 *dst++ = (pixel >> 8);
625 *dst++ = pixel;
628 break;
629 case BPP16_LSB: // 16 bit LSB
630 CYCLE(
631 for ( uint x=0; x<w; x++ ) {
632 GET_PIXEL
633 *dst++ = pixel;
634 *dst++ = pixel >> 8;
637 break;
638 case BPP24_MSB: // 24 bit MSB
639 CYCLE(
640 for ( uint x=0; x<w; x++ ) {
641 GET_PIXEL
642 *dst++ = pixel >> 16;
643 *dst++ = pixel >> 8;
644 *dst++ = pixel;
647 break;
648 case BPP24_LSB: // 24 bit LSB
649 CYCLE(
650 for ( uint x=0; x<w; x++ ) {
651 GET_PIXEL
652 *dst++ = pixel;
653 *dst++ = pixel >> 8;
654 *dst++ = pixel >> 16;
657 break;
658 case BPP32_16_8_0:
659 CYCLE(
660 memcpy( dst, p, w * 4 );
662 break;
663 case BPP32_MSB: // 32 bit MSB
664 CYCLE(
665 for ( uint x=0; x<w; x++ ) {
666 GET_PIXEL
667 *dst++ = pixel >> 24;
668 *dst++ = pixel >> 16;
669 *dst++ = pixel >> 8;
670 *dst++ = pixel;
673 break;
674 case BPP32_LSB: // 32 bit LSB
675 CYCLE(
676 for ( uint x=0; x<w; x++ ) {
677 GET_PIXEL
678 *dst++ = pixel;
679 *dst++ = pixel >> 8;
680 *dst++ = pixel >> 16;
681 *dst++ = pixel >> 24;
684 break;
685 default:
686 qFatal("Logic error 2");
689 xi->data = (char *)newbits;
692 if ( d == 8 && !trucol ) { // 8 bit pixmap
693 int pop[256]; // pixel popularity
695 if ( image.numColors() == 0 )
696 image.setNumColors( 1 );
698 memset( pop, 0, sizeof(int)*256 ); // reset popularity array
699 uint i;
700 for ( i=0; i<h; i++ ) { // for each scanline...
701 uchar* p = image.scanLine( i );
702 uchar *end = p + w;
703 while ( p < end ) // compute popularity
704 pop[*p++]++;
707 newbits = (uchar *)malloc( nbytes ); // copy image into newbits
708 newbits_size = nbytes;
709 Q_CHECK_PTR( newbits );
710 if ( !newbits ) // no memory
711 return PixmapData();
712 uchar* p = newbits;
713 memcpy( p, image.bits(), nbytes ); // copy image data into newbits
716 * The code below picks the most important colors. It is based on the
717 * diversity algorithm, implemented in XV 3.10. XV is (C) by John Bradley.
720 struct PIX { // pixel sort element
721 uchar r,g,b,n; // color + pad
722 int use; // popularity
723 int index; // index in colormap
724 int mindist;
726 int ncols = 0;
727 for ( i=0; i< (uint) image.numColors(); i++ ) { // compute number of colors
728 if ( pop[i] > 0 )
729 ncols++;
731 for ( i=image.numColors(); i<256; i++ ) // ignore out-of-range pixels
732 pop[i] = 0;
734 // works since we make sure above to have at least
735 // one color in the image
736 if ( ncols == 0 )
737 ncols = 1;
739 PIX pixarr[256]; // pixel array
740 PIX pixarr_sorted[256]; // pixel array (sorted)
741 memset( pixarr, 0, ncols*sizeof(PIX) );
742 PIX *px = &pixarr[0];
743 int maxpop = 0;
744 int maxpix = 0;
745 Q_CHECK_PTR( pixarr );
746 uint j = 0;
747 QRgb* ctable = image.colorTable();
748 for ( i=0; i<256; i++ ) { // init pixel array
749 if ( pop[i] > 0 ) {
750 px->r = qRed ( ctable[i] );
751 px->g = qGreen( ctable[i] );
752 px->b = qBlue ( ctable[i] );
753 px->n = 0;
754 px->use = pop[i];
755 if ( pop[i] > maxpop ) { // select most popular entry
756 maxpop = pop[i];
757 maxpix = j;
759 px->index = i;
760 px->mindist = 1000000;
761 px++;
762 j++;
765 pixarr_sorted[0] = pixarr[maxpix];
766 pixarr[maxpix].use = 0;
768 for ( i=1; i< (uint) ncols; i++ ) { // sort pixels
769 int minpix = -1, mindist = -1;
770 px = &pixarr_sorted[i-1];
771 int r = px->r;
772 int g = px->g;
773 int b = px->b;
774 int dist;
775 if ( (i & 1) || i<10 ) { // sort on max distance
776 for ( int j=0; j<ncols; j++ ) {
777 px = &pixarr[j];
778 if ( px->use ) {
779 dist = (px->r - r)*(px->r - r) +
780 (px->g - g)*(px->g - g) +
781 (px->b - b)*(px->b - b);
782 if ( px->mindist > dist )
783 px->mindist = dist;
784 if ( px->mindist > mindist ) {
785 mindist = px->mindist;
786 minpix = j;
790 } else { // sort on max popularity
791 for ( int j=0; j<ncols; j++ ) {
792 px = &pixarr[j];
793 if ( px->use ) {
794 dist = (px->r - r)*(px->r - r) +
795 (px->g - g)*(px->g - g) +
796 (px->b - b)*(px->b - b);
797 if ( px->mindist > dist )
798 px->mindist = dist;
799 if ( px->use > mindist ) {
800 mindist = px->use;
801 minpix = j;
806 pixarr_sorted[i] = pixarr[minpix];
807 pixarr[minpix].use = 0;
810 uint pix[256]; // pixel translation table
811 px = &pixarr_sorted[0];
812 for ( i=0; i< (uint) ncols; i++ ) { // allocate colors
813 QColor c( px->r, px->g, px->b );
814 pix[px->index] = c.pixel(x11Screen());
815 px++;
818 p = newbits;
819 for ( i=0; i< (uint) nbytes; i++ ) { // translate pixels
820 *p = pix[*p];
821 p++;
825 if ( !xi ) { // X image not created
826 #ifdef QT_MITSHM_CONVERSIONS
827 xi = qt_XShmCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0, &shminfo );
828 if( xi != NULL )
829 mitshm_ximage = true;
830 else
831 #endif
832 xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 );
833 if ( xi->bits_per_pixel == 16 ) { // convert 8 bpp ==> 16 bpp
834 ushort *p2;
835 int p2inc = xi->bytes_per_line/sizeof(ushort);
836 ushort *newerbits = (ushort *)malloc( xi->bytes_per_line * h );
837 newbits_size = xi->bytes_per_line * h;
838 Q_CHECK_PTR( newerbits );
839 if ( !newerbits ) // no memory
840 return PixmapData();
841 uchar* p = newbits;
842 for ( uint y=0; y<h; y++ ) { // OOPS: Do right byte order!!
843 p2 = newerbits + p2inc*y;
844 for ( uint x=0; x<w; x++ )
845 *p2++ = *p++;
847 free( newbits );
848 newbits = (uchar *)newerbits;
849 } else if ( xi->bits_per_pixel != 8 ) {
850 #if defined(QT_CHECK_RANGE)
851 qWarning( "QPixmap::convertFromImage: Display not supported "
852 "(bpp=%d)", xi->bits_per_pixel );
853 #endif
855 #ifdef QT_MITSHM_CONVERSIONS
856 if( newbits_size > 0 && mitshm_ximage ) { // need to copy to shared memory
857 memcpy( xi->data, newbits, newbits_size );
858 free( newbits );
859 newbits = (uchar*)xi->data;
861 else
862 #endif
863 xi->data = (char *)newbits;
866 #if 0
867 if ( hd && (width() != (int)w || height() != (int)h || this->depth() != dd) ) {
869 #ifndef QT_NO_XFTFREETYPE
870 if (rendhd) {
871 XftDrawDestroy( (XftDraw *) rendhd );
872 rendhd = 0;
874 #endif // QT_NO_XFTFREETYPE
876 XFreePixmap( dpy, hd ); // don't reuse old pixmap
877 hd = 0;
879 #endif
880 PixmapData dat;
881 PixmapData* data = &dat;
882 data->hd = None;
883 Pixmap& hd = data->hd;
885 if ( !hd ) { // create new pixmap
886 hd = (HANDLE)XCreatePixmap( x11Display(),
887 RootWindow(x11Display(), x11Screen() ),
888 w, h, dd );
890 #ifndef QT_NO_XFTFREETYPE
891 if ( qt_has_xft ) {
892 if ( data->d == 1 ) {
893 rendhd = (HANDLE) XftDrawCreateBitmap( x11Display (), hd );
894 } else {
895 rendhd = (HANDLE) XftDrawCreate( x11Display (), hd,
896 (Visual *) x11Visual(), x11Colormap() );
899 #endif // QT_NO_XFTFREETYPE
903 #ifdef QT_MITSHM_CONVERSIONS
904 if( mitshm_ximage )
905 XShmPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), false ),
906 xi, 0, 0, 0, 0, w, h, False );
907 else
908 #endif
909 XPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), false ),
910 xi, 0, 0, 0, 0, w, h );
912 data->w = w;
913 data->h = h;
914 data->d = dd;
916 XImage* axi = NULL;
917 #ifdef QT_MITSHM_CONVERSIONS
918 bool mitshm_aximage = false;
919 XShmSegmentInfo ashminfo;
920 #endif
921 if ( image.hasAlphaBuffer() ) {
922 abort();
923 #if 0
924 QBitmap m;
925 m = image.createAlphaMask( conversion_flags );
926 setMask( m );
928 #ifndef QT_NO_XFTFREETYPE
929 // does this image have an alphamap (and not just a 1bpp mask)?
930 bool alphamap = image.depth() == 32;
931 if (image.depth() == 8) {
932 const QRgb * const rgb = image.colorTable();
933 for (int i = 0, count = image.numColors(); i < count; ++i) {
934 const int alpha = qAlpha(rgb[i]);
935 if (alpha != 0 && alpha != 0xff) {
936 alphamap = true;
937 break;
942 if (qt_use_xrender && qt_has_xft && alphamap) {
943 data->alphapm = new QPixmap; // create a null pixmap
945 // setup pixmap data
946 data->alphapm->data->w = w;
947 data->alphapm->data->h = h;
948 data->alphapm->data->d = 8;
950 // create 8bpp pixmap and render picture
951 data->alphapm->hd =
952 XCreatePixmap(x11Display(), RootWindow(x11Display(), x11Screen()),
953 w, h, 8);
955 data->alphapm->rendhd =
956 (HANDLE) XftDrawCreateAlpha( x11Display(), data->alphapm->hd, 8 );
958 #ifdef QT_MITSHM_CONVERSIONS
959 axi = qt_XShmCreateImage( x11Display(), (Visual*)x11Visual(),
960 8, ZPixmap, 0, 0, w, h, 8, 0, &ashminfo );
961 if( axi != NULL )
962 mitshm_aximage = true;
963 else
964 #endif
965 axi = XCreateImage(x11Display(), (Visual *) x11Visual(),
966 8, ZPixmap, 0, 0, w, h, 8, 0);
968 if (axi) {
969 if( axi->data==NULL ) {
970 // the data is deleted by qSafeXDestroyImage
971 axi->data = (char *) malloc(h * axi->bytes_per_line);
972 Q_CHECK_PTR( axi->data );
974 char *aptr = axi->data;
976 if (image.depth() == 32) {
977 const int *iptr = (const int *) image.bits();
978 if( axi->bytes_per_line == (int)w ) {
979 int max = w * h;
980 while (max--)
981 *aptr++ = *iptr++ >> 24; // squirt
982 } else {
983 for (uint i = 0; i < h; ++i ) {
984 for (uint j = 0; j < w; ++j )
985 *aptr++ = *iptr++ >> 24; // squirt
986 aptr += ( axi->bytes_per_line - w );
989 } else if (image.depth() == 8) {
990 const QRgb * const rgb = image.colorTable();
991 for (uint y = 0; y < h; ++y) {
992 const uchar *iptr = image.scanLine(y);
993 for (uint x = 0; x < w; ++x)
994 *aptr++ = qAlpha(rgb[*iptr++]);
995 aptr += ( axi->bytes_per_line - w );
999 GC gc = XCreateGC(x11Display(), data->alphapm->hd, 0, 0);
1000 #ifdef QT_MITSHM_CONVERSIONS
1001 if( mitshm_aximage )
1002 XShmPutImage( dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h, False );
1003 else
1004 #endif
1005 XPutImage(dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h);
1006 XFreeGC(x11Display(), gc);
1009 #endif // QT_NO_XFTFREETYPE
1010 #endif
1013 #ifdef QT_MITSHM_CONVERSIONS
1014 if( mitshm_ximage || mitshm_aximage )
1015 XSync( x11Display(), False ); // wait until processed
1016 #endif
1018 if ( data->optim != BestOptim ) { // throw away image
1019 #ifdef QT_MITSHM_CONVERSIONS
1020 if( mitshm_ximage )
1021 qt_XShmDestroyImage( xi, &shminfo );
1022 else
1023 #endif
1024 qSafeXDestroyImage( xi );
1025 data->ximage = 0;
1026 } else { // keep ximage that we created
1027 #ifdef QT_MITSHM_CONVERSIONS
1028 if( mitshm_ximage ) { // copy the XImage?
1029 qt_XShmDestroyImage( xi, &shminfo );
1030 xi = 0;
1032 #endif
1033 data->ximage = xi;
1035 if( axi ) {
1036 #ifdef QT_MITSHM_CONVERSIONS
1037 if( mitshm_aximage )
1038 qt_XShmDestroyImage( axi, &ashminfo );
1039 else
1040 #endif
1041 qSafeXDestroyImage(axi);
1043 return *data;