loplugin:flatten in canvas

Change-Id: If14af63ab4f8fc7b9807319a2100f371ee103465
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92481
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
Noel Grandin
2020-04-18 14:13:49 +02:00
parent cd0ab2cf50
commit 7fa4f64098
14 changed files with 674 additions and 674 deletions

View File

@@ -59,30 +59,30 @@ namespace cairocanvas
maFont->SetLanguage( LanguageTag::convertToLanguageType( rFontRequest.Locale, false)); maFont->SetLanguage( LanguageTag::convertToLanguageType( rFontRequest.Locale, false));
// adjust to stretched/shrunk font // adjust to stretched/shrunk font
if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) ) if( ::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
{ return;
VclPtr<OutputDevice> pOutDev( mpRefDevice->getOutputDevice() );
if( pOutDev ) VclPtr<OutputDevice> pOutDev( mpRefDevice->getOutputDevice() );
{
const bool bOldMapState( pOutDev->IsMapModeEnabled() );
pOutDev->EnableMapMode(false);
const Size aSize = pOutDev->GetFontMetric( *maFont ).GetFontSize(); if( !pOutDev )
return;
const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 ); const bool bOldMapState( pOutDev->IsMapModeEnabled() );
double fStretch = rFontMatrix.m00 + rFontMatrix.m01; pOutDev->EnableMapMode(false);
if( !::basegfx::fTools::equalZero( fDividend) ) const Size aSize = pOutDev->GetFontMetric( *maFont ).GetFontSize();
fStretch /= fDividend;
const long nNewWidth = ::basegfx::fround( aSize.Width() * fStretch ); const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
double fStretch = rFontMatrix.m00 + rFontMatrix.m01;
maFont->SetAverageFontWidth( nNewWidth ); if( !::basegfx::fTools::equalZero( fDividend) )
fStretch /= fDividend;
pOutDev->EnableMapMode(bOldMapState); const long nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
}
} maFont->SetAverageFontWidth( nNewWidth );
pOutDev->EnableMapMode(bOldMapState);
} }
void SAL_CALL CanvasFont::disposing() void SAL_CALL CanvasFont::disposing()

View File

@@ -216,25 +216,25 @@ namespace cairocanvas
{ {
SAL_INFO( "canvas.cairo", "clear whole area: " << maSize.getX() << " x " << maSize.getY() ); SAL_INFO( "canvas.cairo", "clear whole area: " << maSize.getX() << " x " << maSize.getY() );
if( mpCairo ) if( !mpCairo )
{ return;
cairo_save( mpCairo.get() );
cairo_identity_matrix( mpCairo.get() ); cairo_save( mpCairo.get() );
// this does not really differ from all-zero, as cairo
// internally converts to premultiplied alpha. but anyway,
// this keeps it consistent with the other canvas impls
if( mbHaveAlpha )
cairo_set_source_rgba( mpCairo.get(), 1.0, 1.0, 1.0, 0.0 );
else
cairo_set_source_rgb( mpCairo.get(), 1.0, 1.0, 1.0 );
cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() ); cairo_identity_matrix( mpCairo.get() );
cairo_fill( mpCairo.get() ); // this does not really differ from all-zero, as cairo
// internally converts to premultiplied alpha. but anyway,
// this keeps it consistent with the other canvas impls
if( mbHaveAlpha )
cairo_set_source_rgba( mpCairo.get(), 1.0, 1.0, 1.0, 0.0 );
else
cairo_set_source_rgb( mpCairo.get(), 1.0, 1.0, 1.0 );
cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
cairo_restore( mpCairo.get() ); cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() );
} cairo_fill( mpCairo.get() );
cairo_restore( mpCairo.get() );
} }
void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/, void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/,
@@ -243,20 +243,20 @@ namespace cairocanvas
const rendering::ViewState& viewState, const rendering::ViewState& viewState,
const rendering::RenderState& renderState ) const rendering::RenderState& renderState )
{ {
if( mpCairo ) if( !mpCairo )
{ return;
cairo_save( mpCairo.get() );
cairo_set_line_width( mpCairo.get(), 1 ); cairo_save( mpCairo.get() );
useStates( viewState, renderState, true ); cairo_set_line_width( mpCairo.get(), 1 );
cairo_move_to( mpCairo.get(), aStartPoint.X + 0.5, aStartPoint.Y + 0.5 ); useStates( viewState, renderState, true );
cairo_line_to( mpCairo.get(), aEndPoint.X + 0.5, aEndPoint.Y + 0.5 );
cairo_stroke( mpCairo.get() );
cairo_restore( mpCairo.get() ); cairo_move_to( mpCairo.get(), aStartPoint.X + 0.5, aStartPoint.Y + 0.5 );
} cairo_line_to( mpCairo.get(), aEndPoint.X + 0.5, aEndPoint.Y + 0.5 );
cairo_stroke( mpCairo.get() );
cairo_restore( mpCairo.get() );
} }
void CanvasHelper::drawBezier( const rendering::XCanvas* , void CanvasHelper::drawBezier( const rendering::XCanvas* ,
@@ -265,25 +265,25 @@ namespace cairocanvas
const rendering::ViewState& viewState, const rendering::ViewState& viewState,
const rendering::RenderState& renderState ) const rendering::RenderState& renderState )
{ {
if( mpCairo ) if( !mpCairo )
{ return;
cairo_save( mpCairo.get() );
cairo_set_line_width( mpCairo.get(), 1 ); cairo_save( mpCairo.get() );
useStates( viewState, renderState, true ); cairo_set_line_width( mpCairo.get(), 1 );
cairo_move_to( mpCairo.get(), aBezierSegment.Px + 0.5, aBezierSegment.Py + 0.5 ); useStates( viewState, renderState, true );
// tdf#99165 correction of control points not needed here, only hairlines drawn
// (see cairo_set_line_width above)
cairo_curve_to( mpCairo.get(),
aBezierSegment.C1x + 0.5, aBezierSegment.C1y + 0.5,
aBezierSegment.C2x + 0.5, aBezierSegment.C2y + 0.5,
aEndPoint.X + 0.5, aEndPoint.Y + 0.5 );
cairo_stroke( mpCairo.get() );
cairo_restore( mpCairo.get() ); cairo_move_to( mpCairo.get(), aBezierSegment.Px + 0.5, aBezierSegment.Py + 0.5 );
} // tdf#99165 correction of control points not needed here, only hairlines drawn
// (see cairo_set_line_width above)
cairo_curve_to( mpCairo.get(),
aBezierSegment.C1x + 0.5, aBezierSegment.C1y + 0.5,
aBezierSegment.C2x + 0.5, aBezierSegment.C2y + 0.5,
aEndPoint.X + 0.5, aEndPoint.Y + 0.5 );
cairo_stroke( mpCairo.get() );
cairo_restore( mpCairo.get() );
} }
#define PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME "Canvas::ParametricPolyPolygon" #define PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME "Canvas::ParametricPolyPolygon"

View File

@@ -232,21 +232,21 @@ namespace cairocanvas
{ {
static sal_Int32 nFilePostfixCount(0); static sal_Int32 nFilePostfixCount(0);
if( mpRefDevice ) if( !mpRefDevice )
{ return;
OUString aFilename = "dbg_frontbuffer" + OUString::number(nFilePostfixCount) + ".bmp";
SvFileStream aStream( aFilename, StreamMode::STD_READWRITE ); OUString aFilename = "dbg_frontbuffer" + OUString::number(nFilePostfixCount) + ".bmp";
const ::Point aEmptyPoint; SvFileStream aStream( aFilename, StreamMode::STD_READWRITE );
bool bOldMap( mpRefDevice->IsMapModeEnabled() );
mpRefDevice->EnableMapMode( false );
const ::BitmapEx aTempBitmap(mpRefDevice->GetBitmapEx(aEmptyPoint, mpRefDevice->GetOutputSizePixel()));
WriteDIB(aTempBitmap, aStream, false);
mpRefDevice->EnableMapMode( bOldMap );
++nFilePostfixCount; const ::Point aEmptyPoint;
} bool bOldMap( mpRefDevice->IsMapModeEnabled() );
mpRefDevice->EnableMapMode( false );
const ::BitmapEx aTempBitmap(mpRefDevice->GetBitmapEx(aEmptyPoint, mpRefDevice->GetOutputSizePixel()));
WriteDIB(aTempBitmap, aStream, false);
mpRefDevice->EnableMapMode( bOldMap );
++nFilePostfixCount;
} }
SurfaceSharedPtr DeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, int aContent ) SurfaceSharedPtr DeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, int aContent )

View File

@@ -83,75 +83,75 @@ namespace cairocanvas
const double fAlpha( getAlpha() ); const double fAlpha( getAlpha() );
const ::basegfx::B2DHomMatrix aTransform( getTransformation() ); const ::basegfx::B2DHomMatrix aTransform( getTransformation() );
if( isActive() && !::basegfx::fTools::equalZero( fAlpha ) ) if( !(isActive() && !::basegfx::fTools::equalZero( fAlpha )) )
return;
SAL_INFO( "canvas.cairo", "CanvasCustomSprite::redraw called");
if( !pCairo )
return;
basegfx::B2DVector aSize = getSizePixel();
cairo_save( pCairo.get() );
double fX, fY;
fX = rPos.getX();
fY = rPos.getY();
if( !aTransform.isIdentity() )
{ {
SAL_INFO( "canvas.cairo", "CanvasCustomSprite::redraw called"); cairo_matrix_t aMatrix, aInverseMatrix;
if( pCairo ) cairo_matrix_init( &aMatrix,
{ aTransform.get( 0, 0 ), aTransform.get( 1, 0 ), aTransform.get( 0, 1 ),
basegfx::B2DVector aSize = getSizePixel(); aTransform.get( 1, 1 ), aTransform.get( 0, 2 ), aTransform.get( 1, 2 ) );
cairo_save( pCairo.get() );
double fX, fY; aMatrix.x0 = basegfx::fround( aMatrix.x0 );
aMatrix.y0 = basegfx::fround( aMatrix.y0 );
fX = rPos.getX(); cairo_matrix_init( &aInverseMatrix, aMatrix.xx, aMatrix.yx, aMatrix.xy, aMatrix.yy, aMatrix.x0, aMatrix.y0 );
fY = rPos.getY(); cairo_matrix_invert( &aInverseMatrix );
cairo_matrix_transform_distance( &aInverseMatrix, &fX, &fY );
if( !aTransform.isIdentity() ) cairo_set_matrix( pCairo.get(), &aMatrix );
{
cairo_matrix_t aMatrix, aInverseMatrix;
cairo_matrix_init( &aMatrix,
aTransform.get( 0, 0 ), aTransform.get( 1, 0 ), aTransform.get( 0, 1 ),
aTransform.get( 1, 1 ), aTransform.get( 0, 2 ), aTransform.get( 1, 2 ) );
aMatrix.x0 = basegfx::fround( aMatrix.x0 );
aMatrix.y0 = basegfx::fround( aMatrix.y0 );
cairo_matrix_init( &aInverseMatrix, aMatrix.xx, aMatrix.yx, aMatrix.xy, aMatrix.yy, aMatrix.x0, aMatrix.y0 );
cairo_matrix_invert( &aInverseMatrix );
cairo_matrix_transform_distance( &aInverseMatrix, &fX, &fY );
cairo_set_matrix( pCairo.get(), &aMatrix );
}
fX = basegfx::fround( fX );
fY = basegfx::fround( fY );
cairo_matrix_t aOrigMatrix;
cairo_get_matrix( pCairo.get(), &aOrigMatrix );
cairo_translate( pCairo.get(), fX, fY );
if( getClip().is() )
{
const uno::Reference<rendering::XPolyPolygon2D>& rClip( getClip() );
::basegfx::B2DPolyPolygon aClipPoly(
::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
rClip ));
doPolyPolygonImplementation( aClipPoly, Clip, pCairo.get(),
nullptr, SurfaceProviderRef(mpSpriteCanvas.get()),
rClip->getFillRule() );
}
SAL_INFO( "canvas.cairo","aSize " << aSize.getX() << " x " << aSize.getY() << " position: " << fX << "," << fY );
cairo_rectangle( pCairo.get(), 0, 0, floor( aSize.getX() ), floor( aSize.getY() ) );
cairo_clip( pCairo.get() );
cairo_set_matrix( pCairo.get(), &aOrigMatrix );
if( isContentFullyOpaque() )
cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
cairo_set_source_surface( pCairo.get(),
mpBufferSurface->getCairoSurface().get(),
fX, fY );
if( ::rtl::math::approxEqual( fAlpha, 1.0 ) )
cairo_paint( pCairo.get() );
else
cairo_paint_with_alpha( pCairo.get(), fAlpha );
cairo_restore( pCairo.get() );
}
} }
fX = basegfx::fround( fX );
fY = basegfx::fround( fY );
cairo_matrix_t aOrigMatrix;
cairo_get_matrix( pCairo.get(), &aOrigMatrix );
cairo_translate( pCairo.get(), fX, fY );
if( getClip().is() )
{
const uno::Reference<rendering::XPolyPolygon2D>& rClip( getClip() );
::basegfx::B2DPolyPolygon aClipPoly(
::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
rClip ));
doPolyPolygonImplementation( aClipPoly, Clip, pCairo.get(),
nullptr, SurfaceProviderRef(mpSpriteCanvas.get()),
rClip->getFillRule() );
}
SAL_INFO( "canvas.cairo","aSize " << aSize.getX() << " x " << aSize.getY() << " position: " << fX << "," << fY );
cairo_rectangle( pCairo.get(), 0, 0, floor( aSize.getX() ), floor( aSize.getY() ) );
cairo_clip( pCairo.get() );
cairo_set_matrix( pCairo.get(), &aOrigMatrix );
if( isContentFullyOpaque() )
cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
cairo_set_source_surface( pCairo.get(),
mpBufferSurface->getCairoSurface().get(),
fX, fY );
if( ::rtl::math::approxEqual( fAlpha, 1.0 ) )
cairo_paint( pCairo.get() );
else
cairo_paint_with_alpha( pCairo.get(), fAlpha );
cairo_restore( pCairo.get() );
#ifdef CAIRO_CANVAS_PERF_TRACE #ifdef CAIRO_CANVAS_PERF_TRACE
mxDevice->stopPerfTrace( &aTimer, "sprite redraw" ); mxDevice->stopPerfTrace( &aTimer, "sprite redraw" );
#endif #endif

View File

@@ -400,21 +400,21 @@ namespace oglcanvas
const rendering::ViewState& viewState, const rendering::ViewState& viewState,
const rendering::RenderState& renderState ) const rendering::RenderState& renderState )
{ {
if( mpDevice ) if( !mpDevice )
{ return;
mpRecordedActions->push_back( Action() );
Action& rAct=mpRecordedActions->back();
setupGraphicsState( rAct, viewState, renderState ); mpRecordedActions->push_back( Action() );
Action& rAct=mpRecordedActions->back();
// TODO(F2): subdivide&render whole curve setupGraphicsState( rAct, viewState, renderState );
rAct.maFunction = std::bind(&lcl_drawLine,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, // TODO(F2): subdivide&render whole curve
geometry::RealPoint2D( rAct.maFunction = std::bind(&lcl_drawLine,
aBezierSegment.Px, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5,
aBezierSegment.Py), geometry::RealPoint2D(
aEndPoint); aBezierSegment.Px,
} aBezierSegment.Py),
aEndPoint);
} }
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* /*pCanvas*/, uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* /*pCanvas*/,

View File

@@ -194,29 +194,29 @@ namespace canvas
{ {
// check whether bitmap is non-alpha, and whether its // check whether bitmap is non-alpha, and whether its
// transformed size covers the whole sprite. // transformed size covers the whole sprite.
if( !xBitmap->hasAlpha() ) if( xBitmap->hasAlpha() )
{ return;
const geometry::IntegerSize2D& rInputSize(
xBitmap->getSize() );
const ::basegfx::B2DSize& rOurSize(
rSprite->getSizePixel() );
::basegfx::B2DHomMatrix aTransform; const geometry::IntegerSize2D& rInputSize(
if( tools::isInside( xBitmap->getSize() );
::basegfx::B2DRectangle( 0.0,0.0, const ::basegfx::B2DSize& rOurSize(
rOurSize.getX(), rSprite->getSizePixel() );
rOurSize.getY() ),
::basegfx::B2DRectangle( 0.0,0.0, ::basegfx::B2DHomMatrix aTransform;
rInputSize.Width, if( tools::isInside(
rInputSize.Height ), ::basegfx::B2DRectangle( 0.0,0.0,
::canvas::tools::mergeViewAndRenderTransform(aTransform, rOurSize.getX(),
viewState, rOurSize.getY() ),
renderState) ) ) ::basegfx::B2DRectangle( 0.0,0.0,
{ rInputSize.Width,
// bitmap is opaque and will fully cover the sprite, rInputSize.Height ),
// set flag appropriately ::canvas::tools::mergeViewAndRenderTransform(aTransform,
mbIsContentFullyOpaque = true; viewState,
} renderState) ) )
{
// bitmap is opaque and will fully cover the sprite,
// set flag appropriately
mbIsContentFullyOpaque = true;
} }
} }
@@ -257,23 +257,23 @@ namespace canvas
::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos) ); ::basegfx::unotools::b2DPointFromRealPoint2D(aNewPos) );
aPoint *= aTransform; aPoint *= aTransform;
if( aPoint != maPosition ) if( aPoint == maPosition )
return;
const ::basegfx::B2DRectangle& rBounds
= getUpdateArea( ::basegfx::B2DRectangle( 0.0, 0.0,
maSize.getX(),
maSize.getY() ) );
if( mbActive )
{ {
const ::basegfx::B2DRectangle& rBounds mpSpriteCanvas->moveSprite( rSprite,
= getUpdateArea( ::basegfx::B2DRectangle( 0.0, 0.0, rBounds.getMinimum(),
maSize.getX(), rBounds.getMinimum() - maPosition + aPoint,
maSize.getY() ) ); rBounds.getRange() );
if( mbActive )
{
mpSpriteCanvas->moveSprite( rSprite,
rBounds.getMinimum(),
rBounds.getMinimum() - maPosition + aPoint,
rBounds.getRange() );
}
maPosition = aPoint;
} }
maPosition = aPoint;
} }
void CanvasCustomSpriteHelper::transform( const Sprite::Reference& rSprite, void CanvasCustomSpriteHelper::transform( const Sprite::Reference& rSprite,
@@ -283,26 +283,26 @@ namespace canvas
::basegfx::unotools::homMatrixFromAffineMatrix(aMatrix, ::basegfx::unotools::homMatrixFromAffineMatrix(aMatrix,
aTransformation); aTransformation);
if( maTransform != aMatrix ) if( maTransform == aMatrix )
return;
// retrieve bounds before and after transformation change.
const ::basegfx::B2DRectangle& rPrevBounds( getUpdateArea() );
maTransform = aMatrix;
if( !updateClipState( rSprite ) &&
mbActive )
{ {
// retrieve bounds before and after transformation change. mpSpriteCanvas->updateSprite( rSprite,
const ::basegfx::B2DRectangle& rPrevBounds( getUpdateArea() ); maPosition,
rPrevBounds );
maTransform = aMatrix; mpSpriteCanvas->updateSprite( rSprite,
maPosition,
if( !updateClipState( rSprite ) && getUpdateArea() );
mbActive )
{
mpSpriteCanvas->updateSprite( rSprite,
maPosition,
rPrevBounds );
mpSpriteCanvas->updateSprite( rSprite,
maPosition,
getUpdateArea() );
}
mbTransformDirty = true;
} }
mbTransformDirty = true;
} }
void CanvasCustomSpriteHelper::clip( const Sprite::Reference& rSprite, void CanvasCustomSpriteHelper::clip( const Sprite::Reference& rSprite,
@@ -351,20 +351,20 @@ namespace canvas
if( !mpSpriteCanvas.get() ) if( !mpSpriteCanvas.get() )
return; // we're disposed return; // we're disposed
if( !mbActive ) if( mbActive )
return;
mpSpriteCanvas->showSprite( rSprite );
mbActive = true;
// TODO(P1): if clip is the NULL clip (nothing visible),
// also save us the update call.
if( mfAlpha != 0.0 )
{ {
mpSpriteCanvas->showSprite( rSprite ); mpSpriteCanvas->updateSprite( rSprite,
mbActive = true; maPosition,
getUpdateArea() );
// TODO(P1): if clip is the NULL clip (nothing visible),
// also save us the update call.
if( mfAlpha != 0.0 )
{
mpSpriteCanvas->updateSprite( rSprite,
maPosition,
getUpdateArea() );
}
} }
} }
@@ -373,20 +373,20 @@ namespace canvas
if( !mpSpriteCanvas.get() ) if( !mpSpriteCanvas.get() )
return; // we're disposed return; // we're disposed
if( mbActive ) if( !mbActive )
return;
mpSpriteCanvas->hideSprite( rSprite );
mbActive = false;
// TODO(P1): if clip is the NULL clip (nothing visible),
// also save us the update call.
if( mfAlpha != 0.0 )
{ {
mpSpriteCanvas->hideSprite( rSprite ); mpSpriteCanvas->updateSprite( rSprite,
mbActive = false; maPosition,
getUpdateArea() );
// TODO(P1): if clip is the NULL clip (nothing visible),
// also save us the update call.
if( mfAlpha != 0.0 )
{
mpSpriteCanvas->updateSprite( rSprite,
maPosition,
getUpdateArea() );
}
} }
} }

View File

@@ -56,41 +56,41 @@ namespace canvas
{ {
// only deal with change events from the currently // only deal with change events from the currently
// affected sprite // affected sprite
if( rSpriteRecord.mpAffectedSprite == mpAffectedSprite ) if( rSpriteRecord.mpAffectedSprite != mpAffectedSprite )
return;
switch( rSpriteRecord.meChangeType )
{ {
switch( rSpriteRecord.meChangeType ) case SpriteRedrawManager::SpriteChangeRecord::ChangeType::move:
{ if( !mbIsMove )
case SpriteRedrawManager::SpriteChangeRecord::ChangeType::move: {
if( !mbIsMove ) // no move yet - this must be the first one
{ maMoveStartArea = ::basegfx::B2DRectangle(
// no move yet - this must be the first one rSpriteRecord.maOldPos,
maMoveStartArea = ::basegfx::B2DRectangle( rSpriteRecord.maOldPos + rSpriteRecord.maUpdateArea.getRange() );
rSpriteRecord.maOldPos, mbIsMove = true;
rSpriteRecord.maOldPos + rSpriteRecord.maUpdateArea.getRange() ); }
mbIsMove = true;
}
maMoveEndArea = rSpriteRecord.maUpdateArea; maMoveEndArea = rSpriteRecord.maUpdateArea;
break; break;
case SpriteRedrawManager::SpriteChangeRecord::ChangeType::update: case SpriteRedrawManager::SpriteChangeRecord::ChangeType::update:
// update end update area of the // update end update area of the
// sprite. Thus, every update() action // sprite. Thus, every update() action
// _after_ the last move will correctly // _after_ the last move will correctly
// update the final repaint area. And this // update the final repaint area. And this
// does not interfere with subsequent // does not interfere with subsequent
// moves, because moves always perform a // moves, because moves always perform a
// hard set of maMoveEndArea to their // hard set of maMoveEndArea to their
// stored value // stored value
maMoveEndArea.expand( rSpriteRecord.maUpdateArea ); maMoveEndArea.expand( rSpriteRecord.maUpdateArea );
mbIsGenericUpdate = true; mbIsGenericUpdate = true;
break; break;
default: default:
ENSURE_OR_THROW( false, ENSURE_OR_THROW( false,
"Unexpected case in SpriteUpdater::operator()" ); "Unexpected case in SpriteUpdater::operator()" );
break; break;
}
} }
} }

View File

@@ -295,20 +295,20 @@ namespace canvas::tools
#endif #endif
} }
if( renderState.CompositeOperation < rendering::CompositeOperation::CLEAR || if( !(renderState.CompositeOperation < rendering::CompositeOperation::CLEAR ||
renderState.CompositeOperation > rendering::CompositeOperation::SATURATE ) renderState.CompositeOperation > rendering::CompositeOperation::SATURATE) )
{ return;
#if OSL_DEBUG_LEVEL > 0 #if OSL_DEBUG_LEVEL > 0
throw lang::IllegalArgumentException( throw lang::IllegalArgumentException(
OUString::createFromAscii(pStr) + OUString::createFromAscii(pStr) +
": verifyInput(): render state's CompositeOperation value out of range (" + ": verifyInput(): render state's CompositeOperation value out of range (" +
OUString::number(sal::static_int_cast<sal_Int32>(renderState.CompositeOperation)) + OUString::number(sal::static_int_cast<sal_Int32>(renderState.CompositeOperation)) +
" not known)", " not known)",
xIf, nArgPos ); xIf, nArgPos );
#else #else
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
#endif #endif
}
} }
void verifyInput( const rendering::Texture& texture, void verifyInput( const rendering::Texture& texture,
@@ -361,20 +361,20 @@ namespace canvas::tools
#endif #endif
} }
if( texture.RepeatModeY < rendering::TexturingMode::NONE || if( !(texture.RepeatModeY < rendering::TexturingMode::NONE ||
texture.RepeatModeY > rendering::TexturingMode::REPEAT ) texture.RepeatModeY > rendering::TexturingMode::REPEAT) )
{ return;
#if OSL_DEBUG_LEVEL > 0 #if OSL_DEBUG_LEVEL > 0
throw lang::IllegalArgumentException( throw lang::IllegalArgumentException(
OUString::createFromAscii(pStr) + OUString::createFromAscii(pStr) +
": verifyInput(): textures' RepeatModeY value is out of range (" + ": verifyInput(): textures' RepeatModeY value is out of range (" +
OUString::number(sal::static_int_cast<sal_Int32>(texture.RepeatModeY)) + OUString::number(sal::static_int_cast<sal_Int32>(texture.RepeatModeY)) +
" not known)", " not known)",
xIf, nArgPos ); xIf, nArgPos );
#else #else
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
#endif #endif
}
} }
namespace namespace
@@ -483,20 +483,20 @@ namespace canvas::tools
#endif #endif
} }
if( strokeAttributes.JoinType < rendering::PathJoinType::NONE || if( !(strokeAttributes.JoinType < rendering::PathJoinType::NONE ||
strokeAttributes.JoinType > rendering::PathJoinType::BEVEL ) strokeAttributes.JoinType > rendering::PathJoinType::BEVEL) )
{ return;
#if OSL_DEBUG_LEVEL > 0 #if OSL_DEBUG_LEVEL > 0
throw lang::IllegalArgumentException( throw lang::IllegalArgumentException(
OUString::createFromAscii(pStr) + OUString::createFromAscii(pStr) +
": verifyInput(): stroke attributes' JoinType value is out of range (" + ": verifyInput(): stroke attributes' JoinType value is out of range (" +
OUString::number(sal::static_int_cast<sal_Int32>(strokeAttributes.JoinType)) + OUString::number(sal::static_int_cast<sal_Int32>(strokeAttributes.JoinType)) +
" not known)", " not known)",
xIf, nArgPos ); xIf, nArgPos );
#else #else
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
#endif #endif
}
} }
void verifyInput( const rendering::IntegerBitmapLayout& bitmapLayout, void verifyInput( const rendering::IntegerBitmapLayout& bitmapLayout,
@@ -552,20 +552,20 @@ namespace canvas::tools
#endif #endif
} }
if( bitmapLayout.ColorSpace->getEndianness() < util::Endianness::LITTLE || if( !(bitmapLayout.ColorSpace->getEndianness() < util::Endianness::LITTLE ||
bitmapLayout.ColorSpace->getEndianness() > util::Endianness::BIG ) bitmapLayout.ColorSpace->getEndianness() > util::Endianness::BIG) )
{ return;
#if OSL_DEBUG_LEVEL > 0 #if OSL_DEBUG_LEVEL > 0
throw lang::IllegalArgumentException( throw lang::IllegalArgumentException(
OUString::createFromAscii(pStr) + OUString::createFromAscii(pStr) +
": verifyInput(): bitmap layout's ColorSpace getEndianness() value is out of range (" + ": verifyInput(): bitmap layout's ColorSpace getEndianness() value is out of range (" +
OUString::number(sal::static_int_cast<sal_Int32>(bitmapLayout.ColorSpace->getEndianness())) + OUString::number(sal::static_int_cast<sal_Int32>(bitmapLayout.ColorSpace->getEndianness())) +
" not known)", " not known)",
xIf, nArgPos ); xIf, nArgPos );
#else #else
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
#endif #endif
}
} }
void verifyInput( const rendering::FontRequest& fontRequest, void verifyInput( const rendering::FontRequest& fontRequest,
@@ -660,19 +660,19 @@ namespace canvas::tools
#endif #endif
} }
if( size.Height <= 0 ) if( size.Height > 0 )
{ return;
#if OSL_DEBUG_LEVEL > 0 #if OSL_DEBUG_LEVEL > 0
throw lang::IllegalArgumentException( throw lang::IllegalArgumentException(
OUString::createFromAscii(pStr) + OUString::createFromAscii(pStr) +
": verifyBitmapSize(): size has 0 or negative height (value: " + ": verifyBitmapSize(): size has 0 or negative height (value: " +
OUString::number(size.Height) + OUString::number(size.Height) +
")", ")",
xIf, 0 ); xIf, 0 );
#else #else
throw lang::IllegalArgumentException(); throw lang::IllegalArgumentException();
#endif #endif
}
} }
void verifySpriteSize( const geometry::RealSize2D& size, void verifySpriteSize( const geometry::RealSize2D& size,

View File

@@ -31,19 +31,19 @@ namespace vclcanvas
maVDev( VclPtr<VirtualDevice>::Create( rRefDevice, maVDev( VclPtr<VirtualDevice>::Create( rRefDevice,
bMonochromeBuffer ? DeviceFormat::BITMASK : DeviceFormat::DEFAULT ) ) bMonochromeBuffer ? DeviceFormat::BITMASK : DeviceFormat::DEFAULT ) )
{ {
if( !bMonochromeBuffer ) if( bMonochromeBuffer )
{ return;
// #i95645#
// #i95645#
#if defined( MACOSX ) #if defined( MACOSX )
// use AA on VCLCanvas for Mac // use AA on VCLCanvas for Mac
maVDev->SetAntialiasing( AntialiasingFlags::EnableB2dDraw | maVDev->GetAntialiasing() ); maVDev->SetAntialiasing( AntialiasingFlags::EnableB2dDraw | maVDev->GetAntialiasing() );
#else #else
// switch off AA for WIN32 and UNIX, the VCLCanvas does not look good with it and // switch off AA for WIN32 and UNIX, the VCLCanvas does not look good with it and
// is not required to do AA. It would need to be adapted to use it correctly // is not required to do AA. It would need to be adapted to use it correctly
// (especially gradient painting). This will need extra work. // (especially gradient painting). This will need extra work.
maVDev->SetAntialiasing( maVDev->GetAntialiasing() & ~AntialiasingFlags::EnableB2dDraw); maVDev->SetAntialiasing( maVDev->GetAntialiasing() & ~AntialiasingFlags::EnableB2dDraw);
#endif #endif
}
} }
BackBuffer::~BackBuffer() BackBuffer::~BackBuffer()

View File

@@ -106,30 +106,30 @@ namespace vclcanvas
void BitmapBackBuffer::createVDev() const void BitmapBackBuffer::createVDev() const
{ {
if( !mpVDev ) if( mpVDev )
{ return;
// VDev not yet created, do it now. Create an alpha-VDev,
// if bitmap has transparency.
mpVDev = maBitmap->IsTransparent() ?
VclPtr<VirtualDevice>::Create( mrRefDevice, DeviceFormat::DEFAULT, DeviceFormat::DEFAULT ) :
VclPtr<VirtualDevice>::Create( mrRefDevice );
OSL_ENSURE( mpVDev, // VDev not yet created, do it now. Create an alpha-VDev,
"BitmapBackBuffer::createVDev(): Unable to create VirtualDevice" ); // if bitmap has transparency.
mpVDev = maBitmap->IsTransparent() ?
VclPtr<VirtualDevice>::Create( mrRefDevice, DeviceFormat::DEFAULT, DeviceFormat::DEFAULT ) :
VclPtr<VirtualDevice>::Create( mrRefDevice );
mpVDev->SetOutputSizePixel( maBitmap->GetSizePixel() ); OSL_ENSURE( mpVDev,
"BitmapBackBuffer::createVDev(): Unable to create VirtualDevice" );
// #i95645# mpVDev->SetOutputSizePixel( maBitmap->GetSizePixel() );
// #i95645#
#if defined( MACOSX ) #if defined( MACOSX )
// use AA on VCLCanvas for Mac // use AA on VCLCanvas for Mac
mpVDev->SetAntialiasing( AntialiasingFlags::EnableB2dDraw | mpVDev->GetAntialiasing() ); mpVDev->SetAntialiasing( AntialiasingFlags::EnableB2dDraw | mpVDev->GetAntialiasing() );
#else #else
// switch off AA for WIN32 and UNIX, the VCLCanvas does not look good with it and // switch off AA for WIN32 and UNIX, the VCLCanvas does not look good with it and
// is not required to do AA. It would need to be adapted to use it correctly // is not required to do AA. It would need to be adapted to use it correctly
// (especially gradient painting). This will need extra work. // (especially gradient painting). This will need extra work.
mpVDev->SetAntialiasing(mpVDev->GetAntialiasing() & ~AntialiasingFlags::EnableB2dDraw); mpVDev->SetAntialiasing(mpVDev->GetAntialiasing() & ~AntialiasingFlags::EnableB2dDraw);
#endif #endif
}
} }
void BitmapBackBuffer::updateVDev() const void BitmapBackBuffer::updateVDev() const

View File

@@ -154,35 +154,35 @@ namespace vclcanvas
void CanvasHelper::clear() void CanvasHelper::clear()
{ {
// are we disposed? // are we disposed?
if( mpOutDevProvider ) if( !mpOutDevProvider )
{ return;
OutputDevice& rOutDev( mpOutDevProvider->getOutDev() );
tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
rOutDev.EnableMapMode( false ); OutputDevice& rOutDev( mpOutDevProvider->getOutDev() );
rOutDev.SetAntialiasing( AntialiasingFlags::EnableB2dDraw ); tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
rOutDev.SetLineColor( COL_WHITE );
rOutDev.SetFillColor( COL_WHITE );
rOutDev.SetClipRegion();
rOutDev.DrawRect( ::tools::Rectangle( Point(),
rOutDev.GetOutputSizePixel()) );
if( mp2ndOutDevProvider ) rOutDev.EnableMapMode( false );
{ rOutDev.SetAntialiasing( AntialiasingFlags::EnableB2dDraw );
OutputDevice& rOutDev2( mp2ndOutDevProvider->getOutDev() ); rOutDev.SetLineColor( COL_WHITE );
rOutDev.SetFillColor( COL_WHITE );
rOutDev.SetClipRegion();
rOutDev.DrawRect( ::tools::Rectangle( Point(),
rOutDev.GetOutputSizePixel()) );
rOutDev2.SetDrawMode( DrawModeFlags::Default ); if( !mp2ndOutDevProvider )
rOutDev2.EnableMapMode( false ); return;
rOutDev2.SetAntialiasing( AntialiasingFlags::EnableB2dDraw );
rOutDev2.SetLineColor( COL_WHITE ); OutputDevice& rOutDev2( mp2ndOutDevProvider->getOutDev() );
rOutDev2.SetFillColor( COL_WHITE );
rOutDev2.SetClipRegion(); rOutDev2.SetDrawMode( DrawModeFlags::Default );
rOutDev2.DrawRect( ::tools::Rectangle( Point(), rOutDev2.EnableMapMode( false );
rOutDev2.GetOutputSizePixel()) ); rOutDev2.SetAntialiasing( AntialiasingFlags::EnableB2dDraw );
rOutDev2.SetDrawMode( DrawModeFlags::BlackLine | DrawModeFlags::BlackFill | DrawModeFlags::BlackText | rOutDev2.SetLineColor( COL_WHITE );
DrawModeFlags::BlackGradient | DrawModeFlags::BlackBitmap ); rOutDev2.SetFillColor( COL_WHITE );
} rOutDev2.SetClipRegion();
} rOutDev2.DrawRect( ::tools::Rectangle( Point(),
rOutDev2.GetOutputSizePixel()) );
rOutDev2.SetDrawMode( DrawModeFlags::BlackLine | DrawModeFlags::BlackFill | DrawModeFlags::BlackText |
DrawModeFlags::BlackGradient | DrawModeFlags::BlackBitmap );
} }
void CanvasHelper::drawLine( const rendering::XCanvas* , void CanvasHelper::drawLine( const rendering::XCanvas* ,
@@ -192,22 +192,22 @@ namespace vclcanvas
const rendering::RenderState& renderState ) const rendering::RenderState& renderState )
{ {
// are we disposed? // are we disposed?
if( mpOutDevProvider ) if( !mpOutDevProvider )
{ return;
// nope, render
tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
setupOutDevState( viewState, renderState, LINE_COLOR );
const Point aStartPoint( tools::mapRealPoint2D( aStartRealPoint2D, // nope, render
viewState, renderState ) ); tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
const Point aEndPoint( tools::mapRealPoint2D( aEndRealPoint2D, setupOutDevState( viewState, renderState, LINE_COLOR );
viewState, renderState ) );
// TODO(F2): alpha
mpOutDevProvider->getOutDev().DrawLine( aStartPoint, aEndPoint );
if( mp2ndOutDevProvider ) const Point aStartPoint( tools::mapRealPoint2D( aStartRealPoint2D,
mp2ndOutDevProvider->getOutDev().DrawLine( aStartPoint, aEndPoint ); viewState, renderState ) );
} const Point aEndPoint( tools::mapRealPoint2D( aEndRealPoint2D,
viewState, renderState ) );
// TODO(F2): alpha
mpOutDevProvider->getOutDev().DrawLine( aStartPoint, aEndPoint );
if( mp2ndOutDevProvider )
mp2ndOutDevProvider->getOutDev().DrawLine( aStartPoint, aEndPoint );
} }
void CanvasHelper::drawBezier( const rendering::XCanvas* , void CanvasHelper::drawBezier( const rendering::XCanvas* ,
@@ -216,38 +216,38 @@ namespace vclcanvas
const rendering::ViewState& viewState, const rendering::ViewState& viewState,
const rendering::RenderState& renderState ) const rendering::RenderState& renderState )
{ {
if( mpOutDevProvider ) if( !mpOutDevProvider )
{ return;
tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
setupOutDevState( viewState, renderState, LINE_COLOR );
const Point& rStartPoint( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.Px, tools::OutDevStateKeeper aStateKeeper( mpProtectedOutDevProvider );
aBezierSegment.Py), setupOutDevState( viewState, renderState, LINE_COLOR );
viewState, renderState ) );
const Point& rCtrlPoint1( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C1x,
aBezierSegment.C1y),
viewState, renderState ) );
const Point& rCtrlPoint2( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C2x,
aBezierSegment.C2y),
viewState, renderState ) );
const Point& rEndPoint( tools::mapRealPoint2D( _aEndPoint,
viewState, renderState ) );
::tools::Polygon aPoly(4); const Point& rStartPoint( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.Px,
aPoly.SetPoint( rStartPoint, 0 ); aBezierSegment.Py),
aPoly.SetFlags( 0, PolyFlags::Normal ); viewState, renderState ) );
aPoly.SetPoint( rCtrlPoint1, 1 ); const Point& rCtrlPoint1( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C1x,
aPoly.SetFlags( 1, PolyFlags::Control ); aBezierSegment.C1y),
aPoly.SetPoint( rCtrlPoint2, 2 ); viewState, renderState ) );
aPoly.SetFlags( 2, PolyFlags::Control ); const Point& rCtrlPoint2( tools::mapRealPoint2D( geometry::RealPoint2D(aBezierSegment.C2x,
aPoly.SetPoint( rEndPoint, 3 ); aBezierSegment.C2y),
aPoly.SetFlags( 3, PolyFlags::Normal ); viewState, renderState ) );
const Point& rEndPoint( tools::mapRealPoint2D( _aEndPoint,
viewState, renderState ) );
// TODO(F2): alpha ::tools::Polygon aPoly(4);
mpOutDevProvider->getOutDev().DrawPolygon( aPoly ); aPoly.SetPoint( rStartPoint, 0 );
if( mp2ndOutDevProvider ) aPoly.SetFlags( 0, PolyFlags::Normal );
mp2ndOutDevProvider->getOutDev().DrawPolygon( aPoly ); aPoly.SetPoint( rCtrlPoint1, 1 );
} aPoly.SetFlags( 1, PolyFlags::Control );
aPoly.SetPoint( rCtrlPoint2, 2 );
aPoly.SetFlags( 2, PolyFlags::Control );
aPoly.SetPoint( rEndPoint, 3 );
aPoly.SetFlags( 3, PolyFlags::Normal );
// TODO(F2): alpha
mpOutDevProvider->getOutDev().DrawPolygon( aPoly );
if( mp2ndOutDevProvider )
mp2ndOutDevProvider->getOutDev().DrawPolygon( aPoly );
} }
uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* , uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* ,

