Commit ab848324 authored by Erwan Tulou's avatar Erwan Tulou

skins2: rework image control (scale while preserving aspect ratio)

 - implement mouseOver (forgotten in prior commit)
 - picture rescaled only when size changed (better performance)
 - some cosmetics
parent 409553d2
...@@ -38,7 +38,8 @@ CtrlImage::CtrlImage( intf_thread_t *pIntf, GenericBitmap &rBitmap, ...@@ -38,7 +38,8 @@ CtrlImage::CtrlImage( intf_thread_t *pIntf, GenericBitmap &rBitmap,
const UString &rHelp, VarBool *pVisible, bool art ): const UString &rHelp, VarBool *pVisible, bool art ):
CtrlFlat( pIntf, rHelp, pVisible ), CtrlFlat( pIntf, rHelp, pVisible ),
m_pBitmap( &rBitmap ), m_pOriginalBitmap( &rBitmap ), m_pBitmap( &rBitmap ), m_pOriginalBitmap( &rBitmap ),
m_rCommand( rCommand ), m_resizeMethod( resizeMethod ), m_art( art ) m_rCommand( rCommand ), m_resizeMethod( resizeMethod ), m_art( art ),
m_x( 0 ), m_y( 0 )
{ {
// Create an initial unscaled image in the buffer // Create an initial unscaled image in the buffer
m_pImage = OSFactory::instance( pIntf )->createOSGraphics( m_pImage = OSFactory::instance( pIntf )->createOSGraphics(
...@@ -94,103 +95,122 @@ void CtrlImage::handleEvent( EvtGeneric &rEvent ) ...@@ -94,103 +95,122 @@ void CtrlImage::handleEvent( EvtGeneric &rEvent )
bool CtrlImage::mouseOver( int x, int y ) const bool CtrlImage::mouseOver( int x, int y ) const
{ {
if( m_resizeMethod == kMosaic && if( x >= 0 && x < getPosition()->getWidth() &&
x >= 0 && x < getPosition()->getWidth() &&
y >= 0 && y < getPosition()->getHeight() ) y >= 0 && y < getPosition()->getHeight() )
{ {
// In mosaic mode, convert the coordinates to make them fit to the // convert the coordinates to make them fit to the
// size of the original image // size of the original image if needed
x %= m_pImage->getWidth(); switch( m_resizeMethod )
y %= m_pImage->getHeight(); {
case kMosaic:
x %= m_pImage->getWidth();
y %= m_pImage->getHeight();
break;
case kScaleAndRatioPreserved:
x -= m_x;
y -= m_y;
break;
case kScale:
break;
}
return m_pImage->hit( x, y );
} }
return m_pImage->hit( x, y );
return false;
} }
void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest ) void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
{ {
const Position *pPos = getPosition(); const Position *pPos = getPosition();
if( pPos ) if( !pPos )
{ return;
int width = pPos->getWidth();
int height = pPos->getHeight(); int width = pPos->getWidth();
int height = pPos->getHeight();
if( width <= 0 || height <= 0 )
return;
if( m_resizeMethod == kScale ) if( m_resizeMethod == kScale )
{
// Use scaling method
if( width != m_pImage->getWidth() ||
height != m_pImage->getHeight() )
{ {
// Use scaling method OSFactory *pOsFactory = OSFactory::instance( getIntf() );
if( width > 0 && height > 0 ) // Rescale the image with the actual size of the control
{ ScaledBitmap bmp( getIntf(), *m_pBitmap, width, height );
if( width != m_pImage->getWidth() || delete m_pImage;
height != m_pImage->getHeight() ) m_pImage = pOsFactory->createOSGraphics( width, height );
{ m_pImage->drawBitmap( bmp, 0, 0 );
OSFactory *pOsFactory = OSFactory::instance( getIntf() );
// Rescale the image with the actual size of the control
ScaledBitmap bmp( getIntf(), *m_pBitmap, width, height );
delete m_pImage;
m_pImage = pOsFactory->createOSGraphics( width, height );
m_pImage->drawBitmap( bmp, 0, 0 );
}
rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
}
} }
else if( m_resizeMethod == kMosaic ) rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
}
else if( m_resizeMethod == kMosaic )
{
// Use mosaic method
while( width > 0 )
{ {
// Use mosaic method int curWidth = __MIN( width, m_pImage->getWidth() );
while( width > 0 ) height = pPos->getHeight();
int curYDest = yDest;
while( height > 0 )
{ {
int curWidth = __MIN( width, m_pImage->getWidth() ); int curHeight = __MIN( height, m_pImage->getHeight() );
height = pPos->getHeight(); rImage.drawGraphics( *m_pImage, 0, 0, xDest, curYDest,
int curYDest = yDest; curWidth, curHeight );
while( height > 0 ) curYDest += curHeight;
{ height -= m_pImage->getHeight();
int curHeight = __MIN( height, m_pImage->getHeight() );
rImage.drawGraphics( *m_pImage, 0, 0, xDest, curYDest,
curWidth, curHeight );
curYDest += curHeight;
height -= m_pImage->getHeight();
}
xDest += curWidth;
width -= m_pImage->getWidth();
} }
xDest += curWidth;
width -= m_pImage->getWidth();
} }
else if( m_resizeMethod == kScaleAndRatioPreserved ) }
{ else if( m_resizeMethod == kScaleAndRatioPreserved )
int width = pPos->getWidth(); {
int height = pPos->getHeight(); int w0 = m_pBitmap->getWidth();
int h0 = m_pBitmap->getHeight();
int w = m_pBitmap->getWidth();
int h = m_pBitmap->getHeight();
int scaled_height = width * h / w;
int scaled_width = height * w / h;
int x, y; int scaled_height = width * h0 / w0;
int scaled_width = height * w0 / h0;
if( scaled_height > height ) // new image scaled with aspect ratio preserved
{ // and centered inside the control boundaries
width = scaled_width; int w, h;
x = ( pPos->getWidth() - width ) / 2; if( scaled_height > height )
y = 0; {
} w = scaled_width;
else h = height;
{ m_x = ( width - w ) / 2;
height = scaled_height; m_y = 0;
x = 0; }
y = ( pPos->getHeight() - height ) / 2; else
} {
w = width;
h = scaled_height;
m_x = 0;
m_y = ( height - h ) / 2;
}
// rescale the image if size changed
if( w != m_pImage->getWidth() ||
h != m_pImage->getHeight() )
{
OSFactory *pOsFactory = OSFactory::instance( getIntf() ); OSFactory *pOsFactory = OSFactory::instance( getIntf() );
// Rescale the image with the actual size of the control ScaledBitmap bmp( getIntf(), *m_pBitmap, w, h );
ScaledBitmap bmp( getIntf(), *m_pBitmap, width, height );
delete m_pImage; delete m_pImage;
m_pImage = pOsFactory->createOSGraphics( width, height ); m_pImage = pOsFactory->createOSGraphics( w, h );
m_pImage->drawBitmap( bmp, 0, 0 ); m_pImage->drawBitmap( bmp, 0, 0 );
rImage.drawGraphics( *m_pImage, 0, 0, xDest + x, yDest + y );
} }
// draw the scaled image at offset (m_x, m_y) from control origin
rImage.drawGraphics( *m_pImage, 0, 0, xDest + m_x, yDest + m_y );
} }
} }
void CtrlImage::onUpdate( Subject<VarString> &rVariable, void* arg ) void CtrlImage::onUpdate( Subject<VarString> &rVariable, void* arg )
{ {
VlcProc *pVlcProc = VlcProc::instance( getIntf() ); VlcProc *pVlcProc = VlcProc::instance( getIntf() );
......
...@@ -78,6 +78,9 @@ private: ...@@ -78,6 +78,9 @@ private:
resize_t m_resizeMethod; resize_t m_resizeMethod;
/// does the image get updated as art /// does the image get updated as art
bool m_art; bool m_art;
/// offset for image inside the control
int m_x;
int m_y;
/// Method called when the observed variable is modified /// Method called when the observed variable is modified
virtual void onUpdate( Subject<VarString> &rVariable, void* ); virtual void onUpdate( Subject<VarString> &rVariable, void* );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment