1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: bitmapdevice.cxx,v $
10 * $Revision: 1.33.4.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #if defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x580)
33 #include <math.h> // needed for fabs, hypot
35 #include "basebmp/bitmapdevice.hxx"
37 #include "basebmp/compositeiterator.hxx"
38 #include "basebmp/iteratortraits.hxx"
40 #include "basebmp/accessor.hxx"
41 #include "basebmp/accessortraits.hxx"
42 #include "basebmp/accessoradapters.hxx"
43 #include "basebmp/colorblendaccessoradapter.hxx"
45 #include "basebmp/color.hxx"
46 #include "basebmp/colormisc.hxx"
47 #include "basebmp/colortraits.hxx"
49 #include "basebmp/greylevelformats.hxx"
50 #include "basebmp/paletteformats.hxx"
51 #include "basebmp/rgbmaskpixelformats.hxx"
52 #include "basebmp/rgb24pixelformats.hxx"
54 #include "basebmp/scanlineformats.hxx"
55 #include "basebmp/fillimage.hxx"
56 #include "basebmp/scaleimage.hxx"
57 #include "basebmp/clippedlinerenderer.hxx"
58 #include "basebmp/polypolygonrenderer.hxx"
59 #include "basebmp/genericcolorimageaccessor.hxx"
61 #include "basebmp/tools.hxx"
62 #include "intconversion.hxx"
64 #include <rtl/alloc.h>
65 #include <rtl/memory.h>
66 #include <osl/diagnose.h>
68 #include <basegfx/tools/tools.hxx>
69 #include <basegfx/range/b2irange.hxx>
70 #include <basegfx/range/b2drange.hxx>
71 #include <basegfx/polygon/b2dpolygon.hxx>
72 #include <basegfx/polygon/b2dpolygontools.hxx>
73 #include <basegfx/polygon/b2dpolypolygontools.hxx>
74 #include <basegfx/point/b2ipoint.hxx>
75 #include <basegfx/vector/b2ivector.hxx>
77 #include <vigra/iteratortraits.hxx>
78 #include <vigra/rgbvalue.hxx>
79 #include <vigra/copyimage.hxx>
80 #include <vigra/tuple.hxx>
86 /// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
87 template< class Value
, unsigned int RedIndex
, unsigned int BlueIndex
, unsigned int GreenIndex
>
88 inline RGBValue
<Value
, RedIndex
, GreenIndex
, BlueIndex
>
89 operator^( RGBValue
<Value
, RedIndex
, GreenIndex
, BlueIndex
> const& lhs
,
90 RGBValue
<Value
, RedIndex
, GreenIndex
, BlueIndex
> const& rhs
)
92 RGBValue
<Value
, RedIndex
, GreenIndex
, BlueIndex
> res(
105 /** Create the type for an accessor that takes the (mask,bitmap)
106 input value generated from a JoinImageAccessorAdapter, and
107 pipe that through a mask functor.
110 Destination bitmap accessor
113 Input accessor, is expected to generate a std::pair as the
117 Either FastMask or NoFastMask, depending on whether the mask
118 is guaranteed to contain only 0s and 1s.
120 template< class DestAccessor
,
121 class JoinedAccessor
,
123 typename MaskFunctorMode
> struct masked_input_splitting_accessor
125 typedef BinarySetterFunctionAccessorAdapter
<
127 BinaryFunctorSplittingWrapper
<
128 typename outputMaskFunctorSelector
<
129 typename
JoinedAccessor::value_type::first_type
,
130 typename
JoinedAccessor::value_type::second_type
,
132 MaskFunctorMode
>::type
> > type
;
137 // Actual BitmapDevice implementation (templatized by accessor and iterator)
138 //--------------------------------------------------------------------------
140 /** Implementation of the BitmapDevice interface
143 Iterator to access bitmap memory
146 Raw accessor, to access pixel values directly
148 @tpl AccessorSelector
149 Accessor adapter selector, which, when applying the nested
150 template metafunction wrap_accessor to one of the raw bitmap
151 accessors, yields a member type named 'type', which is a
152 wrapped accessor that map color values.
155 Traits template, containing nested traits
156 clipmask_format_traits and alphamask_format_traits, which
157 determine what specialized formats are to be used for clip and
158 alpha masks. With those mask formats, clipping and alpha
159 blending is handled natively.
161 template< class DestIterator
,
163 class AccessorSelector
,
164 class Masks
> class BitmapRenderer
:
168 typedef DestIterator dest_iterator_type
;
169 typedef RawAccessor raw_accessor_type
;
170 typedef AccessorSelector accessor_selector
;
172 typedef typename
Masks::clipmask_format_traits::iterator_type mask_iterator_type
;
173 typedef typename
Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type
;
174 typedef typename
Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type
;
176 typedef typename
Masks::alphamask_format_traits::iterator_type alphamask_iterator_type
;
177 typedef typename
Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type
;
178 typedef typename
Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type
;
180 typedef typename
AccessorSelector::template wrap_accessor
<
181 raw_accessor_type
>::type dest_accessor_type
;
183 typedef AccessorTraits
< dest_accessor_type
> accessor_traits
;
184 typedef CompositeIterator2D
< dest_iterator_type
,
185 mask_iterator_type
> composite_iterator_type
;
186 typedef CompositeIterator2D
< vigra::Diff2D
,
187 vigra::Diff2D
> generic_composite_iterator_type
;
189 typedef BitmapRenderer
<mask_iterator_type
,
190 mask_rawaccessor_type
,
191 mask_accessorselector_type
,
192 Masks
> mask_bitmap_type
;
193 typedef BitmapRenderer
<alphamask_iterator_type
,
194 alphamask_rawaccessor_type
,
195 alphamask_accessorselector_type
,
196 Masks
> alphamask_bitmap_type
;
198 // -------------------------------------------------------
200 typedef AccessorTraits
< raw_accessor_type
> raw_accessor_traits
;
201 typedef typename uInt32Converter
<
202 typename
raw_accessor_type::value_type
>::to to_uint32_functor
;
204 // -------------------------------------------------------
206 typedef typename
raw_accessor_traits::xor_accessor raw_xor_accessor_type
;
207 typedef AccessorTraits
<raw_xor_accessor_type
> raw_xor_accessor_traits
;
208 typedef typename
accessor_selector::template wrap_accessor
<
209 raw_xor_accessor_type
>::type xor_accessor_type
;
210 typedef AccessorTraits
<xor_accessor_type
> xor_accessor_traits
;
212 // -------------------------------------------------------
214 typedef typename
raw_accessor_traits::template masked_accessor
<
215 mask_rawaccessor_type
,
218 Masks::clipmask_polarity
>::type raw_maskedaccessor_type
;
219 typedef typename
accessor_selector::template wrap_accessor
<
220 raw_maskedaccessor_type
>::type masked_accessor_type
;
221 typedef typename AccessorTraits
<
222 raw_maskedaccessor_type
>::xor_accessor raw_maskedxor_accessor_type
;
223 typedef typename
accessor_selector::template wrap_accessor
<
224 raw_maskedxor_accessor_type
>::type masked_xoraccessor_type
;
226 // -------------------------------------------------------
228 // ((iter,mask),mask) special case (e.g. for clipped
229 // drawMaskedColor())
230 typedef AccessorTraits
< raw_maskedaccessor_type
> raw_maskedaccessor_traits
;
231 typedef typename
raw_maskedaccessor_traits::template masked_accessor
<
232 mask_rawaccessor_type
,
233 composite_iterator_type
,
235 Masks::clipmask_polarity
>::type raw_maskedmask_accessor_type
;
237 typedef CompositeIterator2D
<
238 composite_iterator_type
,
239 mask_iterator_type
> composite_composite_mask_iterator_type
;
241 // -------------------------------------------------------
243 typedef ConstantColorBlendSetterAccessorAdapter
<
245 typename
alphamask_rawaccessor_type::value_type
,
246 Masks::alphamask_polarity
> colorblend_accessor_type
;
247 typedef AccessorTraits
<colorblend_accessor_type
> colorblend_accessor_traits
;
248 typedef typename
colorblend_accessor_traits::template masked_accessor
<
249 mask_rawaccessor_type
,
252 Masks::clipmask_polarity
>::type masked_colorblend_accessor_type
;
254 // -------------------------------------------------------
256 typedef ConstantColorBlendSetterAccessorAdapter
<
259 Masks::alphamask_polarity
> colorblend_generic_accessor_type
;
260 typedef AccessorTraits
<colorblend_generic_accessor_type
> colorblend_generic_accessor_traits
;
261 typedef typename
colorblend_generic_accessor_traits::template masked_accessor
<
262 mask_rawaccessor_type
,
265 Masks::clipmask_polarity
>::type masked_colorblend_generic_accessor_type
;
267 // -------------------------------------------------------
269 typedef JoinImageAccessorAdapter
< dest_accessor_type
,
270 mask_rawaccessor_type
> joined_image_accessor_type
;
271 typedef JoinImageAccessorAdapter
< GenericColorImageAccessor
,
272 GenericColorImageAccessor
> joined_generic_image_accessor_type
;
274 // -------------------------------------------------------
276 dest_iterator_type maBegin
;
277 typename
accessor_traits::color_lookup maColorLookup
;
278 to_uint32_functor maToUInt32Converter
;
279 dest_accessor_type maAccessor
;
280 colorblend_accessor_type maColorBlendAccessor
;
281 colorblend_generic_accessor_type maGenericColorBlendAccessor
;
282 raw_accessor_type maRawAccessor
;
283 xor_accessor_type maXorAccessor
;
284 raw_xor_accessor_type maRawXorAccessor
;
285 masked_accessor_type maMaskedAccessor
;
286 masked_colorblend_accessor_type maMaskedColorBlendAccessor
;
287 masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor
;
288 masked_xoraccessor_type maMaskedXorAccessor
;
289 raw_maskedaccessor_type maRawMaskedAccessor
;
290 raw_maskedxor_accessor_type maRawMaskedXorAccessor
;
291 raw_maskedmask_accessor_type maRawMaskedMaskAccessor
;
293 // -------------------------------------------------------
295 BitmapRenderer( const basegfx::B2IRange
& rBounds
,
296 sal_Int32 nScanlineFormat
,
297 sal_Int32 nScanlineStride
,
298 sal_uInt8
* pFirstScanline
,
299 dest_iterator_type begin
,
300 raw_accessor_type rawAccessor
,
301 dest_accessor_type accessor
,
302 const RawMemorySharedArray
& rMem
,
303 const PaletteMemorySharedVector
& rPalette
) :
304 BitmapDevice( rBounds
, nScanlineFormat
,
305 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
)
325 boost::shared_ptr
<BitmapRenderer
> getCompatibleBitmap( const BitmapDeviceSharedPtr
& bmp
) const
327 return boost::dynamic_pointer_cast
< BitmapRenderer
>( bmp
);
330 virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr
& bmp
) const
332 // TODO(P1): dynamic_cast usually called twice for
333 // compatible formats
334 return getCompatibleBitmap(bmp
).get() != NULL
;
337 boost::shared_ptr
<mask_bitmap_type
> getCompatibleClipMask( const BitmapDeviceSharedPtr
& bmp
) const
339 boost::shared_ptr
<mask_bitmap_type
> pMask( boost::dynamic_pointer_cast
<mask_bitmap_type
>( bmp
));
344 if( pMask
->getSize() != getSize() )
350 virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr
& bmp
) const
352 // TODO(P1): dynamic_cast usually called twice for
353 // compatible formats
354 return boost::dynamic_pointer_cast
<mask_bitmap_type
>( bmp
).get() != NULL
;
357 boost::shared_ptr
<alphamask_bitmap_type
> getCompatibleAlphaMask( const BitmapDeviceSharedPtr
& bmp
) const
359 return boost::dynamic_pointer_cast
<alphamask_bitmap_type
>( bmp
);
362 virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr
& bmp
) const
364 // TODO(P1): dynamic_cast usually called twice for
365 // compatible formats
366 return getCompatibleAlphaMask( bmp
).get() != NULL
;
369 virtual void clear_i( Color fillColor
,
370 const basegfx::B2IRange
& rBounds
)
372 fillImage(destIterRange(maBegin
,
380 virtual void setPixel_i( const basegfx::B2IPoint
& rPt
,
384 const DestIterator
pixel( maBegin
+
385 vigra::Diff2D(rPt
.getX(),
387 if( drawMode
== DrawMode_XOR
)
388 maXorAccessor
.set( pixelColor
,
391 maAccessor
.set( pixelColor
,
395 virtual void setPixel_i( const basegfx::B2IPoint
& rPt
,
398 const BitmapDeviceSharedPtr
& rClip
)
400 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rClip
) );
403 const vigra::Diff2D
offset(rPt
.getX(),
406 const composite_iterator_type
aIter(
408 pMask
->maBegin
+ offset
);
410 if( drawMode
== DrawMode_XOR
)
411 maMaskedXorAccessor
.set( pixelColor
,
414 maMaskedAccessor
.set( pixelColor
,
418 virtual Color
getPixel_i(const basegfx::B2IPoint
& rPt
)
420 const DestIterator
pixel( maBegin
+
421 vigra::Diff2D(rPt
.getX(),
423 return maAccessor(pixel
);
426 virtual sal_uInt32
getPixelData_i( const basegfx::B2IPoint
& rPt
)
428 const DestIterator
pixel( maBegin
+
429 vigra::Diff2D(rPt
.getX(),
431 return maToUInt32Converter(maRawAccessor(pixel
));
434 template< typename Iterator
, typename Col
, typename RawAcc
>
435 void implRenderLine2( const basegfx::B2IPoint
& rPt1
,
436 const basegfx::B2IPoint
& rPt2
,
437 const basegfx::B2IRange
& rBounds
,
439 const Iterator
& begin
,
440 const RawAcc
& rawAcc
)
442 renderClippedLine( rPt1
,
450 template< typename Iterator
, typename Accessor
, typename RawAcc
>
451 void implRenderLine( const basegfx::B2IPoint
& rPt1
,
452 const basegfx::B2IPoint
& rPt2
,
453 const basegfx::B2IRange
& rBounds
,
455 const Iterator
& begin
,
457 const RawAcc
& rawAcc
)
459 implRenderLine2( rPt1
,rPt2
,rBounds
,
466 template< typename Iterator
, typename RawAcc
, typename XorAcc
>
467 void implDrawLine( const basegfx::B2IPoint
& rPt1
,
468 const basegfx::B2IPoint
& rPt2
,
469 const basegfx::B2IRange
& rBounds
,
471 const Iterator
& begin
,
472 const RawAcc
& rawAcc
,
473 const XorAcc
& xorAcc
,
476 if( drawMode
== DrawMode_XOR
)
477 implRenderLine( rPt1
, rPt2
, rBounds
, col
,
478 begin
, maAccessor
, xorAcc
);
480 implRenderLine( rPt1
, rPt2
, rBounds
, col
,
481 begin
, maAccessor
, rawAcc
);
484 virtual void drawLine_i(const basegfx::B2IPoint
& rPt1
,
485 const basegfx::B2IPoint
& rPt2
,
486 const basegfx::B2IRange
& rBounds
,
490 implDrawLine(rPt1
,rPt2
,rBounds
,lineColor
,
492 maRawAccessor
,maRawXorAccessor
,drawMode
);
495 composite_iterator_type
getMaskedIter( const BitmapDeviceSharedPtr
& rClip
) const
497 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rClip
) );
500 return composite_iterator_type( maBegin
,
504 virtual void drawLine_i(const basegfx::B2IPoint
& rPt1
,
505 const basegfx::B2IPoint
& rPt2
,
506 const basegfx::B2IRange
& rBounds
,
509 const BitmapDeviceSharedPtr
& rClip
)
511 implDrawLine(rPt1
,rPt2
,rBounds
,lineColor
,
512 getMaskedIter(rClip
),
514 maRawMaskedXorAccessor
,drawMode
);
517 template< typename Iterator
, typename RawAcc
>
518 void implDrawPolygon( const basegfx::B2DPolygon
& rPoly
,
519 const basegfx::B2IRange
& rBounds
,
521 const Iterator
& begin
,
524 basegfx::B2DPolygon
aPoly( rPoly
);
525 if( rPoly
.areControlPointsUsed() )
526 aPoly
= basegfx::tools::adaptiveSubdivideByCount( rPoly
);
528 const typename
dest_iterator_type::value_type
colorIndex( maColorLookup(
531 const sal_uInt32
nVertices( aPoly
.count() );
532 for( sal_uInt32 i
=1; i
<nVertices
; ++i
)
533 implRenderLine2( basegfx::fround(aPoly
.getB2DPoint(i
-1)),
534 basegfx::fround(aPoly
.getB2DPoint(i
)),
540 if( nVertices
> 1 && aPoly
.isClosed() )
541 implRenderLine2( basegfx::fround(aPoly
.getB2DPoint(nVertices
-1)),
542 basegfx::fround(aPoly
.getB2DPoint(0)),
549 virtual void drawPolygon_i(const basegfx::B2DPolygon
& rPoly
,
550 const basegfx::B2IRange
& rBounds
,
554 if( drawMode
== DrawMode_XOR
)
555 implDrawPolygon( rPoly
, rBounds
, lineColor
,
559 implDrawPolygon( rPoly
, rBounds
, lineColor
,
564 virtual void drawPolygon_i(const basegfx::B2DPolygon
& rPoly
,
565 const basegfx::B2IRange
& rBounds
,
568 const BitmapDeviceSharedPtr
& rClip
)
570 if( drawMode
== DrawMode_XOR
)
571 implDrawPolygon( rPoly
, rBounds
, lineColor
,
572 getMaskedIter(rClip
),
573 maRawMaskedXorAccessor
);
575 implDrawPolygon( rPoly
, rBounds
, lineColor
,
576 getMaskedIter(rClip
),
577 maRawMaskedAccessor
);
580 template< typename Iterator
, typename RawAcc
>
581 void implFillPolyPolygon( const basegfx::B2DPolyPolygon
& rPoly
,
583 const Iterator
& begin
,
585 const basegfx::B2IRange
& rBounds
)
587 basegfx::B2DPolyPolygon
aPoly( rPoly
);
588 if( rPoly
.areControlPointsUsed() )
589 aPoly
= basegfx::tools::adaptiveSubdivideByCount( rPoly
);
591 renderClippedPolyPolygon( begin
,
593 maColorLookup( maAccessor
,
597 basegfx::FillRule_EVEN_ODD
);
600 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon
& rPoly
,
603 const basegfx::B2IRange
& rBounds
)
605 if( drawMode
== DrawMode_XOR
)
606 implFillPolyPolygon( rPoly
, fillColor
,
611 implFillPolyPolygon( rPoly
, fillColor
,
617 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon
& rPoly
,
620 const basegfx::B2IRange
& rBounds
,
621 const BitmapDeviceSharedPtr
& rClip
)
623 if( drawMode
== DrawMode_XOR
)
624 implFillPolyPolygon( rPoly
, fillColor
,
625 getMaskedIter(rClip
),
626 maRawMaskedXorAccessor
,
629 implFillPolyPolygon( rPoly
, fillColor
,
630 getMaskedIter(rClip
),
635 template< typename Iterator
, typename RawAcc
>
636 void implDrawBitmap(const BitmapDeviceSharedPtr
& rSrcBitmap
,
637 const basegfx::B2IRange
& rSrcRect
,
638 const basegfx::B2IRange
& rDstRect
,
639 const Iterator
& begin
,
642 boost::shared_ptr
<BitmapRenderer
> pSrcBmp( getCompatibleBitmap(rSrcBitmap
) );
643 OSL_ASSERT( pSrcBmp
);
646 srcIterRange(pSrcBmp
->maBegin
,
647 pSrcBmp
->maRawAccessor
,
652 rSrcBitmap
.get() == this );
655 template< typename Iterator
, typename Acc
>
656 void implDrawBitmapGeneric(const BitmapDeviceSharedPtr
& rSrcBitmap
,
657 const basegfx::B2IRange
& rSrcRect
,
658 const basegfx::B2IRange
& rDstRect
,
659 const Iterator
& begin
,
662 GenericColorImageAccessor
aSrcAcc( rSrcBitmap
);
665 srcIterRange(vigra::Diff2D(),
673 virtual void drawBitmap_i(const BitmapDeviceSharedPtr
& rSrcBitmap
,
674 const basegfx::B2IRange
& rSrcRect
,
675 const basegfx::B2IRange
& rDstRect
,
678 if( isCompatibleBitmap( rSrcBitmap
) )
680 if( drawMode
== DrawMode_XOR
)
681 implDrawBitmap(rSrcBitmap
, rSrcRect
, rDstRect
,
685 implDrawBitmap(rSrcBitmap
, rSrcRect
, rDstRect
,
691 if( drawMode
== DrawMode_XOR
)
692 implDrawBitmapGeneric(rSrcBitmap
, rSrcRect
, rDstRect
,
696 implDrawBitmapGeneric(rSrcBitmap
, rSrcRect
, rDstRect
,
702 virtual void drawBitmap_i(const BitmapDeviceSharedPtr
& rSrcBitmap
,
703 const basegfx::B2IRange
& rSrcRect
,
704 const basegfx::B2IRange
& rDstRect
,
706 const BitmapDeviceSharedPtr
& rClip
)
708 if( isCompatibleBitmap( rSrcBitmap
) )
710 if( drawMode
== DrawMode_XOR
)
711 implDrawBitmap(rSrcBitmap
, rSrcRect
, rDstRect
,
712 getMaskedIter(rClip
),
713 maRawMaskedXorAccessor
);
715 implDrawBitmap(rSrcBitmap
, rSrcRect
, rDstRect
,
716 getMaskedIter(rClip
),
717 maRawMaskedAccessor
);
721 if( drawMode
== DrawMode_XOR
)
722 implDrawBitmapGeneric(rSrcBitmap
, rSrcRect
, rDstRect
,
723 getMaskedIter(rClip
),
724 maMaskedXorAccessor
);
726 implDrawBitmapGeneric(rSrcBitmap
, rSrcRect
, rDstRect
,
727 getMaskedIter(rClip
),
732 virtual void drawMaskedColor_i(Color aSrcColor
,
733 const BitmapDeviceSharedPtr
& rAlphaMask
,
734 const basegfx::B2IRange
& rSrcRect
,
735 const basegfx::B2IPoint
& rDstPoint
)
737 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rAlphaMask
) );
738 boost::shared_ptr
<alphamask_bitmap_type
> pAlpha( getCompatibleAlphaMask(rAlphaMask
) );
742 maColorBlendAccessor
.setColor( aSrcColor
);
744 vigra::copyImage( srcIterRange(pAlpha
->maBegin
,
745 pAlpha
->maRawAccessor
,
748 maColorBlendAccessor
,
753 const composite_iterator_type
aBegin(
754 maBegin
+ vigra::Diff2D(rDstPoint
.getX(),
756 pMask
->maBegin
+ topLeft(rSrcRect
) );
759 aBegin
+ vigra::Diff2D(rSrcRect
.getWidth(),
760 rSrcRect
.getHeight()),
768 GenericColorImageAccessor
aSrcAcc( rAlphaMask
);
769 maGenericColorBlendAccessor
.setColor( aSrcColor
);
771 vigra::copyImage( srcIterRange(vigra::Diff2D(),
775 maGenericColorBlendAccessor
,
780 virtual void drawMaskedColor_i(Color aSrcColor
,
781 const BitmapDeviceSharedPtr
& rAlphaMask
,
782 const basegfx::B2IRange
& rSrcRect
,
783 const basegfx::B2IPoint
& rDstPoint
,
784 const BitmapDeviceSharedPtr
& rClip
)
786 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rAlphaMask
) );
787 boost::shared_ptr
<alphamask_bitmap_type
> pAlpha( getCompatibleAlphaMask(rAlphaMask
) );
791 const composite_iterator_type
aBegin( getMaskedIter(rClip
) );
792 maMaskedColorBlendAccessor
.get1stWrappedAccessor().setColor(
795 vigra::copyImage( srcIterRange(pAlpha
->maBegin
,
796 pAlpha
->maRawAccessor
,
799 maMaskedColorBlendAccessor
,
804 boost::shared_ptr
<mask_bitmap_type
> pClipMask( getCompatibleClipMask(rClip
) );
805 OSL_ASSERT( pClipMask
);
807 // setup a ((iter,mask),clipMask) composite composite
808 // iterator, to pass both masks (clip and alpha mask)
810 const composite_composite_mask_iterator_type
aBegin(
811 composite_iterator_type(
812 maBegin
+ vigra::Diff2D(rDstPoint
.getX(),
814 pMask
->maBegin
+ topLeft(rSrcRect
)),
815 pClipMask
->maBegin
+ vigra::Diff2D(rDstPoint
.getX(),
819 aBegin
+ vigra::Diff2D(rSrcRect
.getWidth(),
820 rSrcRect
.getHeight()),
821 maRawMaskedMaskAccessor
,
828 GenericColorImageAccessor
aSrcAcc( rAlphaMask
);
829 const composite_iterator_type
aBegin( getMaskedIter(rClip
) );
830 maGenericMaskedColorBlendAccessor
.get1stWrappedAccessor().setColor(
833 vigra::copyImage( srcIterRange(vigra::Diff2D(),
837 maGenericMaskedColorBlendAccessor
,
842 template< typename Iterator
, typename Acc
>
843 void implDrawMaskedBitmap(const BitmapDeviceSharedPtr
& rSrcBitmap
,
844 const BitmapDeviceSharedPtr
& rMask
,
845 const basegfx::B2IRange
& rSrcRect
,
846 const basegfx::B2IRange
& rDstRect
,
847 const Iterator
& begin
,
850 boost::shared_ptr
<BitmapRenderer
> pSrcBmp( getCompatibleBitmap(rSrcBitmap
) );
851 boost::shared_ptr
<mask_bitmap_type
> pMask( getCompatibleClipMask(rMask
) );
852 OSL_ASSERT( pMask
&& pSrcBmp
);
855 srcIterRange(composite_iterator_type(
858 joined_image_accessor_type(
860 pMask
->maRawAccessor
),
863 typename masked_input_splitting_accessor
<
865 joined_image_accessor_type
,
866 Masks::clipmask_polarity
,
867 FastMask
>::type(acc
),
869 rSrcBitmap
.get() == this);
872 template< typename Iterator
, typename Acc
>
873 void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr
& rSrcBitmap
,
874 const BitmapDeviceSharedPtr
& rMask
,
875 const basegfx::B2IRange
& rSrcRect
,
876 const basegfx::B2IRange
& rDstRect
,
877 const Iterator
& begin
,
880 GenericColorImageAccessor
aSrcAcc( rSrcBitmap
);
881 GenericColorImageAccessor
aMaskAcc( rMask
);
883 const vigra::Diff2D
aTopLeft(rSrcRect
.getMinX(),
885 const vigra::Diff2D
aBottomRight(rSrcRect
.getMaxX(),
889 generic_composite_iterator_type(
891 generic_composite_iterator_type(
892 aBottomRight
,aBottomRight
),
893 joined_generic_image_accessor_type(
897 typename masked_input_splitting_accessor
<
899 joined_generic_image_accessor_type
,
900 Masks::clipmask_polarity
,
901 NoFastMask
>::type(acc
),
905 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr
& rSrcBitmap
,
906 const BitmapDeviceSharedPtr
& rMask
,
907 const basegfx::B2IRange
& rSrcRect
,
908 const basegfx::B2IRange
& rDstRect
,
911 if( isCompatibleClipMask(rMask
) &&
912 isCompatibleBitmap(rSrcBitmap
) )
914 if( drawMode
== DrawMode_XOR
)
915 implDrawMaskedBitmap(rSrcBitmap
, rMask
,
920 implDrawMaskedBitmap(rSrcBitmap
, rMask
,
927 if( drawMode
== DrawMode_XOR
)
928 implDrawMaskedBitmapGeneric(rSrcBitmap
, rMask
,
933 implDrawMaskedBitmapGeneric(rSrcBitmap
, rMask
,
940 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr
& rSrcBitmap
,
941 const BitmapDeviceSharedPtr
& rMask
,
942 const basegfx::B2IRange
& rSrcRect
,
943 const basegfx::B2IRange
& rDstRect
,
945 const BitmapDeviceSharedPtr
& rClip
)
947 if( isCompatibleClipMask(rMask
) &&
948 isCompatibleBitmap(rSrcBitmap
) )
950 if( drawMode
== DrawMode_XOR
)
951 implDrawMaskedBitmap(rSrcBitmap
, rMask
,
953 getMaskedIter(rClip
),
954 maMaskedXorAccessor
);
956 implDrawMaskedBitmap(rSrcBitmap
, rMask
,
958 getMaskedIter(rClip
),
963 if( drawMode
== DrawMode_XOR
)
964 implDrawMaskedBitmapGeneric(rSrcBitmap
, rMask
,
966 getMaskedIter(rClip
),
967 maMaskedXorAccessor
);
969 implDrawMaskedBitmapGeneric(rSrcBitmap
, rMask
,
971 getMaskedIter(rClip
),
978 struct ImplBitmapDevice
980 /** Bitmap memory plus deleter.
982 Always points to the start of the mem
984 RawMemorySharedArray mpMem
;
986 /// Palette memory plus deleter (might be NULL)
987 PaletteMemorySharedVector mpPalette
;
989 /** Bounds of the device.
991 maBounds.getWidth()/getHeight() yield the true size of the
992 device (i.e. the rectangle given by maBounds covers the device
993 area under the excluding-bottommost-and-rightmost-pixels fill
996 basegfx::B2IRange maBounds
;
998 /** Bounds of the device.
1000 maBounds.getWidth()/getHeight() yield the true size of the
1001 device minus 1 (i.e. the rectangle given by maBounds covers
1002 the device area under the
1003 including-the-bottommost-and-rightmost-pixels fill rule).
1005 The member is used to clip line stroking against the device
1008 basegfx::B2IRange maLineClipRect
;
1010 /// Scanline format, as provided at the constructor
1011 sal_Int32 mnScanlineFormat
;
1013 /// Scanline stride. Negative for bottom-to-top formats
1014 sal_Int32 mnScanlineStride
;
1016 /// raw ptr to 0th scanline. used for cloning a generic renderer
1017 sal_uInt8
* mpFirstScanline
;
1019 /** (Optional) device sharing the same memory, and used for input
1020 clip masks/alpha masks/bitmaps that don't match our exact
1023 This is to avoid the combinatorical explosion when dealing
1024 with n bitmap formats, which could be combined with n clip
1025 masks, alpha masks and bitmap masks (yielding a total of n^4
1026 combinations). Since each BitmapRenderer is specialized for
1027 one specific combination of said formats, a lot of duplicate
1028 code would be generated, most of which probably never
1029 used. Therefore, only the most common combinations are
1030 specialized templates, the remainder gets handled by this
1031 generic renderer (via runtime polymorphism).
1033 BitmapDeviceSharedPtr mpGenericRenderer
;
1037 BitmapDevice::BitmapDevice( const basegfx::B2IRange
& rBounds
,
1038 sal_Int32 nScanlineFormat
,
1039 sal_Int32 nScanlineStride
,
1040 sal_uInt8
* pFirstScanline
,
1041 const RawMemorySharedArray
& rMem
,
1042 const PaletteMemorySharedVector
& rPalette
) :
1043 mpImpl( new ImplBitmapDevice
)
1045 mpImpl
->mpMem
= rMem
;
1046 mpImpl
->mpPalette
= rPalette
;
1047 mpImpl
->maBounds
= rBounds
;
1048 mpImpl
->maLineClipRect
= basegfx::B2IRange( rBounds
.getMinX(),
1050 rBounds
.getMaxX()-1,
1051 rBounds
.getMaxY()-1 );
1052 mpImpl
->mnScanlineFormat
= nScanlineFormat
;
1053 mpImpl
->mnScanlineStride
= nScanlineStride
;
1054 mpImpl
->mpFirstScanline
= pFirstScanline
;
1057 BitmapDevice::~BitmapDevice()
1059 // outline, because of internal ImplBitmapDevice
1062 basegfx::B2IVector
BitmapDevice::getSize() const
1065 return basegfx::B2IVector(
1066 mpImpl
->maBounds
.getMaxX() - mpImpl
->maBounds
.getMinX(),
1067 mpImpl
->maBounds
.getMaxY() - mpImpl
->maBounds
.getMinY() );
1070 bool BitmapDevice::isTopDown() const
1072 return mpImpl
->mnScanlineStride
>= 0;
1075 sal_Int32
BitmapDevice::getScanlineFormat() const
1077 return mpImpl
->mnScanlineFormat
;
1080 sal_Int32
BitmapDevice::getScanlineStride() const
1082 return mpImpl
->mnScanlineStride
< 0 ?
1083 -mpImpl
->mnScanlineStride
: mpImpl
->mnScanlineStride
;
1086 RawMemorySharedArray
BitmapDevice::getBuffer() const
1088 return mpImpl
->mpMem
;
1091 PaletteMemorySharedVector
BitmapDevice::getPalette() const
1093 return mpImpl
->mpPalette
;
1096 sal_Int32
BitmapDevice::getPaletteEntryCount() const
1098 return mpImpl
->mpPalette
? mpImpl
->mpPalette
->size() : 0;
1101 void BitmapDevice::clear( Color fillColor
)
1103 clear_i( fillColor
, mpImpl
->maBounds
);
1106 void BitmapDevice::setPixel( const basegfx::B2IPoint
& rPt
,
1110 if( mpImpl
->maLineClipRect
.isInside(rPt
) )
1111 setPixel_i(rPt
,lineColor
,drawMode
);
1114 void BitmapDevice::setPixel( const basegfx::B2IPoint
& rPt
,
1117 const BitmapDeviceSharedPtr
& rClip
)
1121 setPixel(rPt
,lineColor
,drawMode
);
1125 if( mpImpl
->maLineClipRect
.isInside(rPt
) )
1127 if( isCompatibleClipMask( rClip
) )
1128 setPixel_i(rPt
,lineColor
,drawMode
,rClip
);
1130 getGenericRenderer()->setPixel( rPt
, lineColor
, drawMode
, rClip
);
1134 Color
BitmapDevice::getPixel( const basegfx::B2IPoint
& rPt
)
1136 if( mpImpl
->maLineClipRect
.isInside(rPt
) )
1137 return getPixel_i(rPt
);
1142 sal_uInt32
BitmapDevice::getPixelData( const basegfx::B2IPoint
& rPt
)
1144 if( mpImpl
->maLineClipRect
.isInside(rPt
) )
1145 return getPixelData_i(rPt
);
1150 void BitmapDevice::drawLine( const basegfx::B2IPoint
& rPt1
,
1151 const basegfx::B2IPoint
& rPt2
,
1157 mpImpl
->maLineClipRect
,
1162 void BitmapDevice::drawLine( const basegfx::B2IPoint
& rPt1
,
1163 const basegfx::B2IPoint
& rPt2
,
1166 const BitmapDeviceSharedPtr
& rClip
)
1170 drawLine(rPt1
,rPt2
,lineColor
,drawMode
);
1174 if( isCompatibleClipMask( rClip
) )
1177 mpImpl
->maLineClipRect
,
1182 getGenericRenderer()->drawLine( rPt1
, rPt2
, lineColor
,
1186 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon
& rPoly
,
1190 const sal_uInt32
numVertices( rPoly
.count() );
1192 drawPolygon_i( rPoly
,
1193 mpImpl
->maLineClipRect
,
1194 lineColor
, drawMode
);
1197 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon
& rPoly
,
1200 const BitmapDeviceSharedPtr
& rClip
)
1204 drawPolygon(rPoly
,lineColor
,drawMode
);
1208 const sal_uInt32
numVertices( rPoly
.count() );
1211 if( isCompatibleClipMask( rClip
) )
1212 drawPolygon_i( rPoly
,
1213 mpImpl
->maLineClipRect
,
1214 lineColor
, drawMode
, rClip
);
1216 getGenericRenderer()->drawPolygon( rPoly
, lineColor
,
1221 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon
& rPoly
,
1225 fillPolyPolygon_i( rPoly
, fillColor
, drawMode
, mpImpl
->maBounds
);
1228 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon
& rPoly
,
1231 const BitmapDeviceSharedPtr
& rClip
)
1235 fillPolyPolygon(rPoly
,fillColor
,drawMode
);
1239 if( isCompatibleClipMask( rClip
) )
1240 fillPolyPolygon_i( rPoly
, fillColor
, drawMode
, mpImpl
->maBounds
, rClip
);
1242 getGenericRenderer()->fillPolyPolygon( rPoly
, fillColor
,
1249 void assertImagePoint( const basegfx::B2IPoint
& rPt
,
1250 const basegfx::B2IRange
& rPermittedRange
)
1252 (void)rPt
; (void)rPermittedRange
;
1253 OSL_ASSERT( rPermittedRange
.isInside(rPt
) );
1256 void assertImageRange( const basegfx::B2IRange
& rRange
,
1257 const basegfx::B2IRange
& rPermittedRange
)
1259 #if OSL_DEBUG_LEVEL > 0
1260 basegfx::B2IRange
aRange( rRange
);
1261 aRange
.intersect( rPermittedRange
);
1263 OSL_ASSERT( aRange
== rRange
);
1265 (void)rRange
; (void)rPermittedRange
;
1269 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1270 // to basegfx, and use here!
1271 bool clipAreaImpl( ::basegfx::B2IRange
& io_rSourceArea
,
1272 ::basegfx::B2IPoint
& io_rDestPoint
,
1273 const ::basegfx::B2IRange
& rSourceBounds
,
1274 const ::basegfx::B2IRange
& rDestBounds
)
1276 const ::basegfx::B2IPoint
aSourceTopLeft(
1277 io_rSourceArea
.getMinimum() );
1279 ::basegfx::B2IRange
aLocalSourceArea( io_rSourceArea
);
1281 // clip source area (which must be inside rSourceBounds)
1282 aLocalSourceArea
.intersect( rSourceBounds
);
1284 if( aLocalSourceArea
.isEmpty() )
1287 // calc relative new source area points (relative to orig
1289 const ::basegfx::B2IVector
aUpperLeftOffset(
1290 aLocalSourceArea
.getMinimum()-aSourceTopLeft
);
1291 const ::basegfx::B2IVector
aLowerRightOffset(
1292 aLocalSourceArea
.getMaximum()-aSourceTopLeft
);
1294 ::basegfx::B2IRange
aLocalDestArea( io_rDestPoint
+ aUpperLeftOffset
,
1295 io_rDestPoint
+ aLowerRightOffset
);
1297 // clip dest area (which must be inside rDestBounds)
1298 aLocalDestArea
.intersect( rDestBounds
);
1300 if( aLocalDestArea
.isEmpty() )
1303 // calc relative new dest area points (relative to orig
1305 const ::basegfx::B2IVector
aDestUpperLeftOffset(
1306 aLocalDestArea
.getMinimum()-io_rDestPoint
);
1307 const ::basegfx::B2IVector
aDestLowerRightOffset(
1308 aLocalDestArea
.getMaximum()-io_rDestPoint
);
1310 io_rSourceArea
= ::basegfx::B2IRange( aSourceTopLeft
+ aDestUpperLeftOffset
,
1311 aSourceTopLeft
+ aDestLowerRightOffset
);
1312 io_rDestPoint
= aLocalDestArea
.getMinimum();
1317 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1318 // to basegfx, and use here!
1319 bool clipAreaImpl( ::basegfx::B2IRange
& io_rDestArea
,
1320 ::basegfx::B2IRange
& io_rSourceArea
,
1321 const ::basegfx::B2IRange
& rDestBounds
,
1322 const ::basegfx::B2IRange
& rSourceBounds
)
1324 // extract inherent scale
1325 const double nScaleX( io_rDestArea
.getWidth() / (double)io_rSourceArea
.getWidth() );
1326 const double nScaleY( io_rDestArea
.getHeight() / (double)io_rSourceArea
.getHeight() );
1328 // extract range origins
1329 const basegfx::B2IPoint
aDestTopLeft(
1330 io_rDestArea
.getMinimum() );
1331 const ::basegfx::B2IPoint
aSourceTopLeft(
1332 io_rSourceArea
.getMinimum() );
1334 ::basegfx::B2IRange
aLocalSourceArea( io_rSourceArea
);
1336 // clip source area (which must be inside rSourceBounds)
1337 aLocalSourceArea
.intersect( rSourceBounds
);
1339 if( aLocalSourceArea
.isEmpty() )
1342 // calc relative new source area points (relative to orig
1344 const ::basegfx::B2IVector
aUpperLeftOffset(
1345 aLocalSourceArea
.getMinimum()-aSourceTopLeft
);
1346 const ::basegfx::B2IVector
aLowerRightOffset(
1347 aLocalSourceArea
.getMaximum()-aSourceTopLeft
);
1349 ::basegfx::B2IRange
aLocalDestArea( basegfx::fround(aDestTopLeft
.getX() + nScaleX
*aUpperLeftOffset
.getX()),
1350 basegfx::fround(aDestTopLeft
.getY() + nScaleY
*aUpperLeftOffset
.getY()),
1351 basegfx::fround(aDestTopLeft
.getX() + nScaleX
*aLowerRightOffset
.getX()),
1352 basegfx::fround(aDestTopLeft
.getY() + nScaleY
*aLowerRightOffset
.getY()) );
1354 // clip dest area (which must be inside rDestBounds)
1355 aLocalDestArea
.intersect( rDestBounds
);
1357 if( aLocalDestArea
.isEmpty() )
1360 // calc relative new dest area points (relative to orig
1362 const ::basegfx::B2IVector
aDestUpperLeftOffset(
1363 aLocalDestArea
.getMinimum()-aDestTopLeft
);
1364 const ::basegfx::B2IVector
aDestLowerRightOffset(
1365 aLocalDestArea
.getMaximum()-aDestTopLeft
);
1367 io_rSourceArea
= ::basegfx::B2IRange( basegfx::fround(aSourceTopLeft
.getX() + aDestUpperLeftOffset
.getX()/nScaleX
),
1368 basegfx::fround(aSourceTopLeft
.getY() + aDestUpperLeftOffset
.getY()/nScaleY
),
1369 basegfx::fround(aSourceTopLeft
.getX() + aDestLowerRightOffset
.getX()/nScaleX
),
1370 basegfx::fround(aSourceTopLeft
.getY() + aDestLowerRightOffset
.getY()/nScaleY
) );
1371 io_rDestArea
= aLocalDestArea
;
1373 // final source area clip (chopping round-offs)
1374 io_rSourceArea
.intersect( rSourceBounds
);
1376 if( io_rSourceArea
.isEmpty() )
1384 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr
& rSrcBitmap
,
1385 const basegfx::B2IRange
& rSrcRect
,
1386 const basegfx::B2IRange
& rDstRect
,
1389 const basegfx::B2IVector
& rSrcSize( rSrcBitmap
->getSize() );
1390 const basegfx::B2IRange
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1391 basegfx::B2IRange
aSrcRange( rSrcRect
);
1392 basegfx::B2IRange
aDestRange( rDstRect
);
1394 if( clipAreaImpl( aDestRange
,
1399 assertImageRange(aDestRange
,mpImpl
->maBounds
);
1400 assertImageRange(aSrcRange
,aSrcBounds
);
1402 drawBitmap_i( rSrcBitmap
, aSrcRange
, aDestRange
, drawMode
);
1406 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr
& rSrcBitmap
,
1407 const basegfx::B2IRange
& rSrcRect
,
1408 const basegfx::B2IRange
& rDstRect
,
1410 const BitmapDeviceSharedPtr
& rClip
)
1414 drawBitmap(rSrcBitmap
,rSrcRect
,rDstRect
,drawMode
);
1418 const basegfx::B2IVector
& rSrcSize( rSrcBitmap
->getSize() );
1419 const basegfx::B2IRange
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1420 basegfx::B2IRange
aSrcRange( rSrcRect
);
1421 basegfx::B2IRange
aDestRange( rDstRect
);
1423 if( clipAreaImpl( aDestRange
,
1428 assertImageRange(aDestRange
,mpImpl
->maBounds
);
1429 assertImageRange(aSrcRange
,aSrcBounds
);
1431 if( isCompatibleClipMask( rClip
) )
1433 drawBitmap_i( rSrcBitmap
, aSrcRange
, aDestRange
, drawMode
, rClip
);
1437 getGenericRenderer()->drawBitmap( rSrcBitmap
, rSrcRect
,
1438 rDstRect
, drawMode
, rClip
);
1443 void BitmapDevice::drawMaskedColor( Color aSrcColor
,
1444 const BitmapDeviceSharedPtr
& rAlphaMask
,
1445 const basegfx::B2IRange
& rSrcRect
,
1446 const basegfx::B2IPoint
& rDstPoint
)
1448 const basegfx::B2IVector
& rSrcSize( rAlphaMask
->getSize() );
1449 const basegfx::B2IRange
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1450 basegfx::B2IRange
aSrcRange( rSrcRect
);
1451 basegfx::B2IPoint
aDestPoint( rDstPoint
);
1453 if( clipAreaImpl( aSrcRange
,
1458 assertImagePoint(aDestPoint
,mpImpl
->maBounds
);
1459 assertImageRange(aSrcRange
,aSrcBounds
);
1461 if( rAlphaMask
.get() == this )
1463 // src == dest, copy rAlphaMask beforehand
1464 // ---------------------------------------------------
1466 const basegfx::B2ITuple
aSize( aSrcRange
.getWidth(),
1467 aSrcRange
.getHeight() );
1468 BitmapDeviceSharedPtr
pAlphaCopy(
1469 cloneBitmapDevice( aSize
,
1470 shared_from_this()) );
1471 basegfx::B2ITuple aGcc3WorkaroundTemporary
;
1472 const basegfx::B2IRange
aAlphaRange( aGcc3WorkaroundTemporary
,
1474 pAlphaCopy
->drawBitmap(rAlphaMask
,
1478 drawMaskedColor_i( aSrcColor
, pAlphaCopy
, aAlphaRange
, aDestPoint
);
1482 drawMaskedColor_i( aSrcColor
, rAlphaMask
, aSrcRange
, aDestPoint
);
1487 void BitmapDevice::drawMaskedColor( Color aSrcColor
,
1488 const BitmapDeviceSharedPtr
& rAlphaMask
,
1489 const basegfx::B2IRange
& rSrcRect
,
1490 const basegfx::B2IPoint
& rDstPoint
,
1491 const BitmapDeviceSharedPtr
& rClip
)
1495 drawMaskedColor(aSrcColor
,rAlphaMask
,rSrcRect
,rDstPoint
);
1499 const basegfx::B2IVector
& rSrcSize( rAlphaMask
->getSize() );
1500 const basegfx::B2IRange
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1501 basegfx::B2IRange
aSrcRange( rSrcRect
);
1502 basegfx::B2IPoint
aDestPoint( rDstPoint
);
1504 if( clipAreaImpl( aSrcRange
,
1509 assertImagePoint(aDestPoint
,mpImpl
->maBounds
);
1510 assertImageRange(aSrcRange
,aSrcBounds
);
1512 if( isCompatibleClipMask( rClip
) )
1514 if( rAlphaMask
.get() == this )
1516 // src == dest, copy rAlphaMask beforehand
1517 // ---------------------------------------------------
1519 const basegfx::B2ITuple
aSize( aSrcRange
.getWidth(),
1520 aSrcRange
.getHeight() );
1521 BitmapDeviceSharedPtr
pAlphaCopy(
1522 cloneBitmapDevice( aSize
,
1523 shared_from_this()) );
1524 basegfx::B2ITuple aGcc3WorkaroundTemporary
;
1525 const basegfx::B2IRange
aAlphaRange( aGcc3WorkaroundTemporary
,
1527 pAlphaCopy
->drawBitmap(rAlphaMask
,
1531 drawMaskedColor_i( aSrcColor
, pAlphaCopy
, aAlphaRange
, aDestPoint
, rClip
);
1535 drawMaskedColor_i( aSrcColor
, rAlphaMask
, aSrcRange
, aDestPoint
, rClip
);
1540 getGenericRenderer()->drawMaskedColor( aSrcColor
, rAlphaMask
,
1541 rSrcRect
, rDstPoint
, rClip
);
1546 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr
& rSrcBitmap
,
1547 const BitmapDeviceSharedPtr
& rMask
,
1548 const basegfx::B2IRange
& rSrcRect
,
1549 const basegfx::B2IRange
& rDstRect
,
1552 OSL_ASSERT( rMask
->getSize() == rSrcBitmap
->getSize() );
1554 const basegfx::B2IVector
& rSrcSize( rSrcBitmap
->getSize() );
1555 const basegfx::B2IRange
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1556 basegfx::B2IRange
aSrcRange( rSrcRect
);
1557 basegfx::B2IRange
aDestRange( rDstRect
);
1559 if( clipAreaImpl( aDestRange
,
1564 assertImageRange(aDestRange
,mpImpl
->maBounds
);
1565 assertImageRange(aSrcRange
,aSrcBounds
);
1567 drawMaskedBitmap_i( rSrcBitmap
, rMask
, aSrcRange
, aDestRange
, drawMode
);
1571 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr
& rSrcBitmap
,
1572 const BitmapDeviceSharedPtr
& rMask
,
1573 const basegfx::B2IRange
& rSrcRect
,
1574 const basegfx::B2IRange
& rDstRect
,
1576 const BitmapDeviceSharedPtr
& rClip
)
1580 drawMaskedBitmap(rSrcBitmap
,rMask
,rSrcRect
,rDstRect
,drawMode
);
1584 OSL_ASSERT( rMask
->getSize() == rSrcBitmap
->getSize() );
1586 const basegfx::B2IVector
& rSrcSize( rSrcBitmap
->getSize() );
1587 const basegfx::B2IRange
aSrcBounds( 0,0,rSrcSize
.getX(),rSrcSize
.getY() );
1588 basegfx::B2IRange
aSrcRange( rSrcRect
);
1589 basegfx::B2IRange
aDestRange( rDstRect
);
1591 if( clipAreaImpl( aDestRange
,
1596 assertImageRange(aDestRange
,mpImpl
->maBounds
);
1597 assertImageRange(aSrcRange
,aSrcBounds
);
1599 if( isCompatibleClipMask( rClip
) )
1601 drawMaskedBitmap_i( rSrcBitmap
, rMask
, aSrcRange
, aDestRange
, drawMode
, rClip
);
1605 getGenericRenderer()->drawMaskedBitmap( rSrcBitmap
, rMask
, rSrcRect
,
1606 rDstRect
, drawMode
, rClip
);
1612 //----------------------------------------------------------------------------------
1614 /** Standard clip and alpha masks
1618 typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits
;
1619 typedef PixelFormatTraits_GREY8 alphamask_format_traits
;
1621 /// Clipmask: 0 means opaque
1622 static const bool clipmask_polarity
= false;
1624 /// Alpha mask: 0 means fully transparent
1625 static const bool alphamask_polarity
= true;
1629 /** Clip and alpha masks for the generic renderer (of course, those
1630 need to be generic, too)
1632 struct MaskTraitsGeneric
1634 typedef PixelFormatTraits_GenericInteger clipmask_format_traits
;
1635 typedef PixelFormatTraits_GenericInteger alphamask_format_traits
;
1639 //----------------------------------------------------------------------------------
1641 // Some compilers don't like the nested template wrap_accessor
1642 // reference in the parameter list - being slightly less type safe,
1644 #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
1646 /// Produces a specialized renderer for the given pixel format
1647 template< class FormatTraits
, class MaskTraits
>
1648 BitmapDeviceSharedPtr
createRenderer(
1649 const basegfx::B2IRange
& rBounds
,
1650 sal_Int32 nScanlineFormat
,
1651 sal_Int32 nScanlineStride
,
1652 sal_uInt8
* pFirstScanline
,
1653 typename
FormatTraits::raw_accessor_type
const& rRawAccessor
,
1654 typename
FormatTraits::accessor_selector::template wrap_accessor
<
1655 typename
FormatTraits::raw_accessor_type
>::type
const& rAccessor
,
1656 boost::shared_array
< sal_uInt8
> pMem
,
1657 const PaletteMemorySharedVector
& pPal
)
1661 template< class FormatTraits
, class MaskTraits
, class Accessor
>
1662 BitmapDeviceSharedPtr
createRenderer(
1663 const basegfx::B2IRange
& rBounds
,
1664 sal_Int32 nScanlineFormat
,
1665 sal_Int32 nScanlineStride
,
1666 sal_uInt8
* pFirstScanline
,
1667 typename
FormatTraits::raw_accessor_type
const& rRawAccessor
,
1668 Accessor
const& rAccessor
,
1669 boost::shared_array
< sal_uInt8
> pMem
,
1670 const PaletteMemorySharedVector
& pPal
)
1674 typedef typename
FormatTraits::iterator_type Iterator
;
1675 typedef BitmapRenderer
< Iterator
,
1676 typename
FormatTraits::raw_accessor_type
,
1677 typename
FormatTraits::accessor_selector
,
1678 MaskTraits
> Renderer
;
1680 return BitmapDeviceSharedPtr(
1681 new Renderer( rBounds
,
1686 reinterpret_cast<typename
Iterator::value_type
*>(
1695 /// Create standard grey level palette
1696 PaletteMemorySharedVector
createStandardPalette(
1697 const PaletteMemorySharedVector
& pPal
,
1698 sal_Int32 nNumEntries
)
1700 if( pPal
|| nNumEntries
<= 0 )
1703 boost::shared_ptr
< std::vector
<Color
> > pLocalPal(
1704 new std::vector
<Color
>(nNumEntries
) );
1706 const sal_Int32
nIncrement( 0x00FFFFFF/nNumEntries
);
1708 for( sal_Int32 i
=0, c
=0; i
<nNumEntries
; ++i
,c
+=nIncrement
)
1709 pLocalPal
->at(i
) = Color(0xFF000000 | c
);
1711 pLocalPal
->at(nNumEntries
) = Color(0xFFFFFFFF);
1716 template< class FormatTraits
, class MaskTraits
>
1717 BitmapDeviceSharedPtr
createRenderer(
1718 const basegfx::B2IRange
& rBounds
,
1719 sal_Int32 nScanlineFormat
,
1720 sal_Int32 nScanlineStride
,
1721 sal_uInt8
* pFirstScanline
,
1722 boost::shared_array
< sal_uInt8
> pMem
,
1723 const PaletteMemorySharedVector
& pPal
)
1725 return createRenderer
<FormatTraits
,
1726 MaskTraits
>(rBounds
,
1730 typename
FormatTraits::raw_accessor_type(),
1731 typename
FormatTraits::accessor_selector::template
1733 typename
FormatTraits::raw_accessor_type
>::type(),
1738 template< class FormatTraits
, class MaskTraits
>
1739 BitmapDeviceSharedPtr
createRenderer(
1740 const basegfx::B2IRange
& rBounds
,
1741 sal_Int32 nScanlineFormat
,
1742 sal_Int32 nScanlineStride
,
1743 sal_uInt8
* pFirstScanline
,
1744 boost::shared_array
< sal_uInt8
> pMem
,
1745 PaletteMemorySharedVector pPal
,
1748 pPal
= createStandardPalette(pPal
,
1749 1UL << nBitsPerPixel
);
1752 return createRenderer
<FormatTraits
,
1753 MaskTraits
>(rBounds
,
1757 typename
FormatTraits::raw_accessor_type(),
1758 typename
FormatTraits::accessor_selector::template
1760 typename
FormatTraits::raw_accessor_type
>::type(
1767 //----------------------------------------------------------------------------------
1769 // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
1770 // to o3tl or sal/bithacks.hxx ...
1772 /** Compute the next highest power of 2 of a 32-bit value
1774 Code devised by Sean Anderson, in good ole HAKMEM
1777 @return 1 << (lg(x - 1) + 1)
1779 inline sal_uInt32
nextPow2( sal_uInt32 x
)
1791 //----------------------------------------------------------------------------------
1795 BitmapDeviceSharedPtr
createBitmapDeviceImpl( const basegfx::B2IVector
& rSize
,
1797 sal_Int32 nScanlineFormat
,
1798 boost::shared_array
< sal_uInt8
> pMem
,
1799 PaletteMemorySharedVector pPal
,
1800 const basegfx::B2IRange
* pSubset
)
1802 if( nScanlineFormat
<= Format::NONE
||
1803 nScanlineFormat
> Format::MAX
)
1804 return BitmapDeviceSharedPtr();
1806 static const sal_uInt8 bitsPerPixel
[] =
1809 1, // ONE_BIT_MSB_GREY
1810 1, // ONE_BIT_LSB_GREY
1811 1, // ONE_BIT_MSB_PAL
1812 1, // ONE_BIT_LSB_PAL
1813 4, // FOUR_BIT_MSB_GREY
1814 4, // FOUR_BIT_LSB_GREY
1815 4, // FOUR_BIT_MSB_PAL
1816 4, // FOUR_BIT_LSB_PAL
1818 8, // EIGHT_BIT_GREY
1819 16, // SIXTEEN_BIT_LSB_TC_MASK
1820 16, // SIXTEEN_BIT_MSB_TC_MASK
1821 24, // TWENTYFOUR_BIT_TC_MASK
1822 32, // THIRTYTWO_BIT_TC_MASK
1823 32, // THIRTYTWO_BIT_TC_MASK_ARGB
1826 sal_Int32
nScanlineStride(0);
1828 // round up to full 8 bit, divide by 8
1829 nScanlineStride
= (rSize
.getX()*bitsPerPixel
[nScanlineFormat
] + 7) >> 3;
1831 // rounded up to next full power-of-two number of bytes
1832 const sal_uInt32 bytesPerPixel
= nextPow2(
1833 (bitsPerPixel
[nScanlineFormat
] + 7) >> 3);
1835 // now make nScanlineStride a multiple of bytesPerPixel
1836 nScanlineStride
= (nScanlineStride
+ bytesPerPixel
- 1) / bytesPerPixel
* bytesPerPixel
;
1838 // factor in bottom-up scanline order case
1839 nScanlineStride
*= bTopDown
? 1 : -1;
1841 const std::size_t nMemSize(
1842 (nScanlineStride
< 0 ? -nScanlineStride
: nScanlineStride
)*rSize
.getY() );
1847 reinterpret_cast<sal_uInt8
*>(rtl_allocateMemory( nMemSize
)),
1849 rtl_zeroMemory(pMem
.get(),nMemSize
);
1852 sal_uInt8
* pFirstScanline
= nScanlineStride
< 0 ?
1853 pMem
.get() + nMemSize
+ nScanlineStride
: pMem
.get();
1855 // shrink render area to given subset, if given
1856 basegfx::B2IRange
aBounds(0,0,rSize
.getX(),rSize
.getY());
1858 aBounds
.intersect( *pSubset
);
1860 switch( nScanlineFormat
)
1862 // ----------------------------------------------------------------------
1865 case Format::ONE_BIT_MSB_GREY
:
1866 return createRenderer
<PixelFormatTraits_GREY1_MSB
,StdMasks
>(
1867 aBounds
, nScanlineFormat
, nScanlineStride
,
1868 pFirstScanline
, pMem
, pPal
);
1870 case Format::ONE_BIT_LSB_GREY
:
1871 return createRenderer
<PixelFormatTraits_GREY1_LSB
,StdMasks
>(
1872 aBounds
, nScanlineFormat
, nScanlineStride
,
1873 pFirstScanline
, pMem
, pPal
);
1875 case Format::ONE_BIT_MSB_PAL
:
1876 return createRenderer
<PixelFormatTraits_PAL1_MSB
,StdMasks
>(
1877 aBounds
, nScanlineFormat
, nScanlineStride
,
1878 pFirstScanline
, pMem
, pPal
,
1879 bitsPerPixel
[nScanlineFormat
] );
1881 case Format::ONE_BIT_LSB_PAL
:
1882 return createRenderer
<PixelFormatTraits_PAL1_LSB
,StdMasks
>(
1883 aBounds
, nScanlineFormat
, nScanlineStride
,
1884 pFirstScanline
, pMem
, pPal
,
1885 bitsPerPixel
[nScanlineFormat
] );
1888 // ----------------------------------------------------------------------
1891 case Format::FOUR_BIT_MSB_GREY
:
1892 return createRenderer
<PixelFormatTraits_GREY4_MSB
,StdMasks
>(
1893 aBounds
, nScanlineFormat
, nScanlineStride
,
1894 pFirstScanline
, pMem
, pPal
);
1896 case Format::FOUR_BIT_LSB_GREY
:
1897 return createRenderer
<PixelFormatTraits_GREY4_LSB
,StdMasks
>(
1898 aBounds
, nScanlineFormat
, nScanlineStride
,
1899 pFirstScanline
, pMem
, pPal
);
1901 case Format::FOUR_BIT_MSB_PAL
:
1902 return createRenderer
<PixelFormatTraits_PAL4_MSB
,StdMasks
>(
1903 aBounds
, nScanlineFormat
, nScanlineStride
,
1904 pFirstScanline
, pMem
, pPal
,
1905 bitsPerPixel
[nScanlineFormat
] );
1907 case Format::FOUR_BIT_LSB_PAL
:
1908 return createRenderer
<PixelFormatTraits_PAL4_LSB
,StdMasks
>(
1909 aBounds
, nScanlineFormat
, nScanlineStride
,
1910 pFirstScanline
, pMem
, pPal
,
1911 bitsPerPixel
[nScanlineFormat
] );
1914 // ----------------------------------------------------------------------
1915 // eight bit formats
1917 case Format::EIGHT_BIT_GREY
:
1918 return createRenderer
<PixelFormatTraits_GREY8
,StdMasks
>(
1919 aBounds
, nScanlineFormat
, nScanlineStride
,
1920 pFirstScanline
, pMem
, pPal
);
1922 case Format::EIGHT_BIT_PAL
:
1923 return createRenderer
<PixelFormatTraits_PAL8
,StdMasks
>(
1924 aBounds
, nScanlineFormat
, nScanlineStride
,
1925 pFirstScanline
, pMem
, pPal
,
1926 bitsPerPixel
[nScanlineFormat
] );
1929 // ----------------------------------------------------------------------
1930 // sixteen bit formats
1932 case Format::SIXTEEN_BIT_LSB_TC_MASK
:
1933 return createRenderer
<PixelFormatTraits_RGB16_565_LSB
,StdMasks
>(
1934 aBounds
, nScanlineFormat
, nScanlineStride
,
1935 pFirstScanline
, pMem
, pPal
);
1937 case Format::SIXTEEN_BIT_MSB_TC_MASK
:
1938 return createRenderer
<PixelFormatTraits_RGB16_565_MSB
,StdMasks
>(
1939 aBounds
, nScanlineFormat
, nScanlineStride
,
1940 pFirstScanline
, pMem
, pPal
);
1943 // ----------------------------------------------------------------------
1944 // twentyfour bit formats
1945 case Format::TWENTYFOUR_BIT_TC_MASK
:
1946 return createRenderer
<PixelFormatTraits_BGR24
,StdMasks
>(
1947 aBounds
, nScanlineFormat
, nScanlineStride
,
1948 pFirstScanline
, pMem
, pPal
);
1951 // ----------------------------------------------------------------------
1952 // thirtytwo bit formats
1954 case Format::THIRTYTWO_BIT_TC_MASK
:
1955 return createRenderer
<PixelFormatTraits_RGB32_888
,StdMasks
>(
1956 aBounds
, nScanlineFormat
, nScanlineStride
,
1957 pFirstScanline
, pMem
, pPal
);
1959 case Format::THIRTYTWO_BIT_TC_MASK_ARGB
:
1960 return createRenderer
<PixelFormatTraits_BGR32_888
,StdMasks
>(
1961 aBounds
, nScanlineFormat
, nScanlineStride
,
1962 pFirstScanline
, pMem
, pPal
);
1965 // TODO(F3): other formats not yet implemented
1966 return BitmapDeviceSharedPtr();
1971 BitmapDeviceSharedPtr
createBitmapDevice( const basegfx::B2IVector
& rSize
,
1973 sal_Int32 nScanlineFormat
)
1975 return createBitmapDeviceImpl( rSize
,
1978 boost::shared_array
< sal_uInt8
>(),
1979 PaletteMemorySharedVector(),
1983 BitmapDeviceSharedPtr
createBitmapDevice( const basegfx::B2IVector
& rSize
,
1985 sal_Int32 nScanlineFormat
,
1986 const PaletteMemorySharedVector
& rPalette
)
1988 return createBitmapDeviceImpl( rSize
,
1991 boost::shared_array
< sal_uInt8
>(),
1996 BitmapDeviceSharedPtr
createBitmapDevice( const basegfx::B2IVector
& rSize
,
1998 sal_Int32 nScanlineFormat
,
1999 const RawMemorySharedArray
& rMem
,
2000 const PaletteMemorySharedVector
& rPalette
)
2002 return createBitmapDeviceImpl( rSize
,
2010 BitmapDeviceSharedPtr
subsetBitmapDevice( const BitmapDeviceSharedPtr
& rProto
,
2011 const basegfx::B2IRange
& rSubset
)
2013 return createBitmapDeviceImpl( rProto
->getSize(),
2014 rProto
->isTopDown(),
2015 rProto
->getScanlineFormat(),
2016 rProto
->getBuffer(),
2017 rProto
->getPalette(),
2021 BitmapDeviceSharedPtr
cloneBitmapDevice( const basegfx::B2IVector
& rSize
,
2022 const BitmapDeviceSharedPtr
& rProto
)
2024 return createBitmapDeviceImpl( rSize
,
2025 rProto
->isTopDown(),
2026 rProto
->getScanlineFormat(),
2027 boost::shared_array
< sal_uInt8
>(),
2028 rProto
->getPalette(),
2032 //----------------------------------------------------------------------------------
2034 /// Clone our device, with GenericImageAccessor to handle all formats
2035 BitmapDeviceSharedPtr
BitmapDevice::getGenericRenderer() const
2039 typedef BitmapRenderer
< PixelFormatTraits_GenericInteger::iterator_type
,
2040 PixelFormatTraits_GenericInteger::raw_accessor_type
,
2041 PixelFormatTraits_GenericInteger::accessor_selector
,
2045 if( !mpImpl
->mpGenericRenderer
)
2047 mpImpl
->mpGenericRenderer
.reset(
2051 getScanlineFormat(),
2052 getScanlineStride(),
2053 mpImpl
->mpFirstScanline
,
2054 PixelFormatTraits_GenericInteger::iterator_type(),
2055 GenericIntegerImageRawAccessor
<Color
>(
2056 const_cast<BitmapDevice
*>(this)->shared_from_this()),
2057 GenericIntegerImageAccessor
<Color
>(
2058 const_cast<BitmapDevice
*>(this)->shared_from_this()),
2064 return mpImpl
->mpGenericRenderer
;
2067 } // namespace basebmp