View File

@@ -196,21 +196,21 @@ namespace vclcanvas
{ {
static sal_Int32 nFilePostfixCount(0); static sal_Int32 nFilePostfixCount(0);
if( mpOutDev ) if( !mpOutDev )
{ return;
OUString aFilename = "dbg_frontbuffer" + OUString::number(nFilePostfixCount) + ".bmp";
SvFileStream aStream( aFilename, StreamMode::STD_READWRITE ); OUString aFilename = "dbg_frontbuffer" + OUString::number(nFilePostfixCount) + ".bmp";
const ::Point aEmptyPoint; SvFileStream aStream( aFilename, StreamMode::STD_READWRITE );
OutputDevice& rOutDev = mpOutDev->getOutDev();
bool bOldMap( rOutDev.IsMapModeEnabled() );
rOutDev.EnableMapMode( false );
WriteDIB(rOutDev.GetBitmapEx(aEmptyPoint, rOutDev.GetOutputSizePixel()), aStream, false);
rOutDev.EnableMapMode( bOldMap );
++nFilePostfixCount; const ::Point aEmptyPoint;
} OutputDevice& rOutDev = mpOutDev->getOutDev();
bool bOldMap( rOutDev.IsMapModeEnabled() );
rOutDev.EnableMapMode( false );
WriteDIB(rOutDev.GetBitmapEx(aEmptyPoint, rOutDev.GetOutputSizePixel()), aStream, false);
rOutDev.EnableMapMode( bOldMap );
++nFilePostfixCount;
} }
} }

