CtrlRadialSlider::CtrlRadialSlider( intf_thread_t *pIntf, const GenericBitmap &rBmpSeq, int numImg, VarPercent &rVariable, float minAngle, float maxAngle, const UString &rHelp, VarBool *pVisible ): CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ), m_numImg( numImg ), m_rVariable( rVariable ), m_minAngle( minAngle ), m_maxAngle( maxAngle ), m_cmdUpDown( this ), m_cmdDownUp( this ), m_cmdMove( this ) { // Build the images of the sequence OSFactory *pOsFactory = OSFactory::instance( getIntf() ); m_pImgSeq = pOsFactory->createOSGraphics( rBmpSeq.getWidth(), rBmpSeq.getHeight() ); m_pImgSeq->drawBitmap( rBmpSeq, 0, 0 ); m_width = rBmpSeq.getWidth(); m_height = rBmpSeq.getHeight() / numImg; // States m_fsm.addState( "up" ); m_fsm.addState( "down" ); // Transitions m_fsm.addTransition( "up", "mouse:left:down", "down", &m_cmdUpDown ); m_fsm.addTransition( "down", "mouse:left:up", "up", &m_cmdDownUp ); m_fsm.addTransition( "down", "motion", "down", &m_cmdMove ); // Initial state m_fsm.setState( "up" ); // Observe the variable m_rVariable.addObserver( this ); }
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; }
CtrlImage::CtrlImage( intf_thread_t *pIntf, const GenericBitmap &rBitmap, CmdGeneric &rCommand, resize_t resizeMethod, const UString &rHelp, VarBool *pVisible ): CtrlFlat( pIntf, rHelp, pVisible ), m_rBitmap( rBitmap ), m_rCommand( rCommand ), m_resizeMethod( resizeMethod ) { OSFactory *pOsFactory = OSFactory::instance( pIntf ); // Create an initial unscaled image in the buffer m_pImage = pOsFactory->createOSGraphics( rBitmap.getWidth(), rBitmap.getHeight() ); m_pImage->drawBitmap( m_rBitmap ); }
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; } }
AnimBitmap::AnimBitmap( intf_thread_t *pIntf, const GenericBitmap &rBitmap ): SkinObject( pIntf ), m_pImage( NULL ), m_curFrame( 0 ), m_pTimer( NULL ), m_cmdNextFrame( this ), m_rBitmap( rBitmap ) { // Build the graphics OSFactory *pOsFactory = OSFactory::instance( pIntf ); m_pImage = pOsFactory->createOSGraphics( rBitmap.getWidth(), rBitmap.getHeight() ); m_pImage->drawBitmap( rBitmap, 0, 0 ); m_nbFrames = rBitmap.getNbFrames(); m_frameRate = rBitmap.getFrameRate(); // Create the timer m_pTimer = pOsFactory->createOSTimer( m_cmdNextFrame ); }
void Tooltip::makeImage( const UString &rText ) { // Render the text on a bitmap GenericBitmap *pBmpTip = m_rFont.drawString( rText, 0 ); if( !pBmpTip ) { return; } int w = pBmpTip->getWidth() + 10; int h = m_rFont.getSize() + 8; // Create the image of the tooltip delete m_pImage; m_pImage = OSFactory::instance( getIntf() )->createOSGraphics( w, h ); m_pImage->fillRect( 0, 0, w, h, 0xffffd0 ); m_pImage->drawRect( 0, 0, w, h, 0x000000 ); m_pImage->drawBitmap( *pBmpTip, 0, 0, 5, 5, -1, -1, true ); delete pBmpTip; }
CtrlButton::CtrlButton( intf_thread_t *pIntf, const GenericBitmap &rBmpUp, const GenericBitmap &rBmpOver, const GenericBitmap &rBmpDown, CmdGeneric &rCommand, const UString &rTooltip, const UString &rHelp, VarBool *pVisible ): CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ), m_rCommand( rCommand ), m_tooltip( rTooltip ), m_cmdUpOverDownOver( this, &transUpOverDownOver ), m_cmdDownOverUpOver( this, &transDownOverUpOver ), m_cmdDownOverDown( this, &transDownOverDown ), m_cmdDownDownOver( this, &transDownDownOver ), m_cmdUpOverUp( this, &transUpOverUp ), m_cmdUpUpOver( this, &transUpUpOver ), m_cmdDownUp( this, &transDownUp ), m_cmdUpHidden( this, &transUpHidden ), m_cmdHiddenUp( this, &transHiddenUp ) { // Build the images of the button OSFactory *pOsFactory = OSFactory::instance( pIntf ); m_pImgUp = pOsFactory->createOSGraphics( rBmpUp.getWidth(), rBmpUp.getHeight() ); m_pImgUp->drawBitmap( rBmpUp, 0, 0 ); m_pImgDown = pOsFactory->createOSGraphics( rBmpDown.getWidth(), rBmpDown.getHeight() ); m_pImgDown->drawBitmap( rBmpDown, 0, 0 ); m_pImgOver = pOsFactory->createOSGraphics( rBmpOver.getWidth(), rBmpOver.getHeight() ); m_pImgOver->drawBitmap( rBmpOver, 0, 0 ); // States m_fsm.addState( "up" ); m_fsm.addState( "down" ); m_fsm.addState( "upOver" ); m_fsm.addState( "downOver" ); m_fsm.addState( "hidden" ); // Transitions m_fsm.addTransition( "upOver", "mouse:left:down", "downOver", &m_cmdUpOverDownOver ); m_fsm.addTransition( "upOver", "mouse:left:dblclick", "downOver", &m_cmdUpOverDownOver ); m_fsm.addTransition( "downOver", "mouse:left:up", "upOver", &m_cmdDownOverUpOver ); m_fsm.addTransition( "downOver", "leave", "down", &m_cmdDownOverDown ); m_fsm.addTransition( "down", "enter", "downOver", &m_cmdDownDownOver ); m_fsm.addTransition( "upOver", "leave", "up", &m_cmdUpOverUp ); m_fsm.addTransition( "up", "enter", "upOver", &m_cmdUpUpOver ); m_fsm.addTransition( "down", "mouse:left:up", "up", &m_cmdDownUp ); // XXX: It would be easy to use a "ANY" initial state to handle these // four lines in only one. But till now it isn't worthwhile... m_fsm.addTransition( "up", "special:hide", "hidden", &m_cmdUpHidden ); m_fsm.addTransition( "down", "special:hide", "hidden", &m_cmdUpHidden ); m_fsm.addTransition( "upOver", "special:hide", "hidden", &m_cmdUpHidden ); m_fsm.addTransition( "downOver", "special:hide", "hidden", &m_cmdUpHidden ); m_fsm.addTransition( "hidden", "special:show", "up", &m_cmdHiddenUp ); // Initial state m_fsm.setState( "up" ); m_pImg = m_pImgUp; }
CtrlSliderCursor::CtrlSliderCursor( intf_thread_t *pIntf, const GenericBitmap &rBmpUp, const GenericBitmap &rBmpOver, const GenericBitmap &rBmpDown, const Bezier &rCurve, VarPercent &rVariable, VarBool *pVisible, const UString &rTooltip, const UString &rHelp ): CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ), m_rVariable( rVariable ), m_tooltip( rTooltip ), m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ), m_cmdOverDown( this, &transOverDown ), m_cmdDownOver( this, &transDownOver ), m_cmdOverUp( this, &transOverUp ), m_cmdUpOver( this, &transUpOver ), m_cmdMove( this, &transMove ), m_cmdScroll( this, &transScroll ), m_lastPercentage( 0 ), m_xOffset( 0 ), m_yOffset( 0 ), m_pEvt( NULL ), m_rCurve( rCurve ) { // Build the images of the cursor OSFactory *pOsFactory = OSFactory::instance( getIntf() ); m_pImgUp = pOsFactory->createOSGraphics( rBmpUp.getWidth(), rBmpUp.getHeight() ); m_pImgUp->drawBitmap( rBmpUp, 0, 0 ); m_pImgDown = pOsFactory->createOSGraphics( rBmpDown.getWidth(), rBmpDown.getHeight() ); m_pImgDown->drawBitmap( rBmpDown, 0, 0 ); m_pImgOver = pOsFactory->createOSGraphics( rBmpOver.getWidth(), rBmpOver.getHeight() ); m_pImgOver->drawBitmap( rBmpOver, 0, 0 ); // States m_fsm.addState( "up" ); m_fsm.addState( "over" ); m_fsm.addState( "down" ); // Transitions m_fsm.addTransition( "over", "mouse:left:down", "down", &m_cmdOverDown ); m_fsm.addTransition( "down", "mouse:left:up", "over", &m_cmdDownOver ); m_fsm.addTransition( "over", "leave", "up", &m_cmdOverUp ); m_fsm.addTransition( "up", "enter", "over", &m_cmdUpOver ); m_fsm.addTransition( "down", "motion", "down", &m_cmdMove ); m_fsm.addTransition( "over", "scroll", "over", &m_cmdScroll ); // Initial state m_fsm.setState( "up" ); m_pImg = m_pImgUp; // Observe the position variable m_rVariable.addObserver( this ); // Initial position of the cursor m_lastPercentage = m_rVariable.get(); }
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 CtrlTree::makeImage() { stats_TimerStart( getIntf(), "[Skins] Playlist image", STATS_TIMER_SKINS_PLAYTREE_IMAGE ); delete m_pImage; // Get the size of the control const Position *pPos = getPosition(); if( !pPos ) { stats_TimerStop( getIntf(), STATS_TIMER_SKINS_PLAYTREE_IMAGE ); return; } int width = pPos->getWidth(); int height = pPos->getHeight(); int i_itemHeight = itemHeight(); // Create an image OSFactory *pOsFactory = OSFactory::instance( getIntf() ); m_pImage = pOsFactory->createOSGraphics( width, height ); VarTree::Iterator it = m_firstPos; if( m_pBgBitmap ) { // Draw the background bitmap if( !m_pScaledBitmap || m_pScaledBitmap->getWidth() != width || m_pScaledBitmap->getHeight() != height ) { delete m_pScaledBitmap; m_pScaledBitmap = new ScaledBitmap( getIntf(), *m_pBgBitmap, width, height ); } m_pImage->drawBitmap( *m_pScaledBitmap, 0, 0 ); for( int yPos = 0; yPos < height; yPos += i_itemHeight ) { if( it != m_rTree.end() ) { if( it->isSelected() ) { int rectHeight = __MIN( i_itemHeight, height - yPos ); m_pImage->fillRect( 0, yPos, width, rectHeight, m_selColor ); } do { it = m_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); } while( it != m_rTree.end() && it->isDeleted() ); } } } else { // FIXME (TRYME) // Fill background with background color uint32_t bgColor = m_bgColor1; m_pImage->fillRect( 0, 0, width, height, bgColor ); for( int yPos = 0; yPos < height; yPos += i_itemHeight ) { int rectHeight = __MIN( i_itemHeight, height - yPos ); if( it == m_rTree.end() ) m_pImage->fillRect( 0, yPos, width, rectHeight, bgColor ); else { uint32_t color = ( it->isSelected() ? m_selColor : bgColor ); m_pImage->fillRect( 0, yPos, width, rectHeight, color ); do { it = m_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); } while( it != m_rTree.end() && it->isDeleted() ); } bgColor = ( bgColor == m_bgColor1 ? m_bgColor2 : m_bgColor1 ); } } int bitmapWidth = itemImageWidth(); int yPos = 0; it = m_firstPos; while( it != m_rTree.end() && yPos < height ) { const GenericBitmap *m_pCurBitmap; UString *pStr = it->getString(); uint32_t color = ( it->isPlaying() ? m_playColor : m_fgColor ); // Draw the text if( pStr != NULL ) { int depth = m_flat ? 1 : it->depth(); GenericBitmap *pText = m_rFont.drawString( *pStr, color, width - bitmapWidth * depth ); if( !pText ) { stats_TimerStop( getIntf(), STATS_TIMER_SKINS_PLAYTREE_IMAGE ); return; } if( it->size() ) m_pCurBitmap = it->isExpanded() ? m_pOpenBitmap : m_pClosedBitmap; else m_pCurBitmap = m_pItemBitmap; if( m_pCurBitmap ) { // Make sure we are centered on the line int yPos2 = yPos+(i_itemHeight-m_pCurBitmap->getHeight()+1)/2; if( yPos2 >= height ) { delete pText; break; } m_pImage->drawBitmap( *m_pCurBitmap, 0, 0, bitmapWidth * (depth - 1 ), yPos2, m_pCurBitmap->getWidth(), __MIN( m_pCurBitmap->getHeight(), height - yPos2), true ); } yPos += i_itemHeight - pText->getHeight(); int ySrc = 0; if( yPos < 0 ) { ySrc = - yPos; yPos = 0; } int lineHeight = __MIN( pText->getHeight() - ySrc, height - yPos ); m_pImage->drawBitmap( *pText, 0, ySrc, bitmapWidth * depth, yPos, pText->getWidth(), lineHeight, true ); yPos += (pText->getHeight() - ySrc ); delete pText; } do { it = m_flat ? m_rTree.getNextLeaf( it ) : m_rTree.getNextVisibleItem( it ); } while( it != m_rTree.end() && it->isDeleted() ); } stats_TimerStop( getIntf(), STATS_TIMER_SKINS_PLAYTREE_IMAGE ); }
void CtrlList::makeImage() { delete m_pImage; // Get the size of the control const Position *pPos = getPosition(); if( !pPos ) { return; } int width = pPos->getWidth(); int height = pPos->getHeight(); int itemHeight = m_rFont.getSize() + LINE_INTERVAL; // Create an image OSFactory *pOsFactory = OSFactory::instance( getIntf() ); m_pImage = pOsFactory->createOSGraphics( width, height ); VarList::ConstIterator it = m_rList[m_lastPos]; // Draw the background if( m_pBitmap ) { // A background bitmap is given, so we scale it, ignoring the // background colors ScaledBitmap bmp( getIntf(), *m_pBitmap, width, height ); m_pImage->drawBitmap( bmp, 0, 0 ); // Take care of the selection color for( int yPos = 0; yPos < height; yPos += itemHeight ) { int rectHeight = __MIN( itemHeight, height - yPos ); if( it != m_rList.end() ) { if( (*it).m_selected ) { m_pImage->fillRect( 0, yPos, width, rectHeight, m_selColor ); } ++it; } } } else { // No background bitmap, so use the 2 background colors // Current background color uint32_t bgColor = m_bgColor1; for( int yPos = 0; yPos < height; yPos += itemHeight ) { int rectHeight = __MIN( itemHeight, height - yPos ); if( it != m_rList.end() ) { uint32_t color = ( (*it).m_selected ? m_selColor : bgColor ); m_pImage->fillRect( 0, yPos, width, rectHeight, color ); ++it; } else { m_pImage->fillRect( 0, yPos, width, rectHeight, bgColor ); } // Flip the background color bgColor = ( bgColor == m_bgColor1 ? m_bgColor2 : m_bgColor1 ); } } // Draw the items int yPos = 0; for( it = m_rList[m_lastPos]; it != m_rList.end() && yPos < height; ++it ) { UString *pStr = (UString*)(it->m_cString.get()); uint32_t color = ( it->m_playing ? m_playColor : m_fgColor ); // Draw the text GenericBitmap *pText = m_rFont.drawString( *pStr, color, width ); if( !pText ) { return; } yPos += itemHeight - pText->getHeight(); int ySrc = 0; if( yPos < 0 ) { ySrc = - yPos; yPos = 0; } int lineHeight = __MIN( pText->getHeight() - ySrc, height - yPos ); m_pImage->drawBitmap( *pText, 0, ySrc, 0, yPos, pText->getWidth(), lineHeight, true ); yPos += (pText->getHeight() - ySrc ); delete pText; } }
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 ); }
void CtrlTree::makeImage() { delete m_pImage; // Get the size of the control const Position *pPos = getPosition(); if( !pPos ) return; int width = pPos->getWidth(); int height = pPos->getHeight(); int i_itemHeight = itemHeight(); // Create an image OSFactory *pOsFactory = OSFactory::instance( getIntf() ); m_pImage = pOsFactory->createOSGraphics( width, height ); Iterator it = m_firstPos; if( m_pBgBitmap ) { // Draw the background bitmap if( !m_pScaledBitmap || m_pScaledBitmap->getWidth() != width || m_pScaledBitmap->getHeight() != height ) { delete m_pScaledBitmap; m_pScaledBitmap = new ScaledBitmap( getIntf(), *m_pBgBitmap, width, height ); } m_pImage->drawBitmap( *m_pScaledBitmap, 0, 0 ); for( int yPos = 0; yPos < height && it != m_rTree.end(); yPos += i_itemHeight, ++it ) { if( it->isSelected() ) { int rectHeight = __MIN( i_itemHeight, height - yPos ); m_pImage->fillRect( 0, yPos, width, rectHeight, m_selColor ); } } } else { // Fill background with background color uint32_t bgColor = m_bgColor1; m_pImage->fillRect( 0, 0, width, height, bgColor ); // Overwrite with alternate colors (bgColor1, bgColor2) for( int yPos = 0; yPos < height; yPos += i_itemHeight ) { int rectHeight = __MIN( i_itemHeight, height - yPos ); if( it == m_rTree.end() ) m_pImage->fillRect( 0, yPos, width, rectHeight, bgColor ); else { uint32_t color = ( it->isSelected() ? m_selColor : bgColor ); m_pImage->fillRect( 0, yPos, width, rectHeight, color ); ++it; } bgColor = ( bgColor == m_bgColor1 ? m_bgColor2 : m_bgColor1 ); } } int bitmapWidth = itemImageWidth(); it = m_firstPos; for( int yPos = 0; yPos < height && it != m_rTree.end(); ++it ) { const GenericBitmap *m_pCurBitmap; UString *pStr = it->getString(); if( pStr != NULL ) { uint32_t color = it->isPlaying() ? m_playColor : m_fgColor; int depth = m_flat ? 1 : it->depth(); GenericBitmap *pText = m_rFont.drawString( *pStr, color, width-bitmapWidth*depth ); if( !pText ) { return; } if( it->size() ) m_pCurBitmap = it->isExpanded() ? m_pOpenBitmap : m_pClosedBitmap; else m_pCurBitmap = m_pItemBitmap; if( m_pCurBitmap ) { // Make sure we are centered on the line int yPos2 = yPos+(i_itemHeight-m_pCurBitmap->getHeight()+1)/2; if( yPos2 >= height ) { delete pText; break; } // Draw the icon in front of the text m_pImage->drawBitmap( *m_pCurBitmap, 0, 0, bitmapWidth * (depth - 1 ), yPos2, m_pCurBitmap->getWidth(), __MIN( m_pCurBitmap->getHeight(), height - yPos2), true ); } yPos += i_itemHeight - pText->getHeight(); int ySrc = 0; if( yPos < 0 ) { ySrc = - yPos; yPos = 0; } int lineHeight = __MIN( pText->getHeight() - ySrc, height - yPos ); // Draw the text m_pImage->drawBitmap( *pText, 0, ySrc, bitmapWidth * depth, yPos, pText->getWidth(), lineHeight, true ); yPos += (pText->getHeight() - ySrc ); if( it == m_itOver ) { // Draw the underline bar below the text for drag&drop m_pImage->fillRect( bitmapWidth * (depth - 1 ), yPos - 2, bitmapWidth + pText->getWidth(), __MAX( lineHeight/5, 3 ), m_selColor ); } delete pText; } } }