00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef WIN32_SKINS
00026
00027 #define WINVER 0x500
00028
00029 #include "win32_factory.hpp"
00030 #include "win32_graphics.hpp"
00031 #include "win32_window.hpp"
00032 #include "../src/generic_bitmap.hpp"
00033
00034 #ifndef AC_SRC_ALPHA
00035 #define AC_SRC_ALPHA 1
00036 #endif
00037
00038 Win32Graphics::Win32Graphics( intf_thread_t *pIntf, int width, int height ):
00039 OSGraphics( pIntf ), m_width( width ), m_height( height ), m_hDC( NULL )
00040 {
00041 HBITMAP hBmp;
00042 HDC hDC = GetDC( NULL );
00043 hBmp = CreateCompatibleBitmap( hDC, m_width, m_height );
00044 ReleaseDC( NULL, hDC );
00045
00046 m_hDC = CreateCompatibleDC( NULL );
00047 SelectObject( m_hDC, hBmp );
00048 DeleteObject( hBmp );
00049
00050
00051 m_mask = CreateRectRgn( 0, 0, 0, 0 );
00052 }
00053
00054
00055 Win32Graphics::~Win32Graphics()
00056 {
00057 DeleteDC( m_hDC );
00058 DeleteObject( m_mask );
00059 }
00060
00061
00062 void Win32Graphics::clear()
00063 {
00064
00065 DeleteObject( m_mask );
00066 m_mask = CreateRectRgn( 0, 0, 0, 0 );
00067 }
00068
00069
00070 void Win32Graphics::drawBitmap( const GenericBitmap &rBitmap,
00071 int xSrc, int ySrc, int xDest, int yDest,
00072 int width, int height, bool blend )
00073 {
00074
00075 if( width == -1 )
00076 {
00077 width = rBitmap.getWidth();
00078 }
00079 if( height == -1 )
00080 {
00081 height = rBitmap.getHeight();
00082 }
00083
00084 if( xDest + width > m_width || yDest + height > m_height )
00085 {
00086 msg_Err( getIntf(), "Bitmap too large !" );
00087 return;
00088 }
00089
00090
00091 uint8_t *pBmpData = rBitmap.getData();
00092 if( pBmpData == NULL )
00093 {
00094
00095 return;
00096 }
00097
00098 void *pBits;
00099
00100 BITMAPINFO bmpInfo;
00101 memset( &bmpInfo, 0, sizeof( bmpInfo ) );
00102 bmpInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
00103 bmpInfo.bmiHeader.biWidth = width;
00104 bmpInfo.bmiHeader.biHeight = -height;
00105 bmpInfo.bmiHeader.biPlanes = 1;
00106 bmpInfo.bmiHeader.biBitCount = 32;
00107 bmpInfo.bmiHeader.biCompression = BI_RGB;
00108 bmpInfo.bmiHeader.biSizeImage = width * height * 4;
00109
00110
00111
00112 HDC hDC = CreateCompatibleDC( m_hDC );
00113 HBITMAP hBmp = CreateDIBSection( hDC, &bmpInfo, DIB_RGB_COLORS,
00114 &pBits, NULL, 0 );
00115 SelectObject( hDC, hBmp );
00116
00117
00118 HRGN mask = CreateRectRgn( 0, 0, 0, 0 );
00119
00120
00121 pBmpData += 4 * ySrc * rBitmap.getWidth();
00122
00123
00124 for( int y = 0; y < height; y++ )
00125 {
00126
00127 pBmpData += 4 * xSrc;
00128
00129 bool wasVisible = false;
00130
00131 int visibleSegmentStart = 0;
00132 for( int x = 0; x < width; x++ )
00133 {
00134 uint8_t b = *(pBmpData++);
00135 uint8_t g = *(pBmpData++);
00136 uint8_t r = *(pBmpData++);
00137 uint8_t a = *(pBmpData++);
00138
00139
00140 ((UINT32 *)pBits)[x + y * width] =
00141 (a << 24) | (r << 16) | (g << 8) | b;
00142
00143 if( a > 0 )
00144 {
00145
00146 if( ! wasVisible )
00147 {
00148
00149 visibleSegmentStart = x;
00150 }
00151 wasVisible = true;
00152 }
00153 else
00154 {
00155
00156 if( wasVisible )
00157 {
00158
00159 addSegmentInRegion( mask, visibleSegmentStart, x, y );
00160 }
00161 wasVisible = false;
00162 }
00163 }
00164 if( wasVisible )
00165 {
00166
00167 addSegmentInRegion( mask, visibleSegmentStart, width, y );
00168 }
00169
00170 pBmpData += 4 * (rBitmap.getWidth() - width - xSrc);
00171 }
00172
00173
00174 OffsetRgn( mask, xDest, yDest );
00175 SelectClipRgn( m_hDC, mask );
00176
00177 BLENDFUNCTION bf;
00178 bf.BlendOp = AC_SRC_OVER;
00179 bf.BlendFlags = 0;
00180 bf.SourceConstantAlpha = 0xff;
00181 bf.AlphaFormat = AC_SRC_ALPHA;
00182
00183
00184 BOOL (WINAPI *AlphaBlend)( HDC, int, int, int, int, HDC, int, int,
00185 int, int, BLENDFUNCTION );
00186 AlphaBlend = ((Win32Factory*)OSFactory::instance( getIntf() ))->AlphaBlend;
00187 if( AlphaBlend &&
00188 !AlphaBlend( m_hDC, xDest, yDest, width, height, hDC, 0, 0,
00189 width, height, bf ) )
00190 {
00191 msg_Err( getIntf(), "AlphaBlend() failed" );
00192 }
00193 else if( !AlphaBlend )
00194 {
00195
00196 BitBlt( m_hDC, xDest, yDest, width, height, hDC, 0, 0, SRCCOPY );
00197 }
00198
00199
00200 CombineRgn( m_mask, m_mask, mask, RGN_OR );
00201
00202
00203 DeleteObject( hBmp );
00204 DeleteObject( mask );
00205 DeleteDC( hDC );
00206 }
00207
00208
00209 void Win32Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc,
00210 int ySrc, int xDest, int yDest, int width,
00211 int height )
00212 {
00213 if( width == -1 )
00214 {
00215 width = rGraphics.getWidth();
00216 }
00217 if( height == -1 )
00218 {
00219 height = rGraphics.getHeight();
00220 }
00221
00222
00223 HRGN mask = CreateRectRgn( xSrc, ySrc, xSrc + width, ySrc + height );
00224 CombineRgn( mask, ((Win32Graphics&)rGraphics).getMask(), mask, RGN_AND );
00225 OffsetRgn( mask, xDest - xSrc, yDest - ySrc );
00226
00227
00228 HDC srcDC = ((Win32Graphics&)rGraphics).getDC();
00229 SelectClipRgn( m_hDC, mask );
00230 BitBlt( m_hDC, xDest, yDest, width, height, srcDC, xSrc, ySrc, SRCCOPY );
00231
00232
00233 CombineRgn( m_mask, mask, m_mask, RGN_OR );
00234 DeleteObject( mask );
00235 }
00236
00237
00238 void Win32Graphics::fillRect( int left, int top, int width, int height,
00239 uint32_t color )
00240 {
00241
00242 HRGN newMask = CreateRectRgn( left, top, left + width, top + height );
00243 CombineRgn( m_mask, m_mask, newMask, RGN_OR );
00244 SelectClipRgn( m_hDC, m_mask );
00245 DeleteObject( newMask );
00246
00247
00248 int red = (color & 0xff0000) >> 16;
00249 int green = (color & 0xff00) >> 8;
00250 int blue = color & 0xff;
00251 HBRUSH hBrush = CreateSolidBrush( RGB( red, green, blue ) );
00252
00253
00254 RECT r;
00255 r.left = left;
00256 r.top = top;
00257 r.right = left + width;
00258 r.bottom = top + height;
00259 FillRect( m_hDC, &r, hBrush );
00260 DeleteObject( hBrush );
00261 }
00262
00263
00264 void Win32Graphics::drawRect( int left, int top, int width, int height,
00265 uint32_t color )
00266 {
00267
00268 HRGN l1 = CreateRectRgn( left, top, left + width, top + 1 );
00269 HRGN l2 = CreateRectRgn( left + width - 1, top,
00270 left + width, top + height );
00271 HRGN l3 = CreateRectRgn( left, top + height - 1,
00272 left + width, top + height );
00273 HRGN l4 = CreateRectRgn( left, top, left + 1, top + height );
00274 CombineRgn( m_mask, m_mask, l1, RGN_OR );
00275 CombineRgn( m_mask, m_mask, l2, RGN_OR );
00276 CombineRgn( m_mask, m_mask, l3, RGN_OR );
00277 CombineRgn( m_mask, m_mask, l4, RGN_OR );
00278 DeleteObject( l1 );
00279 DeleteObject( l2 );
00280 DeleteObject( l3 );
00281 DeleteObject( l4 );
00282
00283 SelectClipRgn( m_hDC, m_mask );
00284
00285
00286 int red = (color & 0xff0000) >> 16;
00287 int green = (color & 0xff00) >> 8;
00288 int blue = color & 0xff;
00289 HPEN hPen = CreatePen( PS_SOLID, 0, RGB( red, green, blue ) );
00290 SelectObject( m_hDC, hPen );
00291
00292
00293 MoveToEx( m_hDC, left, top, NULL );
00294 LineTo( m_hDC, left + width - 1, top );
00295 LineTo( m_hDC, left + width - 1, top + height - 1 );
00296 LineTo( m_hDC, left, top + height - 1 );
00297 LineTo( m_hDC, left, top );
00298
00299
00300 DeleteObject( hPen );
00301 }
00302
00303
00304 void Win32Graphics::applyMaskToWindow( OSWindow &rWindow )
00305 {
00306
00307 HWND hWnd = ((Win32Window&)rWindow).getHandle();
00308
00309
00310
00311 HRGN mask = CreateRectRgn( 0, 0, 0, 0 );
00312 CombineRgn( mask, m_mask, NULL, RGN_COPY );
00313 SetWindowRgn( hWnd, mask, TRUE );
00314 }
00315
00316
00317 void Win32Graphics::copyToWindow( OSWindow &rWindow, int xSrc, int ySrc,
00318 int width, int height, int xDest, int yDest )
00319 {
00320
00321 HWND hWnd = ((Win32Window&)rWindow).getHandle();
00322 HDC wndDC = GetWindowDC( hWnd );
00323 HDC srcDC = m_hDC;
00324
00325
00326 BitBlt( wndDC, xDest, yDest, width, height, srcDC, xSrc, ySrc, SRCCOPY );
00327
00328
00329 ReleaseDC( hWnd, wndDC );
00330 }
00331
00332
00333 bool Win32Graphics::hit( int x, int y ) const
00334 {
00335 return PtInRegion( m_mask, x, y ) != 0;
00336 }
00337
00338
00339 void Win32Graphics::addSegmentInRegion( HRGN &rMask, int start,
00340 int end, int line )
00341 {
00342 HRGN buffer = CreateRectRgn( start, line, end, line + 1 );
00343 CombineRgn( rMask, buffer, rMask, RGN_OR );
00344 DeleteObject( buffer );
00345 }
00346
00347 #endif