示例#1
0
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;
}
示例#2
0
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;
    }
}
示例#3
0
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 );
}
示例#4
0
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 );
}
示例#5
0
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 );
}