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