bump product version to 5.0.4.1
[LibreOffice.git] / basebmp / source / bitmapdevice.cxx
blob04d4892ac05449a22cc78ecd77f3114277041415
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 <sal/log.hxx>
56 #include <osl/diagnose.h>
58 #include <basegfx/tools/tools.hxx>
59 #include <basegfx/tools/canvastools.hxx>
60 #include <basegfx/range/b2ibox.hxx>
61 #include <basegfx/range/b2irange.hxx>
62 #include <basegfx/range/b2drange.hxx>
63 #include <basegfx/polygon/b2dpolygon.hxx>
64 #include <basegfx/polygon/b2dpolygontools.hxx>
65 #include <basegfx/polygon/b2dpolypolygontools.hxx>
66 #include <basegfx/point/b2ipoint.hxx>
67 #include <basegfx/vector/b2ivector.hxx>
69 #include <vigra/iteratortraits.hxx>
70 #include <vigra/rgbvalue.hxx>
71 #include <vigra/copyimage.hxx>
72 #include <vigra/tuple.hxx>
75 namespace vigra
78 /// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
79 template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex >
80 inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex>
81 operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs,
82 RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs )
84 RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res(
85 lhs[0] ^ rhs[0],
86 lhs[1] ^ rhs[1],
87 lhs[2] ^ rhs[2]);
88 return res;
92 namespace basebmp
95 static const sal_uInt8 bitsPerPixel[] =
97 0, // NONE
98 1, // ONE_BIT_MSB_GREY
99 1, // ONE_BIT_LSB_GREY
100 1, // ONE_BIT_MSB_PAL
101 1, // ONE_BIT_LSB_PAL
102 4, // FOUR_BIT_MSB_GREY
103 4, // FOUR_BIT_LSB_GREY
104 4, // FOUR_BIT_MSB_PAL
105 4, // FOUR_BIT_LSB_PAL
106 8, // EIGHT_BIT_PAL
107 8, // EIGHT_BIT_GREY
108 16, // SIXTEEN_BIT_LSB_TC_MASK
109 16, // SIXTEEN_BIT_MSB_TC_MASK
110 24, // TWENTYFOUR_BIT_TC_MASK
111 32, // TWENTYFOUR_BIT_TC_MASK_BGRX
112 32, // THIRTYTWO_BIT_TC_MASK_BGRA
113 32, // THIRTYTWO_BIT_TC_MASK_ARGB
114 32, // THIRTYTWO_BIT_TC_MASK_ABGR
115 32, // THIRTYTWO_BIT_TC_MASK_RGBA
118 namespace
120 /** Create the type for an accessor that takes the (mask,bitmap)
121 input value generated from a JoinImageAccessorAdapter, and
122 pipe that through a mask functor.
124 @tpl DestAccessor
125 Destination bitmap accessor
127 @tpl JoinedAccessor
128 Input accessor, is expected to generate a std::pair as the
129 value type
131 @tpl MaskFunctorMode
132 Either FastMask or NoFastMask, depending on whether the mask
133 is guaranteed to contain only 0s and 1s.
135 template< class DestAccessor,
136 class JoinedAccessor,
137 bool polarity,
138 typename MaskFunctorMode > struct masked_input_splitting_accessor
140 typedef BinarySetterFunctionAccessorAdapter<
141 DestAccessor,
142 BinaryFunctorSplittingWrapper<
143 typename outputMaskFunctorSelector<
144 typename JoinedAccessor::value_type::first_type,
145 typename JoinedAccessor::value_type::second_type,
146 polarity,
147 MaskFunctorMode >::type > > type;
152 // Actual BitmapDevice implementation (templatized by accessor and iterator)
154 /** Implementation of the BitmapDevice interface
156 @tpl DestIterator
157 Iterator to access bitmap memory
159 @tpl RawAccessor
160 Raw accessor, to access pixel values directly
162 @tpl AccessorSelector
163 Accessor adapter selector, which, when applying the nested
164 template metafunction wrap_accessor to one of the raw bitmap
165 accessors, yields a member type named 'type', which is a
166 wrapped accessor that map color values.
168 @tpl Masks
169 Traits template, containing nested traits
170 clipmask_format_traits and alphamask_format_traits, which
171 determine what specialized formats are to be used for clip and
172 alpha masks. With those mask formats, clipping and alpha
173 blending is handled natively.
175 template< class DestIterator,
176 class RawAccessor,
177 class AccessorSelector,
178 class Masks > class BitmapRenderer :
179 public BitmapDevice
181 public:
182 typedef DestIterator dest_iterator_type;
183 typedef RawAccessor raw_accessor_type;
184 typedef AccessorSelector accessor_selector;
186 typedef typename Masks::clipmask_format_traits::iterator_type mask_iterator_type;
187 typedef typename Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type;
188 typedef typename Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type;
190 typedef typename Masks::alphamask_format_traits::iterator_type alphamask_iterator_type;
191 typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type;
192 typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type;
194 typedef typename AccessorSelector::template wrap_accessor<
195 raw_accessor_type >::type dest_accessor_type;
197 typedef AccessorTraits< dest_accessor_type > accessor_traits;
198 typedef CompositeIterator2D< dest_iterator_type,
199 mask_iterator_type > composite_iterator_type;
200 typedef CompositeIterator2D< vigra::Diff2D,
201 vigra::Diff2D > generic_composite_iterator_type;
203 typedef BitmapRenderer<mask_iterator_type,
204 mask_rawaccessor_type,
205 mask_accessorselector_type,
206 Masks> mask_bitmap_type;
207 typedef BitmapRenderer<alphamask_iterator_type,
208 alphamask_rawaccessor_type,
209 alphamask_accessorselector_type,
210 Masks> alphamask_bitmap_type;
214 typedef AccessorTraits< raw_accessor_type > raw_accessor_traits;
215 typedef typename uInt32Converter<
216 typename raw_accessor_type::value_type>::to to_uint32_functor;
220 typedef typename raw_accessor_traits::xor_accessor raw_xor_accessor_type;
221 typedef AccessorTraits<raw_xor_accessor_type> raw_xor_accessor_traits;
222 typedef typename accessor_selector::template wrap_accessor<
223 raw_xor_accessor_type >::type xor_accessor_type;
224 typedef AccessorTraits<xor_accessor_type> xor_accessor_traits;
228 typedef typename raw_accessor_traits::template masked_accessor<
229 mask_rawaccessor_type,
230 dest_iterator_type,
231 mask_iterator_type,
232 Masks::clipmask_polarity>::type raw_maskedaccessor_type;
233 typedef typename accessor_selector::template wrap_accessor<
234 raw_maskedaccessor_type >::type masked_accessor_type;
235 typedef typename AccessorTraits<
236 raw_maskedaccessor_type>::xor_accessor raw_maskedxor_accessor_type;
237 typedef typename accessor_selector::template wrap_accessor<
238 raw_maskedxor_accessor_type >::type masked_xoraccessor_type;
242 // ((iter,mask),mask) special case (e.g. for clipped
243 // drawMaskedColor())
244 typedef AccessorTraits< raw_maskedaccessor_type > raw_maskedaccessor_traits;
245 typedef typename raw_maskedaccessor_traits::template masked_accessor<
246 mask_rawaccessor_type,
247 composite_iterator_type,
248 mask_iterator_type,
249 Masks::clipmask_polarity>::type raw_maskedmask_accessor_type;
251 typedef CompositeIterator2D<
252 composite_iterator_type,
253 mask_iterator_type> composite_composite_mask_iterator_type;
257 typedef ConstantColorBlendSetterAccessorAdapter<
258 dest_accessor_type,
259 typename alphamask_rawaccessor_type::value_type,
260 Masks::alphamask_polarity> colorblend_accessor_type;
261 typedef AccessorTraits<colorblend_accessor_type> colorblend_accessor_traits;
262 typedef typename colorblend_accessor_traits::template masked_accessor<
263 mask_rawaccessor_type,
264 dest_iterator_type,
265 mask_iterator_type,
266 Masks::clipmask_polarity>::type masked_colorblend_accessor_type;
270 typedef ConstantColorBlendSetterAccessorAdapter<
271 dest_accessor_type,
272 Color,
273 Masks::alphamask_polarity> colorblend_generic_accessor_type;
274 typedef AccessorTraits<colorblend_generic_accessor_type> colorblend_generic_accessor_traits;
275 typedef typename colorblend_generic_accessor_traits::template masked_accessor<
276 mask_rawaccessor_type,
277 dest_iterator_type,
278 mask_iterator_type,
279 Masks::clipmask_polarity>::type masked_colorblend_generic_accessor_type;
283 typedef JoinImageAccessorAdapter< dest_accessor_type,
284 mask_rawaccessor_type > joined_image_accessor_type;
285 typedef JoinImageAccessorAdapter< GenericColorImageAccessor,
286 GenericColorImageAccessor > joined_generic_image_accessor_type;
290 dest_iterator_type maBegin;
291 typename accessor_traits::color_lookup maColorLookup;
292 IBitmapDeviceDamageTrackerSharedPtr mpDamage;
293 to_uint32_functor maToUInt32Converter;
294 dest_accessor_type maAccessor;
295 colorblend_accessor_type maColorBlendAccessor;
296 colorblend_generic_accessor_type maGenericColorBlendAccessor;
297 raw_accessor_type maRawAccessor;
298 xor_accessor_type maXorAccessor;
299 raw_xor_accessor_type maRawXorAccessor;
300 masked_accessor_type maMaskedAccessor;
301 masked_colorblend_accessor_type maMaskedColorBlendAccessor;
302 masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor;
303 masked_xoraccessor_type maMaskedXorAccessor;
304 raw_maskedaccessor_type maRawMaskedAccessor;
305 raw_maskedxor_accessor_type maRawMaskedXorAccessor;
306 raw_maskedmask_accessor_type maRawMaskedMaskAccessor;
311 BitmapRenderer( const basegfx::B2IBox& rBounds,
312 const basegfx::B2IVector& rBufferSize,
313 Format nScanlineFormat,
314 sal_Int32 nScanlineStride,
315 sal_uInt8* pFirstScanline,
316 dest_iterator_type begin,
317 raw_accessor_type rawAccessor,
318 dest_accessor_type accessor,
319 const RawMemorySharedArray& rMem,
320 const PaletteMemorySharedVector& rPalette,
321 const IBitmapDeviceDamageTrackerSharedPtr& rDamage ) :
322 BitmapDevice( rBounds, rBufferSize, nScanlineFormat,
323 nScanlineStride, pFirstScanline, rMem, rPalette ),
324 maBegin( begin ),
325 maColorLookup(),
326 mpDamage(rDamage),
327 maToUInt32Converter(),
328 maAccessor( accessor ),
329 maColorBlendAccessor( accessor ),
330 maGenericColorBlendAccessor( accessor ),
331 maRawAccessor( rawAccessor ),
332 maXorAccessor( accessor ),
333 maRawXorAccessor( rawAccessor ),
334 maMaskedAccessor( accessor ),
335 maMaskedColorBlendAccessor( maColorBlendAccessor ),
336 maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ),
337 maMaskedXorAccessor( accessor ),
338 maRawMaskedAccessor( rawAccessor ),
339 maRawMaskedXorAccessor( rawAccessor ),
340 maRawMaskedMaskAccessor( rawAccessor )
343 private:
345 void damaged( const basegfx::B2IBox& rDamageRect ) const
347 if( mpDamage )
348 mpDamage->damaged( rDamageRect );
351 void damagedPointSize( const basegfx::B2IPoint& rPoint,
352 const basegfx::B2IBox& rSize ) const
354 if( mpDamage ) {
355 basegfx::B2IPoint aLower( rPoint.getX() + rSize.getWidth(),
356 rPoint.getY() + rSize.getHeight() );
357 damaged( basegfx::B2IBox( rPoint, aLower ) );
361 void damagedPixel( const basegfx::B2IPoint& rDamagePoint ) const
363 if (!mpDamage)
364 return;
366 sal_Int32 nX(rDamagePoint.getX());
367 sal_Int32 nY(rDamagePoint.getY());
368 if (nX < SAL_MAX_INT32)
369 ++nX;
370 if (nY < SAL_MAX_INT32)
371 ++nY;
373 basegfx::B2IPoint aEnd( nX, nY );
374 damaged( basegfx::B2IBox( rDamagePoint, aEnd ) );
377 static boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp )
379 return boost::dynamic_pointer_cast< BitmapRenderer >( bmp );
382 virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const SAL_OVERRIDE
384 // TODO(P1): dynamic_cast usually called twice for
385 // compatible formats
386 return getCompatibleBitmap(bmp).get() != NULL;
389 boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
391 boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ));
393 if( !pMask )
394 return pMask;
396 if( pMask->getSize() != getSize() )
397 pMask.reset();
399 return pMask;
402 virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const SAL_OVERRIDE
404 // TODO(P1): dynamic_cast usually called twice for
405 // compatible formats
406 return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL;
409 static boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp )
411 return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp );
414 virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const SAL_OVERRIDE
416 // TODO(P1): dynamic_cast usually called twice for
417 // compatible formats
418 return getCompatibleAlphaMask( bmp ).get() != NULL;
421 virtual void clear_i( Color fillColor,
422 const basegfx::B2IBox& rBounds ) SAL_OVERRIDE
424 fillImage(destIterRange(maBegin,
425 maRawAccessor,
426 rBounds),
427 maColorLookup(
428 maAccessor,
429 fillColor) );
430 damaged( rBounds );
433 virtual void setPixel_i( const basegfx::B2IPoint& rPt,
434 Color pixelColor,
435 DrawMode drawMode ) SAL_OVERRIDE
437 const DestIterator pixel( maBegin +
438 vigra::Diff2D(rPt.getX(),
439 rPt.getY()) );
440 if( drawMode == DrawMode_XOR )
441 maXorAccessor.set( pixelColor,
442 pixel );
443 else
444 maAccessor.set( pixelColor,
445 pixel );
446 damagedPixel(rPt);
449 virtual void setPixel_i( const basegfx::B2IPoint& rPt,
450 Color pixelColor,
451 DrawMode drawMode,
452 const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
454 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
455 OSL_ASSERT( pMask );
457 const vigra::Diff2D offset(rPt.getX(),
458 rPt.getY());
460 const composite_iterator_type aIter(
461 maBegin + offset,
462 pMask->maBegin + offset );
464 if( drawMode == DrawMode_XOR )
465 maMaskedXorAccessor.set( pixelColor,
466 aIter );
467 else
468 maMaskedAccessor.set( pixelColor,
469 aIter );
470 damagedPixel(rPt);
473 virtual Color getPixel_i(const basegfx::B2IPoint& rPt ) SAL_OVERRIDE
475 const DestIterator pixel( maBegin +
476 vigra::Diff2D(rPt.getX(),
477 rPt.getY()) );
478 return maAccessor(pixel);
481 virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt ) SAL_OVERRIDE
483 const DestIterator pixel( maBegin +
484 vigra::Diff2D(rPt.getX(),
485 rPt.getY()) );
486 return maToUInt32Converter(maRawAccessor(pixel));
489 template< typename Iterator, typename Col, typename RawAcc >
490 void implRenderLine2( const basegfx::B2IPoint& rPt1,
491 const basegfx::B2IPoint& rPt2,
492 const basegfx::B2IBox& rBounds,
493 Col col,
494 const Iterator& begin,
495 const RawAcc& rawAcc )
497 renderClippedLine( rPt1,
498 rPt2,
499 rBounds,
500 col,
501 begin,
502 rawAcc );
504 if (!mpDamage)
505 return;
507 // TODO(P2): perhaps this needs pushing up the stack a bit
508 // to make more complex polygons more efficient ...
509 basegfx::B2IBox aBounds(rPt1, rPt2 );
511 const basegfx::B2IPoint& rEnd = aBounds.getMaximum();
513 sal_Int32 nX(rEnd.getX());
514 sal_Int32 nY(rEnd.getY());
515 if (nX < SAL_MAX_INT32)
516 ++nX;
517 if (nY < SAL_MAX_INT32)
518 ++nY;
520 basegfx::B2IBox aDamagedBox(aBounds.getMinimum(), basegfx::B2IPoint(nX, nY));
521 damaged(aDamagedBox);
524 template< typename Iterator, typename Accessor, typename RawAcc >
525 void implRenderLine( const basegfx::B2IPoint& rPt1,
526 const basegfx::B2IPoint& rPt2,
527 const basegfx::B2IBox& rBounds,
528 Color col,
529 const Iterator& begin,
530 const Accessor& acc,
531 const RawAcc& rawAcc )
533 implRenderLine2( rPt1,rPt2,rBounds,
534 maColorLookup( acc,
535 col ),
536 begin,
537 rawAcc );
540 template< typename Iterator, typename RawAcc, typename XorAcc >
541 void implDrawLine( const basegfx::B2IPoint& rPt1,
542 const basegfx::B2IPoint& rPt2,
543 const basegfx::B2IBox& rBounds,
544 Color col,
545 const Iterator& begin,
546 const RawAcc& rawAcc,
547 const XorAcc& xorAcc,
548 DrawMode drawMode )
550 if( drawMode == DrawMode_XOR )
551 implRenderLine( rPt1, rPt2, rBounds, col,
552 begin, maAccessor, xorAcc );
553 else
554 implRenderLine( rPt1, rPt2, rBounds, col,
555 begin, maAccessor, rawAcc );
558 virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
559 const basegfx::B2IPoint& rPt2,
560 const basegfx::B2IBox& rBounds,
561 Color lineColor,
562 DrawMode drawMode ) SAL_OVERRIDE
564 implDrawLine(rPt1,rPt2,rBounds,lineColor,
565 maBegin,
566 maRawAccessor,maRawXorAccessor,drawMode);
569 composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const
571 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
572 OSL_ASSERT( pMask );
574 return composite_iterator_type( maBegin,
575 pMask->maBegin );
578 virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
579 const basegfx::B2IPoint& rPt2,
580 const basegfx::B2IBox& rBounds,
581 Color lineColor,
582 DrawMode drawMode,
583 const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
585 implDrawLine(rPt1,rPt2,rBounds,lineColor,
586 getMaskedIter(rClip),
587 maRawMaskedAccessor,
588 maRawMaskedXorAccessor,drawMode);
591 template< typename Iterator, typename RawAcc >
592 void implDrawPolygon( const basegfx::B2DPolygon& rPoly,
593 const basegfx::B2IBox& rBounds,
594 Color col,
595 const Iterator& begin,
596 const RawAcc& acc )
598 basegfx::B2DPolygon aPoly( rPoly );
599 if( rPoly.areControlPointsUsed() )
600 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
602 const typename dest_iterator_type::value_type colorIndex( maColorLookup(
603 maAccessor,
604 col));
605 const sal_uInt32 nVertices( aPoly.count() );
606 for( sal_uInt32 i=1; i<nVertices; ++i )
607 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)),
608 basegfx::fround(aPoly.getB2DPoint(i)),
609 rBounds,
610 colorIndex,
611 begin,
612 acc );
614 if( nVertices > 1 && aPoly.isClosed() )
615 implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)),
616 basegfx::fround(aPoly.getB2DPoint(0)),
617 rBounds,
618 colorIndex,
619 begin,
620 acc );
623 virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
624 const basegfx::B2IBox& rBounds,
625 Color lineColor,
626 DrawMode drawMode ) SAL_OVERRIDE
628 if( drawMode == DrawMode_XOR )
629 implDrawPolygon( rPoly, rBounds, lineColor,
630 maBegin,
631 maRawXorAccessor );
632 else
633 implDrawPolygon( rPoly, rBounds, lineColor,
634 maBegin,
635 maRawAccessor );
638 virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
639 const basegfx::B2IBox& rBounds,
640 Color lineColor,
641 DrawMode drawMode,
642 const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
644 if( drawMode == DrawMode_XOR )
645 implDrawPolygon( rPoly, rBounds, lineColor,
646 getMaskedIter(rClip),
647 maRawMaskedXorAccessor );
648 else
649 implDrawPolygon( rPoly, rBounds, lineColor,
650 getMaskedIter(rClip),
651 maRawMaskedAccessor );
654 template< typename Iterator, typename RawAcc >
655 void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
656 Color col,
657 const Iterator& begin,
658 const RawAcc& acc,
659 const basegfx::B2IBox& rBounds )
661 basegfx::B2DPolyPolygon aPoly( rPoly );
662 if( rPoly.areControlPointsUsed() )
663 aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
665 renderClippedPolyPolygon( begin,
666 acc,
667 maColorLookup( maAccessor,
668 col),
669 rBounds,
670 aPoly,
671 basegfx::FillRule_EVEN_ODD );
673 if( mpDamage )
675 basegfx::B2DRange const aPolyBounds( basegfx::tools::getRange(aPoly) );
676 damaged( basegfx::unotools::b2ISurroundingBoxFromB2DRange( aPolyBounds ) );
680 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
681 Color fillColor,
682 DrawMode drawMode,
683 const basegfx::B2IBox& rBounds ) SAL_OVERRIDE
685 if( drawMode == DrawMode_XOR )
686 implFillPolyPolygon( rPoly, fillColor,
687 maBegin,
688 maRawXorAccessor,
689 rBounds );
690 else
691 implFillPolyPolygon( rPoly, fillColor,
692 maBegin,
693 maRawAccessor,
694 rBounds );
697 virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
698 Color fillColor,
699 DrawMode drawMode,
700 const basegfx::B2IBox& rBounds,
701 const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
703 if( drawMode == DrawMode_XOR )
704 implFillPolyPolygon( rPoly, fillColor,
705 getMaskedIter(rClip),
706 maRawMaskedXorAccessor,
707 rBounds );
708 else
709 implFillPolyPolygon( rPoly, fillColor,
710 getMaskedIter(rClip),
711 maRawMaskedAccessor,
712 rBounds );
715 template< typename Iterator, typename RawAcc >
716 void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
717 const basegfx::B2IBox& rSrcRect,
718 const basegfx::B2IBox& rDstRect,
719 const Iterator& begin,
720 const RawAcc& acc)
722 boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
723 OSL_ASSERT( pSrcBmp );
725 scaleImage(
726 srcIterRange(pSrcBmp->maBegin,
727 pSrcBmp->maRawAccessor,
728 rSrcRect),
729 destIterRange(begin,
730 acc,
731 rDstRect),
732 isSharedBuffer(rSrcBitmap) );
733 damaged( rDstRect );
736 template< typename Iterator, typename Acc >
737 void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
738 const basegfx::B2IBox& rSrcRect,
739 const basegfx::B2IBox& rDstRect,
740 const Iterator& begin,
741 const Acc& acc)
743 GenericColorImageAccessor aSrcAcc( rSrcBitmap );
745 scaleImage(
746 srcIterRange(vigra::Diff2D(),
747 aSrcAcc,
748 rSrcRect),
749 destIterRange(begin,
750 acc,
751 rDstRect));
752 damaged( rDstRect );
755 void implDrawBitmapDirect(const BitmapDeviceSharedPtr& rSrcBitmap,
756 const basegfx::B2IBox& rSrcRect,
757 const basegfx::B2IBox& rDstRect)
759 sal_Int32 nSrcX = rSrcRect.getMinX();
760 sal_Int32 nSrcY = rSrcRect.getMinY();
761 sal_Int32 nSrcWidth = rSrcRect.getWidth();
762 sal_Int32 nSrcHeight = rSrcRect.getHeight();
763 sal_Int32 nDestX = rDstRect.getMinX();
764 sal_Int32 nDestY = rDstRect.getMinY();
766 char* dstBuf = reinterpret_cast<char*>(getBuffer().get());
767 char* srcBuf = reinterpret_cast<char*>(rSrcBitmap->getBuffer().get());
768 sal_Int32 dstStride = getScanlineStride();
769 sal_Int32 srcStride = rSrcBitmap->getScanlineStride();
770 sal_Int32 bytesPerPixel = (bitsPerPixel[getScanlineFormat()] + 7) >> 3; // round up to bytes
771 bool dstTopDown = isTopDown();
772 bool srcTopDown = rSrcBitmap->isTopDown();
774 if (dstBuf == srcBuf && nSrcY < nDestY) // reverse copy order to avoid overlapping
776 nSrcY = getBufferSize().getY() - nSrcY - nSrcHeight;
777 nDestY = getBufferSize().getY() - nDestY - nSrcHeight;
778 srcTopDown = !srcTopDown;
779 dstTopDown = !dstTopDown;
782 if (!dstTopDown)
784 dstBuf += dstStride * (getBufferSize().getY() - 1);
785 dstStride = -dstStride;
788 if (!srcTopDown)
790 srcBuf += srcStride * (rSrcBitmap->getBufferSize().getY() - 1);
791 srcStride = -srcStride;
794 char* dstline = dstBuf + dstStride * nDestY + nDestX * bytesPerPixel;
795 char* srcline = srcBuf + srcStride * nSrcY + nSrcX * bytesPerPixel;
796 sal_Int32 lineBytes = nSrcWidth * bytesPerPixel;
798 for(; 0 < nSrcHeight; nSrcHeight--)
800 memmove(dstline, srcline, lineBytes);
801 dstline += dstStride;
802 srcline += srcStride;
806 virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
807 const basegfx::B2IBox& rSrcRect,
808 const basegfx::B2IBox& rDstRect,
809 DrawMode drawMode ) SAL_OVERRIDE
811 if( isCompatibleBitmap( rSrcBitmap ) )
813 if( drawMode == DrawMode_XOR )
814 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
815 maBegin,
816 maRawXorAccessor);
817 else if (bitsPerPixel[getScanlineFormat()] >= 8
818 && rSrcRect.getWidth() == rDstRect.getWidth() && rSrcRect.getHeight() == rDstRect.getHeight()
819 && rSrcBitmap->getScanlineFormat() == getScanlineFormat())
820 implDrawBitmapDirect(rSrcBitmap, rSrcRect, rDstRect);
821 else
822 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
823 maBegin,
824 maRawAccessor);
826 else
828 if( drawMode == DrawMode_XOR )
829 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
830 maBegin,
831 maXorAccessor);
832 else
833 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
834 maBegin,
835 maAccessor);
837 damaged( rDstRect );
840 virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
841 const basegfx::B2IBox& rSrcRect,
842 const basegfx::B2IBox& rDstRect,
843 DrawMode drawMode,
844 const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
846 if( isCompatibleBitmap( rSrcBitmap ) )
848 if( drawMode == DrawMode_XOR )
849 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
850 getMaskedIter(rClip),
851 maRawMaskedXorAccessor);
852 else
853 implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
854 getMaskedIter(rClip),
855 maRawMaskedAccessor);
857 else
859 if( drawMode == DrawMode_XOR )
860 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
861 getMaskedIter(rClip),
862 maMaskedXorAccessor);
863 else
864 implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
865 getMaskedIter(rClip),
866 maMaskedAccessor);
868 damaged( rDstRect );
871 virtual void drawMaskedColor_i(Color aSrcColor,
872 const BitmapDeviceSharedPtr& rAlphaMask,
873 const basegfx::B2IBox& rSrcRect,
874 const basegfx::B2IPoint& rDstPoint ) SAL_OVERRIDE
876 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
877 boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
879 if( pAlpha )
881 maColorBlendAccessor.setColor( aSrcColor );
883 vigra::copyImage( srcIterRange(pAlpha->maBegin,
884 pAlpha->maRawAccessor,
885 rSrcRect),
886 destIter(maBegin,
887 maColorBlendAccessor,
888 rDstPoint) );
890 else if( pMask )
892 const composite_iterator_type aBegin(
893 maBegin + vigra::Diff2D(rDstPoint.getX(),
894 rDstPoint.getY()),
895 pMask->maBegin + topLeft(rSrcRect) );
897 fillImage(aBegin,
898 aBegin + vigra::Diff2D(rSrcRect.getWidth(),
899 rSrcRect.getHeight()),
900 maRawMaskedAccessor,
901 maColorLookup(
902 maAccessor,
903 aSrcColor) );
905 else
907 GenericColorImageAccessor aSrcAcc( rAlphaMask );
908 maGenericColorBlendAccessor.setColor( aSrcColor );
910 vigra::copyImage( srcIterRange(vigra::Diff2D(),
911 aSrcAcc,
912 rSrcRect),
913 destIter(maBegin,
914 maGenericColorBlendAccessor,
915 rDstPoint) );
917 damagedPointSize( rDstPoint, rSrcRect );
920 virtual void drawMaskedColor_i(Color aSrcColor,
921 const BitmapDeviceSharedPtr& rAlphaMask,
922 const basegfx::B2IBox& rSrcRect,
923 const basegfx::B2IPoint& rDstPoint,
924 const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
926 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
927 boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
929 if( pAlpha )
931 const composite_iterator_type aBegin( getMaskedIter(rClip) );
932 maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
933 aSrcColor );
935 vigra::copyImage( srcIterRange(pAlpha->maBegin,
936 pAlpha->maRawAccessor,
937 rSrcRect),
938 destIter(aBegin,
939 maMaskedColorBlendAccessor,
940 rDstPoint) );
942 else if( pMask )
944 boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) );
945 OSL_ASSERT( pClipMask );
947 // setup a ((iter,mask),clipMask) composite composite
948 // iterator, to pass both masks (clip and alpha mask)
949 // to the algorithm
950 const composite_composite_mask_iterator_type aBegin(
951 composite_iterator_type(
952 maBegin + vigra::Diff2D(rDstPoint.getX(),
953 rDstPoint.getY()),
954 pMask->maBegin + topLeft(rSrcRect)),
955 pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(),
956 rDstPoint.getY()) );
958 fillImage(aBegin,
959 aBegin + vigra::Diff2D(rSrcRect.getWidth(),
960 rSrcRect.getHeight()),
961 maRawMaskedMaskAccessor,
962 maColorLookup(
963 maAccessor,
964 aSrcColor) );
966 else
968 GenericColorImageAccessor aSrcAcc( rAlphaMask );
969 const composite_iterator_type aBegin( getMaskedIter(rClip) );
970 maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
971 aSrcColor );
973 vigra::copyImage( srcIterRange(vigra::Diff2D(),
974 aSrcAcc,
975 rSrcRect),
976 destIter(aBegin,
977 maGenericMaskedColorBlendAccessor,
978 rDstPoint) );
980 damagedPointSize( rDstPoint, rSrcRect );
983 template< typename Iterator, typename Acc >
984 void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
985 const BitmapDeviceSharedPtr& rMask,
986 const basegfx::B2IBox& rSrcRect,
987 const basegfx::B2IBox& rDstRect,
988 const Iterator& begin,
989 const Acc& acc)
991 boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
992 boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) );
993 OSL_ASSERT( pMask && pSrcBmp );
995 scaleImage(
996 srcIterRange(composite_iterator_type(
997 pSrcBmp->maBegin,
998 pMask->maBegin),
999 joined_image_accessor_type(
1000 pSrcBmp->maAccessor,
1001 pMask->maRawAccessor),
1002 rSrcRect),
1003 destIterRange(begin,
1004 typename masked_input_splitting_accessor<
1005 Acc,
1006 joined_image_accessor_type,
1007 Masks::clipmask_polarity,
1008 FastMask >::type(acc),
1009 rDstRect),
1010 isSharedBuffer(rSrcBitmap));
1011 damaged( rDstRect );
1014 template< typename Iterator, typename Acc >
1015 void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
1016 const BitmapDeviceSharedPtr& rMask,
1017 const basegfx::B2IBox& rSrcRect,
1018 const basegfx::B2IBox& rDstRect,
1019 const Iterator& begin,
1020 const Acc& acc)
1022 GenericColorImageAccessor aSrcAcc( rSrcBitmap );
1023 GenericColorImageAccessor aMaskAcc( rMask );
1025 const vigra::Diff2D aTopLeft(rSrcRect.getMinX(),
1026 rSrcRect.getMinY());
1027 const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(),
1028 rSrcRect.getMaxY());
1029 scaleImage(
1030 vigra::make_triple(
1031 generic_composite_iterator_type(
1032 aTopLeft,aTopLeft),
1033 generic_composite_iterator_type(
1034 aBottomRight,aBottomRight),
1035 joined_generic_image_accessor_type(
1036 aSrcAcc,
1037 aMaskAcc)),
1038 destIterRange(begin,
1039 typename masked_input_splitting_accessor<
1040 Acc,
1041 joined_generic_image_accessor_type,
1042 Masks::clipmask_polarity,
1043 NoFastMask >::type(acc),
1044 rDstRect));
1045 damaged( rDstRect );
1048 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
1049 const BitmapDeviceSharedPtr& rMask,
1050 const basegfx::B2IBox& rSrcRect,
1051 const basegfx::B2IBox& rDstRect,
1052 DrawMode drawMode ) SAL_OVERRIDE
1054 if( isCompatibleClipMask(rMask) &&
1055 isCompatibleBitmap(rSrcBitmap) )
1057 if( drawMode == DrawMode_XOR )
1058 implDrawMaskedBitmap(rSrcBitmap, rMask,
1059 rSrcRect, rDstRect,
1060 maBegin,
1061 maXorAccessor);
1062 else
1063 implDrawMaskedBitmap(rSrcBitmap, rMask,
1064 rSrcRect, rDstRect,
1065 maBegin,
1066 maAccessor);
1068 else
1070 if( drawMode == DrawMode_XOR )
1071 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1072 rSrcRect, rDstRect,
1073 maBegin,
1074 maXorAccessor);
1075 else
1076 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1077 rSrcRect, rDstRect,
1078 maBegin,
1079 maAccessor);
1081 damaged( rDstRect );
1084 virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
1085 const BitmapDeviceSharedPtr& rMask,
1086 const basegfx::B2IBox& rSrcRect,
1087 const basegfx::B2IBox& rDstRect,
1088 DrawMode drawMode,
1089 const BitmapDeviceSharedPtr& rClip ) SAL_OVERRIDE
1091 if( isCompatibleClipMask(rMask) &&
1092 isCompatibleBitmap(rSrcBitmap) )
1094 if( drawMode == DrawMode_XOR )
1095 implDrawMaskedBitmap(rSrcBitmap, rMask,
1096 rSrcRect, rDstRect,
1097 getMaskedIter(rClip),
1098 maMaskedXorAccessor);
1099 else
1100 implDrawMaskedBitmap(rSrcBitmap, rMask,
1101 rSrcRect, rDstRect,
1102 getMaskedIter(rClip),
1103 maMaskedAccessor);
1105 else
1107 if( drawMode == DrawMode_XOR )
1108 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1109 rSrcRect, rDstRect,
1110 getMaskedIter(rClip),
1111 maMaskedXorAccessor);
1112 else
1113 implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
1114 rSrcRect, rDstRect,
1115 getMaskedIter(rClip),
1116 maMaskedAccessor);
1118 damaged( rDstRect );
1121 IBitmapDeviceDamageTrackerSharedPtr getDamageTracker_i() const SAL_OVERRIDE
1123 return mpDamage;
1125 void setDamageTracker_i( const IBitmapDeviceDamageTrackerSharedPtr& rDamage ) SAL_OVERRIDE
1127 mpDamage = rDamage;
1130 } // namespace
1132 struct ImplBitmapDevice
1134 /** Bitmap memory plus deleter.
1136 Always points to the start of the mem
1138 RawMemorySharedArray mpMem;
1140 /// Palette memory plus deleter (might be NULL)
1141 PaletteMemorySharedVector mpPalette;
1143 /** Bounds of the device.
1145 maBounds.getWidth()/getHeight() yield the true size of the
1146 device (i.e. the rectangle given by maBounds covers the device
1147 area under the including-the-bottommost-and-rightmost-pixels
1148 fill rule)
1150 basegfx::B2IBox maBounds;
1152 //// Size of the actual frame buffer
1153 basegfx::B2IVector maBufferSize;
1155 /// Scanline format, as provided at the constructor
1156 Format mnScanlineFormat;
1158 /// Scanline stride. Negative for bottom-to-top formats
1159 sal_Int32 mnScanlineStride;
1161 /// raw ptr to 0th scanline. used for cloning a generic renderer
1162 sal_uInt8* mpFirstScanline;
1164 /** (Optional) device sharing the same memory, and used for input
1165 clip masks/alpha masks/bitmaps that don't match our exact
1166 bitmap format.
1168 This is to avoid the combinatorical explosion when dealing
1169 with n bitmap formats, which could be combined with n clip
1170 masks, alpha masks and bitmap masks (yielding a total of n^4
1171 combinations). Since each BitmapRenderer is specialized for
1172 one specific combination of said formats, a lot of duplicate
1173 code would be generated, most of which probably never
1174 used. Therefore, only the most common combinations are
1175 specialized templates, the remainder gets handled by this
1176 generic renderer (via runtime polymorphism).
1178 BitmapDeviceSharedPtr mpGenericRenderer;
1182 BitmapDevice::BitmapDevice( const basegfx::B2IBox& rBounds,
1183 const basegfx::B2IVector& rBufferSize,
1184 Format nScanlineFormat,
1185 sal_Int32 nScanlineStride,
1186 sal_uInt8* pFirstScanline,
1187 const RawMemorySharedArray& rMem,
1188 const PaletteMemorySharedVector& rPalette ) :
1189 mpImpl( new ImplBitmapDevice )
1191 mpImpl->mpMem = rMem;
1192 mpImpl->mpPalette = rPalette;
1193 mpImpl->maBounds = rBounds;
1194 mpImpl->maBufferSize = rBufferSize;
1195 mpImpl->mnScanlineFormat = nScanlineFormat;
1196 mpImpl->mnScanlineStride = nScanlineStride;
1197 mpImpl->mpFirstScanline = pFirstScanline;
1200 BitmapDevice::~BitmapDevice()
1202 // outline, because of internal ImplBitmapDevice
1203 SAL_INFO( "basebmp.bitmapdevice", "~BitmapDevice(" << this << ")" );
1206 basegfx::B2IVector BitmapDevice::getSize() const
1208 return basegfx::B2IVector(
1209 mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(),
1210 mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() );
1213 bool BitmapDevice::isTopDown() const
1215 return mpImpl->mnScanlineStride >= 0;
1218 basegfx::B2IVector BitmapDevice::getBufferSize() const
1220 return mpImpl->maBufferSize;
1223 Format BitmapDevice::getScanlineFormat() const
1225 return mpImpl->mnScanlineFormat;
1228 sal_Int32 BitmapDevice::getScanlineStride() const
1230 return mpImpl->mnScanlineStride < 0 ?
1231 -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride;
1234 RawMemorySharedArray BitmapDevice::getBuffer() const
1236 return mpImpl->mpMem;
1239 IBitmapDeviceDamageTrackerSharedPtr BitmapDevice::getDamageTracker() const
1241 return getDamageTracker_i();
1244 void BitmapDevice::setDamageTracker( const IBitmapDeviceDamageTrackerSharedPtr& rDamage )
1246 setDamageTracker_i(rDamage);
1249 PaletteMemorySharedVector BitmapDevice::getPalette() const
1251 return mpImpl->mpPalette;
1254 bool BitmapDevice::isSharedBuffer( const BitmapDeviceSharedPtr& rOther ) const
1256 return rOther.get()->getBuffer().get() == getBuffer().get();
1259 void BitmapDevice::clear( Color fillColor )
1261 clear_i( fillColor, mpImpl->maBounds );
1264 void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1265 Color lineColor,
1266 DrawMode drawMode )
1268 if( mpImpl->maBounds.isInside(rPt) )
1269 setPixel_i(rPt,lineColor,drawMode);
1272 void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
1273 Color lineColor,
1274 DrawMode drawMode,
1275 const BitmapDeviceSharedPtr& rClip )
1277 if( !rClip )
1279 setPixel(rPt,lineColor,drawMode);
1280 return;
1283 if( mpImpl->maBounds.isInside(rPt) )
1285 if( isCompatibleClipMask( rClip ) )
1286 setPixel_i(rPt,lineColor,drawMode,rClip);
1287 else
1288 getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip );
1292 Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt )
1294 if( mpImpl->maBounds.isInside(rPt) )
1295 return getPixel_i(rPt);
1297 return Color();
1300 sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
1302 if( mpImpl->maBounds.isInside(rPt) )
1303 return getPixelData_i(rPt);
1305 return 0;
1308 void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1309 const basegfx::B2IPoint& rPt2,
1310 Color lineColor,
1311 DrawMode drawMode )
1313 drawLine_i( rPt1,
1314 rPt2,
1315 mpImpl->maBounds,
1316 lineColor,
1317 drawMode );
1320 void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
1321 const basegfx::B2IPoint& rPt2,
1322 Color lineColor,
1323 DrawMode drawMode,
1324 const BitmapDeviceSharedPtr& rClip )
1326 if( !rClip )
1328 drawLine(rPt1,rPt2,lineColor,drawMode);
1329 return;
1332 if( isCompatibleClipMask( rClip ) )
1333 drawLine_i( rPt1,
1334 rPt2,
1335 mpImpl->maBounds,
1336 lineColor,
1337 drawMode,
1338 rClip );
1339 else
1340 getGenericRenderer()->drawLine( rPt1, rPt2, lineColor,
1341 drawMode, rClip );
1344 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1345 Color lineColor,
1346 DrawMode drawMode )
1348 const sal_uInt32 numVertices( rPoly.count() );
1349 if( numVertices )
1350 drawPolygon_i( rPoly,
1351 mpImpl->maBounds,
1352 lineColor, drawMode );
1355 void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
1356 Color lineColor,
1357 DrawMode drawMode,
1358 const BitmapDeviceSharedPtr& rClip )
1360 if( !rClip )
1362 drawPolygon(rPoly,lineColor,drawMode);
1363 return;
1366 const sal_uInt32 numVertices( rPoly.count() );
1367 if( numVertices )
1369 if( isCompatibleClipMask( rClip ) )
1370 drawPolygon_i( rPoly,
1371 mpImpl->maBounds,
1372 lineColor, drawMode, rClip );
1373 else
1374 getGenericRenderer()->drawPolygon( rPoly, lineColor,
1375 drawMode, rClip );
1379 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1380 Color fillColor,
1381 DrawMode drawMode )
1383 fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
1386 void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
1387 Color fillColor,
1388 DrawMode drawMode,
1389 const BitmapDeviceSharedPtr& rClip )
1391 if( !rClip )
1393 fillPolyPolygon(rPoly,fillColor,drawMode);
1394 return;
1397 if( isCompatibleClipMask( rClip ) )
1398 fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
1399 else
1400 getGenericRenderer()->fillPolyPolygon( rPoly, fillColor,
1401 drawMode, rClip );
1405 namespace
1407 void assertImagePoint( const basegfx::B2IPoint& rPt,
1408 const basegfx::B2IBox& rPermittedRange )
1410 (void)rPt; (void)rPermittedRange;
1411 OSL_ASSERT( rPermittedRange.isInside(rPt) );
1414 void assertImageRange( const basegfx::B2IBox& rRange,
1415 const basegfx::B2IBox& rPermittedRange )
1417 #if OSL_DEBUG_LEVEL > 0
1418 basegfx::B2IBox aRange( rRange );
1419 aRange.intersect( rPermittedRange );
1421 OSL_ASSERT( aRange == rRange );
1422 #else
1423 (void)rRange; (void)rPermittedRange;
1424 #endif
1427 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1428 // to basegfx, and use here!
1429 bool clipAreaImpl( ::basegfx::B2IBox& io_rSourceArea,
1430 ::basegfx::B2IPoint& io_rDestPoint,
1431 const ::basegfx::B2IBox& rSourceBounds,
1432 const ::basegfx::B2IBox& rDestBounds )
1434 const ::basegfx::B2IPoint aSourceTopLeft(
1435 io_rSourceArea.getMinimum() );
1437 ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1439 // clip source area (which must be inside rSourceBounds)
1440 aLocalSourceArea.intersect( rSourceBounds );
1442 if( aLocalSourceArea.isEmpty() )
1443 return false;
1445 // calc relative new source area points (relative to orig
1446 // source area)
1447 const ::basegfx::B2IVector aUpperLeftOffset(
1448 aLocalSourceArea.getMinimum()-aSourceTopLeft );
1449 const ::basegfx::B2IVector aLowerRightOffset(
1450 aLocalSourceArea.getMaximum()-aSourceTopLeft );
1452 ::basegfx::B2IBox aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
1453 io_rDestPoint + aLowerRightOffset );
1455 // clip dest area (which must be inside rDestBounds)
1456 aLocalDestArea.intersect( rDestBounds );
1458 if( aLocalDestArea.isEmpty() )
1459 return false;
1461 // calc relative new dest area points (relative to orig
1462 // source area)
1463 const ::basegfx::B2IVector aDestUpperLeftOffset(
1464 aLocalDestArea.getMinimum()-io_rDestPoint );
1465 const ::basegfx::B2IVector aDestLowerRightOffset(
1466 aLocalDestArea.getMaximum()-io_rDestPoint );
1468 io_rSourceArea = ::basegfx::B2IBox( aSourceTopLeft + aDestUpperLeftOffset,
1469 aSourceTopLeft + aDestLowerRightOffset );
1470 io_rDestPoint = aLocalDestArea.getMinimum();
1472 return true;
1475 // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
1476 // to basegfx, and use here!
1477 bool clipAreaImpl( ::basegfx::B2IBox& io_rDestArea,
1478 ::basegfx::B2IBox& io_rSourceArea,
1479 const ::basegfx::B2IBox& rDestBounds,
1480 const ::basegfx::B2IBox& rSourceBounds )
1482 // extract inherent scale
1483 double fWidth = io_rSourceArea.getWidth();
1484 if (fWidth == 0.0)
1485 return false;
1487 double fHeight = io_rSourceArea.getHeight();
1488 if (fHeight == 0.0)
1489 return false;
1491 const double nScaleX( io_rDestArea.getWidth() / fWidth );
1492 const double nScaleY( io_rDestArea.getHeight() / fHeight );
1494 // extract range origins
1495 const basegfx::B2IPoint aDestTopLeft(
1496 io_rDestArea.getMinimum() );
1497 const ::basegfx::B2IPoint aSourceTopLeft(
1498 io_rSourceArea.getMinimum() );
1500 ::basegfx::B2IBox aLocalSourceArea( io_rSourceArea );
1502 // clip source area (which must be inside rSourceBounds)
1503 aLocalSourceArea.intersect( rSourceBounds );
1505 if( aLocalSourceArea.isEmpty() )
1506 return false;
1508 // calc relative new source area points (relative to orig
1509 // source area)
1510 const ::basegfx::B2IVector aUpperLeftOffset(
1511 aLocalSourceArea.getMinimum()-aSourceTopLeft );
1512 const ::basegfx::B2IVector aLowerRightOffset(
1513 aLocalSourceArea.getMaximum()-aSourceTopLeft );
1515 ::basegfx::B2IBox aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
1516 basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
1517 basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
1518 basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
1520 // clip dest area (which must be inside rDestBounds)
1521 aLocalDestArea.intersect( rDestBounds );
1523 if( aLocalDestArea.isEmpty() )
1524 return false;
1526 // calc relative new dest area points (relative to orig
1527 // source area)
1528 const ::basegfx::B2IVector aDestUpperLeftOffset(
1529 aLocalDestArea.getMinimum()-aDestTopLeft );
1530 const ::basegfx::B2IVector aDestLowerRightOffset(
1531 aLocalDestArea.getMaximum()-aDestTopLeft );
1533 io_rSourceArea = ::basegfx::B2IBox( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
1534 basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
1535 basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
1536 basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
1537 io_rDestArea = aLocalDestArea;
1539 // final source area clip (chopping round-offs)
1540 io_rSourceArea.intersect( rSourceBounds );
1542 if( io_rSourceArea.isEmpty() )
1543 return false;
1546 return true;
1550 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1551 const basegfx::B2IBox& rSrcRect,
1552 const basegfx::B2IBox& rDstRect,
1553 DrawMode drawMode )
1555 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1556 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1557 basegfx::B2IBox aSrcRange( rSrcRect );
1558 basegfx::B2IBox aDestRange( rDstRect );
1560 if( clipAreaImpl( aDestRange,
1561 aSrcRange,
1562 mpImpl->maBounds,
1563 aSrcBounds ))
1565 assertImageRange(aDestRange,mpImpl->maBounds);
1566 assertImageRange(aSrcRange,aSrcBounds);
1568 drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode );
1572 void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1573 const basegfx::B2IBox& rSrcRect,
1574 const basegfx::B2IBox& rDstRect,
1575 DrawMode drawMode,
1576 const BitmapDeviceSharedPtr& rClip )
1578 if( !rClip )
1580 drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
1581 return;
1584 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1585 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1586 basegfx::B2IBox aSrcRange( rSrcRect );
1587 basegfx::B2IBox aDestRange( rDstRect );
1589 if( clipAreaImpl( aDestRange,
1590 aSrcRange,
1591 mpImpl->maBounds,
1592 aSrcBounds ))
1594 assertImageRange(aDestRange,mpImpl->maBounds);
1595 assertImageRange(aSrcRange,aSrcBounds);
1597 if( isCompatibleClipMask( rClip ) )
1599 drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip );
1601 else
1603 getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect,
1604 rDstRect, drawMode, rClip );
1609 void BitmapDevice::drawMaskedColor( Color aSrcColor,
1610 const BitmapDeviceSharedPtr& rAlphaMask,
1611 const basegfx::B2IBox& rSrcRect,
1612 const basegfx::B2IPoint& rDstPoint )
1614 const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1615 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1616 basegfx::B2IBox aSrcRange( rSrcRect );
1617 basegfx::B2IPoint aDestPoint( rDstPoint );
1619 if( clipAreaImpl( aSrcRange,
1620 aDestPoint,
1621 aSrcBounds,
1622 mpImpl->maBounds ))
1624 assertImagePoint(aDestPoint,mpImpl->maBounds);
1625 assertImageRange(aSrcRange,aSrcBounds);
1627 if( isSharedBuffer(rAlphaMask) )
1629 // src == dest, copy rAlphaMask beforehand
1632 const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1633 aSrcRange.getHeight() );
1634 BitmapDeviceSharedPtr pAlphaCopy(
1635 cloneBitmapDevice( aSize,
1636 shared_from_this()) );
1637 const basegfx::B2IBox aAlphaRange( basegfx::B2ITuple(),
1638 aSize );
1639 pAlphaCopy->drawBitmap(rAlphaMask,
1640 aSrcRange,
1641 aAlphaRange,
1642 DrawMode_PAINT);
1643 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint );
1645 else
1647 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint );
1652 void BitmapDevice::drawMaskedColor( Color aSrcColor,
1653 const BitmapDeviceSharedPtr& rAlphaMask,
1654 const basegfx::B2IBox& rSrcRect,
1655 const basegfx::B2IPoint& rDstPoint,
1656 const BitmapDeviceSharedPtr& rClip )
1658 if( !rClip )
1660 drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
1661 return;
1664 const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
1665 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1666 basegfx::B2IBox aSrcRange( rSrcRect );
1667 basegfx::B2IPoint aDestPoint( rDstPoint );
1669 if( clipAreaImpl( aSrcRange,
1670 aDestPoint,
1671 aSrcBounds,
1672 mpImpl->maBounds ))
1674 assertImagePoint(aDestPoint,mpImpl->maBounds);
1675 assertImageRange(aSrcRange,aSrcBounds);
1677 if( isCompatibleClipMask( rClip ) )
1679 if( isSharedBuffer(rAlphaMask) )
1681 // src == dest, copy rAlphaMask beforehand
1684 const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
1685 aSrcRange.getHeight() );
1686 BitmapDeviceSharedPtr pAlphaCopy(
1687 cloneBitmapDevice( aSize,
1688 shared_from_this()) );
1689 const basegfx::B2IBox aAlphaRange( basegfx::B2ITuple(),
1690 aSize );
1691 pAlphaCopy->drawBitmap(rAlphaMask,
1692 aSrcRange,
1693 aAlphaRange,
1694 DrawMode_PAINT);
1695 drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip );
1697 else
1699 drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
1702 else
1704 getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask,
1705 rSrcRect, rDstPoint, rClip );
1710 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1711 const BitmapDeviceSharedPtr& rMask,
1712 const basegfx::B2IBox& rSrcRect,
1713 const basegfx::B2IBox& rDstRect,
1714 DrawMode drawMode )
1716 OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1718 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1719 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1720 basegfx::B2IBox aSrcRange( rSrcRect );
1721 basegfx::B2IBox aDestRange( rDstRect );
1723 if( clipAreaImpl( aDestRange,
1724 aSrcRange,
1725 mpImpl->maBounds,
1726 aSrcBounds ))
1728 assertImageRange(aDestRange,mpImpl->maBounds);
1729 assertImageRange(aSrcRange,aSrcBounds);
1731 drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode );
1735 void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
1736 const BitmapDeviceSharedPtr& rMask,
1737 const basegfx::B2IBox& rSrcRect,
1738 const basegfx::B2IBox& rDstRect,
1739 DrawMode drawMode,
1740 const BitmapDeviceSharedPtr& rClip )
1742 if( !rClip )
1744 drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
1745 return;
1748 OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
1750 const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
1751 const basegfx::B2IBox aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
1752 basegfx::B2IBox aSrcRange( rSrcRect );
1753 basegfx::B2IBox aDestRange( rDstRect );
1755 if( clipAreaImpl( aDestRange,
1756 aSrcRange,
1757 mpImpl->maBounds,
1758 aSrcBounds ))
1760 assertImageRange(aDestRange,mpImpl->maBounds);
1761 assertImageRange(aSrcRange,aSrcBounds);
1763 if( isCompatibleClipMask( rClip ) )
1765 drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip );
1767 else
1769 getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect,
1770 rDstRect, drawMode, rClip );
1777 /** Standard clip and alpha masks
1779 struct StdMasks
1781 typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits;
1782 typedef PixelFormatTraits_GREY8 alphamask_format_traits;
1784 /// Clipmask: 0 means opaque
1785 static const bool clipmask_polarity = false;
1787 /// Alpha mask: 0 means fully transparent
1788 static const bool alphamask_polarity = true;
1792 // Some compilers don't like the nested template wrap_accessor
1793 // reference in the parameter list - being slightly less type safe,
1794 // then.
1795 #ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
1797 /// Produces a specialized renderer for the given pixel format
1798 template< class FormatTraits, class MaskTraits >
1799 BitmapDeviceSharedPtr createRenderer(
1800 const basegfx::B2IBox& rBounds,
1801 const basegfx::B2IVector& rBufferSize,
1802 Format nScanlineFormat,
1803 sal_Int32 nScanlineStride,
1804 sal_uInt8* pFirstScanline,
1805 typename FormatTraits::raw_accessor_type const& rRawAccessor,
1806 typename FormatTraits::accessor_selector::template wrap_accessor<
1807 typename FormatTraits::raw_accessor_type>::type const& rAccessor,
1808 boost::shared_array< sal_uInt8 > pMem,
1809 const PaletteMemorySharedVector& pPal,
1810 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1811 #else
1813 template< class FormatTraits, class MaskTraits, class Accessor >
1814 BitmapDeviceSharedPtr createRenderer(
1815 const basegfx::B2IBox& rBounds,
1816 const basegfx::B2IVector& rBufferSize,
1817 Format nScanlineFormat,
1818 sal_Int32 nScanlineStride,
1819 sal_uInt8* pFirstScanline,
1820 typename FormatTraits::raw_accessor_type const& rRawAccessor,
1821 Accessor const& rAccessor,
1822 boost::shared_array< sal_uInt8 > pMem,
1823 const PaletteMemorySharedVector& pPal,
1824 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1826 #endif
1828 typedef typename FormatTraits::iterator_type Iterator;
1829 typedef BitmapRenderer< Iterator,
1830 typename FormatTraits::raw_accessor_type,
1831 typename FormatTraits::accessor_selector,
1832 MaskTraits > Renderer;
1834 return BitmapDeviceSharedPtr(
1835 new Renderer( rBounds,
1836 rBufferSize,
1837 nScanlineFormat,
1838 nScanlineStride,
1839 pFirstScanline,
1840 Iterator(
1841 reinterpret_cast<typename Iterator::value_type*>(
1842 pFirstScanline),
1843 nScanlineStride),
1844 rRawAccessor,
1845 rAccessor,
1846 pMem,
1847 pPal,
1848 pDamage ));
1851 /// Create standard grey level palette
1852 PaletteMemorySharedVector createStandardPalette(
1853 const PaletteMemorySharedVector& pPal,
1854 sal_Int32 nNumEntries )
1856 if( pPal || nNumEntries <= 0 )
1857 return pPal;
1859 boost::shared_ptr< std::vector<Color> > pLocalPal(
1860 new std::vector<Color>(nNumEntries) );
1862 const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries );
1863 --nNumEntries;
1864 for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement )
1865 pLocalPal->at(i) = Color(0xFF000000 | c);
1867 pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF);
1869 return pLocalPal;
1872 template< class FormatTraits, class MaskTraits >
1873 BitmapDeviceSharedPtr createRenderer(
1874 const basegfx::B2IBox& rBounds,
1875 const basegfx::B2IVector& rBufferSize,
1876 Format nScanlineFormat,
1877 sal_Int32 nScanlineStride,
1878 sal_uInt8* pFirstScanline,
1879 boost::shared_array< sal_uInt8 > pMem,
1880 const PaletteMemorySharedVector& pPal,
1881 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1883 return createRenderer<FormatTraits,
1884 MaskTraits>(rBounds,
1885 rBufferSize,
1886 nScanlineFormat,
1887 nScanlineStride,
1888 pFirstScanline,
1889 typename FormatTraits::raw_accessor_type(),
1890 typename FormatTraits::accessor_selector::template
1891 wrap_accessor<
1892 typename FormatTraits::raw_accessor_type>::type(),
1893 pMem,
1894 pPal,
1895 pDamage);
1898 template< class FormatTraits, class MaskTraits >
1899 BitmapDeviceSharedPtr createRenderer(
1900 const basegfx::B2IBox& rBounds,
1901 const basegfx::B2IVector& rBufferSize,
1902 Format nScanlineFormat,
1903 sal_Int32 nScanlineStride,
1904 sal_uInt8* pFirstScanline,
1905 boost::shared_array< sal_uInt8 > pMem,
1906 PaletteMemorySharedVector pPal,
1907 int nBitsPerPixel,
1908 const IBitmapDeviceDamageTrackerSharedPtr& pDamage )
1910 pPal = createStandardPalette(pPal,
1911 1UL << nBitsPerPixel);
1913 OSL_ASSERT(pPal);
1914 return createRenderer<FormatTraits,
1915 MaskTraits>(rBounds,
1916 rBufferSize,
1917 nScanlineFormat,
1918 nScanlineStride,
1919 pFirstScanline,
1920 typename FormatTraits::raw_accessor_type(),
1921 typename FormatTraits::accessor_selector::template
1922 wrap_accessor<
1923 typename FormatTraits::raw_accessor_type>::type(
1924 &pPal->at(0),
1925 pPal->size()),
1926 pMem,
1927 pPal,
1928 pDamage);
1932 // TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
1933 // to o3tl or sal/bithacks.hxx ...
1935 /** Compute the next highest power of 2 of a 32-bit value
1937 Code devised by Sean Anderson, in good ole HAKMEM
1938 tradition.
1940 @return 1 << (lg(x - 1) + 1)
1942 inline sal_uInt32 nextPow2( sal_uInt32 x )
1944 --x;
1945 x |= x >> 1;
1946 x |= x >> 2;
1947 x |= x >> 4;
1948 x |= x >> 8;
1949 x |= x >> 16;
1951 return ++x;
1954 namespace
1956 BitmapDeviceSharedPtr createBitmapDeviceImplInner( const basegfx::B2IVector& rSize,
1957 bool bTopDown,
1958 Format nScanlineFormat,
1959 sal_Int32 nScanlineStride,
1960 boost::shared_array< sal_uInt8 > pMem,
1961 PaletteMemorySharedVector pPal,
1962 const basegfx::B2IBox* pSubset,
1963 const IBitmapDeviceDamageTrackerSharedPtr& rDamage,
1964 bool bBlack = true)
1966 OSL_ASSERT(rSize.getX() > 0 && rSize.getY() > 0);
1968 if( nScanlineFormat <= FORMAT_NONE ||
1969 nScanlineFormat > FORMAT_MAX )
1970 return BitmapDeviceSharedPtr();
1972 sal_uInt8 nBitsPerPixel = bitsPerPixel[nScanlineFormat];
1973 if (rSize.getX() > (SAL_MAX_INT32-7) / nBitsPerPixel)
1975 SAL_WARN("basebmp", "suspicious bitmap width " <<
1976 rSize.getX() << " for depth " << nBitsPerPixel);
1977 return BitmapDeviceSharedPtr();
1980 // factor in bottom-up scanline order case
1981 nScanlineStride *= bTopDown ? 1 : -1;
1983 const sal_uInt32 nWidth(nScanlineStride < 0 ? -nScanlineStride : nScanlineStride);
1984 const sal_uInt32 nHeight(rSize.getY());
1986 if (nHeight && nWidth && nWidth > SAL_MAX_INT32 / nHeight)
1988 SAL_WARN( "basebmp", "suspicious massive alloc " << nWidth << " * " << nHeight);
1989 return BitmapDeviceSharedPtr();
1992 const std::size_t nMemSize(nWidth * nHeight);
1994 if( !pMem )
1996 pMem.reset(
1997 static_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
1998 &rtl_freeMemory );
1999 if (pMem.get() == 0 && nMemSize != 0)
2000 return BitmapDeviceSharedPtr();
2001 if (bBlack)
2002 memset(pMem.get(), 0, nMemSize);
2003 else
2004 memset(pMem.get(), 0xFF, nMemSize);
2007 sal_uInt8* pFirstScanline = nScanlineStride < 0 ?
2008 pMem.get() + nMemSize + nScanlineStride : pMem.get();
2010 // shrink render area to given subset, if given
2011 basegfx::B2IBox aBounds(0,0,rSize.getX(),rSize.getY());
2012 if( pSubset )
2013 aBounds.intersect( *pSubset );
2015 switch( nScanlineFormat )
2018 // one bit formats
2020 case FORMAT_ONE_BIT_MSB_GREY:
2021 return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>(
2022 aBounds, rSize, nScanlineFormat, nScanlineStride,
2023 pFirstScanline, pMem, pPal, rDamage );
2025 case FORMAT_ONE_BIT_LSB_GREY:
2026 return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>(
2027 aBounds, rSize, nScanlineFormat, nScanlineStride,
2028 pFirstScanline, pMem, pPal, rDamage );
2030 case FORMAT_ONE_BIT_MSB_PAL:
2031 return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>(
2032 aBounds, rSize, nScanlineFormat, nScanlineStride,
2033 pFirstScanline, pMem, pPal,
2034 bitsPerPixel[nScanlineFormat], rDamage );
2036 case FORMAT_ONE_BIT_LSB_PAL:
2037 return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>(
2038 aBounds, rSize, nScanlineFormat, nScanlineStride,
2039 pFirstScanline, pMem, pPal,
2040 bitsPerPixel[nScanlineFormat], rDamage );
2044 // four bit formats
2046 case FORMAT_FOUR_BIT_MSB_GREY:
2047 return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>(
2048 aBounds, rSize, nScanlineFormat, nScanlineStride,
2049 pFirstScanline, pMem, pPal, rDamage );
2051 case FORMAT_FOUR_BIT_LSB_GREY:
2052 return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>(
2053 aBounds, rSize, nScanlineFormat, nScanlineStride,
2054 pFirstScanline, pMem, pPal, rDamage );
2056 case FORMAT_FOUR_BIT_MSB_PAL:
2057 return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>(
2058 aBounds, rSize, nScanlineFormat, nScanlineStride,
2059 pFirstScanline, pMem, pPal,
2060 bitsPerPixel[nScanlineFormat], rDamage );
2062 case FORMAT_FOUR_BIT_LSB_PAL:
2063 return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>(
2064 aBounds, rSize, nScanlineFormat, nScanlineStride,
2065 pFirstScanline, pMem, pPal,
2066 bitsPerPixel[nScanlineFormat], rDamage );
2070 // eight bit formats
2072 case FORMAT_EIGHT_BIT_GREY:
2073 return createRenderer<PixelFormatTraits_GREY8,StdMasks>(
2074 aBounds, rSize, nScanlineFormat, nScanlineStride,
2075 pFirstScanline, pMem, pPal, rDamage );
2077 case FORMAT_EIGHT_BIT_PAL:
2078 return createRenderer<PixelFormatTraits_PAL8,StdMasks>(
2079 aBounds, rSize, nScanlineFormat, nScanlineStride,
2080 pFirstScanline, pMem, pPal,
2081 bitsPerPixel[nScanlineFormat], rDamage );
2085 // sixteen bit formats
2087 case FORMAT_SIXTEEN_BIT_LSB_TC_MASK:
2088 return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>(
2089 aBounds, rSize, nScanlineFormat, nScanlineStride,
2090 pFirstScanline, pMem, pPal, rDamage );
2092 case FORMAT_SIXTEEN_BIT_MSB_TC_MASK:
2093 return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>(
2094 aBounds, rSize, nScanlineFormat, nScanlineStride,
2095 pFirstScanline, pMem, pPal, rDamage );
2097 // twentyfour bit formats
2098 case FORMAT_TWENTYFOUR_BIT_TC_MASK:
2099 return createRenderer<PixelFormatTraits_BGR24,StdMasks>(
2100 aBounds, rSize, nScanlineFormat, nScanlineStride,
2101 pFirstScanline, pMem, pPal, rDamage );
2103 // thirtytwo bit formats
2105 // 8 red bits, 8 green bits, 8 blue bits, and 8 ignored bits like CAIRO_FORMAT_RGB24
2106 case FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX:
2107 return createRenderer<PixelFormatTraits_BGRX32_8888,StdMasks>(
2108 aBounds, rSize, nScanlineFormat, nScanlineStride,
2109 pFirstScanline, pMem, pPal, rDamage );
2111 case FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA:
2112 return createRenderer<PixelFormatTraits_BGRA32_8888,StdMasks>(
2113 aBounds, rSize, nScanlineFormat, nScanlineStride,
2114 pFirstScanline, pMem, pPal, rDamage );
2116 case FORMAT_THIRTYTWO_BIT_TC_MASK_ARGB:
2117 return createRenderer<PixelFormatTraits_ARGB32_8888,StdMasks>(
2118 aBounds, rSize, nScanlineFormat, nScanlineStride,
2119 pFirstScanline, pMem, pPal, rDamage );
2121 case FORMAT_THIRTYTWO_BIT_TC_MASK_ABGR:
2122 return createRenderer<PixelFormatTraits_ABGR32_8888,StdMasks>(
2123 aBounds, rSize, nScanlineFormat, nScanlineStride,
2124 pFirstScanline, pMem, pPal, rDamage );
2126 case FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA:
2127 return createRenderer<PixelFormatTraits_RGBA32_8888,StdMasks>(
2128 aBounds, rSize, nScanlineFormat, nScanlineStride,
2129 pFirstScanline, pMem, pPal, rDamage );
2131 default:
2132 assert(false); // this cannot happen
2135 // TODO(F3): other formats not yet implemented
2136 return BitmapDeviceSharedPtr();
2139 BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize,
2140 bool bTopDown,
2141 Format nScanlineFormat,
2142 sal_Int32 nScanlineStride,
2143 boost::shared_array< sal_uInt8 > pMem,
2144 PaletteMemorySharedVector pPal,
2145 const basegfx::B2IBox* pSubset,
2146 const IBitmapDeviceDamageTrackerSharedPtr& rDamage,
2147 bool bBlack = true)
2149 BitmapDeviceSharedPtr result( createBitmapDeviceImplInner( rSize, bTopDown, nScanlineFormat, nScanlineStride, pMem, pPal, pSubset, rDamage, bBlack ) );
2151 #ifdef SAL_LOG_INFO
2152 std::ostringstream subset;
2154 if (pSubset)
2155 subset << " subset=" << pSubset->getWidth() << "x" << pSubset->getHeight() << "@(" << pSubset->getMinX() << "," << pSubset->getMinY() << ")";
2157 SAL_INFO( "basebmp.bitmapdevice",
2158 "createBitmapDevice: "
2159 << rSize.getX() << "x" << rSize.getY()
2160 << (bTopDown ? " top-down " : " bottom-up ")
2161 << formatName(nScanlineFormat)
2162 << subset.str()
2163 << " = " << result.get() );
2164 #endif
2165 return result;
2167 } // namespace
2169 sal_Int32 getBitmapDeviceStrideForWidth(Format nScanlineFormat, sal_Int32 nWidth)
2171 sal_uInt8 nBitsPerPixel = bitsPerPixel[nScanlineFormat];
2172 // round up to full 8 bit, divide by 8
2173 sal_Int32 nScanlineStride = (nWidth*nBitsPerPixel + 7) >> 3;
2175 // rounded up to next full power-of-two number of bytes
2176 const sal_uInt32 bytesPerPixel = nextPow2(
2177 (bitsPerPixel[nScanlineFormat] + 7) >> 3);
2179 // now make nScanlineStride a multiple of bytesPerPixel
2180 nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel;
2181 return nScanlineStride;
2184 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2185 bool bTopDown,
2186 Format nScanlineFormat,
2187 sal_Int32 nScanlineStride )
2189 return createBitmapDeviceImpl( rSize,
2190 bTopDown,
2191 nScanlineFormat,
2192 nScanlineStride,
2193 boost::shared_array< sal_uInt8 >(),
2194 PaletteMemorySharedVector(),
2195 NULL,
2196 IBitmapDeviceDamageTrackerSharedPtr() );
2199 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2200 bool bTopDown,
2201 Format nScanlineFormat,
2202 sal_Int32 nScanlineStride,
2203 const PaletteMemorySharedVector& rPalette )
2205 return createBitmapDeviceImpl( rSize,
2206 bTopDown,
2207 nScanlineFormat,
2208 nScanlineStride,
2209 boost::shared_array< sal_uInt8 >(),
2210 rPalette,
2211 NULL,
2212 IBitmapDeviceDamageTrackerSharedPtr() );
2215 BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
2216 bool bTopDown,
2217 Format nScanlineFormat,
2218 sal_Int32 nScanlineStride,
2219 const RawMemorySharedArray& rMem,
2220 const PaletteMemorySharedVector& rPalette )
2222 return createBitmapDeviceImpl( rSize,
2223 bTopDown,
2224 nScanlineFormat,
2225 nScanlineStride,
2226 rMem,
2227 rPalette,
2228 NULL,
2229 IBitmapDeviceDamageTrackerSharedPtr() );
2232 BitmapDeviceSharedPtr createClipDevice( const basegfx::B2IVector& rSize )
2234 BitmapDeviceSharedPtr xClip(
2235 createBitmapDeviceImpl( rSize,
2236 false, /* bTopDown */
2237 basebmp::FORMAT_ONE_BIT_MSB_GREY,
2238 getBitmapDeviceStrideForWidth(basebmp::FORMAT_ONE_BIT_MSB_GREY, rSize.getX()),
2239 boost::shared_array< sal_uInt8 >(),
2240 PaletteMemorySharedVector(),
2241 NULL,
2242 IBitmapDeviceDamageTrackerSharedPtr(),
2243 false /* white */) );
2244 return xClip;
2247 BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto,
2248 const basegfx::B2IBox& rSubset )
2250 SAL_INFO( "basebmp.bitmapdevice", "subsetBitmapDevice: proto=" << rProto.get() );
2251 return createBitmapDeviceImpl( rProto->getSize(),
2252 rProto->isTopDown(),
2253 rProto->getScanlineFormat(),
2254 rProto->getScanlineStride(),
2255 rProto->getBuffer(),
2256 rProto->getPalette(),
2257 &rSubset,
2258 rProto->getDamageTracker() );
2261 BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize,
2262 const BitmapDeviceSharedPtr& rProto )
2264 return createBitmapDeviceImpl( rSize,
2265 rProto->isTopDown(),
2266 rProto->getScanlineFormat(),
2267 rProto->getScanlineStride(),
2268 boost::shared_array< sal_uInt8 >(),
2269 rProto->getPalette(),
2270 NULL,
2271 rProto->getDamageTracker() );
2275 /// Clone our device, with GenericImageAccessor to handle all formats
2276 BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const
2278 return mpImpl->mpGenericRenderer;
2281 } // namespace basebmp
2283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */