bump product version to 4.1.6.2
[LibreOffice.git] / basebmp / source / bitmapdevice.cxx
blob2833b1276fcecaa3ecc236d3f5782c281215dc9a
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 <string.h>
22 #include "basebmp/bitmapdevice.hxx"
24 #include "basebmp/compositeiterator.hxx"
25 #include "basebmp/iteratortraits.hxx"
27 #include "basebmp/accessor.hxx"
28 #include "basebmp/accessortraits.hxx"
29 #include "basebmp/accessoradapters.hxx"
30 #include "basebmp/colorblendaccessoradapter.hxx"
32 #include "basebmp/color.hxx"
33 #include "basebmp/colormisc.hxx"
34 #include "basebmp/colortraits.hxx"
36 #include "basebmp/greylevelformats.hxx"
37 #include "basebmp/paletteformats.hxx"
38 #include "basebmp/rgbmaskpixelformats.hxx"
39 #include "basebmp/rgb24pixelformats.hxx"
41 #include "basebmp/scanlineformats.hxx"
42 #include "basebmp/fillimage.hxx"
43 #include "basebmp/scaleimage.hxx"
44 #include "basebmp/clippedlinerenderer.hxx"
45 #include "basebmp/polypolygonrenderer.hxx"
46 #include "basebmp/genericcolorimageaccessor.hxx"
48 #include "basebmp/tools.hxx"
49 #include "intconversion.hxx"
51 #include <rtl/alloc.h>
52 #include <osl/diagnose.h>
54 #include <basegfx/tools/tools.hxx>
55 #include <basegfx/tools/canvastools.hxx>
56 #include <basegfx/range/b2ibox.hxx>
57 #include <basegfx/range/b2irange.hxx>
58 #include <basegfx/range/b2drange.hxx>
59 #include <basegfx/polygon/b2dpolygon.hxx>
60 #include <basegfx/polygon/b2dpolygontools.hxx>
61 #include <basegfx/polygon/b2dpolypolygontools.hxx>
62 #include <basegfx/point/b2ipoint.hxx>
63 #include <basegfx/vector/b2ivector.hxx>
65 #include <vigra/iteratortraits.hxx>
66 #include <vigra/rgbvalue.hxx>
67 #include <vigra/copyimage.hxx>
68 #include <vigra/tuple.hxx>
71 namespace vigra
74 /// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
75 template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex >
76 inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex>
77 operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs,
78 RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs )
80 RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res(
81 lhs[0] ^ rhs[0],
82 lhs[1] ^ rhs[1],
83 lhs[2] ^ rhs[2]);
84 return res;
88 namespace basebmp
91 namespace
93 /** Create the type for an accessor that takes the (mask,bitmap)
94 input value generated from a JoinImageAccessorAdapter, and
95 pipe that through a mask functor.
97 @tpl DestAccessor
98 Destination bitmap accessor
100 @tpl JoinedAccessor
101 Input accessor, is expected to generate a std::pair as the
102 value type
104 @tpl MaskFunctorMode
105 Either FastMask or NoFastMask, depending on whether the mask
106 is guaranteed to contain only 0s and 1s.
108 template< class DestAccessor,
109 class JoinedAccessor,
110 bool polarity,
111 typename MaskFunctorMode > struct masked_input_splitting_accessor
113 typedef BinarySetterFunctionAccessorAdapter<
114 DestAccessor,
115 BinaryFunctorSplittingWrapper<
116 typename outputMaskFunctorSelector<
117 typename JoinedAccessor::value_type::first_type,
118 typename JoinedAccessor::value_type::second_type,
119 polarity,
120 MaskFunctorMode >::type > > type;
125 // Actual BitmapDevice implementation (templatized by accessor and iterator)
126 //--------------------------------------------------------------------------
128 /** Implementation of the BitmapDevice interface
130 @tpl DestIterator
131 Iterator to access bitmap memory
133 @tpl RawAccessor
134 Raw accessor, to access pixel values directly
136 @tpl AccessorSelector
137 Accessor adapter selector, which, when applying the nested
138 template metafunction wrap_accessor to one of the raw bitmap
139 accessors, yields a member type named 'type', which is a
140 wrapped accessor that map color values.
142 @tpl Masks
143 Traits template, containing nested traits
144 clipmask_format_traits and alphamask_format_traits, which
145 determine what specialized formats are to be used for clip and
146 alpha masks. With those mask formats, clipping and alpha
147 blending is handled natively.
149 template< class DestIterator,
150 class RawAccessor,
151 class AccessorSelector,
152 class Masks > class BitmapRenderer :
153 public BitmapDevice
155 public:
156 typedef DestIterator dest_iterator_type;
157 typedef RawAccessor raw_accessor_type;
158 typedef AccessorSelector accessor_selector;
160 typedef typename Masks::clipmask_format_traits::iterator_type mask_iterator_type;
161 typedef typename Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type;
162 typedef typename Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type;
164 typedef typename Masks::alphamask_format_traits::iterator_type alphamask_iterator_type;
165 typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type;
166 typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type;
168 typedef typename AccessorSelector::template wrap_accessor<
169 raw_accessor_type >::type dest_accessor_type;
171 typedef AccessorTraits< dest_accessor_type > accessor_traits;
172 typedef CompositeIterator2D< dest_iterator_type,
173 mask_iterator_type > composite_iterator_type;
174 typedef CompositeIterator2D< vigra::Diff2D,
175 vigra::Diff2D > generic_composite_iterator_type;
177 typedef BitmapRenderer<mask_iterator_type,
178 mask_rawaccessor_type,
179 mask_accessorselector_type,
180 Masks> mask_bitmap_type;
181 typedef BitmapRenderer<alphamask_iterator_type,
182 alphamask_rawaccessor_type,
183 alphamask_accessorselector_type,
184 Masks> alphamask_bitmap_type;
186 // -------------------------------------------------------
188 typedef AccessorTraits< raw_accessor_type > raw_accessor_traits;
189 typedef typename uInt32Converter<
190 typename raw_accessor_type::value_type>::to to_uint32_functor;
192 // -------------------------------------------------------
194 typedef typename raw_accessor_traits::xor_accessor raw_xor_accessor_type;
195 typedef AccessorTraits<raw_xor_accessor_type> raw_xor_accessor_traits;
196 typedef typename accessor_selector::template wrap_accessor<
197 raw_xor_accessor_type >::type xor_accessor_type;
198 typedef AccessorTraits<xor_accessor_type> xor_accessor_traits;
200 // -------------------------------------------------------
202 typedef typename raw_accessor_traits::template masked_accessor<
203 mask_rawaccessor_type,
204 dest_iterator_type,
205 mask_iterator_type,
206 Masks::clipmask_polarity>::type raw_maskedaccessor_type;
207 typedef typename accessor_selector::template wrap_accessor<
208 raw_maskedaccessor_type >::type masked_accessor_type;
209 typedef typename AccessorTraits<
210 raw_maskedaccessor_type>::xor_accessor raw_maskedxor_accessor_type;
211 typedef typename accessor_selector::template wrap_accessor<
212 raw_maskedxor_accessor_type >::type masked_xoraccessor_type;
214 // -------------------------------------------------------
216 // ((iter,mask),mask) special case (e.g. for clipped
217 // drawMaskedColor())
218 typedef AccessorTraits< raw_maskedaccessor_type > raw_maskedaccessor_traits;
219 typedef typename raw_maskedaccessor_traits::template masked_accessor<
220 mask_rawaccessor_type,
221 composite_iterator_type,
222 mask_iterator_type,
223 Masks::clipmask_polarity>::type raw_maskedmask_accessor_type;
225 typedef CompositeIterator2D<
226 composite_iterator_type,
227 mask_iterator_type> composite_composite_mask_iterator_type;
229 // -------------------------------------------------------
231 typedef ConstantColorBlendSetterAccessorAdapter<
232 dest_accessor_type,
233 typename alphamask_rawaccessor_type::value_type,
234 Masks::alphamask_polarity> colorblend_accessor_type;
235 typedef AccessorTraits<colorblend_accessor_type> colorblend_accessor_traits;
236 typedef typename colorblend_accessor_traits::template masked_accessor<
237 mask_rawaccessor_type,
238 dest_iterator_type,
239 mask_iterator_type,
240 Masks::clipmask_polarity>::type masked_colorblend_accessor_type;
242 // -------------------------------------------------------
244 typedef ConstantColorBlendSetterAccessorAdapter<
245 dest_accessor_type,
246 Color,
247 Masks::alphamask_polarity> colorblend_generic_accessor_type;
248 typedef AccessorTraits<colorblend_generic_accessor_type> colorblend_generic_accessor_traits;
249 typedef typename colorblend_generic_accessor_traits::template masked_accessor<
250 mask_rawaccessor_type,
251 dest_iterator_type,
252 mask_iterator_type,
253 Masks::clipmask_polarity>::type masked_colorblend_generic_accessor_type;
255 // -------------------------------------------------------
257 typedef JoinImageAccessorAdapter< dest_accessor_type,
258 mask_rawaccessor_type > joined_image_accessor_type;
259 typedef JoinImageAccessorAdapter< GenericColorImageAccessor,
260 GenericColorImageAccessor > joined_generic_image_accessor_type;
262 // -------------------------------------------------------
264 dest_iterator_type maBegin;
265 typename accessor_traits::color_lookup maColorLookup;
266 IBitmapDeviceDamageTrackerSharedPtr mpDamage;
267 to_uint32_functor maToUInt32Converter;
268 dest_accessor_type maAccessor;
269 colorblend_accessor_type maColorBlendAccessor;
270 colorblend_generic_accessor_type maGenericColorBlendAccessor;
271 raw_accessor_type maRawAccessor;
272 xor_accessor_type maXorAccessor;
273 raw_xor_accessor_type maRawXorAccessor;
274 masked_accessor_type maMaskedAccessor;
275 masked_colorblend_accessor_type maMaskedColorBlendAccessor;
276 masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor;
277 masked_xoraccessor_type maMaskedXorAccessor;
278 raw_maskedaccessor_type maRawMaskedAccessor;
279 raw_maskedxor_accessor_type maRawMaskedXorAccessor;
280 raw_maskedmask_accessor_type maRawMaskedMaskAccessor;
283 // -------------------------------------------------------
285 BitmapRenderer( const basegfx::B2IBox& rBounds,
286 const basegfx::B2IVector& rBufferSize,
287 sal_Int32 nScanlineFormat,
288 sal_Int32 nScanlineStride,
289 sal_uInt8* pFirstScanline,
290 dest_iterator_type begin,
291 raw_accessor_type rawAccessor,
292 dest_accessor_type accessor,
293 const RawMemorySharedArray& rMem,
294 const PaletteMemorySharedVector& rPalette,
295 const IBitmapDeviceDamageTrackerSharedPtr& rDamage ) :
296 BitmapDevice( rBounds, rBufferSize, nScanlineFormat,
297 nScanlineStride, pFirstScanline, rMem, rPalette ),
298 maBegin( begin ),
299 maColorLookup(),
300 mpDamage(rDamage),
301 maToUInt32Converter(),
302 maAccessor( accessor ),
303 maColorBlendAccessor( accessor ),
304 maGenericColorBlendAccessor( accessor ),
305 maRawAccessor( rawAccessor ),
306 maXorAccessor( accessor ),
307 maRawXorAccessor( rawAccessor ),
308 maMaskedAccessor( accessor ),
309 maMaskedColorBlendAccessor( maColorBlendAccessor ),
310 maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ),
311 maMaskedXorAccessor( accessor ),
312 maRawMaskedAccessor( rawAccessor ),
313 maRawMaskedXorAccessor( rawAccessor ),
314 maRawMaskedMaskAccessor( rawAccessor )
317 private:
319 void damaged( const basegfx::B2IBox& rDamageRect ) const
321 if( mpDamage )
322 mpDamage->damaged( rDamageRect );
325 void damagedPointSize( const basegfx::B2IPoint& rPoint,
326 const basegfx::B2IBox& rSize ) const
328 if( mpDamage ) {
329 basegfx::B2IPoint aLower( rPoint.getX() + rSize.getWidth(),
330 rPoint.getY() + rSize.getHeight() );
331 damaged( basegfx::B2IBox( rPoint, aLower ) );
335 void damagedPixel( const basegfx::B2IPoint& rDamagePoint ) const
337 if( !mpDamage )
338 return;
340 sal_Int32 nX(rDamagePoint.getX());
341 sal_Int32 nY(rDamagePoint.getY());
342 if (nX < SAL_MAX_INT32)
343 ++nX;
344 if (nY < SAL_MAX_INT32)
345 ++nY;
347 basegfx::B2IPoint aEnd( nX, nY );
348 damaged( basegfx::B2IBox( rDamagePoint, aEnd ) );
351 boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
353 return boost::dynamic_pointer_cast< BitmapRenderer >( bmp );
356 virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
358 // TODO(P1): dynamic_cast usually called twice for
359 // compatible formats
360 return getCompatibleBitmap(bmp).get() != NULL;
363 boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
365 boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ));
367 if( !pMask )
368 return pMask;
370 if( pMask->getSize() != getSize() )
371 pMask.reset();
373 return pMask;
376 virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
378 // TODO(P1): dynamic_cast usually called twice for
379 // compatible formats
380 return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL;
383 boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
385 return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp );
388 virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
390 // TODO(P1): dynamic_cast usually called twice for
391 // compatible formats
392 return getCompatibleAlphaMask( bmp ).get() != NULL;
395 virtual void clear_i( Color fillColor,
396 const basegfx::B2IBox& rBounds )
398 fillImage(destIterRange(maBegin,
399 maRawAccessor,
400 rBounds),
401 maColorLookup(
402 maAccessor,
403 fillColor) );
404 damaged( rBounds );
407 virtual void setPixel_i( const basegfx::B2IPoint& rPt,
408 Color pixelColor,
409 DrawMode drawMode )
411 const DestIterator pixel( maBegin +
412 vigra::Diff2D(rPt.getX(),
413 rPt.getY()) );
414 if( drawMode == DrawMode_XOR )
415 maXorAccessor.set( pixelColor,
416 pixel );
417 else
418 maAccessor.set( pixelColor,
419 pixel );
420 damagedPixel(rPt);
423 virtual void setPixel_i( const basegfx::B2IPoint& rPt,
424 Color pixelColor,
425 DrawMode drawMode,
426 const BitmapDeviceSharedPtr& rClip )
428 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
429 OSL_ASSERT( pMask );
431 const vigra::Diff2D offset(rPt.getX(),
432 rPt.getY());
434 const composite_iterator_type aIter(
435 maBegin + offset,
436 pMask->maBegin + offset );
438 if( drawMode == DrawMode_XOR )
439 maMaskedXorAccessor.set( pixelColor,
440 aIter );
441 else
442 maMaskedAccessor.set( pixelColor,
443 aIter );
444 damagedPixel(rPt);
447 virtual Color getPixel_i(const basegfx::B2IPoint& rPt )
449 const DestIterator pixel( maBegin +
450 vigra::Diff2D(rPt.getX(),
451 rPt.getY()) );
452 return maAccessor(pixel);
455 virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt )
457 const DestIterator pixel( maBegin +
458 vigra::Diff2D(rPt.getX(),
459 rPt.getY()) );
460 return maToUInt32Converter(maRawAccessor(pixel));
463 template< typename Iterator, typename Col, typename RawAcc >
464 void implRenderLine2( const basegfx::B2IPoint& rPt1,
465 const basegfx::B2IPoint& rPt2,
466 const basegfx::B2IBox& rBounds,
467 Col col,
468 const Iterator& begin,
469 const RawAcc& rawAcc )
471 renderClippedLine( rPt1,
472 rPt2,
473 rBounds,
474 col,
475 begin,
476 rawAcc );
477 // TODO(P2): perhaps this needs pushing up the stack a bit
478 // to make more complex polygons more efficient ...
479 damaged( basegfx::B2IBox( rPt1, rPt2 ) );
482 template< typename Iterator, typename Accessor, typename RawAcc >
483 void implRenderLine( const basegfx::B2IPoint& rPt1,
484 const basegfx::B2IPoint& rPt2,
485 const basegfx::B2IBox& rBounds,
486 Color col,
487 const Iterator& begin,
488 const Accessor& acc,
489 const RawAcc& rawAcc )
491 implRenderLine2( rPt1,rPt2,rBounds,
492 maColorLookup( acc,
493 col ),
494 begin,
495 rawAcc );
498 template< typename Iterator, typename RawAcc, typename XorAcc >
499 void implDrawLine( const basegfx::B2IPoint& rPt1,
500 const basegfx::B2IPoint& rPt2,
501 const basegfx::B2IBox& rBounds,
502 Color col,
503 const Iterator& begin,
504 const RawAcc& rawAcc,
505 const XorAcc& xorAcc,
506 DrawMode drawMode )
508 if( drawMode == DrawMode_XOR )
509 implRenderLine( rPt1, rPt2, rBounds, col,
510 begin, maAccessor, xorAcc );
511 else
512 implRenderLine( rPt1, rPt2, rBounds, col,
513 begin, maAccessor, rawAcc );
516 virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
517 const basegfx::B2IPoint& rPt2,
518 const basegfx::B2IBox& rBounds,
519 Color lineColor,
520 DrawMode drawMode )
522 implDrawLine(rPt1,rPt2,rBounds,lineColor,
523 maBegin,
524 maRawAccessor,maRawXorAccessor,drawMode);
527 composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const
529 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
530 OSL_ASSERT( pMask );
532 return composite_iterator_type( maBegin,
533 pMask->maBegin );
536 virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
537 const basegfx::B2IPoint& rPt2,
538 const basegfx::B2IBox& rBounds,
539 Color lineColor,
540 DrawMode drawMode,
541 const BitmapDeviceSharedPtr& rClip )
543 implDrawLine(rPt1,rPt2,rBounds,lineColor,
544 getMaskedIter(rClip),
545 maRawMaskedAccessor,
546 maRawMaskedXorAccessor,drawMode);
549 template< typename Iterator, typename RawAcc >
550 void implDrawPolygon( const basegfx::B2DPolygon& rPoly,
551 const basegfx::B2IBox& rBounds,
552 Color col,
553 const Iterator& begin,
554 const RawAcc& acc )
556 basegfx::B2DPolygon aPoly( rPoly );
557 if( rPoly.areControlPointsUsed() )
558 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
560 const typename dest_iterator_type::value_type colorIndex( maColorLookup(
561 maAccessor,
562 col));
563 const sal_uInt32 nVertices( aPoly.count() );
564 for( sal_uInt32 i=1; i<nVertices; ++i )
565 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)),
566 basegfx::fround(aPoly.getB2DPoint(i)),
567 rBounds,
568 colorIndex,
569 begin,
570 acc );
572 if( nVertices > 1 && aPoly.isClosed() )
573 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)),
574 basegfx::fround(aPoly.getB2DPoint(0)),
575 rBounds,
576 colorIndex,
577 begin,
578 acc );
581 virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
582 const basegfx::B2IBox& rBounds,
583 Color lineColor,
584 DrawMode drawMode )
586 if( drawMode == DrawMode_XOR )
587 implDrawPolygon( rPoly, rBounds, lineColor,
588 maBegin,
589 maRawXorAccessor );
590 else
591 implDrawPolygon( rPoly, rBounds, lineColor,
592 maBegin,
593 maRawAccessor );
596 virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
597 const basegfx::B2IBox& rBounds,
598 Color lineColor,
599 DrawMode drawMode,
600 const BitmapDeviceSharedPtr& rClip )
602 if( drawMode == DrawMode_XOR )
603 implDrawPolygon( rPoly, rBounds, lineColor,
604 getMaskedIter(rClip),
605 maRawMaskedXorAccessor );
606 else
607 implDrawPolygon( rPoly, rBounds, lineColor,
608 getMaskedIter(rClip),
609 maRawMaskedAccessor );
612 template< typename Iterator, typename RawAcc >
613 void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
614 Color col,
615 const Iterator& begin,
616 const RawAcc& acc,
617 const basegfx::B2IBox& rBounds )
619 basegfx::B2DPolyPolygon aPoly( rPoly );
620 if( rPoly.areControlPointsUsed() )
621 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
623 renderClippedPolyPolygon( begin,
624 acc,
625 maColorLookup( maAccessor,
626 col),
627 rBounds,
628 aPoly,
629 basegfx::FillRule_EVEN_ODD );
631 if( mpDamage )
633 basegfx::B2DRange const aPolyBounds( basegfx::tools::getRange(aPoly) );
634 damaged( basegfx::unotools::b2ISurroundingBoxFromB2DRange( aPolyBounds ) );
638 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
639 Color fillColor,
640 DrawMode drawMode,
641 const basegfx::B2IBox& rBounds )
643 if( drawMode == DrawMode_XOR )
644 implFillPolyPolygon( rPoly, fillColor,
645 maBegin,
646 maRawXorAccessor,
647 rBounds );
648 else
649 implFillPolyPolygon( rPoly, fillColor,
650 maBegin,
651 maRawAccessor,
652 rBounds );
655 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
656 Color fillColor,
657 DrawMode drawMode,
658 const basegfx::B2IBox& rBounds,
659 const BitmapDeviceSharedPtr& rClip )
661 if( drawMode == DrawMode_XOR )
662 implFillPolyPolygon( rPoly, fillColor,
663 getMaskedIter(rClip),
664 maRawMaskedXorAccessor,
665 rBounds );
666 else
667 implFillPolyPolygon( rPoly, fillColor,
668 getMaskedIter(rClip),
669 maRawMaskedAccessor,
670 rBounds );
673 template< typename Iterator, typename RawAcc >
674 void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
675 const basegfx::B2IBox& rSrcRect,
676 const basegfx::B2IBox& rDstRect,
677 const Iterator& begin,
678 const RawAcc& acc)
680 boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
681 OSL_ASSERT( pSrcBmp );
683 scaleImage(
684 srcIterRange(pSrcBmp->maBegin,
685 pSrcBmp->maRawAccessor,
686 rSrcRect),
687 destIterRange(begin,
688 acc,
689 rDstRect),
690 rSrcBitmap.get() == this );
691 damaged( rDstRect );
694 template< typename Iterator, typename Acc >
695 void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
696 const basegfx::B2IBox& rSrcRect,
697 const basegfx::B2IBox& rDstRect,
698 const Iterator& begin,
699 const Acc& acc)
701 GenericColorImageAccessor aSrcAcc( rSrcBitmap );
703 scaleImage(
704 srcIterRange(vigra::Diff2D(),
705 aSrcAcc,
706 rSrcRect),
707 destIterRange(begin,
708 acc,
709 rDstRect));
710 damaged( rDstRect );
713 virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
714 const basegfx::B2IBox& rSrcRect,
715 const basegfx::B2IBox& rDstRect,
716 DrawMode drawMode )
718 if( isCompatibleBitmap( rSrcBitmap ) )
720 if( drawMode == DrawMode_XOR )
721 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
722 maBegin,
723 maRawXorAccessor);
724 else
725 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
726 maBegin,
727 maRawAccessor);
729 else
731 if( drawMode == DrawMode_XOR )
732 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
733 maBegin,
734 maXorAccessor);
735 else
736 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
737 maBegin,
738 maAccessor);
740 damaged( rDstRect );
743 virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
744 const basegfx::B2IBox& rSrcRect,
745 const basegfx::B2IBox& rDstRect,
746 DrawMode drawMode,
747 const BitmapDeviceSharedPtr& rClip )
749 if( isCompatibleBitmap( rSrcBitmap ) )
751 if( drawMode == DrawMode_XOR )
752 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
753 getMaskedIter(rClip),
754 maRawMaskedXorAccessor);
755 else
756 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
757 getMaskedIter(rClip),
758 maRawMaskedAccessor);
760 else
762 if( drawMode == DrawMode_XOR )
763 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
764 getMaskedIter(rClip),
765 maMaskedXorAccessor);
766 else
767 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
768 getMaskedIter(rClip),
769 maMaskedAccessor);
771 damaged( rDstRect );
774 virtual void drawMaskedColor_i(Color aSrcColor,
775 const BitmapDeviceSharedPtr& rAlphaMask,
776 const basegfx::B2IBox& rSrcRect,
777 const basegfx::B2IPoint& rDstPoint )
779 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
780 boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
782 if( pAlpha )
784 maColorBlendAccessor.setColor( aSrcColor );
786 vigra::copyImage( srcIterRange(pAlpha->maBegin,
787 pAlpha->maRawAccessor,
788 rSrcRect),
789 destIter(maBegin,
790 maColorBlendAccessor,
791 rDstPoint) );
793 else if( pMask )
795 const composite_iterator_type aBegin(
796 maBegin + vigra::Diff2D(rDstPoint.getX(),
797 rDstPoint.getY()),
798 pMask->maBegin + topLeft(rSrcRect) );
800 fillImage(aBegin,
801 aBegin + vigra::Diff2D(rSrcRect.getWidth(),
802 rSrcRect.getHeight()),
803 maRawMaskedAccessor,
804 maColorLookup(
805 maAccessor,
806 aSrcColor) );
808 else
810 GenericColorImageAccessor aSrcAcc( rAlphaMask );
811 maGenericColorBlendAccessor.setColor( aSrcColor );
813 vigra::copyImage( srcIterRange(vigra::Diff2D(),
814 aSrcAcc,
815 rSrcRect),
816 destIter(maBegin,
817 maGenericColorBlendAccessor,
818 rDstPoint) );
820 damagedPointSize( rDstPoint, rSrcRect );
823 virtual void drawMaskedColor_i(Color aSrcColor,
824 const BitmapDeviceSharedPtr& rAlphaMask,
825 const basegfx::B2IBox& rSrcRect,
826 const basegfx::B2IPoint& rDstPoint,
827 const BitmapDeviceSharedPtr& rClip )
829 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
830 boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
832 if( pAlpha )
834 const composite_iterator_type aBegin( getMaskedIter(rClip) );
835 maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
836 aSrcColor );
838 vigra::copyImage( srcIterRange(pAlpha->maBegin,
839 pAlpha->maRawAccessor,
840 rSrcRect),
841 destIter(aBegin,
842 maMaskedColorBlendAccessor,
843 rDstPoint) );
845 else if( pMask )
847 boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) );
848 OSL_ASSERT( pClipMask );
850 // setup a ((iter,mask),clipMask) composite composite
851 // iterator, to pass both masks (clip and alpha mask)
852 // to the algorithm
853 const composite_composite_mask_iterator_type aBegin(
854 composite_iterator_type(
855 maBegin + vigra::Diff2D(rDstPoint.getX(),
856 rDstPoint.getY()),
857 pMask->maBegin + topLeft(rSrcRect)),
858 pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(),
859 rDstPoint.getY()) );
861 fillImage(aBegin,
862 aBegin + vigra::Diff2D(rSrcRect.getWidth(),
863 rSrcRect.getHeight()),
864 maRawMaskedMaskAccessor,
865 maColorLookup(
866 maAccessor,
867 aSrcColor) );
869 else
871 GenericColorImageAccessor aSrcAcc( rAlphaMask );
872 const composite_iterator_type aBegin( getMaskedIter(rClip) );
873 maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
874 aSrcColor );
876 vigra::copyImage( srcIterRange(vigra::Diff2D(),
877 aSrcAcc,
878 rSrcRect),
879 destIter(aBegin,
880 maGenericMaskedColorBlendAccessor,
881 rDstPoint) );
883 damagedPointSize( rDstPoint, rSrcRect );
886 template< typename Iterator, typename Acc >
887 void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
888 const BitmapDeviceSharedPtr& rMask,
889 const basegfx::B2IBox& rSrcRect,
890 const basegfx::B2IBox& rDstRect,
891 const Iterator& begin,
892 const Acc& acc)
894 boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
895 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) );
896 OSL_ASSERT( pMask && pSrcBmp );
898 scaleImage(
899 srcIterRange(composite_iterator_type(
900 pSrcBmp->maBegin,
901 pMask->maBegin),
902 joined_image_accessor_type(
903 pSrcBmp->maAccessor,
904 pMask->maRawAccessor),
905 rSrcRect),
906 destIterRange(begin,
907 typename masked_input_splitting_accessor<
908 Acc,
909 joined_image_accessor_type,
910 Masks::clipmask_polarity,
911 FastMask >::type(acc),
912 rDstRect),
913 rSrcBitmap.get() == this);
914 damaged( rDstRect );
917 template< typename Iterator, typename Acc >
918 void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
919 const BitmapDeviceSharedPtr& rMask,
920 const basegfx::B2IBox& rSrcRect,
921 const basegfx::B2IBox& rDstRect,
922 const Iterator& begin,
923 const Acc& acc)
925 GenericColorImageAccessor aSrcAcc( rSrcBitmap );
926 GenericColorImageAccessor aMaskAcc( rMask );
928 const vigra::Diff2D aTopLeft(rSrcRect.getMinX(),
929 rSrcRect.getMinY());
930 const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(),
931 rSrcRect.getMaxY());
932 scaleImage(
933 vigra::make_triple(
934 generic_composite_iterator_type(
935 aTopLeft,aTopLeft),
936 generic_composite_iterator_type(
937 aBottomRight,aBottomRight),
938 joined_generic_image_accessor_type(
939 aSrcAcc,
940 aMaskAcc)),
941 destIterRange(begin,
942 typename masked_input_splitting_accessor<
943 Acc,
944 joined_generic_image_accessor_type,
945 Masks::clipmask_polarity,
946 NoFastMask >::type(acc),
947 rDstRect));
948 damaged( rDstRect );
951 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
952 const BitmapDeviceSharedPtr& rMask,
953 const basegfx::B2IBox& rSrcRect,
954 const basegfx::B2IBox& rDstRect,
955 DrawMode drawMode )
957 if( isCompatibleClipMask(rMask) &&
958 isCompatibleBitmap(rSrcBitmap) )
960 if( drawMode == DrawMode_XOR )
961 implDrawMaskedBitmap(rSrcBitmap, rMask,
962 rSrcRect, rDstRect,
963 maBegin,
964 maXorAccessor);
965 else
966 implDrawMaskedBitmap(rSrcBitmap, rMask,
967 rSrcRect, rDstRect,
968 maBegin,
969 maAccessor);
971 else
973 if( drawMode == DrawMode_XOR )
974 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
975 rSrcRect, rDstRect,
976 maBegin,
977 maXorAccessor);
978 else
979 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
980 rSrcRect, rDstRect,
981 maBegin,
982 maAccessor);
984 damaged( rDstRect );
987 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
988 const BitmapDeviceSharedPtr& rMask,
989 const basegfx::B2IBox& rSrcRect,
990 const basegfx::B2IBox& rDstRect,
991 DrawMode drawMode,
992 const BitmapDeviceSharedPtr& rClip )
994 if( isCompatibleClipMask(rMask) &&
995 isCompatibleBitmap(rSrcBitmap) )
997 if( drawMode == DrawMode_XOR )
998 implDrawMaskedBitmap(rSrcBitmap, rMask,
999 rSrcRect, rDstRect,
1000 getMaskedIter(rClip),
1001 maMaskedXorAccessor);
1002 else
1003 implDrawMaskedBitmap(rSrcBitmap, rMask,
1004 rSrcRect, rDstRect,
1005 getMaskedIter(rClip),
1006 maMaskedAccessor);
1008 else
1010 if( drawMode == DrawMode_XOR )
1011 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1012 rSrcRect, rDstRect,
1013 getMaskedIter(rClip),
1014 maMaskedXorAccessor);
1015 else
1016 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1017 rSrcRect, rDstRect,
1018 getMaskedIter(rClip),
1019 maMaskedAccessor);
1021 damaged( rDstRect );
1024 IBitmapDeviceDamageTrackerSharedPtr getDamageTracker_i() const
1026 return mpDamage;
1028 void setDamageTracker_i( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1030 mpDamage = rDamage;
1033 } // namespace
1035 struct ImplBitmapDevice
1037 /** Bitmap memory plus deleter.
1039 Always points to the start of the mem
1041 RawMemorySharedArray mpMem;
1043 /// Palette memory plus deleter (might be NULL)
1044 PaletteMemorySharedVector mpPalette;
1046 /** Bounds of the device.
1048 maBounds.getWidth()/getHeight() yield the true size of the
1049 device (i.e. the rectangle given by maBounds covers the device
1050 area under the including-the-bottommost-and-rightmost-pixels
1051 fill rule)
1053 basegfx::B2IBox maBounds;
1055 //// Size of the actual frame buffer
1056 basegfx::B2IVector maBufferSize;
1058 /// Scanline format, as provided at the constructor
1059 sal_Int32 mnScanlineFormat;
1061 /// Scanline stride. Negative for bottom-to-top formats
1062 sal_Int32 mnScanlineStride;
1064 /// raw ptr to 0th scanline. used for cloning a generic renderer
1065 sal_uInt8* mpFirstScanline;
1067 /** (Optional) device sharing the same memory, and used for input
1068 clip masks/alpha masks/bitmaps that don't match our exact
1069 bitmap format.
1071 This is to avoid the combinatorical explosion when dealing
1072 with n bitmap formats, which could be combined with n clip
1073 masks, alpha masks and bitmap masks (yielding a total of n^4
1074 combinations). Since each BitmapRenderer is specialized for
1075 one specific combination of said formats, a lot of duplicate
1076 code would be generated, most of which probably never
1077 used. Therefore, only the most common combinations are
1078 specialized templates, the remainder gets handled by this
1079 generic renderer (via runtime polymorphism).
1081 BitmapDeviceSharedPtr mpGenericRenderer;
1085 BitmapDevice::BitmapDevice( const basegfx::B2IBox& rBounds,
1086 const basegfx::B2IVector& rBufferSize,
1087 sal_Int32 nScanlineFormat,
1088 sal_Int32 nScanlineStride,
1089 sal_uInt8* pFirstScanline,
1090 const RawMemorySharedArray& rMem,
1091 const PaletteMemorySharedVector& rPalette ) :
1092 mpImpl( new ImplBitmapDevice )
1094 mpImpl->mpMem = rMem;
1095 mpImpl->mpPalette = rPalette;
1096 mpImpl->maBounds = rBounds;
1097 mpImpl->maBufferSize = rBufferSize;
1098 mpImpl->mnScanlineFormat = nScanlineFormat;
1099 mpImpl->mnScanlineStride = nScanlineStride;
1100 mpImpl->mpFirstScanline = pFirstScanline;
1103 BitmapDevice::~BitmapDevice()
1105 // outline, because of internal ImplBitmapDevice
1106 SAL_INFO( "basebmp.bitmapdevice", "~BitmapDevice(" << this << ")" );
1109 basegfx::B2IVector BitmapDevice::getSize() const
1111 return basegfx::B2IVector(
1112 mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(),
1113 mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() );
1116 bool BitmapDevice::isTopDown() const
1118 return mpImpl->mnScanlineStride >= 0;
1121 basegfx::B2IVector BitmapDevice::getBufferSize() const
1123 return mpImpl->maBufferSize;
1126 sal_Int32 BitmapDevice::getScanlineFormat() const
1128 return mpImpl->mnScanlineFormat;
1131 sal_Int32 BitmapDevice::getScanlineStride() const
1133 return mpImpl->mnScanlineStride < 0 ?
1134 -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride;
1137 RawMemorySharedArray BitmapDevice::getBuffer() const
1139 return mpImpl->mpMem;
1142 IBitmapDeviceDamageTrackerSharedPtr BitmapDevice::getDamageTracker() const
1144 return getDamageTracker_i();
1147 void BitmapDevice::setDamageTracker( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1149 setDamageTracker_i(rDamage);
1152 PaletteMemorySharedVector BitmapDevice::getPalette() const
1154 return mpImpl->mpPalette;
1157 void BitmapDevice::clear( Color fillColor )
1159 clear_i( fillColor, mpImpl->maBounds );
1162 void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1163 Color lineColor,
1164 DrawMode drawMode )
1166 if( mpImpl->maBounds.isInside(rPt) )
1167 setPixel_i(rPt,lineColor,drawMode);
1170 void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1171 Color lineColor,
1172 DrawMode drawMode,
1173 const BitmapDeviceSharedPtr& rClip )
1175 if( !rClip )
1177 setPixel(rPt,lineColor,drawMode);
1178 return;
1181 if( mpImpl->maBounds.isInside(rPt) )
1183 if( isCompatibleClipMask( rClip ) )
1184 setPixel_i(rPt,lineColor,drawMode,rClip);
1185 else
1186 getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip );
1190 Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt )
1192 if( mpImpl->maBounds.isInside(rPt) )
1193 return getPixel_i(rPt);
1195 return Color();
1198 sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
1200 if( mpImpl->maBounds.isInside(rPt) )
1201 return getPixelData_i(rPt);
1203 return 0;
1206 void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1207 const basegfx::B2IPoint& rPt2,
1208 Color lineColor,
1209 DrawMode drawMode )
1211 drawLine_i( rPt1,
1212 rPt2,
1213 mpImpl->maBounds,
1214 lineColor,
1215 drawMode );
1218 void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1219 const basegfx::B2IPoint& rPt2,
1220 Color lineColor,
1221 DrawMode drawMode,
1222 const BitmapDeviceSharedPtr& rClip )
1224 if( !rClip )
1226 drawLine(rPt1,rPt2,lineColor,drawMode);
1227 return;
1230 if( isCompatibleClipMask( rClip ) )
1231 drawLine_i( rPt1,
1232 rPt2,
1233 mpImpl->maBounds,
1234 lineColor,
1235 drawMode,
1236 rClip );
1237 else
1238 getGenericRenderer()->drawLine( rPt1, rPt2, lineColor,
1239 drawMode, rClip );
1242 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1243 Color lineColor,
1244 DrawMode drawMode )
1246 const sal_uInt32 numVertices( rPoly.count() );
1247 if( numVertices )
1248 drawPolygon_i( rPoly,
1249 mpImpl->maBounds,
1250 lineColor, drawMode );
1253 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1254 Color lineColor,
1255 DrawMode drawMode,
1256 const BitmapDeviceSharedPtr& rClip )
1258 if( !rClip )
1260 drawPolygon(rPoly,lineColor,drawMode);
1261 return;
1264 const sal_uInt32 numVertices( rPoly.count() );
1265 if( numVertices )
1267 if( isCompatibleClipMask( rClip ) )
1268 drawPolygon_i( rPoly,
1269 mpImpl->maBounds,
1270 lineColor, drawMode, rClip );
1271 else
1272 getGenericRenderer()->drawPolygon( rPoly, lineColor,
1273 drawMode, rClip );
1277 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1278 Color fillColor,
1279 DrawMode drawMode )
1281 fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
1284 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1285 Color fillColor,
1286 DrawMode drawMode,
1287 const BitmapDeviceSharedPtr& rClip )
1289 if( !rClip )
1291 fillPolyPolygon(rPoly,fillColor,drawMode);
1292 return;
1295 if( isCompatibleClipMask( rClip ) )
1296 fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
1297 else
1298 getGenericRenderer()->fillPolyPolygon( rPoly, fillColor,
1299 drawMode, rClip );
1303 namespace
1305 void assertImagePoint( const basegfx::B2IPoint& rPt,
1306 const basegfx::B2IBox& rPermittedRange )
1308 (void)rPt; (void)rPermittedRange;
1309 OSL_ASSERT( rPermittedRange.isInside(rPt) );
1312 void assertImageRange( const basegfx::B2IBox& rRange,
1313 const basegfx::B2IBox& rPermittedRange )
1315 #if OSL_DEBUG_LEVEL > 0
1316 basegfx::B2IBox aRange( rRange );
1317 aRange.intersect( rPermittedRange );
1319 OSL_ASSERT( aRange == rRange );
1320 #else
1321 (void)rRange; (void)rPermittedRange;
1322 #endif
1325 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1326 // to basegfx, and use here!
1327 bool clipAreaImpl( ::basegfx::B2IBox& io_rSourceArea,
1328 ::basegfx::B2IPoint& io_rDestPoint,
1329 const ::basegfx::B2IBox& rSourceBounds,
1330 const ::basegfx::B2IBox& rDestBounds )
1332 const ::basegfx::B2IPoint aSourceTopLeft(
1333 io_rSourceArea.getMinimum() );
1335 ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1337 // clip source area (which must be inside rSourceBounds)
1338 aLocalSourceArea.intersect( rSourceBounds );
1340 if( aLocalSourceArea.isEmpty() )
1341 return false;
1343 // calc relative new source area points (relative to orig
1344 // source area)
1345 const ::basegfx::B2IVector aUpperLeftOffset(
1346 aLocalSourceArea.getMinimum()-aSourceTopLeft );
1347 const ::basegfx::B2IVector aLowerRightOffset(
1348 aLocalSourceArea.getMaximum()-aSourceTopLeft );
1350 ::basegfx::B2IBox aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1351 io_rDestPoint + aLowerRightOffset );
1353 // clip dest area (which must be inside rDestBounds)
1354 aLocalDestArea.intersect( rDestBounds );
1356 if( aLocalDestArea.isEmpty() )
1357 return false;
1359 // calc relative new dest area points (relative to orig
1360 // source area)
1361 const ::basegfx::B2IVector aDestUpperLeftOffset(
1362 aLocalDestArea.getMinimum()-io_rDestPoint );
1363 const ::basegfx::B2IVector aDestLowerRightOffset(
1364 aLocalDestArea.getMaximum()-io_rDestPoint );
1366 io_rSourceArea = ::basegfx::B2IBox( aSourceTopLeft + aDestUpperLeftOffset,
1367 aSourceTopLeft + aDestLowerRightOffset );
1368 io_rDestPoint = aLocalDestArea.getMinimum();
1370 return true;
1373 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1374 // to basegfx, and use here!
1375 bool clipAreaImpl( ::basegfx::B2IBox& io_rDestArea,
1376 ::basegfx::B2IBox& io_rSourceArea,
1377 const ::basegfx::B2IBox& rDestBounds,
1378 const ::basegfx::B2IBox& rSourceBounds )
1380 // extract inherent scale
1381 const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() );
1382 const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() );
1384 // extract range origins
1385 const basegfx::B2IPoint aDestTopLeft(
1386 io_rDestArea.getMinimum() );
1387 const ::basegfx::B2IPoint aSourceTopLeft(
1388 io_rSourceArea.getMinimum() );
1390 ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1392 // clip source area (which must be inside rSourceBounds)
1393 aLocalSourceArea.intersect( rSourceBounds );
1395 if( aLocalSourceArea.isEmpty() )
1396 return false;
1398 // calc relative new source area points (relative to orig
1399 // source area)
1400 const ::basegfx::B2IVector aUpperLeftOffset(
1401 aLocalSourceArea.getMinimum()-aSourceTopLeft );
1402 const ::basegfx::B2IVector aLowerRightOffset(
1403 aLocalSourceArea.getMaximum()-aSourceTopLeft );
1405 ::basegfx::B2IBox aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
1406 basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
1407 basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
1408 basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
1410 // clip dest area (which must be inside rDestBounds)
1411 aLocalDestArea.intersect( rDestBounds );
1413 if( aLocalDestArea.isEmpty() )
1414 return false;
1416 // calc relative new dest area points (relative to orig
1417 // source area)
1418 const ::basegfx::B2IVector aDestUpperLeftOffset(
1419 aLocalDestArea.getMinimum()-aDestTopLeft );
1420 const ::basegfx::B2IVector aDestLowerRightOffset(
1421 aLocalDestArea.getMaximum()-aDestTopLeft );
1423 io_rSourceArea = ::basegfx::B2IBox( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
1424 basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
1425 basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
1426 basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
1427 io_rDestArea = aLocalDestArea;
1429 // final source area clip (chopping round-offs)
1430 io_rSourceArea.intersect( rSourceBounds );
1432 if( io_rSourceArea.isEmpty() )
1433 return false;
1436 return true;
1440 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1441 const basegfx::B2IBox& rSrcRect,
1442 const basegfx::B2IBox& rDstRect,
1443 DrawMode drawMode )
1445 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1446 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1447 basegfx::B2IBox aSrcRange( rSrcRect );
1448 basegfx::B2IBox aDestRange( rDstRect );
1450 if( clipAreaImpl( aDestRange,
1451 aSrcRange,
1452 mpImpl->maBounds,
1453 aSrcBounds ))
1455 assertImageRange(aDestRange,mpImpl->maBounds);
1456 assertImageRange(aSrcRange,aSrcBounds);
1458 drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode );
1462 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1463 const basegfx::B2IBox& rSrcRect,
1464 const basegfx::B2IBox& rDstRect,
1465 DrawMode drawMode,
1466 const BitmapDeviceSharedPtr& rClip )
1468 if( !rClip )
1470 drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
1471 return;
1474 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1475 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1476 basegfx::B2IBox aSrcRange( rSrcRect );
1477 basegfx::B2IBox aDestRange( rDstRect );
1479 if( clipAreaImpl( aDestRange,
1480 aSrcRange,
1481 mpImpl->maBounds,
1482 aSrcBounds ))
1484 assertImageRange(aDestRange,mpImpl->maBounds);
1485 assertImageRange(aSrcRange,aSrcBounds);
1487 if( isCompatibleClipMask( rClip ) )
1489 drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip );
1491 else
1493 getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect,
1494 rDstRect, drawMode, rClip );
1499 void BitmapDevice::drawMaskedColor( Color aSrcColor,
1500 const BitmapDeviceSharedPtr& rAlphaMask,
1501 const basegfx::B2IBox& rSrcRect,
1502 const basegfx::B2IPoint& rDstPoint )
1504 const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1505 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1506 basegfx::B2IBox aSrcRange( rSrcRect );
1507 basegfx::B2IPoint aDestPoint( rDstPoint );
1509 if( clipAreaImpl( aSrcRange,
1510 aDestPoint,
1511 aSrcBounds,
1512 mpImpl->maBounds ))
1514 assertImagePoint(aDestPoint,mpImpl->maBounds);
1515 assertImageRange(aSrcRange,aSrcBounds);
1517 if( rAlphaMask.get() == this )
1519 // src == dest, copy rAlphaMask beforehand
1520 // ---------------------------------------------------
1522 const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1523 aSrcRange.getHeight() );
1524 BitmapDeviceSharedPtr pAlphaCopy(
1525 cloneBitmapDevice( aSize,
1526 shared_from_this()) );
1527 basegfx::B2ITuple aGcc3WorkaroundTemporary;
1528 const basegfx::B2IBox aAlphaRange( aGcc3WorkaroundTemporary,
1529 aSize );
1530 pAlphaCopy->drawBitmap(rAlphaMask,
1531 aSrcRange,
1532 aAlphaRange,
1533 DrawMode_PAINT);
1534 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint );
1536 else
1538 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint );
1543 void BitmapDevice::drawMaskedColor( Color aSrcColor,
1544 const BitmapDeviceSharedPtr& rAlphaMask,
1545 const basegfx::B2IBox& rSrcRect,
1546 const basegfx::B2IPoint& rDstPoint,
1547 const BitmapDeviceSharedPtr& rClip )
1549 if( !rClip )
1551 drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
1552 return;
1555 const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1556 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1557 basegfx::B2IBox aSrcRange( rSrcRect );
1558 basegfx::B2IPoint aDestPoint( rDstPoint );
1560 if( clipAreaImpl( aSrcRange,
1561 aDestPoint,
1562 aSrcBounds,
1563 mpImpl->maBounds ))
1565 assertImagePoint(aDestPoint,mpImpl->maBounds);
1566 assertImageRange(aSrcRange,aSrcBounds);
1568 if( isCompatibleClipMask( rClip ) )
1570 if( rAlphaMask.get() == this )
1572 // src == dest, copy rAlphaMask beforehand
1573 // ---------------------------------------------------
1575 const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1576 aSrcRange.getHeight() );
1577 BitmapDeviceSharedPtr pAlphaCopy(
1578 cloneBitmapDevice( aSize,
1579 shared_from_this()) );
1580 basegfx::B2ITuple aGcc3WorkaroundTemporary;
1581 const basegfx::B2IBox aAlphaRange( aGcc3WorkaroundTemporary,
1582 aSize );
1583 pAlphaCopy->drawBitmap(rAlphaMask,
1584 aSrcRange,
1585 aAlphaRange,
1586 DrawMode_PAINT);
1587 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip );
1589 else
1591 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
1594 else
1596 getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask,
1597 rSrcRect, rDstPoint, rClip );
1602 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1603 const BitmapDeviceSharedPtr& rMask,
1604 const basegfx::B2IBox& rSrcRect,
1605 const basegfx::B2IBox& rDstRect,
1606 DrawMode drawMode )
1608 OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1610 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1611 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1612 basegfx::B2IBox aSrcRange( rSrcRect );
1613 basegfx::B2IBox aDestRange( rDstRect );
1615 if( clipAreaImpl( aDestRange,
1616 aSrcRange,
1617 mpImpl->maBounds,
1618 aSrcBounds ))
1620 assertImageRange(aDestRange,mpImpl->maBounds);
1621 assertImageRange(aSrcRange,aSrcBounds);
1623 drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode );
1627 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1628 const BitmapDeviceSharedPtr& rMask,
1629 const basegfx::B2IBox& rSrcRect,
1630 const basegfx::B2IBox& rDstRect,
1631 DrawMode drawMode,
1632 const BitmapDeviceSharedPtr& rClip )
1634 if( !rClip )
1636 drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
1637 return;
1640 OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1642 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1643 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1644 basegfx::B2IBox aSrcRange( rSrcRect );
1645 basegfx::B2IBox aDestRange( rDstRect );
1647 if( clipAreaImpl( aDestRange,
1648 aSrcRange,
1649 mpImpl->maBounds,
1650 aSrcBounds ))
1652 assertImageRange(aDestRange,mpImpl->maBounds);
1653 assertImageRange(aSrcRange,aSrcBounds);
1655 if( isCompatibleClipMask( rClip ) )
1657 drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip );
1659 else
1661 getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect,
1662 rDstRect, drawMode, rClip );
1668 //----------------------------------------------------------------------------------
1670 /** Standard clip and alpha masks
1672 struct StdMasks
1674 typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits;
1675 typedef PixelFormatTraits_GREY8 alphamask_format_traits;
1677 /// Clipmask: 0 means opaque
1678 static const bool clipmask_polarity = false;
1680 /// Alpha mask: 0 means fully transparent
1681 static const bool alphamask_polarity = true;
1684 //----------------------------------------------------------------------------------
1686 // Some compilers don't like the nested template wrap_accessor
1687 // reference in the parameter list - being slightly less type safe,
1688 // then.
1689 #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
1691 /// Produces a specialized renderer for the given pixel format
1692 template< class FormatTraits, class MaskTraits >
1693 BitmapDeviceSharedPtr createRenderer(
1694 const basegfx::B2IBox& rBounds,
1695 const basegfx::B2IVector& rBufferSize,
1696 sal_Int32 nScanlineFormat,
1697 sal_Int32 nScanlineStride,
1698 sal_uInt8* pFirstScanline,
1699 typename FormatTraits::raw_accessor_type const& rRawAccessor,
1700 typename FormatTraits::accessor_selector::template wrap_accessor<
1701 typename FormatTraits::raw_accessor_type>::type const& rAccessor,
1702 boost::shared_array< sal_uInt8 > pMem,
1703 const PaletteMemorySharedVector& pPal,
1704 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1705 #else
1707 template< class FormatTraits, class MaskTraits, class Accessor >
1708 BitmapDeviceSharedPtr createRenderer(
1709 const basegfx::B2IBox& rBounds,
1710 const basegfx::B2IVector& rBufferSize,
1711 sal_Int32 nScanlineFormat,
1712 sal_Int32 nScanlineStride,
1713 sal_uInt8* pFirstScanline,
1714 typename FormatTraits::raw_accessor_type const& rRawAccessor,
1715 Accessor const& rAccessor,
1716 boost::shared_array< sal_uInt8 > pMem,
1717 const PaletteMemorySharedVector& pPal,
1718 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1720 #endif
1722 typedef typename FormatTraits::iterator_type Iterator;
1723 typedef BitmapRenderer< Iterator,
1724 typename FormatTraits::raw_accessor_type,
1725 typename FormatTraits::accessor_selector,
1726 MaskTraits > Renderer;
1728 return BitmapDeviceSharedPtr(
1729 new Renderer( rBounds,
1730 rBufferSize,
1731 nScanlineFormat,
1732 nScanlineStride,
1733 pFirstScanline,
1734 Iterator(
1735 reinterpret_cast<typename Iterator::value_type*>(
1736 pFirstScanline),
1737 nScanlineStride),
1738 rRawAccessor,
1739 rAccessor,
1740 pMem,
1741 pPal,
1742 pDamage ));
1745 /// Create standard grey level palette
1746 PaletteMemorySharedVector createStandardPalette(
1747 const PaletteMemorySharedVector& pPal,
1748 sal_Int32 nNumEntries )
1750 if( pPal || nNumEntries <= 0 )
1751 return pPal;
1753 boost::shared_ptr< std::vector<Color> > pLocalPal(
1754 new std::vector<Color>(nNumEntries) );
1756 const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries );
1757 --nNumEntries;
1758 for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement )
1759 pLocalPal->at(i) = Color(0xFF000000 | c);
1761 pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF);
1763 return pLocalPal;
1766 template< class FormatTraits, class MaskTraits >
1767 BitmapDeviceSharedPtr createRenderer(
1768 const basegfx::B2IBox& rBounds,
1769 const basegfx::B2IVector& rBufferSize,
1770 sal_Int32 nScanlineFormat,
1771 sal_Int32 nScanlineStride,
1772 sal_uInt8* pFirstScanline,
1773 boost::shared_array< sal_uInt8 > pMem,
1774 const PaletteMemorySharedVector& pPal,
1775 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1777 return createRenderer<FormatTraits,
1778 MaskTraits>(rBounds,
1779 rBufferSize,
1780 nScanlineFormat,
1781 nScanlineStride,
1782 pFirstScanline,
1783 typename FormatTraits::raw_accessor_type(),
1784 typename FormatTraits::accessor_selector::template
1785 wrap_accessor<
1786 typename FormatTraits::raw_accessor_type>::type(),
1787 pMem,
1788 pPal,
1789 pDamage);
1792 template< class FormatTraits, class MaskTraits >
1793 BitmapDeviceSharedPtr createRenderer(
1794 const basegfx::B2IBox& rBounds,
1795 const basegfx::B2IVector& rBufferSize,
1796 sal_Int32 nScanlineFormat,
1797 sal_Int32 nScanlineStride,
1798 sal_uInt8* pFirstScanline,
1799 boost::shared_array< sal_uInt8 > pMem,
1800 PaletteMemorySharedVector pPal,
1801 int nBitsPerPixel,
1802 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1804 pPal = createStandardPalette(pPal,
1805 1UL << nBitsPerPixel);
1807 OSL_ASSERT(pPal);
1808 return createRenderer<FormatTraits,
1809 MaskTraits>(rBounds,
1810 rBufferSize,
1811 nScanlineFormat,
1812 nScanlineStride,
1813 pFirstScanline,
1814 typename FormatTraits::raw_accessor_type(),
1815 typename FormatTraits::accessor_selector::template
1816 wrap_accessor<
1817 typename FormatTraits::raw_accessor_type>::type(
1818 &pPal->at(0),
1819 pPal->size()),
1820 pMem,
1821 pPal,
1822 pDamage);
1825 //----------------------------------------------------------------------------------
1827 // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
1828 // to o3tl or sal/bithacks.hxx ...
1830 /** Compute the next highest power of 2 of a 32-bit value
1832 Code devised by Sean Anderson, in good ole HAKMEM
1833 tradition.
1835 @return 1 << (lg(x - 1) + 1)
1837 inline sal_uInt32 nextPow2( sal_uInt32 x )
1839 --x;
1840 x |= x >> 1;
1841 x |= x >> 2;
1842 x |= x >> 4;
1843 x |= x >> 8;
1844 x |= x >> 16;
1846 return ++x;
1849 //----------------------------------------------------------------------------------
1851 namespace
1853 BitmapDeviceSharedPtr createBitmapDeviceImplInner( const basegfx::B2IVector& rSize,
1854 bool bTopDown,
1855 sal_Int32 nScanlineFormat,
1856 boost::shared_array< sal_uInt8 > pMem,
1857 PaletteMemorySharedVector pPal,
1858 const basegfx::B2IBox* pSubset,
1859 const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1861 OSL_ASSERT(rSize.getX() > 0 && rSize.getY() > 0);
1863 if( nScanlineFormat <= Format::NONE ||
1864 nScanlineFormat > Format::MAX )
1865 return BitmapDeviceSharedPtr();
1867 static const sal_uInt8 bitsPerPixel[] =
1869 0, // NONE
1870 1, // ONE_BIT_MSB_GREY
1871 1, // ONE_BIT_LSB_GREY
1872 1, // ONE_BIT_MSB_PAL
1873 1, // ONE_BIT_LSB_PAL
1874 4, // FOUR_BIT_MSB_GREY
1875 4, // FOUR_BIT_LSB_GREY
1876 4, // FOUR_BIT_MSB_PAL
1877 4, // FOUR_BIT_LSB_PAL
1878 8, // EIGHT_BIT_PAL
1879 8, // EIGHT_BIT_GREY
1880 16, // SIXTEEN_BIT_LSB_TC_MASK
1881 16, // SIXTEEN_BIT_MSB_TC_MASK
1882 24, // TWENTYFOUR_BIT_TC_MASK
1883 32, // THIRTYTWO_BIT_TC_MASK_BGRA
1884 32, // THIRTYTWO_BIT_TC_MASK_ARGB
1885 32, // THIRTYTWO_BIT_TC_MASK_ABGR
1886 32, // THIRTYTWO_BIT_TC_MASK_RGBA
1889 sal_Int32 nScanlineStride(0);
1891 // round up to full 8 bit, divide by 8
1892 nScanlineStride = (rSize.getX()*bitsPerPixel[nScanlineFormat] + 7) >> 3;
1894 // rounded up to next full power-of-two number of bytes
1895 const sal_uInt32 bytesPerPixel = nextPow2(
1896 (bitsPerPixel[nScanlineFormat] + 7) >> 3);
1898 // now make nScanlineStride a multiple of bytesPerPixel
1899 nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel;
1901 // factor in bottom-up scanline order case
1902 nScanlineStride *= bTopDown ? 1 : -1;
1904 const sal_uInt32 nWidth(nScanlineStride < 0 ? -nScanlineStride : nScanlineStride);
1905 const sal_uInt32 nHeight(rSize.getY());
1907 if (nHeight && nWidth && nWidth > SAL_MAX_INT32 / nHeight)
1909 SAL_WARN( "basebmp", "suspicious massive alloc " << nWidth << " * " << nHeight);
1910 return BitmapDeviceSharedPtr();
1913 const std::size_t nMemSize(nWidth * nHeight);
1915 if( !pMem )
1917 pMem.reset(
1918 reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
1919 &rtl_freeMemory );
1920 if (pMem.get() == 0 && nMemSize != 0)
1921 return BitmapDeviceSharedPtr();
1922 memset(pMem.get(), 0, nMemSize);
1925 sal_uInt8* pFirstScanline = nScanlineStride < 0 ?
1926 pMem.get() + nMemSize + nScanlineStride : pMem.get();
1928 // shrink render area to given subset, if given
1929 basegfx::B2IBox aBounds(0,0,rSize.getX(),rSize.getY());
1930 if( pSubset )
1931 aBounds.intersect( *pSubset );
1933 switch( nScanlineFormat )
1935 // ----------------------------------------------------------------------
1936 // one bit formats
1938 case Format::ONE_BIT_MSB_GREY:
1939 return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>(
1940 aBounds, rSize, nScanlineFormat, nScanlineStride,
1941 pFirstScanline, pMem, pPal, rDamage );
1943 case Format::ONE_BIT_LSB_GREY:
1944 return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>(
1945 aBounds, rSize, nScanlineFormat, nScanlineStride,
1946 pFirstScanline, pMem, pPal, rDamage );
1948 case Format::ONE_BIT_MSB_PAL:
1949 return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>(
1950 aBounds, rSize, nScanlineFormat, nScanlineStride,
1951 pFirstScanline, pMem, pPal,
1952 bitsPerPixel[nScanlineFormat], rDamage );
1954 case Format::ONE_BIT_LSB_PAL:
1955 return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>(
1956 aBounds, rSize, nScanlineFormat, nScanlineStride,
1957 pFirstScanline, pMem, pPal,
1958 bitsPerPixel[nScanlineFormat], rDamage );
1961 // ----------------------------------------------------------------------
1962 // four bit formats
1964 case Format::FOUR_BIT_MSB_GREY:
1965 return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>(
1966 aBounds, rSize, nScanlineFormat, nScanlineStride,
1967 pFirstScanline, pMem, pPal, rDamage );
1969 case Format::FOUR_BIT_LSB_GREY:
1970 return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>(
1971 aBounds, rSize, nScanlineFormat, nScanlineStride,
1972 pFirstScanline, pMem, pPal, rDamage );
1974 case Format::FOUR_BIT_MSB_PAL:
1975 return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>(
1976 aBounds, rSize, nScanlineFormat, nScanlineStride,
1977 pFirstScanline, pMem, pPal,
1978 bitsPerPixel[nScanlineFormat], rDamage );
1980 case Format::FOUR_BIT_LSB_PAL:
1981 return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>(
1982 aBounds, rSize, nScanlineFormat, nScanlineStride,
1983 pFirstScanline, pMem, pPal,
1984 bitsPerPixel[nScanlineFormat], rDamage );
1987 // ----------------------------------------------------------------------
1988 // eight bit formats
1990 case Format::EIGHT_BIT_GREY:
1991 return createRenderer<PixelFormatTraits_GREY8,StdMasks>(
1992 aBounds, rSize, nScanlineFormat, nScanlineStride,
1993 pFirstScanline, pMem, pPal, rDamage );
1995 case Format::EIGHT_BIT_PAL:
1996 return createRenderer<PixelFormatTraits_PAL8,StdMasks>(
1997 aBounds, rSize, nScanlineFormat, nScanlineStride,
1998 pFirstScanline, pMem, pPal,
1999 bitsPerPixel[nScanlineFormat], rDamage );
2002 // ----------------------------------------------------------------------
2003 // sixteen bit formats
2005 case Format::SIXTEEN_BIT_LSB_TC_MASK:
2006 return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>(
2007 aBounds, rSize, nScanlineFormat, nScanlineStride,
2008 pFirstScanline, pMem, pPal, rDamage );
2010 case Format::SIXTEEN_BIT_MSB_TC_MASK:
2011 return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>(
2012 aBounds, rSize, nScanlineFormat, nScanlineStride,
2013 pFirstScanline, pMem, pPal, rDamage );
2016 // ----------------------------------------------------------------------
2017 // twentyfour bit formats
2018 case Format::TWENTYFOUR_BIT_TC_MASK:
2019 return createRenderer<PixelFormatTraits_BGR24,StdMasks>(
2020 aBounds, rSize, nScanlineFormat, nScanlineStride,
2021 pFirstScanline, pMem, pPal, rDamage );
2024 // ----------------------------------------------------------------------
2025 // thirtytwo bit formats
2027 case Format::THIRTYTWO_BIT_TC_MASK_BGRA:
2028 return createRenderer<PixelFormatTraits_BGRX32_8888,StdMasks>(
2029 aBounds, rSize, nScanlineFormat, nScanlineStride,
2030 pFirstScanline, pMem, pPal, rDamage );
2032 case Format::THIRTYTWO_BIT_TC_MASK_ARGB:
2033 return createRenderer<PixelFormatTraits_XRGB32_8888,StdMasks>(
2034 aBounds, rSize, nScanlineFormat, nScanlineStride,
2035 pFirstScanline, pMem, pPal, rDamage );
2037 case Format::THIRTYTWO_BIT_TC_MASK_ABGR:
2038 return createRenderer<PixelFormatTraits_XBGR32_8888,StdMasks>(
2039 aBounds, rSize, nScanlineFormat, nScanlineStride,
2040 pFirstScanline, pMem, pPal, rDamage );
2042 case Format::THIRTYTWO_BIT_TC_MASK_RGBA:
2043 return createRenderer<PixelFormatTraits_RGBX32_8888,StdMasks>(
2044 aBounds, rSize, nScanlineFormat, nScanlineStride,
2045 pFirstScanline, pMem, pPal, rDamage );
2048 // TODO(F3): other formats not yet implemented
2049 return BitmapDeviceSharedPtr();
2052 BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize,
2053 bool bTopDown,
2054 sal_Int32 nScanlineFormat,
2055 boost::shared_array< sal_uInt8 > pMem,
2056 PaletteMemorySharedVector pPal,
2057 const basegfx::B2IBox* pSubset,
2058 const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
2060 BitmapDeviceSharedPtr result( createBitmapDeviceImplInner( rSize, bTopDown, nScanlineFormat, pMem, pPal, pSubset, rDamage ) );
2062 #ifdef SAL_LOG_INFO
2063 std::ostringstream subset;
2065 if (pSubset)
2066 subset << " subset=" << pSubset->getWidth() << "x" << pSubset->getHeight() << "@(" << pSubset->getMinX() << "," << pSubset->getMinY() << ")";
2068 SAL_INFO( "basebmp.bitmapdevice",
2069 "createBitmapDevice: "
2070 << rSize.getX() << "x" << rSize.getY()
2071 << (bTopDown ? " top-down " : " bottom-up ")
2072 << Format::formatName(nScanlineFormat)
2073 << subset.str()
2074 << " = " << result.get() );
2075 #endif
2076 return result;
2078 } // namespace
2081 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2082 bool bTopDown,
2083 sal_Int32 nScanlineFormat )
2085 return createBitmapDeviceImpl( rSize,
2086 bTopDown,
2087 nScanlineFormat,
2088 boost::shared_array< sal_uInt8 >(),
2089 PaletteMemorySharedVector(),
2090 NULL,
2091 IBitmapDeviceDamageTrackerSharedPtr() );
2094 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2095 bool bTopDown,
2096 sal_Int32 nScanlineFormat,
2097 const PaletteMemorySharedVector& rPalette )
2099 return createBitmapDeviceImpl( rSize,
2100 bTopDown,
2101 nScanlineFormat,
2102 boost::shared_array< sal_uInt8 >(),
2103 rPalette,
2104 NULL,
2105 IBitmapDeviceDamageTrackerSharedPtr() );
2108 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2109 bool bTopDown,
2110 sal_Int32 nScanlineFormat,
2111 const RawMemorySharedArray& rMem,
2112 const PaletteMemorySharedVector& rPalette )
2114 return createBitmapDeviceImpl( rSize,
2115 bTopDown,
2116 nScanlineFormat,
2117 rMem,
2118 rPalette,
2119 NULL,
2120 IBitmapDeviceDamageTrackerSharedPtr() );
2123 BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto,
2124 const basegfx::B2IBox& rSubset )
2126 SAL_INFO( "basebmp.bitmapdevice", "subsetBitmapDevice: proto=" << rProto.get() );
2127 return createBitmapDeviceImpl( rProto->getSize(),
2128 rProto->isTopDown(),
2129 rProto->getScanlineFormat(),
2130 rProto->getBuffer(),
2131 rProto->getPalette(),
2132 &rSubset,
2133 rProto->getDamageTracker() );
2136 BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize,
2137 const BitmapDeviceSharedPtr& rProto )
2139 return createBitmapDeviceImpl( rSize,
2140 rProto->isTopDown(),
2141 rProto->getScanlineFormat(),
2142 boost::shared_array< sal_uInt8 >(),
2143 rProto->getPalette(),
2144 NULL,
2145 rProto->getDamageTracker() );
2148 //----------------------------------------------------------------------------------
2150 /// Clone our device, with GenericImageAccessor to handle all formats
2151 BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const
2153 return mpImpl->mpGenericRenderer;
2156 } // namespace basebmp
2158 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */