⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x11_graphics.cpp

📁 video linux conference
💻 CPP
字号:
/***************************************************************************** * x11_graphics.cpp ***************************************************************************** * Copyright (C) 2003 VideoLAN * $Id: x11_graphics.cpp 10861 2005-05-01 13:19:04Z asmax $ * * Authors: Cyril Deguet     <asmax@via.ecp.fr> *          Olivier Teuli鑢e <ipkiss@via.ecp.fr> * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************/#ifdef X11_SKINS#include <stdlib.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/extensions/shape.h>#include "x11_display.hpp"#include "x11_graphics.hpp"#include "x11_window.hpp"#include "../src/generic_bitmap.hpp"X11Graphics::X11Graphics( intf_thread_t *pIntf, X11Display &rDisplay,                          int width, int height ):    OSGraphics( pIntf ), m_rDisplay( rDisplay ), m_width( width ),    m_height( height ){    // Get the display paramaters    int screen = DefaultScreen( XDISPLAY );    int depth = DefaultDepth( XDISPLAY, screen );    // X11 doesn't accept that !    if( width == 0 || height == 0 )    {        // Avoid a X11 Bad Value error        width = height = 1;        msg_Err( getIntf(), "Invalid image size (null width or height)" );    }    // Create a pixmap    m_pixmap = XCreatePixmap( XDISPLAY, DefaultRootWindow( XDISPLAY ),                              width, height, depth);    // Create the transparency mask (everything is transparent initially)    m_mask = XCreateRegion();    // Create a Graphics Context that does not generate GraphicsExpose events    XGCValues xgcvalues;    xgcvalues.graphics_exposures = False;    m_gc = XCreateGC( XDISPLAY, m_pixmap, GCGraphicsExposures, &xgcvalues );}X11Graphics::~X11Graphics(){    XFreeGC( XDISPLAY, m_gc );    XDestroyRegion( m_mask );    XFreePixmap( XDISPLAY, m_pixmap );}void X11Graphics::clear(){    // Clear the transparency mask    XDestroyRegion( m_mask );    m_mask = XCreateRegion();}void X11Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc,                                int ySrc, int xDest, int yDest, int width,                                int height ){    if( width == -1 )    {        width = rGraphics.getWidth();    }    if( height == -1 )    {        height = rGraphics.getHeight();    }    // Source drawable    Drawable src = ((X11Graphics&)rGraphics).getDrawable();    // Create the mask for transparency    Region voidMask = XCreateRegion();    XRectangle rect;    rect.x = xSrc;    rect.y = ySrc;    rect.width = width;    rect.height = height;    Region clipMask = XCreateRegion();    XUnionRectWithRegion( &rect, voidMask, clipMask );    Region mask = XCreateRegion();    XIntersectRegion( ((X11Graphics&)rGraphics).getMask(), clipMask, mask );    XDestroyRegion( clipMask );    XDestroyRegion( voidMask );    XOffsetRegion( mask, xDest - xSrc, yDest - ySrc );    // Copy the pixmap    XSetRegion( XDISPLAY, m_gc, mask );    XCopyArea( XDISPLAY, src, m_pixmap, m_gc, xSrc, ySrc, width, height,               xDest, yDest );    // Add the source mask to the mask of the graphics    Region newMask = XCreateRegion();    XUnionRegion( m_mask, mask, newMask );    XDestroyRegion( mask );    XDestroyRegion( m_mask );    m_mask = newMask;}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!" );        width = rBitmap.getWidth();    }    if( height == -1 )    {        height = rBitmap.getHeight();    }    else if( height > rBitmap.getHeight() )    {        msg_Dbg( getIntf(), "Bitmap height too small!" );        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 X11Graphics::fillRect( int left, int top, int width, int height,                            uint32_t color ){    // Update the mask with the rectangle area    Region newMask = XCreateRegion();    XRectangle rect;    rect.x = left;    rect.y = top;    rect.width = width;    rect.height = height;    XUnionRectWithRegion( &rect, m_mask, newMask );    XDestroyRegion( m_mask );    m_mask = newMask;    // Draw the rectangle    XGCValues gcVal;    gcVal.foreground = m_rDisplay.getPixelValue( color >> 16, color >> 8, color );    XChangeGC( XDISPLAY, m_gc, GCForeground,  &gcVal );    XSetRegion( XDISPLAY, m_gc, m_mask );    XFillRectangle( XDISPLAY, m_pixmap, m_gc, left, top, width, height );}void X11Graphics::drawRect( int left, int top, int width, int height,                            uint32_t color ){    // Update the mask with the rectangle    addHSegmentInRegion( m_mask, left, left + width, top );    addHSegmentInRegion( m_mask, left, left + width, top + height );    addVSegmentInRegion( m_mask, top, top + height, left );    addVSegmentInRegion( m_mask, top, top + height, left + width );    // Draw the rectangle    XGCValues gcVal;    gcVal.foreground = m_rDisplay.getPixelValue( color >> 16, color >> 8, color );    XChangeGC( XDISPLAY, m_gc, GCForeground,  &gcVal );    XSetRegion( XDISPLAY, m_gc, m_mask );    XDrawRectangle( XDISPLAY, m_pixmap, m_gc, left, top, width - 1, height - 1 );}void X11Graphics::applyMaskToWindow( OSWindow &rWindow ){    // Get the target window    Window win = ((X11Window&)rWindow).getDrawable();    // Change the shape of the window    XShapeCombineRegion( XDISPLAY, win, ShapeBounding, 0, 0, m_mask,                         ShapeSet );}void X11Graphics::copyToWindow( OSWindow &rWindow, int xSrc,  int ySrc,                                int width, int height, int xDest, int yDest ){    // Destination window    Drawable dest = ((X11Window&)rWindow).getDrawable();    XCopyArea( XDISPLAY, m_pixmap, dest, XGC, xSrc, ySrc, width, height,               xDest, yDest );}bool X11Graphics::hit( int x, int y ) const{    return XPointInRegion( m_mask, x, y );}inline void X11Graphics::addHSegmentInRegion( Region &rMask, int xStart,                                              int xEnd, int y ){    XRectangle rect;    rect.x = xStart;    rect.y = y;    rect.width = xEnd - xStart;    rect.height = 1;    Region newMask = XCreateRegion();    XUnionRectWithRegion( &rect, rMask, newMask );    XDestroyRegion( rMask );    rMask = newMask;}inline void X11Graphics::addVSegmentInRegion( Region &rMask, int yStart,                                              int yEnd, int x ){    XRectangle rect;    rect.x = x;    rect.y = yStart;    rect.width = 1;    rect.height = yEnd - yStart;    Region newMask = XCreateRegion();    XUnionRectWithRegion( &rect, rMask, newMask );    XDestroyRegion( rMask );    rMask = newMask;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -