win32_graphics.cpp
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:11k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * win32_graphics.cpp
  3.  *****************************************************************************
  4.  * Copyright (C) 2003 VideoLAN
  5.  * $Id: win32_graphics.cpp 7326 2004-04-12 14:07:57Z ipkiss $
  6.  *
  7.  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
  8.  *          Olivier Teuli鑢e <ipkiss@via.ecp.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. #ifdef WIN32_SKINS
  25. #define WINVER 0x500
  26. #ifndef AC_SRC_ALPHA
  27. #define AC_SRC_ALPHA 1
  28. #endif
  29. #include "win32_factory.hpp"
  30. #include "win32_graphics.hpp"
  31. #include "win32_window.hpp"
  32. #include "../src/generic_bitmap.hpp"
  33. Win32Graphics::Win32Graphics( intf_thread_t *pIntf, int width, int height ):
  34.     OSGraphics( pIntf ), m_width( width ), m_height( height ), m_hDC( NULL )
  35. {
  36.     HBITMAP hBmp;
  37.     HDC hDC = GetDC( NULL );
  38.     hBmp = CreateCompatibleBitmap( hDC, m_width, m_height );
  39.     ReleaseDC( NULL, hDC );
  40.     m_hDC = CreateCompatibleDC( NULL );
  41.     SelectObject( m_hDC, hBmp );
  42.     DeleteObject( hBmp );
  43.     // Create the mask
  44.     m_mask = CreateRectRgn( 0, 0, 0, 0 );
  45. }
  46. Win32Graphics::~Win32Graphics()
  47. {
  48.     DeleteDC( m_hDC );
  49.     DeleteObject( m_mask );
  50. }
  51. void Win32Graphics::clear()
  52. {
  53.     // Clear the transparency mask
  54.     DeleteObject( m_mask );
  55.     m_mask = CreateRectRgn( 0, 0, 0, 0 );
  56. }
  57. void Win32Graphics::drawBitmap( const GenericBitmap &rBitmap,
  58.                                 int xSrc, int ySrc, int xDest, int yDest,
  59.                                 int width, int height )
  60. {
  61.     // Get the bitmap size if necessary
  62.     if( width == -1 )
  63.     {
  64.         width = rBitmap.getWidth();
  65.     }
  66.     if( height == -1 )
  67.     {
  68.         height = rBitmap.getHeight();
  69.     }
  70.     if( xDest + width > m_width || yDest + height > m_height )
  71.     {
  72.         msg_Err( getIntf(), "Bitmap too large !" );
  73.         return;
  74.     }
  75.     // Get a buffer on the image data
  76.     uint8_t *pBmpData = rBitmap.getData();
  77.     if( pBmpData == NULL )
  78.     {
  79.         // Nothing to draw
  80.         return;
  81.     }
  82.     void *pBits;     // pointer to DIB section
  83.     // Fill a BITMAPINFO structure
  84.     BITMAPINFO bmpInfo;
  85.     memset( &bmpInfo, 0, sizeof( bmpInfo ) );
  86.     bmpInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
  87.     bmpInfo.bmiHeader.biWidth = width;
  88.     bmpInfo.bmiHeader.biHeight = -height;
  89.     bmpInfo.bmiHeader.biPlanes = 1;
  90.     bmpInfo.bmiHeader.biBitCount = 32;
  91.     bmpInfo.bmiHeader.biCompression = BI_RGB;
  92.     bmpInfo.bmiHeader.biSizeImage = width * height * 4;
  93.     // Create a DIB (Device Independant Bitmap) and associate it with
  94.     // a temporary DC
  95.     HDC hDC = CreateCompatibleDC( m_hDC );
  96.     HBITMAP hBmp = CreateDIBSection( hDC, &bmpInfo, DIB_RGB_COLORS,
  97.                                      &pBits, NULL, 0 );
  98.     SelectObject( hDC, hBmp );
  99.     // Mask for transparency
  100.     HRGN mask = CreateRectRgn( 0, 0, 0, 0 );
  101.     // Skip the first lines of the image
  102.     pBmpData += 4 * ySrc * rBitmap.getWidth();
  103.     // Copy the bitmap on the image and compute the mask
  104.     for( int y = 0; y < height; y++ )
  105.     {
  106.         // Skip uninteresting bytes at the beginning of the line
  107.         pBmpData += 4 * xSrc;
  108.         // Flag to say whether the previous pixel on the line was visible
  109.         bool wasVisible = false;
  110.         // Beginning of the current visible segment on the line
  111.         int visibleSegmentStart = 0;
  112.         for( int x = 0; x < width; x++ )
  113.         {
  114.             uint8_t b = *(pBmpData++);
  115.             uint8_t g = *(pBmpData++);
  116.             uint8_t r = *(pBmpData++);
  117.             uint8_t a = *(pBmpData++);
  118.             // Draw the pixel
  119.             // Note: the colours are multiplied by a/255, because of the
  120.             // algorithm used by Windows for the AlphaBlending
  121.             ((UINT32 *)pBits)[x + y * width] =
  122.                 (a << 24) | (((r * a) >> 8) << 16) |
  123.                             (((g * a) >> 8) << 8) |
  124.                              ((b * a) >> 8);
  125.             if( a > 0 )
  126.             {
  127.                 // Pixel is visible
  128.                 if( ! wasVisible )
  129.                 {
  130.                     // Beginning of a visible segment
  131.                     visibleSegmentStart = x;
  132.                 }
  133.                 wasVisible = true;
  134.             }
  135.             else
  136.             {
  137.                 // Pixel is transparent
  138.                 if( wasVisible )
  139.                 {
  140.                     // End of a visible segment: add it to the mask
  141.                     addSegmentInRegion( mask, visibleSegmentStart, x, y );
  142.                 }
  143.                 wasVisible = false;
  144.             }
  145.         }
  146.         if( wasVisible )
  147.         {
  148.             // End of a visible segment: add it to the mask
  149.             addSegmentInRegion( mask, visibleSegmentStart, width, y );
  150.         }
  151.         // Skip uninteresting bytes at the end of the line
  152.         pBmpData += 4 * (rBitmap.getWidth() - width - xSrc);
  153.     }
  154.     // Apply the mask to the internal DC
  155.     OffsetRgn( mask, xDest, yDest );
  156.     SelectClipRgn( m_hDC, mask );
  157.     BLENDFUNCTION bf;      // structure for alpha blending
  158.     bf.BlendOp = AC_SRC_OVER;
  159.     bf.BlendFlags = 0;
  160.     bf.SourceConstantAlpha = 0xff;  // don't use constant alpha
  161.     bf.AlphaFormat = AC_SRC_ALPHA;
  162.     // Blend the image onto the internal DC
  163.     BOOL (WINAPI *AlphaBlend)( HDC, int, int, int, int, HDC, int, int,
  164.                                int, int, BLENDFUNCTION );
  165.     AlphaBlend = ((Win32Factory*)OSFactory::instance( getIntf() ))->AlphaBlend;
  166.     if( AlphaBlend &&
  167.         !AlphaBlend( m_hDC, xDest, yDest, width, height, hDC, 0, 0,
  168.                      width, height, bf ) )
  169.     {
  170.         msg_Err( getIntf(), "AlphaBlend() failed" );
  171.     }
  172.     else if( !AlphaBlend )
  173.     {
  174.         // Copy the image onto the internal DC
  175.         BitBlt( m_hDC, xDest, yDest, width, height, hDC, 0, 0, SRCCOPY );
  176.     }
  177.     // Add the bitmap mask to the global graphics mask
  178.     CombineRgn( m_mask, m_mask, mask, RGN_OR );
  179.     // Do cleanup
  180.     DeleteObject( hBmp );
  181.     DeleteObject( mask );
  182.     DeleteDC( hDC );
  183. }
  184. void Win32Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc,
  185.                                   int ySrc, int xDest, int yDest, int width,
  186.                                   int height )
  187. {
  188.     if( width == -1 )
  189.     {
  190.         width = rGraphics.getWidth();
  191.     }
  192.     if( height == -1 )
  193.     {
  194.         height = rGraphics.getHeight();
  195.     }
  196.     // Create the mask for transparency
  197.     HRGN mask = CreateRectRgn( xSrc, ySrc, xSrc + width, ySrc + height );
  198.     CombineRgn( mask, ((Win32Graphics&)rGraphics).getMask(), mask, RGN_AND );
  199.     OffsetRgn( mask, xDest - xSrc, yDest - ySrc );
  200.     // Copy the image
  201.     HDC srcDC = ((Win32Graphics&)rGraphics).getDC();
  202.     SelectClipRgn( m_hDC, mask );
  203.     BitBlt( m_hDC, xDest, yDest, width, height, srcDC, xSrc, ySrc, SRCCOPY );
  204.     // Add the source mask to the mask of the graphics
  205.     CombineRgn( m_mask, mask, m_mask, RGN_OR );
  206.     DeleteObject( mask );
  207. }
  208. void Win32Graphics::fillRect( int left, int top, int width, int height,
  209.                               uint32_t color )
  210. {
  211.     // Update the mask with the rectangle area
  212.     HRGN newMask = CreateRectRgn( left, top, left + width, top + height );
  213.     CombineRgn( m_mask, m_mask, newMask, RGN_OR );
  214.     SelectClipRgn( m_hDC, m_mask );
  215.     DeleteObject( newMask );
  216.     // Create a brush with the color
  217.     int red = (color & 0xff0000) >> 16;
  218.     int green = (color & 0xff00) >> 8;
  219.     int blue = color & 0xff;
  220.     HBRUSH hBrush = CreateSolidBrush( RGB( red, green, blue ) );
  221.     // Draw the rectangle
  222.     RECT r;
  223.     r.left = left;
  224.     r.top = top;
  225.     r.right = left + width;
  226.     r.bottom = top + height;
  227.     FillRect( m_hDC, &r, hBrush );
  228.     DeleteObject( hBrush );
  229. }
  230. void Win32Graphics::drawRect( int left, int top, int width, int height,
  231.                               uint32_t color )
  232. {
  233.     // Update the mask with the rectangle
  234.     HRGN l1 = CreateRectRgn( left, top, left + width, top + 1 );
  235.     HRGN l2 = CreateRectRgn( left + width - 1, top,
  236.                              left + width, top + height );
  237.     HRGN l3 = CreateRectRgn( left, top + height - 1,
  238.                              left + width, top + height );
  239.     HRGN l4 = CreateRectRgn( left, top, left + 1, top + height );
  240.     CombineRgn( m_mask, m_mask, l1, RGN_OR );
  241.     CombineRgn( m_mask, m_mask, l2, RGN_OR );
  242.     CombineRgn( m_mask, m_mask, l3, RGN_OR );
  243.     CombineRgn( m_mask, m_mask, l4, RGN_OR );
  244.     DeleteObject( l1 );
  245.     DeleteObject( l2 );
  246.     DeleteObject( l3 );
  247.     DeleteObject( l4 );
  248.     SelectClipRgn( m_hDC, m_mask );
  249.     // Create a pen with the color
  250.     int red = (color & 0xff0000) >> 16;
  251.     int green = (color & 0xff00) >> 8;
  252.     int blue = color & 0xff;
  253.     HPEN hPen = CreatePen( PS_SOLID, 0, RGB( red, green, blue ) );
  254.     SelectObject( m_hDC, hPen );
  255.     // Draw the rectangle
  256.     MoveToEx( m_hDC, left, top, NULL );
  257.     LineTo( m_hDC, left + width - 1, top );
  258.     LineTo( m_hDC, left + width - 1, top + height - 1 );
  259.     LineTo( m_hDC, left, top + height - 1 );
  260.     LineTo( m_hDC, left, top );
  261.     // Delete the pen
  262.     DeleteObject( hPen );
  263. }
  264. void Win32Graphics::applyMaskToWindow( OSWindow &rWindow )
  265. {
  266.     // Get window handle
  267.     HWND hWnd = ((Win32Window&)rWindow).getHandle();
  268.     // Apply the mask
  269.     // We need to copy the mask, because SetWindowRgn modifies it in our back
  270.     HRGN mask = CreateRectRgn( 0, 0, 0, 0 );
  271.     CombineRgn( mask, m_mask, NULL, RGN_COPY );
  272.     SetWindowRgn( hWnd, mask, TRUE );
  273. }
  274. void Win32Graphics::copyToWindow( OSWindow &rWindow, int xSrc, int ySrc,
  275.                                   int width, int height, int xDest, int yDest )
  276. {
  277.     // Initialize painting
  278.     HWND hWnd = ((Win32Window&)rWindow).getHandle();
  279.     HDC wndDC = GetWindowDC( hWnd );
  280.     HDC srcDC = m_hDC;
  281.     // Draw image on window
  282.     BitBlt( wndDC, xDest, yDest, width, height, srcDC, xSrc, ySrc, SRCCOPY );
  283.     // Release window device context
  284.     ReleaseDC( hWnd, wndDC );
  285. }
  286. bool Win32Graphics::hit( int x, int y ) const
  287. {
  288.     return PtInRegion( m_mask, x, y );
  289. }
  290. void Win32Graphics::addSegmentInRegion( HRGN &rMask, int start,
  291.                                         int end, int line )
  292. {
  293.     HRGN buffer = CreateRectRgn( start, line, end, line + 1 );
  294.     CombineRgn( rMask, buffer, rMask, RGN_OR );
  295.     DeleteObject( buffer );
  296. }
  297. #endif