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

Generated by: LCOV version 1.11