LCOV - code coverage report
Current view: top level - canvas/source/vcl - spritehelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 129 0.0 %
Date: 2012-08-25 Functions: 0 7 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include <canvas/debug.hxx>
      31                 :            : #include <tools/diagnose_ex.h>
      32                 :            : #include <canvas/verbosetrace.hxx>
      33                 :            : 
      34                 :            : #include <rtl/math.hxx>
      35                 :            : 
      36                 :            : #include <vcl/outdev.hxx>
      37                 :            : #include <vcl/bitmap.hxx>
      38                 :            : #include <vcl/alpha.hxx>
      39                 :            : #include <vcl/bitmapex.hxx>
      40                 :            : #include <vcl/canvastools.hxx>
      41                 :            : 
      42                 :            : #include <basegfx/matrix/b2dhommatrix.hxx>
      43                 :            : #include <basegfx/point/b2dpoint.hxx>
      44                 :            : #include <basegfx/tools/canvastools.hxx>
      45                 :            : #include <basegfx/polygon/b2dpolygon.hxx>
      46                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      47                 :            : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      48                 :            : #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
      49                 :            : #include <basegfx/polygon/b2dpolygontriangulator.hxx>
      50                 :            : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      51                 :            : #include <basegfx/numeric/ftools.hxx>
      52                 :            : 
      53                 :            : #include <canvas/canvastools.hxx>
      54                 :            : 
      55                 :            : #include "spritehelper.hxx"
      56                 :            : 
      57                 :            : using namespace ::com::sun::star;
      58                 :            : 
      59                 :            : 
      60                 :            : namespace vclcanvas
      61                 :            : {
      62                 :          0 :     SpriteHelper::SpriteHelper() :
      63                 :            :         mpBackBuffer(),
      64                 :            :         mpBackBufferMask(),
      65                 :            :         maContent(),
      66                 :          0 :         mbShowSpriteBounds(false)
      67                 :            :     {
      68                 :          0 :     }
      69                 :            : 
      70                 :          0 :     void SpriteHelper::init( const geometry::RealSize2D&               rSpriteSize,
      71                 :            :                              const ::canvas::SpriteSurface::Reference& rOwningSpriteCanvas,
      72                 :            :                              const BackBufferSharedPtr&                rBackBuffer,
      73                 :            :                              const BackBufferSharedPtr&                rBackBufferMask,
      74                 :            :                              bool                                      bShowSpriteBounds )
      75                 :            :     {
      76                 :          0 :         ENSURE_OR_THROW( rOwningSpriteCanvas.get() && rBackBuffer && rBackBufferMask,
      77                 :            :                          "SpriteHelper::init(): Invalid sprite canvas or back buffer" );
      78                 :            : 
      79                 :          0 :         mpBackBuffer        = rBackBuffer;
      80                 :          0 :         mpBackBufferMask    = rBackBufferMask;
      81                 :          0 :         mbShowSpriteBounds  = bShowSpriteBounds;
      82                 :            : 
      83                 :          0 :         init( rSpriteSize, rOwningSpriteCanvas );
      84                 :          0 :     }
      85                 :            : 
      86                 :          0 :     void SpriteHelper::disposing()
      87                 :            :     {
      88                 :          0 :         mpBackBuffer.reset();
      89                 :          0 :         mpBackBufferMask.reset();
      90                 :            : 
      91                 :            :         // forward to parent
      92                 :          0 :         CanvasCustomSpriteHelper::disposing();
      93                 :          0 :     }
      94                 :            : 
      95                 :          0 :     void SpriteHelper::redraw( OutputDevice&                rTargetSurface,
      96                 :            :                                const ::basegfx::B2DPoint&   rPos,
      97                 :            :                                bool&                        io_bSurfacesDirty,
      98                 :            :                                bool                         bBufferedUpdate ) const
      99                 :            :     {
     100                 :            :         (void)bBufferedUpdate; // not used on every platform
     101                 :            : 
     102                 :          0 :         if( !mpBackBuffer ||
     103                 :          0 :             !mpBackBufferMask )
     104                 :            :         {
     105                 :          0 :             return; // we're disposed
     106                 :            :         }
     107                 :            : 
     108                 :            :         // log output pos in device pixel
     109                 :            :         VERBOSE_TRACE( "SpriteHelper::redraw(): output pos is (%f, %f)",
     110                 :            :                        rPos.getX(),
     111                 :            :                        rPos.getY() );
     112                 :            : 
     113                 :          0 :         const double fAlpha( getAlpha() );
     114                 :            : 
     115                 :          0 :         if( isActive() &&
     116                 :          0 :             !::basegfx::fTools::equalZero( fAlpha ) )
     117                 :            :         {
     118                 :          0 :             const Point                 aEmptyPoint;
     119                 :          0 :             const ::basegfx::B2DVector& rOrigOutputSize( getSizePixel() );
     120                 :            : 
     121                 :            :             // might get changed below (e.g. adapted for
     122                 :            :             // transformations). IMPORTANT: both position and size are
     123                 :            :             // rounded to integer values. From now on, only those
     124                 :            :             // rounded values are used, to keep clip and content in
     125                 :            :             // sync.
     126                 :          0 :             ::Size  aOutputSize( ::vcl::unotools::sizeFromB2DSize( rOrigOutputSize ) );
     127                 :          0 :             ::Point aOutPos( ::vcl::unotools::pointFromB2DPoint( rPos ) );
     128                 :            : 
     129                 :            : 
     130                 :            :             // TODO(F3): Support for alpha-VDev
     131                 :            : 
     132                 :            :             // Do we have to update our bitmaps (necessary if virdev
     133                 :            :             // was painted to, or transformation changed)?
     134                 :            :             const bool bNeedBitmapUpdate( io_bSurfacesDirty ||
     135                 :          0 :                                           hasTransformChanged() ||
     136                 :          0 :                                           maContent->IsEmpty() );
     137                 :            : 
     138                 :            :             // updating content of sprite cache - surface is no
     139                 :            :             // longer dirty in relation to our cache
     140                 :          0 :             io_bSurfacesDirty = false;
     141                 :          0 :             transformUpdated();
     142                 :            : 
     143                 :          0 :             if( bNeedBitmapUpdate )
     144                 :            :             {
     145                 :          0 :                 Bitmap aBmp( mpBackBuffer->getOutDev().GetBitmap( aEmptyPoint,
     146                 :          0 :                                                                   aOutputSize ) );
     147                 :            : 
     148                 :          0 :                 if( isContentFullyOpaque() )
     149                 :            :                 {
     150                 :            :                     // optimized case: content canvas is fully
     151                 :            :                     // opaque. Note: since we retrieved aBmp directly
     152                 :            :                     // from an OutDev, it's already a 'display bitmap'
     153                 :            :                     // on windows.
     154                 :          0 :                     maContent = BitmapEx( aBmp );
     155                 :            :                 }
     156                 :            :                 else
     157                 :            :                 {
     158                 :            :                     // sprite content might contain alpha, create
     159                 :            :                     // BmpEx, then.
     160                 :          0 :                     Bitmap aMask( mpBackBufferMask->getOutDev().GetBitmap( aEmptyPoint,
     161                 :          0 :                                                                            aOutputSize ) );
     162                 :            : 
     163                 :            :                     // bitmasks are much faster than alphamasks on some platforms
     164                 :            :                     // so convert to bitmask if useful
     165                 :            : #ifndef QUARTZ
     166                 :          0 :                     if( aMask.GetBitCount() != 1 )
     167                 :            :                     {
     168                 :            :                         OSL_FAIL("CanvasCustomSprite::redraw(): Mask bitmap is not "
     169                 :            :                                    "monochrome (performance!)");
     170                 :          0 :                         aMask.MakeMono(255);
     171                 :            :                     }
     172                 :            : #endif
     173                 :            : 
     174                 :            :                     // Note: since we retrieved aBmp and aMask
     175                 :            :                     // directly from an OutDev, it's already a
     176                 :            :                     // 'display bitmap' on windows.
     177                 :          0 :                     maContent = BitmapEx( aBmp, aMask );
     178                 :          0 :                 }
     179                 :            :             }
     180                 :            : 
     181                 :          0 :             ::basegfx::B2DHomMatrix aTransform( getTransformation() );
     182                 :            : 
     183                 :            :             // check whether matrix is "easy" to handle - pure
     184                 :            :             // translations or scales are handled by OutputDevice
     185                 :            :             // alone
     186                 :          0 :             const bool bIdentityTransform( aTransform.isIdentity() );
     187                 :            : 
     188                 :            :             // make transformation absolute (put sprite to final
     189                 :            :             // output position). Need to happen here, as we also have
     190                 :            :             // to translate the clip polygon
     191                 :          0 :             aTransform.translate( aOutPos.X(),
     192                 :          0 :                                   aOutPos.Y() );
     193                 :            : 
     194                 :          0 :             if( !bIdentityTransform )
     195                 :            :             {
     196                 :          0 :                 if( !::basegfx::fTools::equalZero( aTransform.get(0,1) ) ||
     197                 :          0 :                     !::basegfx::fTools::equalZero( aTransform.get(1,0) ) )
     198                 :            :                 {
     199                 :            :                     // "complex" transformation, employ affine
     200                 :            :                     // transformator
     201                 :            : 
     202                 :            :                     // modify output position, to account for the fact
     203                 :            :                     // that transformBitmap() always normalizes its output
     204                 :            :                     // bitmap into the smallest enclosing box.
     205                 :          0 :                     ::basegfx::B2DRectangle aDestRect;
     206                 :            :                     ::canvas::tools::calcTransformedRectBounds( aDestRect,
     207                 :            :                                                                 ::basegfx::B2DRectangle(0,
     208                 :            :                                                                                         0,
     209                 :            :                                                                                         rOrigOutputSize.getX(),
     210                 :            :                                                                                         rOrigOutputSize.getY()),
     211                 :          0 :                                                                 aTransform );
     212                 :            : 
     213                 :          0 :                     aOutPos.X() = ::basegfx::fround( aDestRect.getMinX() );
     214                 :          0 :                     aOutPos.Y() = ::basegfx::fround( aDestRect.getMinY() );
     215                 :            : 
     216                 :            :                     // TODO(P3): Use optimized bitmap transformation here.
     217                 :            : 
     218                 :            :                     // actually re-create the bitmap ONLY if necessary
     219                 :          0 :                     if( bNeedBitmapUpdate )
     220                 :          0 :                         maContent = tools::transformBitmap( *maContent,
     221                 :            :                                                             aTransform,
     222                 :            :                                                             uno::Sequence<double>(),
     223                 :          0 :                                                             tools::MODULATE_NONE );
     224                 :            : 
     225                 :          0 :                     aOutputSize = maContent->GetSizePixel();
     226                 :            :                 }
     227                 :            :                 else
     228                 :            :                 {
     229                 :            :                     // relatively 'simplistic' transformation -
     230                 :            :                     // retrieve scale and translational offset
     231                 :            :                     aOutputSize.setWidth (
     232                 :          0 :                         ::basegfx::fround( rOrigOutputSize.getX() * aTransform.get(0,0) ) );
     233                 :            :                     aOutputSize.setHeight(
     234                 :          0 :                         ::basegfx::fround( rOrigOutputSize.getY() * aTransform.get(1,1) ) );
     235                 :            : 
     236                 :          0 :                     aOutPos.X() = ::basegfx::fround( aTransform.get(0,2) );
     237                 :          0 :                     aOutPos.Y() = ::basegfx::fround( aTransform.get(1,2) );
     238                 :            :                 }
     239                 :            :             }
     240                 :            : 
     241                 :            :             // transformBitmap() might return empty bitmaps, for tiny
     242                 :            :             // scales.
     243                 :          0 :             if( !!(*maContent) )
     244                 :            :             {
     245                 :            :                 // when true, fast path for slide transition has
     246                 :            :                 // already redrawn the sprite.
     247                 :          0 :                 bool bSpriteRedrawn( false );
     248                 :            : 
     249                 :          0 :                 rTargetSurface.Push( PUSH_CLIPREGION );
     250                 :            : 
     251                 :            :                 // apply clip (if any)
     252                 :          0 :                 if( getClip().is() )
     253                 :            :                 {
     254                 :            :                     ::basegfx::B2DPolyPolygon aClipPoly(
     255                 :            :                         ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
     256                 :          0 :                             getClip() ));
     257                 :            : 
     258                 :          0 :                     if( aClipPoly.count() )
     259                 :            :                     {
     260                 :            :                         // aTransform already contains the
     261                 :            :                         // translational component, moving the clip to
     262                 :            :                         // the final sprite output position.
     263                 :          0 :                         aClipPoly.transform( aTransform );
     264                 :            : 
     265                 :            : #if ! defined WNT && ! defined QUARTZ
     266                 :            :                         // non-Windows only - bAtLeastOnePolygon is
     267                 :            :                         // only used in non-WNT code below
     268                 :            : 
     269                 :            :                         // check whether maybe the clip consists
     270                 :            :                         // solely out of rectangular polygons. If this
     271                 :            :                         // is the case, enforce using the triangle
     272                 :            :                         // clip region setup - non-optimized X11
     273                 :            :                         // drivers tend to perform abyssmally on
     274                 :            :                         // XPolygonRegion, which is used internally,
     275                 :            :                         // when filling complex polypolygons.
     276                 :          0 :                         bool bAtLeastOnePolygon( false );
     277                 :          0 :                         const sal_Int32 nPolygons( aClipPoly.count() );
     278                 :            : 
     279                 :          0 :                         for( sal_Int32 i=0; i<nPolygons; ++i )
     280                 :            :                         {
     281                 :          0 :                             if( !::basegfx::tools::isRectangle(
     282                 :          0 :                                     aClipPoly.getB2DPolygon(i)) )
     283                 :            :                             {
     284                 :          0 :                                 bAtLeastOnePolygon = true;
     285                 :          0 :                                 break;
     286                 :            :                             }
     287                 :            :                         }
     288                 :            : #endif
     289                 :            : 
     290                 :          0 :                         if( mbShowSpriteBounds )
     291                 :            :                         {
     292                 :            :                             // Paint green sprite clip area
     293                 :          0 :                             rTargetSurface.SetLineColor( Color( 0,255,0 ) );
     294                 :          0 :                             rTargetSurface.SetFillColor();
     295                 :            : 
     296                 :          0 :                             rTargetSurface.DrawPolyPolygon(PolyPolygon(aClipPoly)); // #i76339#
     297                 :            :                         }
     298                 :            : 
     299                 :            : #if ! defined WNT && ! defined QUARTZ
     300                 :            :                         // as a matter of fact, this fast path only
     301                 :            :                         // performs well for X11 - under Windows, the
     302                 :            :                         // clip via SetTriangleClipRegion is faster.
     303                 :          0 :                         if( bAtLeastOnePolygon &&
     304                 :            :                             bBufferedUpdate &&
     305                 :          0 :                             ::rtl::math::approxEqual(fAlpha, 1.0) &&
     306                 :          0 :                             !maContent->IsTransparent() )
     307                 :            :                         {
     308                 :            :                             // fast path for slide transitions
     309                 :            :                             // (buffered, no alpha, no mask (because
     310                 :            :                             // full slide is contained in the sprite))
     311                 :            : 
     312                 :            :                             // XOR bitmap onto backbuffer, clear area
     313                 :            :                             // that should be _visible_ with black,
     314                 :            :                             // XOR bitmap again on top of that -
     315                 :            :                             // result: XOR cancels out where no black
     316                 :            :                             // has been rendered, and yields the
     317                 :            :                             // original bitmap, where black is
     318                 :            :                             // underneath.
     319                 :          0 :                             rTargetSurface.Push( PUSH_RASTEROP );
     320                 :          0 :                             rTargetSurface.SetRasterOp( ROP_XOR );
     321                 :            :                             rTargetSurface.DrawBitmap( aOutPos,
     322                 :            :                                                        aOutputSize,
     323                 :          0 :                                                        maContent->GetBitmap() );
     324                 :            : 
     325                 :          0 :                             rTargetSurface.SetLineColor();
     326                 :          0 :                             rTargetSurface.SetFillColor( COL_BLACK );
     327                 :          0 :                             rTargetSurface.SetRasterOp( ROP_0 );
     328                 :          0 :                             rTargetSurface.DrawPolyPolygon(PolyPolygon(aClipPoly)); // #i76339#
     329                 :            : 
     330                 :          0 :                             rTargetSurface.SetRasterOp( ROP_XOR );
     331                 :            :                             rTargetSurface.DrawBitmap( aOutPos,
     332                 :            :                                                        aOutputSize,
     333                 :          0 :                                                        maContent->GetBitmap() );
     334                 :            : 
     335                 :          0 :                             rTargetSurface.Pop();
     336                 :            : 
     337                 :          0 :                             bSpriteRedrawn = true;
     338                 :            :                         }
     339                 :            :                         else
     340                 :            : #endif
     341                 :            :                         {
     342                 :          0 :                             Region aClipRegion( aClipPoly );
     343                 :          0 :                             rTargetSurface.SetClipRegion( aClipRegion );
     344                 :            :                         }
     345                 :          0 :                     }
     346                 :            :                 }
     347                 :            : 
     348                 :          0 :                 if( !bSpriteRedrawn )
     349                 :            :                 {
     350                 :          0 :                     if( ::rtl::math::approxEqual(fAlpha, 1.0) )
     351                 :            :                     {
     352                 :            :                         // no alpha modulation -> just copy to output
     353                 :          0 :                         if( maContent->IsTransparent() )
     354                 :          0 :                             rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize, *maContent );
     355                 :            :                         else
     356                 :          0 :                             rTargetSurface.DrawBitmap( aOutPos, aOutputSize, maContent->GetBitmap() );
     357                 :            :                     }
     358                 :            :                     else
     359                 :            :                     {
     360                 :            :                         // TODO(P3): Switch to OutputDevice::DrawTransparent()
     361                 :            :                         // here
     362                 :            : 
     363                 :            :                         // draw semi-transparent
     364                 :          0 :                         sal_uInt8 nColor( static_cast<sal_uInt8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) );
     365                 :          0 :                         AlphaMask aAlpha( maContent->GetSizePixel(),
     366                 :          0 :                                           &nColor );
     367                 :            : 
     368                 :            :                         // mask out fully transparent areas
     369                 :          0 :                         if( maContent->IsTransparent() )
     370                 :          0 :                             aAlpha.Replace( maContent->GetMask(), 255 );
     371                 :            : 
     372                 :            :                         // alpha-blend to output
     373                 :            :                         rTargetSurface.DrawBitmapEx( aOutPos, aOutputSize,
     374                 :            :                                                      BitmapEx( maContent->GetBitmap(),
     375                 :          0 :                                                                aAlpha ) );
     376                 :            :                     }
     377                 :            :                 }
     378                 :            : 
     379                 :          0 :                 rTargetSurface.Pop();
     380                 :            : 
     381                 :          0 :                 if( mbShowSpriteBounds )
     382                 :            :                 {
     383                 :            :                     ::PolyPolygon aMarkerPoly(
     384                 :            :                         ::canvas::tools::getBoundMarksPolyPolygon(
     385                 :          0 :                             ::basegfx::B2DRectangle(aOutPos.X(),
     386                 :          0 :                                                     aOutPos.Y(),
     387                 :          0 :                                                     aOutPos.X() + aOutputSize.Width()-1,
     388                 :          0 :                                                     aOutPos.Y() + aOutputSize.Height()-1) ) );
     389                 :            : 
     390                 :            :                     // Paint little red sprite area markers
     391                 :          0 :                     rTargetSurface.SetLineColor( COL_RED );
     392                 :          0 :                     rTargetSurface.SetFillColor();
     393                 :            : 
     394                 :          0 :                     for( int i=0; i<aMarkerPoly.Count(); ++i )
     395                 :            :                     {
     396                 :          0 :                         rTargetSurface.DrawPolyLine( aMarkerPoly.GetObject((sal_uInt16)i) );
     397                 :            :                     }
     398                 :            : 
     399                 :            :                     // paint sprite prio
     400                 :          0 :                     Font aVCLFont;
     401                 :          0 :                     aVCLFont.SetHeight( std::min(long(20),aOutputSize.Height()) );
     402                 :          0 :                     aVCLFont.SetColor( COL_RED );
     403                 :            : 
     404                 :          0 :                     rTargetSurface.SetTextAlign(ALIGN_TOP);
     405                 :          0 :                     rTargetSurface.SetTextColor( COL_RED );
     406                 :          0 :                     rTargetSurface.SetFont( aVCLFont );
     407                 :            : 
     408                 :            :                     ::rtl::OUString text( ::rtl::math::doubleToUString( getPriority(),
     409                 :            :                                                                         rtl_math_StringFormat_F,
     410                 :          0 :                                                                         2,'.',NULL,' ') );
     411                 :            : 
     412                 :          0 :                     rTargetSurface.DrawText( aOutPos+Point(2,2), text );
     413                 :            :                     VERBOSE_TRACE( "SpriteHelper::redraw(): sprite %X has prio %f\n",
     414                 :          0 :                                    this, getPriority() );
     415                 :            :                 }
     416                 :          0 :             }
     417                 :            :         }
     418                 :            :     }
     419                 :            : 
     420                 :          0 :     ::basegfx::B2DPolyPolygon SpriteHelper::polyPolygonFromXPolyPolygon2D( uno::Reference< rendering::XPolyPolygon2D >& xPoly ) const
     421                 :            :     {
     422                 :          0 :         return ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( xPoly );
     423                 :            :     }
     424                 :            : 
     425                 :          0 : }
     426                 :            : 
     427                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10