/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// FIXME: in vigra
#if defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x580)
#include <math.h> // needed for fabs, hypot
#endif
#include "basebmp/bitmapdevice.hxx"

#include "basebmp/compositeiterator.hxx"
#include "basebmp/iteratortraits.hxx"

#include "basebmp/accessor.hxx"
#include "basebmp/accessortraits.hxx"
#include "basebmp/accessoradapters.hxx"
#include "basebmp/colorblendaccessoradapter.hxx"

#include "basebmp/color.hxx"
#include "basebmp/colormisc.hxx"
#include "basebmp/colortraits.hxx"

#include "basebmp/greylevelformats.hxx"
#include "basebmp/paletteformats.hxx"
#include "basebmp/rgbmaskpixelformats.hxx"
#include "basebmp/rgb24pixelformats.hxx"

#include "basebmp/scanlineformats.hxx"
#include "basebmp/fillimage.hxx"
#include "basebmp/scaleimage.hxx"
#include "basebmp/clippedlinerenderer.hxx"
#include "basebmp/polypolygonrenderer.hxx"
#include "basebmp/genericcolorimageaccessor.hxx"

#include "basebmp/tools.hxx"
#include "intconversion.hxx"

#include <rtl/alloc.h>
#include <rtl/memory.h>
#include <osl/diagnose.h>

#include <basegfx/tools/tools.hxx>
#include <basegfx/range/b2irange.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/point/b2ipoint.hxx>
#include <basegfx/vector/b2ivector.hxx>

#include <vigra/iteratortraits.hxx>
#include <vigra/rgbvalue.hxx>
#include <vigra/copyimage.hxx>
#include <vigra/tuple.hxx>


namespace vigra
{

/// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex >
inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex>
operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs,
           RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs )
{
    RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res(
        lhs[0] ^ rhs[0],
        lhs[1] ^ rhs[1],
        lhs[2] ^ rhs[2]);
    return res;
}
}

namespace basebmp
{

namespace
{
    /** Create the type for an accessor that takes the (mask,bitmap)
        input value generated from a JoinImageAccessorAdapter, and
        pipe that through a mask functor.

        @tpl DestAccessor
        Destination bitmap accessor

        @tpl JoinedAccessor
        Input accessor, is expected to generate a std::pair as the
        value type

        @tpl MaskFunctorMode
        Either FastMask or NoFastMask, depending on whether the mask
        is guaranteed to contain only 0s and 1s.
     */
    template< class    DestAccessor,
              class    JoinedAccessor,
              bool     polarity,
              typename MaskFunctorMode > struct masked_input_splitting_accessor
    {
        typedef BinarySetterFunctionAccessorAdapter< 
            DestAccessor,
            BinaryFunctorSplittingWrapper< 
                typename outputMaskFunctorSelector< 
                         typename JoinedAccessor::value_type::first_type,
                         typename JoinedAccessor::value_type::second_type,
                         polarity,
                         MaskFunctorMode >::type > > type;
    };



    // Actual BitmapDevice implementation (templatized by accessor and iterator)
    //--------------------------------------------------------------------------

    /** Implementation of the BitmapDevice interface

        @tpl DestIterator
        Iterator to access bitmap memory

        @tpl RawAccessor
        Raw accessor, to access pixel values directly

        @tpl AccessorSelector
        Accessor adapter selector, which, when applying the nested
        template metafunction wrap_accessor to one of the raw bitmap
        accessors, yields a member type named 'type', which is a
        wrapped accessor that map color values.

        @tpl Masks
        Traits template, containing nested traits
        clipmask_format_traits and alphamask_format_traits, which
        determine what specialized formats are to be used for clip and
        alpha masks. With those mask formats, clipping and alpha
        blending is handled natively.
     */
    template< class DestIterator, 
              class RawAccessor, 
              class AccessorSelector,
              class Masks > class BitmapRenderer : 
                  public BitmapDevice
    {
    public:
        typedef DestIterator                                               dest_iterator_type;
        typedef RawAccessor                                                raw_accessor_type;
        typedef AccessorSelector                                           accessor_selector;

        typedef typename Masks::clipmask_format_traits::iterator_type      mask_iterator_type;
        typedef typename Masks::clipmask_format_traits::raw_accessor_type  mask_rawaccessor_type;
        typedef typename Masks::clipmask_format_traits::accessor_selector  mask_accessorselector_type;

        typedef typename Masks::alphamask_format_traits::iterator_type     alphamask_iterator_type;
        typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type;
        typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type;

        typedef typename AccessorSelector::template wrap_accessor< 
            raw_accessor_type >::type                                      dest_accessor_type;

        typedef AccessorTraits< dest_accessor_type >                       accessor_traits;
        typedef CompositeIterator2D< dest_iterator_type, 
                                     mask_iterator_type >                  composite_iterator_type;
        typedef CompositeIterator2D< vigra::Diff2D, 
                                     vigra::Diff2D >                       generic_composite_iterator_type;

        typedef BitmapRenderer<mask_iterator_type,
                               mask_rawaccessor_type,
                               mask_accessorselector_type,
                               Masks>                                      mask_bitmap_type;
        typedef BitmapRenderer<alphamask_iterator_type,
                               alphamask_rawaccessor_type,
                               alphamask_accessorselector_type,
                               Masks>                                      alphamask_bitmap_type;

        // -------------------------------------------------------

        typedef AccessorTraits< raw_accessor_type >                        raw_accessor_traits;
        typedef typename uInt32Converter<
            typename raw_accessor_type::value_type>::to                    to_uint32_functor;

        // -------------------------------------------------------

        typedef typename raw_accessor_traits::xor_accessor                 raw_xor_accessor_type;
        typedef AccessorTraits<raw_xor_accessor_type>                      raw_xor_accessor_traits;
        typedef typename accessor_selector::template wrap_accessor< 
            raw_xor_accessor_type >::type                                  xor_accessor_type;
        typedef AccessorTraits<xor_accessor_type>                          xor_accessor_traits;

        // -------------------------------------------------------

        typedef typename raw_accessor_traits::template masked_accessor< 
            mask_rawaccessor_type,
            dest_iterator_type,
            mask_iterator_type,
            Masks::clipmask_polarity>::type                                raw_maskedaccessor_type;
        typedef typename accessor_selector::template wrap_accessor< 
            raw_maskedaccessor_type >::type                                masked_accessor_type;
        typedef typename AccessorTraits<
            raw_maskedaccessor_type>::xor_accessor                         raw_maskedxor_accessor_type;
        typedef typename accessor_selector::template wrap_accessor< 
            raw_maskedxor_accessor_type >::type                            masked_xoraccessor_type;

        // -------------------------------------------------------

        // ((iter,mask),mask) special case (e.g. for clipped
        // drawMaskedColor())
        typedef AccessorTraits< raw_maskedaccessor_type >                  raw_maskedaccessor_traits;
        typedef typename raw_maskedaccessor_traits::template masked_accessor< 
            mask_rawaccessor_type,
            composite_iterator_type,
            mask_iterator_type,
            Masks::clipmask_polarity>::type                                raw_maskedmask_accessor_type;

        typedef CompositeIterator2D< 
            composite_iterator_type,
            mask_iterator_type>                                            composite_composite_mask_iterator_type;
        
        // -------------------------------------------------------

        typedef ConstantColorBlendSetterAccessorAdapter< 
            dest_accessor_type,
            typename alphamask_rawaccessor_type::value_type,
            Masks::alphamask_polarity>                                     colorblend_accessor_type;
        typedef AccessorTraits<colorblend_accessor_type>                   colorblend_accessor_traits;
        typedef typename colorblend_accessor_traits::template masked_accessor< 
            mask_rawaccessor_type,
            dest_iterator_type,
            mask_iterator_type,
            Masks::clipmask_polarity>::type                                masked_colorblend_accessor_type;

        // -------------------------------------------------------

        typedef ConstantColorBlendSetterAccessorAdapter< 
            dest_accessor_type,
            Color,
            Masks::alphamask_polarity>                                     colorblend_generic_accessor_type;
        typedef AccessorTraits<colorblend_generic_accessor_type>           colorblend_generic_accessor_traits;
        typedef typename colorblend_generic_accessor_traits::template masked_accessor< 
            mask_rawaccessor_type,
            dest_iterator_type,
            mask_iterator_type,
            Masks::clipmask_polarity>::type                                masked_colorblend_generic_accessor_type;

        // -------------------------------------------------------

        typedef JoinImageAccessorAdapter< dest_accessor_type,
                                          mask_rawaccessor_type >          joined_image_accessor_type;
        typedef JoinImageAccessorAdapter< GenericColorImageAccessor,
                                          GenericColorImageAccessor >      joined_generic_image_accessor_type;

        // -------------------------------------------------------

        dest_iterator_type                      maBegin;
        typename accessor_traits::color_lookup  maColorLookup;
        to_uint32_functor                       maToUInt32Converter;    
        dest_accessor_type                      maAccessor;
        colorblend_accessor_type                maColorBlendAccessor;
        colorblend_generic_accessor_type        maGenericColorBlendAccessor;
        raw_accessor_type                       maRawAccessor;
        xor_accessor_type                       maXorAccessor;
        raw_xor_accessor_type                   maRawXorAccessor;
        masked_accessor_type                    maMaskedAccessor;
        masked_colorblend_accessor_type         maMaskedColorBlendAccessor;
        masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor;
        masked_xoraccessor_type                 maMaskedXorAccessor;
        raw_maskedaccessor_type                 maRawMaskedAccessor;
        raw_maskedxor_accessor_type             maRawMaskedXorAccessor;
        raw_maskedmask_accessor_type            maRawMaskedMaskAccessor;

        // -------------------------------------------------------

        BitmapRenderer( const basegfx::B2IRange&         rBounds,
                        sal_Int32                        nScanlineFormat,
                        sal_Int32                        nScanlineStride,
                        sal_uInt8*                       pFirstScanline,
                        dest_iterator_type               begin, 
                        raw_accessor_type                rawAccessor,
                        dest_accessor_type               accessor,
                        const RawMemorySharedArray&      rMem,
                        const PaletteMemorySharedVector& rPalette ) :
            BitmapDevice( rBounds, nScanlineFormat, 
                          nScanlineStride, pFirstScanline, rMem, rPalette ),
            maBegin( begin ),
            maColorLookup(),
            maToUInt32Converter(),
            maAccessor( accessor ),
            maColorBlendAccessor( accessor ),
            maGenericColorBlendAccessor( accessor ),
            maRawAccessor( rawAccessor ),
            maXorAccessor( accessor ),
            maRawXorAccessor( rawAccessor ),
            maMaskedAccessor( accessor ),
            maMaskedColorBlendAccessor( maColorBlendAccessor ),
            maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ),
            maMaskedXorAccessor( accessor ),
            maRawMaskedAccessor( rawAccessor ),
            maRawMaskedXorAccessor( rawAccessor ),
            maRawMaskedMaskAccessor( rawAccessor )
        {}

    private:
        boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
        {
            return boost::dynamic_pointer_cast< BitmapRenderer >( bmp );
        }

        virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
        {
            // TODO(P1): dynamic_cast usually called twice for
            // compatible formats
            return getCompatibleBitmap(bmp).get() != NULL;
        }

        boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
        {
            boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ));

            if( !pMask )
                return pMask;

            if( pMask->getSize() != getSize() )
                pMask.reset();

            return pMask;
        }

        virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
        {
            // TODO(P1): dynamic_cast usually called twice for
            // compatible formats
            return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL;
        }

        boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
        {
            return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp );
        }

        virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
        {
            // TODO(P1): dynamic_cast usually called twice for
            // compatible formats
            return getCompatibleAlphaMask( bmp ).get() != NULL;
        }

        virtual void clear_i( Color                     fillColor,
                              const basegfx::B2IRange&  rBounds )
        {
            fillImage(destIterRange(maBegin,
                                    maRawAccessor,
                                    rBounds), 
                      maColorLookup( 
                          maAccessor,
                          fillColor) );
        }

        virtual void setPixel_i( const basegfx::B2IPoint& rPt, 
                                 Color                    pixelColor, 
                                 DrawMode                 drawMode )
        {
            const DestIterator pixel( maBegin + 
                                      vigra::Diff2D(rPt.getX(),
                                                    rPt.getY()) );
            if( drawMode == DrawMode_XOR )
                maXorAccessor.set( pixelColor, 
                                   pixel );
            else
                maAccessor.set( pixelColor, 
                                pixel );
        }

        virtual void setPixel_i( const basegfx::B2IPoint&     rPt, 
                                 Color                        pixelColor, 
                                 DrawMode                     drawMode, 
                                 const BitmapDeviceSharedPtr& rClip )
        {
            boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
            OSL_ASSERT( pMask );

            const vigra::Diff2D offset(rPt.getX(),
                                       rPt.getY());

            const composite_iterator_type aIter( 
                maBegin + offset,
                pMask->maBegin + offset );

            if( drawMode == DrawMode_XOR )
                maMaskedXorAccessor.set( pixelColor,
                                         aIter );
            else
                maMaskedAccessor.set( pixelColor,
                                      aIter );
        }

        virtual Color getPixel_i(const basegfx::B2IPoint& rPt )
        {
            const DestIterator pixel( maBegin + 
                                      vigra::Diff2D(rPt.getX(),
                                                    rPt.getY()) );
            return maAccessor(pixel);
        }

        virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt )
        {
            const DestIterator pixel( maBegin + 
                                      vigra::Diff2D(rPt.getX(),
                                                    rPt.getY()) );
            return maToUInt32Converter(maRawAccessor(pixel));
        }

        template< typename Iterator, typename Col, typename RawAcc >
        void implRenderLine2( const basegfx::B2IPoint& rPt1,
                              const basegfx::B2IPoint& rPt2,
                              const basegfx::B2IRange& rBounds,
                              Col                      col,
                              const Iterator&          begin,
                              const RawAcc&            rawAcc )
        {
            renderClippedLine( rPt1, 
                               rPt2,
                               rBounds,
                               col,
                               begin,
                               rawAcc );
        }

        template< typename Iterator, typename Accessor, typename RawAcc >
        void implRenderLine( const basegfx::B2IPoint& rPt1,
                             const basegfx::B2IPoint& rPt2,
                             const basegfx::B2IRange& rBounds,
                             Color                    col,
                             const Iterator&          begin,
                             const Accessor&          acc,
                             const RawAcc&            rawAcc )
        {
            implRenderLine2( rPt1,rPt2,rBounds,
                             maColorLookup( acc,
                                            col ),
                             begin,
                             rawAcc );
        }
    
        template< typename Iterator, typename RawAcc, typename XorAcc >
        void implDrawLine( const basegfx::B2IPoint& rPt1,
                           const basegfx::B2IPoint& rPt2,
                           const basegfx::B2IRange& rBounds,
                           Color                    col,
                           const Iterator&          begin, 
                           const RawAcc&            rawAcc,
                           const XorAcc&            xorAcc, 
                           DrawMode                 drawMode )
        {
            if( drawMode == DrawMode_XOR )
                implRenderLine( rPt1, rPt2, rBounds, col,
                                begin, maAccessor, xorAcc );
            else
                implRenderLine( rPt1, rPt2, rBounds, col,
                                begin, maAccessor, rawAcc );
        }

        virtual void drawLine_i(const basegfx::B2IPoint& rPt1, 
                                const basegfx::B2IPoint& rPt2, 
                                const basegfx::B2IRange& rBounds,
                                Color                    lineColor, 
                                DrawMode                 drawMode )
        {
            implDrawLine(rPt1,rPt2,rBounds,lineColor,
                         maBegin,
                         maRawAccessor,maRawXorAccessor,drawMode);
        }

        composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const
        {
            boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
            OSL_ASSERT( pMask );

            return composite_iterator_type( maBegin, 
                                            pMask->maBegin );
        }

        virtual void drawLine_i(const basegfx::B2IPoint&     rPt1, 
                                const basegfx::B2IPoint&     rPt2, 
                                const basegfx::B2IRange&     rBounds,
                                Color                        lineColor, 
                                DrawMode                     drawMode, 
                                const BitmapDeviceSharedPtr& rClip )
        {
            implDrawLine(rPt1,rPt2,rBounds,lineColor,
                         getMaskedIter(rClip),
                         maRawMaskedAccessor,
                         maRawMaskedXorAccessor,drawMode);
        }

        template< typename Iterator, typename RawAcc >
        void implDrawPolygon( const basegfx::B2DPolygon& rPoly, 
                              const basegfx::B2IRange&   rBounds,
                              Color                      col,
                              const Iterator&            begin, 
                              const RawAcc&              acc )
        {
            basegfx::B2DPolygon aPoly( rPoly );
            if( rPoly.areControlPointsUsed() )
                aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );

            const typename dest_iterator_type::value_type colorIndex( maColorLookup( 
                                                                          maAccessor,
                                                                          col));
            const sal_uInt32                              nVertices( aPoly.count() );
            for( sal_uInt32 i=1; i<nVertices; ++i )
                implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)), 
                                 basegfx::fround(aPoly.getB2DPoint(i)), 
                                 rBounds,
                                 colorIndex,
                                 begin,
                                 acc );

            if( nVertices > 1 && aPoly.isClosed() )
                implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)), 
                                 basegfx::fround(aPoly.getB2DPoint(0)), 
                                 rBounds,
                                 colorIndex,
                                 begin,
                                 acc );
        }

        virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly, 
                                   const basegfx::B2IRange&   rBounds,
                                   Color                      lineColor, 
                                   DrawMode                   drawMode )
        {
            if( drawMode == DrawMode_XOR )
                implDrawPolygon( rPoly, rBounds, lineColor, 
                                 maBegin, 
                                 maRawXorAccessor );
            else
                implDrawPolygon( rPoly, rBounds, lineColor, 
                                 maBegin, 
                                 maRawAccessor );
        }

        virtual void drawPolygon_i(const basegfx::B2DPolygon&   rPoly, 
                                   const basegfx::B2IRange&     rBounds,
                                   Color                        lineColor, 
                                   DrawMode                     drawMode, 
                                   const BitmapDeviceSharedPtr& rClip )
        {
            if( drawMode == DrawMode_XOR )
                implDrawPolygon( rPoly, rBounds, lineColor, 
                                 getMaskedIter(rClip),
                                 maRawMaskedXorAccessor );
            else
                implDrawPolygon( rPoly, rBounds, lineColor, 
                                 getMaskedIter(rClip),
                                 maRawMaskedAccessor );
        }

        template< typename Iterator, typename RawAcc >
        void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, 
                                  Color                          col,
                                  const Iterator&                begin, 
                                  const RawAcc&                  acc,
                                  const basegfx::B2IRange&       rBounds )
        {
            basegfx::B2DPolyPolygon aPoly( rPoly );
            if( rPoly.areControlPointsUsed() )
                aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );

            renderClippedPolyPolygon( begin, 
                                      acc,
                                      maColorLookup( maAccessor,
                                                     col),
                                      rBounds,
                                      aPoly,
                                      basegfx::FillRule_EVEN_ODD );
        }

        virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly, 
                                       Color                          fillColor, 
                                       DrawMode                       drawMode,
                                       const basegfx::B2IRange&       rBounds )
        {
            if( drawMode == DrawMode_XOR )
                implFillPolyPolygon( rPoly, fillColor, 
                                     maBegin,
                                     maRawXorAccessor,
                                     rBounds );
            else
                implFillPolyPolygon( rPoly, fillColor, 
                                     maBegin,
                                     maRawAccessor,
                                     rBounds );
        }

        virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly, 
                                       Color                          fillColor, 
                                       DrawMode                       drawMode,
                                       const basegfx::B2IRange&       rBounds, 
                                       const BitmapDeviceSharedPtr&   rClip )
        {
            if( drawMode == DrawMode_XOR )
                implFillPolyPolygon( rPoly, fillColor, 
                                     getMaskedIter(rClip),
                                     maRawMaskedXorAccessor,
                                     rBounds );
            else
                implFillPolyPolygon( rPoly, fillColor, 
                                     getMaskedIter(rClip),
                                     maRawMaskedAccessor,
                                     rBounds );
        }

        template< typename Iterator, typename RawAcc >
        void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
                            const basegfx::B2IRange&     rSrcRect,
                            const basegfx::B2IRange&     rDstRect,
                            const Iterator&              begin,
                            const RawAcc&                acc)
        {
            boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
            OSL_ASSERT( pSrcBmp );

            scaleImage(
                srcIterRange(pSrcBmp->maBegin,
                             pSrcBmp->maRawAccessor,
                             rSrcRect),
                destIterRange(begin,
                              acc,
                              rDstRect),
                rSrcBitmap.get() == this );
        }

        template< typename Iterator, typename Acc >
        void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
                                   const basegfx::B2IRange&     rSrcRect,
                                   const basegfx::B2IRange&     rDstRect,
                                   const Iterator&              begin,
                                   const Acc&                   acc)
        {
            GenericColorImageAccessor aSrcAcc( rSrcBitmap );
 
            scaleImage(
                srcIterRange(vigra::Diff2D(),
                             aSrcAcc,
                             rSrcRect),
                destIterRange(begin,
                              acc,
                              rDstRect));
        }

        virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
                                  const basegfx::B2IRange&     rSrcRect,
                                  const basegfx::B2IRange&     rDstRect, 
                                  DrawMode                     drawMode )
        {
            if( isCompatibleBitmap( rSrcBitmap ) )
            {
                if( drawMode == DrawMode_XOR )
                    implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
                                   maBegin,
                                   maRawXorAccessor);
                else
                    implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
                                   maBegin,
                                   maRawAccessor);
            }
            else
            {
                if( drawMode == DrawMode_XOR )
                    implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
                                          maBegin,
                                          maXorAccessor);
                else
                    implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
                                          maBegin,
                                          maAccessor);
            }
        }

        virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
                                  const basegfx::B2IRange&     rSrcRect,
                                  const basegfx::B2IRange&     rDstRect, 
                                  DrawMode                     drawMode, 
                                  const BitmapDeviceSharedPtr& rClip )
        {
            if( isCompatibleBitmap( rSrcBitmap ) )
            {
                if( drawMode == DrawMode_XOR )
                    implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
                                   getMaskedIter(rClip),
                                   maRawMaskedXorAccessor);
                else
                    implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
                                   getMaskedIter(rClip),
                                   maRawMaskedAccessor);
            }
            else
            {
                if( drawMode == DrawMode_XOR )
                    implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
                                          getMaskedIter(rClip),
                                          maMaskedXorAccessor);
                else
                    implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
                                          getMaskedIter(rClip),
                                          maMaskedAccessor);
            }
        }

        virtual void drawMaskedColor_i(Color                        aSrcColor,
                                       const BitmapDeviceSharedPtr& rAlphaMask,
                                       const basegfx::B2IRange&     rSrcRect,
                                       const basegfx::B2IPoint&     rDstPoint )
        {
            boost::shared_ptr<mask_bitmap_type>      pMask( getCompatibleClipMask(rAlphaMask) );
            boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );

            if( pAlpha )
            {
                maColorBlendAccessor.setColor( aSrcColor );

                vigra::copyImage( srcIterRange(pAlpha->maBegin,
                                               pAlpha->maRawAccessor,
                                               rSrcRect),
                                  destIter(maBegin,
                                           maColorBlendAccessor,
                                           rDstPoint) );
            }
            else if( pMask )
            {
                const composite_iterator_type aBegin(
                    maBegin + vigra::Diff2D(rDstPoint.getX(),
                                            rDstPoint.getY()),
                    pMask->maBegin + topLeft(rSrcRect) );
                            
                fillImage(aBegin,
                          aBegin + vigra::Diff2D(rSrcRect.getWidth(),
                                                 rSrcRect.getHeight()), 
                          maRawMaskedAccessor,
                          maColorLookup( 
                              maAccessor,
                              aSrcColor) );
            }
            else
            {
                GenericColorImageAccessor aSrcAcc( rAlphaMask );
                maGenericColorBlendAccessor.setColor( aSrcColor );

                vigra::copyImage( srcIterRange(vigra::Diff2D(),
                                               aSrcAcc,
                                               rSrcRect),
                                  destIter(maBegin,
                                           maGenericColorBlendAccessor,
                                           rDstPoint) );
            }
        }

        virtual void drawMaskedColor_i(Color                        aSrcColor,
                                       const BitmapDeviceSharedPtr& rAlphaMask,
                                       const basegfx::B2IRange&     rSrcRect,
                                       const basegfx::B2IPoint&     rDstPoint, 
                                       const BitmapDeviceSharedPtr& rClip )
        {
            boost::shared_ptr<mask_bitmap_type>      pMask( getCompatibleClipMask(rAlphaMask) );
            boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );

            if( pAlpha )
            {
                const composite_iterator_type aBegin( getMaskedIter(rClip) );
                maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor( 
                    aSrcColor );

                vigra::copyImage( srcIterRange(pAlpha->maBegin,
                                               pAlpha->maRawAccessor,
                                               rSrcRect),
                                  destIter(aBegin,
                                           maMaskedColorBlendAccessor,
                                           rDstPoint) );
            }
            else if( pMask )
            {
                boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) );
                OSL_ASSERT( pClipMask );

                // setup a ((iter,mask),clipMask) composite composite
                // iterator, to pass both masks (clip and alpha mask)
                // to the algorithm
                const composite_composite_mask_iterator_type aBegin(
                    composite_iterator_type(
                        maBegin + vigra::Diff2D(rDstPoint.getX(),
                                                rDstPoint.getY()),
                        pMask->maBegin + topLeft(rSrcRect)),
                    pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(),
                                                       rDstPoint.getY()) );
                            
                fillImage(aBegin,
                          aBegin + vigra::Diff2D(rSrcRect.getWidth(),
                                                 rSrcRect.getHeight()), 
                          maRawMaskedMaskAccessor,
                          maColorLookup( 
                              maAccessor,
                              aSrcColor) );
            }
            else
            {
                GenericColorImageAccessor aSrcAcc( rAlphaMask );
                const composite_iterator_type aBegin( getMaskedIter(rClip) );
                maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor( 
                    aSrcColor );

                vigra::copyImage( srcIterRange(vigra::Diff2D(),
                                               aSrcAcc,
                                               rSrcRect),
                                  destIter(aBegin,
                                           maGenericMaskedColorBlendAccessor,
                                           rDstPoint) );
            }
        }

        template< typename Iterator, typename Acc >
        void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
                                  const BitmapDeviceSharedPtr& rMask,
                                  const basegfx::B2IRange&     rSrcRect,
                                  const basegfx::B2IRange&     rDstRect,
                                  const Iterator&              begin,
                                  const Acc&                   acc)
        {
            boost::shared_ptr<BitmapRenderer>   pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
            boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) );
            OSL_ASSERT( pMask && pSrcBmp );

            scaleImage(
                srcIterRange(composite_iterator_type(
                                 pSrcBmp->maBegin,
                                 pMask->maBegin),
                             joined_image_accessor_type(
                                 pSrcBmp->maAccessor,
                                 pMask->maRawAccessor),
                             rSrcRect),
                destIterRange(begin,
                              typename masked_input_splitting_accessor<
                                       Acc,
                                       joined_image_accessor_type,
                                       Masks::clipmask_polarity,
                                       FastMask >::type(acc),
                              rDstRect),
                rSrcBitmap.get() == this);
        }

        template< typename Iterator, typename Acc >
        void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
                                         const BitmapDeviceSharedPtr& rMask,
                                         const basegfx::B2IRange&     rSrcRect,
                                         const basegfx::B2IRange&     rDstRect,
                                         const Iterator&              begin,
                                         const Acc&                   acc)
        {
            GenericColorImageAccessor aSrcAcc( rSrcBitmap );
            GenericColorImageAccessor aMaskAcc( rMask );

            const vigra::Diff2D aTopLeft(rSrcRect.getMinX(),
                                         rSrcRect.getMinY());
            const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(),
                                             rSrcRect.getMaxY());
            scaleImage(
                vigra::make_triple(
                    generic_composite_iterator_type(
                        aTopLeft,aTopLeft),
                    generic_composite_iterator_type(
                        aBottomRight,aBottomRight),
                    joined_generic_image_accessor_type(
                        aSrcAcc,
                        aMaskAcc)),
                destIterRange(begin,
                              typename masked_input_splitting_accessor<
                                       Acc,
                                       joined_generic_image_accessor_type,
                                       Masks::clipmask_polarity,
                                       NoFastMask >::type(acc),
                              rDstRect));
        }

        virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
                                        const BitmapDeviceSharedPtr& rMask,
                                        const basegfx::B2IRange&     rSrcRect,
                                        const basegfx::B2IRange&     rDstRect, 
                                        DrawMode                     drawMode )
        {
            if( isCompatibleClipMask(rMask) &&
                isCompatibleBitmap(rSrcBitmap) )
            {
                if( drawMode == DrawMode_XOR )
                    implDrawMaskedBitmap(rSrcBitmap, rMask,
                                         rSrcRect, rDstRect,
                                         maBegin,
                                         maXorAccessor);
                else
                    implDrawMaskedBitmap(rSrcBitmap, rMask,
                                         rSrcRect, rDstRect,
                                         maBegin,
                                         maAccessor);
            }
            else
            {
                if( drawMode == DrawMode_XOR )
                    implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
                                                rSrcRect, rDstRect,
                                                maBegin,
                                                maXorAccessor);
                else
                    implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
                                                rSrcRect, rDstRect,
                                                maBegin,
                                                maAccessor);
            }
        }

        virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
                                        const BitmapDeviceSharedPtr& rMask,
                                        const basegfx::B2IRange&     rSrcRect,
                                        const basegfx::B2IRange&     rDstRect, 
                                        DrawMode                     drawMode, 
                                        const BitmapDeviceSharedPtr& rClip )
        {
            if( isCompatibleClipMask(rMask) &&
                isCompatibleBitmap(rSrcBitmap) )
            {
                if( drawMode == DrawMode_XOR )
                    implDrawMaskedBitmap(rSrcBitmap, rMask,
                                         rSrcRect, rDstRect,
                                         getMaskedIter(rClip),
                                         maMaskedXorAccessor);
                else
                    implDrawMaskedBitmap(rSrcBitmap, rMask,
                                         rSrcRect, rDstRect,
                                         getMaskedIter(rClip),
                                         maMaskedAccessor);
            }
            else
            {
                if( drawMode == DrawMode_XOR )
                    implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
                                                rSrcRect, rDstRect,
                                                getMaskedIter(rClip),
                                                maMaskedXorAccessor);
                else
                    implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
                                                rSrcRect, rDstRect,
                                                getMaskedIter(rClip),
                                                maMaskedAccessor);
            }
        }
    };
} // namespace

struct ImplBitmapDevice
{
    /** Bitmap memory plus deleter. 

        Always points to the start of the mem
     */
    RawMemorySharedArray      mpMem;

    /// Palette memory plus deleter (might be NULL)
    PaletteMemorySharedVector mpPalette;

    /** Bounds of the device. 

        maBounds.getWidth()/getHeight() yield the true size of the
        device (i.e. the rectangle given by maBounds covers the device
        area under the excluding-bottommost-and-rightmost-pixels fill
        rule)
     */
    basegfx::B2IRange         maBounds;

    /** Bounds of the device. 

        maBounds.getWidth()/getHeight() yield the true size of the
        device minus 1 (i.e. the rectangle given by maBounds covers
        the device area under the
        including-the-bottommost-and-rightmost-pixels fill rule).

        The member is used to clip line stroking against the device
        bounds.
     */
    basegfx::B2IRange         maLineClipRect;

    /// Scanline format, as provided at the constructor
    sal_Int32                 mnScanlineFormat;

    /// Scanline stride. Negative for bottom-to-top formats
    sal_Int32                 mnScanlineStride;
    
    /// raw ptr to 0th scanline. used for cloning a generic renderer
    sal_uInt8*                mpFirstScanline;

    /** (Optional) device sharing the same memory, and used for input
        clip masks/alpha masks/bitmaps that don't match our exact
        bitmap format.

        This is to avoid the combinatorical explosion when dealing
        with n bitmap formats, which could be combined with n clip
        masks, alpha masks and bitmap masks (yielding a total of n^4
        combinations). Since each BitmapRenderer is specialized for
        one specific combination of said formats, a lot of duplicate
        code would be generated, most of which probably never
        used. Therefore, only the most common combinations are
        specialized templates, the remainder gets handled by this
        generic renderer (via runtime polymorphism).
     */
    BitmapDeviceSharedPtr     mpGenericRenderer;
};


BitmapDevice::BitmapDevice( const basegfx::B2IRange&         rBounds,
                            sal_Int32                        nScanlineFormat,
                            sal_Int32                        nScanlineStride,
                            sal_uInt8*                       pFirstScanline,
                            const RawMemorySharedArray&      rMem,
                            const PaletteMemorySharedVector& rPalette ) :
    mpImpl( new ImplBitmapDevice )
{
    mpImpl->mpMem = rMem;
    mpImpl->mpPalette = rPalette;
    mpImpl->maBounds = rBounds;
    mpImpl->maLineClipRect = basegfx::B2IRange( rBounds.getMinX(),
                                                rBounds.getMinY(),
                                                rBounds.getMaxX()-1,
                                                rBounds.getMaxY()-1 );
    mpImpl->mnScanlineFormat = nScanlineFormat;
    mpImpl->mnScanlineStride = nScanlineStride;
    mpImpl->mpFirstScanline  = pFirstScanline;
}
    
BitmapDevice::~BitmapDevice()
{
    // outline, because of internal ImplBitmapDevice
}

basegfx::B2IVector BitmapDevice::getSize() const
{
    
    return basegfx::B2IVector(
        mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(),
        mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() );
}

bool BitmapDevice::isTopDown() const
{
    return mpImpl->mnScanlineStride >= 0;
}

