bump product version to 4.2.0.1
[LibreOffice.git] / basebmp / source / bitmapdevice.cxx
blob4b86231e6288efecb6391bf64966528ab14cfe9b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <cassert>
23 #include <string.h>
25 #include <basebmp/bitmapdevice.hxx>
27 #include <basebmp/compositeiterator.hxx>
28 #include <basebmp/iteratortraits.hxx>
30 #include <basebmp/accessor.hxx>
31 #include <basebmp/accessortraits.hxx>
32 #include <basebmp/accessoradapters.hxx>
33 #include <basebmp/colorblendaccessoradapter.hxx>
35 #include <basebmp/color.hxx>
36 #include <basebmp/colormisc.hxx>
37 #include <basebmp/colortraits.hxx>
39 #include <basebmp/greylevelformats.hxx>
40 #include <basebmp/paletteformats.hxx>
41 #include <basebmp/rgbmaskpixelformats.hxx>
42 #include <basebmp/rgb24pixelformats.hxx>
44 #include <basebmp/scanlineformats.hxx>
45 #include <basebmp/fillimage.hxx>
46 #include <basebmp/scaleimage.hxx>
47 #include <basebmp/clippedlinerenderer.hxx>
48 #include <basebmp/polypolygonrenderer.hxx>
49 #include <basebmp/genericcolorimageaccessor.hxx>
51 #include <basebmp/tools.hxx>
52 #include "intconversion.hxx"
54 #include <rtl/alloc.h>
55 #include <osl/diagnose.h>
57 #include <basegfx/tools/tools.hxx>
58 #include <basegfx/tools/canvastools.hxx>
59 #include <basegfx/range/b2ibox.hxx>
60 #include <basegfx/range/b2irange.hxx>
61 #include <basegfx/range/b2drange.hxx>
62 #include <basegfx/polygon/b2dpolygon.hxx>
63 #include <basegfx/polygon/b2dpolygontools.hxx>
64 #include <basegfx/polygon/b2dpolypolygontools.hxx>
65 #include <basegfx/point/b2ipoint.hxx>
66 #include <basegfx/vector/b2ivector.hxx>
68 #include <vigra/iteratortraits.hxx>
69 #include <vigra/rgbvalue.hxx>
70 #include <vigra/copyimage.hxx>
71 #include <vigra/tuple.hxx>
74 namespace vigra
77 /// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
78 template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex >
79 inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex>
80 operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs,
81 RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs )
83 RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res(
84 lhs[0] ^ rhs[0],
85 lhs[1] ^ rhs[1],
86 lhs[2] ^ rhs[2]);
87 return res;
91 namespace basebmp
94 static const sal_uInt8 bitsPerPixel[] =
96 0, // NONE
97 1, // ONE_BIT_MSB_GREY
98 1, // ONE_BIT_LSB_GREY
99 1, // ONE_BIT_MSB_PAL
100 1, // ONE_BIT_LSB_PAL
101 4, // FOUR_BIT_MSB_GREY
102 4, // FOUR_BIT_LSB_GREY
103 4, // FOUR_BIT_MSB_PAL
104 4, // FOUR_BIT_LSB_PAL
105 8, // EIGHT_BIT_PAL
106 8, // EIGHT_BIT_GREY
107 16, // SIXTEEN_BIT_LSB_TC_MASK
108 16, // SIXTEEN_BIT_MSB_TC_MASK
109 24, // TWENTYFOUR_BIT_TC_MASK
110 32, // THIRTYTWO_BIT_TC_MASK_BGRA
111 32, // THIRTYTWO_BIT_TC_MASK_ARGB
112 32, // THIRTYTWO_BIT_TC_MASK_ABGR
113 32, // THIRTYTWO_BIT_TC_MASK_RGBA
116 namespace
118 /** Create the type for an accessor that takes the (mask,bitmap)
119 input value generated from a JoinImageAccessorAdapter, and
120 pipe that through a mask functor.
122 @tpl DestAccessor
123 Destination bitmap accessor
125 @tpl JoinedAccessor
126 Input accessor, is expected to generate a std::pair as the
127 value type
129 @tpl MaskFunctorMode
130 Either FastMask or NoFastMask, depending on whether the mask
131 is guaranteed to contain only 0s and 1s.
133 template< class DestAccessor,
134 class JoinedAccessor,
135 bool polarity,
136 typename MaskFunctorMode > struct masked_input_splitting_accessor
138 typedef BinarySetterFunctionAccessorAdapter<
139 DestAccessor,
140 BinaryFunctorSplittingWrapper<
141 typename outputMaskFunctorSelector<
142 typename JoinedAccessor::value_type::first_type,
143 typename JoinedAccessor::value_type::second_type,
144 polarity,
145 MaskFunctorMode >::type > > type;
150 // Actual BitmapDevice implementation (templatized by accessor and iterator)
152 /** Implementation of the BitmapDevice interface
154 @tpl DestIterator
155 Iterator to access bitmap memory
157 @tpl RawAccessor
158 Raw accessor, to access pixel values directly
160 @tpl AccessorSelector
161 Accessor adapter selector, which, when applying the nested
162 template metafunction wrap_accessor to one of the raw bitmap
163 accessors, yields a member type named 'type', which is a
164 wrapped accessor that map color values.
166 @tpl Masks
167 Traits template, containing nested traits
168 clipmask_format_traits and alphamask_format_traits, which
169 determine what specialized formats are to be used for clip and
170 alpha masks. With those mask formats, clipping and alpha
171 blending is handled natively.
173 template< class DestIterator,
174 class RawAccessor,
175 class AccessorSelector,
176 class Masks > class BitmapRenderer :
177 public BitmapDevice
179 public:
180 typedef DestIterator dest_iterator_type;
181 typedef RawAccessor raw_accessor_type;
182 typedef AccessorSelector accessor_selector;
184 typedef typename Masks::clipmask_format_traits::iterator_type mask_iterator_type;
185 typedef typename Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type;
186 typedef typename Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type;
188 typedef typename Masks::alphamask_format_traits::iterator_type alphamask_iterator_type;
189 typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type;
190 typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type;
192 typedef typename AccessorSelector::template wrap_accessor<
193 raw_accessor_type >::type dest_accessor_type;
195 typedef AccessorTraits< dest_accessor_type > accessor_traits;
196 typedef CompositeIterator2D< dest_iterator_type,
197 mask_iterator_type > composite_iterator_type;
198 typedef CompositeIterator2D< vigra::Diff2D,
199 vigra::Diff2D > generic_composite_iterator_type;
201 typedef BitmapRenderer<mask_iterator_type,
202 mask_rawaccessor_type,
203 mask_accessorselector_type,
204 Masks> mask_bitmap_type;
205 typedef BitmapRenderer<alphamask_iterator_type,
206 alphamask_rawaccessor_type,
207 alphamask_accessorselector_type,
208 Masks> alphamask_bitmap_type;
210 // -------------------------------------------------------
212 typedef AccessorTraits< raw_accessor_type > raw_accessor_traits;
213 typedef typename uInt32Converter<
214 typename raw_accessor_type::value_type>::to to_uint32_functor;
216 // -------------------------------------------------------
218 typedef typename raw_accessor_traits::xor_accessor raw_xor_accessor_type;
219 typedef AccessorTraits<raw_xor_accessor_type> raw_xor_accessor_traits;
220 typedef typename accessor_selector::template wrap_accessor<
221 raw_xor_accessor_type >::type xor_accessor_type;
222 typedef AccessorTraits<xor_accessor_type> xor_accessor_traits;
224 // -------------------------------------------------------
226 typedef typename raw_accessor_traits::template masked_accessor<
227 mask_rawaccessor_type,
228 dest_iterator_type,
229 mask_iterator_type,
230 Masks::clipmask_polarity>::type raw_maskedaccessor_type;
231 typedef typename accessor_selector::template wrap_accessor<
232 raw_maskedaccessor_type >::type masked_accessor_type;
233 typedef typename AccessorTraits<
234 raw_maskedaccessor_type>::xor_accessor raw_maskedxor_accessor_type;
235 typedef typename accessor_selector::template wrap_accessor<
236 raw_maskedxor_accessor_type >::type masked_xoraccessor_type;
238 // -------------------------------------------------------
240 // ((iter,mask),mask) special case (e.g. for clipped
241 // drawMaskedColor())
242 typedef AccessorTraits< raw_maskedaccessor_type > raw_maskedaccessor_traits;
243 typedef typename raw_maskedaccessor_traits::template masked_accessor<
244 mask_rawaccessor_type,
245 composite_iterator_type,
246 mask_iterator_type,
247 Masks::clipmask_polarity>::type raw_maskedmask_accessor_type;
249 typedef CompositeIterator2D<
250 composite_iterator_type,
251 mask_iterator_type> composite_composite_mask_iterator_type;
253 // -------------------------------------------------------
255 typedef ConstantColorBlendSetterAccessorAdapter<
256 dest_accessor_type,
257 typename alphamask_rawaccessor_type::value_type,
258 Masks::alphamask_polarity> colorblend_accessor_type;
259 typedef AccessorTraits<colorblend_accessor_type> colorblend_accessor_traits;
260 typedef typename colorblend_accessor_traits::template masked_accessor<
261 mask_rawaccessor_type,
262 dest_iterator_type,
263 mask_iterator_type,
264 Masks::clipmask_polarity>::type masked_colorblend_accessor_type;
266 // -------------------------------------------------------
268 typedef ConstantColorBlendSetterAccessorAdapter<
269 dest_accessor_type,
270 Color,
271 Masks::alphamask_polarity> colorblend_generic_accessor_type;
272 typedef AccessorTraits<colorblend_generic_accessor_type> colorblend_generic_accessor_traits;
273 typedef typename colorblend_generic_accessor_traits::template masked_accessor<
274 mask_rawaccessor_type,
275 dest_iterator_type,
276 mask_iterator_type,
277 Masks::clipmask_polarity>::type masked_colorblend_generic_accessor_type;
279 // -------------------------------------------------------
281 typedef JoinImageAccessorAdapter< dest_accessor_type,
282 mask_rawaccessor_type > joined_image_accessor_type;
283 typedef JoinImageAccessorAdapter< GenericColorImageAccessor,
284 GenericColorImageAccessor > joined_generic_image_accessor_type;
286 // -------------------------------------------------------
288 dest_iterator_type maBegin;
289 typename accessor_traits::color_lookup maColorLookup;
290 IBitmapDeviceDamageTrackerSharedPtr mpDamage;
291 to_uint32_functor maToUInt32Converter;
292 dest_accessor_type maAccessor;
293 colorblend_accessor_type maColorBlendAccessor;
294 colorblend_generic_accessor_type maGenericColorBlendAccessor;
295 raw_accessor_type maRawAccessor;
296 xor_accessor_type maXorAccessor;
297 raw_xor_accessor_type maRawXorAccessor;
298 masked_accessor_type maMaskedAccessor;
299 masked_colorblend_accessor_type maMaskedColorBlendAccessor;
300 masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor;
301 masked_xoraccessor_type maMaskedXorAccessor;
302 raw_maskedaccessor_type maRawMaskedAccessor;
303 raw_maskedxor_accessor_type maRawMaskedXorAccessor;
304 raw_maskedmask_accessor_type maRawMaskedMaskAccessor;
307 // -------------------------------------------------------
309 BitmapRenderer( const basegfx::B2IBox& rBounds,
310 const basegfx::B2IVector& rBufferSize,
311 Format nScanlineFormat,
312 sal_Int32 nScanlineStride,
313 sal_uInt8* pFirstScanline,
314 dest_iterator_type begin,
315 raw_accessor_type rawAccessor,
316 dest_accessor_type accessor,
317 const RawMemorySharedArray& rMem,
318 const PaletteMemorySharedVector& rPalette,
319 const IBitmapDeviceDamageTrackerSharedPtr& rDamage ) :
320 BitmapDevice( rBounds, rBufferSize, nScanlineFormat,
321 nScanlineStride, pFirstScanline, rMem, rPalette ),
322 maBegin( begin ),
323 maColorLookup(),
324 mpDamage(rDamage),
325 maToUInt32Converter(),
326 maAccessor( accessor ),
327 maColorBlendAccessor( accessor ),
328 maGenericColorBlendAccessor( accessor ),
329 maRawAccessor( rawAccessor ),
330 maXorAccessor( accessor ),
331 maRawXorAccessor( rawAccessor ),
332 maMaskedAccessor( accessor ),
333 maMaskedColorBlendAccessor( maColorBlendAccessor ),
334 maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ),
335 maMaskedXorAccessor( accessor ),
336 maRawMaskedAccessor( rawAccessor ),
337 maRawMaskedXorAccessor( rawAccessor ),
338 maRawMaskedMaskAccessor( rawAccessor )
341 private:
343 void damaged( const basegfx::B2IBox& rDamageRect ) const
345 if( mpDamage )
346 mpDamage->damaged( rDamageRect );
349 void damagedPointSize( const basegfx::B2IPoint& rPoint,
350 const basegfx::B2IBox& rSize ) const
352 if( mpDamage ) {
353 basegfx::B2IPoint aLower( rPoint.getX() + rSize.getWidth(),
354 rPoint.getY() + rSize.getHeight() );
355 damaged( basegfx::B2IBox( rPoint, aLower ) );
359 void damagedPixel( const basegfx::B2IPoint& rDamagePoint ) const
361 if( !mpDamage )
362 return;
364 sal_Int32 nX(rDamagePoint.getX());
365 sal_Int32 nY(rDamagePoint.getY());
366 if (nX < SAL_MAX_INT32)
367 ++nX;
368 if (nY < SAL_MAX_INT32)
369 ++nY;
371 basegfx::B2IPoint aEnd( nX, nY );
372 damaged( basegfx::B2IBox( rDamagePoint, aEnd ) );
375 boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
377 return boost::dynamic_pointer_cast< BitmapRenderer >( bmp );
380 virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
382 // TODO(P1): dynamic_cast usually called twice for
383 // compatible formats
384 return getCompatibleBitmap(bmp).get() != NULL;
387 boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
389 boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ));
391 if( !pMask )
392 return pMask;
394 if( pMask->getSize() != getSize() )
395 pMask.reset();
397 return pMask;
400 virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
402 // TODO(P1): dynamic_cast usually called twice for
403 // compatible formats
404 return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL;
407 boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
409 return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp );
412 virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
414 // TODO(P1): dynamic_cast usually called twice for
415 // compatible formats
416 return getCompatibleAlphaMask( bmp ).get() != NULL;
419 virtual void clear_i( Color fillColor,
420 const basegfx::B2IBox& rBounds )
422 fillImage(destIterRange(maBegin,
423 maRawAccessor,
424 rBounds),
425 maColorLookup(
426 maAccessor,
427 fillColor) );
428 damaged( rBounds );
431 virtual void setPixel_i( const basegfx::B2IPoint& rPt,
432 Color pixelColor,
433 DrawMode drawMode )
435 const DestIterator pixel( maBegin +
436 vigra::Diff2D(rPt.getX(),
437 rPt.getY()) );
438 if( drawMode == DrawMode_XOR )
439 maXorAccessor.set( pixelColor,
440 pixel );
441 else
442 maAccessor.set( pixelColor,
443 pixel );
444 damagedPixel(rPt);
447 virtual void setPixel_i( const basegfx::B2IPoint& rPt,
448 Color pixelColor,
449 DrawMode drawMode,
450 const BitmapDeviceSharedPtr& rClip )
452 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
453 OSL_ASSERT( pMask );
455 const vigra::Diff2D offset(rPt.getX(),
456 rPt.getY());
458 const composite_iterator_type aIter(
459 maBegin + offset,
460 pMask->maBegin + offset );
462 if( drawMode == DrawMode_XOR )
463 maMaskedXorAccessor.set( pixelColor,
464 aIter );
465 else
466 maMaskedAccessor.set( pixelColor,
467 aIter );
468 damagedPixel(rPt);
471 virtual Color getPixel_i(const basegfx::B2IPoint& rPt )
473 const DestIterator pixel( maBegin +
474 vigra::Diff2D(rPt.getX(),
475 rPt.getY()) );
476 return maAccessor(pixel);
479 virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt )
481 const DestIterator pixel( maBegin +
482 vigra::Diff2D(rPt.getX(),
483 rPt.getY()) );
484 return maToUInt32Converter(maRawAccessor(pixel));
487 template< typename Iterator, typename Col, typename RawAcc >
488 void implRenderLine2( const basegfx::B2IPoint& rPt1,
489 const basegfx::B2IPoint& rPt2,
490 const basegfx::B2IBox& rBounds,
491 Col col,
492 const Iterator& begin,
493 const RawAcc& rawAcc )
495 renderClippedLine( rPt1,
496 rPt2,
497 rBounds,
498 col,
499 begin,
500 rawAcc );
501 // TODO(P2): perhaps this needs pushing up the stack a bit
502 // to make more complex polygons more efficient ...
503 damaged( basegfx::B2IBox( rPt1, rPt2 ) );
506 template< typename Iterator, typename Accessor, typename RawAcc >
507 void implRenderLine( const basegfx::B2IPoint& rPt1,
508 const basegfx::B2IPoint& rPt2,
509 const basegfx::B2IBox& rBounds,
510 Color col,
511 const Iterator& begin,
512 const Accessor& acc,
513 const RawAcc& rawAcc )
515 implRenderLine2( rPt1,rPt2,rBounds,
516 maColorLookup( acc,
517 col ),
518 begin,
519 rawAcc );
522 template< typename Iterator, typename RawAcc, typename XorAcc >
523 void implDrawLine( const basegfx::B2IPoint& rPt1,
524 const basegfx::B2IPoint& rPt2,
525 const basegfx::B2IBox& rBounds,
526 Color col,
527 const Iterator& begin,
528 const RawAcc& rawAcc,
529 const XorAcc& xorAcc,
530 DrawMode drawMode )
532 if( drawMode == DrawMode_XOR )
533 implRenderLine( rPt1, rPt2, rBounds, col,
534 begin, maAccessor, xorAcc );
535 else
536 implRenderLine( rPt1, rPt2, rBounds, col,
537 begin, maAccessor, rawAcc );
540 virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
541 const basegfx::B2IPoint& rPt2,
542 const basegfx::B2IBox& rBounds,
543 Color lineColor,
544 DrawMode drawMode )
546 implDrawLine(rPt1,rPt2,rBounds,lineColor,
547 maBegin,
548 maRawAccessor,maRawXorAccessor,drawMode);
551 composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const
553 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
554 OSL_ASSERT( pMask );
556 return composite_iterator_type( maBegin,
557 pMask->maBegin );
560 virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
561 const basegfx::B2IPoint& rPt2,
562 const basegfx::B2IBox& rBounds,
563 Color lineColor,
564 DrawMode drawMode,
565 const BitmapDeviceSharedPtr& rClip )
567 implDrawLine(rPt1,rPt2,rBounds,lineColor,
568 getMaskedIter(rClip),
569 maRawMaskedAccessor,
570 maRawMaskedXorAccessor,drawMode);
573 template< typename Iterator, typename RawAcc >
574 void implDrawPolygon( const basegfx::B2DPolygon& rPoly,
575 const basegfx::B2IBox& rBounds,
576 Color col,
577 const Iterator& begin,
578 const RawAcc& acc )
580 basegfx::B2DPolygon aPoly( rPoly );
581 if( rPoly.areControlPointsUsed() )
582 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
584 const typename dest_iterator_type::value_type colorIndex( maColorLookup(
585 maAccessor,
586 col));
587 const sal_uInt32 nVertices( aPoly.count() );
588 for( sal_uInt32 i=1; i<nVertices; ++i )
589 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)),
590 basegfx::fround(aPoly.getB2DPoint(i)),
591 rBounds,
592 colorIndex,
593 begin,
594 acc );
596 if( nVertices > 1 && aPoly.isClosed() )
597 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)),
598 basegfx::fround(aPoly.getB2DPoint(0)),
599 rBounds,
600 colorIndex,
601 begin,
602 acc );
605 virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
606 const basegfx::B2IBox& rBounds,
607 Color lineColor,
608 DrawMode drawMode )
610 if( drawMode == DrawMode_XOR )
611 implDrawPolygon( rPoly, rBounds, lineColor,
612 maBegin,
613 maRawXorAccessor );
614 else
615 implDrawPolygon( rPoly, rBounds, lineColor,
616 maBegin,
617 maRawAccessor );
620 virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
621 const basegfx::B2IBox& rBounds,
622 Color lineColor,
623 DrawMode drawMode,
624 const BitmapDeviceSharedPtr& rClip )
626 if( drawMode == DrawMode_XOR )
627 implDrawPolygon( rPoly, rBounds, lineColor,
628 getMaskedIter(rClip),
629 maRawMaskedXorAccessor );
630 else
631 implDrawPolygon( rPoly, rBounds, lineColor,
632 getMaskedIter(rClip),
633 maRawMaskedAccessor );
636 template< typename Iterator, typename RawAcc >
637 void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
638 Color col,
639 const Iterator& begin,
640 const RawAcc& acc,
641 const basegfx::B2IBox& rBounds )
643 basegfx::B2DPolyPolygon aPoly( rPoly );
644 if( rPoly.areControlPointsUsed() )
645 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
647 renderClippedPolyPolygon( begin,
648 acc,
649 maColorLookup( maAccessor,
650 col),
651 rBounds,
652 aPoly,
653 basegfx::FillRule_EVEN_ODD );
655 if( mpDamage )
657 basegfx::B2DRange const aPolyBounds( basegfx::tools::getRange(aPoly) );
658 damaged( basegfx::unotools::b2ISurroundingBoxFromB2DRange( aPolyBounds ) );
662 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
663 Color fillColor,
664 DrawMode drawMode,
665 const basegfx::B2IBox& rBounds )
667 if( drawMode == DrawMode_XOR )
668 implFillPolyPolygon( rPoly, fillColor,
669 maBegin,
670 maRawXorAccessor,
671 rBounds );
672 else
673 implFillPolyPolygon( rPoly, fillColor,
674 maBegin,
675 maRawAccessor,
676 rBounds );
679 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
680 Color fillColor,
681 DrawMode drawMode,
682 const basegfx::B2IBox& rBounds,
683 const BitmapDeviceSharedPtr& rClip )
685 if( drawMode == DrawMode_XOR )
686 implFillPolyPolygon( rPoly, fillColor,
687 getMaskedIter(rClip),
688 maRawMaskedXorAccessor,
689 rBounds );
690 else
691 implFillPolyPolygon( rPoly, fillColor,
692 getMaskedIter(rClip),
693 maRawMaskedAccessor,
694 rBounds );
697 template< typename Iterator, typename RawAcc >
698 void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
699 const basegfx::B2IBox& rSrcRect,
700 const basegfx::B2IBox& rDstRect,
701 const Iterator& begin,
702 const RawAcc& acc)
704 boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
705 OSL_ASSERT( pSrcBmp );
707 scaleImage(
708 srcIterRange(pSrcBmp->maBegin,
709 pSrcBmp->maRawAccessor,
710 rSrcRect),
711 destIterRange(begin,
712 acc,
713 rDstRect),
714 isSharedBuffer(rSrcBitmap) );
715 damaged( rDstRect );
718 template< typename Iterator, typename Acc >
719 void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
720 const basegfx::B2IBox& rSrcRect,
721 const basegfx::B2IBox& rDstRect,
722 const Iterator& begin,
723 const Acc& acc)
725 GenericColorImageAccessor aSrcAcc( rSrcBitmap );
727 scaleImage(
728 srcIterRange(vigra::Diff2D(),
729 aSrcAcc,
730 rSrcRect),
731 destIterRange(begin,
732 acc,
733 rDstRect));
734 damaged( rDstRect );
737 void implDrawBitmapDirect(const BitmapDeviceSharedPtr& rSrcBitmap,
738 const basegfx::B2IBox& rSrcRect,
739 const basegfx::B2IBox& rDstRect)
741 sal_Int32 nSrcX = rSrcRect.getMinX();
742 sal_Int32 nSrcY = rSrcRect.getMinY();
743 sal_Int32 nSrcWidth = rSrcRect.getWidth();
744 sal_Int32 nSrcHeight = rSrcRect.getHeight();
745 sal_Int32 nDestX = rDstRect.getMinX();
746 sal_Int32 nDestY = rDstRect.getMinY();
748 char* dstBuf = (char*)getBuffer().get();
749 char* srcBuf = (char*)rSrcBitmap->getBuffer().get();
750 sal_Int32 dstStride = getScanlineStride();
751 sal_Int32 srcStride = rSrcBitmap->getScanlineStride();
752 sal_Int32 bytesPerPixel = (bitsPerPixel[getScanlineFormat()] + 7) >> 3; // round up to bytes
753 bool dstTopDown = isTopDown();
754 bool srcTopDown = rSrcBitmap->isTopDown();
756 if (dstBuf == srcBuf && nSrcY < nDestY) // reverse copy order to avoid overlapping
758 nSrcY = getBufferSize().getY() - nSrcY - nSrcHeight;
759 nDestY = getBufferSize().getY() - nDestY - nSrcHeight;
760 srcTopDown = !srcTopDown;
761 dstTopDown = !dstTopDown;
764 if (!dstTopDown)
766 dstBuf += dstStride * (getBufferSize().getY() - 1);
767 dstStride = -dstStride;
770 if (!srcTopDown)
772 srcBuf += srcStride * (rSrcBitmap->getBufferSize().getY() - 1);
773 srcStride = -srcStride;
776 char* dstline = dstBuf + dstStride * nDestY + nDestX * bytesPerPixel;
777 char* srcline = srcBuf + srcStride * nSrcY + nSrcX * bytesPerPixel;
778 sal_Int32 lineBytes = nSrcWidth * bytesPerPixel;
780 for(; 0 < nSrcHeight; nSrcHeight--)
782 memmove(dstline, srcline, lineBytes);
783 dstline += dstStride;
784 srcline += srcStride;
788 virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
789 const basegfx::B2IBox& rSrcRect,
790 const basegfx::B2IBox& rDstRect,
791 DrawMode drawMode )
793 if( isCompatibleBitmap( rSrcBitmap ) )
795 if( drawMode == DrawMode_XOR )
796 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
797 maBegin,
798 maRawXorAccessor);
799 else if (bitsPerPixel[getScanlineFormat()] >= 8
800 && rSrcRect.getWidth() == rDstRect.getWidth() && rSrcRect.getHeight() == rDstRect.getHeight()
801 && rSrcBitmap->getScanlineFormat() == getScanlineFormat())
802 implDrawBitmapDirect(rSrcBitmap, rSrcRect, rDstRect);
803 else
804 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
805 maBegin,
806 maRawAccessor);
808 else
810 if( drawMode == DrawMode_XOR )
811 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
812 maBegin,
813 maXorAccessor);
814 else
815 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
816 maBegin,
817 maAccessor);
819 damaged( rDstRect );
822 virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
823 const basegfx::B2IBox& rSrcRect,
824 const basegfx::B2IBox& rDstRect,
825 DrawMode drawMode,
826 const BitmapDeviceSharedPtr& rClip )
828 if( isCompatibleBitmap( rSrcBitmap ) )
830 if( drawMode == DrawMode_XOR )
831 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
832 getMaskedIter(rClip),
833 maRawMaskedXorAccessor);
834 else
835 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
836 getMaskedIter(rClip),
837 maRawMaskedAccessor);
839 else
841 if( drawMode == DrawMode_XOR )
842 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
843 getMaskedIter(rClip),
844 maMaskedXorAccessor);
845 else
846 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
847 getMaskedIter(rClip),
848 maMaskedAccessor);
850 damaged( rDstRect );
853 virtual void drawMaskedColor_i(Color aSrcColor,
854 const BitmapDeviceSharedPtr& rAlphaMask,
855 const basegfx::B2IBox& rSrcRect,
856 const basegfx::B2IPoint& rDstPoint )
858 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
859 boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
861 if( pAlpha )
863 maColorBlendAccessor.setColor( aSrcColor );
865 vigra::copyImage( srcIterRange(pAlpha->maBegin,
866 pAlpha->maRawAccessor,
867 rSrcRect),
868 destIter(maBegin,
869 maColorBlendAccessor,
870 rDstPoint) );
872 else if( pMask )
874 const composite_iterator_type aBegin(
875 maBegin + vigra::Diff2D(rDstPoint.getX(),
876 rDstPoint.getY()),
877 pMask->maBegin + topLeft(rSrcRect) );
879 fillImage(aBegin,
880 aBegin + vigra::Diff2D(rSrcRect.getWidth(),
881 rSrcRect.getHeight()),
882 maRawMaskedAccessor,
883 maColorLookup(
884 maAccessor,
885 aSrcColor) );
887 else
889 GenericColorImageAccessor aSrcAcc( rAlphaMask );
890 maGenericColorBlendAccessor.setColor( aSrcColor );
892 vigra::copyImage( srcIterRange(vigra::Diff2D(),
893 aSrcAcc,
894 rSrcRect),
895 destIter(maBegin,
896 maGenericColorBlendAccessor,
897 rDstPoint) );
899 damagedPointSize( rDstPoint, rSrcRect );
902 virtual void drawMaskedColor_i(Color aSrcColor,
903 const BitmapDeviceSharedPtr& rAlphaMask,
904 const basegfx::B2IBox& rSrcRect,
905 const basegfx::B2IPoint& rDstPoint,
906 const BitmapDeviceSharedPtr& rClip )
908 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
909 boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
911 if( pAlpha )
913 const composite_iterator_type aBegin( getMaskedIter(rClip) );
914 maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
915 aSrcColor );
917 vigra::copyImage( srcIterRange(pAlpha->maBegin,
918 pAlpha->maRawAccessor,
919 rSrcRect),
920 destIter(aBegin,
921 maMaskedColorBlendAccessor,
922 rDstPoint) );
924 else if( pMask )
926 boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) );
927 OSL_ASSERT( pClipMask );
929 // setup a ((iter,mask),clipMask) composite composite
930 // iterator, to pass both masks (clip and alpha mask)
931 // to the algorithm
932 const composite_composite_mask_iterator_type aBegin(
933 composite_iterator_type(
934 maBegin + vigra::Diff2D(rDstPoint.getX(),
935 rDstPoint.getY()),
936 pMask->maBegin + topLeft(rSrcRect)),
937 pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(),
938 rDstPoint.getY()) );
940 fillImage(aBegin,
941 aBegin + vigra::Diff2D(rSrcRect.getWidth(),
942 rSrcRect.getHeight()),
943 maRawMaskedMaskAccessor,
944 maColorLookup(
945 maAccessor,
946 aSrcColor) );
948 else
950 GenericColorImageAccessor aSrcAcc( rAlphaMask );
951 const composite_iterator_type aBegin( getMaskedIter(rClip) );
952 maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
953 aSrcColor );
955 vigra::copyImage( srcIterRange(vigra::Diff2D(),
956 aSrcAcc,
957 rSrcRect),
958 destIter(aBegin,
959 maGenericMaskedColorBlendAccessor,
960 rDstPoint) );
962 damagedPointSize( rDstPoint, rSrcRect );
965 template< typename Iterator, typename Acc >
966 void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
967 const BitmapDeviceSharedPtr& rMask,
968 const basegfx::B2IBox& rSrcRect,
969 const basegfx::B2IBox& rDstRect,
970 const Iterator& begin,
971 const Acc& acc)
973 boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
974 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) );
975 OSL_ASSERT( pMask && pSrcBmp );
977 scaleImage(
978 srcIterRange(composite_iterator_type(
979 pSrcBmp->maBegin,
980 pMask->maBegin),
981 joined_image_accessor_type(
982 pSrcBmp->maAccessor,
983 pMask->maRawAccessor),
984 rSrcRect),
985 destIterRange(begin,
986 typename masked_input_splitting_accessor<
987 Acc,
988 joined_image_accessor_type,
989 Masks::clipmask_polarity,
990 FastMask >::type(acc),
991 rDstRect),
992 isSharedBuffer(rSrcBitmap));
993 damaged( rDstRect );
996 template< typename Iterator, typename Acc >
997 void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
998 const BitmapDeviceSharedPtr& rMask,
999 const basegfx::B2IBox& rSrcRect,
1000 const basegfx::B2IBox& rDstRect,
1001 const Iterator& begin,
1002 const Acc& acc)
1004 GenericColorImageAccessor aSrcAcc( rSrcBitmap );
1005 GenericColorImageAccessor aMaskAcc( rMask );
1007 const vigra::Diff2D aTopLeft(rSrcRect.getMinX(),
1008 rSrcRect.getMinY());
1009 const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(),
1010 rSrcRect.getMaxY());
1011 scaleImage(
1012 vigra::make_triple(
1013 generic_composite_iterator_type(
1014 aTopLeft,aTopLeft),
1015 generic_composite_iterator_type(
1016 aBottomRight,aBottomRight),
1017 joined_generic_image_accessor_type(
1018 aSrcAcc,
1019 aMaskAcc)),
1020 destIterRange(begin,
1021 typename masked_input_splitting_accessor<
1022 Acc,
1023 joined_generic_image_accessor_type,
1024 Masks::clipmask_polarity,
1025 NoFastMask >::type(acc),
1026 rDstRect));
1027 damaged( rDstRect );
1030 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
1031 const BitmapDeviceSharedPtr& rMask,
1032 const basegfx::B2IBox& rSrcRect,
1033 const basegfx::B2IBox& rDstRect,
1034 DrawMode drawMode )
1036 if( isCompatibleClipMask(rMask) &&
1037 isCompatibleBitmap(rSrcBitmap) )
1039 if( drawMode == DrawMode_XOR )
1040 implDrawMaskedBitmap(rSrcBitmap, rMask,
1041 rSrcRect, rDstRect,
1042 maBegin,
1043 maXorAccessor);
1044 else
1045 implDrawMaskedBitmap(rSrcBitmap, rMask,
1046 rSrcRect, rDstRect,
1047 maBegin,
1048 maAccessor);
1050 else
1052 if( drawMode == DrawMode_XOR )
1053 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1054 rSrcRect, rDstRect,
1055 maBegin,
1056 maXorAccessor);
1057 else
1058 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1059 rSrcRect, rDstRect,
1060 maBegin,
1061 maAccessor);
1063 damaged( rDstRect );
1066 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
1067 const BitmapDeviceSharedPtr& rMask,
1068 const basegfx::B2IBox& rSrcRect,
1069 const basegfx::B2IBox& rDstRect,
1070 DrawMode drawMode,
1071 const BitmapDeviceSharedPtr& rClip )
1073 if( isCompatibleClipMask(rMask) &&
1074 isCompatibleBitmap(rSrcBitmap) )
1076 if( drawMode == DrawMode_XOR )
1077 implDrawMaskedBitmap(rSrcBitmap, rMask,
1078 rSrcRect, rDstRect,
1079 getMaskedIter(rClip),
1080 maMaskedXorAccessor);
1081 else
1082 implDrawMaskedBitmap(rSrcBitmap, rMask,
1083 rSrcRect, rDstRect,
1084 getMaskedIter(rClip),
1085 maMaskedAccessor);
1087 else
1089 if( drawMode == DrawMode_XOR )
1090 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1091 rSrcRect, rDstRect,
1092 getMaskedIter(rClip),
1093 maMaskedXorAccessor);
1094 else
1095 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1096 rSrcRect, rDstRect,
1097 getMaskedIter(rClip),
1098 maMaskedAccessor);
1100 damaged( rDstRect );
1103 IBitmapDeviceDamageTrackerSharedPtr getDamageTracker_i() const
1105 return mpDamage;
1107 void setDamageTracker_i( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1109 mpDamage = rDamage;
1112 } // namespace
1114 struct ImplBitmapDevice
1116 /** Bitmap memory plus deleter.
1118 Always points to the start of the mem
1120 RawMemorySharedArray mpMem;
1122 /// Palette memory plus deleter (might be NULL)
1123 PaletteMemorySharedVector mpPalette;
1125 /** Bounds of the device.
1127 maBounds.getWidth()/getHeight() yield the true size of the
1128 device (i.e. the rectangle given by maBounds covers the device
1129 area under the including-the-bottommost-and-rightmost-pixels
1130 fill rule)
1132 basegfx::B2IBox maBounds;
1134 //// Size of the actual frame buffer
1135 basegfx::B2IVector maBufferSize;
1137 /// Scanline format, as provided at the constructor
1138 Format mnScanlineFormat;
1140 /// Scanline stride. Negative for bottom-to-top formats
1141 sal_Int32 mnScanlineStride;
1143 /// raw ptr to 0th scanline. used for cloning a generic renderer
1144 sal_uInt8* mpFirstScanline;
1146 /** (Optional) device sharing the same memory, and used for input
1147 clip masks/alpha masks/bitmaps that don't match our exact
1148 bitmap format.
1150 This is to avoid the combinatorical explosion when dealing
1151 with n bitmap formats, which could be combined with n clip
1152 masks, alpha masks and bitmap masks (yielding a total of n^4
1153 combinations). Since each BitmapRenderer is specialized for
1154 one specific combination of said formats, a lot of duplicate
1155 code would be generated, most of which probably never
1156 used. Therefore, only the most common combinations are
1157 specialized templates, the remainder gets handled by this
1158 generic renderer (via runtime polymorphism).
1160 BitmapDeviceSharedPtr mpGenericRenderer;
1164 BitmapDevice::BitmapDevice( const basegfx::B2IBox& rBounds,
1165 const basegfx::B2IVector& rBufferSize,
1166 Format nScanlineFormat,
1167 sal_Int32 nScanlineStride,
1168 sal_uInt8* pFirstScanline,
1169 const RawMemorySharedArray& rMem,
1170 const PaletteMemorySharedVector& rPalette ) :
1171 mpImpl( new ImplBitmapDevice )
1173 mpImpl->mpMem = rMem;
1174 mpImpl->mpPalette = rPalette;
1175 mpImpl->maBounds = rBounds;
1176 mpImpl->maBufferSize = rBufferSize;
1177 mpImpl->mnScanlineFormat = nScanlineFormat;
1178 mpImpl->mnScanlineStride = nScanlineStride;
1179 mpImpl->mpFirstScanline = pFirstScanline;
1182 BitmapDevice::~BitmapDevice()
1184 // outline, because of internal ImplBitmapDevice
1185 SAL_INFO( "basebmp.bitmapdevice", "~BitmapDevice(" << this << ")" );
1188 basegfx::B2IVector BitmapDevice::getSize() const
1190 return basegfx::B2IVector(
1191 mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(),
1192 mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() );
1195 bool BitmapDevice::isTopDown() const
1197 return mpImpl->mnScanlineStride >= 0;
1200 basegfx::B2IVector BitmapDevice::getBufferSize() const
1202 return mpImpl->maBufferSize;
1205 Format BitmapDevice::getScanlineFormat() const
1207 return mpImpl->mnScanlineFormat;
1210 sal_Int32 BitmapDevice::getScanlineStride() const
1212 return mpImpl->mnScanlineStride < 0 ?
1213 -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride;
1216 RawMemorySharedArray BitmapDevice::getBuffer() const
1218 return mpImpl->mpMem;
1221 IBitmapDeviceDamageTrackerSharedPtr BitmapDevice::getDamageTracker() const
1223 return getDamageTracker_i();
1226 void BitmapDevice::setDamageTracker( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1228 setDamageTracker_i(rDamage);
1231 PaletteMemorySharedVector BitmapDevice::getPalette() const
1233 return mpImpl->mpPalette;
1236 bool BitmapDevice::isSharedBuffer( const BitmapDeviceSharedPtr& rOther ) const
1238 return rOther.get()->getBuffer().get() == getBuffer().get();
1241 void BitmapDevice::clear( Color fillColor )
1243 clear_i( fillColor, mpImpl->maBounds );
1246 void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1247 Color lineColor,
1248 DrawMode drawMode )
1250 if( mpImpl->maBounds.isInside(rPt) )
1251 setPixel_i(rPt,lineColor,drawMode);
1254 void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1255 Color lineColor,
1256 DrawMode drawMode,
1257 const BitmapDeviceSharedPtr& rClip )
1259 if( !rClip )
1261 setPixel(rPt,lineColor,drawMode);
1262 return;
1265 if( mpImpl->maBounds.isInside(rPt) )
1267 if( isCompatibleClipMask( rClip ) )
1268 setPixel_i(rPt,lineColor,drawMode,rClip);
1269 else
1270 getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip );
1274 Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt )
1276 if( mpImpl->maBounds.isInside(rPt) )
1277 return getPixel_i(rPt);
1279 return Color();
1282 sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
1284 if( mpImpl->maBounds.isInside(rPt) )
1285 return getPixelData_i(rPt);
1287 return 0;
1290 void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1291 const basegfx::B2IPoint& rPt2,
1292 Color lineColor,
1293 DrawMode drawMode )
1295 drawLine_i( rPt1,
1296 rPt2,
1297 mpImpl->maBounds,
1298 lineColor,
1299 drawMode );
1302 void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1303 const basegfx::B2IPoint& rPt2,
1304 Color lineColor,
1305 DrawMode drawMode,
1306 const BitmapDeviceSharedPtr& rClip )
1308 if( !rClip )
1310 drawLine(rPt1,rPt2,lineColor,drawMode);
1311 return;
1314 if( isCompatibleClipMask( rClip ) )
1315 drawLine_i( rPt1,
1316 rPt2,
1317 mpImpl->maBounds,
1318 lineColor,
1319 drawMode,
1320 rClip );
1321 else
1322 getGenericRenderer()->drawLine( rPt1, rPt2, lineColor,
1323 drawMode, rClip );
1326 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1327 Color lineColor,
1328 DrawMode drawMode )
1330 const sal_uInt32 numVertices( rPoly.count() );
1331 if( numVertices )
1332 drawPolygon_i( rPoly,
1333 mpImpl->maBounds,
1334 lineColor, drawMode );
1337 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1338 Color lineColor,
1339 DrawMode drawMode,
1340 const BitmapDeviceSharedPtr& rClip )
1342 if( !rClip )
1344 drawPolygon(rPoly,lineColor,drawMode);
1345 return;
1348 const sal_uInt32 numVertices( rPoly.count() );
1349 if( numVertices )
1351 if( isCompatibleClipMask( rClip ) )
1352 drawPolygon_i( rPoly,
1353 mpImpl->maBounds,
1354 lineColor, drawMode, rClip );
1355 else
1356 getGenericRenderer()->drawPolygon( rPoly, lineColor,
1357 drawMode, rClip );
1361 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1362 Color fillColor,
1363 DrawMode drawMode )
1365 fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
1368 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1369 Color fillColor,
1370 DrawMode drawMode,
1371 const BitmapDeviceSharedPtr& rClip )
1373 if( !rClip )
1375 fillPolyPolygon(rPoly,fillColor,drawMode);
1376 return;
1379 if( isCompatibleClipMask( rClip ) )
1380 fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
1381 else
1382 getGenericRenderer()->fillPolyPolygon( rPoly, fillColor,
1383 drawMode, rClip );
1387 namespace
1389 void assertImagePoint( const basegfx::B2IPoint& rPt,
1390 const basegfx::B2IBox& rPermittedRange )
1392 (void)rPt; (void)rPermittedRange;
1393 OSL_ASSERT( rPermittedRange.isInside(rPt) );
1396 void assertImageRange( const basegfx::B2IBox& rRange,
1397 const basegfx::B2IBox& rPermittedRange )
1399 #if OSL_DEBUG_LEVEL > 0
1400 basegfx::B2IBox aRange( rRange );
1401 aRange.intersect( rPermittedRange );
1403 OSL_ASSERT( aRange == rRange );
1404 #else
1405 (void)rRange; (void)rPermittedRange;
1406 #endif
1409 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1410 // to basegfx, and use here!
1411 bool clipAreaImpl( ::basegfx::B2IBox& io_rSourceArea,
1412 ::basegfx::B2IPoint& io_rDestPoint,
1413 const ::basegfx::B2IBox& rSourceBounds,
1414 const ::basegfx::B2IBox& rDestBounds )
1416 const ::basegfx::B2IPoint aSourceTopLeft(
1417 io_rSourceArea.getMinimum() );
1419 ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1421 // clip source area (which must be inside rSourceBounds)
1422 aLocalSourceArea.intersect( rSourceBounds );
1424 if( aLocalSourceArea.isEmpty() )
1425 return false;
1427 // calc relative new source area points (relative to orig
1428 // source area)
1429 const ::basegfx::B2IVector aUpperLeftOffset(
1430 aLocalSourceArea.getMinimum()-aSourceTopLeft );
1431 const ::basegfx::B2IVector aLowerRightOffset(
1432 aLocalSourceArea.getMaximum()-aSourceTopLeft );
1434 ::basegfx::B2IBox aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1435 io_rDestPoint + aLowerRightOffset );
1437 // clip dest area (which must be inside rDestBounds)
1438 aLocalDestArea.intersect( rDestBounds );
1440 if( aLocalDestArea.isEmpty() )
1441 return false;
1443 // calc relative new dest area points (relative to orig
1444 // source area)
1445 const ::basegfx::B2IVector aDestUpperLeftOffset(
1446 aLocalDestArea.getMinimum()-io_rDestPoint );
1447 const ::basegfx::B2IVector aDestLowerRightOffset(
1448 aLocalDestArea.getMaximum()-io_rDestPoint );
1450 io_rSourceArea = ::basegfx::B2IBox( aSourceTopLeft + aDestUpperLeftOffset,
1451 aSourceTopLeft + aDestLowerRightOffset );
1452 io_rDestPoint = aLocalDestArea.getMinimum();
1454 return true;
1457 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1458 // to basegfx, and use here!
1459 bool clipAreaImpl( ::basegfx::B2IBox& io_rDestArea,
1460 ::basegfx::B2IBox& io_rSourceArea,
1461 const ::basegfx::B2IBox& rDestBounds,
1462 const ::basegfx::B2IBox& rSourceBounds )
1464 // extract inherent scale
1465 const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() );
1466 const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() );
1468 // extract range origins
1469 const basegfx::B2IPoint aDestTopLeft(
1470 io_rDestArea.getMinimum() );
1471 const ::basegfx::B2IPoint aSourceTopLeft(
1472 io_rSourceArea.getMinimum() );
1474 ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1476 // clip source area (which must be inside rSourceBounds)
1477 aLocalSourceArea.intersect( rSourceBounds );
1479 if( aLocalSourceArea.isEmpty() )
1480 return false;
1482 // calc relative new source area points (relative to orig
1483 // source area)
1484 const ::basegfx::B2IVector aUpperLeftOffset(
1485 aLocalSourceArea.getMinimum()-aSourceTopLeft );
1486 const ::basegfx::B2IVector aLowerRightOffset(
1487 aLocalSourceArea.getMaximum()-aSourceTopLeft );
1489 ::basegfx::B2IBox aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
1490 basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
1491 basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
1492 basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
1494 // clip dest area (which must be inside rDestBounds)
1495 aLocalDestArea.intersect( rDestBounds );
1497 if( aLocalDestArea.isEmpty() )
1498 return false;
1500 // calc relative new dest area points (relative to orig
1501 // source area)
1502 const ::basegfx::B2IVector aDestUpperLeftOffset(
1503 aLocalDestArea.getMinimum()-aDestTopLeft );
1504 const ::basegfx::B2IVector aDestLowerRightOffset(
1505 aLocalDestArea.getMaximum()-aDestTopLeft );
1507 io_rSourceArea = ::basegfx::B2IBox( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
1508 basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
1509 basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
1510 basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
1511 io_rDestArea = aLocalDestArea;
1513 // final source area clip (chopping round-offs)
1514 io_rSourceArea.intersect( rSourceBounds );
1516 if( io_rSourceArea.isEmpty() )
1517 return false;
1520 return true;
1524 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1525 const basegfx::B2IBox& rSrcRect,
1526 const basegfx::B2IBox& rDstRect,
1527 DrawMode drawMode )
1529 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1530 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1531 basegfx::B2IBox aSrcRange( rSrcRect );
1532 basegfx::B2IBox aDestRange( rDstRect );
1534 if( clipAreaImpl( aDestRange,
1535 aSrcRange,
1536 mpImpl->maBounds,
1537 aSrcBounds ))
1539 assertImageRange(aDestRange,mpImpl->maBounds);
1540 assertImageRange(aSrcRange,aSrcBounds);
1542 drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode );
1546 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1547 const basegfx::B2IBox& rSrcRect,
1548 const basegfx::B2IBox& rDstRect,
1549 DrawMode drawMode,
1550 const BitmapDeviceSharedPtr& rClip )
1552 if( !rClip )
1554 drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
1555 return;
1558 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1559 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1560 basegfx::B2IBox aSrcRange( rSrcRect );
1561 basegfx::B2IBox aDestRange( rDstRect );
1563 if( clipAreaImpl( aDestRange,
1564 aSrcRange,
1565 mpImpl->maBounds,
1566 aSrcBounds ))
1568 assertImageRange(aDestRange,mpImpl->maBounds);
1569 assertImageRange(aSrcRange,aSrcBounds);
1571 if( isCompatibleClipMask( rClip ) )
1573 drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip );
1575 else
1577 getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect,
1578 rDstRect, drawMode, rClip );
1583 void BitmapDevice::drawMaskedColor( Color aSrcColor,
1584 const BitmapDeviceSharedPtr& rAlphaMask,
1585 const basegfx::B2IBox& rSrcRect,
1586 const basegfx::B2IPoint& rDstPoint )
1588 const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1589 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1590 basegfx::B2IBox aSrcRange( rSrcRect );
1591 basegfx::B2IPoint aDestPoint( rDstPoint );
1593 if( clipAreaImpl( aSrcRange,
1594 aDestPoint,
1595 aSrcBounds,
1596 mpImpl->maBounds ))
1598 assertImagePoint(aDestPoint,mpImpl->maBounds);
1599 assertImageRange(aSrcRange,aSrcBounds);
1601 if( isSharedBuffer(rAlphaMask) )
1603 // src == dest, copy rAlphaMask beforehand
1604 // ---------------------------------------------------
1606 const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1607 aSrcRange.getHeight() );
1608 BitmapDeviceSharedPtr pAlphaCopy(
1609 cloneBitmapDevice( aSize,
1610 shared_from_this()) );
1611 basegfx::B2ITuple aGcc3WorkaroundTemporary;
1612 const basegfx::B2IBox aAlphaRange( aGcc3WorkaroundTemporary,
1613 aSize );
1614 pAlphaCopy->drawBitmap(rAlphaMask,
1615 aSrcRange,
1616 aAlphaRange,
1617 DrawMode_PAINT);
1618 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint );
1620 else
1622 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint );
1627 void BitmapDevice::drawMaskedColor( Color aSrcColor,
1628 const BitmapDeviceSharedPtr& rAlphaMask,
1629 const basegfx::B2IBox& rSrcRect,
1630 const basegfx::B2IPoint& rDstPoint,
1631 const BitmapDeviceSharedPtr& rClip )
1633 if( !rClip )
1635 drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
1636 return;
1639 const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1640 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1641 basegfx::B2IBox aSrcRange( rSrcRect );
1642 basegfx::B2IPoint aDestPoint( rDstPoint );
1644 if( clipAreaImpl( aSrcRange,
1645 aDestPoint,
1646 aSrcBounds,
1647 mpImpl->maBounds ))
1649 assertImagePoint(aDestPoint,mpImpl->maBounds);
1650 assertImageRange(aSrcRange,aSrcBounds);
1652 if( isCompatibleClipMask( rClip ) )
1654 if( isSharedBuffer(rAlphaMask) )
1656 // src == dest, copy rAlphaMask beforehand
1657 // ---------------------------------------------------
1659 const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1660 aSrcRange.getHeight() );
1661 BitmapDeviceSharedPtr pAlphaCopy(
1662 cloneBitmapDevice( aSize,
1663 shared_from_this()) );
1664 basegfx::B2ITuple aGcc3WorkaroundTemporary;
1665 const basegfx::B2IBox aAlphaRange( aGcc3WorkaroundTemporary,
1666 aSize );
1667 pAlphaCopy->drawBitmap(rAlphaMask,
1668 aSrcRange,
1669 aAlphaRange,
1670 DrawMode_PAINT);
1671 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip );
1673 else
1675 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
1678 else
1680 getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask,
1681 rSrcRect, rDstPoint, rClip );
1686 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1687 const BitmapDeviceSharedPtr& rMask,
1688 const basegfx::B2IBox& rSrcRect,
1689 const basegfx::B2IBox& rDstRect,
1690 DrawMode drawMode )
1692 OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1694 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1695 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1696 basegfx::B2IBox aSrcRange( rSrcRect );
1697 basegfx::B2IBox aDestRange( rDstRect );
1699 if( clipAreaImpl( aDestRange,
1700 aSrcRange,
1701 mpImpl->maBounds,
1702 aSrcBounds ))
1704 assertImageRange(aDestRange,mpImpl->maBounds);
1705 assertImageRange(aSrcRange,aSrcBounds);
1707 drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode );
1711 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1712 const BitmapDeviceSharedPtr& rMask,
1713 const basegfx::B2IBox& rSrcRect,
1714 const basegfx::B2IBox& rDstRect,
1715 DrawMode drawMode,
1716 const BitmapDeviceSharedPtr& rClip )
1718 if( !rClip )
1720 drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
1721 return;
1724 OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1726 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1727 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1728 basegfx::B2IBox aSrcRange( rSrcRect );
1729 basegfx::B2IBox aDestRange( rDstRect );
1731 if( clipAreaImpl( aDestRange,
1732 aSrcRange,
1733 mpImpl->maBounds,
1734 aSrcBounds ))
1736 assertImageRange(aDestRange,mpImpl->maBounds);
1737 assertImageRange(aSrcRange,aSrcBounds);
1739 if( isCompatibleClipMask( rClip ) )
1741 drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip );
1743 else
1745 getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect,
1746 rDstRect, drawMode, rClip );
1753 /** Standard clip and alpha masks
1755 struct StdMasks
1757 typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits;
1758 typedef PixelFormatTraits_GREY8 alphamask_format_traits;
1760 /// Clipmask: 0 means opaque
1761 static const bool clipmask_polarity = false;
1763 /// Alpha mask: 0 means fully transparent
1764 static const bool alphamask_polarity = true;
1768 // Some compilers don't like the nested template wrap_accessor
1769 // reference in the parameter list - being slightly less type safe,
1770 // then.
1771 #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
1773 /// Produces a specialized renderer for the given pixel format
1774 template< class FormatTraits, class MaskTraits >
1775 BitmapDeviceSharedPtr createRenderer(
1776 const basegfx::B2IBox& rBounds,
1777 const basegfx::B2IVector& rBufferSize,
1778 Format nScanlineFormat,
1779 sal_Int32 nScanlineStride,
1780 sal_uInt8* pFirstScanline,
1781 typename FormatTraits::raw_accessor_type const& rRawAccessor,
1782 typename FormatTraits::accessor_selector::template wrap_accessor<
1783 typename FormatTraits::raw_accessor_type>::type const& rAccessor,
1784 boost::shared_array< sal_uInt8 > pMem,
1785 const PaletteMemorySharedVector& pPal,
1786 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1787 #else
1789 template< class FormatTraits, class MaskTraits, class Accessor >
1790 BitmapDeviceSharedPtr createRenderer(
1791 const basegfx::B2IBox& rBounds,
1792 const basegfx::B2IVector& rBufferSize,
1793 Format nScanlineFormat,
1794 sal_Int32 nScanlineStride,
1795 sal_uInt8* pFirstScanline,
1796 typename FormatTraits::raw_accessor_type const& rRawAccessor,
1797 Accessor const& rAccessor,
1798 boost::shared_array< sal_uInt8 > pMem,
1799 const PaletteMemorySharedVector& pPal,
1800 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1802 #endif
1804 typedef typename FormatTraits::iterator_type Iterator;
1805 typedef BitmapRenderer< Iterator,
1806 typename FormatTraits::raw_accessor_type,
1807 typename FormatTraits::accessor_selector,
1808 MaskTraits > Renderer;
1810 return BitmapDeviceSharedPtr(
1811 new Renderer( rBounds,
1812 rBufferSize,
1813 nScanlineFormat,
1814 nScanlineStride,
1815 pFirstScanline,
1816 Iterator(
1817 reinterpret_cast<typename Iterator::value_type*>(
1818 pFirstScanline),
1819 nScanlineStride),
1820 rRawAccessor,
1821 rAccessor,
1822 pMem,
1823 pPal,
1824 pDamage ));
1827 /// Create standard grey level palette
1828 PaletteMemorySharedVector createStandardPalette(
1829 const PaletteMemorySharedVector& pPal,
1830 sal_Int32 nNumEntries )
1832 if( pPal || nNumEntries <= 0 )
1833 return pPal;
1835 boost::shared_ptr< std::vector<Color> > pLocalPal(
1836 new std::vector<Color>(nNumEntries) );
1838 const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries );
1839 --nNumEntries;
1840 for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement )
1841 pLocalPal->at(i) = Color(0xFF000000 | c);
1843 pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF);
1845 return pLocalPal;
1848 template< class FormatTraits, class MaskTraits >
1849 BitmapDeviceSharedPtr createRenderer(
1850 const basegfx::B2IBox& rBounds,
1851 const basegfx::B2IVector& rBufferSize,
1852 Format nScanlineFormat,
1853 sal_Int32 nScanlineStride,
1854 sal_uInt8* pFirstScanline,
1855 boost::shared_array< sal_uInt8 > pMem,
1856 const PaletteMemorySharedVector& pPal,
1857 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1859 return createRenderer<FormatTraits,
1860 MaskTraits>(rBounds,
1861 rBufferSize,
1862 nScanlineFormat,
1863 nScanlineStride,
1864 pFirstScanline,
1865 typename FormatTraits::raw_accessor_type(),
1866 typename FormatTraits::accessor_selector::template
1867 wrap_accessor<
1868 typename FormatTraits::raw_accessor_type>::type(),
1869 pMem,
1870 pPal,
1871 pDamage);
1874 template< class FormatTraits, class MaskTraits >
1875 BitmapDeviceSharedPtr createRenderer(
1876 const basegfx::B2IBox& rBounds,
1877 const basegfx::B2IVector& rBufferSize,
1878 Format nScanlineFormat,
1879 sal_Int32 nScanlineStride,
1880 sal_uInt8* pFirstScanline,
1881 boost::shared_array< sal_uInt8 > pMem,
1882 PaletteMemorySharedVector pPal,
1883 int nBitsPerPixel,
1884 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1886 pPal = createStandardPalette(pPal,
1887 1UL << nBitsPerPixel);
1889 OSL_ASSERT(pPal);
1890 return createRenderer<FormatTraits,
1891 MaskTraits>(rBounds,
1892 rBufferSize,
1893 nScanlineFormat,
1894 nScanlineStride,
1895 pFirstScanline,
1896 typename FormatTraits::raw_accessor_type(),
1897 typename FormatTraits::accessor_selector::template
1898 wrap_accessor<
1899 typename FormatTraits::raw_accessor_type>::type(
1900 &pPal->at(0),
1901 pPal->size()),
1902 pMem,
1903 pPal,
1904 pDamage);
1908 // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
1909 // to o3tl or sal/bithacks.hxx ...
1911 /** Compute the next highest power of 2 of a 32-bit value
1913 Code devised by Sean Anderson, in good ole HAKMEM
1914 tradition.
1916 @return 1 << (lg(x - 1) + 1)
1918 inline sal_uInt32 nextPow2( sal_uInt32 x )
1920 --x;
1921 x |= x >> 1;
1922 x |= x >> 2;
1923 x |= x >> 4;
1924 x |= x >> 8;
1925 x |= x >> 16;
1927 return ++x;
1933 namespace
1935 BitmapDeviceSharedPtr createBitmapDeviceImplInner( const basegfx::B2IVector& rSize,
1936 bool bTopDown,
1937 Format nScanlineFormat,
1938 boost::shared_array< sal_uInt8 > pMem,
1939 PaletteMemorySharedVector pPal,
1940 const basegfx::B2IBox* pSubset,
1941 const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1943 OSL_ASSERT(rSize.getX() > 0 && rSize.getY() > 0);
1945 if( nScanlineFormat <= FORMAT_NONE ||
1946 nScanlineFormat > FORMAT_MAX )
1947 return BitmapDeviceSharedPtr();
1951 sal_Int32 nScanlineStride(0);
1953 // round up to full 8 bit, divide by 8
1954 nScanlineStride = (rSize.getX()*bitsPerPixel[nScanlineFormat] + 7) >> 3;
1956 // rounded up to next full power-of-two number of bytes
1957 const sal_uInt32 bytesPerPixel = nextPow2(
1958 (bitsPerPixel[nScanlineFormat] + 7) >> 3);
1960 // now make nScanlineStride a multiple of bytesPerPixel
1961 nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel;
1963 // factor in bottom-up scanline order case
1964 nScanlineStride *= bTopDown ? 1 : -1;
1966 const sal_uInt32 nWidth(nScanlineStride < 0 ? -nScanlineStride : nScanlineStride);
1967 const sal_uInt32 nHeight(rSize.getY());
1969 if (nHeight && nWidth && nWidth > SAL_MAX_INT32 / nHeight)
1971 SAL_WARN( "basebmp", "suspicious massive alloc " << nWidth << " * " << nHeight);
1972 return BitmapDeviceSharedPtr();
1975 const std::size_t nMemSize(nWidth * nHeight);
1977 if( !pMem )
1979 pMem.reset(
1980 reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
1981 &rtl_freeMemory );
1982 if (pMem.get() == 0 && nMemSize != 0)
1983 return BitmapDeviceSharedPtr();
1984 memset(pMem.get(), 0, nMemSize);
1987 sal_uInt8* pFirstScanline = nScanlineStride < 0 ?
1988 pMem.get() + nMemSize + nScanlineStride : pMem.get();
1990 // shrink render area to given subset, if given
1991 basegfx::B2IBox aBounds(0,0,rSize.getX(),rSize.getY());
1992 if( pSubset )
1993 aBounds.intersect( *pSubset );
1995 switch( nScanlineFormat )
1997 // ----------------------------------------------------------------------
1998 // one bit formats
2000 case FORMAT_ONE_BIT_MSB_GREY:
2001 return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>(
2002 aBounds, rSize, nScanlineFormat, nScanlineStride,
2003 pFirstScanline, pMem, pPal, rDamage );
2005 case FORMAT_ONE_BIT_LSB_GREY:
2006 return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>(
2007 aBounds, rSize, nScanlineFormat, nScanlineStride,
2008 pFirstScanline, pMem, pPal, rDamage );
2010 case FORMAT_ONE_BIT_MSB_PAL:
2011 return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>(
2012 aBounds, rSize, nScanlineFormat, nScanlineStride,
2013 pFirstScanline, pMem, pPal,
2014 bitsPerPixel[nScanlineFormat], rDamage );
2016 case FORMAT_ONE_BIT_LSB_PAL:
2017 return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>(
2018 aBounds, rSize, nScanlineFormat, nScanlineStride,
2019 pFirstScanline, pMem, pPal,
2020 bitsPerPixel[nScanlineFormat], rDamage );
2023 // ----------------------------------------------------------------------
2024 // four bit formats
2026 case FORMAT_FOUR_BIT_MSB_GREY:
2027 return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>(
2028 aBounds, rSize, nScanlineFormat, nScanlineStride,
2029 pFirstScanline, pMem, pPal, rDamage );
2031 case FORMAT_FOUR_BIT_LSB_GREY:
2032 return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>(
2033 aBounds, rSize, nScanlineFormat, nScanlineStride,
2034 pFirstScanline, pMem, pPal, rDamage );
2036 case FORMAT_FOUR_BIT_MSB_PAL:
2037 return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>(
2038 aBounds, rSize, nScanlineFormat, nScanlineStride,
2039 pFirstScanline, pMem, pPal,
2040 bitsPerPixel[nScanlineFormat], rDamage );
2042 case FORMAT_FOUR_BIT_LSB_PAL:
2043 return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>(
2044 aBounds, rSize, nScanlineFormat, nScanlineStride,
2045 pFirstScanline, pMem, pPal,
2046 bitsPerPixel[nScanlineFormat], rDamage );
2049 // ----------------------------------------------------------------------
2050 // eight bit formats
2052 case FORMAT_EIGHT_BIT_GREY:
2053 return createRenderer<PixelFormatTraits_GREY8,StdMasks>(
2054 aBounds, rSize, nScanlineFormat, nScanlineStride,
2055 pFirstScanline, pMem, pPal, rDamage );
2057 case FORMAT_EIGHT_BIT_PAL:
2058 return createRenderer<PixelFormatTraits_PAL8,StdMasks>(
2059 aBounds, rSize, nScanlineFormat, nScanlineStride,
2060 pFirstScanline, pMem, pPal,
2061 bitsPerPixel[nScanlineFormat], rDamage );
2064 // ----------------------------------------------------------------------
2065 // sixteen bit formats
2067 case FORMAT_SIXTEEN_BIT_LSB_TC_MASK:
2068 return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>(
2069 aBounds, rSize, nScanlineFormat, nScanlineStride,
2070 pFirstScanline, pMem, pPal, rDamage );
2072 case FORMAT_SIXTEEN_BIT_MSB_TC_MASK:
2073 return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>(
2074 aBounds, rSize, nScanlineFormat, nScanlineStride,
2075 pFirstScanline, pMem, pPal, rDamage );
2078 // ----------------------------------------------------------------------
2079 // twentyfour bit formats
2080 case FORMAT_TWENTYFOUR_BIT_TC_MASK:
2081 return createRenderer<PixelFormatTraits_BGR24,StdMasks>(
2082 aBounds, rSize, nScanlineFormat, nScanlineStride,
2083 pFirstScanline, pMem, pPal, rDamage );
2086 // ----------------------------------------------------------------------
2087 // thirtytwo bit formats
2089 case FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA:
2090 return createRenderer<PixelFormatTraits_BGRX32_8888,StdMasks>(
2091 aBounds, rSize, nScanlineFormat, nScanlineStride,
2092 pFirstScanline, pMem, pPal, rDamage );
2094 case FORMAT_THIRTYTWO_BIT_TC_MASK_ARGB:
2095 return createRenderer<PixelFormatTraits_XRGB32_8888,StdMasks>(
2096 aBounds, rSize, nScanlineFormat, nScanlineStride,
2097 pFirstScanline, pMem, pPal, rDamage );
2099 case FORMAT_THIRTYTWO_BIT_TC_MASK_ABGR:
2100 return createRenderer<PixelFormatTraits_XBGR32_8888,StdMasks>(
2101 aBounds, rSize, nScanlineFormat, nScanlineStride,
2102 pFirstScanline, pMem, pPal, rDamage );
2104 case FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA:
2105 return createRenderer<PixelFormatTraits_RGBX32_8888,StdMasks>(
2106 aBounds, rSize, nScanlineFormat, nScanlineStride,
2107 pFirstScanline, pMem, pPal, rDamage );
2109 default:
2110 assert(false); // this cannot happen
2113 // TODO(F3): other formats not yet implemented
2114 return BitmapDeviceSharedPtr();
2117 BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize,
2118 bool bTopDown,
2119 Format nScanlineFormat,
2120 boost::shared_array< sal_uInt8 > pMem,
2121 PaletteMemorySharedVector pPal,
2122 const basegfx::B2IBox* pSubset,
2123 const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
2125 BitmapDeviceSharedPtr result( createBitmapDeviceImplInner( rSize, bTopDown, nScanlineFormat, pMem, pPal, pSubset, rDamage ) );
2127 #ifdef SAL_LOG_INFO
2128 std::ostringstream subset;
2130 if (pSubset)
2131 subset << " subset=" << pSubset->getWidth() << "x" << pSubset->getHeight() << "@(" << pSubset->getMinX() << "," << pSubset->getMinY() << ")";
2133 SAL_INFO( "basebmp.bitmapdevice",
2134 "createBitmapDevice: "
2135 << rSize.getX() << "x" << rSize.getY()
2136 << (bTopDown ? " top-down " : " bottom-up ")
2137 << formatName(nScanlineFormat)
2138 << subset.str()
2139 << " = " << result.get() );
2140 #endif
2141 return result;
2143 } // namespace
2146 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2147 bool bTopDown,
2148 Format nScanlineFormat )
2150 return createBitmapDeviceImpl( rSize,
2151 bTopDown,
2152 nScanlineFormat,
2153 boost::shared_array< sal_uInt8 >(),
2154 PaletteMemorySharedVector(),
2155 NULL,
2156 IBitmapDeviceDamageTrackerSharedPtr() );
2159 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2160 bool bTopDown,
2161 Format nScanlineFormat,
2162 const PaletteMemorySharedVector& rPalette )
2164 return createBitmapDeviceImpl( rSize,
2165 bTopDown,
2166 nScanlineFormat,
2167 boost::shared_array< sal_uInt8 >(),
2168 rPalette,
2169 NULL,
2170 IBitmapDeviceDamageTrackerSharedPtr() );
2173 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2174 bool bTopDown,
2175 Format nScanlineFormat,
2176 const RawMemorySharedArray& rMem,
2177 const PaletteMemorySharedVector& rPalette )
2179 return createBitmapDeviceImpl( rSize,
2180 bTopDown,
2181 nScanlineFormat,
2182 rMem,
2183 rPalette,
2184 NULL,
2185 IBitmapDeviceDamageTrackerSharedPtr() );
2188 BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto,
2189 const basegfx::B2IBox& rSubset )
2191 SAL_INFO( "basebmp.bitmapdevice", "subsetBitmapDevice: proto=" << rProto.get() );
2192 return createBitmapDeviceImpl( rProto->getSize(),
2193 rProto->isTopDown(),
2194 rProto->getScanlineFormat(),
2195 rProto->getBuffer(),
2196 rProto->getPalette(),
2197 &rSubset,
2198 rProto->getDamageTracker() );
2201 BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize,
2202 const BitmapDeviceSharedPtr& rProto )
2204 return createBitmapDeviceImpl( rSize,
2205 rProto->isTopDown(),
2206 rProto->getScanlineFormat(),
2207 boost::shared_array< sal_uInt8 >(),
2208 rProto->getPalette(),
2209 NULL,
2210 rProto->getDamageTracker() );
2214 /// Clone our device, with GenericImageAccessor to handle all formats
2215 BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const
2217 return mpImpl->mpGenericRenderer;
2220 } // namespace basebmp
2222 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */