/* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . / /** * PURPOSE: * Efficient bitmaps of colour depths 1, 2, 4, 8, 16, 24 and 32bpp * * COMMENTS: * None */ #ifdef __GNUG__ #pragma implementation #pragma implementation "wx_pixmap.h" #pragma implementation "wx_pixmap_dither.h" #endif #include #include #include // changed in wxWindows 2.4.2: //#include "wx_prec.h" #include #include #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOM #include #include #include "wx_pixmap.h" #include "wx_pixmap_translate.h" #endif #ifdef wx_msw #include #endif #ifdef wx_x #include #endif /* * Globals */ unsigned char *TrueTransTab = NULL; int TrueTransCount = 0; unsigned char *FastDitherTab = NULL; int FastDitherCount = 0; #ifdef wx_x typedef struct wxVisualType { int depth, vclass; } wxVisualType; static wxVisualType wxVisualTypes[] = { {32, TrueColor}, {24, TrueColor}, {16, TrueColor}, {15, TrueColor}, {8, PseudoColor}, {8, GrayScale}, {-1, 0} }; #endif /* Order of RGB components in true-colour modes */ #define RGB_ORDER_NONE 0 #define RGB_ORDER_RGB 1 #define RGB_ORDER_BGR 2 /* * Determine the colour component with the biggest weight for sorting and * colour-lookup. */ #if (COLOUR_WEIGHT_RED > COLOUR_WEIGHT_GREEN) #error here #define AUX1_COMPONENT green #define COLOUR_WEIGHT_AUX1 COLOUR_WEIGHT_GREEN #if (COLOUR_WEIGHT_RED > COLOUR_WEIGHT_BLUE) #define SORT_COMPONENT red #define AUX2_COMPONENT blue #define COLOUR_WEIGHT_MAX COLOUR_WEIGHT_RED #define COLOUR_WEIGHT_AUX1 COLOUR_WEIGHT_BLUE #else #define SORT_COMPONENT blue #define AUX2_COMPONENT red #define COLOUR_WEIGHT_MAX COLOUR_WEIGHT_BLUE #define COLOUR_WEIGHT_AUX2 COLOUR_WEIGHT_RED #endif #else #define AUX1_COMPONENT red #define COLOUR_WEIGHT_AUX1 COLOUR_WEIGHT_RED #if (COLOUR_WEIGHT_GREEN > COLOUR_WEIGHT_BLUE) #define SORT_COMPONENT green #define AUX2_COMPONENT blue #define COLOUR_WEIGHT_MAX COLOUR_WEIGHT_GREEN #define COLOUR_WEIGHT_AUX2 COLOUR_WEIGHT_BLUE #else #define SORT_COMPONENT blue #define AUX2_COMPONENT green #define COLOUR_WEIGHT_MAX COLOUR_WEIGHT_BLUE #define COLOUR_WEIGHT_AUX2 COLOUR_WEIGHT_GREEN #endif #endif #define SELECT_COMPONENT(x,c) x.c // General, platform independent members int wxPixmap::getWidth(void) {return(width);} int wxPixmap::getHeight(void) {return(height);} int wxPixmap::getDepth(void) {return(depth);} int wxPixmap::getPitch(void) {return(pitch);} char *wxPixmap::getData(void) {return(data);} wxColour *wxPixmap::getPalette(void) {return(palette);} // Returns the depth of the current mode int wxPixmap::getModeDepth(void) {return(displayDepth);} // Returns the pitch of the current mode int wxPixmap::getModePitch(void) {return(displayPitch);} // Returns a pointer to the mode-translated data or NULL if none. char *wxPixmap::getModeData(void) {return(modeData);} // Returns a pointer to the translation table or NULL if none exists. // The format depends on the display depth: <= 8 ==> 8bit, else 32bit unsigned char *wxPixmap::getTranslationTable(void) { if ((depth > 12) && (displayDepth <= 8)) return TrueTransTab; return TransTab.c; } // Error reporting / handling void wxPixmap::errorMemory(void) { #if (DEBUG > 0) *errorstr << "Can't claim memory!" << endl; #endif } void wxPixmap::errorGeneric(char *message) { #if (DEBUG > 0) *errorstr << message << endl; #endif } // Display can't change on X, but it can on other systems. // Returns depth of new mode. Internal variables holding mode information // will be overwritten after calling this function, so make sure you copy // them first if you need them. void wxPixmap::getDisplayAttributes(void) { #ifdef wx_x int i; #if 0 for (i=0; wxVisualTypes[i].depth >= 0; i++) { if (XMatchVisualInfo(display, screen, wxVisualTypes[i].depth, wxVisualTypes[i].vclass, &visualInfo)) break; } #else displayDepth = wxDisplayDepth(); for (i=0; wxVisualTypes[i].depth >= 0; i++) { if (wxVisualTypes[i].depth == displayDepth) { if (XMatchVisualInfo(display, screen, wxVisualTypes[i].depth, wxVisualTypes[i].vclass, &visualInfo)) break; } } #endif if (wxVisualTypes[i].depth < 0) { errorGeneric("Can't get appropriate X visual"); displayDepth = -1; } // On X we have to find the bpp manually int j; XPixmapFormatValues *pixvals = XListPixmapFormats(display, &i); for (j=0; j 8) { if ((visualInfo.red_mask < visualInfo.green_mask) && (visualInfo.green_mask < visualInfo.blue_mask)) rgbOrder = RGB_ORDER_RGB; else if ((visualInfo.red_mask > visualInfo.green_mask) && (visualInfo.green_mask > visualInfo.blue_mask)) rgbOrder = RGB_ORDER_BGR; #if (DEBUG > 0) else *errorstr << "Unrecognized pixel format, assuming r,g,b" << endl; #endif } if (BitmapBitOrder(display) == LSBFirst) destBitorder = 0; else destBitorder = 1; if (ImageByteOrder(display) == LSBFirst) destByteorder = 0; else destByteorder = 1; //cout << "destBit " << destBitorder << ", destByte " << destByteorder << endl; #endif #ifdef wx_msw int bpp, planes, pfi; PIXELFORMATDESCRIPTOR pfd; desktop = GetDesktopWindow(); rootDC = GetDC(desktop); bpp = GetDeviceCaps(rootDC, BITSPIXEL); planes = GetDeviceCaps(rootDC, PLANES); displayDepth = bpp * planes; pfi = 1;//GetPixelFormat(rootDC); if (pfi != 0) { if (DescribePixelFormat(rootDC, pfi, sizeof(PIXELFORMATDESCRIPTOR), &pfd) != 0) { displayDepth = (int)pfd.cRedBits + (int)pfd.cGreenBits + (int)pfd.cBlueBits; rgbOrder = RGB_ORDER_BGR; if (displayDepth > 8) { if ((pfd.cRedShift < pfd.cGreenShift) && (pfd.cGreenShift < pfd.cBlueShift)) rgbOrder = RGB_ORDER_RGB; else if ((pfd.cRedShift > pfd.cGreenShift) && (pfd.cGreenShift > pfd.cBlueShift)) rgbOrder = RGB_ORDER_BGR; #if (DEBUG > 0) else *errorstr << "Unrecognized pixel format, assuming b,g,r" << endl; #endif } #if (DEBUG > 0) else *errorstr << "Error describing pixel format (" << GetLastError() << ")" << endl; #endif } } #if (DEBUG > 0) else *errorstr << "Error reading pixel format (" << GetLastError() << ")" << endl; #endif // On NT use the machine order destBitorder = WX_PIXMAP_SRC_BITORDER; destByteorder = WX_PIXMAP_SRC_BYTEORDER; #endif // Filter out unsupported display depths switch (displayDepth) { case 1: case 2: case 4: case 8: case 15: case 16: case 24: case 32: break; default: #if (DEBUG > 0) *errorstr << "Unsupported display depth " << displayDepth << endl; #endif displayDepth = -1; return; } #if (DEBUG > 0) *errorstr << "Display depth = " << displayDepth << ", rgb format " << ((rgbOrder == RGB_ORDER_RGB) ? "r,g,b" : "b,g,r") << endl; #endif } void wxPixmap::initColoursForMode(bool forceUpdate) { #ifdef wx_pixmap_alloc_cols // Clear colour allocation bitfield memset(ColourAlloc, 0, 32); #else processParentPalette(forceUpdate); #endif setupTranslators(); } // Stuff shared by all constructors. void wxPixmap::initVariables(void) { data = NULL; modeData = NULL; palette = NULL; TransTab.c = NULL; validDisplay = FALSE; busyCursorMode = TRUE; parentWin = NULL; errorstr = NULL; #ifndef wx_pixmap_alloc_cols parentPalette = NULL; pixmapPalette = NULL; parentPaletteDepth = 0; #endif width=0; height=0; depth=0; pad=0; #if (DEBUG > 0) #ifdef wx_x // For some reason the other variant crashes on Sun errorstr = (ostream*)&cerr; #else #ifdef wx_msw errorstr = new ofstream("debug.log",ios::out | ios::trunc); #else errorstr = new ostream(&streamBuf); #endif #endif #endif #ifdef wx_x xim = NULL; display = wxGetDisplay(); myGC = (GC)0; screen = XDefaultScreen(display); rootwin = XRootWindow(display, screen); //Screen *myScreen = DefaultScreenOfDisplay(display); //cout << "root depth " << myScreen->root_depth << endl; #endif #ifdef wx_msw bitmap = (HBITMAP)0; windowHandle = (HWND)0; rootDC = (HDC)0; srcDC = (HDC)0; winDC = (HDC)0; oldDCObject = (HGDIOBJ)0; #endif getDisplayAttributes(); } // New Depth and Flags are passed to this function to allow optimising colour handling. void wxPixmap::freeResources(int Depth, unsigned int Flags) { #ifdef wx_msw if (bitmap != (HBITMAP)0) { DeleteObject(bitmap); bitmap = (HBITMAP)0; } if (modeData != data) { free(modeData); modeData = NULL; } // For symmetry to X if (data != NULL) { free(data); data = NULL; } if (srcDC != (HDC)0) { SelectObject(srcDC, oldDCObject); DeleteObject(srcDC); srcDC = (HDC)0; } #endif #ifdef wx_x if ((modeData != NULL) && (modeData != data)) { // In this case the XImage structure was initialised with modeData // rather than data. Therefore on deleting xim modeData will be // deleted automatically. Use malloc/free combination rather than // new/delete. free(data); data = NULL; } // Free image if any. This also destroys the data it was initialised with // (see above). if (xim != NULL) { XDestroyImage(xim); xim = NULL; } // The graphical context can change every time newPixmap is called, therefore // it must be deleted here and not in the destructor. if (myGC != (GC)0) { XFreeGC(display, myGC); myGC = (GC)0; } // If the new palette is the same as the old one we leave the colours as they are. // Note that calling with no colour translation but with samepalette doesn't // free anthing - that's because the Translation table has to be present even // if no _automatic_ translation takes place. #ifdef wx_pixmap_alloc_cols if ((Flags & WX_PIXFLAG_SAMEPALETTE) == 0) { // Free colours if any were allocated (i.e. displayDepth <= 8) if ((displayDepth <= 8) && (TransTab.c != NULL)) { unsigned long pixels[256]; int i, j; for (i=0, j=0; i<(1<>3] & (1 << (i & 7))) != 0) { pixels[j++] = i; } } XFreeColors(display, xat.colormap, pixels, j, 0); // *errorstr << j << " colours freed." << endl; } } #endif #endif // #ifdef wx_x // This is for all machines again if ((Flags & WX_PIXFLAG_SAMEPALETTE) == 0) { // In case both depth > 8 (true-colour) and old depth > 8 we don't need to make a new // colourtable, hence we don't have to delete the old one. if ((depth <= 12) && (Depth <= 12) && (TransTab.c != NULL)) { delete [] TransTab.c; TransTab.c = NULL; } } // Update TrueColour Translation table if ((depth > 12) && (displayDepth <= 8)) { if (depth != Depth) { TrueTransCount--; #ifdef WX_PIXMAP_GLOBAL_VOLATILE if (TrueTransCount == 0) { delete [] TrueTransTab; TrueTransTab = NULL; } #endif } } // Fast dithering table? if ((pixFlags & WX_PIXFLAG_FASTDITHER) != 0) { FastDitherCount--; #ifdef WX_PIXMAP_GLOBAL_VOLATILE if (FastDitherCount == 0) { delete [] FastDitherTab; FastDitherTab = NULL; } #endif } if (palette != NULL) { delete [] palette; palette = NULL; } } #ifndef wx_pixmap_alloc_cols void wxPixmap::processParentPalette(bool forceUpdate) { if (displayDepth > 8) { if (parentPalette != NULL) { delete [] parentPalette; parentPalette=NULL; parentPaletteDepth = 0; } } // For non-truecolour modes read the screen palette and install fast lookup functions // Essentially forceUpdate should only be set to true if only the palette, not the // more depth has changed. else if ((parentPaletteDepth != displayDepth) || forceUpdate) { unsigned int i, ncols; ncols = (1<>1; } last = value+1; } // fill remaining entries while (last < 256) {parentInverse[last] = (1<= 0) || (up < (1<= 0) { match = COLOUR_WEIGHT_MAX * square_val((int)SORT_COMPONENT - (int)SELECT_COMPONENT(parentPalette[down], SORT_COMPONENT)); if (match > bestMatch) down=-1; else { match += COLOUR_WEIGHT_AUX1 * square_val((int)AUX1_COMPONENT - (int)SELECT_COMPONENT(parentPalette[down], AUX1_COMPONENT)) + COLOUR_WEIGHT_AUX2 * square_val((int)AUX2_COMPONENT - (int)SELECT_COMPONENT(parentPalette[down], AUX2_COMPONENT)); if (match < bestMatch) {bestMatch = match; bestIdx = down;} down--; } } if (up < (1< bestMatch) up=(1<>3) | ((green & 0xf8)<<2) | ((blue&0xf8)<<7)]); } // Converts the pixmap's palette into a wx_permute_cmap which is needed by the ditherer. // Only call if depth <= 8! Other modes are assumed true-colour. void wxPixmap::processPixmapPalette(void) { int i; int tabsize; if (depth <= 8) tabsize = (1<> 8); grey += step; } } else { unsigned char red, green, blue; for (i=0; i 0) { if (TransTabSize > 256) // For a true colour mode? { if (TrueTransTab == NULL) { if ((TrueTransTab = new unsigned char[(1<<15)]) == NULL) { errorMemory(); return; } BuildTrueTable = TRUE; } TrueTransCount++; } if (TransTabSize <= 256); { // Base type of translation table depends on display depth if (displayDepth <= 8) TransTab.c = new unsigned char[TransTabSize]; else TransTab.l = new COLORREF[TransTabSize]; if (TransTab.c == NULL) { errorMemory(); return; } } // *errorstr << "Allocated Translation table of size " << TransTabSize << endl; } if (((pixFlags & WX_PIXFLAG_FASTDITHER) != 0) && (displayDepth <= 8)) { if (FastDitherTab == NULL) { if ((FastDitherTab = new unsigned char[(1<<15)]) == NULL) { errorMemory(); return; } if (busyCursorMode) ::wxBeginBusyCursor(); for (i=0; i<0x8000; i++) { PALETTE_SHORT_TO_RGB(i, red, green, blue); FastDitherTab[i] = findBestColour(red, green, blue); } if (busyCursorMode) ::wxEndBusyCursor(); } FastDitherCount++; } // Palette indices --> pixel indices if ((depth <= 12) && (displayDepth <= 8)) { int tabsize; if (depth <= 8) tabsize = (1<>3] & (1 << ((xcolour.pixel) & 7))) == 0) { ColourAlloc[(xcolour.pixel)>>3] |= (1 << ((xcolour.pixel) & 7)); } else { pixel = xcolour.pixel; XFreeColors(display, xat.colormap, &pixel, 1, 0); } } TransTab.c[i] = (unsigned char)xcolour.pixel; // *errorstr << i << " (" << cstring << "): " << xcolour.pixel << endl; #endif #ifdef wx_msw TransTab.c[i] = (unsigned char)(GetNearestPaletteIndex(rootDC, red | (green<<8) | (blue<<16))); #endif #else bestIdx = findBestColour(red, green, blue); TransTab.c[i] = parentPalette[bestIdx].number; #endif } } if ((depth > 8) && (displayDepth <= 8)) { if (BuildTrueTable) { if (busyCursorMode) ::wxBeginBusyCursor(); // This is a bit heavy... for (i=0; i<0x8000; i++) { // The internal format is always the same PALETTE_SHORT_TO_RGB(i,red,green,blue); #ifdef wx_pixmap_alloc_cols #ifdef wx_x sprintf(cstring, "rgb:%x/%x/%x", red, green, blue); XParseColor(display, xat.colormap, cstring, &xcolour); if (XAllocColor(display, xat.colormap, &xcolour)) { if ((ColourAlloc[(xcolour.pixel)>>3] & (1 << ((xcolour.pixel) & 7))) == 0) { ColourAlloc[(xcolour.pixel)>>3] |= (1 << ((xcolour.pixel) & 7)); } else { pixel = xcolour.pixel; XFreeColors(display, xat.colormap, &pixel, 1, 0); } } TrueTransTab[i] = (unsigned char)xcolour.pixel; #endif #ifdef wx_msw TrueTransTab[i] = (unsigned char)(GetNearestPaletteIndex(rootDC, red | (green<<8) | (blue<<16))); #endif #else bestIdx = (FastDitherTab == NULL) ? findBestColour(red, green, blue) : FastDitherTab[i]; TrueTransTab[i] = parentPalette[bestIdx].number; #endif } if (busyCursorMode) ::wxEndBusyCursor(); } } // Special translation tables which are platform independent (true-colour displays): if ((depth <= 12) && (displayDepth > 8)) { int tabsize; if (depth <= 8) tabsize = (1<> 8); // convert fixpoint to integer, rounding. if (grey > 255) grey = 255; if (destByteorder == WX_PIXMAP_SRC_BYTEORDER) TransTab.l[i] = _RGBL_TO_PALETTE_SHORT15(grey, grey, grey); else TransTab.l[i] = _RGBL_TO_PALETTE_SHORT15i(grey, grey, grey); } } else if (displayDepth == 16) // 16bpp { for (i=0; i> 8); if (grey > 255) grey = 255; if (destByteorder == WX_PIXMAP_SRC_BYTEORDER) TransTab.l[i] = _RGBL_TO_PALETTE_SHORT16(grey, grey, grey); else TransTab.l[i] = _RGBL_TO_PALETTE_SHORT16i(grey, grey, grey); } } else // 24/32bpp { for (i=0; i> 8; if (destByteorder == WX_PIXMAP_SRC_BYTEORDER) TransTab.l[i] = _RGB_TO_PALETTE_LONG(grey, grey, grey); else TransTab.l[i] = _RGB_TO_PALETTE_LONGi(grey, grey, grey); } } } else // palette != NULL ==> determine the true-colour values { if (displayDepth == 15) { for (i=0; i 0) *errorstr << "Translation table (" << TransTabSize << "), table entry size "; if (displayDepth <= 8) *errorstr << (int)8; else *errorstr << (int)32; *errorstr << " bits." << endl; *errorstr << hex; if (displayDepth <= 8) { if (depth > 12) { for (i=0; i just build // the tables. if (((displayDepth == lastDisplayDepth) && ((modeFlags & WX_PIXMODE_PALETTE) != 0)) || ((pixFlags & WX_PIXFLAG_TRANSLATE) == 0)) { initColoursForMode(TRUE); buildTranslationTable(); } else { // otherwise we need to set up completely new buffers and stuff. if (TrueTransTab != NULL) { delete [] TrueTransTab; TrueTransTab = NULL; TrueTransCount = 0; } if (FastDitherTab != NULL) { delete [] FastDitherTab; FastDitherTab = NULL; FastDitherCount = 0; } newPixmap(parentWin, width, height, depth, pad, data, pixFlags | WX_PIXFLAG_SAMEPALETTE, palette); } } wxPixmap::wxPixmap(void) { initVariables(); } wxPixmap::wxPixmap(wxWindow *Win, int Width, int Height, int Depth, int Pad, char *Data, unsigned int Flags, wxColour *Palette) { initVariables(); newPixmap(Win, Width, Height, Depth, Pad, Data, Flags, Palette); } wxPixmap::~wxPixmap(void) { if (errorstr != NULL) { #ifndef wx_x #ifdef wx_msw errorstr->flush(); #endif delete errorstr; #endif } // Use illegal value for depth to make sure everything is freed freeResources(0, 0); #ifndef wx_pixmap_alloc_cols if (parentPalette != NULL) {delete [] parentPalette; parentPalette = NULL;} if (pixmapPalette != NULL) {delete [] pixmapPalette; pixmapPalette = NULL;} #endif } int wxPixmap::newPixmap(wxWindow *Win, int Width, int Height, int Depth, int Pad, char *Data, unsigned int Flags, wxColour *Palette) { int lastDepth = depth; #ifdef wx_msw int virtWidth; #endif // Can we display it at all? if (displayDepth <= 0) return -1; // Filter out unsupported depths switch (Depth) { case 1: case 2: case 4: case 8: case 12: case 15: case 24: case 32: break; default: #if (DEBUG > 0) *errorstr << "Unsupported colour depth " << Depth << endl; #endif return -1; } freeResources(Depth, Flags); width = Width; height = Height; depth = Depth; pad = Pad; if ((depth == 12) || (depth == 15) || (depth == 16)) pitch = (width * 16 + Pad - 1) >> 3; else pitch = (width * depth + Pad - 1) >> 3; switch (Pad) { case 16: pitch &= ~1; break; case 32: pitch &= ~3; break; case 64: pitch &= ~7; break; case 128: pitch &= ~15; break; case 256: pitch &= ~31; break; default: break; } data = Data; validDisplay = FALSE; pixFlags = Flags; parentWin = Win; if ((pixFlags & WX_PIXFLAG_FASTDITHER) != 0) { pixFlags |= WX_PIXFLAG_DITHER; colour_matcher = &wxPixmap::findFastColour; } else { colour_matcher = &wxPixmap::findBestColour; } // If the depth changed the translation tables _must_ be updated if (lastDepth != Depth) { pixFlags &= ~WX_PIXFLAG_SAMEPALETTE; } if ((pixFlags & WX_PIXFLAG_SAMEPALETTE) == 0) { if ((Palette != NULL) && (Depth <= 8)) { palette = new wxColour[1<> 3) & ~3; if ((modeData = (char*)malloc(displayPitch*height*sizeof(char))) == NULL) { errorMemory(); return(-1); } #endif #ifdef wx_msw virtWidth = width; while (((displayPitch = virtWidth * useDepth) & 31) != 0) virtWidth++; displayPitch >>= 3; if ((modeData = (char*)malloc(displayPitch * height * sizeof(char))) == NULL) { errorMemory(); return -1; } #endif // *errorstr << "Allocated buffer of size " << width << '*' << height << ", " << displayPitch*height << endl; } #ifdef wx_msw bmDesc.bmType = 0; bmDesc.bmWidth = virtWidth; bmDesc.bmHeight = height; bmDesc.bmWidthBytes = displayPitch; bmDesc.bmPlanes = 1; bmDesc.bmBitsPixel = displayDepth; bmDesc.bmBits = (LPVOID)modeData; bitmap = CreateBitmapIndirect(&bmDesc); if (bitmap == (HBITMAP)0) { errorMemory(); return(-1); } // *errorstr << "bitmap handle = " << (long)bitmap << endl; #endif #ifdef wx_x // *errorstr << "Get Handle... " << endl; windowHandle = parentWin->GetXWindow(); // *errorstr << "windowHandle = " << windowHandle << endl; // Use visualInfo.depth rather than displayDepth (24bpp vs 32bpp!) xim = XCreateImage(display, visualInfo.visual, visualInfo.depth, ZPixmap, 0, modeData, width, height, displayPad, displayPitch); // Get parent window attributes to get colourmap XGetWindowAttributes(display, windowHandle, &xat); //cout << "window depth " << xat.depth << endl; xgcvals.function = GXcopy; myGC = XCreateGC(display, windowHandle, GCFunction, &xgcvals); #endif #ifdef wx_msw windowHandle = parentWin->GetHWND(); winDC = GetDC(windowHandle); srcDC = CreateCompatibleDC(winDC); //srcDC = CreateCompatibleDC(NULL); oldDCObject = SelectObject(srcDC, (HGDIOBJ)bitmap); #endif initColoursForMode(); // Now create the translation table if necessary (if depth, lastDepth > 8 we can use the // previous one. if (((depth != displayDepth) && (lastDepth <= 12)) || (depth <= 12)) { if ((pixFlags & WX_PIXFLAG_SAMEPALETTE) == 0) {buildTranslationTable();} } // In case the fast dither table has to be built, call function too... else if ((FastDitherTab == NULL) && ((pixFlags & WX_PIXFLAG_FASTDITHER) != 0) && (displayDepth < 15)) { buildTranslationTable(); } // In case the pixmap should be dithered: if (((pixFlags & WX_PIXFLAG_DITHER) != 0) && (depth <= 12) && (displayDepth <= 8)) { processPixmapPalette(); } return(0); } #ifdef wx_msw // Special Win hack void wxPixmap::win_translate_24_to_24(unsigned char *dest) { int i, j; unsigned char *b, *d, *bline, *dline; bline = (unsigned char*)data; dline = dest; for (i=0; i 0) *errorstr << "Can't translate from " << depth << " to " << displayDepth << endl; #endif } } validDisplay = TRUE; } // Ditherer to display modes with <= 8bpp. Otherwise use the simple translator. void wxPixmap::ditherToMode(void) { int status=0; unsigned char *dest = (unsigned char *)modeData; if ((data == NULL) || (modeData == NULL) || (displayDepth <= 0)) return; /*for (int i=0; i<(1<*pixdither1)(dest, displayPad); break; case 2: if (pixdither2 != NULL) (this->*pixdither2)(dest, displayPad); break; case 4: if (pixdither4 != NULL) (this->*pixdither4)(dest, displayPad); break; case 8: if (pixdither8 != NULL) (this->*pixdither8)(dest, displayPad); break; case 12: if (pixdither12 != NULL) (this->*pixdither12)(dest, displayPad); break; case 15: if (pixdither15 != NULL) (this->*pixdither15)(dest, displayPad); break; case 24: if (pixdither24 != NULL) (this->*pixdither24)(dest, displayPad); break; case 32: if (pixdither32 != NULL) (this->*pixdither32)(dest, displayPad); break; default: status = -1; break; } if ((busyCursorMode) && ((pixFlags & WX_PIXFLAG_FASTDITHER) == 0)) ::wxEndBusyCursor(); if (status < 0) { #if (DEBUG > 0) *errorstr << "Can't dither from " << depth << " to " << displayDepth << endl; #endif } } validDisplay = TRUE; } int wxPixmap::plotPixmap(int PosX, int PosY) { // *errorstr << "plotPixmap: parentWin=" << (long)parentWin << ", data=" << (long)data << ", modeData=" << (long)modeData << endl; if ((parentWin != NULL) && (data != NULL)) { if (parentWin->IsShown()) { // Do we have to do a colour translation? if (!validDisplay) { if (data != modeData) { if (((pixFlags & WX_PIXFLAG_DITHER) != 0) && (displayDepth <= 8)) {ditherToMode();} else if ((pixFlags & WX_PIXFLAG_TRANSLATE) != 0) {translateToMode();} } #ifdef wx_msw // I'd really like to avoid this but Windoze gets in the way SetBitmapBits(bitmap, displayPitch * height, modeData); #endif } #ifdef wx_x /*cout << "width = " << xim->width << ", pitch = " << xim->bytes_per_line << ", bpp = " << xim->bits_per_pixel << ", depth = " << xim->depth << ", pad = " << xim->bitmap_pad << endl; cout << "format = " << xim->format << ", byte_order = " << xim->byte_order << ", bitmap_unit = " << xim->bitmap_unit << ", bitmap_bit_order = " << xim->bitmap_bit_order << ", rmask = " << xim->red_mask << ", gmask = " << xim->green_mask << ", bmask = " << xim->blue_mask << endl;*/ XPutImage(display, windowHandle, myGC, xim, 0, 0, PosX, PosY, width, height); #endif #ifdef wx_msw if (BitBlt(winDC, PosX, PosY, width, height, srcDC, 0, 0, SRCCOPY) == 0) return -1; #endif } return 0; } else { errorGeneric("Window or image definition missing!"); } return -1; } void wxPixmap::invalidatePixmap(void) {validDisplay = FALSE;} /* * re-build the true-colour --> colourmapped table and the fast ditherer table * (in case another application modified a colour and the display goes wrong). */ void wxPixmap::refreshGlobalTables(void) { int newTables=0; if ((depth > 12) && (displayDepth <= 8)) { newTables |= 1; if (TrueTransTab != NULL) { delete [] TrueTransTab; TrueTransTab = NULL; TrueTransCount--; } } if ((pixFlags & WX_PIXFLAG_FASTDITHER) != 0) { newTables |= 2; if (FastDitherTab != NULL) { delete [] FastDitherTab; FastDitherTab = NULL; FastDitherCount--; } } if (newTables != 0) buildTranslationTable(); } /* * Display the busy mouse pointer when an operation takes longer (e.g. dithering)... */ bool wxPixmap::setBusyCursor(bool newMode) { bool oldMode = busyCursorMode; busyCursorMode = newMode; return oldMode; } // Finally compile the auto-generated ditherers #include "wx_pixmap_dither.cpp"