summaryrefslogtreecommitdiff
path: root/basebmp/source
diff options
context:
space:
mode:
Diffstat (limited to 'basebmp/source')
-rw-r--r--basebmp/source/bitmapdevice.cxx2064
-rw-r--r--basebmp/source/debug.cxx106
-rw-r--r--basebmp/source/intconversion.hxx88
-rw-r--r--basebmp/source/makefile.mk76
-rw-r--r--basebmp/source/polypolygonrenderer.cxx127
5 files changed, 2461 insertions, 0 deletions
diff --git a/basebmp/source/bitmapdevice.cxx b/basebmp/source/bitmapdevice.cxx
new file mode 100644
index 000000000000..4e179c3a0ce0
--- /dev/null
+++ b/basebmp/source/bitmapdevice.cxx
@@ -0,0 +1,2064 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// FIXME: in vigra
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x580)
+#include <math.h> // needed for fabs, hypot
+#endif
+#include "basebmp/bitmapdevice.hxx"
+
+#include "basebmp/compositeiterator.hxx"
+#include "basebmp/iteratortraits.hxx"
+
+#include "basebmp/accessor.hxx"
+#include "basebmp/accessortraits.hxx"
+#include "basebmp/accessoradapters.hxx"
+#include "basebmp/colorblendaccessoradapter.hxx"
+
+#include "basebmp/color.hxx"
+#include "basebmp/colormisc.hxx"
+#include "basebmp/colortraits.hxx"
+
+#include "basebmp/greylevelformats.hxx"
+#include "basebmp/paletteformats.hxx"
+#include "basebmp/rgbmaskpixelformats.hxx"
+#include "basebmp/rgb24pixelformats.hxx"
+
+#include "basebmp/scanlineformats.hxx"
+#include "basebmp/fillimage.hxx"
+#include "basebmp/scaleimage.hxx"
+#include "basebmp/clippedlinerenderer.hxx"
+#include "basebmp/polypolygonrenderer.hxx"
+#include "basebmp/genericcolorimageaccessor.hxx"
+
+#include "basebmp/tools.hxx"
+#include "intconversion.hxx"
+
+#include <rtl/alloc.h>
+#include <rtl/memory.h>
+#include <osl/diagnose.h>
+
+#include <basegfx/tools/tools.hxx>
+#include <basegfx/range/b2irange.hxx>
+#include <basegfx/range/b2drange.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+
+#include <vigra/iteratortraits.hxx>
+#include <vigra/rgbvalue.hxx>
+#include <vigra/copyimage.hxx>
+#include <vigra/tuple.hxx>
+
+
+namespace vigra
+{
+
+/// componentwise xor of an RGBValue (missing from rgbvalue.hxx)
+template< class Value, unsigned int RedIndex, unsigned int BlueIndex, unsigned int GreenIndex >
+inline RGBValue<Value, RedIndex, GreenIndex, BlueIndex>
+operator^( RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& lhs,
+ RGBValue<Value, RedIndex, GreenIndex, BlueIndex> const& rhs )
+{
+ RGBValue<Value, RedIndex, GreenIndex, BlueIndex> res(
+ lhs[0] ^ rhs[0],
+ lhs[1] ^ rhs[1],
+ lhs[2] ^ rhs[2]);
+ return res;
+}
+}
+
+namespace basebmp
+{
+
+namespace
+{
+ /** Create the type for an accessor that takes the (mask,bitmap)
+ input value generated from a JoinImageAccessorAdapter, and
+ pipe that through a mask functor.
+
+ @tpl DestAccessor
+ Destination bitmap accessor
+
+ @tpl JoinedAccessor
+ Input accessor, is expected to generate a std::pair as the
+ value type
+
+ @tpl MaskFunctorMode
+ Either FastMask or NoFastMask, depending on whether the mask
+ is guaranteed to contain only 0s and 1s.
+ */
+ template< class DestAccessor,
+ class JoinedAccessor,
+ bool polarity,
+ typename MaskFunctorMode > struct masked_input_splitting_accessor
+ {
+ typedef BinarySetterFunctionAccessorAdapter<
+ DestAccessor,
+ BinaryFunctorSplittingWrapper<
+ typename outputMaskFunctorSelector<
+ typename JoinedAccessor::value_type::first_type,
+ typename JoinedAccessor::value_type::second_type,
+ polarity,
+ MaskFunctorMode >::type > > type;
+ };
+
+
+
+ // Actual BitmapDevice implementation (templatized by accessor and iterator)
+ //--------------------------------------------------------------------------
+
+ /** Implementation of the BitmapDevice interface
+
+ @tpl DestIterator
+ Iterator to access bitmap memory
+
+ @tpl RawAccessor
+ Raw accessor, to access pixel values directly
+
+ @tpl AccessorSelector
+ Accessor adapter selector, which, when applying the nested
+ template metafunction wrap_accessor to one of the raw bitmap
+ accessors, yields a member type named 'type', which is a
+ wrapped accessor that map color values.
+
+ @tpl Masks
+ Traits template, containing nested traits
+ clipmask_format_traits and alphamask_format_traits, which
+ determine what specialized formats are to be used for clip and
+ alpha masks. With those mask formats, clipping and alpha
+ blending is handled natively.
+ */
+ template< class DestIterator,
+ class RawAccessor,
+ class AccessorSelector,
+ class Masks > class BitmapRenderer :
+ public BitmapDevice
+ {
+ public:
+ typedef DestIterator dest_iterator_type;
+ typedef RawAccessor raw_accessor_type;
+ typedef AccessorSelector accessor_selector;
+
+ typedef typename Masks::clipmask_format_traits::iterator_type mask_iterator_type;
+ typedef typename Masks::clipmask_format_traits::raw_accessor_type mask_rawaccessor_type;
+ typedef typename Masks::clipmask_format_traits::accessor_selector mask_accessorselector_type;
+
+ typedef typename Masks::alphamask_format_traits::iterator_type alphamask_iterator_type;
+ typedef typename Masks::alphamask_format_traits::raw_accessor_type alphamask_rawaccessor_type;
+ typedef typename Masks::alphamask_format_traits::accessor_selector alphamask_accessorselector_type;
+
+ typedef typename AccessorSelector::template wrap_accessor<
+ raw_accessor_type >::type dest_accessor_type;
+
+ typedef AccessorTraits< dest_accessor_type > accessor_traits;
+ typedef CompositeIterator2D< dest_iterator_type,
+ mask_iterator_type > composite_iterator_type;
+ typedef CompositeIterator2D< vigra::Diff2D,
+ vigra::Diff2D > generic_composite_iterator_type;
+
+ typedef BitmapRenderer<mask_iterator_type,
+ mask_rawaccessor_type,
+ mask_accessorselector_type,
+ Masks> mask_bitmap_type;
+ typedef BitmapRenderer<alphamask_iterator_type,
+ alphamask_rawaccessor_type,
+ alphamask_accessorselector_type,
+ Masks> alphamask_bitmap_type;
+
+ // -------------------------------------------------------
+
+ typedef AccessorTraits< raw_accessor_type > raw_accessor_traits;
+ typedef typename uInt32Converter<
+ typename raw_accessor_type::value_type>::to to_uint32_functor;
+
+ // -------------------------------------------------------
+
+ typedef typename raw_accessor_traits::xor_accessor raw_xor_accessor_type;
+ typedef AccessorTraits<raw_xor_accessor_type> raw_xor_accessor_traits;
+ typedef typename accessor_selector::template wrap_accessor<
+ raw_xor_accessor_type >::type xor_accessor_type;
+ typedef AccessorTraits<xor_accessor_type> xor_accessor_traits;
+
+ // -------------------------------------------------------
+
+ typedef typename raw_accessor_traits::template masked_accessor<
+ mask_rawaccessor_type,
+ dest_iterator_type,
+ mask_iterator_type,
+ Masks::clipmask_polarity>::type raw_maskedaccessor_type;
+ typedef typename accessor_selector::template wrap_accessor<
+ raw_maskedaccessor_type >::type masked_accessor_type;
+ typedef typename AccessorTraits<
+ raw_maskedaccessor_type>::xor_accessor raw_maskedxor_accessor_type;
+ typedef typename accessor_selector::template wrap_accessor<
+ raw_maskedxor_accessor_type >::type masked_xoraccessor_type;
+
+ // -------------------------------------------------------
+
+ // ((iter,mask),mask) special case (e.g. for clipped
+ // drawMaskedColor())
+ typedef AccessorTraits< raw_maskedaccessor_type > raw_maskedaccessor_traits;
+ typedef typename raw_maskedaccessor_traits::template masked_accessor<
+ mask_rawaccessor_type,
+ composite_iterator_type,
+ mask_iterator_type,
+ Masks::clipmask_polarity>::type raw_maskedmask_accessor_type;
+
+ typedef CompositeIterator2D<
+ composite_iterator_type,
+ mask_iterator_type> composite_composite_mask_iterator_type;
+
+ // -------------------------------------------------------
+
+ typedef ConstantColorBlendSetterAccessorAdapter<
+ dest_accessor_type,
+ typename alphamask_rawaccessor_type::value_type,
+ Masks::alphamask_polarity> colorblend_accessor_type;
+ typedef AccessorTraits<colorblend_accessor_type> colorblend_accessor_traits;
+ typedef typename colorblend_accessor_traits::template masked_accessor<
+ mask_rawaccessor_type,
+ dest_iterator_type,
+ mask_iterator_type,
+ Masks::clipmask_polarity>::type masked_colorblend_accessor_type;
+
+ // -------------------------------------------------------
+
+ typedef ConstantColorBlendSetterAccessorAdapter<
+ dest_accessor_type,
+ Color,
+ Masks::alphamask_polarity> colorblend_generic_accessor_type;
+ typedef AccessorTraits<colorblend_generic_accessor_type> colorblend_generic_accessor_traits;
+ typedef typename colorblend_generic_accessor_traits::template masked_accessor<
+ mask_rawaccessor_type,
+ dest_iterator_type,
+ mask_iterator_type,
+ Masks::clipmask_polarity>::type masked_colorblend_generic_accessor_type;
+
+ // -------------------------------------------------------
+
+ typedef JoinImageAccessorAdapter< dest_accessor_type,
+ mask_rawaccessor_type > joined_image_accessor_type;
+ typedef JoinImageAccessorAdapter< GenericColorImageAccessor,
+ GenericColorImageAccessor > joined_generic_image_accessor_type;
+
+ // -------------------------------------------------------
+
+ dest_iterator_type maBegin;
+ typename accessor_traits::color_lookup maColorLookup;
+ to_uint32_functor maToUInt32Converter;
+ dest_accessor_type maAccessor;
+ colorblend_accessor_type maColorBlendAccessor;
+ colorblend_generic_accessor_type maGenericColorBlendAccessor;
+ raw_accessor_type maRawAccessor;
+ xor_accessor_type maXorAccessor;
+ raw_xor_accessor_type maRawXorAccessor;
+ masked_accessor_type maMaskedAccessor;
+ masked_colorblend_accessor_type maMaskedColorBlendAccessor;
+ masked_colorblend_generic_accessor_type maGenericMaskedColorBlendAccessor;
+ masked_xoraccessor_type maMaskedXorAccessor;
+ raw_maskedaccessor_type maRawMaskedAccessor;
+ raw_maskedxor_accessor_type maRawMaskedXorAccessor;
+ raw_maskedmask_accessor_type maRawMaskedMaskAccessor;
+
+ // -------------------------------------------------------
+
+ BitmapRenderer( const basegfx::B2IRange& rBounds,
+ sal_Int32 nScanlineFormat,
+ sal_Int32 nScanlineStride,
+ sal_uInt8* pFirstScanline,
+ dest_iterator_type begin,
+ raw_accessor_type rawAccessor,
+ dest_accessor_type accessor,
+ const RawMemorySharedArray& rMem,
+ const PaletteMemorySharedVector& rPalette ) :
+ BitmapDevice( rBounds, nScanlineFormat,
+ nScanlineStride, pFirstScanline, rMem, rPalette ),
+ maBegin( begin ),
+ maColorLookup(),
+ maToUInt32Converter(),
+ maAccessor( accessor ),
+ maColorBlendAccessor( accessor ),
+ maGenericColorBlendAccessor( accessor ),
+ maRawAccessor( rawAccessor ),
+ maXorAccessor( accessor ),
+ maRawXorAccessor( rawAccessor ),
+ maMaskedAccessor( accessor ),
+ maMaskedColorBlendAccessor( maColorBlendAccessor ),
+ maGenericMaskedColorBlendAccessor( maGenericColorBlendAccessor ),
+ maMaskedXorAccessor( accessor ),
+ maRawMaskedAccessor( rawAccessor ),
+ maRawMaskedXorAccessor( rawAccessor ),
+ maRawMaskedMaskAccessor( rawAccessor )
+ {}
+
+ private:
+ boost::shared_ptr<BitmapRenderer> getCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
+ {
+ return boost::dynamic_pointer_cast< BitmapRenderer >( bmp );
+ }
+
+ virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const
+ {
+ // TODO(P1): dynamic_cast usually called twice for
+ // compatible formats
+ return getCompatibleBitmap(bmp).get() != NULL;
+ }
+
+ boost::shared_ptr<mask_bitmap_type> getCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
+ {
+ boost::shared_ptr<mask_bitmap_type> pMask( boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ));
+
+ if( !pMask )
+ return pMask;
+
+ if( pMask->getSize() != getSize() )
+ pMask.reset();
+
+ return pMask;
+ }
+
+ virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const
+ {
+ // TODO(P1): dynamic_cast usually called twice for
+ // compatible formats
+ return boost::dynamic_pointer_cast<mask_bitmap_type>( bmp ).get() != NULL;
+ }
+
+ boost::shared_ptr<alphamask_bitmap_type> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
+ {
+ return boost::dynamic_pointer_cast<alphamask_bitmap_type>( bmp );
+ }
+
+ virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const
+ {
+ // TODO(P1): dynamic_cast usually called twice for
+ // compatible formats
+ return getCompatibleAlphaMask( bmp ).get() != NULL;
+ }
+
+ virtual void clear_i( Color fillColor,
+ const basegfx::B2IRange& rBounds )
+ {
+ fillImage(destIterRange(maBegin,
+ maRawAccessor,
+ rBounds),
+ maColorLookup(
+ maAccessor,
+ fillColor) );
+ }
+
+ virtual void setPixel_i( const basegfx::B2IPoint& rPt,
+ Color pixelColor,
+ DrawMode drawMode )
+ {
+ const DestIterator pixel( maBegin +
+ vigra::Diff2D(rPt.getX(),
+ rPt.getY()) );
+ if( drawMode == DrawMode_XOR )
+ maXorAccessor.set( pixelColor,
+ pixel );
+ else
+ maAccessor.set( pixelColor,
+ pixel );
+ }
+
+ virtual void setPixel_i( const basegfx::B2IPoint& rPt,
+ Color pixelColor,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+ {
+ boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
+ OSL_ASSERT( pMask );
+
+ const vigra::Diff2D offset(rPt.getX(),
+ rPt.getY());
+
+ const composite_iterator_type aIter(
+ maBegin + offset,
+ pMask->maBegin + offset );
+
+ if( drawMode == DrawMode_XOR )
+ maMaskedXorAccessor.set( pixelColor,
+ aIter );
+ else
+ maMaskedAccessor.set( pixelColor,
+ aIter );
+ }
+
+ virtual Color getPixel_i(const basegfx::B2IPoint& rPt )
+ {
+ const DestIterator pixel( maBegin +
+ vigra::Diff2D(rPt.getX(),
+ rPt.getY()) );
+ return maAccessor(pixel);
+ }
+
+ virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt )
+ {
+ const DestIterator pixel( maBegin +
+ vigra::Diff2D(rPt.getX(),
+ rPt.getY()) );
+ return maToUInt32Converter(maRawAccessor(pixel));
+ }
+
+ template< typename Iterator, typename Col, typename RawAcc >
+ void implRenderLine2( const basegfx::B2IPoint& rPt1,
+ const basegfx::B2IPoint& rPt2,
+ const basegfx::B2IRange& rBounds,
+ Col col,
+ const Iterator& begin,
+ const RawAcc& rawAcc )
+ {
+ renderClippedLine( rPt1,
+ rPt2,
+ rBounds,
+ col,
+ begin,
+ rawAcc );
+ }
+
+ template< typename Iterator, typename Accessor, typename RawAcc >
+ void implRenderLine( const basegfx::B2IPoint& rPt1,
+ const basegfx::B2IPoint& rPt2,
+ const basegfx::B2IRange& rBounds,
+ Color col,
+ const Iterator& begin,
+ const Accessor& acc,
+ const RawAcc& rawAcc )
+ {
+ implRenderLine2( rPt1,rPt2,rBounds,
+ maColorLookup( acc,
+ col ),
+ begin,
+ rawAcc );
+ }
+
+ template< typename Iterator, typename RawAcc, typename XorAcc >
+ void implDrawLine( const basegfx::B2IPoint& rPt1,
+ const basegfx::B2IPoint& rPt2,
+ const basegfx::B2IRange& rBounds,
+ Color col,
+ const Iterator& begin,
+ const RawAcc& rawAcc,
+ const XorAcc& xorAcc,
+ DrawMode drawMode )
+ {
+ if( drawMode == DrawMode_XOR )
+ implRenderLine( rPt1, rPt2, rBounds, col,
+ begin, maAccessor, xorAcc );
+ else
+ implRenderLine( rPt1, rPt2, rBounds, col,
+ begin, maAccessor, rawAcc );
+ }
+
+ virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
+ const basegfx::B2IPoint& rPt2,
+ const basegfx::B2IRange& rBounds,
+ Color lineColor,
+ DrawMode drawMode )
+ {
+ implDrawLine(rPt1,rPt2,rBounds,lineColor,
+ maBegin,
+ maRawAccessor,maRawXorAccessor,drawMode);
+ }
+
+ composite_iterator_type getMaskedIter( const BitmapDeviceSharedPtr& rClip ) const
+ {
+ boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rClip) );
+ OSL_ASSERT( pMask );
+
+ return composite_iterator_type( maBegin,
+ pMask->maBegin );
+ }
+
+ virtual void drawLine_i(const basegfx::B2IPoint& rPt1,
+ const basegfx::B2IPoint& rPt2,
+ const basegfx::B2IRange& rBounds,
+ Color lineColor,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+ {
+ implDrawLine(rPt1,rPt2,rBounds,lineColor,
+ getMaskedIter(rClip),
+ maRawMaskedAccessor,
+ maRawMaskedXorAccessor,drawMode);
+ }
+
+ template< typename Iterator, typename RawAcc >
+ void implDrawPolygon( const basegfx::B2DPolygon& rPoly,
+ const basegfx::B2IRange& rBounds,
+ Color col,
+ const Iterator& begin,
+ const RawAcc& acc )
+ {
+ basegfx::B2DPolygon aPoly( rPoly );
+ if( rPoly.areControlPointsUsed() )
+ aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
+
+ const typename dest_iterator_type::value_type colorIndex( maColorLookup(
+ maAccessor,
+ col));
+ const sal_uInt32 nVertices( aPoly.count() );
+ for( sal_uInt32 i=1; i<nVertices; ++i )
+ implRenderLine2( basegfx::fround(aPoly.getB2DPoint(i-1)),
+ basegfx::fround(aPoly.getB2DPoint(i)),
+ rBounds,
+ colorIndex,
+ begin,
+ acc );
+
+ if( nVertices > 1 && aPoly.isClosed() )
+ implRenderLine2( basegfx::fround(aPoly.getB2DPoint(nVertices-1)),
+ basegfx::fround(aPoly.getB2DPoint(0)),
+ rBounds,
+ colorIndex,
+ begin,
+ acc );
+ }
+
+ virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
+ const basegfx::B2IRange& rBounds,
+ Color lineColor,
+ DrawMode drawMode )
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawPolygon( rPoly, rBounds, lineColor,
+ maBegin,
+ maRawXorAccessor );
+ else
+ implDrawPolygon( rPoly, rBounds, lineColor,
+ maBegin,
+ maRawAccessor );
+ }
+
+ virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
+ const basegfx::B2IRange& rBounds,
+ Color lineColor,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawPolygon( rPoly, rBounds, lineColor,
+ getMaskedIter(rClip),
+ maRawMaskedXorAccessor );
+ else
+ implDrawPolygon( rPoly, rBounds, lineColor,
+ getMaskedIter(rClip),
+ maRawMaskedAccessor );
+ }
+
+ template< typename Iterator, typename RawAcc >
+ void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
+ Color col,
+ const Iterator& begin,
+ const RawAcc& acc,
+ const basegfx::B2IRange& rBounds )
+ {
+ basegfx::B2DPolyPolygon aPoly( rPoly );
+ if( rPoly.areControlPointsUsed() )
+ aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
+
+ renderClippedPolyPolygon( begin,
+ acc,
+ maColorLookup( maAccessor,
+ col),
+ rBounds,
+ aPoly,
+ basegfx::FillRule_EVEN_ODD );
+ }
+
+ virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
+ Color fillColor,
+ DrawMode drawMode,
+ const basegfx::B2IRange& rBounds )
+ {
+ if( drawMode == DrawMode_XOR )
+ implFillPolyPolygon( rPoly, fillColor,
+ maBegin,
+ maRawXorAccessor,
+ rBounds );
+ else
+ implFillPolyPolygon( rPoly, fillColor,
+ maBegin,
+ maRawAccessor,
+ rBounds );
+ }
+
+ virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
+ Color fillColor,
+ DrawMode drawMode,
+ const basegfx::B2IRange& rBounds,
+ const BitmapDeviceSharedPtr& rClip )
+ {
+ if( drawMode == DrawMode_XOR )
+ implFillPolyPolygon( rPoly, fillColor,
+ getMaskedIter(rClip),
+ maRawMaskedXorAccessor,
+ rBounds );
+ else
+ implFillPolyPolygon( rPoly, fillColor,
+ getMaskedIter(rClip),
+ maRawMaskedAccessor,
+ rBounds );
+ }
+
+ template< typename Iterator, typename RawAcc >
+ void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ const Iterator& begin,
+ const RawAcc& acc)
+ {
+ boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
+ OSL_ASSERT( pSrcBmp );
+
+ scaleImage(
+ srcIterRange(pSrcBmp->maBegin,
+ pSrcBmp->maRawAccessor,
+ rSrcRect),
+ destIterRange(begin,
+ acc,
+ rDstRect),
+ rSrcBitmap.get() == this );
+ }
+
+ template< typename Iterator, typename Acc >
+ void implDrawBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ const Iterator& begin,
+ const Acc& acc)
+ {
+ GenericColorImageAccessor aSrcAcc( rSrcBitmap );
+
+ scaleImage(
+ srcIterRange(vigra::Diff2D(),
+ aSrcAcc,
+ rSrcRect),
+ destIterRange(begin,
+ acc,
+ rDstRect));
+ }
+
+ virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ DrawMode drawMode )
+ {
+ if( isCompatibleBitmap( rSrcBitmap ) )
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
+ maBegin,
+ maRawXorAccessor);
+ else
+ implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
+ maBegin,
+ maRawAccessor);
+ }
+ else
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
+ maBegin,
+ maXorAccessor);
+ else
+ implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
+ maBegin,
+ maAccessor);
+ }
+ }
+
+ virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+ {
+ if( isCompatibleBitmap( rSrcBitmap ) )
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
+ getMaskedIter(rClip),
+ maRawMaskedXorAccessor);
+ else
+ implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
+ getMaskedIter(rClip),
+ maRawMaskedAccessor);
+ }
+ else
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
+ getMaskedIter(rClip),
+ maMaskedXorAccessor);
+ else
+ implDrawBitmapGeneric(rSrcBitmap, rSrcRect, rDstRect,
+ getMaskedIter(rClip),
+ maMaskedAccessor);
+ }
+ }
+
+ virtual void drawMaskedColor_i(Color aSrcColor,
+ const BitmapDeviceSharedPtr& rAlphaMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IPoint& rDstPoint )
+ {
+ boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
+ boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
+
+ if( pAlpha )
+ {
+ maColorBlendAccessor.setColor( aSrcColor );
+
+ vigra::copyImage( srcIterRange(pAlpha->maBegin,
+ pAlpha->maRawAccessor,
+ rSrcRect),
+ destIter(maBegin,
+ maColorBlendAccessor,
+ rDstPoint) );
+ }
+ else if( pMask )
+ {
+ const composite_iterator_type aBegin(
+ maBegin + vigra::Diff2D(rDstPoint.getX(),
+ rDstPoint.getY()),
+ pMask->maBegin + topLeft(rSrcRect) );
+
+ fillImage(aBegin,
+ aBegin + vigra::Diff2D(rSrcRect.getWidth(),
+ rSrcRect.getHeight()),
+ maRawMaskedAccessor,
+ maColorLookup(
+ maAccessor,
+ aSrcColor) );
+ }
+ else
+ {
+ GenericColorImageAccessor aSrcAcc( rAlphaMask );
+ maGenericColorBlendAccessor.setColor( aSrcColor );
+
+ vigra::copyImage( srcIterRange(vigra::Diff2D(),
+ aSrcAcc,
+ rSrcRect),
+ destIter(maBegin,
+ maGenericColorBlendAccessor,
+ rDstPoint) );
+ }
+ }
+
+ virtual void drawMaskedColor_i(Color aSrcColor,
+ const BitmapDeviceSharedPtr& rAlphaMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IPoint& rDstPoint,
+ const BitmapDeviceSharedPtr& rClip )
+ {
+ boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rAlphaMask) );
+ boost::shared_ptr<alphamask_bitmap_type> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
+
+ if( pAlpha )
+ {
+ const composite_iterator_type aBegin( getMaskedIter(rClip) );
+ maMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
+ aSrcColor );
+
+ vigra::copyImage( srcIterRange(pAlpha->maBegin,
+ pAlpha->maRawAccessor,
+ rSrcRect),
+ destIter(aBegin,
+ maMaskedColorBlendAccessor,
+ rDstPoint) );
+ }
+ else if( pMask )
+ {
+ boost::shared_ptr<mask_bitmap_type> pClipMask( getCompatibleClipMask(rClip) );
+ OSL_ASSERT( pClipMask );
+
+ // setup a ((iter,mask),clipMask) composite composite
+ // iterator, to pass both masks (clip and alpha mask)
+ // to the algorithm
+ const composite_composite_mask_iterator_type aBegin(
+ composite_iterator_type(
+ maBegin + vigra::Diff2D(rDstPoint.getX(),
+ rDstPoint.getY()),
+ pMask->maBegin + topLeft(rSrcRect)),
+ pClipMask->maBegin + vigra::Diff2D(rDstPoint.getX(),
+ rDstPoint.getY()) );
+
+ fillImage(aBegin,
+ aBegin + vigra::Diff2D(rSrcRect.getWidth(),
+ rSrcRect.getHeight()),
+ maRawMaskedMaskAccessor,
+ maColorLookup(
+ maAccessor,
+ aSrcColor) );
+ }
+ else
+ {
+ GenericColorImageAccessor aSrcAcc( rAlphaMask );
+ const composite_iterator_type aBegin( getMaskedIter(rClip) );
+ maGenericMaskedColorBlendAccessor.get1stWrappedAccessor().setColor(
+ aSrcColor );
+
+ vigra::copyImage( srcIterRange(vigra::Diff2D(),
+ aSrcAcc,
+ rSrcRect),
+ destIter(aBegin,
+ maGenericMaskedColorBlendAccessor,
+ rDstPoint) );
+ }
+ }
+
+ template< typename Iterator, typename Acc >
+ void implDrawMaskedBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
+ const BitmapDeviceSharedPtr& rMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ const Iterator& begin,
+ const Acc& acc)
+ {
+ boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
+ boost::shared_ptr<mask_bitmap_type> pMask( getCompatibleClipMask(rMask) );
+ OSL_ASSERT( pMask && pSrcBmp );
+
+ scaleImage(
+ srcIterRange(composite_iterator_type(
+ pSrcBmp->maBegin,
+ pMask->maBegin),
+ joined_image_accessor_type(
+ pSrcBmp->maAccessor,
+ pMask->maRawAccessor),
+ rSrcRect),
+ destIterRange(begin,
+ typename masked_input_splitting_accessor<
+ Acc,
+ joined_image_accessor_type,
+ Masks::clipmask_polarity,
+ FastMask >::type(acc),
+ rDstRect),
+ rSrcBitmap.get() == this);
+ }
+
+ template< typename Iterator, typename Acc >
+ void implDrawMaskedBitmapGeneric(const BitmapDeviceSharedPtr& rSrcBitmap,
+ const BitmapDeviceSharedPtr& rMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ const Iterator& begin,
+ const Acc& acc)
+ {
+ GenericColorImageAccessor aSrcAcc( rSrcBitmap );
+ GenericColorImageAccessor aMaskAcc( rMask );
+
+ const vigra::Diff2D aTopLeft(rSrcRect.getMinX(),
+ rSrcRect.getMinY());
+ const vigra::Diff2D aBottomRight(rSrcRect.getMaxX(),
+ rSrcRect.getMaxY());
+ scaleImage(
+ vigra::make_triple(
+ generic_composite_iterator_type(
+ aTopLeft,aTopLeft),
+ generic_composite_iterator_type(
+ aBottomRight,aBottomRight),
+ joined_generic_image_accessor_type(
+ aSrcAcc,
+ aMaskAcc)),
+ destIterRange(begin,
+ typename masked_input_splitting_accessor<
+ Acc,
+ joined_generic_image_accessor_type,
+ Masks::clipmask_polarity,
+ NoFastMask >::type(acc),
+ rDstRect));
+ }
+
+ virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
+ const BitmapDeviceSharedPtr& rMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ DrawMode drawMode )
+ {
+ if( isCompatibleClipMask(rMask) &&
+ isCompatibleBitmap(rSrcBitmap) )
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawMaskedBitmap(rSrcBitmap, rMask,
+ rSrcRect, rDstRect,
+ maBegin,
+ maXorAccessor);
+ else
+ implDrawMaskedBitmap(rSrcBitmap, rMask,
+ rSrcRect, rDstRect,
+ maBegin,
+ maAccessor);
+ }
+ else
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
+ rSrcRect, rDstRect,
+ maBegin,
+ maXorAccessor);
+ else
+ implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
+ rSrcRect, rDstRect,
+ maBegin,
+ maAccessor);
+ }
+ }
+
+ virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
+ const BitmapDeviceSharedPtr& rMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+ {
+ if( isCompatibleClipMask(rMask) &&
+ isCompatibleBitmap(rSrcBitmap) )
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawMaskedBitmap(rSrcBitmap, rMask,
+ rSrcRect, rDstRect,
+ getMaskedIter(rClip),
+ maMaskedXorAccessor);
+ else
+ implDrawMaskedBitmap(rSrcBitmap, rMask,
+ rSrcRect, rDstRect,
+ getMaskedIter(rClip),
+ maMaskedAccessor);
+ }
+ else
+ {
+ if( drawMode == DrawMode_XOR )
+ implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
+ rSrcRect, rDstRect,
+ getMaskedIter(rClip),
+ maMaskedXorAccessor);
+ else
+ implDrawMaskedBitmapGeneric(rSrcBitmap, rMask,
+ rSrcRect, rDstRect,
+ getMaskedIter(rClip),
+ maMaskedAccessor);
+ }
+ }
+ };
+} // namespace
+
+struct ImplBitmapDevice
+{
+ /** Bitmap memory plus deleter.
+
+ Always points to the start of the mem
+ */
+ RawMemorySharedArray mpMem;
+
+ /// Palette memory plus deleter (might be NULL)
+ PaletteMemorySharedVector mpPalette;
+
+ /** Bounds of the device.
+
+ maBounds.getWidth()/getHeight() yield the true size of the
+ device (i.e. the rectangle given by maBounds covers the device
+ area under the excluding-bottommost-and-rightmost-pixels fill
+ rule)
+ */
+ basegfx::B2IRange maBounds;
+
+ /** Bounds of the device.
+
+ maBounds.getWidth()/getHeight() yield the true size of the
+ device minus 1 (i.e. the rectangle given by maBounds covers
+ the device area under the
+ including-the-bottommost-and-rightmost-pixels fill rule).
+
+ The member is used to clip line stroking against the device
+ bounds.
+ */
+ basegfx::B2IRange maLineClipRect;
+
+ /// Scanline format, as provided at the constructor
+ sal_Int32 mnScanlineFormat;
+
+ /// Scanline stride. Negative for bottom-to-top formats
+ sal_Int32 mnScanlineStride;
+
+ /// raw ptr to 0th scanline. used for cloning a generic renderer
+ sal_uInt8* mpFirstScanline;
+
+ /** (Optional) device sharing the same memory, and used for input
+ clip masks/alpha masks/bitmaps that don't match our exact
+ bitmap format.
+
+ This is to avoid the combinatorical explosion when dealing
+ with n bitmap formats, which could be combined with n clip
+ masks, alpha masks and bitmap masks (yielding a total of n^4
+ combinations). Since each BitmapRenderer is specialized for
+ one specific combination of said formats, a lot of duplicate
+ code would be generated, most of which probably never
+ used. Therefore, only the most common combinations are
+ specialized templates, the remainder gets handled by this
+ generic renderer (via runtime polymorphism).
+ */
+ BitmapDeviceSharedPtr mpGenericRenderer;
+};
+
+
+BitmapDevice::BitmapDevice( const basegfx::B2IRange& rBounds,
+ sal_Int32 nScanlineFormat,
+ sal_Int32 nScanlineStride,
+ sal_uInt8* pFirstScanline,
+ const RawMemorySharedArray& rMem,
+ const PaletteMemorySharedVector& rPalette ) :
+ mpImpl( new ImplBitmapDevice )
+{
+ mpImpl->mpMem = rMem;
+ mpImpl->mpPalette = rPalette;
+ mpImpl->maBounds = rBounds;
+ mpImpl->maLineClipRect = basegfx::B2IRange( rBounds.getMinX(),
+ rBounds.getMinY(),
+ rBounds.getMaxX()-1,
+ rBounds.getMaxY()-1 );
+ mpImpl->mnScanlineFormat = nScanlineFormat;
+ mpImpl->mnScanlineStride = nScanlineStride;
+ mpImpl->mpFirstScanline = pFirstScanline;
+}
+
+BitmapDevice::~BitmapDevice()
+{
+ // outline, because of internal ImplBitmapDevice
+}
+
+basegfx::B2IVector BitmapDevice::getSize() const
+{
+
+ return basegfx::B2IVector(
+ mpImpl->maBounds.getMaxX() - mpImpl->maBounds.getMinX(),
+ mpImpl->maBounds.getMaxY() - mpImpl->maBounds.getMinY() );
+}
+
+bool BitmapDevice::isTopDown() const
+{
+ return mpImpl->mnScanlineStride >= 0;
+}
+
+sal_Int32 BitmapDevice::getScanlineFormat() const
+{
+ return mpImpl->mnScanlineFormat;
+}
+
+sal_Int32 BitmapDevice::getScanlineStride() const
+{
+ return mpImpl->mnScanlineStride < 0 ?
+ -mpImpl->mnScanlineStride : mpImpl->mnScanlineStride;
+}
+
+RawMemorySharedArray BitmapDevice::getBuffer() const
+{
+ return mpImpl->mpMem;
+}
+
+PaletteMemorySharedVector BitmapDevice::getPalette() const
+{
+ return mpImpl->mpPalette;
+}
+
+sal_Int32 BitmapDevice::getPaletteEntryCount() const
+{
+ return mpImpl->mpPalette ? mpImpl->mpPalette->size() : 0;
+}
+
+void BitmapDevice::clear( Color fillColor )
+{
+ clear_i( fillColor, mpImpl->maBounds );
+}
+
+void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
+ Color lineColor,
+ DrawMode drawMode )
+{
+ if( mpImpl->maLineClipRect.isInside(rPt) )
+ setPixel_i(rPt,lineColor,drawMode);
+}
+
+void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt,
+ Color lineColor,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+{
+ if( !rClip )
+ {
+ setPixel(rPt,lineColor,drawMode);
+ return;
+ }
+
+ if( mpImpl->maLineClipRect.isInside(rPt) )
+ {
+ if( isCompatibleClipMask( rClip ) )
+ setPixel_i(rPt,lineColor,drawMode,rClip);
+ else
+ getGenericRenderer()->setPixel( rPt, lineColor, drawMode, rClip );
+ }
+}
+
+Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt )
+{
+ if( mpImpl->maLineClipRect.isInside(rPt) )
+ return getPixel_i(rPt);
+
+ return Color();
+}
+
+sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
+{
+ if( mpImpl->maLineClipRect.isInside(rPt) )
+ return getPixelData_i(rPt);
+
+ return 0;
+}
+
+void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
+ const basegfx::B2IPoint& rPt2,
+ Color lineColor,
+ DrawMode drawMode )
+{
+ drawLine_i( rPt1,
+ rPt2,
+ mpImpl->maLineClipRect,
+ lineColor,
+ drawMode );
+}
+
+void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
+ const basegfx::B2IPoint& rPt2,
+ Color lineColor,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+{
+ if( !rClip )
+ {
+ drawLine(rPt1,rPt2,lineColor,drawMode);
+ return;
+ }
+
+ if( isCompatibleClipMask( rClip ) )
+ drawLine_i( rPt1,
+ rPt2,
+ mpImpl->maLineClipRect,
+ lineColor,
+ drawMode,
+ rClip );
+ else
+ getGenericRenderer()->drawLine( rPt1, rPt2, lineColor,
+ drawMode, rClip );
+}
+
+void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
+ Color lineColor,
+ DrawMode drawMode )
+{
+ const sal_uInt32 numVertices( rPoly.count() );
+ if( numVertices )
+ drawPolygon_i( rPoly,
+ mpImpl->maLineClipRect,
+ lineColor, drawMode );
+}
+
+void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly,
+ Color lineColor,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+{
+ if( !rClip )
+ {
+ drawPolygon(rPoly,lineColor,drawMode);
+ return;
+ }
+
+ const sal_uInt32 numVertices( rPoly.count() );
+ if( numVertices )
+ {
+ if( isCompatibleClipMask( rClip ) )
+ drawPolygon_i( rPoly,
+ mpImpl->maLineClipRect,
+ lineColor, drawMode, rClip );
+ else
+ getGenericRenderer()->drawPolygon( rPoly, lineColor,
+ drawMode, rClip );
+ }
+}
+
+void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
+ Color fillColor,
+ DrawMode drawMode )
+{
+ fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
+}
+
+void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
+ Color fillColor,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+{
+ if( !rClip )
+ {
+ fillPolyPolygon(rPoly,fillColor,drawMode);
+ return;
+ }
+
+ if( isCompatibleClipMask( rClip ) )
+ fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
+ else
+ getGenericRenderer()->fillPolyPolygon( rPoly, fillColor,
+ drawMode, rClip );
+}
+
+
+namespace
+{
+ void assertImagePoint( const basegfx::B2IPoint& rPt,
+ const basegfx::B2IRange& rPermittedRange )
+ {
+ (void)rPt; (void)rPermittedRange;
+ OSL_ASSERT( rPermittedRange.isInside(rPt) );
+ }
+
+ void assertImageRange( const basegfx::B2IRange& rRange,
+ const basegfx::B2IRange& rPermittedRange )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ basegfx::B2IRange aRange( rRange );
+ aRange.intersect( rPermittedRange );
+
+ OSL_ASSERT( aRange == rRange );
+#else
+ (void)rRange; (void)rPermittedRange;
+#endif
+ }
+
+ // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
+ // to basegfx, and use here!
+ bool clipAreaImpl( ::basegfx::B2IRange& io_rSourceArea,
+ ::basegfx::B2IPoint& io_rDestPoint,
+ const ::basegfx::B2IRange& rSourceBounds,
+ const ::basegfx::B2IRange& rDestBounds )
+ {
+ const ::basegfx::B2IPoint aSourceTopLeft(
+ io_rSourceArea.getMinimum() );
+
+ ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
+
+ // clip source area (which must be inside rSourceBounds)
+ aLocalSourceArea.intersect( rSourceBounds );
+
+ if( aLocalSourceArea.isEmpty() )
+ return false;
+
+ // calc relative new source area points (relative to orig
+ // source area)
+ const ::basegfx::B2IVector aUpperLeftOffset(
+ aLocalSourceArea.getMinimum()-aSourceTopLeft );
+ const ::basegfx::B2IVector aLowerRightOffset(
+ aLocalSourceArea.getMaximum()-aSourceTopLeft );
+
+ ::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
+ io_rDestPoint + aLowerRightOffset );
+
+ // clip dest area (which must be inside rDestBounds)
+ aLocalDestArea.intersect( rDestBounds );
+
+ if( aLocalDestArea.isEmpty() )
+ return false;
+
+ // calc relative new dest area points (relative to orig
+ // source area)
+ const ::basegfx::B2IVector aDestUpperLeftOffset(
+ aLocalDestArea.getMinimum()-io_rDestPoint );
+ const ::basegfx::B2IVector aDestLowerRightOffset(
+ aLocalDestArea.getMaximum()-io_rDestPoint );
+
+ io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
+ aSourceTopLeft + aDestLowerRightOffset );
+ io_rDestPoint = aLocalDestArea.getMinimum();
+
+ return true;
+ }
+
+ // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
+ // to basegfx, and use here!
+ bool clipAreaImpl( ::basegfx::B2IRange& io_rDestArea,
+ ::basegfx::B2IRange& io_rSourceArea,
+ const ::basegfx::B2IRange& rDestBounds,
+ const ::basegfx::B2IRange& rSourceBounds )
+ {
+ // extract inherent scale
+ const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() );
+ const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() );
+
+ // extract range origins
+ const basegfx::B2IPoint aDestTopLeft(
+ io_rDestArea.getMinimum() );
+ const ::basegfx::B2IPoint aSourceTopLeft(
+ io_rSourceArea.getMinimum() );
+
+ ::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
+
+ // clip source area (which must be inside rSourceBounds)
+ aLocalSourceArea.intersect( rSourceBounds );
+
+ if( aLocalSourceArea.isEmpty() )
+ return false;
+
+ // calc relative new source area points (relative to orig
+ // source area)
+ const ::basegfx::B2IVector aUpperLeftOffset(
+ aLocalSourceArea.getMinimum()-aSourceTopLeft );
+ const ::basegfx::B2IVector aLowerRightOffset(
+ aLocalSourceArea.getMaximum()-aSourceTopLeft );
+
+ ::basegfx::B2IRange aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
+ basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
+ basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
+ basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
+
+ // clip dest area (which must be inside rDestBounds)
+ aLocalDestArea.intersect( rDestBounds );
+
+ if( aLocalDestArea.isEmpty() )
+ return false;
+
+ // calc relative new dest area points (relative to orig
+ // source area)
+ const ::basegfx::B2IVector aDestUpperLeftOffset(
+ aLocalDestArea.getMinimum()-aDestTopLeft );
+ const ::basegfx::B2IVector aDestLowerRightOffset(
+ aLocalDestArea.getMaximum()-aDestTopLeft );
+
+ io_rSourceArea = ::basegfx::B2IRange( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
+ basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
+ basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
+ basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
+ io_rDestArea = aLocalDestArea;
+
+ // final source area clip (chopping round-offs)
+ io_rSourceArea.intersect( rSourceBounds );
+
+ if( io_rSourceArea.isEmpty() )
+ return false;
+
+
+ return true;
+ }
+}
+
+void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ DrawMode drawMode )
+{
+ const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
+ const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
+ basegfx::B2IRange aSrcRange( rSrcRect );
+ basegfx::B2IRange aDestRange( rDstRect );
+
+ if( clipAreaImpl( aDestRange,
+ aSrcRange,
+ mpImpl->maBounds,
+ aSrcBounds ))
+ {
+ assertImageRange(aDestRange,mpImpl->maBounds);
+ assertImageRange(aSrcRange,aSrcBounds);
+
+ drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode );
+ }
+}
+
+void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+{
+ if( !rClip )
+ {
+ drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
+ return;
+ }
+
+ const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
+ const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
+ basegfx::B2IRange aSrcRange( rSrcRect );
+ basegfx::B2IRange aDestRange( rDstRect );
+
+ if( clipAreaImpl( aDestRange,
+ aSrcRange,
+ mpImpl->maBounds,
+ aSrcBounds ))
+ {
+ assertImageRange(aDestRange,mpImpl->maBounds);
+ assertImageRange(aSrcRange,aSrcBounds);
+
+ if( isCompatibleClipMask( rClip ) )
+ {
+ drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip );
+ }
+ else
+ {
+ getGenericRenderer()->drawBitmap( rSrcBitmap, rSrcRect,
+ rDstRect, drawMode, rClip );
+ }
+ }
+}
+
+void BitmapDevice::drawMaskedColor( Color aSrcColor,
+ const BitmapDeviceSharedPtr& rAlphaMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IPoint& rDstPoint )
+{
+ const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
+ const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
+ basegfx::B2IRange aSrcRange( rSrcRect );
+ basegfx::B2IPoint aDestPoint( rDstPoint );
+
+ if( clipAreaImpl( aSrcRange,
+ aDestPoint,
+ aSrcBounds,
+ mpImpl->maBounds ))
+ {
+ assertImagePoint(aDestPoint,mpImpl->maBounds);
+ assertImageRange(aSrcRange,aSrcBounds);
+
+ if( rAlphaMask.get() == this )
+ {
+ // src == dest, copy rAlphaMask beforehand
+ // ---------------------------------------------------
+
+ const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
+ aSrcRange.getHeight() );
+ BitmapDeviceSharedPtr pAlphaCopy(
+ cloneBitmapDevice( aSize,
+ shared_from_this()) );
+ basegfx::B2ITuple aGcc3WorkaroundTemporary;
+ const basegfx::B2IRange aAlphaRange( aGcc3WorkaroundTemporary,
+ aSize );
+ pAlphaCopy->drawBitmap(rAlphaMask,
+ aSrcRange,
+ aAlphaRange,
+ DrawMode_PAINT);
+ drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint );
+ }
+ else
+ {
+ drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint );
+ }
+ }
+}
+
+void BitmapDevice::drawMaskedColor( Color aSrcColor,
+ const BitmapDeviceSharedPtr& rAlphaMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IPoint& rDstPoint,
+ const BitmapDeviceSharedPtr& rClip )
+{
+ if( !rClip )
+ {
+ drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
+ return;
+ }
+
+ const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
+ const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
+ basegfx::B2IRange aSrcRange( rSrcRect );
+ basegfx::B2IPoint aDestPoint( rDstPoint );
+
+ if( clipAreaImpl( aSrcRange,
+ aDestPoint,
+ aSrcBounds,
+ mpImpl->maBounds ))
+ {
+ assertImagePoint(aDestPoint,mpImpl->maBounds);
+ assertImageRange(aSrcRange,aSrcBounds);
+
+ if( isCompatibleClipMask( rClip ) )
+ {
+ if( rAlphaMask.get() == this )
+ {
+ // src == dest, copy rAlphaMask beforehand
+ // ---------------------------------------------------
+
+ const basegfx::B2ITuple aSize( aSrcRange.getWidth(),
+ aSrcRange.getHeight() );
+ BitmapDeviceSharedPtr pAlphaCopy(
+ cloneBitmapDevice( aSize,
+ shared_from_this()) );
+ basegfx::B2ITuple aGcc3WorkaroundTemporary;
+ const basegfx::B2IRange aAlphaRange( aGcc3WorkaroundTemporary,
+ aSize );
+ pAlphaCopy->drawBitmap(rAlphaMask,
+ aSrcRange,
+ aAlphaRange,
+ DrawMode_PAINT);
+ drawMaskedColor_i( aSrcColor, pAlphaCopy, aAlphaRange, aDestPoint, rClip );
+ }
+ else
+ {
+ drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
+ }
+ }
+ else
+ {
+ getGenericRenderer()->drawMaskedColor( aSrcColor, rAlphaMask,
+ rSrcRect, rDstPoint, rClip );
+ }
+ }
+}
+
+void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
+ const BitmapDeviceSharedPtr& rMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ DrawMode drawMode )
+{
+ OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
+
+ const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
+ const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
+ basegfx::B2IRange aSrcRange( rSrcRect );
+ basegfx::B2IRange aDestRange( rDstRect );
+
+ if( clipAreaImpl( aDestRange,
+ aSrcRange,
+ mpImpl->maBounds,
+ aSrcBounds ))
+ {
+ assertImageRange(aDestRange,mpImpl->maBounds);
+ assertImageRange(aSrcRange,aSrcBounds);
+
+ drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode );
+ }
+}
+
+void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
+ const BitmapDeviceSharedPtr& rMask,
+ const basegfx::B2IRange& rSrcRect,
+ const basegfx::B2IRange& rDstRect,
+ DrawMode drawMode,
+ const BitmapDeviceSharedPtr& rClip )
+{
+ if( !rClip )
+ {
+ drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
+ return;
+ }
+
+ OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
+
+ const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
+ const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
+ basegfx::B2IRange aSrcRange( rSrcRect );
+ basegfx::B2IRange aDestRange( rDstRect );
+
+ if( clipAreaImpl( aDestRange,
+ aSrcRange,
+ mpImpl->maBounds,
+ aSrcBounds ))
+ {
+ assertImageRange(aDestRange,mpImpl->maBounds);
+ assertImageRange(aSrcRange,aSrcBounds);
+
+ if( isCompatibleClipMask( rClip ) )
+ {
+ drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip );
+ }
+ else
+ {
+ getGenericRenderer()->drawMaskedBitmap( rSrcBitmap, rMask, rSrcRect,
+ rDstRect, drawMode, rClip );
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------------------
+
+/** Standard clip and alpha masks
+ */
+struct StdMasks
+{
+ typedef PixelFormatTraits_GREY1_MSB clipmask_format_traits;
+ typedef PixelFormatTraits_GREY8 alphamask_format_traits;
+
+ /// Clipmask: 0 means opaque
+ static const bool clipmask_polarity = false;
+
+ /// Alpha mask: 0 means fully transparent
+ static const bool alphamask_polarity = true;
+};
+
+#if 0
+/** Clip and alpha masks for the generic renderer (of course, those
+ need to be generic, too)
+ */
+struct MaskTraitsGeneric
+{
+ typedef PixelFormatTraits_GenericInteger clipmask_format_traits;
+ typedef PixelFormatTraits_GenericInteger alphamask_format_traits;
+};
+#endif
+
+//----------------------------------------------------------------------------------
+
+// Some compilers don't like the nested template wrap_accessor
+// reference in the parameter list - being slightly less type safe,
+// then.
+#ifndef BASEBMP_NO_NESTED_TEMPLATE_PARAMETER
+
+/// Produces a specialized renderer for the given pixel format
+template< class FormatTraits, class MaskTraits >
+BitmapDeviceSharedPtr createRenderer(
+ const basegfx::B2IRange& rBounds,
+ sal_Int32 nScanlineFormat,
+ sal_Int32 nScanlineStride,
+ sal_uInt8* pFirstScanline,
+ typename FormatTraits::raw_accessor_type const& rRawAccessor,
+ typename FormatTraits::accessor_selector::template wrap_accessor<
+ typename FormatTraits::raw_accessor_type>::type const& rAccessor,
+ boost::shared_array< sal_uInt8 > pMem,
+ const PaletteMemorySharedVector& pPal )
+
+#else
+
+template< class FormatTraits, class MaskTraits, class Accessor >
+BitmapDeviceSharedPtr createRenderer(
+ const basegfx::B2IRange& rBounds,
+ sal_Int32 nScanlineFormat,
+ sal_Int32 nScanlineStride,
+ sal_uInt8* pFirstScanline,
+ typename FormatTraits::raw_accessor_type const& rRawAccessor,
+ Accessor const& rAccessor,
+ boost::shared_array< sal_uInt8 > pMem,
+ const PaletteMemorySharedVector& pPal )
+
+#endif
+{
+ typedef typename FormatTraits::iterator_type Iterator;
+ typedef BitmapRenderer< Iterator,
+ typename FormatTraits::raw_accessor_type,
+ typename FormatTraits::accessor_selector,
+ MaskTraits > Renderer;
+
+ return BitmapDeviceSharedPtr(
+ new Renderer( rBounds,
+ nScanlineFormat,
+ nScanlineStride,
+ pFirstScanline,
+ Iterator(
+ reinterpret_cast<typename Iterator::value_type*>(
+ pFirstScanline),
+ nScanlineStride),
+ rRawAccessor,
+ rAccessor,
+ pMem,
+ pPal ));
+}
+
+/// Create standard grey level palette
+PaletteMemorySharedVector createStandardPalette(
+ const PaletteMemorySharedVector& pPal,
+ sal_Int32 nNumEntries )
+{
+ if( pPal || nNumEntries <= 0 )
+ return pPal;
+
+ boost::shared_ptr< std::vector<Color> > pLocalPal(
+ new std::vector<Color>(nNumEntries) );
+
+ const sal_Int32 nIncrement( 0x00FFFFFF/nNumEntries );
+ --nNumEntries;
+ for( sal_Int32 i=0, c=0; i<nNumEntries; ++i,c+=nIncrement )
+ pLocalPal->at(i) = Color(0xFF000000 | c);
+
+ pLocalPal->at(nNumEntries) = Color(0xFFFFFFFF);
+
+ return pLocalPal;
+}
+
+template< class FormatTraits, class MaskTraits >
+BitmapDeviceSharedPtr createRenderer(
+ const basegfx::B2IRange& rBounds,
+ sal_Int32 nScanlineFormat,
+ sal_Int32 nScanlineStride,
+ sal_uInt8* pFirstScanline,
+ boost::shared_array< sal_uInt8 > pMem,
+ const PaletteMemorySharedVector& pPal )
+{
+ return createRenderer<FormatTraits,
+ MaskTraits>(rBounds,
+ nScanlineFormat,
+ nScanlineStride,
+ pFirstScanline,
+ typename FormatTraits::raw_accessor_type(),
+ typename FormatTraits::accessor_selector::template
+ wrap_accessor<
+ typename FormatTraits::raw_accessor_type>::type(),
+ pMem,
+ pPal);
+}
+
+template< class FormatTraits, class MaskTraits >
+BitmapDeviceSharedPtr createRenderer(
+ const basegfx::B2IRange& rBounds,
+ sal_Int32 nScanlineFormat,
+ sal_Int32 nScanlineStride,
+ sal_uInt8* pFirstScanline,
+ boost::shared_array< sal_uInt8 > pMem,
+ PaletteMemorySharedVector pPal,
+ int nBitsPerPixel )
+{
+ pPal = createStandardPalette(pPal,
+ 1UL << nBitsPerPixel);
+
+ OSL_ASSERT(pPal);
+ return createRenderer<FormatTraits,
+ MaskTraits>(rBounds,
+ nScanlineFormat,
+ nScanlineStride,
+ pFirstScanline,
+ typename FormatTraits::raw_accessor_type(),
+ typename FormatTraits::accessor_selector::template
+ wrap_accessor<
+ typename FormatTraits::raw_accessor_type>::type(
+ &pPal->at(0),
+ pPal->size()),
+ pMem,
+ pPal);
+}
+
+//----------------------------------------------------------------------------------
+
+// TODO(Q3): consolidate with canvas/canvastools.hxx! Best move this
+// to o3tl or sal/bithacks.hxx ...
+
+/** Compute the next highest power of 2 of a 32-bit value
+
+ Code devised by Sean Anderson, in good ole HAKMEM
+ tradition.
+
+ @return 1 << (lg(x - 1) + 1)
+*/
+inline sal_uInt32 nextPow2( sal_uInt32 x )
+{
+ --x;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ x |= x >> 16;
+
+ return ++x;
+}
+
+//----------------------------------------------------------------------------------
+
+namespace
+{
+BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize,
+ bool bTopDown,
+ sal_Int32 nScanlineFormat,
+ boost::shared_array< sal_uInt8 > pMem,
+ PaletteMemorySharedVector pPal,
+ const basegfx::B2IRange* pSubset )
+{
+ if( nScanlineFormat <= Format::NONE ||
+ nScanlineFormat > Format::MAX )
+ return BitmapDeviceSharedPtr();
+
+ static const sal_uInt8 bitsPerPixel[] =
+ {
+ 0, // NONE
+ 1, // ONE_BIT_MSB_GREY
+ 1, // ONE_BIT_LSB_GREY
+ 1, // ONE_BIT_MSB_PAL
+ 1, // ONE_BIT_LSB_PAL
+ 4, // FOUR_BIT_MSB_GREY
+ 4, // FOUR_BIT_LSB_GREY
+ 4, // FOUR_BIT_MSB_PAL
+ 4, // FOUR_BIT_LSB_PAL
+ 8, // EIGHT_BIT_PAL
+ 8, // EIGHT_BIT_GREY
+ 16, // SIXTEEN_BIT_LSB_TC_MASK
+ 16, // SIXTEEN_BIT_MSB_TC_MASK
+ 24, // TWENTYFOUR_BIT_TC_MASK
+ 32, // THIRTYTWO_BIT_TC_MASK
+ 32, // THIRTYTWO_BIT_TC_MASK_ARGB
+ };
+
+ sal_Int32 nScanlineStride(0);
+
+ // round up to full 8 bit, divide by 8
+ nScanlineStride = (rSize.getX()*bitsPerPixel[nScanlineFormat] + 7) >> 3;
+
+ // rounded up to next full power-of-two number of bytes
+ const sal_uInt32 bytesPerPixel = nextPow2(
+ (bitsPerPixel[nScanlineFormat] + 7) >> 3);
+
+ // now make nScanlineStride a multiple of bytesPerPixel
+ nScanlineStride = (nScanlineStride + bytesPerPixel - 1) / bytesPerPixel * bytesPerPixel;
+
+ // factor in bottom-up scanline order case
+ nScanlineStride *= bTopDown ? 1 : -1;
+
+ const std::size_t nMemSize(
+ (nScanlineStride < 0 ? -nScanlineStride : nScanlineStride)*rSize.getY() );
+
+ if( !pMem )
+ {
+ pMem.reset(
+ reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
+ &rtl_freeMemory );
+ rtl_zeroMemory(pMem.get(),nMemSize);
+ }
+
+ sal_uInt8* pFirstScanline = nScanlineStride < 0 ?
+ pMem.get() + nMemSize + nScanlineStride : pMem.get();
+
+ // shrink render area to given subset, if given
+ basegfx::B2IRange aBounds(0,0,rSize.getX(),rSize.getY());
+ if( pSubset )
+ aBounds.intersect( *pSubset );
+
+ switch( nScanlineFormat )
+ {
+ // ----------------------------------------------------------------------
+ // one bit formats
+
+ case Format::ONE_BIT_MSB_GREY:
+ return createRenderer<PixelFormatTraits_GREY1_MSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+ case Format::ONE_BIT_LSB_GREY:
+ return createRenderer<PixelFormatTraits_GREY1_LSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+ case Format::ONE_BIT_MSB_PAL:
+ return createRenderer<PixelFormatTraits_PAL1_MSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal,
+ bitsPerPixel[nScanlineFormat] );
+
+ case Format::ONE_BIT_LSB_PAL:
+ return createRenderer<PixelFormatTraits_PAL1_LSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal,
+ bitsPerPixel[nScanlineFormat] );
+
+
+ // ----------------------------------------------------------------------
+ // four bit formats
+
+ case Format::FOUR_BIT_MSB_GREY:
+ return createRenderer<PixelFormatTraits_GREY4_MSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+ case Format::FOUR_BIT_LSB_GREY:
+ return createRenderer<PixelFormatTraits_GREY4_LSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+ case Format::FOUR_BIT_MSB_PAL:
+ return createRenderer<PixelFormatTraits_PAL4_MSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal,
+ bitsPerPixel[nScanlineFormat] );
+
+ case Format::FOUR_BIT_LSB_PAL:
+ return createRenderer<PixelFormatTraits_PAL4_LSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal,
+ bitsPerPixel[nScanlineFormat] );
+
+
+ // ----------------------------------------------------------------------
+ // eight bit formats
+
+ case Format::EIGHT_BIT_GREY:
+ return createRenderer<PixelFormatTraits_GREY8,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+ case Format::EIGHT_BIT_PAL:
+ return createRenderer<PixelFormatTraits_PAL8,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal,
+ bitsPerPixel[nScanlineFormat] );
+
+
+ // ----------------------------------------------------------------------
+ // sixteen bit formats
+
+ case Format::SIXTEEN_BIT_LSB_TC_MASK:
+ return createRenderer<PixelFormatTraits_RGB16_565_LSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+ case Format::SIXTEEN_BIT_MSB_TC_MASK:
+ return createRenderer<PixelFormatTraits_RGB16_565_MSB,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+
+ // ----------------------------------------------------------------------
+ // twentyfour bit formats
+ case Format::TWENTYFOUR_BIT_TC_MASK:
+ return createRenderer<PixelFormatTraits_BGR24,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+
+ // ----------------------------------------------------------------------
+ // thirtytwo bit formats
+
+ case Format::THIRTYTWO_BIT_TC_MASK:
+ return createRenderer<PixelFormatTraits_RGB32_888,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+
+ case Format::THIRTYTWO_BIT_TC_MASK_ARGB:
+ return createRenderer<PixelFormatTraits_BGR32_888,StdMasks>(
+ aBounds, nScanlineFormat, nScanlineStride,
+ pFirstScanline, pMem, pPal );
+ }
+
+ // TODO(F3): other formats not yet implemented
+ return BitmapDeviceSharedPtr();
+}
+} // namespace
+
+
+BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
+ bool bTopDown,
+ sal_Int32 nScanlineFormat )
+{
+ return createBitmapDeviceImpl( rSize,
+ bTopDown,
+ nScanlineFormat,
+ boost::shared_array< sal_uInt8 >(),
+ PaletteMemorySharedVector(),
+ NULL );
+}
+
+BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
+ bool bTopDown,
+ sal_Int32 nScanlineFormat,
+ const PaletteMemorySharedVector& rPalette )
+{
+ return createBitmapDeviceImpl( rSize,
+ bTopDown,
+ nScanlineFormat,
+ boost::shared_array< sal_uInt8 >(),
+ rPalette,
+ NULL );
+}
+
+BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
+ bool bTopDown,
+ sal_Int32 nScanlineFormat,
+ const RawMemorySharedArray& rMem,
+ const PaletteMemorySharedVector& rPalette )
+{
+ return createBitmapDeviceImpl( rSize,
+ bTopDown,
+ nScanlineFormat,
+ rMem,
+ rPalette,
+ NULL );
+}
+
+BitmapDeviceSharedPtr subsetBitmapDevice( const BitmapDeviceSharedPtr& rProto,
+ const basegfx::B2IRange& rSubset )
+{
+ return createBitmapDeviceImpl( rProto->getSize(),
+ rProto->isTopDown(),
+ rProto->getScanlineFormat(),
+ rProto->getBuffer(),
+ rProto->getPalette(),
+ &rSubset );
+}
+
+BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize,
+ const BitmapDeviceSharedPtr& rProto )
+{
+ return createBitmapDeviceImpl( rSize,
+ rProto->isTopDown(),
+ rProto->getScanlineFormat(),
+ boost::shared_array< sal_uInt8 >(),
+ rProto->getPalette(),
+ NULL );
+}
+
+//----------------------------------------------------------------------------------
+
+/// Clone our device, with GenericImageAccessor to handle all formats
+BitmapDeviceSharedPtr BitmapDevice::getGenericRenderer() const
+{
+#if 0
+ // xxx TODO
+ typedef BitmapRenderer< PixelFormatTraits_GenericInteger::iterator_type,
+ PixelFormatTraits_GenericInteger::raw_accessor_type,
+ PixelFormatTraits_GenericInteger::accessor_selector,
+ MaskTraitsGeneric >
+ Renderer;
+
+ if( !mpImpl->mpGenericRenderer )
+ {
+ mpImpl->mpGenericRenderer.reset(
+ new Renderer(
+ mpImpl->maBounds,
+ isTopDown(),
+ getScanlineFormat(),
+ getScanlineStride(),
+ mpImpl->mpFirstScanline,
+ PixelFormatTraits_GenericInteger::iterator_type(),
+ GenericIntegerImageRawAccessor<Color>(
+ const_cast<BitmapDevice*>(this)->shared_from_this()),
+ GenericIntegerImageAccessor<Color>(
+ const_cast<BitmapDevice*>(this)->shared_from_this()),
+ getBuffer(),
+ getPalette() ));
+ }
+#endif
+
+ return mpImpl->mpGenericRenderer;
+}
+
+} // namespace basebmp
diff --git a/basebmp/source/debug.cxx b/basebmp/source/debug.cxx
new file mode 100644
index 000000000000..7781e43c19bc
--- /dev/null
+++ b/basebmp/source/debug.cxx
@@ -0,0 +1,106 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <osl/diagnose.h>
+
+#include <basegfx/point/b2ipoint.hxx>
+#include <basegfx/vector/b2ivector.hxx>
+
+#include <basebmp/scanlineformats.hxx>
+#include <basebmp/color.hxx>
+#include <basebmp/bitmapdevice.hxx>
+#include <basebmp/debug.hxx>
+
+#include <iomanip>
+
+namespace basebmp
+{
+ namespace
+ {
+ static const char* getFormatString( sal_Int32 nScanlineFormat )
+ {
+ switch( nScanlineFormat )
+ {
+ case Format::ONE_BIT_MSB_GREY:
+ return "ONE_BIT_MSB_GREY";
+ case Format::ONE_BIT_LSB_GREY:
+ return "ONE_BIT_LSB_GREY";
+ case Format::ONE_BIT_MSB_PAL:
+ return "ONE_BIT_MSB_PAL";
+ case Format::ONE_BIT_LSB_PAL:
+ return "ONE_BIT_LSB_PAL";
+ case Format::FOUR_BIT_MSB_GREY:
+ return "FOUR_BIT_MSB_GREY";
+ case Format::FOUR_BIT_LSB_GREY:
+ return "FOUR_BIT_LSB_GREY";
+ case Format::FOUR_BIT_MSB_PAL:
+ return "FOUR_BIT_MSB_PAL";
+ case Format::FOUR_BIT_LSB_PAL:
+ return "FOUR_BIT_LSB_PAL";
+ case Format::EIGHT_BIT_PAL:
+ return "EIGHT_BIT_PAL";
+ case Format::EIGHT_BIT_GREY:
+ return "EIGHT_BIT_GREY";
+ case Format::SIXTEEN_BIT_LSB_TC_MASK:
+ return "SIXTEEN_BIT_LSB_TC_MASK";
+ case Format::SIXTEEN_BIT_MSB_TC_MASK:
+ return "SIXTEEN_BIT_MSB_TC_MASK";
+ case Format::TWENTYFOUR_BIT_TC_MASK:
+ return "TWENTYFOUR_BIT_TC_MASK";
+ case Format::THIRTYTWO_BIT_TC_MASK:
+ return "THIRTYTWO_BIT_TC_MASK";
+ default:
+ return "<unknown>";
+ }
+ }
+ }
+
+ void debugDump( const BitmapDeviceSharedPtr& rDevice,
+ std::ostream& rOutputStream )
+ {
+ const basegfx::B2IVector aSize( rDevice->getSize() );
+ const bool bTopDown( rDevice->isTopDown() );
+ const sal_Int32 nScanlineFormat( rDevice->getScanlineFormat() );
+
+ rOutputStream
+ << "/* basebmp::BitmapDevice content dump */" << std::endl
+ << "/* Width = " << aSize.getX() << " */" << std::endl
+ << "/* Height = " << aSize.getY() << " */" << std::endl
+ << "/* TopDown = " << bTopDown << " */" << std::endl
+ << "/* Format = " << getFormatString(nScanlineFormat) << " */" << std::endl
+ << "/* (dumped entries are already mapped RGBA color values) */" << std::endl
+ << std::endl;
+
+ rOutputStream << std::hex;
+ for( int y=0; y<aSize.getY(); ++y )
+ {
+ for( int x=0; x<aSize.getX(); ++x )
+ rOutputStream << std::setw(8) << (sal_uInt32)rDevice->getPixel( basegfx::B2IPoint(x,y) ).toInt32() << " ";
+ rOutputStream << std::endl;
+ }
+ }
+}
diff --git a/basebmp/source/intconversion.hxx b/basebmp/source/intconversion.hxx
new file mode 100644
index 000000000000..0fb7a0bf684a
--- /dev/null
+++ b/basebmp/source/intconversion.hxx
@@ -0,0 +1,88 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_BASEBMP_INTCONVERSION_HXX
+#define INCLUDED_BASEBMP_INTCONVERSION_HXX
+
+#include <vigra/rgbvalue.hxx>
+#include <functional>
+
+namespace basebmp
+{
+ // metafunctions to retrieve correct POD from/to basebmp::Color
+ //------------------------------------------------------------------------
+
+ /// type-safe conversion from RgbValue to packed int32
+ template< class RgbVal > struct UInt32FromRgbValue
+ {
+ sal_uInt32 operator()( RgbVal const& c ) const
+ {
+ return (c[0] << 16) | (c[1] << 8) | c[2];
+ }
+ };
+
+ /// type-safe conversion from packed int32 to RgbValue
+ template< class RgbVal > struct RgbValueFromUInt32
+ {
+ RgbVal operator()( sal_uInt32 c ) const
+ {
+ return RgbVal((c >> 16) & 0xFF,
+ (c >> 8) & 0xFF,
+ c & 0xFF);
+ }
+ };
+
+ /// Get converter from given data type to sal_uInt32
+ template< typename DataType > struct uInt32Converter
+ {
+ typedef std::identity<DataType> to;
+ typedef std::identity<DataType> from;
+ };
+ template< unsigned int RedIndex,
+ unsigned int GreenIndex,
+ unsigned int BlueIndex > struct uInt32Converter<
+ vigra::RGBValue< sal_uInt8,
+ RedIndex,
+ GreenIndex,
+ BlueIndex > >
+ {
+ typedef UInt32FromRgbValue<
+ vigra::RGBValue< sal_uInt8,
+ RedIndex,
+ GreenIndex,
+ BlueIndex > >
+ to;
+ typedef RgbValueFromUInt32<
+ vigra::RGBValue< sal_uInt8,
+ RedIndex,
+ GreenIndex,
+ BlueIndex > >
+ from;
+ };
+}
+
+#endif /* INCLUDED_BASEBMP_INTCONVERSION_HXX */
diff --git a/basebmp/source/makefile.mk b/basebmp/source/makefile.mk
new file mode 100644
index 000000000000..55b27cfa7565
--- /dev/null
+++ b/basebmp/source/makefile.mk
@@ -0,0 +1,76 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/
+
+PRJNAME=basebmp
+TARGET=wrapper
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+
+
+# TODO(F3) unify BASEBMP_NO_NESTED_TEMPLATE_PARAMETER and
+# VIGRA_WITHOUT_NESTED_TEMPLATES_PARAMS
+#
+# - VIGRA_WITHOUT_NESTED_TEMPLATES_PARAMS avoids template parameters
+# to templates - the template keyword is broken for SunCC
+# - VIGRA_HAS_LONG_LONG enables long long overloads (but appears to not work
+# reliably in some environments, and is thus not enabled)
+# - VIGRA_HAS_LONG_DOUBLE enables long double overloads
+
+.IF "$(OS)"!="WNT"
+CDEFS+= -DVIGRA_HAS_LONG_DOUBLE
+.ENDIF
+
+.IF "$(OS)"=="SOLARIS" && "$(COM)"!="GCC"
+CDEFS+= -DBASEBMP_NO_NESTED_TEMPLATE_PARAMETER -DVIGRA_WITHOUT_NESTED_TEMPLATE_PARAMS
+.ENDIF
+
+# SunStudio 12 (-m64 and -m32 modes): three test cases of the unit tests fail
+# if compiled with default -xalias_level (and optimization level -xO3)
+.IF "$(OS)"=="SOLARIS"
+# For Sun Studio 8 this switch does not work: compilation fails on bitmapdevice.cxx
+.IF "$(CCNUMVER)"!="00050005"
+CDEFS+=-xalias_level=compatible
+.ENDIF
+.ENDIF
+
+# --- Common ----------------------------------------------------------
+
+SLOFILES = \
+ $(SLO)$/bitmapdevice.obj \
+ $(SLO)$/debug.obj \
+ $(SLO)$/polypolygonrenderer.obj
+
+# $(SLO)$/genericintegerimageaccessor.obj \
+
+# ==========================================================================
+
+.INCLUDE : target.mk
diff --git a/basebmp/source/polypolygonrenderer.cxx b/basebmp/source/polypolygonrenderer.cxx
new file mode 100644
index 000000000000..79453402ef4c
--- /dev/null
+++ b/basebmp/source/polypolygonrenderer.cxx
@@ -0,0 +1,127 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "basebmp/polypolygonrenderer.hxx"
+
+#include <algorithm>
+
+
+namespace basebmp
+{
+namespace detail
+{
+ sal_uInt32 setupGlobalEdgeTable( VectorOfVectorOfVertices& rGET,
+ basegfx::B2DPolyPolygon const& rPolyPoly,
+ sal_Int32 nMinY )
+ {
+ sal_Int32 const nNumScanlines( (sal_Int32)rGET.size() );
+
+ // add all polygons to GET
+ for( sal_uInt32 i(0), nCount(rPolyPoly.count());
+ i<nCount;
+ ++i )
+ {
+ // add all vertices to GET
+ const basegfx::B2DPolygon& rPoly( rPolyPoly.getB2DPolygon(i) );
+ for( sal_uInt32 k(0), nVertices(rPoly.count());
+ k<nVertices;
+ ++k )
+ {
+ const basegfx::B2DPoint& rP1( rPoly.getB2DPoint(k) );
+ const basegfx::B2DPoint& rP2( rPoly.getB2DPoint( (k + 1) % nVertices ) );
+
+ const sal_Int32 nVertexYP1( basegfx::fround(rP1.getY()) );
+ const sal_Int32 nVertexYP2( basegfx::fround(rP2.getY()) );
+
+ // insert only vertices which are not strictly
+ // horizontal. Strictly horizontal vertices don't add
+ // any information that is not already present - due
+ // to their adjacent vertices.
+ if(nVertexYP1 != nVertexYP2)
+ {
+ if( nVertexYP2 < nVertexYP1 )
+ {
+ const sal_Int32 nStartScanline(nVertexYP2 - nMinY);
+
+ // edge direction is upwards - add with swapped vertices
+ if( nStartScanline < nNumScanlines )
+ rGET[ nStartScanline ].push_back( Vertex(rP2, rP1, false) );
+ }
+ else
+ {
+ const sal_Int32 nStartScanline(nVertexYP1 - nMinY);
+
+ if( nStartScanline < nNumScanlines )
+ rGET[ nStartScanline ].push_back( Vertex(rP1, rP2, true) );
+ }
+ }
+ }
+ }
+
+ // now sort all scanlines individually, with increasing x
+ // coordinates
+ VectorOfVectorOfVertices::iterator aIter( rGET.begin() );
+ const VectorOfVectorOfVertices::iterator aEnd( rGET.end() );
+ sal_uInt32 nVertexCount(0);
+ RasterConvertVertexComparator aComp;
+ while( aIter != aEnd )
+ {
+ std::sort( aIter->begin(),
+ aIter->end(),
+ aComp );
+ nVertexCount += aIter->size();
+
+ ++aIter;
+ }
+
+ return nVertexCount;
+ }
+
+ void sortAET( VectorOfVertexPtr& rAETSrc,
+ VectorOfVertexPtr& rAETDest )
+ {
+ static RasterConvertVertexComparator aComp;
+
+ rAETDest.clear();
+
+ // prune AET from ended edges
+ VectorOfVertexPtr::iterator iter( rAETSrc.begin() );
+ VectorOfVertexPtr::iterator const end( rAETSrc.end() );
+ while( iter != end )
+ {
+ if( (*iter)->mnYCounter > 0 )
+ rAETDest.push_back( *iter );
+ ++iter;
+ }
+
+ // stable sort is necessary, to avoid segment crossing where
+ // none was intended.
+ std::stable_sort( rAETDest.begin(), rAETDest.end(), aComp );
+ }
+
+} // namespace detail
+} // namespace basebmp