1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "basebmp/bitmapdevice.hxx"
31 #include "basebmp/compositeiterator.hxx"
32 #include "basebmp/iteratortraits.hxx"
34 #include "basebmp/accessor.hxx"
35 #include "basebmp/accessortraits.hxx"
36 #include "basebmp/accessoradapters.hxx"
37 #include "basebmp/colorblendaccessoradapter.hxx"
39 #include "basebmp/color.hxx"
40 #include "basebmp/colormisc.hxx"
41 #include "basebmp/colortraits.hxx"
43 #include "basebmp/greylevelformats.hxx"
44 #include "basebmp/paletteformats.hxx"
45 #include "basebmp/rgbmaskpixelformats.hxx"
46 #include "basebmp/rgb24pixelformats.hxx"
48 #include "basebmp/scanlineformats.hxx"
49 #include "basebmp/fillimage.hxx"
50 #include "basebmp/scaleimage.hxx"
51 #include "basebmp/clippedlinerenderer.hxx"
52 #include "basebmp/polypolygonrenderer.hxx"
53 #include "basebmp/genericcolorimageaccessor.hxx"
55 #include "basebmp/tools.hxx"
56 #include "intconversion.hxx"
58 #include <rtl/alloc.h>
59 #include <rtl/memory.h>
60 #include <osl/diagnose.h>
62 #include <basegfx/tools/tools.hxx>
63 #include <basegfx/tools/canvastools.hxx>
64 #include <basegfx/range/b2ibox.hxx>
65 #include <basegfx/range/b2irange.hxx>
66 #include <basegfx/range/b2drange.hxx>
67 #include <basegfx/polygon/b2dpolygon.hxx>
68 #include <basegfx/polygon/b2dpolygontools.hxx>
69 #include <basegfx/polygon/b2dpolypolygontools.hxx>
70 #include <basegfx/point/b2ipoint.hxx>
71 #include <basegfx/vector/b2ivector.hxx>
73 #include <vigra/iteratortraits.hxx>
74 #include <vigra/rgbvalue.hxx>
75 #include <vigra/copyimage.hxx>
76 #include <vigra/tuple.hxx>
82 /// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
83 template< class Value
, unsigned int RedIndex
, unsigned int BlueIndex
, unsigned int GreenIndex
>
84 inline RGBValue
<Value
, RedIndex
, GreenIndex
, BlueIndex
>
85 operator^( RGBValue
<Value
, RedIndex
, GreenIndex
, BlueIndex
> const& lhs
,
86 RGBValue
<Value
, RedIndex
, GreenIndex
, BlueIndex
> const& rhs
)
88 RGBValue
<Value
, RedIndex
, GreenIndex
, BlueIndex
> res(
101 /** Create the type for an accessor that takes the (mask,bitmap)
102 input value generated from a JoinImageAccessorAdapter, and
103 pipe that through a mask functor.
106 Destination bitmap accessor
109 Input accessor, is expected to generate a std::pair as the
113 Either FastMask or NoFastMask, depending on whether the mask
114 is guaranteed to contain only 0s and 1s.
116 template< class DestAccessor
,
117 class JoinedAccessor
,
119 typename MaskFunctorMode
> struct masked_input_splitting_accessor
121 typedef BinarySetterFunctionAccessorAdapter
<
123 BinaryFunctorSplittingWrapper
<
124 typename outputMaskFunctorSelector
<
125 typename
JoinedAccessor::value_type::first_type
,
126 typename
JoinedAccessor::value_type::second_type
,
128 MaskFunctorMode
>::type
> > type
;
133 // Actual BitmapDevice implementation (templatized by accessor and iterator)
134 //--------------------------------------------------------------------------
136 /** Implementation of the BitmapDevice interface
139 Iterator to access bitmap memory
142 Raw accessor, to access pixel values directly
144 @tpl AccessorSelector
145 Accessor adapter selector, which, when applying the nested
146 template metafunction wrap_accessor to one of the raw bitmap
147 accessors, yields a member type named 'type', which is a
148 wrapped accessor that map color values.
151 Traits template, containing nested traits
152 clipmask_format_traits and alphamask_format_traits, which
153 determine what specialized formats are to be used for clip and
154 alpha masks. With those mask formats, clipping and alpha
155 blending is handled natively.
157 template< class DestIterator
,
159 class AccessorSelector
,
160 class Masks
> class BitmapRenderer
:
164 typedef DestIterator dest_iterator_type
;
165 typedef RawAccessor raw_accessor_type
;
166 typedef AccessorSelector accessor_selector
;
168 typedef typename
Masks::clipmask_format_traits::iterator_type mask_iterator_type
;
169 typedef typename
Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type
;
170 typedef typename
Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type
;
172 typedef typename
Masks::alphamask_format_traits::iterator_type alphamask_iterator_type
;
173 typedef typename
Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type
;
174 typedef typename
Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type
;
176 typedef typename
AccessorSelector::template wrap_accessor
<
177 raw_accessor_type
>::type dest_accessor_type
;
179 typedef AccessorTraits
< dest_accessor_type
> accessor_traits
;
180 typedef CompositeIterator2D
< dest_iterator_type
,
181 mask_iterator_type
> composite_iterator_type
;
182 typedef CompositeIterator2D
< vigra::Diff2D
,
183 vigra::Diff2D
> generic_composite_iterator_type
;
185 typedef BitmapRenderer
<mask_iterator_type
,
186 mask_rawaccessor_type
,
187 mask_accessorselector_type
,
188 Masks
> mask_bitmap_type
;
189 typedef BitmapRenderer
<alphamask_iterator_type
,
190 alphamask_rawaccessor_type
,
191 alphamask_accessorselector_type
,
192 Masks
> alphamask_bitmap_type
;
194 // -------------------------------------------------------
196 typedef AccessorTraits
< raw_accessor_type
> raw_accessor_traits
;
197 typedef typename uInt32Converter
<
198 typename
raw_accessor_type::value_type
>::to to_uint32_functor
;
200 // -------------------------------------------------------
202 typedef typename
raw_accessor_traits::xor_accessor raw_xor_accessor_type
;
203 typedef AccessorTraits
<raw_xor_accessor_type
> raw_xor_accessor_traits
;
204 typedef typename
accessor_selector::template wrap_accessor
<
205 raw_xor_accessor_type
>::type xor_accessor_type
;
206 typedef AccessorTraits
<xor_accessor_type
> xor_accessor_traits
;
208 // -------------------------------------------------------
210 typedef typename
raw_accessor_traits::template masked_accessor
<
211 mask_rawaccessor_type
,
214 Masks::clipmask_polarity
>::type raw_maskedaccessor_type
;
215 typedef typename
accessor_selector::template wrap_accessor
<
216 raw_maskedaccessor_type
>::type masked_accessor_type
;
217 typedef typename AccessorTraits
<
218 raw_maskedaccessor_type
>::xor_accessor raw_maskedxor_accessor_type
;
219 typedef typename
accessor_selector::template wrap_accessor
<
220 raw_maskedxor_accessor_type
>::type masked_xoraccessor_type
;
222 // -------------------------------------------------------
224 // ((iter,mask),mask) special case (e.g. for clipped
225 // drawMaskedColor())
226 typedef AccessorTraits
< raw_maskedaccessor_type
> raw_maskedaccessor_traits
;
227 typedef typename
raw_maskedaccessor_traits::template masked_accessor
<
228 mask_rawaccessor_type
,
229 composite_iterator_type
,
231 Masks::clipmask_polarity
>::type raw_maskedmask_accessor_type
;
233 typedef CompositeIterator2D
<
234 composite_iterator_type
,
235 mask_iterator_type
> composite_composite_mask_iterator_type
;
237 // -------------------------------------------------------
239 typedef ConstantColorBlendSetterAccessorAdapter
<
241 typename
alphamask_rawaccessor_type::value_type
,
242 Masks::alphamask_polarity
> colorblend_accessor_type
;
243 typedef AccessorTraits
<colorblend_accessor_type
> colorblend_accessor_traits
;
244 typedef typename
colorblend_accessor_traits::template masked_accessor
<
245 mask_rawaccessor_type
,
248 Masks::clipmask_polarity
>::type masked_colorblend_accessor_type
;
250 // -------------------------------------------------------
252 typedef ConstantColorBlendSetterAccessorAdapter
<
255 Masks::alphamask_polarity
> colorblend_generic_accessor_type
;
256 typedef AccessorTraits
<colorblend_generic_accessor_type
> colorblend_generic_accessor_traits
;
257 typedef typename
colorblend_generic_accessor_traits::template masked_accessor
<
258 mask_rawaccessor_type
,
261 Masks::clipmask_polarity
>::type masked_colorblend_generic_accessor_type
;
263 // -------------------------------------------------------
265 typedef JoinImageAccessorAdapter
< dest_accessor_type
,
266 mask_rawaccessor_type
> joined_image_accessor_type
;
267 typedef JoinImageAccessorAdapter
< GenericColorImageAccessor
,
268 GenericColorImageAccessor
> joined_generic_image_accessor_type
;
270 // -------------------------------------------------------
272 dest_iterator_type maBegin
;
273 typename
accessor_traits::color_lookup maColorLookup
;
274 IBitmapDeviceDamageTrackerSharedPtr mpDamage
;
275 to_uint32_functor maToUInt32Converter
;
276 dest_accessor_type maAccessor
;
277 colorblend_accessor_type maColorBlendAccessor
;
278 colorblend_generic_accessor_type maGenericColorBlendAccessor
;
279 raw_accessor_type maRawAccessor
;
280 xor_accessor_type maXorAccessor
;
281 raw_xor_accessor_type maRawXorAccessor
;
282 masked_accessor_type maMaskedAccessor
;
283 masked_colorblend_accessor_type maMaskedColorBlendAccessor
;
284 masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor
;
285 masked_xoraccessor_type maMaskedXorAccessor
;
286 raw_maskedaccessor_type maRawMaskedAccessor
;
287 raw_maskedxor_accessor_type maRawMaskedXorAccessor
;
288 raw_maskedmask_accessor_type maRawMaskedMaskAccessor
;
291 // -------------------------------------------------------
293 BitmapRenderer( const basegfx::B2IBox
& rBounds
,
294 sal_Int32 nScanlineFormat
,
295 sal_Int32 nScanlineStride
,
296 sal_uInt8
* pFirstScanline
,
297 dest_iterator_type begin
,
298 raw_accessor_type rawAccessor
,
299 dest_accessor_type accessor
,
300 const RawMemorySharedArray
& rMem
,
301 const PaletteMemorySharedVector
& rPalette
,
302 const IBitmapDeviceDamageTrackerSharedPtr
& rDamage
) :
303 BitmapDevice( rBounds
, nScanlineFormat
,
304 nScanlineStride
, pFirstScanline
, rMem
, rPalette
),
308 maToUInt32Converter(),
309 maAccessor( accessor
),
310 maColorBlendAccessor( accessor
),
311 maGenericColorBlendAccessor( accessor
),
312 maRawAccessor( rawAccessor
),
313 maXorAccessor( accessor
),
314 maRawXorAccessor( rawAccessor
),
315 maMaskedAccessor( accessor
),
316 maMaskedColorBlendAccessor( maColorBlendAccessor
),
317 maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor
),
318 maMaskedXorAccessor( accessor
),
319 maRawMaskedAccessor( rawAccessor
),
320 maRawMaskedXorAccessor( rawAccessor
),
321 maRawMaskedMaskAccessor( rawAccessor
)
326 void damaged( const basegfx::B2IBox
& rDamageRect
) const
329 mpDamage
->damaged( rDamageRect
);
332 void damagedPointSize( const basegfx::B2IPoint
& rPoint
,
333 const basegfx::B2IBox
& rSize
) const
336 basegfx::B2IPoint
aLower( rPoint
.getX() + rSize
.getWidth(),
337 rPoint
.getY() + rSize
.getHeight() );
338 damaged( basegfx::B2IBox( rPoint
, aLower
) );
342 void damagedPixel( const basegfx::B2IPoint
& rDamagePoint
) const
346 basegfx::B2IPoint
aEnd( rDamagePoint
.getX() + 1,
347 rDamagePoint
.getY() + 1 );
348 damaged( basegfx::B2IBox( rDamagePoint
, aEnd
) );
351 boost::shared_ptr
<BitmapRenderer
> getCompatibleBitmap( const BitmapDeviceSharedPtr
& bmp
) const
353 return boost::dynamic_pointer_cast
< BitmapRenderer
>( bmp
);
356 virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr
& bmp
) const
358 // TODO(P1): dynamic_cast usually called twice for
359 // compatible formats
360 return getCompatibleBitmap(bmp
).get() != NULL
;
363 boost::shared_ptr
<mask_bitmap_type
> getCompatibleClipMask( const BitmapDeviceSharedPtr
& bmp
) const
365 boost::shared_ptr
<mask_bitmap_type
> pMask( boost::dynamic_pointer_cast
<mask_bitmap_type
>( bmp
));
370 if( pMask
->getSize() != getSize() )
376 virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr
& bmp
) const
378 // TODO(P1): dynamic_cast usually called twice for
379 // compatible formats
380 return boost::dynamic_pointer_cast
<mask_bitmap_type
>( bmp
).get() != NULL
;
383 boost::shared_ptr
<alphamask_bitmap_type
> getCompatibleAlphaMask( const BitmapDeviceSharedPtr
& bmp
) const
385 return boost::dynamic_pointer_cast
<alphamask_bitmap_type
>( bmp
);
388 virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr
& bmp
) const
390 // TODO(P1): dynamic_cast usually called twice for
391 // compatible formats
392 return getCompatibleAlphaMask( bmp
).get() != NULL
;
395 virtual void clear_i( Color fillColor
,
396 const basegfx::B2IBox
& rBounds
)
398 fillImage(destIterRange(maBegin
,
407 virtual void setPixel_i( const basegfx::B2IPoint
& rPt
,
411 const DestIterator
pixel( maBegin
+
412 vigra::Diff2D(rPt
.getX(),
414 if( drawMode
== DrawMode_XOR
)
415 maXorAccessor
.set( pixelColor
,
418 maAccessor
.set( pixelColor
,
423 virtual void setPixel_i( const basegfx::B2IPoint
& rPt
,
426 const BitmapDeviceSharedPtr
& rClip
)
428 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rClip
) );
431 const vigra::Diff2D
offset(rPt
.getX(),
434 const composite_iterator_type
aIter(
436 pMask
->maBegin
+ offset
);
438 if( drawMode
== DrawMode_XOR
)
439 maMaskedXorAccessor
.set( pixelColor
,
442 maMaskedAccessor
.set( pixelColor
,
447 virtual Color
getPixel_i(const basegfx::B2IPoint
& rPt
)
449 const DestIterator
pixel( maBegin
+
450 vigra::Diff2D(rPt
.getX(),
452 return maAccessor(pixel
);
455 virtual sal_uInt32
getPixelData_i( const basegfx::B2IPoint
& rPt
)
457 const DestIterator
pixel( maBegin
+
458 vigra::Diff2D(rPt
.getX(),
460 return maToUInt32Converter(maRawAccessor(pixel
));
463 template< typename Iterator
, typename Col
, typename RawAcc
>
464 void implRenderLine2( const basegfx::B2IPoint
& rPt1
,
465 const basegfx::B2IPoint
& rPt2
,
466 const basegfx::B2IBox
& rBounds
,
468 const Iterator
& begin
,
469 const RawAcc
& rawAcc
)
471 renderClippedLine( rPt1
,
477 // TODO(P2): perhaps this needs pushing up the stack a bit
478 // to make more complex polygons more efficient ...
479 damaged( basegfx::B2IBox( rPt1
, rPt2
) );
482 template< typename Iterator
, typename Accessor
, typename RawAcc
>
483 void implRenderLine( const basegfx::B2IPoint
& rPt1
,
484 const basegfx::B2IPoint
& rPt2
,
485 const basegfx::B2IBox
& rBounds
,
487 const Iterator
& begin
,
489 const RawAcc
& rawAcc
)
491 implRenderLine2( rPt1
,rPt2
,rBounds
,
498 template< typename Iterator
, typename RawAcc
, typename XorAcc
>
499 void implDrawLine( const basegfx::B2IPoint
& rPt1
,
500 const basegfx::B2IPoint
& rPt2
,
501 const basegfx::B2IBox
& rBounds
,
503 const Iterator
& begin
,
504 const RawAcc
& rawAcc
,
505 const XorAcc
& xorAcc
,
508 if( drawMode
== DrawMode_XOR
)
509 implRenderLine( rPt1
, rPt2
, rBounds
, col
,
510 begin
, maAccessor
, xorAcc
);
512 implRenderLine( rPt1
, rPt2
, rBounds
, col
,
513 begin
, maAccessor
, rawAcc
);
516 virtual void drawLine_i(const basegfx::B2IPoint
& rPt1
,
517 const basegfx::B2IPoint
& rPt2
,
518 const basegfx::B2IBox
& rBounds
,
522 implDrawLine(rPt1
,rPt2
,rBounds
,lineColor
,
524 maRawAccessor
,maRawXorAccessor
,drawMode
);
527 composite_iterator_type
getMaskedIter( const BitmapDeviceSharedPtr
& rClip
) const
529 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rClip
) );
532 return composite_iterator_type( maBegin
,
536 virtual void drawLine_i(const basegfx::B2IPoint
& rPt1
,
537 const basegfx::B2IPoint
& rPt2
,
538 const basegfx::B2IBox
& rBounds
,
541 const BitmapDeviceSharedPtr
& rClip
)
543 implDrawLine(rPt1
,rPt2
,rBounds
,lineColor
,
544 getMaskedIter(rClip
),
546 maRawMaskedXorAccessor
,drawMode
);
549 template< typename Iterator
, typename RawAcc
>
550 void implDrawPolygon( const basegfx::B2DPolygon
& rPoly
,
551 const basegfx::B2IBox
& rBounds
,
553 const Iterator
& begin
,
556 basegfx::B2DPolygon
aPoly( rPoly
);
557 if( rPoly
.areControlPointsUsed() )
558 aPoly
= basegfx::tools::adaptiveSubdivideByCount( rPoly
);
560 const typename
dest_iterator_type::value_type
colorIndex( maColorLookup(
563 const sal_uInt32
nVertices( aPoly
.count() );
564 for( sal_uInt32 i
=1; i
<nVertices
; ++i
)
565 implRenderLine2( basegfx::fround(aPoly
.getB2DPoint(i
-1)),
566 basegfx::fround(aPoly
.getB2DPoint(i
)),
572 if( nVertices
> 1 && aPoly
.isClosed() )
573 implRenderLine2( basegfx::fround(aPoly
.getB2DPoint(nVertices
-1)),
574 basegfx::fround(aPoly
.getB2DPoint(0)),
581 virtual void drawPolygon_i(const basegfx::B2DPolygon
& rPoly
,
582 const basegfx::B2IBox
& rBounds
,
586 if( drawMode
== DrawMode_XOR
)
587 implDrawPolygon( rPoly
, rBounds
, lineColor
,
591 implDrawPolygon( rPoly
, rBounds
, lineColor
,
596 virtual void drawPolygon_i(const basegfx::B2DPolygon
& rPoly
,
597 const basegfx::B2IBox
& rBounds
,
600 const BitmapDeviceSharedPtr
& rClip
)
602 if( drawMode
== DrawMode_XOR
)
603 implDrawPolygon( rPoly
, rBounds
, lineColor
,
604 getMaskedIter(rClip
),
605 maRawMaskedXorAccessor
);
607 implDrawPolygon( rPoly
, rBounds
, lineColor
,
608 getMaskedIter(rClip
),
609 maRawMaskedAccessor
);
612 template< typename Iterator
, typename RawAcc
>
613 void implFillPolyPolygon( const basegfx::B2DPolyPolygon
& rPoly
,
615 const Iterator
& begin
,
617 const basegfx::B2IBox
& rBounds
)
619 basegfx::B2DPolyPolygon
aPoly( rPoly
);
620 if( rPoly
.areControlPointsUsed() )
621 aPoly
= basegfx::tools::adaptiveSubdivideByCount( rPoly
);
623 renderClippedPolyPolygon( begin
,
625 maColorLookup( maAccessor
,
629 basegfx::FillRule_EVEN_ODD
);
633 basegfx::B2DRange
const aPolyBounds( basegfx::tools::getRange(aPoly
) );
634 damaged( basegfx::unotools::b2ISurroundingBoxFromB2DRange( aPolyBounds
) );
638 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon
& rPoly
,
641 const basegfx::B2IBox
& rBounds
)
643 if( drawMode
== DrawMode_XOR
)
644 implFillPolyPolygon( rPoly
, fillColor
,
649 implFillPolyPolygon( rPoly
, fillColor
,
655 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon
& rPoly
,
658 const basegfx::B2IBox
& rBounds
,
659 const BitmapDeviceSharedPtr
& rClip
)
661 if( drawMode
== DrawMode_XOR
)
662 implFillPolyPolygon( rPoly
, fillColor
,
663 getMaskedIter(rClip
),
664 maRawMaskedXorAccessor
,
667 implFillPolyPolygon( rPoly
, fillColor
,
668 getMaskedIter(rClip
),
673 template< typename Iterator
, typename RawAcc
>
674 void implDrawBitmap(const BitmapDeviceSharedPtr
& rSrcBitmap
,
675 const basegfx::B2IBox
& rSrcRect
,
676 const basegfx::B2IBox
& rDstRect
,
677 const Iterator
& begin
,
680 boost::shared_ptr
<BitmapRenderer
> pSrcBmp( getCompatibleBitmap(rSrcBitmap
) );
681 OSL_ASSERT( pSrcBmp
);
684 srcIterRange(pSrcBmp
->maBegin
,
685 pSrcBmp
->maRawAccessor
,
690 rSrcBitmap
.get() == this );
694 template< typename Iterator
, typename Acc
>
695 void implDrawBitmapGeneric(const BitmapDeviceSharedPtr
& rSrcBitmap
,
696 const basegfx::B2IBox
& rSrcRect
,
697 const basegfx::B2IBox
& rDstRect
,
698 const Iterator
& begin
,
701 GenericColorImageAccessor
aSrcAcc( rSrcBitmap
);
704 srcIterRange(vigra::Diff2D(),
713 virtual void drawBitmap_i(const BitmapDeviceSharedPtr
& rSrcBitmap
,
714 const basegfx::B2IBox
& rSrcRect
,
715 const basegfx::B2IBox
& rDstRect
,
718 if( isCompatibleBitmap( rSrcBitmap
) )
720 if( drawMode
== DrawMode_XOR
)
721 implDrawBitmap(rSrcBitmap
, rSrcRect
, rDstRect
,
725 implDrawBitmap(rSrcBitmap
, rSrcRect
, rDstRect
,
731 if( drawMode
== DrawMode_XOR
)
732 implDrawBitmapGeneric(rSrcBitmap
, rSrcRect
, rDstRect
,
736 implDrawBitmapGeneric(rSrcBitmap
, rSrcRect
, rDstRect
,
743 virtual void drawBitmap_i(const BitmapDeviceSharedPtr
& rSrcBitmap
,
744 const basegfx::B2IBox
& rSrcRect
,
745 const basegfx::B2IBox
& rDstRect
,
747 const BitmapDeviceSharedPtr
& rClip
)
749 if( isCompatibleBitmap( rSrcBitmap
) )
751 if( drawMode
== DrawMode_XOR
)
752 implDrawBitmap(rSrcBitmap
, rSrcRect
, rDstRect
,
753 getMaskedIter(rClip
),
754 maRawMaskedXorAccessor
);
756 implDrawBitmap(rSrcBitmap
, rSrcRect
, rDstRect
,
757 getMaskedIter(rClip
),
758 maRawMaskedAccessor
);
762 if( drawMode
== DrawMode_XOR
)
763 implDrawBitmapGeneric(rSrcBitmap
, rSrcRect
, rDstRect
,
764 getMaskedIter(rClip
),
765 maMaskedXorAccessor
);
767 implDrawBitmapGeneric(rSrcBitmap
, rSrcRect
, rDstRect
,
768 getMaskedIter(rClip
),
774 virtual void drawMaskedColor_i(Color aSrcColor
,
775 const BitmapDeviceSharedPtr
& rAlphaMask
,
776 const basegfx::B2IBox
& rSrcRect
,
777 const basegfx::B2IPoint
& rDstPoint
)
779 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rAlphaMask
) );
780 boost::shared_ptr
<alphamask_bitmap_type
> pAlpha( getCompatibleAlphaMask(rAlphaMask
) );
784 maColorBlendAccessor
.setColor( aSrcColor
);
786 vigra::copyImage( srcIterRange(pAlpha
->maBegin
,
787 pAlpha
->maRawAccessor
,
790 maColorBlendAccessor
,
795 const composite_iterator_type
aBegin(
796 maBegin
+ vigra::Diff2D(rDstPoint
.getX(),
798 pMask
->maBegin
+ topLeft(rSrcRect
) );
801 aBegin
+ vigra::Diff2D(rSrcRect
.getWidth(),
802 rSrcRect
.getHeight()),
810 GenericColorImageAccessor
aSrcAcc( rAlphaMask
);
811 maGenericColorBlendAccessor
.setColor( aSrcColor
);
813 vigra::copyImage( srcIterRange(vigra::Diff2D(),
817 maGenericColorBlendAccessor
,
820 damagedPointSize( rDstPoint
, rSrcRect
);
823 virtual void drawMaskedColor_i(Color aSrcColor
,
824 const BitmapDeviceSharedPtr
& rAlphaMask
,
825 const basegfx::B2IBox
& rSrcRect
,
826 const basegfx::B2IPoint
& rDstPoint
,
827 const BitmapDeviceSharedPtr
& rClip
)
829 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rAlphaMask
) );
830 boost::shared_ptr
<alphamask_bitmap_type
> pAlpha( getCompatibleAlphaMask(rAlphaMask
) );
834 const composite_iterator_type
aBegin( getMaskedIter(rClip
) );
835 maMaskedColorBlendAccessor
.get1stWrappedAccessor().setColor(
838 vigra::copyImage( srcIterRange(pAlpha
->maBegin
,
839 pAlpha
->maRawAccessor
,
842 maMaskedColorBlendAccessor
,
847 boost::shared_ptr
<mask_bitmap_type
> pClipMask( getCompatibleClipMask(rClip
) );
848 OSL_ASSERT( pClipMask
);
850 // setup a ((iter,mask),clipMask) composite composite
851 // iterator, to pass both masks (clip and alpha mask)
853 const composite_composite_mask_iterator_type
aBegin(
854 composite_iterator_type(
855 maBegin
+ vigra::Diff2D(rDstPoint
.getX(),
857 pMask
->maBegin
+ topLeft(rSrcRect
)),
858 pClipMask
->maBegin
+ vigra::Diff2D(rDstPoint
.getX(),
862 aBegin
+ vigra::Diff2D(rSrcRect
.getWidth(),
863 rSrcRect
.getHeight()),
864 maRawMaskedMaskAccessor
,
871 GenericColorImageAccessor
aSrcAcc( rAlphaMask
);
872 const composite_iterator_type
aBegin( getMaskedIter(rClip
) );
873 maGenericMaskedColorBlendAccessor
.get1stWrappedAccessor().setColor(
876 vigra::copyImage( srcIterRange(vigra::Diff2D(),
880 maGenericMaskedColorBlendAccessor
,
883 damagedPointSize( rDstPoint
, rSrcRect
);
886 template< typename Iterator
, typename Acc
>
887 void implDrawMaskedBitmap(const BitmapDeviceSharedPtr
& rSrcBitmap
,
888 const BitmapDeviceSharedPtr
& rMask
,
889 const basegfx::B2IBox
& rSrcRect
,
890 const basegfx::B2IBox
& rDstRect
,
891 const Iterator
& begin
,
894 boost::shared_ptr
<BitmapRenderer
> pSrcBmp( getCompatibleBitmap(rSrcBitmap
) );
895 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rMask
) );
896 OSL_ASSERT( pMask
&& pSrcBmp
);
899 srcIterRange(composite_iterator_type(
902 joined_image_accessor_type(
904 pMask
->maRawAccessor
),
907 typename masked_input_splitting_accessor
<
909 joined_image_accessor_type
,
910 Masks::clipmask_polarity
,
911 FastMask
>::type(acc
),
913 rSrcBitmap
.get() == this);
917 template< typename Iterator
, typename Acc
>
918 void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr
& rSrcBitmap
,
919 const BitmapDeviceSharedPtr
& rMask
,
920 const basegfx::B2IBox
& rSrcRect
,
921 const basegfx::B2IBox
& rDstRect
,
922 const Iterator
& begin
,
925 GenericColorImageAccessor
aSrcAcc( rSrcBitmap
);
926 GenericColorImageAccessor
aMaskAcc( rMask
);
928 const vigra::Diff2D
aTopLeft(rSrcRect
.getMinX(),
930 const vigra::Diff2D
aBottomRight(rSrcRect
.getMaxX(),
934 generic_composite_iterator_type(
936 generic_composite_iterator_type(
937 aBottomRight
,aBottomRight
),
938 joined_generic_image_accessor_type(
942 typename masked_input_splitting_accessor
<
944 joined_generic_image_accessor_type
,
945 Masks::clipmask_polarity
,
946 NoFastMask
>::type(acc
),
951 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr
& rSrcBitmap
,
952 const BitmapDeviceSharedPtr
& rMask
,
953 const basegfx::B2IBox
& rSrcRect
,
954 const basegfx::B2IBox
& rDstRect
,
957 if( isCompatibleClipMask(rMask
) &&
958 isCompatibleBitmap(rSrcBitmap
) )
960 if( drawMode
== DrawMode_XOR
)
961 implDrawMaskedBitmap(rSrcBitmap
, rMask
,
966 implDrawMaskedBitmap(rSrcBitmap
, rMask
,
973 if( drawMode
== DrawMode_XOR
)
974 implDrawMaskedBitmapGeneric(rSrcBitmap
, rMask
,
979 implDrawMaskedBitmapGeneric(rSrcBitmap
, rMask
,
987 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr
& rSrcBitmap
,
988 const BitmapDeviceSharedPtr
& rMask
,
989 const basegfx::B2IBox
& rSrcRect
,
990 const basegfx::B2IBox
& rDstRect
,
992 const BitmapDeviceSharedPtr
& rClip
)
994 if( isCompatibleClipMask(rMask
) &&
995 isCompatibleBitmap(rSrcBitmap
) )
997 if( drawMode
== DrawMode_XOR
)
998 implDrawMaskedBitmap(rSrcBitmap
, rMask
,
1000 getMaskedIter(rClip
),
1001 maMaskedXorAccessor
);
1003 implDrawMaskedBitmap(rSrcBitmap
, rMask
,
1005 getMaskedIter(rClip
),
1010 if( drawMode
== DrawMode_XOR
)
1011 implDrawMaskedBitmapGeneric(rSrcBitmap
, rMask
,
1013 getMaskedIter(rClip
),
1014 maMaskedXorAccessor
);
1016 implDrawMaskedBitmapGeneric(rSrcBitmap
, rMask
,
1018 getMaskedIter(rClip
),
1021 damaged( rDstRect
);
1024 IBitmapDeviceDamageTrackerSharedPtr
getDamageTracker_i() const
1028 void setDamageTracker_i( const IBitmapDeviceDamageTrackerSharedPtr
& rDamage
)
1035 struct ImplBitmapDevice
1037 /** Bitmap memory plus deleter.
1039 Always points to the start of the mem
1041 RawMemorySharedArray mpMem
;
1043 /// Palette memory plus deleter (might be NULL)
1044 PaletteMemorySharedVector mpPalette
;
1046 /** Bounds of the device.
1048 maBounds.getWidth()/getHeight() yield the true size of the
1049 device (i.e. the rectangle given by maBounds covers the device
1050 area under the including-the-bottommost-and-rightmost-pixels
1053 basegfx::B2IBox maBounds
;
1055 /// Scanline format, as provided at the constructor
1056 sal_Int32 mnScanlineFormat
;
1058 /// Scanline stride. Negative for bottom-to-top formats
1059 sal_Int32 mnScanlineStride
;
1061 /// raw ptr to 0th scanline. used for cloning a generic renderer
1062 sal_uInt8
* mpFirstScanline
;
1064 /** (Optional) device sharing the same memory, and used for input
1065 clip masks/alpha masks/bitmaps that don't match our exact
1068 This is to avoid the combinatorical explosion when dealing
1069 with n bitmap formats, which could be combined with n clip
1070 masks, alpha masks and bitmap masks (yielding a total of n^4
1071 combinations). Since each BitmapRenderer is specialized for
1072 one specific combination of said formats, a lot of duplicate
1073 code would be generated, most of which probably never
1074 used. Therefore, only the most common combinations are
1075 specialized templates, the remainder gets handled by this
1076 generic renderer (via runtime polymorphism).
1078 BitmapDeviceSharedPtr mpGenericRenderer
;
1082 BitmapDevice::BitmapDevice( const basegfx::B2IBox
& rBounds
,
1083 sal_Int32 nScanlineFormat
,
1084 sal_Int32 nScanlineStride
,
1085 sal_uInt8
* pFirstScanline
,
1086 const RawMemorySharedArray
& rMem
,
1087 const PaletteMemorySharedVector
& rPalette
) :
1088 mpImpl( new ImplBitmapDevice
)
1090 mpImpl
->mpMem
= rMem
;
1091 mpImpl
->mpPalette
= rPalette
;
1092 mpImpl
->maBounds
= rBounds
;
1093 mpImpl
->mnScanlineFormat
= nScanlineFormat
;
1094 mpImpl
->mnScanlineStride
= nScanlineStride
;
1095 mpImpl
->mpFirstScanline
= pFirstScanline
;
1098 BitmapDevice::~BitmapDevice()
1100 // outline, because of internal ImplBitmapDevice
1103 basegfx::B2IVector
BitmapDevice::getSize() const
1105 return basegfx::B2IVector(
1106 mpImpl
->maBounds
.getMaxX() - mpImpl
->maBounds
.getMinX(),
1107 mpImpl
->maBounds
.getMaxY() - mpImpl
->maBounds
.getMinY() );
1110 bool BitmapDevice::isTopDown() const
1112 return mpImpl
->mnScanlineStride
>= 0;
1115 sal_Int32
BitmapDevice::getScanlineFormat() const
1117 return mpImpl
->mnScanlineFormat
;
1120 sal_Int32
BitmapDevice::getScanlineStride() const
1122 return mpImpl
->mnScanlineStride
< 0 ?
1123 -mpImpl
->mnScanlineStride
: mpImpl
->mnScanlineStride
;
1126 RawMemorySharedArray
BitmapDevice::getBuffer() const
1128 return mpImpl
->mpMem
;
1131 IBitmapDeviceDamageTrackerSharedPtr
BitmapDevice::getDamageTracker() const
1133 return getDamageTracker_i();
1136 void BitmapDevice::setDamageTracker( const IBitmapDeviceDamageTrackerSharedPtr
& rDamage
)
1138 setDamageTracker_i(rDamage
);
1141 PaletteMemorySharedVector
BitmapDevice::getPalette() const
1143 return mpImpl
->mpPalette
;
1146 void BitmapDevice::clear( Color fillColor
)
1148 clear_i( fillColor
, mpImpl
->maBounds
);
1151 void BitmapDevice::setPixel( const basegfx::B2IPoint
& rPt
,
1155 if( mpImpl
->maBounds
.isInside(rPt
) )
1156 setPixel_i(rPt
,lineColor
,drawMode
);
1159 void BitmapDevice::setPixel( const basegfx::B2IPoint
& rPt
,
1162 const BitmapDeviceSharedPtr
& rClip
)
1166 setPixel(rPt
,lineColor
,drawMode
);
1170 if( mpImpl
->maBounds
.isInside(rPt
) )
1172 if( isCompatibleClipMask( rClip
) )
1173 setPixel_i(rPt
,lineColor
,drawMode
,rClip
);
1175 getGenericRenderer()->setPixel( rPt
, lineColor
, drawMode
, rClip
);
1179 Color
BitmapDevice::getPixel( const basegfx::B2IPoint
& rPt
)
1181 if( mpImpl
->maBounds
.isInside(rPt
) )
1182 return getPixel_i(rPt
);
1187 sal_uInt32
BitmapDevice::getPixelData( const basegfx::B2IPoint
& rPt
)
1189 if( mpImpl
->maBounds
.isInside(rPt
) )
1190 return getPixelData_i(rPt
);
1195 void BitmapDevice::drawLine( const basegfx::B2IPoint
& rPt1
,
1196 const basegfx::B2IPoint
& rPt2
,
1207 void BitmapDevice::drawLine( const basegfx::B2IPoint
& rPt1
,
1208 const basegfx::B2IPoint
& rPt2
,
1211 const BitmapDeviceSharedPtr
& rClip
)
1215 drawLine(rPt1
,rPt2
,lineColor
,drawMode
);
1219 if( isCompatibleClipMask( rClip
) )
1227 getGenericRenderer()->drawLine( rPt1
, rPt2
, lineColor
,
1231 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon
& rPoly
,
1235 const sal_uInt32
numVertices( rPoly
.count() );
1237 drawPolygon_i( rPoly
,
1239 lineColor
, drawMode
);
1242 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon
& rPoly
,
1245 const BitmapDeviceSharedPtr
& rClip
)
1249 drawPolygon(rPoly
,lineColor
,drawMode
);
1253 const sal_uInt32
numVertices( rPoly
.count() );
1256 if( isCompatibleClipMask( rClip
) )
1257 drawPolygon_i( rPoly
,
1259 lineColor
, drawMode
, rClip
);
1261 getGenericRenderer()->drawPolygon( rPoly
, lineColor
,
1266 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon
& rPoly
,
1270 fillPolyPolygon_i( rPoly
, fillColor
, drawMode
, mpImpl
->maBounds
);
1273 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon
& rPoly
,
1276 const BitmapDeviceSharedPtr
& rClip
)
1280 fillPolyPolygon(rPoly
,fillColor
,drawMode
);
1284 if( isCompatibleClipMask( rClip
) )
1285 fillPolyPolygon_i( rPoly
, fillColor
, drawMode
, mpImpl
->maBounds
, rClip
);
1287 getGenericRenderer()->fillPolyPolygon( rPoly
, fillColor
,
1294 void assertImagePoint( const basegfx::B2IPoint
& rPt
,
1295 const basegfx::B2IBox
& rPermittedRange
)
1297 (void)rPt
; (void)rPermittedRange
;
1298 OSL_ASSERT( rPermittedRange
.isInside(rPt
) );
1301 void assertImageRange( const basegfx::B2IBox
& rRange
,
1302 const basegfx::B2IBox
& rPermittedRange
)
1304 #if OSL_DEBUG_LEVEL > 0
1305 basegfx::B2IBox
aRange( rRange
);
1306 aRange
.intersect( rPermittedRange
);
1308 OSL_ASSERT( aRange
== rRange
);
1310 (void)rRange
; (void)rPermittedRange
;
1314 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1315 // to basegfx, and use here!
1316 bool clipAreaImpl( ::basegfx::B2IBox
& io_rSourceArea
,
1317 ::basegfx::B2IPoint
& io_rDestPoint
,
1318 const ::basegfx::B2IBox
& rSourceBounds
,
1319 const ::basegfx::B2IBox
& rDestBounds
)
1321 const ::basegfx::B2IPoint
aSourceTopLeft(
1322 io_rSourceArea
.getMinimum() );
1324 ::basegfx::B2IBox
aLocalSourceArea( io_rSourceArea
);
1326 // clip source area (which must be inside rSourceBounds)
1327 aLocalSourceArea
.intersect( rSourceBounds
);
1329 if( aLocalSourceArea
.isEmpty() )
1332 // calc relative new source area points (relative to orig
1334 const ::basegfx::B2IVector
aUpperLeftOffset(
1335 aLocalSourceArea
.getMinimum()-aSourceTopLeft
);
1336 const ::basegfx::B2IVector
aLowerRightOffset(
1337 aLocalSourceArea
.getMaximum()-aSourceTopLeft
);
1339 ::basegfx::B2IBox
aLocalDestArea( io_rDestPoint
+ aUpperLeftOffset
,
1340 io_rDestPoint
+ aLowerRightOffset
);
1342 // clip dest area (which must be inside rDestBounds)
1343 aLocalDestArea
.intersect( rDestBounds
);
1345 if( aLocalDestArea
.isEmpty() )
1348 // calc relative new dest area points (relative to orig
1350 const ::basegfx::B2IVector
aDestUpperLeftOffset(
1351 aLocalDestArea
.getMinimum()-io_rDestPoint
);
1352 const ::basegfx::B2IVector
aDestLowerRightOffset(
1353 aLocalDestArea
.getMaximum()-io_rDestPoint
);
1355 io_rSourceArea
= ::basegfx::B2IBox( aSourceTopLeft
+ aDestUpperLeftOffset
,
1356 aSourceTopLeft
+ aDestLowerRightOffset
);
1357 io_rDestPoint
= aLocalDestArea
.getMinimum();
1362 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1363 // to basegfx, and use here!
1364 bool clipAreaImpl( ::basegfx::B2IBox
& io_rDestArea
,
1365 ::basegfx::B2IBox
& io_rSourceArea
,
1366 const ::basegfx::B2IBox
& rDestBounds
,
1367 const ::basegfx::B2IBox
& rSourceBounds
)
1369 // extract inherent scale
1370 const double nScaleX( io_rDestArea
.getWidth() / (double)io_rSourceArea
.getWidth() );
1371 const double nScaleY( io_rDestArea
.getHeight() / (double)io_rSourceArea
.getHeight() );
1373 // extract range origins
1374 const basegfx::B2IPoint
aDestTopLeft(
1375 io_rDestArea
.getMinimum() );
1376 const ::basegfx::B2IPoint
aSourceTopLeft(
1377 io_rSourceArea
.getMinimum() );
1379 ::basegfx::B2IBox
aLocalSourceArea( io_rSourceArea
);
1381 // clip source area (which must be inside rSourceBounds)
1382 aLocalSourceArea
.intersect( rSourceBounds
);
1384 if( aLocalSourceArea
.isEmpty() )
1387 // calc relative new source area points (relative to orig
1389 const ::basegfx::B2IVector
aUpperLeftOffset(
1390 aLocalSourceArea
.getMinimum()-aSourceTopLeft
);
1391 const ::basegfx::B2IVector
aLowerRightOffset(
1392 aLocalSourceArea
.getMaximum()-aSourceTopLeft
);
1394 ::basegfx::B2IBox
aLocalDestArea( basegfx::fround(aDestTopLeft
.getX() + nScaleX
*aUpperLeftOffset
.getX()),
1395 basegfx::fround(aDestTopLeft
.getY() + nScaleY
*aUpperLeftOffset
.getY()),
1396 basegfx::fround(aDestTopLeft
.getX() + nScaleX
*aLowerRightOffset
.getX()),
1397 basegfx::fround(aDestTopLeft
.getY() + nScaleY
*aLowerRightOffset
.getY()) );
1399 // clip dest area (which must be inside rDestBounds)
1400 aLocalDestArea
.intersect( rDestBounds
);
1402 if( aLocalDestArea
.isEmpty() )
1405 // calc relative new dest area points (relative to orig
1407 const ::basegfx::B2IVector
aDestUpperLeftOffset(
1408 aLocalDestArea
.getMinimum()-aDestTopLeft
);
1409 const ::basegfx::B2IVector
aDestLowerRightOffset(
1410 aLocalDestArea
.getMaximum()-aDestTopLeft
);
1412 io_rSourceArea
= ::basegfx::B2IBox( basegfx::fround(aSourceTopLeft
.getX() + aDestUpperLeftOffset
.getX()/nScaleX
),
1413 basegfx::fround(aSourceTopLeft
.getY() + aDestUpperLeftOffset
.getY()/nScaleY
),
1414 basegfx::fround(aSourceTopLeft
.getX() + aDestLowerRightOffset
.getX()/nScaleX
),
1415 basegfx::fround(aSourceTopLeft
.getY() + aDestLowerRightOffset
.getY()/nScaleY
) );
1416 io_rDestArea
= aLocalDestArea
;
1418 // final source area clip (chopping round-offs)
1419 io_rSourceArea
.intersect( rSourceBounds
);
1421 if( io_rSourceArea
.isEmpty() )
1429 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr
& rSrcBitmap
,
1430 const basegfx::B2IBox
& rSrcRect
,
1431 const basegfx::B2IBox
& rDstRect
,
1434 const basegfx::B2IVector
& rSrcSize( rSrcBitmap
->getSize() );
1435 const basegfx::B2IBox
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1436 basegfx::B2IBox
aSrcRange( rSrcRect
);
1437 basegfx::B2IBox
aDestRange( rDstRect
);
1439 if( clipAreaImpl( aDestRange
,
1444 assertImageRange(aDestRange
,mpImpl
->maBounds
);
1445 assertImageRange(aSrcRange
,aSrcBounds
);
1447 drawBitmap_i( rSrcBitmap
, aSrcRange
, aDestRange
, drawMode
);
1451 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr
& rSrcBitmap
,
1452 const basegfx::B2IBox
& rSrcRect
,
1453 const basegfx::B2IBox
& rDstRect
,
1455 const BitmapDeviceSharedPtr
& rClip
)
1459 drawBitmap(rSrcBitmap
,rSrcRect
,rDstRect
,drawMode
);
1463 const basegfx::B2IVector
& rSrcSize( rSrcBitmap
->getSize() );
1464 const basegfx::B2IBox
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1465 basegfx::B2IBox
aSrcRange( rSrcRect
);
1466 basegfx::B2IBox
aDestRange( rDstRect
);
1468 if( clipAreaImpl( aDestRange
,
1473 assertImageRange(aDestRange
,mpImpl
->maBounds
);
1474 assertImageRange(aSrcRange
,aSrcBounds
);
1476 if( isCompatibleClipMask( rClip
) )
1478 drawBitmap_i( rSrcBitmap
, aSrcRange
, aDestRange
, drawMode
, rClip
);
1482 getGenericRenderer()->drawBitmap( rSrcBitmap
, rSrcRect
,
1483 rDstRect
, drawMode
, rClip
);
1488 void BitmapDevice::drawMaskedColor( Color aSrcColor
,
1489 const BitmapDeviceSharedPtr
& rAlphaMask
,
1490 const basegfx::B2IBox
& rSrcRect
,
1491 const basegfx::B2IPoint
& rDstPoint
)
1493 const basegfx::B2IVector
& rSrcSize( rAlphaMask
->getSize() );
1494 const basegfx::B2IBox
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1495 basegfx::B2IBox
aSrcRange( rSrcRect
);
1496 basegfx::B2IPoint
aDestPoint( rDstPoint
);
1498 if( clipAreaImpl( aSrcRange
,
1503 assertImagePoint(aDestPoint
,mpImpl
->maBounds
);
1504 assertImageRange(aSrcRange
,aSrcBounds
);
1506 if( rAlphaMask
.get() == this )
1508 // src == dest, copy rAlphaMask beforehand
1509 // ---------------------------------------------------
1511 const basegfx::B2ITuple
aSize( aSrcRange
.getWidth(),
1512 aSrcRange
.getHeight() );
1513 BitmapDeviceSharedPtr
pAlphaCopy(
1514 cloneBitmapDevice( aSize
,
1515 shared_from_this()) );
1516 basegfx::B2ITuple aGcc3WorkaroundTemporary
;
1517 const basegfx::B2IBox
aAlphaRange( aGcc3WorkaroundTemporary
,
1519 pAlphaCopy
->drawBitmap(rAlphaMask
,
1523 drawMaskedColor_i( aSrcColor
, pAlphaCopy
, aAlphaRange
, aDestPoint
);
1527 drawMaskedColor_i( aSrcColor
, rAlphaMask
, aSrcRange
, aDestPoint
);
1532 void BitmapDevice::drawMaskedColor( Color aSrcColor
,
1533 const BitmapDeviceSharedPtr
& rAlphaMask
,
1534 const basegfx::B2IBox
& rSrcRect
,
1535 const basegfx::B2IPoint
& rDstPoint
,
1536 const BitmapDeviceSharedPtr
& rClip
)
1540 drawMaskedColor(aSrcColor
,rAlphaMask
,rSrcRect
,rDstPoint
);
1544 const basegfx::B2IVector
& rSrcSize( rAlphaMask
->getSize() );
1545 const basegfx::B2IBox
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1546 basegfx::B2IBox
aSrcRange( rSrcRect
);
1547 basegfx::B2IPoint
aDestPoint( rDstPoint
);
1549 if( clipAreaImpl( aSrcRange
,
1554 assertImagePoint(aDestPoint
,mpImpl
->maBounds
);
1555 assertImageRange(aSrcRange
,aSrcBounds
);
1557 if( isCompatibleClipMask( rClip
) )
1559 if( rAlphaMask
.get() == this )
1561 // src == dest, copy rAlphaMask beforehand
1562 // ---------------------------------------------------
1564 const basegfx::B2ITuple
aSize( aSrcRange
.getWidth(),
1565 aSrcRange
.getHeight() );
1566 BitmapDeviceSharedPtr
pAlphaCopy(
1567 cloneBitmapDevice( aSize
,
1568 shared_from_this()) );
1569 basegfx::B2ITuple aGcc3WorkaroundTemporary
;
1570 const basegfx::B2IBox
aAlphaRange( aGcc3WorkaroundTemporary
,
1572 pAlphaCopy
->drawBitmap(rAlphaMask
,
1576 drawMaskedColor_i( aSrcColor
, pAlphaCopy
, aAlphaRange
, aDestPoint
, rClip
);
1580 drawMaskedColor_i( aSrcColor
, rAlphaMask
, aSrcRange
, aDestPoint
, rClip
);
1585 getGenericRenderer()->drawMaskedColor( aSrcColor
, rAlphaMask
,
1586 rSrcRect
, rDstPoint
, rClip
);
1591 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr
& rSrcBitmap
,
1592 const BitmapDeviceSharedPtr
& rMask
,
1593 const basegfx::B2IBox
& rSrcRect
,
1594 const basegfx::B2IBox
& rDstRect
,
1597 OSL_ASSERT( rMask
->getSize() == rSrcBitmap
->getSize() );
1599 const basegfx::B2IVector
& rSrcSize( rSrcBitmap
->getSize() );
1600 const basegfx::B2IBox
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1601 basegfx::B2IBox
aSrcRange( rSrcRect
);
1602 basegfx::B2IBox
aDestRange( rDstRect
);
1604 if( clipAreaImpl( aDestRange
,
1609 assertImageRange(aDestRange
,mpImpl
->maBounds
);
1610 assertImageRange(aSrcRange
,aSrcBounds
);
1612 drawMaskedBitmap_i( rSrcBitmap
, rMask
, aSrcRange
, aDestRange
, drawMode
);
1616 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr
& rSrcBitmap
,
1617 const BitmapDeviceSharedPtr
& rMask
,
1618 const basegfx::B2IBox
& rSrcRect
,
1619 const basegfx::B2IBox
& rDstRect
,
1621 const BitmapDeviceSharedPtr
& rClip
)
1625 drawMaskedBitmap(rSrcBitmap
,rMask
,rSrcRect
,rDstRect
,drawMode
);
1629 OSL_ASSERT( rMask
->getSize() == rSrcBitmap
->getSize() );
1631 const basegfx::B2IVector
& rSrcSize( rSrcBitmap
->getSize() );
1632 const basegfx::B2IBox
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1633 basegfx::B2IBox
aSrcRange( rSrcRect
);
1634 basegfx::B2IBox
aDestRange( rDstRect
);
1636 if( clipAreaImpl( aDestRange
,
1641 assertImageRange(aDestRange
,mpImpl
->maBounds
);
1642 assertImageRange(aSrcRange
,aSrcBounds
);
1644 if( isCompatibleClipMask( rClip
) )
1646 drawMaskedBitmap_i( rSrcBitmap
, rMask
, aSrcRange
, aDestRange
, drawMode
, rClip
);
1650 getGenericRenderer()->drawMaskedBitmap( rSrcBitmap
, rMask
, rSrcRect
,
1651 rDstRect
, drawMode
, rClip
);
1657 //----------------------------------------------------------------------------------
1659 /** Standard clip and alpha masks
1663 typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits
;
1664 typedef PixelFormatTraits_GREY8 alphamask_format_traits
;
1666 /// Clipmask: 0 means opaque
1667 static const bool clipmask_polarity
= false;
1669 /// Alpha mask: 0 means fully transparent
1670 static const bool alphamask_polarity
= true;
1673 //----------------------------------------------------------------------------------
1675 // Some compilers don't like the nested template wrap_accessor
1676 // reference in the parameter list - being slightly less type safe,
1678 #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
1680 /// Produces a specialized renderer for the given pixel format
1681 template< class FormatTraits
, class MaskTraits
>
1682 BitmapDeviceSharedPtr
createRenderer(
1683 const basegfx::B2IBox
& rBounds
,
1684 sal_Int32 nScanlineFormat
,
1685 sal_Int32 nScanlineStride
,
1686 sal_uInt8
* pFirstScanline
,
1687 typename
FormatTraits::raw_accessor_type
const& rRawAccessor
,
1688 typename
FormatTraits::accessor_selector::template wrap_accessor
<
1689 typename
FormatTraits::raw_accessor_type
>::type
const& rAccessor
,
1690 boost::shared_array
< sal_uInt8
> pMem
,
1691 const PaletteMemorySharedVector
& pPal
,
1692 const IBitmapDeviceDamageTrackerSharedPtr
& pDamage
)
1695 template< class FormatTraits
, class MaskTraits
, class Accessor
>
1696 BitmapDeviceSharedPtr
createRenderer(
1697 const basegfx::B2IBox
& rBounds
,
1698 sal_Int32 nScanlineFormat
,
1699 sal_Int32 nScanlineStride
,
1700 sal_uInt8
* pFirstScanline
,
1701 typename
FormatTraits::raw_accessor_type
const& rRawAccessor
,
1702 Accessor
const& rAccessor
,
1703 boost::shared_array
< sal_uInt8
> pMem
,
1704 const PaletteMemorySharedVector
& pPal
,
1705 const IBitmapDeviceDamageTrackerSharedPtr
& pDamage
)
1709 typedef typename
FormatTraits::iterator_type Iterator
;
1710 typedef BitmapRenderer
< Iterator
,
1711 typename
FormatTraits::raw_accessor_type
,
1712 typename
FormatTraits::accessor_selector
,
1713 MaskTraits
> Renderer
;
1715 return BitmapDeviceSharedPtr(
1716 new Renderer( rBounds
,
1721 reinterpret_cast<typename
Iterator::value_type
*>(
1731 /// Create standard grey level palette
1732 PaletteMemorySharedVector
createStandardPalette(
1733 const PaletteMemorySharedVector
& pPal
,
1734 sal_Int32 nNumEntries
)
1736 if( pPal
|| nNumEntries
<= 0 )
1739 boost::shared_ptr
< std::vector
<Color
> > pLocalPal(
1740 new std::vector
<Color
>(nNumEntries
) );
1742 const sal_Int32
nIncrement( 0x00FFFFFF/nNumEntries
);
1744 for( sal_Int32 i
=0, c
=0; i
<nNumEntries
; ++i
,c
+=nIncrement
)
1745 pLocalPal
->at(i
) = Color(0xFF000000 | c
);
1747 pLocalPal
->at(nNumEntries
) = Color(0xFFFFFFFF);
1752 template< class FormatTraits
, class MaskTraits
>
1753 BitmapDeviceSharedPtr
createRenderer(
1754 const basegfx::B2IBox
& rBounds
,
1755 sal_Int32 nScanlineFormat
,
1756 sal_Int32 nScanlineStride
,
1757 sal_uInt8
* pFirstScanline
,
1758 boost::shared_array
< sal_uInt8
> pMem
,
1759 const PaletteMemorySharedVector
& pPal
,
1760 const IBitmapDeviceDamageTrackerSharedPtr
& pDamage
)
1762 return createRenderer
<FormatTraits
,
1763 MaskTraits
>(rBounds
,
1767 typename
FormatTraits::raw_accessor_type(),
1768 typename
FormatTraits::accessor_selector::template
1770 typename
FormatTraits::raw_accessor_type
>::type(),
1776 template< class FormatTraits
, class MaskTraits
>
1777 BitmapDeviceSharedPtr
createRenderer(
1778 const basegfx::B2IBox
& rBounds
,
1779 sal_Int32 nScanlineFormat
,
1780 sal_Int32 nScanlineStride
,
1781 sal_uInt8
* pFirstScanline
,
1782 boost::shared_array
< sal_uInt8
> pMem
,
1783 PaletteMemorySharedVector pPal
,
1785 const IBitmapDeviceDamageTrackerSharedPtr
& pDamage
)
1787 pPal
= createStandardPalette(pPal
,
1788 1UL << nBitsPerPixel
);
1791 return createRenderer
<FormatTraits
,
1792 MaskTraits
>(rBounds
,
1796 typename
FormatTraits::raw_accessor_type(),
1797 typename
FormatTraits::accessor_selector::template
1799 typename
FormatTraits::raw_accessor_type
>::type(
1807 //----------------------------------------------------------------------------------
1809 // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
1810 // to o3tl or sal/bithacks.hxx ...
1812 /** Compute the next highest power of 2 of a 32-bit value
1814 Code devised by Sean Anderson, in good ole HAKMEM
1817 @return 1 << (lg(x - 1) + 1)
1819 inline sal_uInt32
nextPow2( sal_uInt32 x
)
1831 //----------------------------------------------------------------------------------
1835 BitmapDeviceSharedPtr
createBitmapDeviceImpl( const basegfx::B2IVector
& rSize
,
1837 sal_Int32 nScanlineFormat
,
1838 boost::shared_array
< sal_uInt8
> pMem
,
1839 PaletteMemorySharedVector pPal
,
1840 const basegfx::B2IBox
* pSubset
,
1841 const IBitmapDeviceDamageTrackerSharedPtr
& rDamage
)
1843 OSL_ASSERT(rSize
.getX() > 0 && rSize
.getY() > 0);
1845 if( nScanlineFormat
<= Format::NONE
||
1846 nScanlineFormat
> Format::MAX
)
1847 return BitmapDeviceSharedPtr();
1849 static const sal_uInt8 bitsPerPixel
[] =
1852 1, // ONE_BIT_MSB_GREY
1853 1, // ONE_BIT_LSB_GREY
1854 1, // ONE_BIT_MSB_PAL
1855 1, // ONE_BIT_LSB_PAL
1856 4, // FOUR_BIT_MSB_GREY
1857 4, // FOUR_BIT_LSB_GREY
1858 4, // FOUR_BIT_MSB_PAL
1859 4, // FOUR_BIT_LSB_PAL
1861 8, // EIGHT_BIT_GREY
1862 16, // SIXTEEN_BIT_LSB_TC_MASK
1863 16, // SIXTEEN_BIT_MSB_TC_MASK
1864 24, // TWENTYFOUR_BIT_TC_MASK
1865 32, // THIRTYTWO_BIT_TC_MASK
1866 32, // THIRTYTWO_BIT_TC_MASK_ARGB
1869 sal_Int32
nScanlineStride(0);
1871 // round up to full 8 bit, divide by 8
1872 nScanlineStride
= (rSize
.getX()*bitsPerPixel
[nScanlineFormat
] + 7) >> 3;
1874 // rounded up to next full power-of-two number of bytes
1875 const sal_uInt32 bytesPerPixel
= nextPow2(
1876 (bitsPerPixel
[nScanlineFormat
] + 7) >> 3);
1878 // now make nScanlineStride a multiple of bytesPerPixel
1879 nScanlineStride
= (nScanlineStride
+ bytesPerPixel
- 1) / bytesPerPixel
* bytesPerPixel
;
1881 // factor in bottom-up scanline order case
1882 nScanlineStride
*= bTopDown
? 1 : -1;
1884 const sal_uInt32
nWidth(nScanlineStride
< 0 ? -nScanlineStride
: nScanlineStride
);
1885 const sal_uInt32
nHeight(rSize
.getY());
1887 if (nHeight
&& nWidth
&& nWidth
> SAL_MAX_INT32
/ nHeight
)
1889 SAL_WARN( "basebmp", "suspicious massive alloc " << nWidth
<< " * " << nHeight
);
1890 return BitmapDeviceSharedPtr();
1893 const std::size_t nMemSize(nWidth
* nHeight
);
1898 reinterpret_cast<sal_uInt8
*>(rtl_allocateMemory( nMemSize
)),
1900 if (pMem
.get() == 0 && nMemSize
!= 0)
1901 return BitmapDeviceSharedPtr();
1902 rtl_zeroMemory(pMem
.get(),nMemSize
);
1905 sal_uInt8
* pFirstScanline
= nScanlineStride
< 0 ?
1906 pMem
.get() + nMemSize
+ nScanlineStride
: pMem
.get();
1908 // shrink render area to given subset, if given
1909 basegfx::B2IBox
aBounds(0,0,rSize
.getX(),rSize
.getY());
1911 aBounds
.intersect( *pSubset
);
1913 switch( nScanlineFormat
)
1915 // ----------------------------------------------------------------------
1918 case Format::ONE_BIT_MSB_GREY
:
1919 return createRenderer
<PixelFormatTraits_GREY1_MSB
,StdMasks
>(
1920 aBounds
, nScanlineFormat
, nScanlineStride
,
1921 pFirstScanline
, pMem
, pPal
, rDamage
);
1923 case Format::ONE_BIT_LSB_GREY
:
1924 return createRenderer
<PixelFormatTraits_GREY1_LSB
,StdMasks
>(
1925 aBounds
, nScanlineFormat
, nScanlineStride
,
1926 pFirstScanline
, pMem
, pPal
, rDamage
);
1928 case Format::ONE_BIT_MSB_PAL
:
1929 return createRenderer
<PixelFormatTraits_PAL1_MSB
,StdMasks
>(
1930 aBounds
, nScanlineFormat
, nScanlineStride
,
1931 pFirstScanline
, pMem
, pPal
,
1932 bitsPerPixel
[nScanlineFormat
], rDamage
);
1934 case Format::ONE_BIT_LSB_PAL
:
1935 return createRenderer
<PixelFormatTraits_PAL1_LSB
,StdMasks
>(
1936 aBounds
, nScanlineFormat
, nScanlineStride
,
1937 pFirstScanline
, pMem
, pPal
,
1938 bitsPerPixel
[nScanlineFormat
], rDamage
);
1941 // ----------------------------------------------------------------------
1944 case Format::FOUR_BIT_MSB_GREY
:
1945 return createRenderer
<PixelFormatTraits_GREY4_MSB
,StdMasks
>(
1946 aBounds
, nScanlineFormat
, nScanlineStride
,
1947 pFirstScanline
, pMem
, pPal
, rDamage
);
1949 case Format::FOUR_BIT_LSB_GREY
:
1950 return createRenderer
<PixelFormatTraits_GREY4_LSB
,StdMasks
>(
1951 aBounds
, nScanlineFormat
, nScanlineStride
,
1952 pFirstScanline
, pMem
, pPal
, rDamage
);
1954 case Format::FOUR_BIT_MSB_PAL
:
1955 return createRenderer
<PixelFormatTraits_PAL4_MSB
,StdMasks
>(
1956 aBounds
, nScanlineFormat
, nScanlineStride
,
1957 pFirstScanline
, pMem
, pPal
,
1958 bitsPerPixel
[nScanlineFormat
], rDamage
);
1960 case Format::FOUR_BIT_LSB_PAL
:
1961 return createRenderer
<PixelFormatTraits_PAL4_LSB
,StdMasks
>(
1962 aBounds
, nScanlineFormat
, nScanlineStride
,
1963 pFirstScanline
, pMem
, pPal
,
1964 bitsPerPixel
[nScanlineFormat
], rDamage
);
1967 // ----------------------------------------------------------------------
1968 // eight bit formats
1970 case Format::EIGHT_BIT_GREY
:
1971 return createRenderer
<PixelFormatTraits_GREY8
,StdMasks
>(
1972 aBounds
, nScanlineFormat
, nScanlineStride
,
1973 pFirstScanline
, pMem
, pPal
, rDamage
);
1975 case Format::EIGHT_BIT_PAL
:
1976 return createRenderer
<PixelFormatTraits_PAL8
,StdMasks
>(
1977 aBounds
, nScanlineFormat
, nScanlineStride
,
1978 pFirstScanline
, pMem
, pPal
,
1979 bitsPerPixel
[nScanlineFormat
], rDamage
);
1982 // ----------------------------------------------------------------------
1983 // sixteen bit formats
1985 case Format::SIXTEEN_BIT_LSB_TC_MASK
:
1986 return createRenderer
<PixelFormatTraits_RGB16_565_LSB
,StdMasks
>(
1987 aBounds
, nScanlineFormat
, nScanlineStride
,
1988 pFirstScanline
, pMem
, pPal
, rDamage
);
1990 case Format::SIXTEEN_BIT_MSB_TC_MASK
:
1991 return createRenderer
<PixelFormatTraits_RGB16_565_MSB
,StdMasks
>(
1992 aBounds
, nScanlineFormat
, nScanlineStride
,
1993 pFirstScanline
, pMem
, pPal
, rDamage
);
1996 // ----------------------------------------------------------------------
1997 // twentyfour bit formats
1998 case Format::TWENTYFOUR_BIT_TC_MASK
:
1999 return createRenderer
<PixelFormatTraits_BGR24
,StdMasks
>(
2000 aBounds
, nScanlineFormat
, nScanlineStride
,
2001 pFirstScanline
, pMem
, pPal
, rDamage
);
2004 // ----------------------------------------------------------------------
2005 // thirtytwo bit formats
2007 case Format::THIRTYTWO_BIT_TC_MASK
:
2008 return createRenderer
<PixelFormatTraits_RGB32_888
,StdMasks
>(
2009 aBounds
, nScanlineFormat
, nScanlineStride
,
2010 pFirstScanline
, pMem
, pPal
, rDamage
);
2012 case Format::THIRTYTWO_BIT_TC_MASK_ARGB
:
2013 return createRenderer
<PixelFormatTraits_BGR32_888
,StdMasks
>(
2014 aBounds
, nScanlineFormat
, nScanlineStride
,
2015 pFirstScanline
, pMem
, pPal
, rDamage
);
2018 // TODO(F3): other formats not yet implemented
2019 return BitmapDeviceSharedPtr();
2024 BitmapDeviceSharedPtr
createBitmapDevice( const basegfx::B2IVector
& rSize
,
2026 sal_Int32 nScanlineFormat
)
2028 return createBitmapDeviceImpl( rSize
,
2031 boost::shared_array
< sal_uInt8
>(),
2032 PaletteMemorySharedVector(),
2034 IBitmapDeviceDamageTrackerSharedPtr() );
2037 BitmapDeviceSharedPtr
createBitmapDevice( const basegfx::B2IVector
& rSize
,
2039 sal_Int32 nScanlineFormat
,
2040 const PaletteMemorySharedVector
& rPalette
)
2042 return createBitmapDeviceImpl( rSize
,
2045 boost::shared_array
< sal_uInt8
>(),
2048 IBitmapDeviceDamageTrackerSharedPtr() );
2051 BitmapDeviceSharedPtr
createBitmapDevice( const basegfx::B2IVector
& rSize
,
2053 sal_Int32 nScanlineFormat
,
2054 const RawMemorySharedArray
& rMem
,
2055 const PaletteMemorySharedVector
& rPalette
)
2057 return createBitmapDeviceImpl( rSize
,
2063 IBitmapDeviceDamageTrackerSharedPtr() );
2066 BitmapDeviceSharedPtr
subsetBitmapDevice( const BitmapDeviceSharedPtr
& rProto
,
2067 const basegfx::B2IBox
& rSubset
)
2069 return createBitmapDeviceImpl( rProto
->getSize(),
2070 rProto
->isTopDown(),
2071 rProto
->getScanlineFormat(),
2072 rProto
->getBuffer(),
2073 rProto
->getPalette(),
2075 rProto
->getDamageTracker() );
2078 BitmapDeviceSharedPtr
cloneBitmapDevice( const basegfx::B2IVector
& rSize
,
2079 const BitmapDeviceSharedPtr
& rProto
)
2081 return createBitmapDeviceImpl( rSize
,
2082 rProto
->isTopDown(),
2083 rProto
->getScanlineFormat(),
2084 boost::shared_array
< sal_uInt8
>(),
2085 rProto
->getPalette(),
2087 rProto
->getDamageTracker() );
2090 //----------------------------------------------------------------------------------
2092 /// Clone our device, with GenericImageAccessor to handle all formats
2093 BitmapDeviceSharedPtr
BitmapDevice::getGenericRenderer() const
2095 return mpImpl
->mpGenericRenderer
;
2098 } // namespace basebmp
2100 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */