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