sal_Int32 BitmapDevice::getScanlineFormat() const
{
    return mpImpl->mnScanlineFormat;
}

sal_Int32 BitmapDevice::getScanlineStride() const
{
    return mpImpl->mnScanlineStride < 0 ? 
        -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride;
}

RawMemorySharedArray BitmapDevice::getBuffer() const
{
    return mpImpl->mpMem;
}

PaletteMemorySharedVector BitmapDevice::getPalette() const
{
    return mpImpl->mpPalette;
}

sal_Int32 BitmapDevice::getPaletteEntryCount() const
{
    return mpImpl->mpPalette ? mpImpl->mpPalette->size() : 0;
}

void BitmapDevice::clear( Color fillColor )
{
    clear_i( fillColor, mpImpl->maBounds );
}

void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt, 
                             Color                    lineColor, 
                             DrawMode                 drawMode )
{
    if( mpImpl->maLineClipRect.isInside(rPt) )
        setPixel_i(rPt,lineColor,drawMode);
}

void BitmapDevice::setPixel( const basegfx::B2IPoint&     rPt, 
                             Color                        lineColor, 
                             DrawMode                     drawMode, 
                             const BitmapDeviceSharedPtr& rClip )
{
    if( !rClip )
    {
        setPixel(rPt,lineColor,drawMode);
        return;
    }

    if( mpImpl->maLineClipRect.isInside(rPt) )
    {
        if( isCompatibleClipMask( rClip ) )
            setPixel_i(rPt,lineColor,drawMode,rClip);
        else
            getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip );
    }
}

Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt )
{
    if( mpImpl->maLineClipRect.isInside(rPt) )
        return getPixel_i(rPt);

    return Color();
}

sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
{
    if( mpImpl->maLineClipRect.isInside(rPt) )
        return getPixelData_i(rPt);

    return 0;
}

void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1, 
                             const basegfx::B2IPoint& rPt2, 
                             Color                    lineColor, 
                             DrawMode                 drawMode )
{
    drawLine_i( rPt1, 
                rPt2,
                mpImpl->maLineClipRect,
                lineColor,
                drawMode );
}

void BitmapDevice::drawLine( const basegfx::B2IPoint&     rPt1, 
                             const basegfx::B2IPoint&     rPt2, 
                             Color                        lineColor, 
                             DrawMode                     drawMode, 
                             const BitmapDeviceSharedPtr& rClip )
{
    if( !rClip )
    {
        drawLine(rPt1,rPt2,lineColor,drawMode);
        return;
    }

    if( isCompatibleClipMask( rClip ) )
        drawLine_i( rPt1, 
                    rPt2,
                    mpImpl->maLineClipRect,
                    lineColor,
                    drawMode,
                    rClip );
    else
        getGenericRenderer()->drawLine( rPt1, rPt2, lineColor, 
                                        drawMode, rClip );
}

void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly, 
                                Color                      lineColor, 
                                DrawMode                   drawMode )
{
    const sal_uInt32 numVertices( rPoly.count() );
    if( numVertices )
        drawPolygon_i( rPoly,
                       mpImpl->maLineClipRect,
                       lineColor, drawMode );
}

void BitmapDevice::drawPolygon( const basegfx::B2DPolygon&   rPoly, 
                                Color                        lineColor, 
                                DrawMode                     drawMode, 
                                const BitmapDeviceSharedPtr& rClip )
{
    if( !rClip )
    {
        drawPolygon(rPoly,lineColor,drawMode);
        return;
    }

    const sal_uInt32 numVertices( rPoly.count() );
    if( numVertices )
    {
        if( isCompatibleClipMask( rClip ) )
            drawPolygon_i( rPoly,
                           mpImpl->maLineClipRect,
                           lineColor, drawMode, rClip );
        else
            getGenericRenderer()->drawPolygon( rPoly, lineColor, 
                                               drawMode, rClip );
    }
}

void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, 
                                    Color                          fillColor, 
                                    DrawMode                       drawMode )
{
    fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
}

void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, 
                                    Color                          fillColor, 
                                    DrawMode                       drawMode, 
                                    const BitmapDeviceSharedPtr&   rClip )
{
    if( !rClip )
    {
        fillPolyPolygon(rPoly,fillColor,drawMode);
        return;
    }

    if( isCompatibleClipMask( rClip ) )
        fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
    else
        getGenericRenderer()->fillPolyPolygon( rPoly, fillColor, 
                                               drawMode, rClip );
}


namespace
{
    void assertImagePoint( const basegfx::B2IPoint& rPt,
                           const basegfx::B2IRange& rPermittedRange )
    {
        (void)rPt; (void)rPermittedRange;
        OSL_ASSERT( rPermittedRange.isInside(rPt) );
    }

    void assertImageRange( const basegfx::B2IRange& rRange,
                           const basegfx::B2IRange& rPermittedRange )
    {
#if OSL_DEBUG_LEVEL > 0
        basegfx::B2IRange aRange( rRange );
        aRange.intersect( rPermittedRange );

        OSL_ASSERT( aRange == rRange );
#else
        (void)rRange; (void)rPermittedRange;
#endif
    }

    // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
    // to basegfx, and use here!
    bool clipAreaImpl( ::basegfx::B2IRange&       io_rSourceArea,
                       ::basegfx::B2IPoint&       io_rDestPoint,
                       const ::basegfx::B2IRange& rSourceBounds,
                       const ::basegfx::B2IRange& rDestBounds )
    {
        const ::basegfx::B2IPoint aSourceTopLeft( 
            io_rSourceArea.getMinimum() );

        ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );

        // clip source area (which must be inside rSourceBounds)
        aLocalSourceArea.intersect( rSourceBounds );

        if( aLocalSourceArea.isEmpty() )
            return false;
            
        // calc relative new source area points (relative to orig
        // source area)
        const ::basegfx::B2IVector aUpperLeftOffset( 
            aLocalSourceArea.getMinimum()-aSourceTopLeft );
        const ::basegfx::B2IVector aLowerRightOffset( 
            aLocalSourceArea.getMaximum()-aSourceTopLeft );

        ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
                                            io_rDestPoint + aLowerRightOffset );
            
        // clip dest area (which must be inside rDestBounds)
        aLocalDestArea.intersect( rDestBounds );
            
        if( aLocalDestArea.isEmpty() )
            return false;

        // calc relative new dest area points (relative to orig
        // source area)
        const ::basegfx::B2IVector aDestUpperLeftOffset( 
            aLocalDestArea.getMinimum()-io_rDestPoint );
        const ::basegfx::B2IVector aDestLowerRightOffset( 
            aLocalDestArea.getMaximum()-io_rDestPoint );

        io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
                                              aSourceTopLeft + aDestLowerRightOffset );
        io_rDestPoint  = aLocalDestArea.getMinimum();

        return true;
    }

    // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
    // to basegfx, and use here!
    bool clipAreaImpl( ::basegfx::B2IRange&       io_rDestArea,
                       ::basegfx::B2IRange&       io_rSourceArea,
                       const ::basegfx::B2IRange& rDestBounds,
                       const ::basegfx::B2IRange& rSourceBounds )
    {
        // extract inherent scale
        const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() );
        const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() );

        // extract range origins
        const basegfx::B2IPoint   aDestTopLeft( 
            io_rDestArea.getMinimum() );
        const ::basegfx::B2IPoint aSourceTopLeft( 
            io_rSourceArea.getMinimum() );

        ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );

        // clip source area (which must be inside rSourceBounds)
        aLocalSourceArea.intersect( rSourceBounds );

        if( aLocalSourceArea.isEmpty() )
            return false;
            
        // calc relative new source area points (relative to orig
        // source area)
        const ::basegfx::B2IVector aUpperLeftOffset( 
            aLocalSourceArea.getMinimum()-aSourceTopLeft );
        const ::basegfx::B2IVector aLowerRightOffset( 
            aLocalSourceArea.getMaximum()-aSourceTopLeft );

        ::basegfx::B2IRange aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
                                            basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
                                            basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
                                            basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
            
        // clip dest area (which must be inside rDestBounds)
        aLocalDestArea.intersect( rDestBounds );
            
        if( aLocalDestArea.isEmpty() )
            return false;

        // calc relative new dest area points (relative to orig
        // source area)
        const ::basegfx::B2IVector aDestUpperLeftOffset( 
            aLocalDestArea.getMinimum()-aDestTopLeft );
        const ::basegfx::B2IVector aDestLowerRightOffset( 
            aLocalDestArea.getMaximum()-aDestTopLeft );

        io_rSourceArea = ::basegfx::B2IRange( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
                                              basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
                                              basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
                                              basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
        io_rDestArea   = aLocalDestArea;

        // final source area clip (chopping round-offs)
        io_rSourceArea.intersect( rSourceBounds );
            
        if( io_rSourceArea.isEmpty() )
            return false;


        return true;
    }
}

void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
                               const basegfx::B2IRange&     rSrcRect,
                               const basegfx::B2IRange&     rDstRect, 
                               DrawMode                     drawMode )
{
    const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
    const basegfx::B2IRange   aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    basegfx::B2IRange         aSrcRange( rSrcRect );
    basegfx::B2IRange         aDestRange( rDstRect );

    if( clipAreaImpl( aDestRange,
                      aSrcRange,
                      mpImpl->maBounds,
                      aSrcBounds ))
    {
        assertImageRange(aDestRange,mpImpl->maBounds);
        assertImageRange(aSrcRange,aSrcBounds);

        drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode );
    }
}

void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
                               const basegfx::B2IRange&     rSrcRect,
                               const basegfx::B2IRange&     rDstRect, 
                               DrawMode                     drawMode, 
                               const BitmapDeviceSharedPtr& rClip )
{
    if( !rClip )
    {
        drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
        return;
    }

    const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
    const basegfx::B2IRange   aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    basegfx::B2IRange         aSrcRange( rSrcRect );
    basegfx::B2IRange         aDestRange( rDstRect );

    if( clipAreaImpl( aDestRange,
                      aSrcRange,
                      mpImpl->maBounds,
                      aSrcBounds ))
    {
        assertImageRange(aDestRange,mpImpl->maBounds);
        assertImageRange(aSrcRange,aSrcBounds);

        if( isCompatibleClipMask( rClip ) )
        {
            drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip );
        }
        else
        {
            getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect, 
                                              rDstRect, drawMode, rClip );
        }
    }
}

void BitmapDevice::drawMaskedColor( Color                        aSrcColor,
                                    const BitmapDeviceSharedPtr& rAlphaMask,
                                    const basegfx::B2IRange&     rSrcRect,
                                    const basegfx::B2IPoint&     rDstPoint )
{
    const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
    const basegfx::B2IRange   aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    basegfx::B2IRange         aSrcRange( rSrcRect );
    basegfx::B2IPoint         aDestPoint( rDstPoint );

    if( clipAreaImpl( aSrcRange,
                      aDestPoint,
                      aSrcBounds,
                      mpImpl->maBounds ))
    {
        assertImagePoint(aDestPoint,mpImpl->maBounds);
        assertImageRange(aSrcRange,aSrcBounds);

        if( rAlphaMask.get() == this )
        {
            // src == dest, copy rAlphaMask beforehand
            // ---------------------------------------------------

            const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
                                           aSrcRange.getHeight() );
            BitmapDeviceSharedPtr pAlphaCopy( 
                cloneBitmapDevice( aSize,
                                   shared_from_this()) );
            basegfx::B2ITuple aGcc3WorkaroundTemporary;
            const basegfx::B2IRange aAlphaRange( aGcc3WorkaroundTemporary,
                                                 aSize );
            pAlphaCopy->drawBitmap(rAlphaMask,
                                   aSrcRange,
                                   aAlphaRange,
                                   DrawMode_PAINT);
            drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint );
        }
        else
        {
            drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint );
        }
    }
}

void BitmapDevice::drawMaskedColor( Color                        aSrcColor,
                                    const BitmapDeviceSharedPtr& rAlphaMask,
                                    const basegfx::B2IRange&     rSrcRect,
                                    const basegfx::B2IPoint&     rDstPoint, 
                                    const BitmapDeviceSharedPtr& rClip )
{
    if( !rClip )
    {
        drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
        return;
    }

    const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
    const basegfx::B2IRange   aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    basegfx::B2IRange         aSrcRange( rSrcRect );
    basegfx::B2IPoint         aDestPoint( rDstPoint );

    if( clipAreaImpl( aSrcRange,
                      aDestPoint,
                      aSrcBounds,
                      mpImpl->maBounds ))
    {
        assertImagePoint(aDestPoint,mpImpl->maBounds);
        assertImageRange(aSrcRange,aSrcBounds);

        if( isCompatibleClipMask( rClip ) )
        {
            if( rAlphaMask.get() == this )
            {
                // src == dest, copy rAlphaMask beforehand
                // ---------------------------------------------------

                const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
                                               aSrcRange.getHeight() );
                BitmapDeviceSharedPtr pAlphaCopy( 
                    cloneBitmapDevice( aSize,
                                       shared_from_this()) );
                basegfx::B2ITuple aGcc3WorkaroundTemporary;
                const basegfx::B2IRange aAlphaRange( aGcc3WorkaroundTemporary,
                                                     aSize );
                pAlphaCopy->drawBitmap(rAlphaMask,
                                       aSrcRange,
                                       aAlphaRange,
                                       DrawMode_PAINT);
                drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip );
            }
            else
            {
                drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
            }
        }
        else
        {
            getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask,
                                                   rSrcRect, rDstPoint, rClip );
        }
    }
}

void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
                                     const BitmapDeviceSharedPtr& rMask,
                                     const basegfx::B2IRange&     rSrcRect,
                                     const basegfx::B2IRange&     rDstRect, 
                                     DrawMode                     drawMode )
{
    OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );

    const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
    const basegfx::B2IRange   aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    basegfx::B2IRange         aSrcRange( rSrcRect );
    basegfx::B2IRange         aDestRange( rDstRect );

    if( clipAreaImpl( aDestRange,
                      aSrcRange,
                      mpImpl->maBounds,
                      aSrcBounds ))
    {
        assertImageRange(aDestRange,mpImpl->maBounds);
        assertImageRange(aSrcRange,aSrcBounds);

        drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode );
    }
}

void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
                                     const BitmapDeviceSharedPtr& rMask,
                                     const basegfx::B2IRange&     rSrcRect,
                                     const basegfx::B2IRange&     rDstRect, 
                                     DrawMode                     drawMode, 
                                     const BitmapDeviceSharedPtr& rClip )
{
    if( !rClip )
    {
        drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
        return;
    }

    OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );

    const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
    const basegfx::B2IRange   aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
    basegfx::B2IRange         aSrcRange( rSrcRect );
    basegfx::B2IRange         aDestRange( rDstRect );

    if( clipAreaImpl( aDestRange,
                      aSrcRange,
                      mpImpl->maBounds,
                      aSrcBounds ))
    {
        assertImageRange(aDestRange,mpImpl->maBounds);
        assertImageRange(aSrcRange,aSrcBounds);

        if( isCompatibleClipMask( rClip ) )
        {
            drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip );
        }
        else
        {
            getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect, 
                                                    rDstRect, drawMode, rClip );
        }
    }
}


//----------------------------------------------------------------------------------

/** Standard clip and alpha masks
 */
struct StdMasks
{
    typedef PixelFormatTraits_GREY1_MSB   clipmask_format_traits;
    typedef PixelFormatTraits_GREY8       alphamask_format_traits;

    /// Clipmask: 0 means opaque
    static const bool clipmask_polarity  = false;

    /// Alpha mask: 0 means fully transparent
    static const bool alphamask_polarity = true;
};

#if 0
/** Clip and alpha masks for the generic renderer (of course, those
    need to be generic, too)
 */
struct MaskTraitsGeneric
{
    typedef PixelFormatTraits_GenericInteger   clipmask_format_traits;
    typedef PixelFormatTraits_GenericInteger   alphamask_format_traits;
};
#endif

//----------------------------------------------------------------------------------

// Some compilers don't like the nested template wrap_accessor
// reference in the parameter list - being slightly less type safe,
// then.
#ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER

/// Produces a specialized renderer for the given pixel format
template< class FormatTraits, class MaskTraits >
BitmapDeviceSharedPtr createRenderer(
    const basegfx::B2IRange&                                     rBounds,
    sal_Int32                                                    nScanlineFormat,
    sal_Int32                                                    nScanlineStride,
    sal_uInt8*                                                   pFirstScanline,
    typename FormatTraits::raw_accessor_type const&              rRawAccessor,
    typename FormatTraits::accessor_selector::template wrap_accessor<
          typename FormatTraits::raw_accessor_type>::type const& rAccessor,
    boost::shared_array< sal_uInt8 >                             pMem,
    const PaletteMemorySharedVector&                             pPal )

#else

template< class FormatTraits, class MaskTraits, class Accessor >
BitmapDeviceSharedPtr createRenderer(
    const basegfx::B2IRange&                                     rBounds,
    sal_Int32                                                    nScanlineFormat,
    sal_Int32                                                    nScanlineStride,
    sal_uInt8*                                                   pFirstScanline,
    typename FormatTraits::raw_accessor_type const&              rRawAccessor,
    Accessor const&                                              rAccessor,
    boost::shared_array< sal_uInt8 >                             pMem,
    const PaletteMemorySharedVector&                             pPal )

#endif
{
    typedef typename FormatTraits::iterator_type                Iterator;
    typedef BitmapRenderer< Iterator,
                            typename FormatTraits::raw_accessor_type,
                            typename FormatTraits::accessor_selector,
                            MaskTraits >                        Renderer;

    return BitmapDeviceSharedPtr( 
        new Renderer( rBounds,
                      nScanlineFormat,
                      nScanlineStride,
                      pFirstScanline,
                      Iterator(
                          reinterpret_cast<typename Iterator::value_type*>(
                              pFirstScanline),
                          nScanlineStride),
                      rRawAccessor,
                      rAccessor,
                      pMem,
                      pPal ));
}

/// Create standard grey level palette
PaletteMemorySharedVector createStandardPalette( 
    const PaletteMemorySharedVector& pPal,
    sal_Int32                        nNumEntries )
{
    if( pPal || nNumEntries <= 0 )
        return pPal;

    boost::shared_ptr< std::vector<Color> > pLocalPal(
        new std::vector<Color>(nNumEntries) );
    
    const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries );
    --nNumEntries;
    for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement )
        pLocalPal->at(i) = Color(0xFF000000 | c);
    
    pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF);
    
    return pLocalPal;
}

template< class FormatTraits, class MaskTraits >
BitmapDeviceSharedPtr createRenderer(
    const basegfx::B2IRange&                rBounds,
    sal_Int32                               nScanlineFormat,
    sal_Int32                               nScanlineStride,
    sal_uInt8*                              pFirstScanline,
    boost::shared_array< sal_uInt8 >        pMem,
    const PaletteMemorySharedVector&        pPal )
{
    return createRenderer<FormatTraits,
                          MaskTraits>(rBounds,
                                      nScanlineFormat,
                                      nScanlineStride,
                                      pFirstScanline,
                                      typename FormatTraits::raw_accessor_type(),
                                      typename FormatTraits::accessor_selector::template
                                      wrap_accessor<
                                          typename FormatTraits::raw_accessor_type>::type(),
                                      pMem,
                                      pPal);
}

template< class FormatTraits, class MaskTraits >
BitmapDeviceSharedPtr createRenderer(
    const basegfx::B2IRange&                rBounds,
    sal_Int32                               nScanlineFormat,
    sal_Int32                               nScanlineStride,
    sal_uInt8*                              pFirstScanline,
    boost::shared_array< sal_uInt8 >        pMem,
    PaletteMemorySharedVector               pPal,
    int                                     nBitsPerPixel )
{
    pPal = createStandardPalette(pPal,
                                 1UL << nBitsPerPixel);

    OSL_ASSERT(pPal);
    return createRenderer<FormatTraits,
                          MaskTraits>(rBounds,
                                      nScanlineFormat,
                                      nScanlineStride,
                                      pFirstScanline,
                                      typename FormatTraits::raw_accessor_type(),
                                      typename FormatTraits::accessor_selector::template 
                                          wrap_accessor<
                                      typename FormatTraits::raw_accessor_type>::type(
                                          &pPal->at(0),
                                          pPal->size()),
                                      pMem,
                                      pPal);
}

//----------------------------------------------------------------------------------

// TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
// to o3tl or sal/bithacks.hxx ...

/** Compute the next highest power of 2 of a 32-bit value

	Code devised by Sean Anderson, in good ole HAKMEM
	tradition.

    @return 1 << (lg(x - 1) + 1)
*/
inline sal_uInt32 nextPow2( sal_uInt32 x )
{
    --x;
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;

    return ++x;
}

//----------------------------------------------------------------------------------

namespace
{
BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector&        rSize,
                                              bool                             bTopDown,
                                              sal_Int32                        nScanlineFormat,
                                              boost::shared_array< sal_uInt8 > pMem,
                                              PaletteMemorySharedVector        pPal,
                                              const basegfx::B2IRange*         pSubset )
{
    if( nScanlineFormat <= Format::NONE || 
        nScanlineFormat >  Format::MAX )
        return BitmapDeviceSharedPtr();

    static const sal_uInt8 bitsPerPixel[] = 
    {
        0,  // NONE                   
        1,  // ONE_BIT_MSB_GREY       
        1,  // ONE_BIT_LSB_GREY       
        1,  // ONE_BIT_MSB_PAL        
        1,  // ONE_BIT_LSB_PAL        
        4,  // FOUR_BIT_MSB_GREY      
        4,  // FOUR_BIT_LSB_GREY      
        4,  // FOUR_BIT_MSB_PAL       
        4,  // FOUR_BIT_LSB_PAL       
        8,  // EIGHT_BIT_PAL          
        8,  // EIGHT_BIT_GREY         
        16, // SIXTEEN_BIT_LSB_TC_MASK    
        16, // SIXTEEN_BIT_MSB_TC_MASK    
        24, // TWENTYFOUR_BIT_TC_MASK 
        32, // THIRTYTWO_BIT_TC_MASK  
        32, // THIRTYTWO_BIT_TC_MASK_ARGB
    };

    sal_Int32  nScanlineStride(0);

    // round up to full 8 bit, divide by 8
    nScanlineStride = (rSize.getX()*bitsPerPixel[nScanlineFormat] + 7) >> 3;

    // rounded up to next full power-of-two number of bytes
    const sal_uInt32 bytesPerPixel = nextPow2(
        (bitsPerPixel[nScanlineFormat] + 7) >> 3);

    // now make nScanlineStride a multiple of bytesPerPixel
    nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel;

    // factor in bottom-up scanline order case
    nScanlineStride *= bTopDown ? 1 : -1;

    const std::size_t nMemSize( 
        (nScanlineStride < 0 ? -nScanlineStride : nScanlineStride)*rSize.getY() );

    if( !pMem )
    {
        pMem.reset(
            reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
            &rtl_freeMemory );
        rtl_zeroMemory(pMem.get(),nMemSize);
    }

    sal_uInt8* pFirstScanline = nScanlineStride < 0 ? 
        pMem.get() + nMemSize + nScanlineStride : pMem.get();

    // shrink render area to given subset, if given
    basegfx::B2IRange aBounds(0,0,rSize.getX(),rSize.getY());
    if( pSubset )
        aBounds.intersect( *pSubset );

    switch( nScanlineFormat )
    {
        // ----------------------------------------------------------------------
        // one bit formats

        case Format::ONE_BIT_MSB_GREY:
            return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );

        case Format::ONE_BIT_LSB_GREY:
            return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );

        case Format::ONE_BIT_MSB_PAL:
            return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal,
                bitsPerPixel[nScanlineFormat] );

        case Format::ONE_BIT_LSB_PAL:
            return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal,
                bitsPerPixel[nScanlineFormat] );


        // ----------------------------------------------------------------------
        // four bit formats

        case Format::FOUR_BIT_MSB_GREY:
            return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );

        case Format::FOUR_BIT_LSB_GREY:
            return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );

        case Format::FOUR_BIT_MSB_PAL:
            return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal,
                bitsPerPixel[nScanlineFormat] );

        case Format::FOUR_BIT_LSB_PAL:
            return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal,
                bitsPerPixel[nScanlineFormat] );


        // ----------------------------------------------------------------------
        // eight bit formats

        case Format::EIGHT_BIT_GREY:
            return createRenderer<PixelFormatTraits_GREY8,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );

        case Format::EIGHT_BIT_PAL:
            return createRenderer<PixelFormatTraits_PAL8,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal,
                bitsPerPixel[nScanlineFormat] );


        // ----------------------------------------------------------------------
        // sixteen bit formats

        case Format::SIXTEEN_BIT_LSB_TC_MASK:
            return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );

        case Format::SIXTEEN_BIT_MSB_TC_MASK:
            return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );


        // ----------------------------------------------------------------------
        // twentyfour bit formats
        case Format::TWENTYFOUR_BIT_TC_MASK:
            return createRenderer<PixelFormatTraits_BGR24,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );


        // ----------------------------------------------------------------------
        // thirtytwo bit formats

        case Format::THIRTYTWO_BIT_TC_MASK:
            return createRenderer<PixelFormatTraits_RGB32_888,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );

        case Format::THIRTYTWO_BIT_TC_MASK_ARGB:
            return createRenderer<PixelFormatTraits_BGR32_888,StdMasks>(
                aBounds, nScanlineFormat, nScanlineStride,
                pFirstScanline, pMem, pPal );
    }

    // TODO(F3): other formats not yet implemented
    return BitmapDeviceSharedPtr();
}
} // namespace


BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
                                          bool                      bTopDown,
                                          sal_Int32                 nScanlineFormat )
{
    return createBitmapDeviceImpl( rSize, 
                                   bTopDown, 
                                   nScanlineFormat, 
                                   boost::shared_array< sal_uInt8 >(),
                                   PaletteMemorySharedVector(),
                                   NULL );
}

BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector&        rSize,
                                          bool                             bTopDown,
                                          sal_Int32                        nScanlineFormat,
                                          const PaletteMemorySharedVector& rPalette )
{
    return createBitmapDeviceImpl( rSize, 
                                   bTopDown, 
                                   nScanlineFormat, 
                                   boost::shared_array< sal_uInt8 >(),
                                   rPalette,
                                   NULL );
}

BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector&        rSize,
                                          bool                             bTopDown,
                                          sal_Int32                        nScanlineFormat,
                                          const RawMemorySharedArray&      rMem,
                                          const PaletteMemorySharedVector& rPalette )
{
    return createBitmapDeviceImpl( rSize, 
                                   bTopDown, 
                                   nScanlineFormat, 
                                   rMem,
                                   rPalette,
                                   NULL );
}

BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr&     rProto,
                                          const basegfx::B2IRange&         rSubset )
{
    return createBitmapDeviceImpl( rProto->getSize(),
                                   rProto->isTopDown(), 
                                   rProto->getScanlineFormat(), 
                                   rProto->getBuffer(),
                                   rProto->getPalette(),
                                   &rSubset );
}

BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector&        rSize,
                                         const BitmapDeviceSharedPtr&     rProto )
{
    return createBitmapDeviceImpl( rSize, 
                                   rProto->isTopDown(), 
                                   rProto->getScanlineFormat(), 
                                   boost::shared_array< sal_uInt8 >(),
                                   rProto->getPalette(),
                                   NULL );
}

//----------------------------------------------------------------------------------

/// Clone our device, with GenericImageAccessor to handle all formats
BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const
{
#if 0
    // xxx TODO
    typedef BitmapRenderer< PixelFormatTraits_GenericInteger::iterator_type,
                            PixelFormatTraits_GenericInteger::raw_accessor_type,
                            PixelFormatTraits_GenericInteger::accessor_selector,
                            MaskTraitsGeneric >                        
            Renderer;

    if( !mpImpl->mpGenericRenderer )
    {
        mpImpl->mpGenericRenderer.reset(
            new Renderer(
                mpImpl->maBounds, 
                isTopDown(), 
                getScanlineFormat(), 
                getScanlineStride(),
                mpImpl->mpFirstScanline,
                PixelFormatTraits_GenericInteger::iterator_type(),
                GenericIntegerImageRawAccessor<Color>(
                    const_cast<BitmapDevice*>(this)->shared_from_this()),
                GenericIntegerImageAccessor<Color>(
                    const_cast<BitmapDevice*>(this)->shared_from_this()),
                getBuffer(), 
                getPalette() ));
    }
#endif

    return mpImpl->mpGenericRenderer;
}

} // namespace basebmp
