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