bool BitmapImpl::drawBitmap( const GenericBitmap &rSource, int xSrc, int ySrc, int xDest, int yDest, int width, int height ) { int srcWidth = rSource.getWidth(); uint32_t *pSrc = (uint32_t*)rSource.getData() + ySrc * srcWidth + xSrc; if( !pSrc ) { return false; } if( xSrc < 0 || xSrc + width > srcWidth || ySrc < 0 || ySrc + height > rSource.getHeight() ) { msg_Warn( getIntf(), "drawBitmap: source rect too small, ignoring" ); return false; } if( xDest < 0 || xDest + width > m_width || yDest < 0 || yDest + height > m_height ) { msg_Warn( getIntf(), "drawBitmap: dest rect too small, ignoring" ); return false; } uint32_t *pDest = (uint32_t*)m_pData + yDest * m_width + xDest ; for( int y = 0; y < height; y++ ) { memcpy( pDest, pSrc, 4 * width ); pSrc += srcWidth; pDest += m_width; } return true; }
void BitmapImpl::drawBitmap( const GenericBitmap &rSource, int xSrc, int ySrc, int xDest, int yDest, int width, int height ) { int srcWidth = rSource.getWidth(); uint32_t *pSrc = (uint32_t*)rSource.getData() + ySrc * srcWidth + xSrc; uint32_t *pDest = (uint32_t*)m_pData + yDest * m_width + xDest ; for( int y = 0; y < height; y++ ) { memcpy( pDest, pSrc, 4 * width ); pSrc += srcWidth; pDest += m_width; } }
void X11Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc, int ySrc, int xDest, int yDest, int width, int height, bool blend ) { // Get the bitmap size if necessary if( width == -1 ) { width = rBitmap.getWidth(); } else if( width > rBitmap.getWidth() ) { msg_Dbg( getIntf(), "bitmap width too small (%i)", rBitmap.getWidth() ); width = rBitmap.getWidth(); } if( height == -1 ) { height = rBitmap.getHeight(); } else if( height > rBitmap.getHeight() ) { msg_Dbg( getIntf(), "bitmap height too small (%i)", rBitmap.getHeight() ); height = rBitmap.getHeight(); } // Nothing to draw if width or height is null if( width == 0 || height == 0 ) { return; } // Safety check for debugging purpose if( xDest + width > m_width || yDest + height > m_height ) { msg_Dbg( getIntf(), "bitmap too large" ); return; } // Get a buffer on the image data uint8_t *pBmpData = rBitmap.getData(); if( pBmpData == NULL ) { // Nothing to draw return; } // Get the image from the pixmap XImage *pImage = XGetImage( XDISPLAY, m_pixmap, xDest, yDest, width, height, AllPlanes, ZPixmap ); if( pImage == NULL ) { msg_Dbg( getIntf(), "XGetImage returned NULL" ); return; } char *pData = pImage->data; // Get the padding of this image int pad = pImage->bitmap_pad >> 3; int shift = ( pad - ( (width * XPIXELSIZE) % pad ) ) % pad; // Mask for transparency Region mask = XCreateRegion(); // Get a pointer on the right X11Display::makePixel method X11Display::MakePixelFunc_t makePixelFunc = ( blend ? m_rDisplay.getBlendPixel() : m_rDisplay.getPutPixel() ); // Skip the first lines of the image pBmpData += 4 * ySrc * rBitmap.getWidth(); // Copy the bitmap on the image and compute the mask for( int y = 0; y < height; y++ ) { // Skip uninteresting bytes at the beginning of the line pBmpData += 4 * xSrc; // Flag to say whether the previous pixel on the line was visible bool wasVisible = false; // Beginning of the current visible segment on the line int visibleSegmentStart = 0; for( int x = 0; x < width; x++ ) { uint8_t b = *(pBmpData++); uint8_t g = *(pBmpData++); uint8_t r = *(pBmpData++); uint8_t a = *(pBmpData++); // Draw the pixel (m_rDisplay.*makePixelFunc)( (uint8_t*)pData, r, g, b, a ); pData += XPIXELSIZE; if( a > 0 ) { // Pixel is visible if( ! wasVisible ) { // Beginning of a visible segment visibleSegmentStart = x; } wasVisible = true; } else { // Pixel is transparent if( wasVisible ) { // End of a visible segment: add it to the mask addHSegmentInRegion( mask, visibleSegmentStart, x, y ); } wasVisible = false; } } if( wasVisible ) { // End of a visible segment: add it to the mask addHSegmentInRegion( mask, visibleSegmentStart, width, y ); } pData += shift; // Skip uninteresting bytes at the end of the line pBmpData += 4 * (rBitmap.getWidth() - width - xSrc); } // Apply the mask to the graphics context XOffsetRegion( mask, xDest, yDest ); XSetRegion( XDISPLAY, m_gc, mask ); // Copy the image on the pixmap XPutImage( XDISPLAY, m_pixmap, m_gc, pImage, 0, 0, xDest, yDest, width, height); XDestroyImage( pImage ); // Add the bitmap mask to the global graphics mask Region newMask = XCreateRegion(); XUnionRegion( mask, m_mask, newMask ); XDestroyRegion( m_mask ); m_mask = newMask; XDestroyRegion( mask ); }
void Win32Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc, int ySrc, int xDest, int yDest, int width, int height, bool blend ) { (void)blend; // check and adapt to source if needed if( !checkBoundaries( 0, 0, rBitmap.getWidth(), rBitmap.getHeight(), xSrc, ySrc, width, height ) ) { msg_Err( getIntf(), "empty source! pls, debug your skin" ); return; } // check destination if( !checkBoundaries( 0, 0, m_width, m_height, xDest, yDest, width, height ) ) { msg_Err( getIntf(), "out of reach destination! pls, debug your skin" ); return; } // Get a buffer on the image data uint8_t *pBmpData = rBitmap.getData(); if( pBmpData == NULL ) { // Nothing to draw return; } void *pBits; // pointer to DIB section // Fill a BITMAPINFO structure BITMAPINFO bmpInfo; memset( &bmpInfo, 0, sizeof( bmpInfo ) ); bmpInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); bmpInfo.bmiHeader.biWidth = width; bmpInfo.bmiHeader.biHeight = -height; bmpInfo.bmiHeader.biPlanes = 1; bmpInfo.bmiHeader.biBitCount = 32; bmpInfo.bmiHeader.biCompression = BI_RGB; bmpInfo.bmiHeader.biSizeImage = width * height * 4; // Create a DIB (Device Independent Bitmap) and associate it with // a temporary DC HDC hDC = CreateCompatibleDC( m_hDC ); HBITMAP hBmp = CreateDIBSection( hDC, &bmpInfo, DIB_RGB_COLORS, &pBits, NULL, 0 ); SelectObject( hDC, hBmp ); // Mask for transparency HRGN mask = CreateRectRgn( 0, 0, 0, 0 ); // Skip the first lines of the image pBmpData += 4 * ySrc * rBitmap.getWidth(); // Copy the bitmap on the image and compute the mask for( int y = 0; y < height; y++ ) { // Skip uninteresting bytes at the beginning of the line pBmpData += 4 * xSrc; // Flag to say whether the previous pixel on the line was visible bool wasVisible = false; // Beginning of the current visible segment on the line int visibleSegmentStart = 0; for( int x = 0; x < width; x++ ) { uint8_t b = *(pBmpData++); uint8_t g = *(pBmpData++); uint8_t r = *(pBmpData++); uint8_t a = *(pBmpData++); // Draw the pixel ((UINT32 *)pBits)[x + y * width] = (a << 24) | (r << 16) | (g << 8) | b; if( a > 0 ) { // Pixel is visible if( ! wasVisible ) { // Beginning of a visible segment visibleSegmentStart = x; } wasVisible = true; } else { // Pixel is transparent if( wasVisible ) { // End of a visible segment: add it to the mask addSegmentInRegion( mask, visibleSegmentStart, x, y ); } wasVisible = false; } } if( wasVisible ) { // End of a visible segment: add it to the mask addSegmentInRegion( mask, visibleSegmentStart, width, y ); } // Skip uninteresting bytes at the end of the line pBmpData += 4 * (rBitmap.getWidth() - width - xSrc); } // Apply the mask to the internal DC OffsetRgn( mask, xDest, yDest ); SelectClipRgn( m_hDC, mask ); BLENDFUNCTION bf; // structure for alpha blending bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = 0xff; // don't use constant alpha bf.AlphaFormat = AC_SRC_ALPHA; // Blend the image onto the internal DC if( !AlphaBlend( m_hDC, xDest, yDest, width, height, hDC, 0, 0, width, height, bf ) ) { msg_Err( getIntf(), "AlphaBlend() failed" ); } // Add the bitmap mask to the global graphics mask CombineRgn( m_mask, m_mask, mask, RGN_OR ); // Do cleanup DeleteObject( hBmp ); DeleteObject( mask ); DeleteDC( hDC ); }
void X11Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc, int ySrc, int xDest, int yDest, int width, int height, bool blend ) { // check and adapt to source if needed if( !checkBoundaries( 0, 0, rBitmap.getWidth(), rBitmap.getHeight(), xSrc, ySrc, width, height ) ) { msg_Err( getIntf(), "empty source! pls, debug your skin" ); return; } // check destination if( !checkBoundaries( 0, 0, m_width, m_height, xDest, yDest, width, height ) ) { msg_Err( getIntf(), "out of reach destination! pls, debug your skin" ); return; } // Get a buffer on the image data uint8_t *pBmpData = rBitmap.getData(); if( pBmpData == NULL ) { // Nothing to draw return; } // Force pending XCopyArea to be sent to the X Server // before issuing an XGetImage. XSync( XDISPLAY, False ); // Get the image from the pixmap XImage *pImage = XGetImage( XDISPLAY, m_pixmap, xDest, yDest, width, height, AllPlanes, ZPixmap ); if( pImage == NULL ) { msg_Dbg( getIntf(), "XGetImage returned NULL" ); return; } char *pData = pImage->data; // Get the padding of this image int pad = pImage->bitmap_pad >> 3; int shift = ( pad - ( (width * XPIXELSIZE) % pad ) ) % pad; // Mask for transparency Region mask = XCreateRegion(); // Get a pointer on the right X11Display::makePixel method X11Display::MakePixelFunc_t makePixelFunc = ( blend ? m_rDisplay.getBlendPixel() : m_rDisplay.getPutPixel() ); // Skip the first lines of the image pBmpData += 4 * ySrc * rBitmap.getWidth(); // Copy the bitmap on the image and compute the mask for( int y = 0; y < height; y++ ) { // Skip uninteresting bytes at the beginning of the line pBmpData += 4 * xSrc; // Flag to say whether the previous pixel on the line was visible bool wasVisible = false; // Beginning of the current visible segment on the line int visibleSegmentStart = 0; for( int x = 0; x < width; x++ ) { uint8_t b = *(pBmpData++); uint8_t g = *(pBmpData++); uint8_t r = *(pBmpData++); uint8_t a = *(pBmpData++); // Draw the pixel (m_rDisplay.*makePixelFunc)( (uint8_t*)pData, r, g, b, a ); pData += XPIXELSIZE; if( a > 0 ) { // Pixel is visible if( ! wasVisible ) { // Beginning of a visible segment visibleSegmentStart = x; } wasVisible = true; } else { // Pixel is transparent if( wasVisible ) { // End of a visible segment: add it to the mask addHSegmentInRegion( mask, visibleSegmentStart, x, y ); } wasVisible = false; } } if( wasVisible ) { // End of a visible segment: add it to the mask addHSegmentInRegion( mask, visibleSegmentStart, width, y ); } pData += shift; // Skip uninteresting bytes at the end of the line pBmpData += 4 * (rBitmap.getWidth() - width - xSrc); } // Apply the mask to the graphics context XOffsetRegion( mask, xDest, yDest ); XSetRegion( XDISPLAY, m_gc, mask ); // Copy the image on the pixmap XPutImage( XDISPLAY, m_pixmap, m_gc, pImage, 0, 0, xDest, yDest, width, height); XDestroyImage( pImage ); // Add the bitmap mask to the global graphics mask Region newMask = XCreateRegion(); XUnionRegion( mask, m_mask, newMask ); XDestroyRegion( m_mask ); m_mask = newMask; XDestroyRegion( mask ); }