📄 win32_graphics.cpp
字号:
/***************************************************************************** * win32_graphics.cpp ***************************************************************************** * Copyright (C) 2003 VideoLAN * $Id: win32_graphics.cpp 11017 2005-05-14 23:50:13Z 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 WIN32_SKINS#define WINVER 0x500#ifndef AC_SRC_ALPHA#define AC_SRC_ALPHA 1#endif#include "win32_factory.hpp"#include "win32_graphics.hpp"#include "win32_window.hpp"#include "../src/generic_bitmap.hpp"Win32Graphics::Win32Graphics( intf_thread_t *pIntf, int width, int height ): OSGraphics( pIntf ), m_width( width ), m_height( height ), m_hDC( NULL ){ HBITMAP hBmp; HDC hDC = GetDC( NULL ); hBmp = CreateCompatibleBitmap( hDC, m_width, m_height ); ReleaseDC( NULL, hDC ); m_hDC = CreateCompatibleDC( NULL ); SelectObject( m_hDC, hBmp ); DeleteObject( hBmp ); // Create the mask m_mask = CreateRectRgn( 0, 0, 0, 0 );}Win32Graphics::~Win32Graphics(){ DeleteDC( m_hDC ); DeleteObject( m_mask );}void Win32Graphics::clear(){ // Clear the transparency mask DeleteObject( m_mask ); m_mask = CreateRectRgn( 0, 0, 0, 0 );}void Win32Graphics::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(); } if( height == -1 ) { height = rBitmap.getHeight(); } if( xDest + width > m_width || yDest + height > m_height ) { msg_Err( getIntf(), "Bitmap too large !" ); 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 Independant 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 BOOL (WINAPI *AlphaBlend)( HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION ); AlphaBlend = ((Win32Factory*)OSFactory::instance( getIntf() ))->AlphaBlend; if( AlphaBlend && !AlphaBlend( m_hDC, xDest, yDest, width, height, hDC, 0, 0, width, height, bf ) ) { msg_Err( getIntf(), "AlphaBlend() failed" ); } else if( !AlphaBlend ) { // Copy the image onto the internal DC BitBlt( m_hDC, xDest, yDest, width, height, hDC, 0, 0, SRCCOPY ); } // 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 Win32Graphics::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(); } // Create the mask for transparency HRGN mask = CreateRectRgn( xSrc, ySrc, xSrc + width, ySrc + height ); CombineRgn( mask, ((Win32Graphics&)rGraphics).getMask(), mask, RGN_AND ); OffsetRgn( mask, xDest - xSrc, yDest - ySrc ); // Copy the image HDC srcDC = ((Win32Graphics&)rGraphics).getDC(); SelectClipRgn( m_hDC, mask ); BitBlt( m_hDC, xDest, yDest, width, height, srcDC, xSrc, ySrc, SRCCOPY ); // Add the source mask to the mask of the graphics CombineRgn( m_mask, mask, m_mask, RGN_OR ); DeleteObject( mask );}void Win32Graphics::fillRect( int left, int top, int width, int height, uint32_t color ){ // Update the mask with the rectangle area HRGN newMask = CreateRectRgn( left, top, left + width, top + height ); CombineRgn( m_mask, m_mask, newMask, RGN_OR ); SelectClipRgn( m_hDC, m_mask ); DeleteObject( newMask ); // Create a brush with the color int red = (color & 0xff0000) >> 16; int green = (color & 0xff00) >> 8; int blue = color & 0xff; HBRUSH hBrush = CreateSolidBrush( RGB( red, green, blue ) ); // Draw the rectangle RECT r; r.left = left; r.top = top; r.right = left + width; r.bottom = top + height; FillRect( m_hDC, &r, hBrush ); DeleteObject( hBrush );}void Win32Graphics::drawRect( int left, int top, int width, int height, uint32_t color ){ // Update the mask with the rectangle HRGN l1 = CreateRectRgn( left, top, left + width, top + 1 ); HRGN l2 = CreateRectRgn( left + width - 1, top, left + width, top + height ); HRGN l3 = CreateRectRgn( left, top + height - 1, left + width, top + height ); HRGN l4 = CreateRectRgn( left, top, left + 1, top + height ); CombineRgn( m_mask, m_mask, l1, RGN_OR ); CombineRgn( m_mask, m_mask, l2, RGN_OR ); CombineRgn( m_mask, m_mask, l3, RGN_OR ); CombineRgn( m_mask, m_mask, l4, RGN_OR ); DeleteObject( l1 ); DeleteObject( l2 ); DeleteObject( l3 ); DeleteObject( l4 ); SelectClipRgn( m_hDC, m_mask ); // Create a pen with the color int red = (color & 0xff0000) >> 16; int green = (color & 0xff00) >> 8; int blue = color & 0xff; HPEN hPen = CreatePen( PS_SOLID, 0, RGB( red, green, blue ) ); SelectObject( m_hDC, hPen ); // Draw the rectangle MoveToEx( m_hDC, left, top, NULL ); LineTo( m_hDC, left + width - 1, top ); LineTo( m_hDC, left + width - 1, top + height - 1 ); LineTo( m_hDC, left, top + height - 1 ); LineTo( m_hDC, left, top ); // Delete the pen DeleteObject( hPen );}void Win32Graphics::applyMaskToWindow( OSWindow &rWindow ){ // Get window handle HWND hWnd = ((Win32Window&)rWindow).getHandle(); // Apply the mask // We need to copy the mask, because SetWindowRgn modifies it in our back HRGN mask = CreateRectRgn( 0, 0, 0, 0 ); CombineRgn( mask, m_mask, NULL, RGN_COPY ); SetWindowRgn( hWnd, mask, TRUE );}void Win32Graphics::copyToWindow( OSWindow &rWindow, int xSrc, int ySrc, int width, int height, int xDest, int yDest ){ // Initialize painting HWND hWnd = ((Win32Window&)rWindow).getHandle(); HDC wndDC = GetWindowDC( hWnd ); HDC srcDC = m_hDC; // Draw image on window BitBlt( wndDC, xDest, yDest, width, height, srcDC, xSrc, ySrc, SRCCOPY ); // Release window device context ReleaseDC( hWnd, wndDC );}bool Win32Graphics::hit( int x, int y ) const{ return PtInRegion( m_mask, x, y );}void Win32Graphics::addSegmentInRegion( HRGN &rMask, int start, int end, int line ){ HRGN buffer = CreateRectRgn( start, line, end, line + 1 ); CombineRgn( rMask, buffer, rMask, RGN_OR ); DeleteObject( buffer );}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -