Commit a1921136 authored by Erwan Tulou's avatar Erwan Tulou

skins2: improve refresh of layouts

Up to now, notification of invalidated subareas was available for controls
but yet, the layout always ended up being totally rebuilt. For instance,
 a small animated image meant a total rebuild of everything. For simple skins,
 this could go unnoticed, but old computers had much difficulty with more
 complex skins (e.g wmp11), that were mostly busy rebuilding layouts
 over and over.

This patch ensures that only what needs to be rebuilt is rebuilt. Some skins
 like wmp11 on Linux do show dramatic improvement with this one patch.
parent 6fad8bff
......@@ -114,16 +114,22 @@ bool CtrlButton::mouseOver( int x, int y ) const
}
void CtrlButton::draw( OSGraphics &rImage, int xDest, int yDest )
{
if( m_pImg )
void CtrlButton::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
const Position *pPos = getPosition();
rect region( pPos->getLeft(), pPos->getTop(),
pPos->getWidth(), pPos->getHeight() );
rect clip( xDest, yDest, w, h );
rect inter;
if( rect::intersect( region, clip, &inter ) && m_pImg )
{
// Draw the current image
m_pImg->draw( rImage, xDest, yDest );
m_pImg->draw( rImage, inter.x, inter.y, inter.width, inter.height,
inter.x - pPos->getLeft(),
inter.y - pPos->getTop() );
}
}
void CtrlButton::setImage( AnimBitmap *pImg )
{
AnimBitmap *pOldImg = m_pImg;
......@@ -147,7 +153,7 @@ void CtrlButton::setImage( AnimBitmap *pImg )
void CtrlButton::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg )
{
notifyLayout();
notifyLayout( m_pImg->getWidth(), m_pImg->getHeight() );
}
......
......@@ -57,7 +57,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Get the text of the tooltip
virtual UString getTooltipText() const { return m_tooltip; }
......
......@@ -134,12 +134,25 @@ bool CtrlCheckbox::mouseOver( int x, int y ) const
}
void CtrlCheckbox::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlCheckbox::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
if( m_pImgCurrent )
if( !m_pImgCurrent )
return;
const Position *pPos = getPosition();
// rect region( pPos->getLeft(), pPos->getTop(),
// pPos->getWidth(), pPos->getHeight() );
rect region( pPos->getLeft(), pPos->getTop(),
m_pImgCurrent->getWidth(), m_pImgCurrent->getHeight() );
rect clip( xDest, yDest, w, h );
rect inter;
if( rect::intersect( region, clip, &inter ) )
{
// Draw the current image
m_pImgCurrent->draw( rImage, xDest, yDest );
m_pImgCurrent->draw( rImage,
inter.x, inter.y, inter.width, inter.height,
inter.x - pPos->getLeft(),
inter.y - pPos->getTop() );
}
}
......@@ -248,7 +261,7 @@ void CtrlCheckbox::onVarBoolUpdate( VarBool &rVariable )
void CtrlCheckbox::onUpdate( Subject<AnimBitmap> &rBitmap, void *arg )
{
notifyLayout();
notifyLayout( m_pImgCurrent->getWidth(), m_pImgCurrent->getHeight() );
}
......
......@@ -61,7 +61,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Get the text of the tooltip XXX
virtual UString getTooltipText() const { return *m_pTooltip; }
......
......@@ -74,8 +74,11 @@ void CtrlGeneric::unsetLayout()
}
void CtrlGeneric::notifyLayout( int width, int height,
int xOffSet, int yOffSet ) const
int xOffSet, int yOffSet )
{
width = ( width > 0 ) ? width : m_pPosition->getWidth();
height = ( height > 0 ) ? height : m_pPosition->getHeight();
// Notify the layout
if( m_pLayout )
{
......
......@@ -53,7 +53,7 @@ public:
virtual bool mouseOver( int x, int y ) const { return false; }
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest ) { }
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h ) { }
/// Set the position and the associated layout of the control
virtual void setLayout( GenericLayout *pLayout,
......@@ -96,7 +96,7 @@ protected:
* Use the default values to repaint the whole window
*/
virtual void notifyLayout( int witdh = -1, int height = -1,
int xOffSet = 0, int yOffSet = 0 ) const;
int xOffSet = 0, int yOffSet = 0 );
/**
* Same as notifyLayout(), but takes optional images as parameters.
......
......@@ -118,7 +118,7 @@ bool CtrlImage::mouseOver( int x, int y ) const
}
void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
const Position *pPos = getPosition();
if( !pPos )
......@@ -129,6 +129,13 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
if( width <= 0 || height <= 0 )
return;
rect region( pPos->getLeft(), pPos->getTop(),
pPos->getWidth(), pPos->getHeight() );
rect clip( xDest, yDest, w, h );
rect inter;
if( !rect::intersect( region, clip, &inter ) )
return;
if( m_resizeMethod == kScale )
{
// Use scaling method
......@@ -142,25 +149,40 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
m_pImage = pOsFactory->createOSGraphics( width, height );
m_pImage->drawBitmap( bmp, 0, 0 );
}
rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
rImage.drawGraphics( *m_pImage,
inter.x - pPos->getLeft(),
inter.y - pPos->getTop(),
inter.x, inter.y,
inter.width, inter.height );
}
else if( m_resizeMethod == kMosaic )
{
int xDest0 = pPos->getLeft();
int yDest0 = pPos->getTop();
// Use mosaic method
while( width > 0 )
{
int curWidth = __MIN( width, m_pImage->getWidth() );
height = pPos->getHeight();
int curYDest = yDest;
int curYDest = yDest0;
while( height > 0 )
{
int curHeight = __MIN( height, m_pImage->getHeight() );
rImage.drawGraphics( *m_pImage, 0, 0, xDest, curYDest,
curWidth, curHeight );
rect region1( xDest0, curYDest, curWidth, curHeight );
rect inter1;
if( rect::intersect( region1, clip, &inter1 ) )
{
rImage.drawGraphics( *m_pImage,
inter1.x - region1.x,
inter1.y - region1.y,
inter1.x, inter1.y,
inter1.width, inter1.height );
}
curYDest += curHeight;
height -= m_pImage->getHeight();
}
xDest += curWidth;
xDest0 += curWidth;
width -= m_pImage->getWidth();
}
}
......@@ -202,7 +224,16 @@ void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
}
// 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 );
rect region1( pPos->getLeft() + m_x, pPos->getTop() + m_y, w, h );
rect inter1;
if( rect::intersect( region1, inter, &inter1 ) )
{
rImage.drawGraphics( *m_pImage,
inter1.x - pPos->getLeft() - m_x,
inter1.y - pPos->getTop() - m_y,
inter1.x, inter1.y,
inter1.width, inter1.height );
}
}
}
......
......@@ -60,7 +60,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Get the type of control (custom RTTI)
virtual string getType() const { return "image"; }
......
......@@ -349,11 +349,19 @@ bool CtrlList::mouseOver( int x, int y ) const
}
void CtrlList::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlList::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
if( m_pImage )
const Position *pPos = getPosition();
rect region( pPos->getLeft(), pPos->getTop(),
pPos->getWidth(), pPos->getHeight() );
rect clip( xDest, yDest, w, h );
rect inter;
if( rect::intersect( region, clip, &inter ) && m_pImage )
{
rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
rImage.drawGraphics( *m_pImage,
inter.x - pPos->getLeft(),
inter.y - pPos->getTop(),
inter.x, inter.y, inter.width, inter.height );
}
}
......
......@@ -53,7 +53,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Called when the layout is resized
virtual void onResize();
......
......@@ -66,9 +66,9 @@ bool CtrlMove::mouseOver( int x, int y ) const
}
void CtrlMove::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlMove::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
m_rCtrl.draw( rImage, xDest, yDest );
m_rCtrl.draw( rImage, xDest, yDest, w, h );
}
......
......@@ -49,7 +49,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Set the position and the associated layout of the decorated control
virtual void setLayout( GenericLayout *pLayout,
......
......@@ -90,18 +90,33 @@ bool CtrlRadialSlider::mouseOver( int x, int y ) const
}
void CtrlRadialSlider::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlRadialSlider::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
rImage.drawGraphics( *m_pImgSeq, 0, m_position * m_height, xDest, yDest,
m_width, m_height );
const Position *pPos = getPosition();
rect region( pPos->getLeft(), pPos->getTop(), m_width, m_height );
rect clip( xDest, yDest, w ,h );
rect inter;
if( rect::intersect( region, clip, &inter ) )
rImage.drawGraphics( *m_pImgSeq,
inter.x - region.x,
inter.y - region.y + m_position * m_height,
inter.x, inter.y,
inter.width, inter.height );
}
void CtrlRadialSlider::onUpdate( Subject<VarPercent> &rVariable,
void *arg )
{
m_position = (int)( m_rVariable.get() * ( m_numImg - 1 ) );
notifyLayout( m_width, m_height );
if( &rVariable == &m_rVariable )
{
int position = (int)( m_rVariable.get() * ( m_numImg - 1 ) );
if( position == m_position )
return;
m_position = position;
notifyLayout( m_width, m_height );
}
}
......
......@@ -55,7 +55,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Get the type of control (custom RTTI)
virtual string getType() const { return "radial_slider"; }
......
......@@ -75,9 +75,9 @@ bool CtrlResize::mouseOver( int x, int y ) const
}
void CtrlResize::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlResize::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
m_rCtrl.draw( rImage, xDest, yDest );
m_rCtrl.draw( rImage, xDest, yDest, w, h );
}
......
......@@ -50,7 +50,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Set the position and the associated layout of the decorated control
virtual void setLayout( GenericLayout *pLayout,
......
......@@ -143,24 +143,65 @@ bool CtrlSliderCursor::mouseOver( int x, int y ) const
}
void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
if( m_pImg )
{
// Compute the position of the cursor
int xPos, yPos;
m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
// Draw the current image
rect inter;
rect clip( xDest, yDest, w, h);
if( rect::intersect( m_currentCursorRect, clip, &inter ) )
rImage.drawGraphics( *m_pImg,
inter.x - m_currentCursorRect.x,
inter.y - m_currentCursorRect.y,
inter.x, inter.y, inter.width, inter.height );
}
}
// Compute the resize factors
float factorX, factorY;
getResizeFactors( factorX, factorY );
xPos = (int)(xPos * factorX);
yPos = (int)(yPos * factorY);
// Draw the current image
rImage.drawGraphics( *m_pImg, 0, 0,
xDest + xPos - m_pImg->getWidth() / 2,
yDest + yPos - m_pImg->getHeight() / 2 );
void CtrlSliderCursor::onPositionChange()
{
// Compute the position of the cursor
int xPos, yPos;
m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
// Compute the resize factors
float factorX, factorY;
getResizeFactors( factorX, factorY );
xPos = (int)(xPos * factorX);
yPos = (int)(yPos * factorY);
const Position *pPos = getPosition();
int x = pPos->getLeft() + xPos - m_pImg->getWidth() / 2;
int y = pPos->getTop() + yPos - m_pImg->getHeight() / 2;
m_currentCursorRect = rect( x, y, m_pImg->getWidth(), m_pImg->getHeight() );
}
void CtrlSliderCursor::onResize()
{
onPositionChange();
}
void CtrlSliderCursor::notifyLayout( int width, int height, int xOffSet, int yOffSet )
{
if( width > 0 && height > 0 )
{
CtrlGeneric::notifyLayout( width, height, xOffSet, yOffSet );
}
else
{
onPositionChange();
const Position *pPos = getPosition();
CtrlGeneric::notifyLayout( m_currentCursorRect.width,
m_currentCursorRect.height,
m_currentCursorRect.x - pPos->getLeft(),
m_currentCursorRect.y - pPos->getTop() );
}
}
......@@ -169,7 +210,7 @@ void CtrlSliderCursor::onUpdate( Subject<VarPercent> &rVariable,
void *arg )
{
// The position has changed
refreshLayout();
refreshLayout( false );
}
......@@ -280,20 +321,42 @@ void CtrlSliderCursor::getResizeFactors( float &rFactorX,
}
void CtrlSliderCursor::refreshLayout()
void CtrlSliderCursor::refreshLayout( bool force )
{
if( !m_pImg )
notifyLayout();
else
// Compute the position of the cursor
int xPos, yPos;
m_rCurve.getPoint( m_rVariable.get(), xPos, yPos );
// Compute the resize factors
float factorX, factorY;
getResizeFactors( factorX, factorY );
xPos = (int)(xPos * factorX);
yPos = (int)(yPos * factorY);
const Position *pPos = getPosition();
int x = pPos->getLeft() + xPos - m_pImg->getWidth() / 2;
int y = pPos->getTop() + yPos - m_pImg->getHeight() / 2;
rect region( x, y, m_pImg->getWidth(), m_pImg->getHeight() );
if( !force &&
region.x == m_currentCursorRect.x &&
region.y == m_currentCursorRect.y &&
region.width == m_currentCursorRect.width &&
region.height == m_currentCursorRect.height )
{
// Compute the resize factors
float factorX, factorY;
getResizeFactors( factorX, factorY );
return;
}
notifyLayout( (int)(m_rCurve.getWidth() * factorX) + m_pImg->getWidth(),
(int)(m_rCurve.getHeight() * factorY) + m_pImg->getHeight(),
- m_pImg->getWidth() / 2,
- m_pImg->getHeight() / 2 );
rect join;
if( rect::join( m_currentCursorRect, region, &join ) )
{
m_currentCursorRect = region;
notifyLayout( join.width, join.height,
join.x - pPos->getLeft(),
join.y - pPos->getTop() );
}
}
......@@ -308,9 +371,9 @@ CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf,
m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
m_pImgSeq( pBackground ), m_nbHoriz( nbHoriz ), m_nbVert( nbVert ),
m_padHoriz( padHoriz ), m_padVert( padVert ), m_bgWidth( 0 ),
m_bgHeight( 0 ), m_position( 0 )
m_bgHeight( 0 ), m_position( 0 ), m_pScaledBmp( NULL )
{
if( pBackground )
if( m_pImgSeq )
{
// Build the background image sequence
// Note: we suppose that the last padding is not included in the
......@@ -332,7 +395,10 @@ CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf,
CtrlSliderBg::~CtrlSliderBg()
{
m_rVariable.delObserver( this );
if( m_pImgSeq )
m_rVariable.delObserver( this );
delete m_pScaledBmp;
}
......@@ -347,7 +413,7 @@ bool CtrlSliderBg::mouseOver( int x, int y ) const
}
void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
if( !m_pImgSeq || m_bgWidth <=0 || m_bgHeight <= 0 )
return;
......@@ -356,18 +422,35 @@ void CtrlSliderBg::draw( OSGraphics &rImage, int xDest, int yDest )
float factorX, factorY;
getResizeFactors( factorX, factorY );
// Rescale the image with the actual size of the control
ScaledBitmap bmp( getIntf(), *m_pImgSeq,
m_bgWidth * m_nbHoriz - (int)(m_padHoriz * factorX),
m_bgHeight * m_nbVert - (int)(m_padVert * factorY) );
int width = m_bgWidth * m_nbHoriz - (int)(m_padHoriz * factorX);
int height = m_bgHeight * m_nbVert - (int)(m_padVert * factorY);
// Rescale the image with the actual size of the control if needed
if( !m_pScaledBmp ||
m_pScaledBmp->getWidth() != width ||
m_pScaledBmp->getHeight() != height )
{
delete m_pScaledBmp;
m_pScaledBmp = new ScaledBitmap( getIntf(), *m_pImgSeq, width, height );
}
// Locate the right image in the background bitmap
int x = m_bgWidth * ( m_position % m_nbHoriz );
int y = m_bgHeight * ( m_position / m_nbHoriz );
// Draw the background image
rImage.drawBitmap( bmp, x, y, xDest, yDest,
m_bgWidth - (int)(m_padHoriz * factorX),
m_bgHeight - (int)(m_padVert * factorY) );
const Position *pPos = getPosition();
rect region( pPos->getLeft(), pPos->getTop(),
m_bgWidth - (int)(m_padHoriz * factorX),
m_bgHeight - (int)(m_padVert * factorY) );
rect clip( xDest, yDest, w, h );
rect inter;
if( rect::intersect( region, clip, &inter ) )
rImage.drawBitmap( *m_pScaledBmp,
x + inter.x - region.x,
y + inter.y - region.y,
inter.x, inter.y,
inter.width, inter.height );
}
......
......@@ -32,6 +32,7 @@
class GenericBitmap;
class ScaledBitmap;
class OSGraphics;
class VarPercent;
......@@ -58,7 +59,18 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Called when the position is set
virtual void onPositionChange();
/// Method called when the control is resized
virtual void onResize();
/// Method called to notify are to be updated
virtual void notifyLayout( int witdh = -1, int height = -1,
int xOffSet = 0, int yOffSet = 0 );
/// Get the text of the tooltip
virtual UString getTooltipText() const { return m_tooltip; }
......@@ -77,6 +89,7 @@ private:
int m_width, m_height;
/// Position of the cursor
int m_xPosition, m_yPosition;
rect m_currentCursorRect;
/// Callback objects
DEFINE_CALLBACK( CtrlSliderCursor, OverDown )
DEFINE_CALLBACK( CtrlSliderCursor, DownOver )
......@@ -104,7 +117,7 @@ private:
void getResizeFactors( float &rFactorX, float &rFactorY ) const;
/// Call notifyLayout
void refreshLayout();
void refreshLayout( bool force = true );
};
......@@ -123,7 +136,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Handle an event
virtual void handleEvent( EvtGeneric &rEvent );
......@@ -150,6 +163,8 @@ private:
int m_width, m_height;
/// Background image sequence (optional)
GenericBitmap *m_pImgSeq;
/// Scaled bitmap if needed
ScaledBitmap *m_pScaledBmp;
/// Number of images in the background bitmap
int m_nbHoriz, m_nbVert;
/// Number of pixels between two images
......
......@@ -150,8 +150,10 @@ bool CtrlText::mouseOver( int x, int y ) const
}
void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h )
{
rect clip( xDest, yDest, w, h );
const Position *pPos = getPosition();
if( m_pCurrImg )
{
// Compute the dimensions to draw
......@@ -178,12 +180,18 @@ void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
else if( m_alignment == kCenter &&
width < getPosition()->getWidth() )
{
// The text is shorter than the width of the control, so we
// can center it
// The text is shorter than the width of the control, so we
// can center it
offset = (getPosition()->getWidth() - width) / 2;
}
rImage.drawBitmap( *m_pCurrImg, -m_xPos, 0, xDest + offset,
yDest, width, height, true );
rect region( pPos->getLeft() + offset,
pPos->getTop(), width, height );
rect inter;
if( rect::intersect( region, clip, &inter ) )
rImage.drawBitmap( *m_pCurrImg, -m_xPos + inter.x - region.x,
inter.y - region.y,
inter.x, inter.y,
inter.width, inter.height, true );
}
}
}
......
......@@ -74,7 +74,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Set the text of the control, with an optional color
/// This takes effect immediatly
......
......@@ -636,10 +636,19 @@ bool CtrlTree::mouseOver( int x, int y ) const
x >= 0 && x <= pPos->getWidth() && y >= 0 && y <= pPos->getHeight();
}
void CtrlTree::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlTree::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h)
{
if( m_pImage )
rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
const Position *pPos = getPosition();
rect region( pPos->getLeft(), pPos->getTop(),
pPos->getWidth(), pPos->getHeight() );
rect clip( xDest, yDest, w, h );
rect inter;
if( rect::intersect( region, clip, &inter ) && m_pImage )
rImage.drawGraphics( *m_pImage,
inter.x - pPos->getLeft(),
inter.y - pPos->getTop(),
inter.x, inter.y, inter.width, inter.height );
}
bool CtrlTree::ensureVisible( VarTree::Iterator item )
......
......@@ -62,7 +62,7 @@ public:
virtual bool mouseOver( int x, int y ) const;
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Called when the layout is resized
virtual void onResize();
......
......@@ -85,14 +85,25 @@ void CtrlVideo::onPositionChange()
}
void CtrlVideo::draw( OSGraphics &rImage, int xDest, int yDest )
void CtrlVideo::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h)
{
const Position *pPos = getPosition();
if( pPos )
rect region( pPos->getLeft(), pPos->getTop(),
pPos->getWidth(), pPos->getHeight() );
rect clip( xDest, yDest, w, h );
rect inter;
if( rect::intersect( region, clip, &inter ) )
{
// Draw a black rectangle under the video to avoid transparency
rImage.fillRect( pPos->getLeft(), pPos->getTop(), pPos->getWidth(),
pPos->getHeight(), 0 );
rImage.fillRect( inter.x, inter.y, inter.width, inter.height, 0 );
}
if( m_pVoutWindow )
{
m_pVoutWindow->move( pPos->getLeft(), pPos->getTop() );
m_pVoutWindow->resize( pPos->getWidth(), pPos->getHeight() );
m_pVoutWindow->show();
}
}
......
......@@ -51,7 +51,7 @@ public:
virtual void onPositionChange();
/// Draw the control on the given graphics
virtual void draw( OSGraphics &rImage, int xDest, int yDest );
virtual void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h );
/// Get the type of control (custom RTTI)
virtual string getType() const { return "video"; }
......
......@@ -69,7 +69,8 @@ void AnimBitmap::stopAnim()
}
void AnimBitmap::draw( OSGraphics &rImage, int xDest, int yDest )
void AnimBitmap::draw( OSGraphics &rImage, int xDest, int yDest, int w, int h,
int xOffset, int yOffset )
{
// Draw the current frame
int height = m_pImage->getHeight() / m_nbFrames;
......@@ -79,9 +80,9 @@ void AnimBitmap::draw( OSGraphics &rImage, int xDest, int yDest )
// rImage.drawGraphics( *m_pImage, 0, ySrc, xDest, yDest,
// m_pImage->getWidth(), height );
// A new way .... needs to be tested thoroughly
rImage.drawBitmap( m_rBitmap, 0, ySrc, xDest, yDest,
m_pImage->getWidth(), height, true );
rImage.drawBitmap( m_rBitmap,
xOffset, ySrc + yOffset,
xDest, yDest, w, h, true );
}
......
......@@ -49,7 +49,7 @@ public:
void stopAnim();
/// Draw the current frame on another graphics
void draw( OSGraphics &rImage, int xDest, int yDest );
void draw( OSGraphics &rImage, int xDest, int yDest, int w, int h, int xOffset = 0, int yOffset = 0 );
/// Tell whether the pixel at the given position is visible
bool hit( int x, int y ) const;
......
......@@ -109,10 +109,6 @@ void GenericLayout::addControl( CtrlGeneric *pControl,
// Associate this layout to the control
pControl->setLayout( this, rPosition );
// Draw the control
if( pControl->isVisible() )
pControl->draw( *m_pImage, rPosition.getLeft(), rPosition.getTop() );
// Add the control in the list.
// This list must remain sorted by layer order
list<LayeredControl>::iterator it;
......@@ -153,19 +149,23 @@ void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl,
int width, int height,
int xOffSet, int yOffSet )
{
// The size is not valid, refresh the whole layout
if( width <= 0 || height <= 0 )
{
refreshAll();
// Do nothing if the layout or control is hidden
if( !m_visible )
return;
}
const Position *pPos = rCtrl.getPosition();
if( pPos )
if( width > 0 && height > 0 )
{
refreshRect( pPos->getLeft() + xOffSet,
// make sure region is within the layout
rect region( pPos->getLeft() + xOffSet,
pPos->getTop() + yOffSet,
width, height );
rect layout( 0, 0, m_rect.getWidth(), m_rect.getHeight() );
rect inter;
if( rect::intersect( layout, region, &inter ) )
{
refreshRect( inter.x, inter.y, inter.width, inter.height );
}
}
}
......@@ -223,10 +223,9 @@ void GenericLayout::refreshRect( int x, int y, int width, int height )
for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
{
CtrlGeneric *pCtrl = (*iter).m_pControl;
const Position *pPos = pCtrl->getPosition();
if( pPos && pCtrl->isVisible() )
if( pCtrl->isVisible() )
{
pCtrl->draw( *m_pImage, pPos->getLeft(), pPos->getTop() );
pCtrl->draw( *m_pImage, x, y, width, height );
}
}
......@@ -237,16 +236,6 @@ void GenericLayout::refreshRect( int x, int y, int width, int height )
// first apply new shape to the window
pWindow->updateShape();
// Check boundaries
if( x < 0 )
x = 0;
if( y < 0)
y = 0;
if( x + width > m_rect.getWidth() )
width = m_rect.getWidth() - x;
if( y + height > m_rect.getHeight() )
height = m_rect.getHeight() - y;
pWindow->refresh( x, y, width, height );
}
}
......
......@@ -93,4 +93,110 @@ private:
};
class rect
{
public:
rect( int v_x = 0, int v_y = 0, int v_width = 0, int v_height = 0 )
: x( v_x ), y( v_y ), width( v_width ), height( v_height ) { }
~rect() { }
int x;
int y;
int width;
int height;
// rect2 fully included in rect1
static bool isIncluded( rect& rect2, rect& rect1 )
{
int x1 = rect1.x;
int y1 = rect1.y;
int w1 = rect1.width;
int h1 = rect1.height;
int x2 = rect2.x;
int y2 = rect2.y;
int w2 = rect2.width;
int h2 = rect2.height;
return x2 >= x1 && x2 < x1 + w1
&& y2 >= y1 && y2 < y1 + h1
&& w2 <= w1
&& h2 <= h1;
}
static bool areDisjunct( rect& rect2, rect& rect1 )
{
int x1 = rect1.x;
int y1 = rect1.y;
int w1 = rect1.width;
int h1 = rect1.height;
int x2 = rect2.x;
int y2 = rect2.y;
int w2 = rect2.width;
int h2 = rect2.height;
return y2 + h2 -1 < y1 // rect2 above rect1
|| y2 > y1 + h1 - 1 // rect2 under rect1
|| x2 > x1 + w1 -1 // rect2 right of rect1
|| x2 + w2 - 1 < x1; // rect2 left of rect1
}
static bool intersect( rect& rect1, rect& rect2, rect* pRect )
{
int x1 = rect1.x;
int y1 = rect1.y;
int w1 = rect1.width;
int h1 = rect1.height;
int x2 = rect2.x;
int y2 = rect2.y;
int w2 = rect2.width;
int h2 = rect2.height;
if( areDisjunct( rect1, rect2 ) )
return false;
else
{
int left = max( x1, x2 );
int right = min( x1 + w1 - 1, x2 + w2 - 1 );
int top = max( y1, y2 );
int bottom = min( y1 + h1 - 1, y2 + h2 -1 );
pRect->x = left;
pRect->y = top;
pRect->width = right - left + 1;
pRect->height = bottom - top + 1;
return pRect->width > 0 && pRect->height > 0;
}
}
static bool join( rect& rect1, rect& rect2, rect* pRect )
{
int x1 = rect1.x;
int y1 = rect1.y;
int w1 = rect1.width;
int h1 = rect1.height;
int x2 = rect2.x;
int y2 = rect2.y;
int w2 = rect2.width;
int h2 = rect2.height;
int left = min( x1, x2 );
int right = max( x1 + w1 - 1, x2 + w2 - 1 );
int top = min( y1, y2 );
int bottom = max( y1 + h1 - 1, y2 + h2 -1 );
pRect->x = left;
pRect->y = top;
pRect->width = right - left + 1;
pRect->height = bottom - top + 1;
return pRect->width > 0 && pRect->height > 0;
}
static int min( int x, int y ) { return x < y ? x : y; }
static int max( int x, int y ) { return x < y ? y : x; }
};
#endif
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