#pragma warning (disable:4800) #include "stdafx.h" #include "dibsection.hpp" #include "dibsurf.hpp" //lint !e537 #include #include //******************************************************************* // // DESCRIPTION:Implementation file for CDIBSurface class // // AUTHOR: Andrew Farrier // // SourceSafe Version: $Revision: 107 $ // //****************************************************************** std::vector *CDIBSurface::m_FreeDC = NULL; std::vector *CDIBSurface::m_AllDCs = NULL; int CDIBSurface::m_DCStackRefCount = 0; int g_NumDibSurf = 0; bool CDIBSurface::Blt (int x,int y,int width,int height,const CDIBSurface *src,int srcx,int srcy,DWORD rop) { ASSERT (m_DIBData); ASSERT (src); ASSERT (IsValid ()); if(!src) return false; if (rop == SRCCOPY && src->GetBitDepth() == GetBitDepth()) { // use non-GDI versions if(src->UseMask () && src->Mask()) return MaskBltNonGDI (x,y,width,height,*src,srcx,srcy); else return BltNonGDI (x,y,width,height,*src,srcx,srcy); } else if(src->UseMask ()) return MaskBlt (x,y,width,height,src,srcx,srcy); else { HDC dc1,dc2; bool toret; dc1 = GetDC (); dc2 = src->GetDC (); if (!(dc1 && dc2)) { if (dc1) ReleaseDC (dc1); if (dc2) src->ReleaseDC (dc2); return false; } toret = (::BitBlt (dc1,x,y,width,height,dc2,srcx,srcy,rop) == TRUE); ReleaseDC (dc1); src->ReleaseDC (dc2); return toret; } } void CDIBSurface::UseDC (HDC tempdc) { ASSERT (m_DIBData); if (m_DIBData->m_SelectedDC == tempdc) { m_DIBData->m_SelectedDCRefCount++; return; } HBITMAP bmap = GetBitmap(); ASSERT (bmap); m_DIBData->m_OldBitmap = (HBITMAP) SelectObject (tempdc,bmap); m_DIBData->m_SelectedDC = tempdc; m_DIBData->m_SelectedDCRefCount=1; m_DIBData->m_AllocedDC = false; return ; } HDC CDIBSurface::GetDC (void) { HDC tempdc; HBITMAP tempbits; ASSERT (m_DIBData); if (m_DIBData->m_SelectedDC) { m_DIBData->m_SelectedDCRefCount++; return m_DIBData->m_SelectedDC; } if (m_FreeDC->size () == 0) { tempdc = CreateCompatibleDC (NULL); ASSERT (tempdc); tempbits = (HBITMAP) GetCurrentObject (tempdc,OBJ_BITMAP); SelectObject (tempdc,tempbits); m_AllDCs->push_back (DCData (tempdc,tempbits)); m_FreeDC->push_back (tempdc); } tempdc = m_FreeDC->back (); m_FreeDC->pop_back (); // asking for a DC only makes sense if you have a bitmap selected in it GetBitmap(); ASSERT (m_DIBData->m_BackBits); if (m_DIBData->m_BackBits) if (!SelectObject (tempdc,m_DIBData->m_BackBits)) { m_FreeDC->push_back (tempdc); return NULL; } m_DIBData->m_SelectedDC = tempdc; m_DIBData->m_SelectedDCRefCount=1; m_DIBData->m_AllocedDC = true; return tempdc; } HDC CDIBSurface::GetDC (void) const { HDC tempdc; HBITMAP tempbits; ASSERT (m_DIBData); if (m_DIBData->m_SelectedDC) { m_DIBData->m_SelectedDCRefCount++; return m_DIBData->m_SelectedDC; } if (m_FreeDC->size () == 0) { tempdc = CreateCompatibleDC (NULL); ASSERT (tempdc); tempbits = (HBITMAP) GetCurrentObject (tempdc,OBJ_BITMAP); SelectObject (tempdc,tempbits); m_AllDCs->push_back (DCData (tempdc,tempbits)); m_FreeDC->push_back (tempdc); } tempdc = m_FreeDC->back(); m_FreeDC->pop_back (); // asking for a DC only makes sense if you have a bitmap selected in it GetBitmap(); ASSERT (m_DIBData->m_BackBits); if (m_DIBData->m_BackBits) if (!SelectObject (tempdc,m_DIBData->m_BackBits)) { m_FreeDC->push_back (tempdc); return NULL; } m_DIBData->m_SelectedDC = tempdc; m_DIBData->m_SelectedDCRefCount=1; m_DIBData->m_AllocedDC = true; return tempdc; } void CDIBSurface::ReleaseDC (HDC dc) const { std::vector::iterator iter; ASSERT (dc); ASSERT (m_DIBData); m_DIBData->m_SelectedDCRefCount--; if (m_DIBData->m_SelectedDCRefCount) return; if (m_DIBData->m_AllocedDC) { iter = m_AllDCs->begin (); while(iter != m_AllDCs->end ()) { if(iter->thedc == dc) { HBITMAP temp = (HBITMAP) GetCurrentObject (dc,OBJ_BITMAP); if (temp != iter->oldbits) SelectObject (dc,iter->oldbits); break; } iter++; } } else { SelectObject (dc,m_DIBData->m_OldBitmap); } m_DIBData->m_SelectedDC = NULL; if (m_DIBData->m_AllocedDC) m_FreeDC->push_back (dc); } CDIBSurface::~CDIBSurface (void) { if(m_RefCount) { Release (); } m_RefCount = NULL; m_DIBData = NULL; } CDIBSurface::CDIBSurface (const CDIBSurface& p) { ASSERT (p.m_RefCount); ASSERT (p.m_DIBData); m_RefCount = p.m_RefCount; m_DIBData = p.m_DIBData; AddRef (); } CDIBSurface& CDIBSurface::operator= (const CDIBSurface& p) { ASSERT (p.m_RefCount); ASSERT (p.m_DIBData); if(m_DIBData) { Release (); } m_RefCount = p.m_RefCount; m_DIBData = p.m_DIBData; AddRef (); return *this; } bool CDIBSurface::SplitRef (void) { DIBData *olddata; ASSERT (m_DIBData); ASSERT (m_RefCount); if(*m_RefCount < 2) return true; olddata = m_DIBData; //m_RefCount--; Release (); // *m_RefCount -= 1; m_RefCount = new UINT; *m_RefCount = 0; AddRef (); m_DIBData = new DIBData; ClearData (); if(!Create (olddata->m_Width,olddata->m_Height,olddata->m_BitDepth)) return false; UINT tocopy; if(m_DIBData->m_Pitch == olddata->m_Pitch) { tocopy = abs (m_DIBData->m_Pitch) * m_DIBData->m_Height; memcpy (m_DIBData->m_Data,olddata->m_Data,tocopy); } else { int y; unsigned char *dest,*src; dest = m_DIBData->m_UpperLeft; src = olddata->m_UpperLeft; for(y=0;ym_Height;y++) { memcpy (dest,src,m_DIBData->m_Pitch); dest += m_DIBData->m_Pitch; src += olddata->m_Pitch; } } if(olddata->m_Mask) { if(!CalcMask ()) return false; HDC dc1,dc2; dc1 = m_DIBData->m_Mask->GetDC (); dc2 = olddata->m_Mask->GetDC (); BitBlt (dc1,0,0,m_DIBData->m_Width,m_DIBData->m_Height,dc2,0,0,SRCCOPY); m_DIBData->m_Mask->ReleaseDC (dc1); olddata->m_Mask->ReleaseDC (dc2); } m_DIBData->m_UseMask = olddata->m_UseMask; return true; } CDIBSurface::CDIBSurface (void) { m_RefCount = new UINT; ASSERT (m_RefCount); *m_RefCount = 0; AddRef (); m_DIBData = new DIBData; ClearData (); } unsigned char *CDIBSurface::GetMem( int x, int y ) { ASSERT( m_DIBData ); unsigned char *pBits = NULL; if( 0 <= x && GetWidth() > x && 0 <= y && GetHeight() > y && m_DIBData->m_Data && GdiFlush() ) { int nPixelSize = GetBitDepth() >> 3; int nPitch = GetPitch(); pBits = m_DIBData->m_Data; if( 0 > nPitch ) pBits -= nPitch * (GetHeight() - y - 1); else pBits += nPitch * y; pBits += nPixelSize * x; } return( pBits ); } //**************************************************************** // // Function Name: CDIBSurface::CDIBSurface // // Description: Constructor for CDIBSurface. Empties the fields and calls Create // // Returns:nothing // //**************************************************************** CDIBSurface::CDIBSurface (UINT Width,UINT Height,UINT BitDepth) { if(!m_DCStackRefCount) { m_AllDCs = new std::vector; m_FreeDC = new std::vector; } m_DCStackRefCount++; m_RefCount = new UINT; ASSERT (m_RefCount); *m_RefCount = 0; AddRef (); m_DIBData = new DIBData; ASSERT (m_DIBData); ClearData (); if(!Create (Width,Height,BitDepth)) { throw std::runtime_error ("unable to create a blank CDIBSurface"); } } //**************************************************************** // // Function Name: CDIBSurface::Create // // Description: creates a new DIBSection of the specified size // If already present of the right size then just clear to black // If wrong size then destroy and create a new one // // Returns: true if section was created // //**************************************************************** bool CDIBSurface::Create (UINT Width,UINT Height,UINT BitDepth) { RECT arect; ASSERT (m_DIBData); // if we already have a surface with the current size then just repaint it to black if((m_DIBData->m_Data) && (Width == m_DIBData->m_Width) && (Height == m_DIBData->m_Height) && (BitDepth == m_DIBData->m_BitDepth)) { arect.left = 0; arect.top = 0; arect.right = (long) m_DIBData->m_Width; arect.bottom = (long) m_DIBData->m_Height; HDC dc = GetDC (); FillRect (dc,&arect,(HBRUSH) GetStockObject (BLACK_BRUSH)); ReleaseDC (dc); return true; } // delete the current surface if we have one if(m_DIBData->m_Data) Destroy (); g_NumDibSurf++; if((Width == 0) || (Height == 0) || (BitDepth == 0)) return true; m_DIBData->m_Width = Width; m_DIBData->m_Height = Height; m_DIBData->m_BitDepth = BitDepth; // when we create a DIB section we need to setup a BITMAPINFO structure to pass to CreateDIBSection // this structure hold all the data about out buffer switch(m_DIBData->m_BitDepth) { case 24: m_DIBData->m_Pitch = (int) m_DIBData->m_Width*3; m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03); break; case 16: m_DIBData->m_Pitch = (int) m_DIBData->m_Width*2; m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03); break; case 8: m_DIBData->m_Pitch = (int) m_DIBData->m_Width; m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03); break; case 4: m_DIBData->m_Pitch = (int) ((m_DIBData->m_Width+1)>>1); m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03); break; case 1: m_DIBData->m_Pitch = (int) ((m_DIBData->m_Width+7)>>3); m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03); break; default: OutputDebugString ("Unsupported Bitdepth for DibSections"); return false; } // create a DC to use the DIB section in #if 0 m_DIBData->m_BackDC = CreateCompatibleDC (NULL); ASSERT(NULL != m_DIBData->m_BackDC); if (NULL == m_DIBData->m_BackDC) { Destroy (); return false; } #endif m_DIBData->m_BackBits = NULL; // select the dib section into the DC from above // m_DIBData->m_OldBits = (HBITMAP) SelectObject (m_DIBData->m_BackDC,m_DIBData->m_BackBits); m_DIBData->m_Data = new BYTE [abs (m_DIBData->m_Pitch) * m_DIBData->m_Height]; if (!m_DIBData->m_Data) { Destroy(); return false; } memset (m_DIBData->m_Data,0,abs (m_DIBData->m_Pitch) * m_DIBData->m_Height); if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1))); else m_DIBData->m_UpperLeft = m_DIBData->m_Data; // init the whole surface to black arect.left = 0; arect.top = 0; arect.right = (long) m_DIBData->m_Width; arect.bottom = (long) m_DIBData->m_Height; // HDC testdc = CreateCompatibleDC (NULL); // HBITMAP testbit = (HBITMAP) SelectObject (testdc,m_DIBData->m_BackBits); // dc = GetDC (); // FillRect (dc,&arect,(HBRUSH) GetStockObject (BLACK_BRUSH)); // ReleaseDC (dc); // SelectObject (testdc,testbit); // DeleteDC (testdc); return true; } //**************************************************************** // // Function Name: CDIBSurface::Destroy // // Description: clean up after ourselves. // // Returns: nothing // //**************************************************************** void CDIBSurface::Destroy (void) { ASSERT (m_DIBData); if(!m_DIBData->m_Data) return; g_NumDibSurf--; // select the old bitmap back into our DC then delete the DC // SelectObject (m_DIBData->m_BackDC,m_DIBData->m_OldBits); // DeleteDC (m_DIBData->m_BackDC); // m_DIBData->m_BackDC = NULL; // m_DIBData->m_OldBits = NULL; if (m_DIBData->m_BackBits) // if you have the bits, then the data is from the dibsection DeleteObject (m_DIBData->m_BackBits); else delete [] m_DIBData->m_Data; // otherwise the data was new'd m_DIBData->m_BackBits = NULL; m_DIBData->m_Width = m_DIBData->m_Height = m_DIBData->m_BitDepth = m_DIBData->m_Pitch = 0; m_DIBData->m_Data = NULL; m_DIBData->m_UpperLeft = NULL; // select the old mask bitmap back into our DC then delete the DC m_DIBData->m_UseMask = false; delete m_DIBData->m_Mask; m_DIBData->m_Mask = NULL; } //**************************************************************** // // Function Name: CDIBSurface::Fill // // Description: Will fill the rectangle passed in with the color requested // // Returns: true is successful // //**************************************************************** bool CDIBSurface::Fill (const CRect *therect,const COLORREF colorref) { HBRUSH stupid; HDC dc; bool fred; CRect temp; ASSERT (m_DIBData); ASSERT (therect); if(!therect) return false; temp = *therect; temp.right += 1; temp.bottom += 1; stupid = CreateSolidBrush (colorref); dc = GetDC (); #pragma warning (disable : 4800) fred = FillRect (dc,therect,stupid); ReleaseDC (dc); DeleteObject (stupid); return fred; } //**************************************************************** // // Function Name: CDIBSurface::FillHatchBrush // // Description: Will fill the rectangle passed in with the color requested // // Returns: true is successful // //**************************************************************** bool CDIBSurface::FillHatchBrush (const CRect *therect, int stockHatchBrushStyle, const COLORREF colorref) { HBRUSH stupid,oldBrush; HDC dc; bool fred; CRect temp; ASSERT (m_DIBData); ASSERT (therect); if(!therect) return false; temp = *therect; temp.right += 1; temp.bottom += 1; stupid = CreateHatchBrush (stockHatchBrushStyle,colorref); dc = GetDC (); oldBrush = (HBRUSH)SelectObject(dc,stupid); #pragma warning (disable : 4800) fred = PatBlt(dc, therect->left, therect->top,therect->right, therect->bottom, 0x00A000C9); SelectObject(dc,oldBrush); ReleaseDC (dc); DeleteObject (stupid); return fred; } //**************************************************************** // // Function Name: CDIBSurface::GetColor // // Description: will get the current color at the location x,y // // Returns: current color as a COLORREF // //**************************************************************** COLORREF CDIBSurface::GetColor (UINT x,UINT y) const { DWORD value; COLORREF toret; RGBQUAD temp; int red,blue,green; HDC dc; ASSERT (m_DIBData); value = GetValue (x,y); switch(m_DIBData->m_BitDepth) { case 1: case 4: case 8: dc = GetDC (); if(GetDIBColorTable (dc,value,1,&temp) == 0) { ReleaseDC (dc); return RGB (0,0,0); } ReleaseDC (dc); toret = RGBQUADtoCOLORREF (temp); break; case 16: red = value >> 7; green = value >> 2; blue = (int) (value << 3); blue &= 0xf8; green &= 0xf8; red &= 0xf8; toret = (blue<<16) + (green<<8) + red; break; case 24: toret = (value); break; default: ASSERT (false); toret = false; break; } return toret; } void CDIBSurface::SetColor (UINT x,UINT y,COLORREF color) { int red,green,blue; unsigned char *mem; ASSERT (m_DIBData); mem = GetMem (); mem += GetLocation (x,y); switch(m_DIBData->m_BitDepth) { case 16: unsigned short *mem16; mem16 = (unsigned short *) mem; red = color&0xff; green = (color>>8) & 0xff; blue = (color>>16) & 0xff; red >>= 3; green >>= 3; blue >>= 3; (*mem16) = (red<<10)+(green<<5)+blue; break; case 24: red = color&0xff; green = (color>>8) & 0xff; blue = (color>>16) & 0xff; (*mem) = blue; mem++; (*mem) = green; mem++; (*mem) = red; break; default: ASSERT (false); break; } } void CDIBSurface::SetColor( COLORREF color ) { Fill( 0, 0, m_DIBData->m_Width, m_DIBData->m_Height, color ); } //**************************************************************** // // Function Name: CDIBSurface::MaskBlt // // Description: will use src and mask to perform a mask blt to this DIBSurface // white is tranparent, black is opaque // // Returns: true if successful // //**************************************************************** bool CDIBSurface::MaskBlt (const int x,const int y,const int width,const int height,const HDC src,const HDC mask,const int srcx,const int srcy) { ASSERT (m_DIBData); ASSERT (src); ASSERT (mask); if(!src) return false; if(!mask) return false; HDC dc = GetDC (); SetBkColor(dc, RGB(255, 255, 255)); // 1s --> 0xFFFFFF SetTextColor(dc, RGB(0, 0, 0)); // 0s --> 0x000000 BitBlt(dc, x, y, width, height, src, srcx, srcy, SRCINVERT); BitBlt(dc, x, y, width, height, mask, srcx, srcy, SRCAND); BitBlt(dc, x, y, width, height, src, srcx, srcy, SRCINVERT); ReleaseDC (dc); return true; } //**************************************************************** // // Function Name: CDIBSurface::MaskBlt // // Description: will perform a mask blt using the data from src // // Returns: true if successful // //**************************************************************** bool CDIBSurface::MaskBlt (const int x,const int y,const int width,const int height,const CDIBSurface *src,const int srcx,const int srcy) { ASSERT (m_DIBData); ASSERT (src); ASSERT (src->m_DIBData); if(src == NULL) return false; ASSERT (src->UseMask ()); if(!src->UseMask ()) return false; HDC dc = GetDC (); SetBkColor(dc, RGB(255, 255, 255)); // 1s --> 0xFFFFFF SetTextColor(dc, RGB(0, 0, 0)); // 0s --> 0x000000 // BitBlt(m_BackDC, x, y, width, height, src->m_BackDC, srcx, srcy, SRCINVERT); HDC dc2,dc3; dc2 = src->m_DIBData->m_Mask->GetDC (); dc3 = src->GetDC (); BitBlt(dc, x, y, width, height, dc2, srcx, srcy, SRCAND); BitBlt(dc, x, y, width, height, dc3, srcx, srcy, SRCPAINT); src->m_DIBData->m_Mask->ReleaseDC (dc2); src->ReleaseDC (dc3); ReleaseDC (dc); return true; } bool CDIBSurface::RotateBlt( int left, int top, int right, int bottom, const CDIBSurface& src, int x, int y, int ang ) { #if 1 // This only works between similarly-depth'ed surfaces. if( GetBitDepth() != src.GetBitDepth() ) return( Blt( CRect( left, top, right, bottom ), src, CPoint( x, y ) ) ); // return( false ); // Degenerate case if( 0 == ang ) return( Blt( CRect( left, top, right, bottom ), src, CPoint( x, y ) ) ); int nDstW = GetWidth(), nDstH = GetHeight(); if( nDstW <= left || nDstH < top || 0 > right || 0 > bottom ) return( true ); int nSrcW = src.GetWidth(), nSrcH = src.GetHeight(); int nSrcP = src.GetPitch(), nDstP = GetPitch(); if( 0 > left ) { x -= left; left = 0; } if( 0 > top ) { y -= top; top = 0; } if( nDstW < right ) right = nDstW; if( nDstH < bottom ) bottom = nDstH; nDstW = right - left; nDstH = bottom - top; if( x + nDstW > nSrcW ) { nDstW = nSrcW - x; right = left + nDstW; } if( y + nDstH > nSrcH ) { nDstH = nSrcH - y; bottom = top + nDstH; } if( nDstW != nDstH ) return( false ); const BYTE *pSBits = src.GetMem(); if( 0 > nSrcP ) pSBits -= nSrcP * (nSrcH - 1); BYTE *pDBits = GetMem(); if( 0 > nDstP ) pDBits -= nDstP * (nDstH - 1); int nOffset, nPixelSize = GetBitDepth() >> 3; int nPixelStride, nSrcStride, nDstStride = nDstP - nPixelSize * nDstW; switch( ang ) { #if 0 // Handled by short-circuit case above case 0: nPixelStride = nPixelSize; nSrcStride = nSrcP - nDstW * nPixelSize; nOffset = 0; break; #endif case 90: nPixelStride = -nSrcP; nSrcStride = nDstH * nSrcP + nPixelSize; nOffset = nSrcP * (nDstH - 1); break; case 180: nPixelStride = -nPixelSize; nSrcStride = nPixelSize * nDstW - nSrcP; nOffset = nSrcP * (nDstH - 1) + nPixelSize * (nDstW - 1); break; case 270: nPixelStride = nSrcP; nSrcStride = -(nSrcP * nDstH) - nPixelSize; nOffset = (nDstW - 1) * nPixelSize; break; default: return( false ); } pDBits += nDstP * top + nPixelSize * left; pSBits += nSrcP * y + nPixelSize * x + nOffset; while( 0 < nDstH-- ) { for( int i = 0; i < nDstW; i++ ) { for( int j = 0; j < nPixelSize; j++ ) *pDBits++ = pSBits[ j ]; pSBits += nPixelStride; } pDBits += nDstStride; pSBits += nSrcStride; } return( true ); #else // FIX implement return( Blt( loc, src, srcloc ) ); #endif } bool CDIBSurface::TransparentBlt( int left, int top, int right, int bottom, const CDIBSurface& src, int x, int y, const COLORREF bgClr ) { #if 1 // This only works between similarly-depth'ed surfaces. if( GetBitDepth() != src.GetBitDepth() ) return( Blt( CRect( left, top, right, bottom ), src, CPoint( x, y ) ) ); // return( false ); int nDstW = GetWidth(), nDstH = GetHeight(); if( nDstW <= left || nDstH < top || 0 > right || 0 > bottom ) return( true ); int nSrcW = src.GetWidth(), nSrcH = src.GetHeight(); int nSrcP = src.GetPitch(), nDstP = GetPitch(); if( 0 > left ) { x -= left; left = 0; } if( 0 > top ) { y -= top; top = 0; } if( nDstW < right ) right = nDstW; if( nDstH < bottom ) bottom = nDstH; nDstW = right - left; nDstH = bottom - top; if( x + nDstW > nSrcW ) { nDstW = nSrcW - x; right = left + nDstW; } if( y + nDstH > nSrcH ) { nDstH = nSrcH - y; bottom = top + nDstH; } const BYTE *pSBits = src.GetMem(); if( 0 > nSrcP ) pSBits -= nSrcP * (nSrcH - 1); BYTE *pDBits = GetMem(); if( 0 > nDstP ) pDBits -= nDstP * (nDstH - 1); switch( GetBitDepth() ) { case 16: { pDBits += nDstP * top + left * sizeof( WORD ); pSBits += nSrcP * y + x * sizeof( WORD ); const WORD *pS = (const WORD *)pSBits; WORD *pD = (WORD *)pDBits; WORD crClr = ConvertColorToWord( bgClr ); int nSrcS = (nSrcP - nDstW * sizeof( WORD )) / sizeof( WORD ); int nDstS = (nDstP - nDstW * sizeof( WORD )) / sizeof( WORD ); while( 0 < nDstH-- ) { for( int i = nDstW; i; i-- ) { if( *pS != crClr ) *pD = *pS; pD++; pS++; } pD += nDstS; pS += nSrcS; } break; } case 24: { pDBits += nDstP * top + left * sizeof( RGBTRIPLE ); pSBits += nSrcP * y + x * sizeof( RGBTRIPLE ); const RGBTRIPLE *pS = (const RGBTRIPLE *)pSBits; RGBTRIPLE *pD = (RGBTRIPLE *)pDBits; // RGBTRIPLE crClr = ConvertColorToTriple( bgClr ); int nSrcS = (nSrcP - nDstW * sizeof( RGBTRIPLE )) / sizeof( RGBTRIPLE ); int nDstS = (nDstP - nDstW * sizeof( RGBTRIPLE )) / sizeof( RGBTRIPLE ); while( 0 < nDstH-- ) { for( int i = nDstW; i; i-- ) { if( memcmp( pS, pD, 3 ) ) *pD = *pS; pD++; pS++; } pD += nDstS; pS += nSrcS; } break; } case 32: { pDBits += nDstP * top + left * sizeof( DWORD ); pSBits += nSrcP * y + x * sizeof( DWORD ); const DWORD *pS = (const DWORD *)pSBits; DWORD *pD = (DWORD *)pDBits; DWORD crClr = ConvertColorToLong( bgClr ); int nSrcS = (nSrcP - nDstW * sizeof( DWORD )) / sizeof( DWORD ); int nDstS = (nDstP - nDstW * sizeof( DWORD )) / sizeof( DWORD ); while( 0 < nDstH-- ) { for( int i = nDstW; i; i-- ) { if( (0x00ffffff & *pS) != crClr ) *pD = *pS; pD++; pS++; } pD += nDstS; pS += nSrcS; } break; } } return( true ); #else // FIX implement Blt( loc, src, srcloc ); return( true ); #endif } //**************************************************************** // // Function Name: CDIBSurface::CalcMask // // Description: will create a mask for the DIBSurface based on the color passed in // all pixels that are the same color as colorref are considered transparent // // Returns: true if successful // //**************************************************************** bool CDIBSurface::CalcMask (COLORREF colorref) { if(!CalcMask ()) return false; switch(m_DIBData->m_BitDepth) { case 1: m_DIBData->m_UseMask = Create1BitMask (colorref); break; case 4: m_DIBData->m_UseMask = Create4BitMask (colorref); break; case 8: m_DIBData->m_UseMask = Create8BitMask (colorref); break; case 16: m_DIBData->m_UseMask = Create16BitMask (colorref); break; case 24: m_DIBData->m_UseMask = Create24BitMask (colorref); break; default: ASSERT (false); break; } if(!m_DIBData->m_UseMask) { delete m_DIBData->m_Mask; m_DIBData->m_Mask = NULL; } return m_DIBData->m_UseMask; } //**************************************************************** // // Function Name: CDIBSurface::CalcMask // // Description: will create a mask for the DIBSurface the initial image is all opaque // // Returns: true if successful // //**************************************************************** bool CDIBSurface::CalcMask (void) { ASSERT (m_DIBData); delete m_DIBData->m_Mask; m_DIBData->m_Mask = NULL; m_DIBData->m_Mask = new CDIBSurface (); if(!m_DIBData->m_Mask) return false; if(!m_DIBData->m_Mask->Create (m_DIBData->m_Width,m_DIBData->m_Height,1)) //lint !e539 huh { delete m_DIBData->m_Mask; m_DIBData->m_Mask = NULL; return false; } m_DIBData->m_UseMask = true; return true; } bool CDIBSurface::DestroyMask (void) { ASSERT (m_DIBData); delete m_DIBData->m_Mask; m_DIBData->m_Mask = NULL; m_DIBData->m_UseMask = false; return true; } int CDIBSurface::FloodFill (const CPoint& start,const COLORREF color) { COLORREF srccolor,intcolor; CPoint temp; std::stack data; int count=0; ASSERT (m_DIBData); if(m_DIBData->m_BitDepth == 24) return FloodFill24 (start,color); intcolor = color; if (m_DIBData->m_BitDepth == 16) intcolor &= 0x00f8f8f8; srccolor = GetColor (start.x,start.y); if(srccolor == intcolor) return 0; data.push (start); while(!data.empty ()) { temp = data.top (); data.pop (); if(GetColor (temp.x,temp.y)==srccolor) { SetColor (temp.x,temp.y,color); count++; if(temp.y != 0) data.push (CPoint(temp.x,temp.y-1)); if(temp.y != (m_DIBData->m_Height-1)) data.push (CPoint(temp.x,temp.y+1)); if(temp.x != 0) data.push (CPoint(temp.x-1,temp.y)); if(temp.x != (m_DIBData->m_Width-1)) data.push (CPoint(temp.x+1,temp.y)); } } return count; } // assume the alpha is an eight bit surface where the indexs are really the alpha values // 0 in the alpha means to use leave the dest alone // 255 in the alpha means to be 100% from the source. bool CDIBSurface::AlphaBlt (const int x,const int y,const int width,const int height,const CDIBSurface *src,const CDIBSurface *alpha,const int srcx,const int srcy,const int alphasrcx,const int alphasrcy) { ASSERT (m_DIBData); ASSERT (src->m_DIBData); ASSERT (alpha->m_DIBData); ASSERT (alpha->GetBitDepth () == 8); ASSERT ((GetBitDepth()==16)||(GetBitDepth()==24)); ASSERT ((src->GetBitDepth()==16)||(src->GetBitDepth()==24)); ASSERT (GetBitDepth() == src->GetBitDepth ()); ASSERT ((x+width) <= GetWidth ()); ASSERT ((srcx+width) <= src->GetWidth ()); ASSERT ((y+height) <= GetHeight ()); ASSERT ((srcy+height) <= src->GetHeight ()); ASSERT (x >= 0); ASSERT (y >= 0); ASSERT (width >= 0); ASSERT (height >= 0); ASSERT (srcx >= 0); ASSERT (srcy >= 0); int asrcx = (alphasrcx < 0) ? srcx : alphasrcx; int asrcy = (alphasrcy < 0) ? srcy : alphasrcy; ASSERT ((asrcx+width) <= alpha->GetWidth ()); ASSERT ((asrcy+height) <= alpha->GetHeight ()); switch(GetBitDepth ()) { case 16: return AlphaBlt16 (x,y,width,height,src,alpha,srcx,srcy,asrcx,asrcy); break; case 24: return AlphaBlt24 (x,y,width,height,src,alpha,srcx,srcy,asrcx,asrcy); break; default: ASSERT (false); break; } return false; } bool CDIBSurface::ColorBlt (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy,COLORREF color,bool addred,bool addgreen,bool addblue,CDIBSurface *altmask) { ASSERT (m_DIBData); ASSERT (src->m_DIBData); ASSERT ((GetBitDepth()==16)||(GetBitDepth()==24)); ASSERT (GetBitDepth() == src->GetBitDepth ()); ASSERT ((src!=this) || ((srcx==x) && (srcy==y))); ASSERT ((x+width) <= GetWidth ()); ASSERT ((srcx+width) <= src->GetWidth ()); ASSERT ((y+height) <= GetHeight ()); ASSERT ((srcy+height) <= src->GetHeight ()); ASSERT (x >= 0); ASSERT (y >= 0); ASSERT (width >= 0); ASSERT (height >= 0); ASSERT (srcx >= 0); ASSERT (srcy >= 0); switch(GetBitDepth ()) { case 16: return ColorBlt16 (x,y,width,height,src,srcx,srcy,color,addred,addgreen,addblue,altmask); break; case 24: return ColorBlt24 (x,y,width,height,src,srcx,srcy,color,addred,addgreen,addblue,altmask); break; default: ASSERT (false); break; } return false; } bool CDIBSurface::GrayBlt (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy, CDIBSurface *altmask) { ASSERT (m_DIBData); ASSERT (src->m_DIBData); ASSERT ((GetBitDepth()==16)||(GetBitDepth()==24)); ASSERT (GetBitDepth() == src->GetBitDepth ()); ASSERT ((src!=this) || ((srcx==x) && (srcy==y))); ASSERT ((x+width) <= GetWidth ()); ASSERT ((srcx+width) <= src->GetWidth ()); ASSERT ((y+height) <= GetHeight ()); ASSERT ((srcy+height) <= src->GetHeight ()); ASSERT (x >= 0); ASSERT (y >= 0); ASSERT (width >= 0); ASSERT (height >= 0); ASSERT (srcx >= 0); ASSERT (srcy >= 0); switch(GetBitDepth ()) { case 16: return GrayBlt16 (x,y,width,height,src,srcx,srcy,altmask); break; case 24: return GrayBlt24 (x,y,width,height,src,srcx,srcy,altmask); break; default: ASSERT (false); break; } return false; } bool CDIBSurface::MultBlt (const int x,const int y,const int width,const int height,const CDIBSurface* src,const int srcx,const int srcy,const float red,const float green,const float blue,CDIBSurface *altmask) { ASSERT (m_DIBData); ASSERT (src->m_DIBData); ASSERT ((GetBitDepth()==16)||(GetBitDepth()==24)); ASSERT (GetBitDepth() == src->GetBitDepth ()); ASSERT ((src!=this) || ((srcx==x) && (srcy==y))); int nWidth = GetWidth(), nHeight = GetHeight(); int l = x, t = y, w = width, h = height; if( 0 > l ) { w += l; l = 0; } if( 0 > t ) { h += t; t = 0; } if( nWidth < l + w ) w = nWidth - l; if( nHeight < t + h ) h = nHeight - t; ASSERT (w >= 0); ASSERT (h >= 0); ASSERT ((srcx+w) <= src->GetWidth ()); ASSERT ((srcy+h) <= src->GetHeight ()); ASSERT (srcx >= 0); ASSERT (srcy >= 0); // ASSERT ((x+width) <= GetWidth ()); // ASSERT ((y+height) <= GetHeight ()); // ASSERT (x >= 0); // ASSERT (y >= 0); switch(GetBitDepth ()) { case 16: return MultBlt16 (l,t,w,h,src,srcx,srcy,red,green,blue,altmask); break; case 24: return MultBlt24 (l,t,w,h,src,srcx,srcy,red,green,blue,altmask); break; default: ASSERT (false); break; } return false; } //**************************************************************** // // Function Name: MaskBlt // // Description: will use src and mask to perform a mask blt to this DIBSurface // white is tranparent, black is opaque // // Returns: true if successful // //**************************************************************** bool MaskBlt (HDC dest,const int x,const int y,const int width,const int height,const HDC src,const HDC mask,const int srcx,const int srcy,const int maskx,const int masky) { ASSERT (src); ASSERT (mask); if((!src) || (!mask)) return false; SetBkColor(dest, RGB(255, 255, 255)); // 1s --> 0xFFFFFF SetTextColor(dest, RGB(0, 0, 0)); // 0s --> 0x000000 BitBlt(dest, x, y, width, height, src, srcx, srcy, SRCINVERT); BitBlt(dest, x, y, width, height, mask, maskx, masky, SRCAND); BitBlt(dest, x, y, width, height, src, srcx, srcy, SRCINVERT); return true; } bool MaskBlt (HDC dest,const int x,const int y,const int width,const int height,const HDC src,const HDC mask,const int srcx,const int srcy) { ASSERT (dest); ASSERT (src); ASSERT (mask); if((!src) || (!mask)) return false; SetBkColor(dest, RGB(255, 255, 255)); // 1s --> 0xFFFFFF SetTextColor(dest, RGB(0, 0, 0)); // 0s --> 0x000000 BitBlt(dest, x, y, width, height, src, srcx, srcy, SRCINVERT); BitBlt(dest, x, y, width, height, mask, srcx, srcy, SRCAND); BitBlt(dest, x, y, width, height, src, srcx, srcy, SRCINVERT); return true; } //**************************************************************** // // Function Name: MaskBlt // // Description: will perform a mask blt using the data from src // // Returns: true if successful // //**************************************************************** bool MaskBlt (HDC dest,const int x,const int y,const int width,const int height,const CDIBSurface *src,const int srcx,const int srcy) { ASSERT (dest); ASSERT (src); // ASSERT (src->UseMask ()); if(!src) return false; if (src->UseMask ()) { SetBkColor(dest, RGB(255, 255, 255)); // 1s --> 0xFFFFFF SetTextColor(dest, RGB(0, 0, 0)); // 0s --> 0x000000 HDC tmphdc; /* tmphdc = src->GetDC (); BitBlt(dest, x, y, width, height, tmphdc, srcx, srcy, SRCINVERT); src->ReleaseDC(tmphdc); */ tmphdc = src->Mask ()->GetDC (); BitBlt(dest, x, y, width, height, tmphdc, srcx, srcy, SRCAND); src->Mask ()->ReleaseDC(tmphdc); tmphdc = src->GetDC (); BitBlt(dest, x, y, width, height, tmphdc, srcx, srcy, SRCPAINT); src->ReleaseDC(tmphdc); } else { HDC tmphdc; tmphdc = src->GetDC (); BitBlt(dest, x, y, width, height, tmphdc, srcx, srcy, SRCCOPY); src->ReleaseDC(tmphdc); } return true; } bool CDIBSurface::CalcMask (const std::vector& colors) { std::vector::const_iterator iter; UINT x,y; COLORREF curcolor; COLORREF curmask; ASSERT (m_DIBData); if(!CalcMask ()) return false; ASSERT (m_DIBData->m_Mask); if(!m_DIBData->m_Mask) return false; iter = colors.begin (); while(iter != colors.end ()) { curmask = (*iter); for(y=0;ym_Height;y++) { for(x=0;xm_Width;x++) { curcolor = GetColor (x,y); if(curcolor == curmask) m_DIBData->m_Mask->SetColor (x,y,RGB (255,255,255)); } } iter++; } for(y=0;ym_Height;y++) { for(x=0;xm_Width;x++) { curcolor = m_DIBData->m_Mask->GetColor (x,y); if(curcolor == RGB (255,255,255)) SetColor (x,y,RGB (0,0,0)); } } return true; } bool CDIBSurface::ConvertBitDepth (int newdepth) { CDIBSurface temp; ASSERT (m_DIBData); if (m_DIBData->m_BitDepth == newdepth) return true; if((m_DIBData->m_BitDepth == 24) && (newdepth == 16)) return Convert24to16 (); if(!temp.Create (m_DIBData->m_Width,m_DIBData->m_Height,newdepth)) return false; if (!temp.Blt (0,0,m_DIBData->m_Width,m_DIBData->m_Height,this,0,0)) return false; if(m_DIBData->m_Mask) { if(!temp.CalcMask ()) return false; HDC dc1,dc2; dc1 = temp.m_DIBData->m_Mask->GetDC (); dc2 = m_DIBData->m_Mask->GetDC (); BitBlt (dc1,0,0,m_DIBData->m_Width,m_DIBData->m_Height,dc2,0,0,SRCCOPY); temp.m_DIBData->m_Mask->ReleaseDC (dc1); m_DIBData->m_Mask->ReleaseDC (dc2); } // (*temp.m_RefCount)++; temp.AddRef (); Destroy (); memcpy (m_DIBData,temp.m_DIBData,sizeof (DIBData)); delete temp.m_DIBData; delete temp.m_RefCount; temp.m_DIBData = NULL; temp.m_RefCount = NULL; return true; } HBITMAP CDIBSurface::GetBitmap (void) const // actually creates the DIB section (if needed) { if (m_DIBData->m_BackBits != NULL) return m_DIBData->m_BackBits; BITMAPINFO *bitinfo = AllocBitmapInfo(); unsigned char *olddata = m_DIBData->m_Data; HDC dc = ::GetDC (NULL); m_DIBData->m_BackBits = CreateDIBSection (dc,bitinfo,DIB_RGB_COLORS,(void **) &m_DIBData->m_Data,NULL,NULL); if (m_DIBData->m_BackBits == NULL) { DWORD error = GetLastError (); OutputDebugString ("error code is "); m_DIBData->m_Data = olddata; } else // move data over { // ::SetDIBits (dc, m_DIBData->m_BackBits, 0, bitinfo->bmiHeader.biHeight, olddata, bitinfo, DIB_RGB_COLORS); memcpy (m_DIBData->m_Data, olddata, abs (m_DIBData->m_Pitch) * m_DIBData->m_Height); delete olddata; } ::ReleaseDC (NULL, dc); delete bitinfo; if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1))); else m_DIBData->m_UpperLeft = m_DIBData->m_Data; ASSERT(NULL != m_DIBData->m_BackBits); return m_DIBData->m_BackBits; } void CDIBSurface::ReleaseBitmap (void) const // call to free up GDI resources { if (m_DIBData->m_BackBits == NULL) return; unsigned char *newdata = new unsigned char [abs (m_DIBData->m_Pitch) * m_DIBData->m_Height]; if (!newdata) return; // GDI resource not freed, but bitmap still works #if 1 // m_BackBits must not be selected into a DC ASSERT (m_DIBData->m_SelectedDC == NULL); // (if that's a problem, release the dc here) memcpy (newdata, m_DIBData->m_Data, abs (m_DIBData->m_Pitch) * m_DIBData->m_Height); DeleteObject (m_DIBData->m_BackBits); m_DIBData->m_BackBits = NULL; m_DIBData->m_Data = newdata; if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1))); else m_DIBData->m_UpperLeft = m_DIBData->m_Data; #else BITMAPINFO *bitinfo = AllocBitmapInfo(); if (!bitinfo) delete newdata; else { // m_BackBits must not be selected into a DC ASSERT (m_DIBData->m_SelectedDC == NULL); // (if that's a problem, release the dc here) HDC dc = ::GetDC (NULL); // move data over if (GetDIBits (dc, m_DIBData->m_BackBits, 0, bitinfo->bmiHeader.biHeight, newdata, bitinfo, DIB_RGB_COLORS)) { DeleteObject (m_DIBData->m_BackBits); m_DIBData->m_BackBits = NULL; m_DIBData->m_Data = newdata; if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1))); else m_DIBData->m_UpperLeft = m_DIBData->m_Data; } else { DWORD err = GetLastError(); DPRINTF ("GetDIBits failed, error 0x%lx\n", err); delete newdata; } ::ReleaseDC (NULL, dc); } delete bitinfo; #endif } BITMAPINFO *CDIBSurface::AllocBitmapInfo (void) const // delete when done with it { short index; BITMAPINFO *bitinfo; // when we create a DIB section we need to setup a BITMAPINFO structure to pass to CreateDIBSection // this structure hold all the data about out buffer switch(m_DIBData->m_BitDepth) { case 24: bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)]; if(bitinfo == NULL) return NULL; memset (bitinfo,0,sizeof (BITMAPINFO)); bitinfo->bmiHeader.biBitCount = 24; break; case 16: bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)]; if(bitinfo == NULL) return NULL; memset (bitinfo,0,sizeof (BITMAPINFO)); bitinfo->bmiHeader.biBitCount = 16; break; case 8: bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*256)]; if(bitinfo == NULL) return NULL; //lint !e525 huh memset (bitinfo,0,sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*256)); //lint !e419 ok size good for(index = 0;index<256;index++) { bitinfo->bmiColors[index].rgbRed = 0; //lint !e662 !e661 ok bitinfo->bmiColors[index].rgbGreen = 0; //lint !e662 !e661 ok bitinfo->bmiColors[index].rgbBlue = 0; //lint !e662 !e661 ok } bitinfo->bmiHeader.biBitCount = 8; break; case 4: bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*16)]; if(bitinfo == NULL) return NULL; //lint !e525 huh memset (bitinfo,0,sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*16)); //lint !e419 size is good for(index = 0;index<16;index++) { bitinfo->bmiColors[index].rgbRed = 0; //lint !e662 !e661 ok bitinfo->bmiColors[index].rgbGreen = 0; //lint !e662 !e661 ok bitinfo->bmiColors[index].rgbBlue = 0; //lint !e662 !e661 ok } bitinfo->bmiHeader.biBitCount = 4; break; case 1: bitinfo = (BITMAPINFO *) new BYTE[sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*2)]; if(bitinfo == NULL) return NULL; //lint !e525 huh memset (bitinfo,0,sizeof (BITMAPINFO)+(sizeof (PALETTEENTRY)*2)); //lint !e419 size is good bitinfo->bmiColors[0].rgbRed = 0; //line !e662 !e661 bitinfo->bmiColors[0].rgbGreen = 0; //line !e662 !e661 bitinfo->bmiColors[0].rgbBlue = 0; //line !e662 !e661 bitinfo->bmiColors[1].rgbRed = 255; //lint !e415 ok bitinfo->bmiColors[1].rgbGreen = 255; //lint !e415 ok bitinfo->bmiColors[1].rgbBlue = 255; //lint !e415 ok bitinfo->bmiHeader.biBitCount = 1; break; default: OutputDebugString ("Unsupported Bitdepth for DibSections"); return NULL; } // these are our generic fields for both 8 and 16-bit bitinfo->bmiHeader.biHeight = (long) (-1*((int) m_DIBData->m_Height)); // we use a negative height to mean a top-down bitmap bitinfo->bmiHeader.biWidth = (long) m_DIBData->m_Width; bitinfo->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); bitinfo->bmiHeader.biPlanes = 1; bitinfo->bmiHeader.biCompression = BI_RGB; bitinfo->bmiHeader.biSizeImage = 0; bitinfo->bmiHeader.biXPelsPerMeter = 0; bitinfo->bmiHeader.biYPelsPerMeter = 0; bitinfo->bmiHeader.biClrUsed = 0; bitinfo->bmiHeader.biClrImportant = 0; return bitinfo; } #ifdef USE_FEWER_GDI_RES using namespace NWarp; namespace { bool intersectintervals (int width, int srcx, int srcmax, int destx, int destmax, int& srcoffx, int& destoffx, int& interw) { if (destx + width <= 0 || destx >= destmax || srcx + width <= 0 || srcx >= srcmax) return false; // clip by minimum dest coord if (destx < 0) { destoffx = 0; srcoffx = srcx - destx; interw = width + destx; } else { destoffx = destx; srcoffx = srcx; interw = width; } // clip by minimum src coord if (srcx < 0) { destoffx -= srcx; srcoffx -= srcx; interw += srcx; } // clip by maximum source and dest coords if (srcoffx + interw > srcmax) interw = srcmax - srcoffx; if (destoffx + interw > destmax) interw = destmax - destoffx; ASSERT (srcoffx >= 0); ASSERT (srcoffx < srcmax); ASSERT (destoffx >= 0); ASSERT (destoffx < destmax); ASSERT (interw > 0); ASSERT (interw <= width); return true; } } // this version does not have the rop argument, assumes SRC_COPY template bool BltNonGDI (PixelHandlerType& pixelhandler, const CDIBSurface& dest,const int destx,const int desty,const int width,const int height,const CDIBSurface& src,const int srcx,const int srcy) { ASSERT (pixelhandler.Depth() == src.GetBitDepth()); ASSERT (pixelhandler.Depth() == dest.GetBitDepth()); int srcoffx, destoffx, interw; int srcoffy, destoffy, interh; if (!intersectintervals (width, srcx, src.GetWidth(), destx, dest.GetWidth(), srcoffx, destoffx, interw)) return true; // nothing to blit if (!intersectintervals (height, srcy, src.GetHeight(), desty, dest.GetHeight(), srcoffy, destoffy, interh)) return true; // nothing to blit const unsigned char *srcscanline = src.GetMem() + srcoffy * src.GetPitch(); const unsigned char *destscanline = dest.GetMem() + destoffy * dest.GetPitch(); // can be made much faster by doing larger reads/writes on aligned data #if 1 if ((pixelhandler.Depth() & 0x7) == 0) { const int pixsize = (pixelhandler.Depth() >> 3); for (int j = 0; j < interh; j++) { memcpy ((void*)(destscanline + destoffx * pixsize), (void*)(srcscanline + srcoffx * pixsize), interw * pixsize); srcscanline += src.GetPitch(); destscanline += dest.GetPitch(); } } else #endif for (int j = 0; j < interh; j++) { CPixelAddress s = pixelhandler.Increment (pixelhandler.PixelAddress ((void*)srcscanline), srcoffx); CPixelAddress d = pixelhandler.Increment (pixelhandler.PixelAddress ((void*)destscanline), destoffx); for (int i = 0; i < interw; i++) { CPixel pixel = pixelhandler.Get (s); pixelhandler.Set (d, pixel); s = pixelhandler.Increment (s); d = pixelhandler.Increment (d); } srcscanline += src.GetPitch(); destscanline += dest.GetPitch(); } return true; } #pragma intrinsic(memcpy) // this version does not have the rop argument, assumes SRC_COPY bool BltNonGDI16 (const CDIBSurface& dest,const int destx,const int desty,const int width,const int height,const CDIBSurface& src,const int srcx,const int srcy) { ASSERT (16 == src.GetBitDepth()); ASSERT (16 == dest.GetBitDepth()); int srcoffx, destoffx, interw; int srcoffy, destoffy, interh; if (!intersectintervals (width, srcx, src.GetWidth(), destx, dest.GetWidth(), srcoffx, destoffx, interw)) return true; // nothing to blit if (!intersectintervals (height, srcy, src.GetHeight(), desty, dest.GetHeight(), srcoffy, destoffy, interh)) return true; // nothing to blit const int srcpitch = src.GetPitch(); const int destpitch = dest.GetPitch(); const unsigned char *srcscanline = src.GetMem() + srcoffy * srcpitch; const unsigned char *destscanline = dest.GetMem() + destoffy * destpitch; const unsigned char *s = srcscanline + (srcoffx << 1); const unsigned char *d = destscanline + (destoffx << 1); const unsigned char *q = s + interh * srcpitch; ASSERT (((DWORD)s & 0x03) != 3); // these addresses cause stalls, but should not happen ASSERT (((DWORD)d & 0x03) != 3); // these addresses cause stalls, but should not happen while (s != q) { memcpy ((void*)d, s, interw << 1); s += srcpitch; d += destpitch; } return true; } // this version does not have the rop argument, assumes SRC_COPY template bool MaskBltNonGDI (PixelHandlerType& pixelhandler, const CDIBSurface& dest,const int destx,const int desty,int width,int height,const CDIBSurface& src,int srcx,int srcy) { ASSERT (pixelhandler.Depth() == src.GetBitDepth()); ASSERT (pixelhandler.Depth() == dest.GetBitDepth()); ASSERT (src.UseMask()); if(!src.UseMask ()) return false; CPixelHandler1 pixelhandler1; int srcoffx, destoffx, interw; int srcoffy, destoffy, interh; if (width <= 0 || !intersectintervals (width, srcx, src.GetWidth(), destx, dest.GetWidth(), srcoffx, destoffx, interw)) return true; // nothing to blit if (height <= 0 || !intersectintervals (height, srcy, src.GetHeight(), desty, dest.GetHeight(), srcoffy, destoffy, interh)) return true; // nothing to blit const unsigned char *srcscanline = src.GetMem() + srcoffy * src.GetPitch(); const unsigned char *maskscanline = src.Mask()->GetMem() + srcoffy * src.Mask()->GetPitch(); const unsigned char *destscanline = dest.GetMem() + destoffy * dest.GetPitch(); // can be made much faster by doing larger reads/writes on aligned data for (int j = 0; j < interh; j++) { CPixelAddress m = pixelhandler1.Increment (pixelhandler1.PixelAddress ((void*)maskscanline), srcoffx); CPixelAddress s = pixelhandler.Increment (pixelhandler.PixelAddress ((void*)srcscanline), srcoffx); CPixelAddress d = pixelhandler.Increment (pixelhandler.PixelAddress ((void*)destscanline), destoffx); for (int i = 0; i < interw; i++) { if (pixelhandler1.Get (m) == 0) pixelhandler.Set (d, pixelhandler.Get (s)); m = pixelhandler1.Increment (m); s = pixelhandler.Increment (s); d = pixelhandler.Increment (d); } maskscanline += src.Mask()->GetPitch(); srcscanline += src.GetPitch(); destscanline += dest.GetPitch(); } return true; } // this version does not have the rop argument, assumes SRC_COPY bool MaskBltNonGDI16 (const CDIBSurface& dest,const int destx,const int desty,int width,int height,const CDIBSurface& src,int srcx,int srcy) { ASSERT (16 == src.GetBitDepth()); ASSERT (16 == dest.GetBitDepth()); ASSERT (src.UseMask()); if(!src.UseMask ()) return false; int srcoffx, destoffx, interw; int srcoffy, destoffy, interh; if (!intersectintervals (width, srcx, src.GetWidth(), destx, dest.GetWidth(), srcoffx, destoffx, interw)) return true; // nothing to blit if (!intersectintervals (height, srcy, src.GetHeight(), desty, dest.GetHeight(), srcoffy, destoffy, interh)) return true; // nothing to blit CPixelHandler1 pixelhandler1; const int srcpitch = src.GetPitch(); const int destpitch = dest.GetPitch(); const int maskpitch = src.Mask()->GetPitch(); const unsigned char *srcscanline = src.GetMem() + srcoffy * srcpitch; const unsigned char *maskscanline = src.Mask()->GetMem() + srcoffy * maskpitch; const unsigned char *destscanline = dest.GetMem() + destoffy * destpitch; const unsigned char *s = srcscanline + (srcoffx << 1); const unsigned char *d = destscanline + (destoffx << 1); const unsigned char *q = s + interh * srcpitch; ASSERT (((DWORD)s & 0x03) != 3); // these addresses cause stalls, but should not happen ASSERT (((DWORD)d & 0x03) != 3); // these addresses cause stalls, but should not happen while (s != q) { CPixelAddress m = pixelhandler1.Increment (pixelhandler1.PixelAddress ((void*)maskscanline), srcoffx); const unsigned short *is = (const unsigned short *)s; const unsigned short *iq = (const unsigned short *)s + interw; unsigned short *id = (unsigned short *)d; while (is != iq) { if (pixelhandler1.Get (m) == 0) *id = *is; m = pixelhandler1.Increment (m); ++is, ++id; } s += srcpitch; d += destpitch; maskscanline += maskpitch; } return true; } // this version does not have the rop argument, assumes SRC_COPY bool CDIBSurface::BltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy) { #ifdef _DEBUG static int doit = 0; if (doit) { // revert back to traditional blit for tests HDC dc1,dc2; bool toret; dc1 = GetDC (); dc2 = src.GetDC (); if (!(dc1 && dc2)) { if (dc1) ReleaseDC (dc1); if (dc2) src.ReleaseDC (dc2); return false; } toret = (::BitBlt (dc1,x,y,width,height,dc2,srcx,srcy,SRCCOPY) == TRUE); ReleaseDC (dc1); src.ReleaseDC (dc2); return toret; } #endif ASSERT (GetBitDepth() == src.GetBitDepth()); switch (GetBitDepth()) { case 1: return ::BltNonGDI (CPixelHandler1(), *this,x,y,width,height,src,srcx,srcy); case 8: return ::BltNonGDI (CPixelHandler8(), *this,x,y,width,height,src,srcx,srcy); case 16: return ::BltNonGDI16 (*this,x,y,width,height,src,srcx,srcy); case 24: return ::BltNonGDI (CPixelHandler24(), *this,x,y,width,height,src,srcx,srcy); case 32: return ::BltNonGDI (CPixelHandler32(), *this,x,y,width,height,src,srcx,srcy); default: ASSERT (0); return false; } } // this version does not have the rop argument, assumes SRC_COPY bool CDIBSurface::MaskBltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy) { #ifdef _DEBUG static int doit = 0; if (doit) { // revert back to traditional blit for tests ASSERT (m_DIBData); ASSERT (src.m_DIBData); ASSERT (src.UseMask ()); if(!src.UseMask ()) return false; HDC dc = GetDC (); SetBkColor(dc, RGB(255, 255, 255)); // 1s --> 0xFFFFFF SetTextColor(dc, RGB(0, 0, 0)); // 0s --> 0x000000 // BitBlt(m_BackDC, x, y, width, height, src->m_BackDC, srcx, srcy, SRCINVERT); HDC dc2,dc3; dc2 = src.m_DIBData->m_Mask->GetDC (); dc3 = src.GetDC (); BitBlt(dc, x, y, width, height, dc2, srcx, srcy, SRCAND); BitBlt(dc, x, y, width, height, dc3, srcx, srcy, SRCPAINT); src.m_DIBData->m_Mask->ReleaseDC (dc2); src.ReleaseDC (dc3); ReleaseDC (dc); return true; } #endif ASSERT (GetBitDepth() == src.GetBitDepth()); switch (GetBitDepth()) { case 1: return ::MaskBltNonGDI (CPixelHandler1(), *this,x,y,width,height,src,srcx,srcy); case 8: return ::MaskBltNonGDI (CPixelHandler8(), *this,x,y,width,height,src,srcx,srcy); case 16: return ::MaskBltNonGDI (CPixelHandler16(), *this,x,y,width,height,src,srcx,srcy); case 24: return ::MaskBltNonGDI (CPixelHandler24(), *this,x,y,width,height,src,srcx,srcy); case 32: return ::MaskBltNonGDI (CPixelHandler32(), *this,x,y,width,height,src,srcx,srcy); default: ASSERT (0); return false; } } #else bool CDIBSurface::BltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy) { HDC dc1,dc2; bool toret; dc1 = GetDC (); dc2 = src.GetDC (); if (!(dc1 && dc2)) { if (dc1) ReleaseDC (dc1); if (dc2) src.ReleaseDC (dc2); return false; } toret = (::BitBlt (dc1,x,y,width,height,dc2,srcx,srcy,SRCCOPY) == TRUE); ReleaseDC (dc1); src.ReleaseDC (dc2); return toret; } bool CDIBSurface::MaskBltNonGDI (int x,int y,int width,int height,const CDIBSurface& src,int srcx,int srcy) { ASSERT (m_DIBData); ASSERT (src.m_DIBData); ASSERT (src.UseMask ()); if(!src.UseMask ()) return false; HDC dc = GetDC (); SetBkColor(dc, RGB(255, 255, 255)); // 1s --> 0xFFFFFF SetTextColor(dc, RGB(0, 0, 0)); // 0s --> 0x000000 // BitBlt(m_BackDC, x, y, width, height, src->m_BackDC, srcx, srcy, SRCINVERT); HDC dc2,dc3; dc2 = src.m_DIBData->m_Mask->GetDC (); dc3 = src.GetDC (); BitBlt(dc, x, y, width, height, dc2, srcx, srcy, SRCAND); BitBlt(dc, x, y, width, height, dc3, srcx, srcy, SRCPAINT); src.m_DIBData->m_Mask->ReleaseDC (dc2); src.ReleaseDC (dc3); ReleaseDC (dc); return true; } #endif