Commit 108fc274 authored by Cyril Deguet's avatar Cyril Deguet
Browse files

* os_graphics.hpp: added a parameter "blend" to drawBitmap(), to perform alpha

  blending only when it is useful (i.e. when drawing antialiased text)
* x11/*: optimized drawBitmap when alpha blending is not used: 5 times faster
parent 60b5f4b5
......@@ -471,7 +471,7 @@ void CtrlList::makeImage()
}
int lineHeight = __MIN( pText->getHeight() - ySrc, height - yPos );
m_pImage->drawBitmap( *pText, 0, ySrc, 0, yPos, pText->getWidth(),
lineHeight );
lineHeight, true );
yPos += (pText->getHeight() - ySrc );
delete pText;
......
......@@ -160,7 +160,7 @@ void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
if( width > 0 && height > 0 )
{
rImage.drawBitmap( *m_pCurrImg, -m_xPos, 0, xDest, yDest,
width, height );
width, height, true );
}
}
}
......
......@@ -23,19 +23,18 @@
#ifdef MACOSX_SKINS
#include <Carbon/Carbon.h>
#include "macosx_loop.hpp"
MacOSXLoop::MacOSXLoop( intf_thread_t *pIntf ):
OSLoop( pIntf )
OSLoop( pIntf ), m_exit( false )
{
// TODO
}
MacOSXLoop::~MacOSXLoop()
{
// TODO
}
......@@ -62,13 +61,58 @@ void MacOSXLoop::destroy( intf_thread_t *pIntf )
void MacOSXLoop::run()
{
// TODO
// Main event loop
while( !m_exit )
{
EventRef pEvent;
OSStatus err = ReceiveNextEvent( 0, NULL, kEventDurationForever, true,
&pEvent );
if( err != noErr )
{
// Get the event type
UInt32 evClass = GetEventClass( pEvent );
switch( evClass )
{
case kEventClassMouse:
{
break;
}
case kEventClassKeyboard:
{
break;
}
case kEventClassWindow:
{
handleWindowEvent( pEvent );
break;
}
default:
{
EventTargetRef pTarget;
pTarget = GetEventDispatcherTarget();
SendEventToEventTarget( pEvent, pTarget );
ReleaseEvent( pEvent );
}
}
}
}
}
void MacOSXLoop::exit()
{
// TODO
m_exit = true;
}
void MacOSXLoop::handleWindowEvent( EventRef pEvent )
{
UInt32 evKind = GetEventKind( pEvent );
}
......
......@@ -49,6 +49,11 @@ class MacOSXLoop: public OSLoop
// Private because it's a singleton
MacOSXLoop( intf_thread_t *pIntf );
virtual ~MacOSXLoop();
// Flag set to exit the loop
bool m_exit;
// Handle a window event
void handleWindowEvent( EventRef pEvent );
};
#endif
......@@ -60,9 +60,9 @@ void FT2Bitmap::draw( const FT_Bitmap &rBitmap, int left, int top,
{
// The buffer in FT_Bitmap contains alpha values
uint8_t val = *(pBuf++);
*(pData++) = blue;
*(pData++) = green;
*(pData++) = red;
*(pData++) = (blue * val) >> 8;
*(pData++) = (green * val) >> 8;
*(pData++) = (red * val) >> 8;
*(pData++) = val;
}
}
......
......@@ -49,7 +49,8 @@ class OSGraphics: public SkinObject
/// Render a bitmap on this graphics
virtual void drawBitmap( const GenericBitmap &rBitmap, int xSrc = 0,
int ySrc = 0, int xDest = 0, int yDest = 0,
int width = -1, int height = -1 ) = 0;
int width = -1, int height = -1,
bool blend = false) = 0;
/// Draw a filled rectangle on the grahics (color is #RRGGBB)
virtual void fillRect( int left, int top, int width, int height,
......
......@@ -113,7 +113,7 @@ void Tooltip::makeImage( const UString &rText )
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 );
m_pImage->drawBitmap( *pBmpTip, 0, 0, 5, 5, -1, -1, true );
delete pBmpTip;
}
......
......@@ -68,7 +68,7 @@ void Win32Graphics::clear()
void Win32Graphics::drawBitmap( const GenericBitmap &rBitmap,
int xSrc, int ySrc, int xDest, int yDest,
int width, int height )
int width, int height, bool blend )
{
// Get the bitmap size if necessary
if( width == -1 )
......
......@@ -44,7 +44,8 @@ class Win32Graphics: public OSGraphics
/// Render a bitmap on this graphics
virtual void drawBitmap( const GenericBitmap &rBitmap, int xSrc = 0,
int ySrc = 0, int xDest = 0, int yDest = 0,
int width = -1, int height = -1 );
int width = -1, int height = -1,
bool blend = false );
/// Draw another graphics on this one
virtual void drawGraphics( const OSGraphics &rGraphics, int xSrc = 0,
......
......@@ -31,6 +31,24 @@
#include "x11_display.hpp"
#include "../src/logger.hpp"
// Macro to compute a pixel value
#define PUT_PIXEL(value, r, g, b, type) \
value = \
( ((type)r >> m_redRightShift) << m_redLeftShift ) | \
( ((type)g >> m_greenRightShift) << m_greenLeftShift ) | \
( ((type)b >> m_blueRightShift) << m_blueLeftShift );
// Macro to blend a pixel with another color
#define BLEND_PIXEL(value, r, g, b, a, type) \
uint16_t temp; \
temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift)); \
uint8_t red = r + ( temp * (255 - a) ) / 255; \
temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift)); \
uint8_t green = g + ( temp * (255 - a) ) / 255; \
temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift)); \
uint8_t blue = b + ( temp * (255 - a) ) / 255; \
PUT_PIXEL(value, red, green, blue, type)
X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
m_mainWindow( 0 ), m_gc( NULL ), m_colormap( 0 )
......@@ -52,6 +70,7 @@ X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
int screen = DefaultScreen( m_pDisplay );
int depth = DefaultDepth( m_pDisplay, screen );
int order = ImageByteOrder( m_pDisplay );
Window root = DefaultRootWindow( m_pDisplay );
// Template for looking up the XVisualInfo
XVisualInfo xVInfoTemplate;
......@@ -84,8 +103,7 @@ X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
getShifts( pVInfo->blue_mask, m_blueLeftShift, m_blueRightShift );
// Create a color map
m_colormap = XCreateColormap( m_pDisplay,
DefaultRootWindow( m_pDisplay ),
m_colormap = XCreateColormap( m_pDisplay, root,
DefaultVisual( m_pDisplay, screen ), AllocAll );
// Create the palette
......@@ -97,12 +115,16 @@ X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
pColors[i].pixel = 254-i;
pColors[i].pad = 0;
pColors[i].flags = DoRed | DoGreen | DoBlue;
pColors[i].red = (i >> m_redLeftShift) << (m_redRightShift + 8);
pColors[i].green = (i >> m_greenLeftShift) << (m_greenRightShift + 8);
pColors[i].blue = (i >> m_blueLeftShift) << (m_blueRightShift + 8);
pColors[i].red =
(i >> m_redLeftShift) << (m_redRightShift + 8);
pColors[i].green =
(i >> m_greenLeftShift) << (m_greenRightShift + 8);
pColors[i].blue =
(i >> m_blueLeftShift) << (m_blueRightShift + 8);
}
XStoreColors( m_pDisplay, m_colormap, pColors, 255 );
makePixelImpl = &X11Display::makePixel8;
blendPixelImpl = &X11Display::blendPixel8;
putPixelImpl = &X11Display::putPixel8;
m_pixelSize = 1;
break;
......@@ -130,21 +152,17 @@ X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
m_greenRightShift );
getShifts( pVInfo->blue_mask, m_blueLeftShift, m_blueRightShift );
if( depth == 8 )
{
makePixelImpl = &X11Display::makePixel8;
m_pixelSize = 1;
}
if( depth == 15 || depth == 16 )
{
if( order == MSBFirst )
{
makePixelImpl = &X11Display::makePixel16MSB;
blendPixelImpl = &X11Display::blendPixel16MSB;
putPixelImpl = &X11Display::putPixel16MSB;
}
else
{
makePixelImpl = &X11Display::makePixel16LSB;
blendPixelImpl = &X11Display::blendPixel16LSB;
putPixelImpl = &X11Display::putPixel16LSB;
}
m_pixelSize = 2;
}
......@@ -152,11 +170,13 @@ X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
{
if( order == MSBFirst )
{
makePixelImpl = &X11Display::makePixel32MSB;
blendPixelImpl = &X11Display::blendPixel32MSB;
putPixelImpl = &X11Display::putPixel32MSB;
}
else
{
makePixelImpl = &X11Display::makePixel32LSB;
blendPixelImpl = &X11Display::blendPixel32LSB;
putPixelImpl = &X11Display::putPixel32LSB;
}
m_pixelSize = 4;
}
......@@ -179,14 +199,12 @@ X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
{
XGCValues xgcvalues;
xgcvalues.graphics_exposures = False;
m_gc = XCreateGC( m_pDisplay, DefaultRootWindow( m_pDisplay ),
GCGraphicsExposures, &xgcvalues );
m_gc = XCreateGC( m_pDisplay, root, GCGraphicsExposures, &xgcvalues );
// Create a parent window to have a single task in the task bar
XSetWindowAttributes attr;
m_mainWindow = XCreateWindow( m_pDisplay, DefaultRootWindow( m_pDisplay),
0, 0, 1, 1, 0, 0, InputOutput,
CopyFromParent, 0, &attr );
m_mainWindow = XCreateWindow( m_pDisplay, root, 0, 0, 1, 1, 0, 0,
InputOutput, CopyFromParent, 0, &attr );
// Changing decorations
struct {
......@@ -264,150 +282,138 @@ void X11Display::getShifts( uint32_t mask, int &rLeftShift,
}
void X11Display::makePixel8( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const
void X11Display::blendPixel8( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
// Get the current pixel value
uint8_t value = 255 - *pPixel;
// Compute the new color values
uint16_t temp;
temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
uint8_t red = ( temp * (255 - a) + r * a ) / 255;
temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
uint8_t green = ( temp * (255 - a) + g * a ) / 255;
temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
// Set the new pixel value
value =
( ((uint8_t)red >> m_redRightShift) << m_redLeftShift ) |
( ((uint8_t)green >> m_greenRightShift) << m_greenLeftShift ) |
( ((uint8_t)blue >> m_blueRightShift) << m_blueLeftShift );
BLEND_PIXEL(value, r, g, b, a, uint8_t)
*pPixel = 255 - value;
}
void X11Display::makePixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
void X11Display::blendPixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
// Get the current pixel value
uint16_t value = pPixel[1] | pPixel[0] << 8;
// Compute the new color values
uint16_t temp;
temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
uint8_t red = ( temp * (255 - a) + r * a ) / 255;
temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
uint8_t green = ( temp * (255 - a) + g * a ) / 255;
temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
// Set the new pixel value
value =
( ((uint16_t)red >> m_redRightShift) << m_redLeftShift ) |
( ((uint16_t)green >> m_greenRightShift) << m_greenLeftShift ) |
( ((uint16_t)blue >> m_blueRightShift) << m_blueLeftShift );
BLEND_PIXEL(value, r, g, b, a, uint16_t)
pPixel[1] = value;
value >>= 8;
pPixel[1] = value; value >>= 8;
pPixel[0] = value;
}
void X11Display::makePixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
void X11Display::blendPixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
// Get the current pixel value
uint16_t value = pPixel[0] | pPixel[1] << 8;
// Compute the new color values
uint16_t temp;
temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
uint8_t red = ( temp * (255 - a) + r * a ) / 255;
temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
uint8_t green = ( temp * (255 - a) + g * a ) / 255;
temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
// Set the new pixel value
value =
( ((uint16_t)red >> m_redRightShift) << m_redLeftShift ) |
( ((uint16_t)green >> m_greenRightShift) << m_greenLeftShift ) |
( ((uint16_t)blue >> m_blueRightShift) << m_blueLeftShift );
BLEND_PIXEL(value, r, g, b, a, uint16_t)
pPixel[0] = value;
value >>= 8;
pPixel[0] = value; value >>= 8;
pPixel[1] = value;
}
void X11Display::makePixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
void X11Display::blendPixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
// Get the current pixel value
uint32_t value = pPixel[3] | pPixel[2] << 8 | pPixel[1] << 16 |
pPixel[0] << 24;
// Compute the new color values
uint16_t temp;
temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
uint8_t red = ( temp * (255 - a) + r * a ) / 255;
temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
uint8_t green = ( temp * (255 - a) + g * a ) / 255;
temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
// Set the new pixel value
value =
( ((uint32_t)red >> m_redRightShift) << m_redLeftShift ) |
( ((uint32_t)green >> m_greenRightShift) << m_greenLeftShift ) |
( ((uint32_t)blue >> m_blueRightShift) << m_blueLeftShift );
BLEND_PIXEL(value, r, g, b, a, uint32_t)
pPixel[3] = value;
value >>= 8;
pPixel[2] = value;
value >>= 8;
pPixel[1] = value;
value >>= 8;
pPixel[3] = value; value >>= 8;
pPixel[2] = value; value >>= 8;
pPixel[1] = value; value >>= 8;
pPixel[0] = value;
}
void X11Display::makePixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
void X11Display::blendPixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
// Get the current pixel value
uint32_t value = pPixel[0] | pPixel[1] << 8 | pPixel[2] << 16 |
pPixel[3] << 24;
// Compute the new color values
uint16_t temp;
temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
uint8_t red = ( temp * (255 - a) + r * a ) / 255;
temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
uint8_t green = ( temp * (255 - a) + g * a ) / 255;
temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
// Set the new pixel value
value =
( ((uint32_t)red >> m_redRightShift) << m_redLeftShift ) |
( ((uint32_t)green >> m_greenRightShift) << m_greenLeftShift ) |
( ((uint32_t)blue >> m_blueRightShift) << m_blueLeftShift );
BLEND_PIXEL(value, r, g, b, a, uint32_t)
pPixel[0] = value; value >>= 8;
pPixel[1] = value; value >>= 8;
pPixel[2] = value; value >>= 8;
pPixel[3] = value;
}
void X11Display::putPixel8( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
uint8_t value = 255 - *pPixel;
PUT_PIXEL(value, r, g, b, uint8_t)
*pPixel = 255 - value;
}
void X11Display::putPixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
uint16_t value = pPixel[1] | pPixel[0] << 8;
PUT_PIXEL(value, r, g, b, uint16_t)
pPixel[1] = value; value >>= 8;
pPixel[0] = value;
value >>= 8;
}
void X11Display::putPixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
uint16_t value = pPixel[0] | pPixel[1] << 8;
PUT_PIXEL(value, r, g, b, uint16_t)
pPixel[0] = value; value >>= 8;
pPixel[1] = value;
value >>= 8;
pPixel[2] = value;
value >>= 8;
}
void X11Display::putPixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
uint32_t value = pPixel[3] | pPixel[2] << 8 | pPixel[1] << 16 |
pPixel[0] << 24;
PUT_PIXEL(value, r, g, b, uint32_t)
pPixel[3] = value; value >>= 8;
pPixel[2] = value; value >>= 8;
pPixel[1] = value; value >>= 8;
pPixel[0] = value;
}
void X11Display::putPixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
uint8_t b, uint8_t a ) const
{
uint32_t value = pPixel[0] | pPixel[1] << 8 | pPixel[2] << 16 |
pPixel[3] << 24;
PUT_PIXEL(value, r, g, b, uint32_t)
pPixel[0] = value; value >>= 8;
pPixel[1] = value; value >>= 8;
pPixel[2] = value; value >>= 8;
pPixel[3] = value;
}
unsigned long X11Display::getPixelValue( uint8_t r, uint8_t g, uint8_t b ) const
unsigned long X11Display::getPixelValue( uint8_t r, uint8_t g, uint8_t b )
const
{
unsigned long value;
value = ( ((uint32_t)r >> m_redRightShift) << m_redLeftShift ) |
......
......@@ -58,12 +58,15 @@ class X11Display: public SkinObject
/// Get the colormap
Colormap getColormap() const { return m_colormap; }
/// Type of function to convert RGB values into a pixel
/// Type of function to put RGBA values into a pixel
typedef void (X11Display::*MakePixelFunc_t)( uint8_t *pPixel,
uint8_t r, uint8_t g, uint8_t b, uint8_t a ) const;
/// Get a pointer on the right makePixel implementation
MakePixelFunc_t getMakePixel() const { return makePixelImpl; }
/// Get a pointer on the right blendPixel implementation
MakePixelFunc_t getBlendPixel() const { return blendPixelImpl; }
/// Get a pointer on the right putPixel implementation
MakePixelFunc_t getPutPixel() const { return putPixelImpl; }
/// Get the pixel value corresponding to the given colors
unsigned long getPixelValue( uint8_t r, uint8_t g, uint8_t b ) const;
......@@ -86,33 +89,54 @@ class X11Display: public SkinObject
int m_redLeftShift, m_redRightShift;
int m_greenLeftShift, m_greenRightShift;
int m_blueLeftShift, m_blueRightShift;
/// Pointer on the right implementation of getPixel
MakePixelFunc_t makePixelImpl;
/// Pointer on the right implementation of blendPixel
MakePixelFunc_t blendPixelImpl;
/// Pointer on the right implementation of putPixel
MakePixelFunc_t putPixelImpl;
/// Calculate shifts from a color mask
void getShifts( uint32_t mask, int &rLeftShift,
int &rRightShift ) const;
/// 8 bpp version of makePixel
void makePixel8( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const;
/// 8 bpp version of blendPixel
void blendPixel8( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const;
/// 16 bpp MSB first version of blendPixel
void blendPixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const;
/// 16 bpp LSB first version of blendPixel
void blendPixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const;
/// 24/32 bpp MSB first version of blendPixel
void blendPixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const;
/// 24/32 bpp LSB first version of blendPixel
void blendPixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const;
/// 8 bpp version of putPixel