View File

@@ -597,64 +597,64 @@ namespace vclcanvas
void SpriteCanvasHelper::renderSpriteCount( OutputDevice& rOutDev ) void SpriteCanvasHelper::renderSpriteCount( OutputDevice& rOutDev )
{ {
if( mpRedrawManager ) if( !mpRedrawManager )
{ return;
sal_Int32 nCount(0);
mpRedrawManager->forEachSprite( makeAdder(nCount,sal_Int32(1)) ); sal_Int32 nCount(0);
OUString text( OUString::number(nCount) );
// pad with leading space mpRedrawManager->forEachSprite( makeAdder(nCount,sal_Int32(1)) );
while( text.getLength() < 3 ) OUString text( OUString::number(nCount) );
text = " " + text;
text = "Sprites: " + text; // pad with leading space
while( text.getLength() < 3 )
text = " " + text;
renderInfoText( rOutDev, text = "Sprites: " + text;
text,
Point(0, 30) ); renderInfoText( rOutDev,
} text,
Point(0, 30) );
} }
void SpriteCanvasHelper::renderMemUsage( OutputDevice& rOutDev ) void SpriteCanvasHelper::renderMemUsage( OutputDevice& rOutDev )
{ {
BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() ); BackBufferSharedPtr pBackBuffer( mpOwningSpriteCanvas->getBackBuffer() );
if( mpRedrawManager && if( !(mpRedrawManager &&
pBackBuffer ) pBackBuffer) )
{ return;
double nPixel(0.0);
// accumulate pixel count for each sprite into fCount double nPixel(0.0);
mpRedrawManager->forEachSprite(
[&nPixel]( const ::canvas::Sprite::Reference& rSprite )
{ makeAdder( nPixel, 1.0 )( calcNumPixel(rSprite) ); }
);
static const int NUM_VIRDEV(2); // accumulate pixel count for each sprite into fCount
static const int BYTES_PER_PIXEL(3); mpRedrawManager->forEachSprite(
[&nPixel]( const ::canvas::Sprite::Reference& rSprite )
{ makeAdder( nPixel, 1.0 )( calcNumPixel(rSprite) ); }
);
const Size& rVDevSize( maVDev->GetOutputSizePixel() ); static const int NUM_VIRDEV(2);
const Size& rBackBufferSize( pBackBuffer->getOutDev().GetOutputSizePixel() ); static const int BYTES_PER_PIXEL(3);
const double nMemUsage( nPixel * NUM_VIRDEV * BYTES_PER_PIXEL + const Size& rVDevSize( maVDev->GetOutputSizePixel() );
rVDevSize.Width()*rVDevSize.Height() * BYTES_PER_PIXEL + const Size& rBackBufferSize( pBackBuffer->getOutDev().GetOutputSizePixel() );
rBackBufferSize.Width()*rBackBufferSize.Height() * BYTES_PER_PIXEL );
OUString text( ::rtl::math::doubleToUString( nMemUsage / 1048576.0, const double nMemUsage( nPixel * NUM_VIRDEV * BYTES_PER_PIXEL +
rtl_math_StringFormat_F, rVDevSize.Width()*rVDevSize.Height() * BYTES_PER_PIXEL +
2,'.',nullptr,' ') ); rBackBufferSize.Width()*rBackBufferSize.Height() * BYTES_PER_PIXEL );
// pad with leading space OUString text( ::rtl::math::doubleToUString( nMemUsage / 1048576.0,
while( text.getLength() < 4 ) rtl_math_StringFormat_F,
text = " " + text; 2,'.',nullptr,' ') );
text = "Mem: " + text + "MB"; // pad with leading space
while( text.getLength() < 4 )
text = " " + text;
renderInfoText( rOutDev, text = "Mem: " + text + "MB";
text,
Point(0, 60) ); renderInfoText( rOutDev,
} text,
Point(0, 60) );
} }
} }

View File

@@ -98,248 +98,248 @@ namespace vclcanvas
const double fAlpha( getAlpha() ); const double fAlpha( getAlpha() );
if( isActive() && if( !(isActive() &&
!::basegfx::fTools::equalZero( fAlpha ) ) !::basegfx::fTools::equalZero( fAlpha )) )
return;
const Point aEmptyPoint;
const ::basegfx::B2DVector& rOrigOutputSize( getSizePixel() );
// might get changed below (e.g. adapted for
// transformations). IMPORTANT: both position and size are
// rounded to integer values. From now on, only those
// rounded values are used, to keep clip and content in
// sync.
::Size aOutputSize( vcl::unotools::sizeFromB2DSize( rOrigOutputSize ) );
::Point aOutPos( vcl::unotools::pointFromB2DPoint( rPos ) );
// TODO(F3): Support for alpha-VDev
// Do we have to update our bitmaps (necessary if virdev
// was painted to, or transformation changed)?
const bool bNeedBitmapUpdate( io_bSurfacesDirty ||
hasTransformChanged() ||
maContent->IsEmpty() );
// updating content of sprite cache - surface is no
// longer dirty in relation to our cache
io_bSurfacesDirty = false;
transformUpdated();
if( bNeedBitmapUpdate )
{ {
const Point aEmptyPoint; BitmapEx aBmp( mpBackBuffer->getOutDev().GetBitmapEx( aEmptyPoint,
const ::basegfx::B2DVector& rOrigOutputSize( getSizePixel() ); aOutputSize ) );
// might get changed below (e.g. adapted for if( isContentFullyOpaque() )
// transformations). IMPORTANT: both position and size are
// rounded to integer values. From now on, only those
// rounded values are used, to keep clip and content in
// sync.
::Size aOutputSize( vcl::unotools::sizeFromB2DSize( rOrigOutputSize ) );
::Point aOutPos( vcl::unotools::pointFromB2DPoint( rPos ) );
// TODO(F3): Support for alpha-VDev
// Do we have to update our bitmaps (necessary if virdev
// was painted to, or transformation changed)?
const bool bNeedBitmapUpdate( io_bSurfacesDirty ||
hasTransformChanged() ||
maContent->IsEmpty() );
// updating content of sprite cache - surface is no
// longer dirty in relation to our cache
io_bSurfacesDirty = false;
transformUpdated();
if( bNeedBitmapUpdate )
{ {
BitmapEx aBmp( mpBackBuffer->getOutDev().GetBitmapEx( aEmptyPoint, // optimized case: content canvas is fully
aOutputSize ) ); // opaque. Note: since we retrieved aBmp directly
// from an OutDev, it's already a 'display bitmap'
if( isContentFullyOpaque() ) // on windows.
{ maContent = aBmp;
// optimized case: content canvas is fully
// opaque. Note: since we retrieved aBmp directly
// from an OutDev, it's already a 'display bitmap'
// on windows.
maContent = aBmp;
}
else
{
// sprite content might contain alpha, create
// BmpEx, then.
BitmapEx aMask( mpBackBufferMask->getOutDev().GetBitmapEx( aEmptyPoint,
aOutputSize ) );
// bitmasks are much faster than alphamasks on some platforms
// so convert to bitmask if useful
bool convertTo1Bpp = aMask.GetBitCount() != 1;
#ifdef MACOSX
convertTo1Bpp = false;
#endif
if( SkiaHelper::isVCLSkiaEnabled())
convertTo1Bpp = false;
if( convertTo1Bpp )
{
OSL_FAIL("CanvasCustomSprite::redraw(): Mask bitmap is not "
"monochrome (performance!)");
BitmapEx aMaskEx(aMask);
BitmapFilter::Filter(aMaskEx, BitmapMonochromeFilter(255));
aMask = aMaskEx.GetBitmap();
}
// Note: since we retrieved aBmp and aMask
// directly from an OutDev, it's already a
// 'display bitmap' on windows.
if( aMask.GetBitCount() == 1 )
maContent = BitmapEx( aBmp.GetBitmap(), aMask.GetBitmap() );
else
maContent = BitmapEx( aBmp.GetBitmap(), AlphaMask( aMask.GetBitmap()) );
}
} }
else
::basegfx::B2DHomMatrix aTransform( getTransformation() );
// check whether matrix is "easy" to handle - pure
// translations or scales are handled by OutputDevice
// alone
const bool bIdentityTransform( aTransform.isIdentity() );
// make transformation absolute (put sprite to final
// output position). Need to happen here, as we also have
// to translate the clip polygon
aTransform.translate( aOutPos.X(),
aOutPos.Y() );
if( !bIdentityTransform )
{ {
// Avoid the trick with the negative width in the OpenGL case, // sprite content might contain alpha, create
// OutputDevice::DrawDeviceAlphaBitmap() doesn't like it. // BmpEx, then.
if (!::basegfx::fTools::equalZero( aTransform.get(0,1) ) || BitmapEx aMask( mpBackBufferMask->getOutDev().GetBitmapEx( aEmptyPoint,
!::basegfx::fTools::equalZero( aTransform.get(1,0) ) aOutputSize ) );
#if HAVE_FEATURE_UI
|| OpenGLHelper::isVCLOpenGLEnabled() // bitmasks are much faster than alphamasks on some platforms
// so convert to bitmask if useful
bool convertTo1Bpp = aMask.GetBitCount() != 1;
#ifdef MACOSX
convertTo1Bpp = false;
#endif #endif
|| SkiaHelper::isVCLSkiaEnabled() if( SkiaHelper::isVCLSkiaEnabled())
) convertTo1Bpp = false;
if( convertTo1Bpp )
{ {
// "complex" transformation, employ affine OSL_FAIL("CanvasCustomSprite::redraw(): Mask bitmap is not "
// transformator "monochrome (performance!)");
BitmapEx aMaskEx(aMask);
BitmapFilter::Filter(aMaskEx, BitmapMonochromeFilter(255));
aMask = aMaskEx.GetBitmap();
}
// modify output position, to account for the fact // Note: since we retrieved aBmp and aMask
// that transformBitmap() always normalizes its output // directly from an OutDev, it's already a
// bitmap into the smallest enclosing box. // 'display bitmap' on windows.
::basegfx::B2DRectangle aDestRect; if( aMask.GetBitCount() == 1 )
::canvas::tools::calcTransformedRectBounds( aDestRect, maContent = BitmapEx( aBmp.GetBitmap(), aMask.GetBitmap() );
::basegfx::B2DRectangle(0, else
0, maContent = BitmapEx( aBmp.GetBitmap(), AlphaMask( aMask.GetBitmap()) );
rOrigOutputSize.getX(), }
rOrigOutputSize.getY()), }
aTransform );
aOutPos.setX( ::basegfx::fround( aDestRect.getMinX() ) ); ::basegfx::B2DHomMatrix aTransform( getTransformation() );
aOutPos.setY( ::basegfx::fround( aDestRect.getMinY() ) );
// TODO(P3): Use optimized bitmap transformation here. // check whether matrix is "easy" to handle - pure
// translations or scales are handled by OutputDevice
// alone
const bool bIdentityTransform( aTransform.isIdentity() );
// actually re-create the bitmap ONLY if necessary // make transformation absolute (put sprite to final
if( bNeedBitmapUpdate ) // output position). Need to happen here, as we also have
maContent = tools::transformBitmap( *maContent, // to translate the clip polygon
aTransform.translate( aOutPos.X(),
aOutPos.Y() );
if( !bIdentityTransform )
{
// Avoid the trick with the negative width in the OpenGL case,
// OutputDevice::DrawDeviceAlphaBitmap() doesn't like it.
if (!::basegfx::fTools::equalZero( aTransform.get(0,1) ) ||
!::basegfx::fTools::equalZero( aTransform.get(1,0) )
#if HAVE_FEATURE_UI
|| OpenGLHelper::isVCLOpenGLEnabled()
#endif
|| SkiaHelper::isVCLSkiaEnabled()
)
{
// "complex" transformation, employ affine
// transformator
// modify output position, to account for the fact
// that transformBitmap() always normalizes its output
// bitmap into the smallest enclosing box.
::basegfx::B2DRectangle aDestRect;
::canvas::tools::calcTransformedRectBounds( aDestRect,
::basegfx::B2DRectangle(0,
0,
rOrigOutputSize.getX(),
rOrigOutputSize.getY()),
aTransform ); aTransform );
aOutputSize = maContent->GetSizePixel(); aOutPos.setX( ::basegfx::fround( aDestRect.getMinX() ) );
} aOutPos.setY( ::basegfx::fround( aDestRect.getMinY() ) );
else
{
// relatively 'simplistic' transformation -
// retrieve scale and translational offset
aOutputSize.setWidth (
::basegfx::fround( rOrigOutputSize.getX() * aTransform.get(0,0) ) );
aOutputSize.setHeight(
::basegfx::fround( rOrigOutputSize.getY() * aTransform.get(1,1) ) );
aOutPos.setX( ::basegfx::fround( aTransform.get(0,2) ) ); // TODO(P3): Use optimized bitmap transformation here.
aOutPos.setY( ::basegfx::fround( aTransform.get(1,2) ) );
} // actually re-create the bitmap ONLY if necessary
if( bNeedBitmapUpdate )
maContent = tools::transformBitmap( *maContent,
aTransform );
aOutputSize = maContent->GetSizePixel();
} }
else
// transformBitmap() might return empty bitmaps, for tiny
// scales.
if( !!(*maContent) )
{ {
rTargetSurface.Push( PushFlags::CLIPREGION ); // relatively 'simplistic' transformation -
// retrieve scale and translational offset
aOutputSize.setWidth (
::basegfx::fround( rOrigOutputSize.getX() * aTransform.get(0,0) ) );
aOutputSize.setHeight(
::basegfx::fround( rOrigOutputSize.getY() * aTransform.get(1,1) ) );
// apply clip (if any) aOutPos.setX( ::basegfx::fround( aTransform.get(0,2) ) );
if( getClip().is() ) aOutPos.setY( ::basegfx::fround( aTransform.get(1,2) ) );
{ }
::basegfx::B2DPolyPolygon aClipPoly( }
::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
getClip() ));
if( aClipPoly.count() ) // transformBitmap() might return empty bitmaps, for tiny
{ // scales.
// aTransform already contains the if( !(*maContent) )
// translational component, moving the clip to return;
// the final sprite output position.
aClipPoly.transform( aTransform );
if( mbShowSpriteBounds ) rTargetSurface.Push( PushFlags::CLIPREGION );
{
// Paint green sprite clip area
rTargetSurface.SetLineColor( Color( 0,255,0 ) );
rTargetSurface.SetFillColor();
rTargetSurface.DrawPolyPolygon(::tools::PolyPolygon(aClipPoly)); // #i76339# // apply clip (if any)
} if( getClip().is() )
{
::basegfx::B2DPolyPolygon aClipPoly(
::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
getClip() ));
vcl::Region aClipRegion( aClipPoly ); if( aClipPoly.count() )
rTargetSurface.SetClipRegion( aClipRegion ); {
} // aTransform already contains the
} // translational component, moving the clip to
// the final sprite output position.
if( ::rtl::math::approxEqual(fAlpha, 1.0) ) aClipPoly.transform( aTransform );
{
// no alpha modulation -> just copy to output
if( maContent->IsTransparent() )
rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize, *maContent );
else
rTargetSurface.DrawBitmap( aOutPos, aOutputSize, maContent->GetBitmap() );
}
else
{
// TODO(P3): Switch to OutputDevice::DrawTransparent()
// here
// draw semi-transparent
sal_uInt8 nColor( static_cast<sal_uInt8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) );
AlphaMask aAlpha( maContent->GetSizePixel(),
&nColor );
// mask out fully transparent areas
if( maContent->IsTransparent() )
aAlpha.Replace( maContent->GetMask(), 255 );
// alpha-blend to output
rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize,
BitmapEx( maContent->GetBitmap(),
aAlpha ) );
}
rTargetSurface.Pop();
if( mbShowSpriteBounds ) if( mbShowSpriteBounds )
{ {
::tools::PolyPolygon aMarkerPoly( // Paint green sprite clip area
::canvas::tools::getBoundMarksPolyPolygon( rTargetSurface.SetLineColor( Color( 0,255,0 ) );
::basegfx::B2DRectangle(aOutPos.X(),
aOutPos.Y(),
aOutPos.X() + aOutputSize.Width()-1,
aOutPos.Y() + aOutputSize.Height()-1) ) );
// Paint little red sprite area markers
rTargetSurface.SetLineColor( COL_RED );
rTargetSurface.SetFillColor(); rTargetSurface.SetFillColor();
for( int i=0; i<aMarkerPoly.Count(); ++i ) rTargetSurface.DrawPolyPolygon(::tools::PolyPolygon(aClipPoly)); // #i76339#
{
rTargetSurface.DrawPolyLine( aMarkerPoly.GetObject(static_cast<sal_uInt16>(i)) );
}
// paint sprite prio
vcl::Font aVCLFont;
aVCLFont.SetFontHeight( std::min(long(20),aOutputSize.Height()) );
aVCLFont.SetColor( COL_RED );
rTargetSurface.SetTextAlign(ALIGN_TOP);
rTargetSurface.SetTextColor( COL_RED );
rTargetSurface.SetFont( aVCLFont );
OUString text( ::rtl::math::doubleToUString( getPriority(),
rtl_math_StringFormat_F,
2,'.',nullptr,' ') );
rTargetSurface.DrawText( aOutPos+Point(2,2), text );
SAL_INFO( "canvas.vcl",
"sprite " << this << " has prio " << getPriority());
} }
vcl::Region aClipRegion( aClipPoly );
rTargetSurface.SetClipRegion( aClipRegion );
} }
} }
if( ::rtl::math::approxEqual(fAlpha, 1.0) )
{
// no alpha modulation -> just copy to output
if( maContent->IsTransparent() )
rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize, *maContent );
else
rTargetSurface.DrawBitmap( aOutPos, aOutputSize, maContent->GetBitmap() );
}
else
{
// TODO(P3): Switch to OutputDevice::DrawTransparent()
// here
// draw semi-transparent
sal_uInt8 nColor( static_cast<sal_uInt8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) );
AlphaMask aAlpha( maContent->GetSizePixel(),
&nColor );
// mask out fully transparent areas
if( maContent->IsTransparent() )
aAlpha.Replace( maContent->GetMask(), 255 );
// alpha-blend to output
rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize,
BitmapEx( maContent->GetBitmap(),
aAlpha ) );
}
rTargetSurface.Pop();
if( !mbShowSpriteBounds )
return;
::tools::PolyPolygon aMarkerPoly(
::canvas::tools::getBoundMarksPolyPolygon(
::basegfx::B2DRectangle(aOutPos.X(),
aOutPos.Y(),
aOutPos.X() + aOutputSize.Width()-1,
aOutPos.Y() + aOutputSize.Height()-1) ) );
// Paint little red sprite area markers
rTargetSurface.SetLineColor( COL_RED );
rTargetSurface.SetFillColor();
for( int i=0; i<aMarkerPoly.Count(); ++i )
{
rTargetSurface.DrawPolyLine( aMarkerPoly.GetObject(static_cast<sal_uInt16>(i)) );
}
// paint sprite prio
vcl::Font aVCLFont;
aVCLFont.SetFontHeight( std::min(long(20),aOutputSize.Height()) );
aVCLFont.SetColor( COL_RED );
rTargetSurface.SetTextAlign(ALIGN_TOP);
rTargetSurface.SetTextColor( COL_RED );
rTargetSurface.SetFont( aVCLFont );
OUString text( ::rtl::math::doubleToUString( getPriority(),
rtl_math_StringFormat_F,
2,'.',nullptr,' ') );
rTargetSurface.DrawText( aOutPos+Point(2,2), text );
SAL_INFO( "canvas.vcl",
"sprite " << this << " has prio " << getPriority());
} }
::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const