LCOV - code coverage report
Current view: top level - basebmp/source - bitmapdevice.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 573 691 82.9 %
Date: 2014-11-03 Functions: 253 1087 23.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <sal/config.h>
      21             : 
      22             : #include <cassert>
      23             : #include <string.h>
      24             : 
      25             : #include <basebmp/bitmapdevice.hxx>
      26             : 
      27             : #include <basebmp/compositeiterator.hxx>
      28             : #include <basebmp/iteratortraits.hxx>
      29             : 
      30             : #include <basebmp/accessor.hxx>
      31             : #include <basebmp/accessortraits.hxx>
      32             : #include <basebmp/accessoradapters.hxx>
      33             : #include <basebmp/colorblendaccessoradapter.hxx>
      34             : 
      35             : #include <basebmp/color.hxx>
      36             : #include <basebmp/colormisc.hxx>
      37             : #include <basebmp/colortraits.hxx>
      38             : 
      39             : #include <basebmp/greylevelformats.hxx>
      40             : #include <basebmp/paletteformats.hxx>
      41             : #include <basebmp/rgbmaskpixelformats.hxx>
      42             : #include <basebmp/rgb24pixelformats.hxx>
      43             : 
      44             : #include <basebmp/scanlineformats.hxx>
      45             : #include <basebmp/fillimage.hxx>
      46             : #include <basebmp/scaleimage.hxx>
      47             : #include <basebmp/clippedlinerenderer.hxx>
      48             : #include <basebmp/polypolygonrenderer.hxx>
      49             : #include <basebmp/genericcolorimageaccessor.hxx>
      50             : 
      51             : #include <basebmp/tools.hxx>
      52             : #include "intconversion.hxx"
      53             : 
      54             : #include <rtl/alloc.h>
      55             : #include <osl/diagnose.h>
      56             : 
      57             : #include <basegfx/tools/tools.hxx>
      58             : #include <basegfx/tools/canvastools.hxx>
      59             : #include <basegfx/range/b2ibox.hxx>
      60             : #include <basegfx/range/b2irange.hxx>
      61             : #include <basegfx/range/b2drange.hxx>
      62             : #include <basegfx/polygon/b2dpolygon.hxx>
      63             : #include <basegfx/polygon/b2dpolygontools.hxx>
      64             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      65             : #include <basegfx/point/b2ipoint.hxx>
      66             : #include <basegfx/vector/b2ivector.hxx>
      67             : 
      68             : #include <vigra/iteratortraits.hxx>
      69             : #include <vigra/rgbvalue.hxx>
      70             : #include <vigra/copyimage.hxx>
      71             : #include <vigra/tuple.hxx>
      72             : 
      73             : 
      74             : namespace vigra
      75             : {
      76             : 
      77             : /// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
      78             : template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex >
      79             : inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex>
      80    19575503 : operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs,
      81             :            RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs )
      82             : {
      83             :     RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res(
      84    39151006 :         lhs[0] ^ rhs[0],
      85    39151006 :         lhs[1] ^ rhs[1],
      86    97877515 :         lhs[2] ^ rhs[2]);
      87    19575503 :     return res;
      88             : }
      89             : }
      90             : 
      91             : namespace basebmp
      92             : {
      93             : 
      94             : static const sal_uInt8 bitsPerPixel[] =
      95             : {
      96             :     0,  // NONE
      97             :     1,  // ONE_BIT_MSB_GREY
      98             :     1,  // ONE_BIT_LSB_GREY
      99             :     1,  // ONE_BIT_MSB_PAL
     100             :     1,  // ONE_BIT_LSB_PAL
     101             :     4,  // FOUR_BIT_MSB_GREY
     102             :     4,  // FOUR_BIT_LSB_GREY
     103             :     4,  // FOUR_BIT_MSB_PAL
     104             :     4,  // FOUR_BIT_LSB_PAL
     105             :     8,  // EIGHT_BIT_PAL
     106             :     8,  // EIGHT_BIT_GREY
     107             :     16, // SIXTEEN_BIT_LSB_TC_MASK
     108             :     16, // SIXTEEN_BIT_MSB_TC_MASK
     109             :     24, // TWENTYFOUR_BIT_TC_MASK
     110             :     32, // THIRTYTWO_BIT_TC_MASK_BGRA
     111             :     32, // THIRTYTWO_BIT_TC_MASK_ARGB
     112             :     32, // THIRTYTWO_BIT_TC_MASK_ABGR
     113             :     32, // THIRTYTWO_BIT_TC_MASK_RGBA
     114             : };
     115             : 
     116             : namespace
     117             : {
     118             :     /** Create the type for an accessor that takes the (mask,bitmap)
     119             :         input value generated from a JoinImageAccessorAdapter, and
     120             :         pipe that through a mask functor.
     121             : 
     122             :         @tpl DestAccessor
     123             :         Destination bitmap accessor
     124             : 
     125             :         @tpl JoinedAccessor
     126             :         Input accessor, is expected to generate a std::pair as the
     127             :         value type
     128             : 
     129             :         @tpl MaskFunctorMode
     130             :         Either FastMask or NoFastMask, depending on whether the mask
     131             :         is guaranteed to contain only 0s and 1s.
     132             :      */
     133             :     template< class    DestAccessor,
     134             :               class    JoinedAccessor,
     135             :               bool     polarity,
     136             :               typename MaskFunctorMode > struct masked_input_splitting_accessor
     137             :     {
     138             :         typedef BinarySetterFunctionAccessorAdapter<
     139             :             DestAccessor,
     140             :             BinaryFunctorSplittingWrapper<
     141             :                 typename outputMaskFunctorSelector<
     142             :                          typename JoinedAccessor::value_type::first_type,
     143             :                          typename JoinedAccessor::value_type::second_type,
     144             :                          polarity,
     145             :                          MaskFunctorMode >::type > > type;
     146             :     };
     147             : 
     148             : 
     149             : 
     150             :     // Actual BitmapDevice implementation (templatized by accessor and iterator)
     151             : 
     152             :     /** Implementation of the BitmapDevice interface
     153             : 
     154             :         @tpl DestIterator
     155             :         Iterator to access bitmap memory
     156             : 
     157             :         @tpl RawAccessor
     158             :         Raw accessor, to access pixel values directly
     159             : 
     160             :         @tpl AccessorSelector
     161             :         Accessor adapter selector, which, when applying the nested
     162             :         template metafunction wrap_accessor to one of the raw bitmap
     163             :         accessors, yields a member type named 'type', which is a
     164             :         wrapped accessor that map color values.
     165             : 
     166             :         @tpl Masks
     167             :         Traits template, containing nested traits
     168             :         clipmask_format_traits and alphamask_format_traits, which
     169             :         determine what specialized formats are to be used for clip and
     170             :         alpha masks. With those mask formats, clipping and alpha
     171             :         blending is handled natively.
     172             :      */
     173             :     template< class DestIterator,
     174             :               class RawAccessor,
     175             :               class AccessorSelector,
     176     3613086 :               class Masks > class BitmapRenderer :
     177             :                   public BitmapDevice
     178             :     {
     179             :     public:
     180             :         typedef DestIterator                                               dest_iterator_type;
     181             :         typedef RawAccessor                                                raw_accessor_type;
     182             :         typedef AccessorSelector                                           accessor_selector;
     183             : 
     184             :         typedef typename Masks::clipmask_format_traits::iterator_type      mask_iterator_type;
     185             :         typedef typename Masks::clipmask_format_traits::raw_accessor_type  mask_rawaccessor_type;
     186             :         typedef typename Masks::clipmask_format_traits::accessor_selector  mask_accessorselector_type;
     187             : 
     188             :         typedef typename Masks::alphamask_format_traits::iterator_type     alphamask_iterator_type;
     189             :         typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type;
     190             :         typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type;
     191             : 
     192             :         typedef typename AccessorSelector::template wrap_accessor<
     193             :             raw_accessor_type >::type                                      dest_accessor_type;
     194             : 
     195             :         typedef AccessorTraits< dest_accessor_type >                       accessor_traits;
     196             :         typedef CompositeIterator2D< dest_iterator_type,
     197             :                                      mask_iterator_type >                  composite_iterator_type;
     198             :         typedef CompositeIterator2D< vigra::Diff2D,
     199             :                                      vigra::Diff2D >                       generic_composite_iterator_type;
     200             : 
     201             :         typedef BitmapRenderer<mask_iterator_type,
     202             :                                mask_rawaccessor_type,
     203             :                                mask_accessorselector_type,
     204             :                                Masks>                                      mask_bitmap_type;
     205             :         typedef BitmapRenderer<alphamask_iterator_type,
     206             :                                alphamask_rawaccessor_type,
     207             :                                alphamask_accessorselector_type,
     208             :                                Masks>                                      alphamask_bitmap_type;
     209             : 
     210             : 
     211             : 
     212             :         typedef AccessorTraits< raw_accessor_type >                        raw_accessor_traits;
     213             :         typedef typename uInt32Converter<
     214             :             typename raw_accessor_type::value_type>::to                    to_uint32_functor;
     215             : 
     216             : 
     217             : 
     218             :         typedef typename raw_accessor_traits::xor_accessor                 raw_xor_accessor_type;
     219             :         typedef AccessorTraits<raw_xor_accessor_type>                      raw_xor_accessor_traits;
     220             :         typedef typename accessor_selector::template wrap_accessor<
     221             :             raw_xor_accessor_type >::type                                  xor_accessor_type;
     222             :         typedef AccessorTraits<xor_accessor_type>                          xor_accessor_traits;
     223             : 
     224             : 
     225             : 
     226             :         typedef typename raw_accessor_traits::template masked_accessor<
     227             :             mask_rawaccessor_type,
     228             :             dest_iterator_type,
     229             :             mask_iterator_type,
     230             :             Masks::clipmask_polarity>::type                                raw_maskedaccessor_type;
     231             :         typedef typename accessor_selector::template wrap_accessor<
     232             :             raw_maskedaccessor_type >::type                                masked_accessor_type;
     233             :         typedef typename AccessorTraits<
     234             :             raw_maskedaccessor_type>::xor_accessor                         raw_maskedxor_accessor_type;
     235             :         typedef typename accessor_selector::template wrap_accessor<
     236             :             raw_maskedxor_accessor_type >::type                            masked_xoraccessor_type;
     237             : 
     238             : 
     239             : 
     240             :         // ((iter,mask),mask) special case (e.g. for clipped
     241             :         // drawMaskedColor())
     242             :         typedef AccessorTraits< raw_maskedaccessor_type >                  raw_maskedaccessor_traits;
     243             :         typedef typename raw_maskedaccessor_traits::template masked_accessor<
     244             :             mask_rawaccessor_type,
     245             :             composite_iterator_type,
     246             :             mask_iterator_type,
     247             :             Masks::clipmask_polarity>::type                                raw_maskedmask_accessor_type;
     248             : 
     249             :         typedef CompositeIterator2D<
     250             :             composite_iterator_type,
     251             :             mask_iterator_type>                                            composite_composite_mask_iterator_type;
     252             : 
     253             : 
     254             : 
     255             :         typedef ConstantColorBlendSetterAccessorAdapter<
     256             :             dest_accessor_type,
     257             :             typename alphamask_rawaccessor_type::value_type,
     258             :             Masks::alphamask_polarity>                                     colorblend_accessor_type;
     259             :         typedef AccessorTraits<colorblend_accessor_type>                   colorblend_accessor_traits;
     260             :         typedef typename colorblend_accessor_traits::template masked_accessor<
     261             :             mask_rawaccessor_type,
     262             :             dest_iterator_type,
     263             :             mask_iterator_type,
     264             :             Masks::clipmask_polarity>::type                                masked_colorblend_accessor_type;
     265             : 
     266             : 
     267             : 
     268             :         typedef ConstantColorBlendSetterAccessorAdapter<
     269             :             dest_accessor_type,
     270             :             Color,
     271             :             Masks::alphamask_polarity>                                     colorblend_generic_accessor_type;
     272             :         typedef AccessorTraits<colorblend_generic_accessor_type>           colorblend_generic_accessor_traits;
     273             :         typedef typename colorblend_generic_accessor_traits::template masked_accessor<
     274             :             mask_rawaccessor_type,
     275             :             dest_iterator_type,
     276             :             mask_iterator_type,
     277             :             Masks::clipmask_polarity>::type                                masked_colorblend_generic_accessor_type;
     278             : 
     279             : 
     280             : 
     281             :         typedef JoinImageAccessorAdapter< dest_accessor_type,
     282             :                                           mask_rawaccessor_type >          joined_image_accessor_type;
     283             :         typedef JoinImageAccessorAdapter< GenericColorImageAccessor,
     284             :                                           GenericColorImageAccessor >      joined_generic_image_accessor_type;
     285             : 
     286             : 
     287             : 
     288             :         dest_iterator_type                      maBegin;
     289             :         typename accessor_traits::color_lookup  maColorLookup;
     290             :         IBitmapDeviceDamageTrackerSharedPtr     mpDamage;
     291             :         to_uint32_functor                       maToUInt32Converter;
     292             :         dest_accessor_type                      maAccessor;
     293             :         colorblend_accessor_type                maColorBlendAccessor;
     294             :         colorblend_generic_accessor_type        maGenericColorBlendAccessor;
     295             :         raw_accessor_type                       maRawAccessor;
     296             :         xor_accessor_type                       maXorAccessor;
     297             :         raw_xor_accessor_type                   maRawXorAccessor;
     298             :         masked_accessor_type                    maMaskedAccessor;
     299             :         masked_colorblend_accessor_type         maMaskedColorBlendAccessor;
     300             :         masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor;
     301             :         masked_xoraccessor_type                 maMaskedXorAccessor;
     302             :         raw_maskedaccessor_type                 maRawMaskedAccessor;
     303             :         raw_maskedxor_accessor_type             maRawMaskedXorAccessor;
     304             :         raw_maskedmask_accessor_type            maRawMaskedMaskAccessor;
     305             : 
     306             : 
     307             : 
     308             : 
     309     1830472 :         BitmapRenderer( const basegfx::B2IBox&                     rBounds,
     310             :                         const basegfx::B2IVector&                  rBufferSize,
     311             :                         Format                                     nScanlineFormat,
     312             :                         sal_Int32                                  nScanlineStride,
     313             :                         sal_uInt8*                                 pFirstScanline,
     314             :                         dest_iterator_type                         begin,
     315             :                         raw_accessor_type                          rawAccessor,
     316             :                         dest_accessor_type                         accessor,
     317             :                         const RawMemorySharedArray&                rMem,
     318             :                         const PaletteMemorySharedVector&           rPalette,
     319             :                         const IBitmapDeviceDamageTrackerSharedPtr& rDamage ) :
     320             :             BitmapDevice( rBounds, rBufferSize, nScanlineFormat,
     321             :                           nScanlineStride, pFirstScanline, rMem, rPalette ),
     322             :             maBegin( begin ),
     323             :             maColorLookup(),
     324             :             mpDamage(rDamage),
     325             :             maToUInt32Converter(),
     326             :             maAccessor( accessor ),
     327             :             maColorBlendAccessor( accessor ),
     328             :             maGenericColorBlendAccessor( accessor ),
     329             :             maRawAccessor( rawAccessor ),
     330             :             maXorAccessor( accessor ),
     331             :             maRawXorAccessor( rawAccessor ),
     332             :             maMaskedAccessor( accessor ),
     333             :             maMaskedColorBlendAccessor( maColorBlendAccessor ),
     334             :             maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ),
     335             :             maMaskedXorAccessor( accessor ),
     336             :             maRawMaskedAccessor( rawAccessor ),
     337             :             maRawMaskedXorAccessor( rawAccessor ),
     338     1830472 :             maRawMaskedMaskAccessor( rawAccessor )
     339     1830472 :         {}
     340             : 
     341             :     private:
     342             : 
     343     5234534 :         void damaged( const basegfx::B2IBox& rDamageRect ) const
     344             :         {
     345     5234534 :             if( mpDamage )
     346           0 :                 mpDamage->damaged( rDamageRect );
     347     5234534 :         }
     348             : 
     349     2293658 :         void damagedPointSize( const basegfx::B2IPoint& rPoint,
     350             :                                const basegfx::B2IBox&   rSize ) const
     351             :         {
     352     2293658 :             if( mpDamage ) {
     353           0 :                 basegfx::B2IPoint aLower( rPoint.getX() + rSize.getWidth(),
     354           0 :                                           rPoint.getY() + rSize.getHeight() );
     355           0 :                 damaged( basegfx::B2IBox( rPoint, aLower ) );
     356             :             }
     357     2293658 :         }
     358             : 
     359     1326210 :         void damagedPixel( const basegfx::B2IPoint& rDamagePoint ) const
     360             :         {
     361     1326210 :             if( !mpDamage )
     362     2652420 :                 return;
     363             : 
     364           0 :             sal_Int32 nX(rDamagePoint.getX());
     365           0 :             sal_Int32 nY(rDamagePoint.getY());
     366           0 :             if (nX < SAL_MAX_INT32)
     367           0 :                 ++nX;
     368           0 :             if (nY < SAL_MAX_INT32)
     369           0 :                 ++nY;
     370             : 
     371           0 :             basegfx::B2IPoint aEnd( nX, nY );
     372           0 :             damaged( basegfx::B2IBox( rDamagePoint, aEnd ) );
     373             :         }
     374             : 
     375      595412 :         boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
     376             :         {
     377      595412 :             return boost::dynamic_pointer_cast< BitmapRenderer >( bmp );
     378             :         }
     379             : 
     380      582402 :         virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const SAL_OVERRIDE
     381             :         {
     382             :             // TODO(P1): dynamic_cast usually called twice for
     383             :             // compatible formats
     384      582402 :             return getCompatibleBitmap(bmp).get() != NULL;
     385             :         }
     386             : 
     387     3003255 :         boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
     388             :         {
     389     3003255 :             boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ));
     390             : 
     391     3003255 :             if( !pMask )
     392     2293658 :                 return pMask;
     393             : 
     394      709597 :             if( pMask->getSize() != getSize() )
     395           0 :                 pMask.reset();
     396             : 
     397      709597 :             return pMask;
     398             :         }
     399             : 
     400      728912 :         virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const SAL_OVERRIDE
     401             :         {
     402             :             // TODO(P1): dynamic_cast usually called twice for
     403             :             // compatible formats
     404      728912 :             return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL;
     405             :         }
     406             : 
     407     2293658 :         boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
     408             :         {
     409     2293658 :             return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp );
     410             :         }
     411             : 
     412           0 :         virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const SAL_OVERRIDE
     413             :         {
     414             :             // TODO(P1): dynamic_cast usually called twice for
     415             :             // compatible formats
     416           0 :             return getCompatibleAlphaMask( bmp ).get() != NULL;
     417             :         }
     418             : 
     419         148 :         virtual void clear_i( Color                   fillColor,
     420             :                               const basegfx::B2IBox&  rBounds ) SAL_OVERRIDE
     421             :         {
     422         148 :             fillImage(destIterRange(maBegin,
     423             :                                     maRawAccessor,
     424         148 :                                     rBounds),
     425             :                       maColorLookup(
     426             :                           maAccessor,
     427         444 :                           fillColor) );
     428         148 :             damaged( rBounds );
     429         148 :         }
     430             : 
     431      768243 :         virtual void setPixel_i( const basegfx::B2IPoint& rPt,
     432             :                                  Color                    pixelColor,
     433             :                                  DrawMode                 drawMode ) SAL_OVERRIDE
     434             :         {
     435     1536486 :             const DestIterator pixel( maBegin +
     436             :                                       vigra::Diff2D(rPt.getX(),
     437      768243 :                                                     rPt.getY()) );
     438      768243 :             if( drawMode == DrawMode_XOR )
     439           0 :                 maXorAccessor.set( pixelColor,
     440             :                                    pixel );
     441             :             else
     442      768243 :                 maAccessor.set( pixelColor,
     443             :                                 pixel );
     444      768243 :             damagedPixel(rPt);
     445      768243 :         }
     446             : 
     447      557967 :         virtual void setPixel_i( const basegfx::B2IPoint&     rPt,
     448             :                                  Color                        pixelColor,
     449             :                                  DrawMode                     drawMode,
     450             :                                  const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
     451             :         {
     452      557967 :             boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
     453             :             OSL_ASSERT( pMask );
     454             : 
     455             :             const vigra::Diff2D offset(rPt.getX(),
     456      557967 :                                        rPt.getY());
     457             : 
     458             :             const composite_iterator_type aIter(
     459      557967 :                 maBegin + offset,
     460     1115934 :                 pMask->maBegin + offset );
     461             : 
     462      557967 :             if( drawMode == DrawMode_XOR )
     463           0 :                 maMaskedXorAccessor.set( pixelColor,
     464             :                                          aIter );
     465             :             else
     466      557967 :                 maMaskedAccessor.set( pixelColor,
     467             :                                       aIter );
     468      557967 :             damagedPixel(rPt);
     469      557967 :         }
     470             : 
     471   123542882 :         virtual Color getPixel_i(const basegfx::B2IPoint& rPt ) SAL_OVERRIDE
     472             :         {
     473   247085764 :             const DestIterator pixel( maBegin +
     474             :                                       vigra::Diff2D(rPt.getX(),
     475   123542882 :                                                     rPt.getY()) );
     476   123542882 :             return maAccessor(pixel);
     477             :         }
     478             : 
     479           8 :         virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt ) SAL_OVERRIDE
     480             :         {
     481          16 :             const DestIterator pixel( maBegin +
     482             :                                       vigra::Diff2D(rPt.getX(),
     483           8 :                                                     rPt.getY()) );
     484           8 :             return maToUInt32Converter(maRawAccessor(pixel));
     485             :         }
     486             : 
     487             :         template< typename Iterator, typename Col, typename RawAcc >
     488     4596510 :         void implRenderLine2( const basegfx::B2IPoint& rPt1,
     489             :                               const basegfx::B2IPoint& rPt2,
     490             :                               const basegfx::B2IBox&   rBounds,
     491             :                               Col                      col,
     492             :                               const Iterator&          begin,
     493             :                               const RawAcc&            rawAcc )
     494             :         {
     495     4596510 :             renderClippedLine( rPt1,
     496             :                                rPt2,
     497             :                                rBounds,
     498             :                                col,
     499             :                                begin,
     500     9193020 :                                rawAcc );
     501             :             // TODO(P2): perhaps this needs pushing up the stack a bit
     502             :             // to make more complex polygons more efficient ...
     503     4596510 :             damaged( basegfx::B2IBox( rPt1, rPt2 ) );
     504     4596510 :         }
     505             : 
     506             :         template< typename Iterator, typename Accessor, typename RawAcc >
     507     3330233 :         void implRenderLine( const basegfx::B2IPoint& rPt1,
     508             :                              const basegfx::B2IPoint& rPt2,
     509             :                              const basegfx::B2IBox&   rBounds,
     510             :                              Color                    col,
     511             :                              const Iterator&          begin,
     512             :                              const Accessor&          acc,
     513             :                              const RawAcc&            rawAcc )
     514             :         {
     515     3330233 :             implRenderLine2( rPt1,rPt2,rBounds,
     516             :                              maColorLookup( acc,
     517             :                                             col ),
     518             :                              begin,
     519     6660406 :                              rawAcc );
     520     3330233 :         }
     521             : 
     522             :         template< typename Iterator, typename RawAcc, typename XorAcc >
     523     3330233 :         void implDrawLine( const basegfx::B2IPoint& rPt1,
     524             :                            const basegfx::B2IPoint& rPt2,
     525             :                            const basegfx::B2IBox&   rBounds,
     526             :                            Color                    col,
     527             :                            const Iterator&          begin,
     528             :                            const RawAcc&            rawAcc,
     529             :                            const XorAcc&            xorAcc,
     530             :                            DrawMode                 drawMode )
     531             :         {
     532     3330233 :             if( drawMode == DrawMode_XOR )
     533          16 :                 implRenderLine( rPt1, rPt2, rBounds, col,
     534          16 :                                 begin, maAccessor, xorAcc );
     535             :             else
     536     3330217 :                 implRenderLine( rPt1, rPt2, rBounds, col,
     537     3330217 :                                 begin, maAccessor, rawAcc );
     538     3330233 :         }
     539             : 
     540     3244323 :         virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
     541             :                                 const basegfx::B2IPoint& rPt2,
     542             :                                 const basegfx::B2IBox&   rBounds,
     543             :                                 Color                    lineColor,
     544             :                                 DrawMode                 drawMode ) SAL_OVERRIDE
     545             :         {
     546     3244323 :             implDrawLine(rPt1,rPt2,rBounds,lineColor,
     547             :                          maBegin,
     548     3244323 :                          maRawAccessor,maRawXorAccessor,drawMode);
     549     3244323 :         }
     550             : 
     551      151622 :         composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const
     552             :         {
     553      151622 :             boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
     554             :             OSL_ASSERT( pMask );
     555             : 
     556             :             return composite_iterator_type( maBegin,
     557      151622 :                                             pMask->maBegin );
     558             :         }
     559             : 
     560       85910 :         virtual void drawLine_i(const basegfx::B2IPoint&     rPt1,
     561             :                                 const basegfx::B2IPoint&     rPt2,
     562             :                                 const basegfx::B2IBox&       rBounds,
     563             :                                 Color                        lineColor,
     564             :                                 DrawMode                     drawMode,
     565             :                                 const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
     566             :         {
     567       85910 :             implDrawLine(rPt1,rPt2,rBounds,lineColor,
     568             :                          getMaskedIter(rClip),
     569             :                          maRawMaskedAccessor,
     570      171820 :                          maRawMaskedXorAccessor,drawMode);
     571       85910 :         }
     572             : 
     573             :         template< typename Iterator, typename RawAcc >
     574      262774 :         void implDrawPolygon( const basegfx::B2DPolygon& rPoly,
     575             :                               const basegfx::B2IBox&     rBounds,
     576             :                               Color                      col,
     577             :                               const Iterator&            begin,
     578             :                               const RawAcc&              acc )
     579             :         {
     580      262774 :             basegfx::B2DPolygon aPoly( rPoly );
     581      262774 :             if( rPoly.areControlPointsUsed() )
     582           0 :                 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
     583             : 
     584             :             const typename dest_iterator_type::value_type colorIndex( maColorLookup(
     585             :                                                                           maAccessor,
     586      262774 :                                                                           col));
     587      262774 :             const sal_uInt32                              nVertices( aPoly.count() );
     588     1520238 :             for( sal_uInt32 i=1; i<nVertices; ++i )
     589     1257464 :                 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)),
     590             :                                  basegfx::fround(aPoly.getB2DPoint(i)),
     591             :                                  rBounds,
     592             :                                  colorIndex,
     593             :                                  begin,
     594     2514928 :                                  acc );
     595             : 
     596      262774 :             if( nVertices > 1 && aPoly.isClosed() )
     597        8813 :                 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)),
     598             :                                  basegfx::fround(aPoly.getB2DPoint(0)),
     599             :                                  rBounds,
     600             :                                  colorIndex,
     601             :                                  begin,
     602       17626 :                                  acc );
     603      262774 :         }
     604             : 
     605      261264 :         virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
     606             :                                    const basegfx::B2IBox&     rBounds,
     607             :                                    Color                      lineColor,
     608             :                                    DrawMode                   drawMode ) SAL_OVERRIDE
     609             :         {
     610      261264 :             if( drawMode == DrawMode_XOR )
     611           0 :                 implDrawPolygon( rPoly, rBounds, lineColor,
     612             :                                  maBegin,
     613           0 :                                  maRawXorAccessor );
     614             :             else
     615      261264 :                 implDrawPolygon( rPoly, rBounds, lineColor,
     616             :                                  maBegin,
     617      261264 :                                  maRawAccessor );
     618      261264 :         }
     619             : 
     620        1510 :         virtual void drawPolygon_i(const basegfx::B2DPolygon&   rPoly,
     621             :                                    const basegfx::B2IBox&       rBounds,
     622             :                                    Color                        lineColor,
     623             :                                    DrawMode                     drawMode,
     624             :                                    const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
     625             :         {
     626        1510 :             if( drawMode == DrawMode_XOR )
     627           0 :                 implDrawPolygon( rPoly, rBounds, lineColor,
     628             :                                  getMaskedIter(rClip),
     629           0 :                                  maRawMaskedXorAccessor );
     630             :             else
     631        1510 :                 implDrawPolygon( rPoly, rBounds, lineColor,
     632             :                                  getMaskedIter(rClip),
     633        3020 :                                  maRawMaskedAccessor );
     634        1510 :         }
     635             : 
     636             :         template< typename Iterator, typename RawAcc >
     637     4655917 :         void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
     638             :                                   Color                          col,
     639             :                                   const Iterator&                begin,
     640             :                                   const RawAcc&                  acc,
     641             :                                   const basegfx::B2IBox&         rBounds )
     642             :         {
     643     4655917 :             basegfx::B2DPolyPolygon aPoly( rPoly );
     644     4655917 :             if( rPoly.areControlPointsUsed() )
     645           0 :                 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
     646             : 
     647     4655917 :             renderClippedPolyPolygon( begin,
     648             :                                       acc,
     649             :                                       maColorLookup( maAccessor,
     650             :                                                      col),
     651             :                                       rBounds,
     652             :                                       aPoly,
     653     9169937 :                                       basegfx::FillRule_EVEN_ODD );
     654             : 
     655     4655917 :             if( mpDamage )
     656             :             {
     657           0 :                 basegfx::B2DRange const aPolyBounds( basegfx::tools::getRange(aPoly) );
     658           0 :                 damaged( basegfx::unotools::b2ISurroundingBoxFromB2DRange( aPolyBounds ) );
     659     4655917 :             }
     660     4655917 :         }
     661             : 
     662     4594481 :         virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
     663             :                                        Color                          fillColor,
     664             :                                        DrawMode                       drawMode,
     665             :                                        const basegfx::B2IBox&         rBounds ) SAL_OVERRIDE
     666             :         {
     667     4594481 :             if( drawMode == DrawMode_XOR )
     668      115135 :                 implFillPolyPolygon( rPoly, fillColor,
     669             :                                      maBegin,
     670             :                                      maRawXorAccessor,
     671      115135 :                                      rBounds );
     672             :             else
     673     4479346 :                 implFillPolyPolygon( rPoly, fillColor,
     674             :                                      maBegin,
     675             :                                      maRawAccessor,
     676     4479346 :                                      rBounds );
     677     4594481 :         }
     678             : 
     679       61436 :         virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
     680             :                                        Color                          fillColor,
     681             :                                        DrawMode                       drawMode,
     682             :                                        const basegfx::B2IBox&         rBounds,
     683             :                                        const BitmapDeviceSharedPtr&   rClip ) SAL_OVERRIDE
     684             :         {
     685       61436 :             if( drawMode == DrawMode_XOR )
     686         186 :                 implFillPolyPolygon( rPoly, fillColor,
     687             :                                      getMaskedIter(rClip),
     688             :                                      maRawMaskedXorAccessor,
     689         372 :                                      rBounds );
     690             :             else
     691       61250 :                 implFillPolyPolygon( rPoly, fillColor,
     692             :                                      getMaskedIter(rClip),
     693             :                                      maRawMaskedAccessor,
     694      122500 :                                      rBounds );
     695       61436 :         }
     696             : 
     697             :         template< typename Iterator, typename RawAcc >
     698       13002 :         void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
     699             :                             const basegfx::B2IBox&       rSrcRect,
     700             :                             const basegfx::B2IBox&       rDstRect,
     701             :                             const Iterator&              begin,
     702             :                             const RawAcc&                acc)
     703             :         {
     704       13002 :             boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
     705             :             OSL_ASSERT( pSrcBmp );
     706             : 
     707       13002 :             scaleImage(
     708       13002 :                 srcIterRange(pSrcBmp->maBegin,
     709       13002 :                              pSrcBmp->maRawAccessor,
     710       26004 :                              rSrcRect),
     711             :                 destIterRange(begin,
     712             :                               acc,
     713             :                               rDstRect),
     714       39006 :                 isSharedBuffer(rSrcBitmap) );
     715       13002 :             damaged( rDstRect );
     716       13002 :         }
     717             : 
     718             :         template< typename Iterator, typename Acc >
     719        3834 :         void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
     720             :                                    const basegfx::B2IBox&       rSrcRect,
     721             :                                    const basegfx::B2IBox&       rDstRect,
     722             :                                    const Iterator&              begin,
     723             :                                    const Acc&                   acc)
     724             :         {
     725        3834 :             GenericColorImageAccessor aSrcAcc( rSrcBitmap );
     726             : 
     727        3834 :             scaleImage(
     728             :                 srcIterRange(vigra::Diff2D(),
     729             :                              aSrcAcc,
     730             :                              rSrcRect),
     731             :                 destIterRange(begin,
     732             :                               acc,
     733        7668 :                               rDstRect));
     734        3834 :             damaged( rDstRect );
     735        3834 :         }
     736             : 
     737      565558 :         void implDrawBitmapDirect(const BitmapDeviceSharedPtr& rSrcBitmap,
     738             :                                   const basegfx::B2IBox&       rSrcRect,
     739             :                                   const basegfx::B2IBox&       rDstRect)
     740             :         {
     741      565558 :             sal_Int32 nSrcX = rSrcRect.getMinX();
     742      565558 :             sal_Int32 nSrcY = rSrcRect.getMinY();
     743      565558 :             sal_Int32 nSrcWidth = rSrcRect.getWidth();
     744      565558 :             sal_Int32 nSrcHeight = rSrcRect.getHeight();
     745      565558 :             sal_Int32 nDestX = rDstRect.getMinX();
     746      565558 :             sal_Int32 nDestY = rDstRect.getMinY();
     747             : 
     748      565558 :             char* dstBuf =  (char*)getBuffer().get();
     749      565558 :             char* srcBuf =  (char*)rSrcBitmap->getBuffer().get();
     750      565558 :             sal_Int32 dstStride =  getScanlineStride();
     751      565558 :             sal_Int32 srcStride =  rSrcBitmap->getScanlineStride();
     752      565558 :             sal_Int32 bytesPerPixel = (bitsPerPixel[getScanlineFormat()] + 7) >> 3; // round up to bytes
     753      565558 :             bool dstTopDown = isTopDown();
     754      565558 :             bool srcTopDown = rSrcBitmap->isTopDown();
     755             : 
     756      565558 :             if (dstBuf == srcBuf && nSrcY < nDestY) // reverse copy order to avoid overlapping
     757             :             {
     758          72 :                 nSrcY = getBufferSize().getY() - nSrcY - nSrcHeight;
     759          72 :                 nDestY = getBufferSize().getY() - nDestY - nSrcHeight;
     760          72 :                 srcTopDown = !srcTopDown;
     761          72 :                 dstTopDown = !dstTopDown;
     762             :             }
     763             : 
     764      565558 :             if (!dstTopDown)
     765             :             {
     766      565484 :                 dstBuf += dstStride * (getBufferSize().getY() - 1);
     767      565484 :                 dstStride = -dstStride;
     768             :             }
     769             : 
     770      565558 :             if (!srcTopDown)
     771             :             {
     772      565484 :                 srcBuf += srcStride * (rSrcBitmap->getBufferSize().getY() - 1);
     773      565484 :                 srcStride = -srcStride;
     774             :             }
     775             : 
     776      565558 :             char* dstline = dstBuf + dstStride * nDestY + nDestX * bytesPerPixel;
     777      565558 :             char* srcline = srcBuf + srcStride * nSrcY + nSrcX * bytesPerPixel;
     778      565558 :             sal_Int32 lineBytes = nSrcWidth * bytesPerPixel;
     779             : 
     780    33395771 :             for(; 0 < nSrcHeight; nSrcHeight--)
     781             :             {
     782    32830213 :                 memmove(dstline, srcline, lineBytes);
     783    32830213 :                 dstline += dstStride;
     784    32830213 :                 srcline += srcStride;
     785             :             }
     786      565558 :         }
     787             : 
     788      580355 :         virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
     789             :                                   const basegfx::B2IBox&       rSrcRect,
     790             :                                   const basegfx::B2IBox&       rDstRect,
     791             :                                   DrawMode                     drawMode ) SAL_OVERRIDE
     792             :         {
     793      580355 :             if( isCompatibleBitmap( rSrcBitmap ) )
     794             :             {
     795      576521 :                 if( drawMode == DrawMode_XOR )
     796           0 :                     implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
     797             :                                    maBegin,
     798           0 :                                    maRawXorAccessor);
     799     2273241 :                 else if (bitsPerPixel[getScanlineFormat()] >= 8
     800     1131162 :                          && rSrcRect.getWidth() == rDstRect.getWidth() && rSrcRect.getHeight() == rDstRect.getHeight()
     801      565558 :                          && rSrcBitmap->getScanlineFormat() == getScanlineFormat())
     802      565558 :                     implDrawBitmapDirect(rSrcBitmap, rSrcRect, rDstRect);
     803             :                 else
     804       10963 :                     implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
     805             :                                    maBegin,
     806       10963 :                                    maRawAccessor);
     807             :             }
     808             :             else
     809             :             {
     810        3834 :                 if( drawMode == DrawMode_XOR )
     811           0 :                     implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
     812             :                                           maBegin,
     813           0 :                                           maXorAccessor);
     814             :                 else
     815        3834 :                     implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
     816             :                                           maBegin,
     817        3834 :                                           maAccessor);
     818             :             }
     819      580355 :             damaged( rDstRect );
     820      580355 :         }
     821             : 
     822        2039 :         virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
     823             :                                   const basegfx::B2IBox&       rSrcRect,
     824             :                                   const basegfx::B2IBox&       rDstRect,
     825             :                                   DrawMode                     drawMode,
     826             :                                   const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
     827             :         {
     828        2039 :             if( isCompatibleBitmap( rSrcBitmap ) )
     829             :             {
     830        2039 :                 if( drawMode == DrawMode_XOR )
     831           0 :                     implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
     832             :                                    getMaskedIter(rClip),
     833           0 :                                    maRawMaskedXorAccessor);
     834             :                 else
     835        2039 :                     implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
     836             :                                    getMaskedIter(rClip),
     837        4078 :                                    maRawMaskedAccessor);
     838             :             }
     839             :             else
     840             :             {
     841           0 :                 if( drawMode == DrawMode_XOR )
     842           0 :                     implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
     843             :                                           getMaskedIter(rClip),
     844           0 :                                           maMaskedXorAccessor);
     845             :                 else
     846           0 :                     implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
     847             :                                           getMaskedIter(rClip),
     848           0 :                                           maMaskedAccessor);
     849             :             }
     850        2039 :             damaged( rDstRect );
     851        2039 :         }
     852             : 
     853     2292933 :         virtual void drawMaskedColor_i(Color                        aSrcColor,
     854             :                                        const BitmapDeviceSharedPtr& rAlphaMask,
     855             :                                        const basegfx::B2IBox&       rSrcRect,
     856             :                                        const basegfx::B2IPoint&     rDstPoint ) SAL_OVERRIDE
     857             :         {
     858     2292933 :             boost::shared_ptr<mask_bitmap_type>      pMask( getCompatibleClipMask(rAlphaMask) );
     859     4585866 :             boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
     860             : 
     861     2292933 :             if( pAlpha )
     862             :             {
     863     2292933 :                 maColorBlendAccessor.setColor( aSrcColor );
     864             : 
     865     4585866 :                 vigra::copyImage( srcIterRange(pAlpha->maBegin,
     866     2292933 :                                                pAlpha->maRawAccessor,
     867             :                                                rSrcRect),
     868             :                                   destIter(maBegin,
     869             :                                            maColorBlendAccessor,
     870     6878799 :                                            rDstPoint) );
     871             :             }
     872           0 :             else if( pMask )
     873             :             {
     874             :                 const composite_iterator_type aBegin(
     875           0 :                     maBegin + vigra::Diff2D(rDstPoint.getX(),
     876             :                                             rDstPoint.getY()),
     877           0 :                     pMask->maBegin + topLeft(rSrcRect) );
     878             : 
     879           0 :                 fillImage(aBegin,
     880           0 :                           aBegin + vigra::Diff2D(rSrcRect.getWidth(),
     881           0 :                                                  rSrcRect.getHeight()),
     882             :                           maRawMaskedAccessor,
     883             :                           maColorLookup(
     884             :                               maAccessor,
     885           0 :                               aSrcColor) );
     886             :             }
     887             :             else
     888             :             {
     889           0 :                 GenericColorImageAccessor aSrcAcc( rAlphaMask );
     890           0 :                 maGenericColorBlendAccessor.setColor( aSrcColor );
     891             : 
     892           0 :                 vigra::copyImage( srcIterRange(vigra::Diff2D(),
     893             :                                                aSrcAcc,
     894             :                                                rSrcRect),
     895             :                                   destIter(maBegin,
     896             :                                            maGenericColorBlendAccessor,
     897           0 :                                            rDstPoint) );
     898             :             }
     899     4585866 :             damagedPointSize( rDstPoint, rSrcRect );
     900     2292933 :         }
     901             : 
     902         725 :         virtual void drawMaskedColor_i(Color                        aSrcColor,
     903             :                                        const BitmapDeviceSharedPtr& rAlphaMask,
     904             :                                        const basegfx::B2IBox&       rSrcRect,
     905             :                                        const basegfx::B2IPoint&     rDstPoint,
     906             :                                        const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
     907             :         {
     908         725 :             boost::shared_ptr<mask_bitmap_type>      pMask( getCompatibleClipMask(rAlphaMask) );
     909        1450 :             boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
     910             : 
     911         725 :             if( pAlpha )
     912             :             {
     913         725 :                 const composite_iterator_type aBegin( getMaskedIter(rClip) );
     914         725 :                 maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
     915             :                     aSrcColor );
     916             : 
     917        1450 :                 vigra::copyImage( srcIterRange(pAlpha->maBegin,
     918         725 :                                                pAlpha->maRawAccessor,
     919             :                                                rSrcRect),
     920             :                                   destIter(aBegin,
     921             :                                            maMaskedColorBlendAccessor,
     922        2900 :                                            rDstPoint) );
     923             :             }
     924           0 :             else if( pMask )
     925             :             {
     926           0 :                 boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) );
     927             :                 OSL_ASSERT( pClipMask );
     928             : 
     929             :                 // setup a ((iter,mask),clipMask) composite composite
     930             :                 // iterator, to pass both masks (clip and alpha mask)
     931             :                 // to the algorithm
     932             :                 const composite_composite_mask_iterator_type aBegin(
     933             :                     composite_iterator_type(
     934           0 :                         maBegin + vigra::Diff2D(rDstPoint.getX(),
     935             :                                                 rDstPoint.getY()),
     936           0 :                         pMask->maBegin + topLeft(rSrcRect)),
     937           0 :                     pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(),
     938           0 :                                                        rDstPoint.getY()) );
     939             : 
     940           0 :                 fillImage(aBegin,
     941           0 :                           aBegin + vigra::Diff2D(rSrcRect.getWidth(),
     942           0 :                                                  rSrcRect.getHeight()),
     943             :                           maRawMaskedMaskAccessor,
     944             :                           maColorLookup(
     945             :                               maAccessor,
     946           0 :                               aSrcColor) );
     947             :             }
     948             :             else
     949             :             {
     950           0 :                 GenericColorImageAccessor aSrcAcc( rAlphaMask );
     951           0 :                 const composite_iterator_type aBegin( getMaskedIter(rClip) );
     952           0 :                 maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
     953             :                     aSrcColor );
     954             : 
     955           0 :                 vigra::copyImage( srcIterRange(vigra::Diff2D(),
     956             :                                                aSrcAcc,
     957             :                                                rSrcRect),
     958             :                                   destIter(aBegin,
     959             :                                            maGenericMaskedColorBlendAccessor,
     960           0 :                                            rDstPoint) );
     961             :             }
     962        1450 :             damagedPointSize( rDstPoint, rSrcRect );
     963         725 :         }
     964             : 
     965             :         template< typename Iterator, typename Acc >
     966           8 :         void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
     967             :                                   const BitmapDeviceSharedPtr& rMask,
     968             :                                   const basegfx::B2IBox&       rSrcRect,
     969             :                                   const basegfx::B2IBox&       rDstRect,
     970             :                                   const Iterator&              begin,
     971             :                                   const Acc&                   acc)
     972             :         {
     973           8 :             boost::shared_ptr<BitmapRenderer>   pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
     974          16 :             boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) );
     975             :             OSL_ASSERT( pMask && pSrcBmp );
     976             : 
     977           8 :             scaleImage(
     978             :                 srcIterRange(composite_iterator_type(
     979           8 :                                  pSrcBmp->maBegin,
     980           8 :                                  pMask->maBegin),
     981             :                              joined_image_accessor_type(
     982           8 :                                  pSrcBmp->maAccessor,
     983           8 :                                  pMask->maRawAccessor),
     984             :                              rSrcRect),
     985             :                 destIterRange(begin,
     986             :                               typename masked_input_splitting_accessor<
     987             :                                        Acc,
     988             :                                        joined_image_accessor_type,
     989             :                                        Masks::clipmask_polarity,
     990             :                                        FastMask >::type(acc),
     991          16 :                               rDstRect),
     992          48 :                 isSharedBuffer(rSrcBitmap));
     993          16 :             damaged( rDstRect );
     994           8 :         }
     995             : 
     996             :         template< typename Iterator, typename Acc >
     997       19315 :         void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
     998             :                                          const BitmapDeviceSharedPtr& rMask,
     999             :                                          const basegfx::B2IBox&       rSrcRect,
    1000             :                                          const basegfx::B2IBox&       rDstRect,
    1001             :                                          const Iterator&              begin,
    1002             :                                          const Acc&                   acc)
    1003             :         {
    1004       19315 :             GenericColorImageAccessor aSrcAcc( rSrcBitmap );
    1005       38630 :             GenericColorImageAccessor aMaskAcc( rMask );
    1006             : 
    1007             :             const vigra::Diff2D aTopLeft(rSrcRect.getMinX(),
    1008       19315 :                                          rSrcRect.getMinY());
    1009             :             const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(),
    1010       19315 :                                              rSrcRect.getMaxY());
    1011       19315 :             scaleImage(
    1012             :                 vigra::make_triple(
    1013             :                     generic_composite_iterator_type(
    1014             :                         aTopLeft,aTopLeft),
    1015             :                     generic_composite_iterator_type(
    1016             :                         aBottomRight,aBottomRight),
    1017             :                     joined_generic_image_accessor_type(
    1018             :                         aSrcAcc,
    1019             :                         aMaskAcc)),
    1020             :                 destIterRange(begin,
    1021             :                               typename masked_input_splitting_accessor<
    1022             :                                        Acc,
    1023             :                                        joined_generic_image_accessor_type,
    1024             :                                        Masks::clipmask_polarity,
    1025             :                                        NoFastMask >::type(acc),
    1026       38630 :                               rDstRect));
    1027       38630 :             damaged( rDstRect );
    1028       19315 :         }
    1029             : 
    1030       19321 :         virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
    1031             :                                         const BitmapDeviceSharedPtr& rMask,
    1032             :                                         const basegfx::B2IBox&       rSrcRect,
    1033             :                                         const basegfx::B2IBox&       rDstRect,
    1034             :                                         DrawMode                     drawMode ) SAL_OVERRIDE
    1035             :         {
    1036       19329 :             if( isCompatibleClipMask(rMask) &&
    1037           8 :                 isCompatibleBitmap(rSrcBitmap) )
    1038             :             {
    1039           8 :                 if( drawMode == DrawMode_XOR )
    1040           0 :                     implDrawMaskedBitmap(rSrcBitmap, rMask,
    1041             :                                          rSrcRect, rDstRect,
    1042             :                                          maBegin,
    1043           0 :                                          maXorAccessor);
    1044             :                 else
    1045           8 :                     implDrawMaskedBitmap(rSrcBitmap, rMask,
    1046             :                                          rSrcRect, rDstRect,
    1047             :                                          maBegin,
    1048           8 :                                          maAccessor);
    1049             :             }
    1050             :             else
    1051             :             {
    1052       19313 :                 if( drawMode == DrawMode_XOR )
    1053           0 :                     implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
    1054             :                                                 rSrcRect, rDstRect,
    1055             :                                                 maBegin,
    1056           0 :                                                 maXorAccessor);
    1057             :                 else
    1058       19313 :                     implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
    1059             :                                                 rSrcRect, rDstRect,
    1060             :                                                 maBegin,
    1061       19313 :                                                 maAccessor);
    1062             :             }
    1063       19321 :             damaged( rDstRect );
    1064       19321 :         }
    1065             : 
    1066           2 :         virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
    1067             :                                         const BitmapDeviceSharedPtr& rMask,
    1068             :                                         const basegfx::B2IBox&       rSrcRect,
    1069             :                                         const basegfx::B2IBox&       rDstRect,
    1070             :                                         DrawMode                     drawMode,
    1071             :                                         const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
    1072             :         {
    1073           2 :             if( isCompatibleClipMask(rMask) &&
    1074           0 :                 isCompatibleBitmap(rSrcBitmap) )
    1075             :             {
    1076           0 :                 if( drawMode == DrawMode_XOR )
    1077           0 :                     implDrawMaskedBitmap(rSrcBitmap, rMask,
    1078             :                                          rSrcRect, rDstRect,
    1079             :                                          getMaskedIter(rClip),
    1080           0 :                                          maMaskedXorAccessor);
    1081             :                 else
    1082           0 :                     implDrawMaskedBitmap(rSrcBitmap, rMask,
    1083             :                                          rSrcRect, rDstRect,
    1084             :                                          getMaskedIter(rClip),
    1085           0 :                                          maMaskedAccessor);
    1086             :             }
    1087             :             else
    1088             :             {
    1089           2 :                 if( drawMode == DrawMode_XOR )
    1090           0 :                     implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
    1091             :                                                 rSrcRect, rDstRect,
    1092             :                                                 getMaskedIter(rClip),
    1093           0 :                                                 maMaskedXorAccessor);
    1094             :                 else
    1095           2 :                     implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
    1096             :                                                 rSrcRect, rDstRect,
    1097             :                                                 getMaskedIter(rClip),
    1098           4 :                                                 maMaskedAccessor);
    1099             :             }
    1100           2 :             damaged( rDstRect );
    1101           2 :         }
    1102             : 
    1103     1256252 :         IBitmapDeviceDamageTrackerSharedPtr getDamageTracker_i() const SAL_OVERRIDE
    1104             :         {
    1105     1256252 :             return mpDamage;
    1106             :         }
    1107           0 :         void setDamageTracker_i( const IBitmapDeviceDamageTrackerSharedPtr& rDamage ) SAL_OVERRIDE
    1108             :         {
    1109           0 :             mpDamage = rDamage;
    1110           0 :         }
    1111             :     };
    1112             : } // namespace
    1113             : 
    1114     3637015 : struct ImplBitmapDevice
    1115             : {
    1116             :     /** Bitmap memory plus deleter.
    1117             : 
    1118             :         Always points to the start of the mem
    1119             :      */
    1120             :     RawMemorySharedArray      mpMem;
    1121             : 
    1122             :     /// Palette memory plus deleter (might be NULL)
    1123             :     PaletteMemorySharedVector mpPalette;
    1124             : 
    1125             :     /** Bounds of the device.
    1126             : 
    1127             :         maBounds.getWidth()/getHeight() yield the true size of the
    1128             :         device (i.e. the rectangle given by maBounds covers the device
    1129             :         area under the including-the-bottommost-and-rightmost-pixels
    1130             :         fill rule)
    1131             :      */
    1132             :     basegfx::B2IBox           maBounds;
    1133             : 
    1134             :     //// Size of the actual frame buffer
    1135             :     basegfx::B2IVector        maBufferSize;
    1136             : 
    1137             :     /// Scanline format, as provided at the constructor
    1138             :     Format                    mnScanlineFormat;
    1139             : 
    1140             :     /// Scanline stride. Negative for bottom-to-top formats
    1141             :     sal_Int32                 mnScanlineStride;
    1142             : 
    1143             :     /// raw ptr to 0th scanline. used for cloning a generic renderer
    1144             :     sal_uInt8*                mpFirstScanline;
    1145             : 
    1146             :     /** (Optional) device sharing the same memory, and used for input
    1147             :         clip masks/alpha masks/bitmaps that don't match our exact
    1148             :         bitmap format.
    1149             : 
    1150             :         This is to avoid the combinatorical explosion when dealing
    1151             :         with n bitmap formats, which could be combined with n clip
    1152             :         masks, alpha masks and bitmap masks (yielding a total of n^4
    1153             :         combinations). Since each BitmapRenderer is specialized for
    1154             :         one specific combination of said formats, a lot of duplicate
    1155             :         code would be generated, most of which probably never
    1156             :         used. Therefore, only the most common combinations are
    1157             :         specialized templates, the remainder gets handled by this
    1158             :         generic renderer (via runtime polymorphism).
    1159             :      */
    1160             :     BitmapDeviceSharedPtr     mpGenericRenderer;
    1161             : };
    1162             : 
    1163             : 
    1164     1830472 : BitmapDevice::BitmapDevice( const basegfx::B2IBox&           rBounds,
    1165             :                             const basegfx::B2IVector&        rBufferSize,
    1166             :                             Format                           nScanlineFormat,
    1167             :                             sal_Int32                        nScanlineStride,
    1168             :                             sal_uInt8*                       pFirstScanline,
    1169             :                             const RawMemorySharedArray&      rMem,
    1170             :                             const PaletteMemorySharedVector& rPalette ) :
    1171     1830472 :     mpImpl( new ImplBitmapDevice )
    1172             : {
    1173     1830472 :     mpImpl->mpMem = rMem;
    1174     1830472 :     mpImpl->mpPalette = rPalette;
    1175     1830472 :     mpImpl->maBounds = rBounds;
    1176     1830472 :     mpImpl->maBufferSize = rBufferSize;
    1177     1830472 :     mpImpl->mnScanlineFormat = nScanlineFormat;
    1178     1830472 :     mpImpl->mnScanlineStride = nScanlineStride;
    1179     1830472 :     mpImpl->mpFirstScanline  = pFirstScanline;
    1180     1830472 : }
    1181             : 
    1182     1806543 : BitmapDevice::~BitmapDevice()
    1183             : {
    1184             :     // outline, because of internal ImplBitmapDevice
    1185             :     SAL_INFO( "basebmp.bitmapdevice", "~BitmapDevice(" << this << ")" );
    1186     1806543 : }
    1187             : 
    1188    15537538 : basegfx::B2IVector BitmapDevice::getSize() const
    1189             : {
    1190             :     return basegfx::B2IVector(
    1191    15537538 :         mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(),
    1192    31075076 :         mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() );
    1193             : }
    1194             : 
    1195     3699346 : bool BitmapDevice::isTopDown() const
    1196             : {
    1197     3699346 :     return mpImpl->mnScanlineStride >= 0;
    1198             : }
    1199             : 
    1200     1131112 : basegfx::B2IVector BitmapDevice::getBufferSize() const
    1201             : {
    1202     1131112 :     return mpImpl->maBufferSize;
    1203             : }
    1204             : 
    1205    10442003 : Format BitmapDevice::getScanlineFormat() const
    1206             : {
    1207    10442003 :     return mpImpl->mnScanlineFormat;
    1208             : }
    1209             : 
    1210     2299378 : sal_Int32 BitmapDevice::getScanlineStride() const
    1211             : {
    1212     2299378 :     return mpImpl->mnScanlineStride < 0 ?
    1213     2299378 :         -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride;
    1214             : }
    1215             : 
    1216     8019921 : RawMemorySharedArray BitmapDevice::getBuffer() const
    1217             : {
    1218     8019921 :     return mpImpl->mpMem;
    1219             : }
    1220             : 
    1221     1256252 : IBitmapDeviceDamageTrackerSharedPtr BitmapDevice::getDamageTracker() const
    1222             : {
    1223     1256252 :     return getDamageTracker_i();
    1224             : }
    1225             : 
    1226           0 : void BitmapDevice::setDamageTracker( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
    1227             : {
    1228           0 :     setDamageTracker_i(rDamage);
    1229           0 : }
    1230             : 
    1231     2022779 : PaletteMemorySharedVector BitmapDevice::getPalette() const
    1232             : {
    1233     2022779 :     return mpImpl->mpPalette;
    1234             : }
    1235             : 
    1236     2306668 : bool BitmapDevice::isSharedBuffer( const BitmapDeviceSharedPtr& rOther ) const
    1237             : {
    1238     2306668 :     return rOther.get()->getBuffer().get() == getBuffer().get();
    1239             : }
    1240             : 
    1241         148 : void BitmapDevice::clear( Color fillColor )
    1242             : {
    1243         148 :     clear_i( fillColor, mpImpl->maBounds );
    1244         148 : }
    1245             : 
    1246      782184 : void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
    1247             :                              Color                    lineColor,
    1248             :                              DrawMode                 drawMode )
    1249             : {
    1250      782184 :     if( mpImpl->maBounds.isInside(rPt) )
    1251      768243 :         setPixel_i(rPt,lineColor,drawMode);
    1252      782184 : }
    1253             : 
    1254     1340091 : void BitmapDevice::setPixel( const basegfx::B2IPoint&     rPt,
    1255             :                              Color                        lineColor,
    1256             :                              DrawMode                     drawMode,
    1257             :                              const BitmapDeviceSharedPtr& rClip )
    1258             : {
    1259     1340091 :     if( !rClip )
    1260             :     {
    1261      782124 :         setPixel(rPt,lineColor,drawMode);
    1262     2122215 :         return;
    1263             :     }
    1264             : 
    1265      557967 :     if( mpImpl->maBounds.isInside(rPt) )
    1266             :     {
    1267      557967 :         if( isCompatibleClipMask( rClip ) )
    1268      557967 :             setPixel_i(rPt,lineColor,drawMode,rClip);
    1269             :         else
    1270           0 :             getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip );
    1271             :     }
    1272             : }
    1273             : 
    1274   123542882 : Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt )
    1275             : {
    1276   123542882 :     if( mpImpl->maBounds.isInside(rPt) )
    1277   123542882 :         return getPixel_i(rPt);
    1278             : 
    1279           0 :     return Color();
    1280             : }
    1281             : 
    1282          12 : sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
    1283             : {
    1284          12 :     if( mpImpl->maBounds.isInside(rPt) )
    1285           8 :         return getPixelData_i(rPt);
    1286             : 
    1287           4 :     return 0;
    1288             : }
    1289             : 
    1290     3244323 : void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
    1291             :                              const basegfx::B2IPoint& rPt2,
    1292             :                              Color                    lineColor,
    1293             :                              DrawMode                 drawMode )
    1294             : {
    1295             :     drawLine_i( rPt1,
    1296             :                 rPt2,
    1297     3244323 :                 mpImpl->maBounds,
    1298             :                 lineColor,
    1299     6488646 :                 drawMode );
    1300     3244323 : }
    1301             : 
    1302     3330181 : void BitmapDevice::drawLine( const basegfx::B2IPoint&     rPt1,
    1303             :                              const basegfx::B2IPoint&     rPt2,
    1304             :                              Color                        lineColor,
    1305             :                              DrawMode                     drawMode,
    1306             :                              const BitmapDeviceSharedPtr& rClip )
    1307             : {
    1308     3330181 :     if( !rClip )
    1309             :     {
    1310     3244271 :         drawLine(rPt1,rPt2,lineColor,drawMode);
    1311     6574452 :         return;
    1312             :     }
    1313             : 
    1314       85910 :     if( isCompatibleClipMask( rClip ) )
    1315             :         drawLine_i( rPt1,
    1316             :                     rPt2,
    1317       85910 :                     mpImpl->maBounds,
    1318             :                     lineColor,
    1319             :                     drawMode,
    1320      171820 :                     rClip );
    1321             :     else
    1322             :         getGenericRenderer()->drawLine( rPt1, rPt2, lineColor,
    1323           0 :                                         drawMode, rClip );
    1324             : }
    1325             : 
    1326      261264 : void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
    1327             :                                 Color                      lineColor,
    1328             :                                 DrawMode                   drawMode )
    1329             : {
    1330      261264 :     const sal_uInt32 numVertices( rPoly.count() );
    1331      261264 :     if( numVertices )
    1332             :         drawPolygon_i( rPoly,
    1333      261264 :                        mpImpl->maBounds,
    1334      522528 :                        lineColor, drawMode );
    1335      261264 : }
    1336             : 
    1337      262740 : void BitmapDevice::drawPolygon( const basegfx::B2DPolygon&   rPoly,
    1338             :                                 Color                        lineColor,
    1339             :                                 DrawMode                     drawMode,
    1340             :                                 const BitmapDeviceSharedPtr& rClip )
    1341             : {
    1342      262740 :     if( !rClip )
    1343             :     {
    1344      261230 :         drawPolygon(rPoly,lineColor,drawMode);
    1345      523970 :         return;
    1346             :     }
    1347             : 
    1348        1510 :     const sal_uInt32 numVertices( rPoly.count() );
    1349        1510 :     if( numVertices )
    1350             :     {
    1351        1510 :         if( isCompatibleClipMask( rClip ) )
    1352             :             drawPolygon_i( rPoly,
    1353        1510 :                            mpImpl->maBounds,
    1354        3020 :                            lineColor, drawMode, rClip );
    1355             :         else
    1356             :             getGenericRenderer()->drawPolygon( rPoly, lineColor,
    1357           0 :                                                drawMode, rClip );
    1358             :     }
    1359             : }
    1360             : 
    1361     4594481 : void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
    1362             :                                     Color                          fillColor,
    1363             :                                     DrawMode                       drawMode )
    1364             : {
    1365     4594481 :     fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
    1366     4594481 : }
    1367             : 
    1368     4549114 : void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
    1369             :                                     Color                          fillColor,
    1370             :                                     DrawMode                       drawMode,
    1371             :                                     const BitmapDeviceSharedPtr&   rClip )
    1372             : {
    1373     4549114 :     if( !rClip )
    1374             :     {
    1375     4487678 :         fillPolyPolygon(rPoly,fillColor,drawMode);
    1376     9036792 :         return;
    1377             :     }
    1378             : 
    1379       61436 :     if( isCompatibleClipMask( rClip ) )
    1380       61436 :         fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
    1381             :     else
    1382             :         getGenericRenderer()->fillPolyPolygon( rPoly, fillColor,
    1383           0 :                                                drawMode, rClip );
    1384             : }
    1385             : 
    1386             : 
    1387             : namespace
    1388             : {
    1389     2293658 :     void assertImagePoint( const basegfx::B2IPoint& rPt,
    1390             :                            const basegfx::B2IBox&   rPermittedRange )
    1391             :     {
    1392             :         (void)rPt; (void)rPermittedRange;
    1393             :         OSL_ASSERT( rPermittedRange.isInside(rPt) );
    1394     2293658 :     }
    1395             : 
    1396     3497092 :     void assertImageRange( const basegfx::B2IBox& rRange,
    1397             :                            const basegfx::B2IBox& rPermittedRange )
    1398             :     {
    1399             : #if OSL_DEBUG_LEVEL > 0
    1400             :         basegfx::B2IBox aRange( rRange );
    1401             :         aRange.intersect( rPermittedRange );
    1402             : 
    1403             :         OSL_ASSERT( aRange == rRange );
    1404             : #else
    1405             :         (void)rRange; (void)rPermittedRange;
    1406             : #endif
    1407     3497092 :     }
    1408             : 
    1409             :     // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
    1410             :     // to basegfx, and use here!
    1411     3274133 :     bool clipAreaImpl( ::basegfx::B2IBox&       io_rSourceArea,
    1412             :                        ::basegfx::B2IPoint&     io_rDestPoint,
    1413             :                        const ::basegfx::B2IBox& rSourceBounds,
    1414             :                        const ::basegfx::B2IBox& rDestBounds )
    1415             :     {
    1416             :         const ::basegfx::B2IPoint aSourceTopLeft(
    1417     3274133 :             io_rSourceArea.getMinimum() );
    1418             : 
    1419     3274133 :         ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
    1420             : 
    1421             :         // clip source area (which must be inside rSourceBounds)
    1422     3274133 :         aLocalSourceArea.intersect( rSourceBounds );
    1423             : 
    1424     3274133 :         if( aLocalSourceArea.isEmpty() )
    1425           0 :             return false;
    1426             : 
    1427             :         // calc relative new source area points (relative to orig
    1428             :         // source area)
    1429             :         const ::basegfx::B2IVector aUpperLeftOffset(
    1430     6548266 :             aLocalSourceArea.getMinimum()-aSourceTopLeft );
    1431             :         const ::basegfx::B2IVector aLowerRightOffset(
    1432     6548266 :             aLocalSourceArea.getMaximum()-aSourceTopLeft );
    1433             : 
    1434     6548266 :         ::basegfx::B2IBox aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
    1435     9822399 :                                           io_rDestPoint + aLowerRightOffset );
    1436             : 
    1437             :         // clip dest area (which must be inside rDestBounds)
    1438     3274133 :         aLocalDestArea.intersect( rDestBounds );
    1439             : 
    1440     3274133 :         if( aLocalDestArea.isEmpty() )
    1441      980475 :             return false;
    1442             : 
    1443             :         // calc relative new dest area points (relative to orig
    1444             :         // source area)
    1445             :         const ::basegfx::B2IVector aDestUpperLeftOffset(
    1446     4587316 :             aLocalDestArea.getMinimum()-io_rDestPoint );
    1447             :         const ::basegfx::B2IVector aDestLowerRightOffset(
    1448     4587316 :             aLocalDestArea.getMaximum()-io_rDestPoint );
    1449             : 
    1450     4587316 :         io_rSourceArea = ::basegfx::B2IBox( aSourceTopLeft + aDestUpperLeftOffset,
    1451     6880974 :                                             aSourceTopLeft + aDestLowerRightOffset );
    1452     2293658 :         io_rDestPoint  = aLocalDestArea.getMinimum();
    1453             : 
    1454     5567791 :         return true;
    1455             :     }
    1456             : 
    1457             :     // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
    1458             :     // to basegfx, and use here!
    1459      602696 :     bool clipAreaImpl( ::basegfx::B2IBox&       io_rDestArea,
    1460             :                        ::basegfx::B2IBox&       io_rSourceArea,
    1461             :                        const ::basegfx::B2IBox& rDestBounds,
    1462             :                        const ::basegfx::B2IBox& rSourceBounds )
    1463             :     {
    1464             :         // extract inherent scale
    1465      602696 :         double fWidth = io_rSourceArea.getWidth();
    1466      602696 :         if (fWidth == 0.0)
    1467           0 :             return false;
    1468             : 
    1469      602696 :         double fHeight = io_rSourceArea.getHeight();
    1470      602696 :         if (fHeight == 0.0)
    1471           0 :             return false;
    1472             : 
    1473      602696 :         const double nScaleX( io_rDestArea.getWidth() / fWidth );
    1474      602696 :         const double nScaleY( io_rDestArea.getHeight() / fHeight );
    1475             : 
    1476             :         // extract range origins
    1477             :         const basegfx::B2IPoint   aDestTopLeft(
    1478      602696 :             io_rDestArea.getMinimum() );
    1479             :         const ::basegfx::B2IPoint aSourceTopLeft(
    1480     1205392 :             io_rSourceArea.getMinimum() );
    1481             : 
    1482      602696 :         ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
    1483             : 
    1484             :         // clip source area (which must be inside rSourceBounds)
    1485      602696 :         aLocalSourceArea.intersect( rSourceBounds );
    1486             : 
    1487      602696 :         if( aLocalSourceArea.isEmpty() )
    1488          16 :             return false;
    1489             : 
    1490             :         // calc relative new source area points (relative to orig
    1491             :         // source area)
    1492             :         const ::basegfx::B2IVector aUpperLeftOffset(
    1493     1205360 :             aLocalSourceArea.getMinimum()-aSourceTopLeft );
    1494             :         const ::basegfx::B2IVector aLowerRightOffset(
    1495     1205360 :             aLocalSourceArea.getMaximum()-aSourceTopLeft );
    1496             : 
    1497     1205360 :         ::basegfx::B2IBox aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
    1498     1205360 :                                           basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
    1499     1205360 :                                           basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
    1500     4218760 :                                           basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
    1501             : 
    1502             :         // clip dest area (which must be inside rDestBounds)
    1503      602680 :         aLocalDestArea.intersect( rDestBounds );
    1504             : 
    1505      602680 :         if( aLocalDestArea.isEmpty() )
    1506         963 :             return false;
    1507             : 
    1508             :         // calc relative new dest area points (relative to orig
    1509             :         // source area)
    1510             :         const ::basegfx::B2IVector aDestUpperLeftOffset(
    1511     1203434 :             aLocalDestArea.getMinimum()-aDestTopLeft );
    1512             :         const ::basegfx::B2IVector aDestLowerRightOffset(
    1513     1203434 :             aLocalDestArea.getMaximum()-aDestTopLeft );
    1514             : 
    1515     1203434 :         io_rSourceArea = ::basegfx::B2IBox( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
    1516     1203434 :                                             basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
    1517     1203434 :                                             basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
    1518     4212019 :                                             basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
    1519      601717 :         io_rDestArea   = aLocalDestArea;
    1520             : 
    1521             :         // final source area clip (chopping round-offs)
    1522      601717 :         io_rSourceArea.intersect( rSourceBounds );
    1523             : 
    1524      601717 :         if( io_rSourceArea.isEmpty() )
    1525           0 :             return false;
    1526             : 
    1527             : 
    1528     1204413 :         return true;
    1529             :     }
    1530             : }
    1531             : 
    1532      581334 : void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
    1533             :                                const basegfx::B2IBox&       rSrcRect,
    1534             :                                const basegfx::B2IBox&       rDstRect,
    1535             :                                DrawMode                     drawMode )
    1536             : {
    1537      581334 :     const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
    1538      581334 :     const basegfx::B2IBox     aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    1539      581334 :     basegfx::B2IBox           aSrcRange( rSrcRect );
    1540      581334 :     basegfx::B2IBox           aDestRange( rDstRect );
    1541             : 
    1542      581334 :     if( clipAreaImpl( aDestRange,
    1543             :                       aSrcRange,
    1544      581334 :                       mpImpl->maBounds,
    1545      581334 :                       aSrcBounds ))
    1546             :     {
    1547      580355 :         assertImageRange(aDestRange,mpImpl->maBounds);
    1548      580355 :         assertImageRange(aSrcRange,aSrcBounds);
    1549             : 
    1550      580355 :         drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode );
    1551      581334 :     }
    1552      581334 : }
    1553             : 
    1554      304985 : void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
    1555             :                                const basegfx::B2IBox&       rSrcRect,
    1556             :                                const basegfx::B2IBox&       rDstRect,
    1557             :                                DrawMode                     drawMode,
    1558             :                                const BitmapDeviceSharedPtr& rClip )
    1559             : {
    1560      304985 :     if( !rClip )
    1561             :     {
    1562      302946 :         drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
    1563      607931 :         return;
    1564             :     }
    1565             : 
    1566        2039 :     const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
    1567        2039 :     const basegfx::B2IBox     aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    1568        2039 :     basegfx::B2IBox           aSrcRange( rSrcRect );
    1569        2039 :     basegfx::B2IBox           aDestRange( rDstRect );
    1570             : 
    1571        2039 :     if( clipAreaImpl( aDestRange,
    1572             :                       aSrcRange,
    1573        2039 :                       mpImpl->maBounds,
    1574        2039 :                       aSrcBounds ))
    1575             :     {
    1576        2039 :         assertImageRange(aDestRange,mpImpl->maBounds);
    1577        2039 :         assertImageRange(aSrcRange,aSrcBounds);
    1578             : 
    1579        2039 :         if( isCompatibleClipMask( rClip ) )
    1580             :         {
    1581        2039 :             drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip );
    1582             :         }
    1583             :         else
    1584             :         {
    1585             :             getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect,
    1586           0 :                                               rDstRect, drawMode, rClip );
    1587             :         }
    1588        2039 :     }
    1589             : }
    1590             : 
    1591     3273336 : void BitmapDevice::drawMaskedColor( Color                        aSrcColor,
    1592             :                                     const BitmapDeviceSharedPtr& rAlphaMask,
    1593             :                                     const basegfx::B2IBox&       rSrcRect,
    1594             :                                     const basegfx::B2IPoint&     rDstPoint )
    1595             : {
    1596     3273336 :     const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
    1597     3273336 :     const basegfx::B2IBox     aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    1598     3273336 :     basegfx::B2IBox           aSrcRange( rSrcRect );
    1599     6546672 :     basegfx::B2IPoint         aDestPoint( rDstPoint );
    1600             : 
    1601     3273336 :     if( clipAreaImpl( aSrcRange,
    1602             :                       aDestPoint,
    1603             :                       aSrcBounds,
    1604     3273336 :                       mpImpl->maBounds ))
    1605             :     {
    1606     2292933 :         assertImagePoint(aDestPoint,mpImpl->maBounds);
    1607     2292933 :         assertImageRange(aSrcRange,aSrcBounds);
    1608             : 
    1609     2292933 :         if( isSharedBuffer(rAlphaMask) )
    1610             :         {
    1611             :             // src == dest, copy rAlphaMask beforehand
    1612             : 
    1613             : 
    1614           0 :             const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
    1615           0 :                                            aSrcRange.getHeight() );
    1616             :             BitmapDeviceSharedPtr pAlphaCopy(
    1617             :                 cloneBitmapDevice( aSize,
    1618           0 :                                    shared_from_this()) );
    1619             :             const basegfx::B2IBox aAlphaRange( basegfx::B2ITuple(),
    1620           0 :                                                aSize );
    1621             :             pAlphaCopy->drawBitmap(rAlphaMask,
    1622             :                                    aSrcRange,
    1623             :                                    aAlphaRange,
    1624           0 :                                    DrawMode_PAINT);
    1625           0 :             drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint );
    1626             :         }
    1627             :         else
    1628             :         {
    1629     2292933 :             drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint );
    1630             :         }
    1631     3273336 :     }
    1632     3273336 : }
    1633             : 
    1634     3274117 : void BitmapDevice::drawMaskedColor( Color                        aSrcColor,
    1635             :                                     const BitmapDeviceSharedPtr& rAlphaMask,
    1636             :                                     const basegfx::B2IBox&       rSrcRect,
    1637             :                                     const basegfx::B2IPoint&     rDstPoint,
    1638             :                                     const BitmapDeviceSharedPtr& rClip )
    1639             : {
    1640     3274117 :     if( !rClip )
    1641             :     {
    1642     3273320 :         drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
    1643     6547437 :         return;
    1644             :     }
    1645             : 
    1646         797 :     const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
    1647         797 :     const basegfx::B2IBox     aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    1648         797 :     basegfx::B2IBox           aSrcRange( rSrcRect );
    1649        1594 :     basegfx::B2IPoint         aDestPoint( rDstPoint );
    1650             : 
    1651         797 :     if( clipAreaImpl( aSrcRange,
    1652             :                       aDestPoint,
    1653             :                       aSrcBounds,
    1654         797 :                       mpImpl->maBounds ))
    1655             :     {
    1656         725 :         assertImagePoint(aDestPoint,mpImpl->maBounds);
    1657         725 :         assertImageRange(aSrcRange,aSrcBounds);
    1658             : 
    1659         725 :         if( isCompatibleClipMask( rClip ) )
    1660             :         {
    1661         725 :             if( isSharedBuffer(rAlphaMask) )
    1662             :             {
    1663             :                 // src == dest, copy rAlphaMask beforehand
    1664             : 
    1665             : 
    1666           0 :                 const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
    1667           0 :                                                aSrcRange.getHeight() );
    1668             :                 BitmapDeviceSharedPtr pAlphaCopy(
    1669             :                     cloneBitmapDevice( aSize,
    1670           0 :                                        shared_from_this()) );
    1671             :                 const basegfx::B2IBox aAlphaRange( basegfx::B2ITuple(),
    1672           0 :                                                    aSize );
    1673             :                 pAlphaCopy->drawBitmap(rAlphaMask,
    1674             :                                        aSrcRange,
    1675             :                                        aAlphaRange,
    1676           0 :                                        DrawMode_PAINT);
    1677           0 :                 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip );
    1678             :             }
    1679             :             else
    1680             :             {
    1681         725 :                 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
    1682             :             }
    1683             :         }
    1684             :         else
    1685             :         {
    1686             :             getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask,
    1687           0 :                                                    rSrcRect, rDstPoint, rClip );
    1688             :         }
    1689         797 :     }
    1690             : }
    1691             : 
    1692       19321 : void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
    1693             :                                      const BitmapDeviceSharedPtr& rMask,
    1694             :                                      const basegfx::B2IBox&       rSrcRect,
    1695             :                                      const basegfx::B2IBox&       rDstRect,
    1696             :                                      DrawMode                     drawMode )
    1697             : {
    1698             :     OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
    1699             : 
    1700       19321 :     const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
    1701       19321 :     const basegfx::B2IBox     aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    1702       19321 :     basegfx::B2IBox           aSrcRange( rSrcRect );
    1703       19321 :     basegfx::B2IBox           aDestRange( rDstRect );
    1704             : 
    1705       19321 :     if( clipAreaImpl( aDestRange,
    1706             :                       aSrcRange,
    1707       19321 :                       mpImpl->maBounds,
    1708       19321 :                       aSrcBounds ))
    1709             :     {
    1710       19321 :         assertImageRange(aDestRange,mpImpl->maBounds);
    1711       19321 :         assertImageRange(aSrcRange,aSrcBounds);
    1712             : 
    1713       19321 :         drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode );
    1714       19321 :     }
    1715       19321 : }
    1716             : 
    1717       19315 : void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
    1718             :                                      const BitmapDeviceSharedPtr& rMask,
    1719             :                                      const basegfx::B2IBox&       rSrcRect,
    1720             :                                      const basegfx::B2IBox&       rDstRect,
    1721             :                                      DrawMode                     drawMode,
    1722             :                                      const BitmapDeviceSharedPtr& rClip )
    1723             : {
    1724       19315 :     if( !rClip )
    1725             :     {
    1726       19313 :         drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
    1727       38628 :         return;
    1728             :     }
    1729             : 
    1730             :     OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
    1731             : 
    1732           2 :     const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
    1733           2 :     const basegfx::B2IBox     aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    1734           2 :     basegfx::B2IBox           aSrcRange( rSrcRect );
    1735           2 :     basegfx::B2IBox           aDestRange( rDstRect );
    1736             : 
    1737           2 :     if( clipAreaImpl( aDestRange,
    1738             :                       aSrcRange,
    1739           2 :                       mpImpl->maBounds,
    1740           2 :                       aSrcBounds ))
    1741             :     {
    1742           2 :         assertImageRange(aDestRange,mpImpl->maBounds);
    1743           2 :         assertImageRange(aSrcRange,aSrcBounds);
    1744             : 
    1745           2 :         if( isCompatibleClipMask( rClip ) )
    1746             :         {
    1747           2 :             drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip );
    1748             :         }
    1749             :         else
    1750             :         {
    1751             :             getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect,
    1752           0 :                                                     rDstRect, drawMode, rClip );
    1753             :         }
    1754           2 :     }
    1755             : }
    1756             : 
    1757             : 
    1758             : 
    1759             : /** Standard clip and alpha masks
    1760             :  */
    1761             : struct StdMasks
    1762             : {
    1763             :     typedef PixelFormatTraits_GREY1_MSB   clipmask_format_traits;
    1764             :     typedef PixelFormatTraits_GREY8       alphamask_format_traits;
    1765             : 
    1766             :     /// Clipmask: 0 means opaque
    1767             :     static const bool clipmask_polarity  = false;
    1768             : 
    1769             :     /// Alpha mask: 0 means fully transparent
    1770             :     static const bool alphamask_polarity = true;
    1771             : };
    1772             : 
    1773             : 
    1774             : // Some compilers don't like the nested template wrap_accessor
    1775             : // reference in the parameter list - being slightly less type safe,
    1776             : // then.
    1777             : #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
    1778             : 
    1779             : /// Produces a specialized renderer for the given pixel format
    1780             : template< class FormatTraits, class MaskTraits >
    1781     1830472 : BitmapDeviceSharedPtr createRenderer(
    1782             :     const basegfx::B2IBox&                                       rBounds,
    1783             :     const basegfx::B2IVector&                                    rBufferSize,
    1784             :     Format                                                       nScanlineFormat,
    1785             :     sal_Int32                                                    nScanlineStride,
    1786             :     sal_uInt8*                                                   pFirstScanline,
    1787             :     typename FormatTraits::raw_accessor_type const&              rRawAccessor,
    1788             :     typename FormatTraits::accessor_selector::template wrap_accessor<
    1789             :           typename FormatTraits::raw_accessor_type>::type const& rAccessor,
    1790             :     boost::shared_array< sal_uInt8 >                             pMem,
    1791             :     const PaletteMemorySharedVector&                             pPal,
    1792             :     const IBitmapDeviceDamageTrackerSharedPtr&                   pDamage )
    1793             : #else
    1794             : 
    1795             : template< class FormatTraits, class MaskTraits, class Accessor >
    1796             : BitmapDeviceSharedPtr createRenderer(
    1797             :     const basegfx::B2IBox&                                       rBounds,
    1798             :     const basegfx::B2IVector&                                    rBufferSize,
    1799             :     Format                                                       nScanlineFormat,
    1800             :     sal_Int32                                                    nScanlineStride,
    1801             :     sal_uInt8*                                                   pFirstScanline,
    1802             :     typename FormatTraits::raw_accessor_type const&              rRawAccessor,
    1803             :     Accessor const&                                              rAccessor,
    1804             :     boost::shared_array< sal_uInt8 >                             pMem,
    1805             :     const PaletteMemorySharedVector&                             pPal,
    1806             :     const IBitmapDeviceDamageTrackerSharedPtr&                   pDamage )
    1807             : 
    1808             : #endif
    1809             : {
    1810             :     typedef typename FormatTraits::iterator_type                Iterator;
    1811             :     typedef BitmapRenderer< Iterator,
    1812             :                             typename FormatTraits::raw_accessor_type,
    1813             :                             typename FormatTraits::accessor_selector,
    1814             :                             MaskTraits >                        Renderer;
    1815             : 
    1816             :     return BitmapDeviceSharedPtr(
    1817             :         new Renderer( rBounds,
    1818             :                       rBufferSize,
    1819             :                       nScanlineFormat,
    1820             :                       nScanlineStride,
    1821             :                       pFirstScanline,
    1822             :                       Iterator(
    1823             :                           reinterpret_cast<typename Iterator::value_type*>(
    1824             :                               pFirstScanline),
    1825             :                           nScanlineStride),
    1826             :                       rRawAccessor,
    1827             :                       rAccessor,
    1828             :                       pMem,
    1829             :                       pPal,
    1830     1830472 :                       pDamage ));
    1831             : }
    1832             : 
    1833             : /// Create standard grey level palette
    1834      294322 : PaletteMemorySharedVector createStandardPalette(
    1835             :     const PaletteMemorySharedVector& pPal,
    1836             :     sal_Int32                        nNumEntries )
    1837             : {
    1838      294322 :     if( pPal || nNumEntries <= 0 )
    1839      294250 :         return pPal;
    1840             : 
    1841             :     boost::shared_ptr< std::vector<Color> > pLocalPal(
    1842          72 :         new std::vector<Color>(nNumEntries) );
    1843             : 
    1844          72 :     const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries );
    1845          72 :     --nNumEntries;
    1846         144 :     for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement )
    1847          72 :         pLocalPal->at(i) = Color(0xFF000000 | c);
    1848             : 
    1849          72 :     pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF);
    1850             : 
    1851          72 :     return pLocalPal;
    1852             : }
    1853             : 
    1854             : template< class FormatTraits, class MaskTraits >
    1855     1536150 : BitmapDeviceSharedPtr createRenderer(
    1856             :     const basegfx::B2IBox&                     rBounds,
    1857             :     const basegfx::B2IVector&                  rBufferSize,
    1858             :     Format                                     nScanlineFormat,
    1859             :     sal_Int32                                  nScanlineStride,
    1860             :     sal_uInt8*                                 pFirstScanline,
    1861             :     boost::shared_array< sal_uInt8 >           pMem,
    1862             :     const PaletteMemorySharedVector&           pPal,
    1863             :     const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
    1864             : {
    1865             :     return createRenderer<FormatTraits,
    1866             :                           MaskTraits>(rBounds,
    1867             :                                       rBufferSize,
    1868             :                                       nScanlineFormat,
    1869             :                                       nScanlineStride,
    1870             :                                       pFirstScanline,
    1871             :                                       typename FormatTraits::raw_accessor_type(),
    1872             :                                       typename FormatTraits::accessor_selector::template
    1873             :                                       wrap_accessor<
    1874             :                                           typename FormatTraits::raw_accessor_type>::type(),
    1875             :                                       pMem,
    1876             :                                       pPal,
    1877     1536150 :                                       pDamage);
    1878             : }
    1879             : 
    1880             : template< class FormatTraits, class MaskTraits >
    1881      294322 : BitmapDeviceSharedPtr createRenderer(
    1882             :     const basegfx::B2IBox&                     rBounds,
    1883             :     const basegfx::B2IVector&                  rBufferSize,
    1884             :     Format                                     nScanlineFormat,
    1885             :     sal_Int32                                  nScanlineStride,
    1886             :     sal_uInt8*                                 pFirstScanline,
    1887             :     boost::shared_array< sal_uInt8 >           pMem,
    1888             :     PaletteMemorySharedVector                  pPal,
    1889             :     int                                        nBitsPerPixel,
    1890             :     const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
    1891             : {
    1892      294322 :     pPal = createStandardPalette(pPal,
    1893             :                                  1UL << nBitsPerPixel);
    1894             : 
    1895             :     OSL_ASSERT(pPal);
    1896             :     return createRenderer<FormatTraits,
    1897             :                           MaskTraits>(rBounds,
    1898             :                                       rBufferSize,
    1899             :                                       nScanlineFormat,
    1900             :                                       nScanlineStride,
    1901             :                                       pFirstScanline,
    1902             :                                       typename FormatTraits::raw_accessor_type(),
    1903             :                                       typename FormatTraits::accessor_selector::template
    1904             :                                           wrap_accessor<
    1905             :                                       typename FormatTraits::raw_accessor_type>::type(
    1906      294322 :                                           &pPal->at(0),
    1907             :                                           pPal->size()),
    1908             :                                       pMem,
    1909             :                                       pPal,
    1910      588644 :                                       pDamage);
    1911             : }
    1912             : 
    1913             : 
    1914             : // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
    1915             : // to o3tl or sal/bithacks.hxx ...
    1916             : 
    1917             : /** Compute the next highest power of 2 of a 32-bit value
    1918             : 
    1919             :     Code devised by Sean Anderson, in good ole HAKMEM
    1920             :     tradition.
    1921             : 
    1922             :     @return 1 << (lg(x - 1) + 1)
    1923             : */
    1924     1830478 : inline sal_uInt32 nextPow2( sal_uInt32 x )
    1925             : {
    1926     1830478 :     --x;
    1927     1830478 :     x |= x >> 1;
    1928     1830478 :     x |= x >> 2;
    1929     1830478 :     x |= x >> 4;
    1930     1830478 :     x |= x >> 8;
    1931     1830478 :     x |= x >> 16;
    1932             : 
    1933     1830478 :     return ++x;
    1934             : }
    1935             : 
    1936             : 
    1937             : 
    1938             : 
    1939             : namespace
    1940             : {
    1941     1830478 : BitmapDeviceSharedPtr createBitmapDeviceImplInner( const basegfx::B2IVector&                  rSize,
    1942             :                                                    bool                                       bTopDown,
    1943             :                                                    Format                                     nScanlineFormat,
    1944             :                                                    boost::shared_array< sal_uInt8 >           pMem,
    1945             :                                                    PaletteMemorySharedVector                  pPal,
    1946             :                                                    const basegfx::B2IBox*                     pSubset,
    1947             :                                                    const IBitmapDeviceDamageTrackerSharedPtr& rDamage,
    1948             :                                                    bool bBlack = true)
    1949             : {
    1950             :     OSL_ASSERT(rSize.getX() > 0 && rSize.getY() > 0);
    1951             : 
    1952     3660956 :     if( nScanlineFormat <= FORMAT_NONE ||
    1953     1830478 :         nScanlineFormat >  FORMAT_MAX )
    1954           0 :         return BitmapDeviceSharedPtr();
    1955             : 
    1956     1830478 :     sal_uInt8 nBitsPerPixel = bitsPerPixel[nScanlineFormat];
    1957     1830478 :     if (rSize.getX() > (SAL_MAX_INT32-7) / nBitsPerPixel)
    1958             :     {
    1959             :         SAL_WARN("basebmp", "suspicious bitmap width " <<
    1960             :                  rSize.getX() << " for depth " << nBitsPerPixel);
    1961           0 :         return BitmapDeviceSharedPtr();
    1962             :     }
    1963             :     // round up to full 8 bit, divide by 8
    1964     1830478 :     sal_Int32 nScanlineStride = (rSize.getX()*nBitsPerPixel + 7) >> 3;
    1965             : 
    1966             :     // rounded up to next full power-of-two number of bytes
    1967             :     const sal_uInt32 bytesPerPixel = nextPow2(
    1968     1830478 :         (bitsPerPixel[nScanlineFormat] + 7) >> 3);
    1969             : 
    1970             :     // now make nScanlineStride a multiple of bytesPerPixel
    1971     1830478 :     nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel;
    1972             : 
    1973             :     // factor in bottom-up scanline order case
    1974     1830478 :     nScanlineStride *= bTopDown ? 1 : -1;
    1975             : 
    1976     1830478 :     const sal_uInt32 nWidth(nScanlineStride < 0 ? -nScanlineStride : nScanlineStride);
    1977     1830478 :     const sal_uInt32 nHeight(rSize.getY());
    1978             : 
    1979     1830478 :     if (nHeight && nWidth && nWidth > SAL_MAX_INT32 / nHeight)
    1980             :     {
    1981             :         SAL_WARN( "basebmp", "suspicious massive alloc " << nWidth << " * " << nHeight);
    1982           6 :         return BitmapDeviceSharedPtr();
    1983             :     }
    1984             : 
    1985     1830472 :     const std::size_t nMemSize(nWidth * nHeight);
    1986             : 
    1987     1830472 :     if( !pMem )
    1988             :     {
    1989             :         pMem.reset(
    1990      700879 :             reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
    1991      700879 :             &rtl_freeMemory );
    1992      700879 :         if (pMem.get() == 0 && nMemSize != 0)
    1993           0 :             return BitmapDeviceSharedPtr();
    1994      700879 :         if (bBlack)
    1995      672864 :             memset(pMem.get(), 0, nMemSize);
    1996             :         else
    1997       28015 :             memset(pMem.get(), 0xFF, nMemSize);
    1998             :     }
    1999             : 
    2000             :     sal_uInt8* pFirstScanline = nScanlineStride < 0 ?
    2001     1830472 :         pMem.get() + nMemSize + nScanlineStride : pMem.get();
    2002             : 
    2003             :     // shrink render area to given subset, if given
    2004     1830472 :     basegfx::B2IBox aBounds(0,0,rSize.getX(),rSize.getY());
    2005     1830472 :     if( pSubset )
    2006      963481 :         aBounds.intersect( *pSubset );
    2007             : 
    2008     1830472 :     switch( nScanlineFormat )
    2009             :     {
    2010             : 
    2011             :         // one bit formats
    2012             : 
    2013             :         case FORMAT_ONE_BIT_MSB_GREY:
    2014             :             return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>(
    2015             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2016       28029 :                 pFirstScanline, pMem, pPal, rDamage );
    2017             : 
    2018             :         case FORMAT_ONE_BIT_LSB_GREY:
    2019             :             return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>(
    2020             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2021           0 :                 pFirstScanline, pMem, pPal, rDamage );
    2022             : 
    2023             :         case FORMAT_ONE_BIT_MSB_PAL:
    2024             :             return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>(
    2025             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2026             :                 pFirstScanline, pMem, pPal,
    2027       35598 :                 bitsPerPixel[nScanlineFormat], rDamage );
    2028             : 
    2029             :         case FORMAT_ONE_BIT_LSB_PAL:
    2030             :             return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>(
    2031             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2032             :                 pFirstScanline, pMem, pPal,
    2033           2 :                 bitsPerPixel[nScanlineFormat], rDamage );
    2034             : 
    2035             : 
    2036             : 
    2037             :         // four bit formats
    2038             : 
    2039             :         case FORMAT_FOUR_BIT_MSB_GREY:
    2040             :             return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>(
    2041             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2042           0 :                 pFirstScanline, pMem, pPal, rDamage );
    2043             : 
    2044             :         case FORMAT_FOUR_BIT_LSB_GREY:
    2045             :             return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>(
    2046             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2047           0 :                 pFirstScanline, pMem, pPal, rDamage );
    2048             : 
    2049             :         case FORMAT_FOUR_BIT_MSB_PAL:
    2050             :             return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>(
    2051             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2052             :                 pFirstScanline, pMem, pPal,
    2053         526 :                 bitsPerPixel[nScanlineFormat], rDamage );
    2054             : 
    2055             :         case FORMAT_FOUR_BIT_LSB_PAL:
    2056             :             return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>(
    2057             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2058             :                 pFirstScanline, pMem, pPal,
    2059           0 :                 bitsPerPixel[nScanlineFormat], rDamage );
    2060             : 
    2061             : 
    2062             : 
    2063             :         // eight bit formats
    2064             : 
    2065             :         case FORMAT_EIGHT_BIT_GREY:
    2066             :             return createRenderer<PixelFormatTraits_GREY8,StdMasks>(
    2067             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2068       22406 :                 pFirstScanline, pMem, pPal, rDamage );
    2069             : 
    2070             :         case FORMAT_EIGHT_BIT_PAL:
    2071             :             return createRenderer<PixelFormatTraits_PAL8,StdMasks>(
    2072             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2073             :                 pFirstScanline, pMem, pPal,
    2074      258196 :                 bitsPerPixel[nScanlineFormat], rDamage );
    2075             : 
    2076             : 
    2077             : 
    2078             :         // sixteen bit formats
    2079             : 
    2080             :         case FORMAT_SIXTEEN_BIT_LSB_TC_MASK:
    2081             :             return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>(
    2082             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2083           4 :                 pFirstScanline, pMem, pPal, rDamage );
    2084             : 
    2085             :         case FORMAT_SIXTEEN_BIT_MSB_TC_MASK:
    2086             :             return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>(
    2087             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2088           0 :                 pFirstScanline, pMem, pPal, rDamage );
    2089             : 
    2090             : 
    2091             : 
    2092             :         // twentyfour bit formats
    2093             :         case FORMAT_TWENTYFOUR_BIT_TC_MASK:
    2094             :             return createRenderer<PixelFormatTraits_BGR24,StdMasks>(
    2095             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2096     1485639 :                 pFirstScanline, pMem, pPal, rDamage );
    2097             : 
    2098             : 
    2099             : 
    2100             :         // thirtytwo bit formats
    2101             : 
    2102             :         case FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA:
    2103             :             return createRenderer<PixelFormatTraits_BGRX32_8888,StdMasks>(
    2104             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2105          72 :                 pFirstScanline, pMem, pPal, rDamage );
    2106             : 
    2107             :         case FORMAT_THIRTYTWO_BIT_TC_MASK_ARGB:
    2108             :             return createRenderer<PixelFormatTraits_XRGB32_8888,StdMasks>(
    2109             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2110           0 :                 pFirstScanline, pMem, pPal, rDamage );
    2111             : 
    2112             :         case FORMAT_THIRTYTWO_BIT_TC_MASK_ABGR:
    2113             :             return createRenderer<PixelFormatTraits_XBGR32_8888,StdMasks>(
    2114             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2115           0 :                 pFirstScanline, pMem, pPal, rDamage );
    2116             : 
    2117             :         case FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA:
    2118             :             return createRenderer<PixelFormatTraits_RGBX32_8888,StdMasks>(
    2119             :                 aBounds, rSize, nScanlineFormat, nScanlineStride,
    2120           0 :                 pFirstScanline, pMem, pPal, rDamage );
    2121             : 
    2122             :         default:
    2123             :             assert(false); // this cannot happen
    2124             :     }
    2125             : 
    2126             :     // TODO(F3): other formats not yet implemented
    2127           0 :     return BitmapDeviceSharedPtr();
    2128             : }
    2129             : 
    2130     1830478 : BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector&                  rSize,
    2131             :                                               bool                                       bTopDown,
    2132             :                                               Format                                     nScanlineFormat,
    2133             :                                               boost::shared_array< sal_uInt8 >           pMem,
    2134             :                                               PaletteMemorySharedVector                  pPal,
    2135             :                                               const basegfx::B2IBox*                     pSubset,
    2136             :                                               const IBitmapDeviceDamageTrackerSharedPtr& rDamage,
    2137             :                                               bool bBlack = true)
    2138             : {
    2139     1830478 :     BitmapDeviceSharedPtr result( createBitmapDeviceImplInner( rSize, bTopDown, nScanlineFormat, pMem, pPal, pSubset, rDamage, bBlack ) );
    2140             : 
    2141             : #ifdef SAL_LOG_INFO
    2142             :     std::ostringstream subset;
    2143             : 
    2144             :     if (pSubset)
    2145             :         subset << " subset=" << pSubset->getWidth() << "x" << pSubset->getHeight() << "@(" << pSubset->getMinX() << "," << pSubset->getMinY() << ")";
    2146             : 
    2147             :     SAL_INFO( "basebmp.bitmapdevice",
    2148             :               "createBitmapDevice: "
    2149             :               << rSize.getX() << "x" << rSize.getY()
    2150             :               << (bTopDown ? " top-down " : " bottom-up ")
    2151             :               << formatName(nScanlineFormat)
    2152             :               << subset.str()
    2153             :               << " = " << result.get() );
    2154             : #endif
    2155     1830478 :     return result;
    2156             : }
    2157             : } // namespace
    2158             : 
    2159             : 
    2160      274534 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
    2161             :                                           bool                      bTopDown,
    2162             :                                           Format                    nScanlineFormat )
    2163             : {
    2164             :     return createBitmapDeviceImpl( rSize,
    2165             :                                    bTopDown,
    2166             :                                    nScanlineFormat,
    2167             :                                    boost::shared_array< sal_uInt8 >(),
    2168             :                                    PaletteMemorySharedVector(),
    2169             :                                    NULL,
    2170      274534 :                                    IBitmapDeviceDamageTrackerSharedPtr() );
    2171             : }
    2172             : 
    2173       20668 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector&        rSize,
    2174             :                                           bool                             bTopDown,
    2175             :                                           Format                           nScanlineFormat,
    2176             :                                           const PaletteMemorySharedVector& rPalette )
    2177             : {
    2178             :     return createBitmapDeviceImpl( rSize,
    2179             :                                    bTopDown,
    2180             :                                    nScanlineFormat,
    2181             :                                    boost::shared_array< sal_uInt8 >(),
    2182             :                                    rPalette,
    2183             :                                    NULL,
    2184       20668 :                                    IBitmapDeviceDamageTrackerSharedPtr() );
    2185             : }
    2186             : 
    2187      251009 : BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector&        rSize,
    2188             :                                           bool                             bTopDown,
    2189             :                                           Format                           nScanlineFormat,
    2190             :                                           const RawMemorySharedArray&      rMem,
    2191             :                                           const PaletteMemorySharedVector& rPalette )
    2192             : {
    2193             :     return createBitmapDeviceImpl( rSize,
    2194             :                                    bTopDown,
    2195             :                                    nScanlineFormat,
    2196             :                                    rMem,
    2197             :                                    rPalette,
    2198             :                                    NULL,
    2199      251009 :                                    IBitmapDeviceDamageTrackerSharedPtr() );
    2200             : }
    2201             : 
    2202       28015 : BitmapDeviceSharedPtr createClipDevice( const basegfx::B2IVector&        rSize )
    2203             : {
    2204             :     BitmapDeviceSharedPtr xClip(
    2205             :              createBitmapDeviceImpl( rSize,
    2206             :                                      false, /* bTopDown */
    2207             :                                      basebmp::FORMAT_ONE_BIT_MSB_GREY,
    2208             :                                      boost::shared_array< sal_uInt8 >(),
    2209             :                                      PaletteMemorySharedVector(),
    2210             :                                      NULL,
    2211             :                                      IBitmapDeviceDamageTrackerSharedPtr(),
    2212       28015 :                                      false /* white */) );
    2213       28015 :     return xClip;
    2214             : }
    2215             : 
    2216      963481 : BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto,
    2217             :                                           const basegfx::B2IBox&       rSubset )
    2218             : {
    2219             :     SAL_INFO( "basebmp.bitmapdevice", "subsetBitmapDevice: proto=" << rProto.get() );
    2220             :     return createBitmapDeviceImpl( rProto->getSize(),
    2221      963481 :                                    rProto->isTopDown(),
    2222             :                                    rProto->getScanlineFormat(),
    2223             :                                    rProto->getBuffer(),
    2224             :                                    rProto->getPalette(),
    2225             :                                    &rSubset,
    2226     1926962 :                                    rProto->getDamageTracker() );
    2227             : }
    2228             : 
    2229      292771 : BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector&    rSize,
    2230             :                                          const BitmapDeviceSharedPtr& rProto )
    2231             : {
    2232             :     return createBitmapDeviceImpl( rSize,
    2233      292771 :                                    rProto->isTopDown(),
    2234             :                                    rProto->getScanlineFormat(),
    2235             :                                    boost::shared_array< sal_uInt8 >(),
    2236             :                                    rProto->getPalette(),
    2237             :                                    NULL,
    2238      585542 :                                    rProto->getDamageTracker() );
    2239             : }
    2240             : 
    2241             : 
    2242             : /// Clone our device, with GenericImageAccessor to handle all formats
    2243           0 : BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const
    2244             : {
    2245           0 :     return mpImpl->mpGenericRenderer;
    2246             : }
    2247             : 
    2248             : } // namespace basebmp
    2249             : 
    2250             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10