diff options
author | Thorsten Behrens <thb@openoffice.org> | 2006-05-31 08:49:45 +0000 |
---|---|---|
committer | Thorsten Behrens <thb@openoffice.org> | 2006-05-31 08:49:45 +0000 |
commit | ef0bbaaf42d5d1784ab158d1b6b0535459702823 (patch) | |
tree | 89fa01c3069b3fc4f3afbe8850b001c755b8e787 /basebmp | |
parent | c16e3ab6fba4dc9a7217c97b198a801dcca94ee0 (diff) |
#i65904# Initial revision
Diffstat (limited to 'basebmp')
27 files changed, 6078 insertions, 0 deletions
diff --git a/basebmp/inc/basebmp/accessor.hxx b/basebmp/inc/basebmp/accessor.hxx new file mode 100644 index 000000000000..2718ad1bf5e9 --- /dev/null +++ b/basebmp/inc/basebmp/accessor.hxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: accessor.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:41 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_ACCESSOR_HXX +#define INCLUDED_BASEBMP_ACCESSOR_HXX + +namespace basebmp +{ + +template<typename ValueType> class StandardAccessor +{ +public: + typedef ValueType value_type; + typedef ValueType data_type; + + template< class Iterator > + value_type operator()(Iterator const& i) const { return i.get(); } + value_type operator()(value_type const* i) const { return *i; } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return i.get(diff); + } + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + i.set( vigra::detail::RequiresExplicitCast<value_type>::cast(value) ); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + i.set( vigra::detail::RequiresExplicitCast<value_type>::cast(value), + diff ); + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_ACCESSOR_HXX */ diff --git a/basebmp/inc/basebmp/accessoradapters.hxx b/basebmp/inc/basebmp/accessoradapters.hxx new file mode 100644 index 000000000000..63c7e2ad25bc --- /dev/null +++ b/basebmp/inc/basebmp/accessoradapters.hxx @@ -0,0 +1,271 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: accessoradapters.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:41 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_ACCESSORADAPTERS_HXX +#define INCLUDED_BASEBMP_ACCESSORADAPTERS_HXX + +#include "metafunctions.hxx" +#include "packedpixeliterator.hxx" +#include "paletteimageaccessor.hxx" + +namespace basebmp +{ + +/** Interpose given accessor's set methods with a binary function, + taking both old and new value. + */ +template< class WrappedAccessor, typename Functor > class BinarySetterFunctionAccessorAdapter : + public WrappedAccessor +{ +private: + Functor maFunctor; + +public: + BinarySetterFunctionAccessorAdapter() : + WrappedAccessor(), + maFunctor() + {} + + explicit BinarySetterFunctionAccessorAdapter( WrappedAccessor accessor ) : + WrappedAccessor( accessor ), + maFunctor() + {} + + BinarySetterFunctionAccessorAdapter( WrappedAccessor accessor, + Functor functor ) : + WrappedAccessor( accessor ), + maFunctor( functor ) + {} + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + WrappedAccessor::set( + maFunctor(WrappedAccessor::operator()(i), + value), + i ); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + WrappedAccessor::set( + maFunctor(WrappedAccessor::operator()(i,diff), + value), + i, + diff ); + } +}; + +/** Read from two input iterators, pipe that through given functor, and write result + to the first iterator + + Note: iterator type is fixed, to facilitate type-safe mask + optimizations (see below) + */ +template< class WrappedAccessor1, + class WrappedAccessor2, + class Iterator1, + class Iterator2, + typename Functor > class BinaryInputAccessorAdapter +{ +private: + WrappedAccessor1 ma1stAccessor; + WrappedAccessor2 ma2ndAccessor; + Functor maFunctor; + +public: + typedef typename WrappedAccessor1::value_type value_type; + + BinaryInputAccessorAdapter() : + ma1stAccessor(), + ma2ndAccessor(), + maFunctor() + {} + + explicit BinaryInputAccessorAdapter( WrappedAccessor1 accessor1 ) : + ma1stAccessor( accessor1 ), + ma2ndAccessor(), + maFunctor() + {} + + BinaryInputAccessorAdapter( WrappedAccessor1 accessor1, + WrappedAccessor2 accessor2 ) : + ma1stAccessor( accessor1 ), + ma2ndAccessor( accessor2 ), + maFunctor() + {} + + BinaryInputAccessorAdapter( WrappedAccessor1 accessor1, + WrappedAccessor2 accessor2, + Functor func ) : + ma1stAccessor( accessor1 ), + ma2ndAccessor( accessor2 ), + maFunctor( func ) + {} + + value_type operator()(Iterator1 const& i, Iterator2 const& j) const + { + return maFunctor(ma1stAccessor(i), + ma2ndAccessor(j)); + } + template< class Difference > + value_type operator()(Iterator1 const& i, Iterator2 const& j, Difference const& diff) const + { + return maFunctor(ma1stAccessor(i,diff), + ma2ndAccessor(j,diff)); + } + + template< typename V > + void set(V const& value, Iterator1 const& i, Iterator2 const& j) const + { + ma1stAccessor.set( + maFunctor(ma1stAccessor(i), + ma2ndAccessor(j)), + i ); + } + + template< typename V, class Difference > + void set(V const& value, Iterator1 const& i, Iterator2 const& j, Difference const& diff) const + { + ma1stAccessor.set( + maFunctor(ma1stAccessor(i,diff), + ma2ndAccessor(j,diff)), + i, + diff ); + } +}; + +// Some common accessor wrappers +// ------------------------------------------------------------ + +// XOR +template< typename T > struct XorFunctor +{ + T operator()( T v1, T v2 ) const { return v1 ^ v2; } +}; +template< class WrappedAccessor > struct xorAccessor +{ + typedef BinarySetterFunctionAccessorAdapter< WrappedAccessor, + XorFunctor< typename WrappedAccessor::value_type > > + type; +}; + +// Mask +template< typename T > struct MaskFunctor +{ + /** Mask v with state of m + + @return v, if m != 0, and vigra::NumericTraits<T>::zero + otherwise. + */ + T operator()( T v, T m ) const + { + // TODO(Q3): use traits to get unsigned type for T (if + // not already) + + // mask will be 0, iff m == 0, and 1 otherwise + const T mask( static_cast<unsigned int>(m | -m) >> (sizeof(unsigned int)*8 - 1) ); + return mask*v; + } +}; +// Faster mask (assuming mask accessor output is already either 0 or 1) +template< typename T > struct FastMaskFunctor +{ + T operator()( T v, T m ) const + { + return m*v; + } +}; +// Chosen function crucially depends on iterator - we can choose the +// faster direkt masking for 1bpp packed pixel iterators +template< class WrappedAccessor, + class MaskAccessor, + class Iterator, + class MaskIterator > struct maskedAccessor +{ + typedef BinaryInputAccessorAdapter< WrappedAccessor, + MaskAccessor, + Iterator, + MaskIterator, + MaskFunctor< typename WrappedAccessor::value_type > > + type; +}; +// partial specialization, to use fast 1bpp mask function for +// corresponding iterator type +template< class WrappedAccessor, + class MaskAccessor, + class Iterator > struct maskedAccessor< WrappedAccessor, + MaskAccessor, + Iterator, + PackedPixelIterator< typename MaskAccessor::data_type, + typename MaskAccessor::value_type, + 1, + true > > +{ + typedef BinaryInputAccessorAdapter< WrappedAccessor, + MaskAccessor, + Iterator, + PackedPixelIterator< typename MaskAccessor::data_type, + typename MaskAccessor::value_type, + 1, + true >, + FastMaskFunctor< typename WrappedAccessor::value_type > > + type; +}; +template< class WrappedAccessor, + class MaskAccessor, + class Iterator > struct maskedAccessor< WrappedAccessor, + MaskAccessor, + Iterator, + PackedPixelIterator< typename MaskAccessor::data_type, + typename MaskAccessor::value_type, + 1, + false > > +{ + typedef BinaryInputAccessorAdapter< WrappedAccessor, + MaskAccessor, + Iterator, + PackedPixelIterator< typename MaskAccessor::data_type, + typename MaskAccessor::value_type, + 1, + false >, + FastMaskFunctor< typename WrappedAccessor::value_type > > + type; +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_ACCESSORADAPTERS_HXX */ diff --git a/basebmp/inc/basebmp/bitmapdevice.hxx b/basebmp/inc/basebmp/bitmapdevice.hxx new file mode 100644 index 000000000000..3fd6401a6be6 --- /dev/null +++ b/basebmp/inc/basebmp/bitmapdevice.hxx @@ -0,0 +1,381 @@ +/************************************************************************* + * + * $RCSfile: bitmapdevice.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:41 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_BITMAPDEVICE_HXX +#define INCLUDED_BASEBMP_BITMAPDEVICE_HXX + +#ifndef _SAL_TYPES_H_ +#include <sal/types.h> +#endif +#ifndef INCLUDED_BASEBMP_DRAWMODES_HXX +#include "drawmodes.hxx" +#endif + +#include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + + +/* What to do first: + + 1,8,24 bpp, with blt, fill/drawPolygon, drawLine & get/setPixel + + Then: + + all other formats, top down vs. bottom up + + Last: + + Modulation, clip + + */ + +namespace basegfx +{ + class B2IPoint; + class B2DPoint; + class B2IVector; + class B2IRange; + class B2DPolygon; + class B2DPolyPolygon; +} + +namespace basebmp +{ + +// Temporary. Use like the tools color object +class Color; +typedef boost::shared_ptr< class BitmapDevice > BitmapDeviceSharedPtr; +typedef boost::shared_ptr< sal_uInt8 > RawMemorySharedPtr; + +struct ImplBitmapDevice; + +/** Definition of BitmapDevice interface + + Use createBitmapDevice() factory method to create one instance. + + Implementation note: the clip mask and bitmap parameter instances + of BitmapDevice that are passed to individual BitmapDevice + instances work best with 1 bit MSB masks for the clip and a format + matching that of the target BitmapDevice for the other + parameters. Everything else is accepted, but potentially slow. + */ +class BitmapDevice : private boost::noncopyable +{ +public: + /** Query size of device in pixel + */ + basegfx::B2IVector getSize() const; + + /** Query whether buffer starts with 0th scanline + + @return true, if the buffer memory starts with the 0th + scanline, and false if it starts with the last + */ + bool isTopDown() const; + + /** Query type of scanline memory format + */ + sal_Int32 getScanlineFormat() const; + + /** Query byte offset to get from scanline n to scanline n+1 + + @return the scanline stride in bytes. In the case of + bottom-first formats, this offset will be negative. + */ + sal_Int32 getScanlineStride() const; + + /** Get pointer to frame buffer + */ + RawMemorySharedPtr getBuffer() const; + + /** Get pointer to palette + + @return pointer to array of getPaletteEntryCount() Color + entries, if this is a palette format. If not, NULL is + returned. + */ + const Color* getPalette() const; + + /** Query number of palette entries + */ + const sal_Int32 getPaletteEntryCount() const; + + /** Clear whole device with given color + */ + void clear( Color fillColor ); + + /** Set given pixel to specified color + + @param rPt + Pixel to set + + @param pixelColor + Color value to set the pixel to + + @param drawMode + Draw mode to use when changing the pixel value + */ + void setPixel( const basegfx::B2IPoint& rPt, + Color pixelColor, + DrawMode drawMode ); + + /** Set given pixel to specified color + + @param rPt + Pixel to set + + @param pixelColor + Color value to set the pixel to + + @param drawMode + Draw mode to use when changing the pixel value + + @param rClip + Clip mask to use. If the clip mask is 0 at the given pixel + position, no change will happen. + */ + void setPixel( const basegfx::B2IPoint& rPt, + Color pixelColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + /** Get color value at given pixel + */ + Color getPixel( const basegfx::B2IPoint& rPt ); + + /** Draw a line + + @param rPt1 + Start point of the line + + @param rPt2 + End point of the line. If the analytical line from rP1 to rPt2 + (with the actual pixel positions are assumed to be the center + of the pixel) is exactly in the middle between two pixel, this + method always selects the pixel closer to rPt1. + + @param lineColor + Color value to draw the line with + + @param drawMode + Draw mode to use when changing the pixel value + */ + void drawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + Color lineColor, + DrawMode drawMode ); + + /** Draw a line + + @param rPt1 + Start point of the line + + @param rPt2 + End point of the line. If the analytical line from rP1 to rPt2 + (with the actual pixel positions are assumed to be the center + of the pixel) is exactly in the middle between two pixel, this + method always selects the pixel closer to rPt1. + + @param lineColor + Color value to draw the line with + + @param drawMode + Draw mode to use when changing the pixel value + + @param rClip + Clip mask to use. Pixel where the corresponding clip mask + pixel is 0 will not be touched. + */ + void drawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + void drawPolygon( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode ); + void drawPolygon( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + void fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode ); + void fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + void drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ); + void drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + + void drawMaskedColor( Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint ); + void drawMaskedColor( Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint, + const BitmapDeviceSharedPtr& rClip ); + + void drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ); + void drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ); + +protected: + BitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + const RawMemorySharedPtr& rMem ); + + virtual ~BitmapDevice(); + +private: + virtual bool isCompatibleBitmap( const BitmapDeviceSharedPtr& bmp ) const = 0; + virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const = 0; + virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const = 0; + + virtual const Color* getPalette_i() const = 0; + virtual const sal_Int32 getPaletteEntryCount_i() const = 0; + + virtual void clear_i( Color fillColor ) = 0; + + virtual void setPixel_i( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode ) = 0; + virtual void setPixel_i( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + virtual Color getPixel_i( const basegfx::B2IPoint& rPt ) = 0; + + virtual void drawLine_i( const basegfx::B2DPoint& rPt1, + const basegfx::B2DPoint& rPt2, + Color lineColor, + DrawMode drawMode ) = 0; + virtual void drawLine_i( const basegfx::B2DPoint& rPt1, + const basegfx::B2DPoint& rPt2, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + virtual void drawPolygon_i( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode ) = 0; + virtual void drawPolygon_i( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + virtual void fillPolyPolygon_i( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const basegfx::B2IRange& rBounds ) = 0; + virtual void fillPolyPolygon_i( const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const basegfx::B2IRange& rBounds, + const BitmapDeviceSharedPtr& rClip ) = 0; + + // must work with *this == rSrcBitmap! + virtual void drawBitmap_i( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) = 0; + virtual void drawBitmap_i( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + // must work with *this == rSrcBitmap! + virtual void drawMaskedColor_i( Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint ) = 0; + virtual void drawMaskedColor_i( Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint, + const BitmapDeviceSharedPtr& rClip ) = 0; + + // must work with *this == rSrcBitmap! + virtual void drawMaskedBitmap_i( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) = 0; + virtual void drawMaskedBitmap_i( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) = 0; + + boost::scoped_ptr< ImplBitmapDevice > mpImpl; +}; + +/** Factory method to create a BitmapDevice for given scanline format + */ +BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat ); + +} + +#endif /* INCLUDED_BASEBMP_BITMAPDEVICE_HXX */ diff --git a/basebmp/inc/basebmp/clippedlinerenderer.hxx b/basebmp/inc/basebmp/clippedlinerenderer.hxx new file mode 100644 index 000000000000..92be0308a5c7 --- /dev/null +++ b/basebmp/inc/basebmp/clippedlinerenderer.hxx @@ -0,0 +1,370 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: clippedlinerenderer.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:41 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_CLIPPEDLINERENDERER_HXX +#define INCLUDED_BASEBMP_CLIPPEDLINERENDERER_HXX + +#include <basegfx/tools/rectcliptools.hxx> + +namespace basebmp +{ + +// factored-out bresenham setup code, which is used from two different +// places in renderClippedLine() below. Admittedly messy for the long +// parameter list... +inline bool prepareClip( sal_Int32 a1, + sal_Int32 a2, + sal_Int32 b1, + sal_Int32 da, + sal_Int32 db, + sal_Int32& o_as, + sal_Int32& o_bs, + int sa, + int sb, + sal_Int32& io_rem, + int& o_n, + sal_uInt32 clipCode1, + sal_uInt32 clipCount1, + sal_uInt32 clipCode2, + sal_uInt32 clipCount2, + sal_Int32 aMin, + sal_uInt32 aMinFlag, + sal_Int32 aMax, + sal_uInt32 aMaxFlag, + sal_Int32 bMin, + sal_uInt32 bMinFlag, + sal_Int32 bMax, + sal_uInt32 bMaxFlag, + bool bRoundTowardsPt2 ) +{ + int ca, cb; + if( clipCode1 ) + { + if( clipCode1 & aMinFlag ) + { + ca = 2*db*(aMin - a1); + o_as = aMin; + } + else if( clipCode1 & aMaxFlag ) + { + ca = 2*db*(a1 - aMax); + o_as = aMax; + } + + if( clipCode1 & bMinFlag ) + { + cb = 2*da*(bMin - b1); + o_bs = bMin; + } + else if( clipCode1 & bMaxFlag ) + { + cb = 2*da*(b1 - bMax); + o_bs = bMax; + } + + if( clipCount1 == 2 ) + clipCode1 &= (ca + da < cb + !bRoundTowardsPt2) ? ~(aMin|aMax) : ~(bMin|bMax); + + if( clipCode1 & (aMin|aMax) ) + { + cb = (ca + da - !bRoundTowardsPt2) / (2*da); + + if( sb >= 0 ) + { + o_bs = b1 + cb; + if( o_bs > bMax ) + return; + } + else + { + o_bs = b1 - cb; + if( o_bs < bMin ) + return; + } + + io_rem += ca - 2*da*cb; + } + else + { + ca = (cb - da + 2*db - bRoundTowardsPt2) / (2*db); + if( sa >= 0 ) + { + o_as = a1 + ca; + if( o_as > aMax ) + return; + } + else + { + o_as = a1 - ca; + if( o_as < aMin ) + return; + } + + io_rem += 2*db*ca - cb; + } + } + else + { + o_as = a1; o_bs = b1; + } + + bool bRetVal = false; + if( clipCode2 ) + { + if( clipCount2 == 2 ) + { + ca = 2*db*((clipCode2 & aMin) ? a1 - aMin : aMax - a1); + cb = 2*da*((clipCode2 & bMin) ? b1 - bMin : bMax - b1); + clipCode2 &= (cb + da < ca + bRoundTowardsPt2) ? ~(aMin|aMax) : ~(bMin|bMax); + } + + if( clipCode2 & (aMin|aMax) ) + o_n = (clipCode2 & aMin) ? o_as - aMin : aMax - o_as; + else + { + o_n = (clipCode2 & bMin) ? o_bs - bMin : bMax - o_bs; + bRetVal = true; + } + } + else + o_n = (a2 >= o_as) ? a2 - o_as : o_as - a2; + + return bRetVal; +} + + +/** Render line to image iterators, clip against given rectangle + + This method renders a line from aPt1 to aPt2, clipped against + rClipRect (the clipping will take place pixel-perfect, i.e. as if + the original bresenham-rendered line would have been clipped each + pixel individually. No slight shifts compared to unclipped lines). + + @param aPt1 + Start point of the line + + @param aPt2 + End point of the line + + @param rClipRect + Rectangle to clip against + + @param color + Color value to render the line with + + @param begin + left-top image iterator + + @param end + right-bottom image iterator + + @param acc + Image accessor + + @param bRoundTowardsPt2 + Rounding mode to use. Giving false here results in line pixel tend + towards pt1, i.e. when a pixel exactly hits the middle between two + pixel, the pixel closer to pt1 will be chosen. Giving true here + makes renderClippedLine() choose pt2 in those cases. + */ +template< class Iterator, class Accessor > +void renderClippedLine( basegfx::B2IPoint aPt1, + basegfx::B2IPoint aPt2, + const basegfx::B2IRange& rClipRect, + typename Accessor::value_type color, + Iterator begin, + Iterator end, + Accessor acc, + bool bRoundTowardsPt2=false ) +{ + // Algorithm according to Steven Eker's 'Pixel-perfect line clipping', + // Graphics Gems V, pp. 314-322 + sal_uInt32 clipCode1 = basegfx::tools::getCohenSutherlandClipFlags(aPt1, + rClipRect); + sal_uInt32 clipCode2 = basegfx::tools::getCohenSutherlandClipFlags(aPt2, + rClipRect); + + if( clipCode1 & clipCode2 ) + return; // line fully clipped away + + sal_uInt32 clipCount1 = basegfx::tools::getNumberOfClipPlanes(clipCode1); + sal_uInt32 clipCount2 = basegfx::tools::getNumberOfClipPlanes(clipCode2); + + if( (clipCode1 != 0 && clipCode2 == 0) + || (clipCount1 == 2 && clipCount2 == 1) ) + { + std::swap(clipCount2,clipCount1); + std::swap(clipCode2,clipCode1); + std::swap(aPt1,aPt2); + bRoundTowardsPt2 = !bRoundTowardsPt2; + } + + const sal_Int32 x1 = aPt1.getX(); + const sal_Int32 x2 = aPt2.getX(); + const sal_Int32 y1 = aPt1.getY(); + const sal_Int32 y2 = aPt2.getY(); + + // TODO(E1): This might overflow + sal_Int32 adx = x2 - x1; + int sx = 1; + if( adx < 0 ) + { + adx *= -1; + sx = -1; + } + + // TODO(E1): This might overflow + sal_Int32 ady = y2 - y1; + int sy = 1; + if( ady < 0 ) + { + ady *= -1; + sy = -1; + } + + int n = 0; + sal_Int32 xs = x1; + sal_Int32 ys = y1; + if( adx >= ady ) + { + // semi-horizontal line + sal_Int32 rem = 2*ady - adx - !bRoundTowardsPt2; + + const bool bUseAlternateBresenham( + prepareClip(x1, x2, y1, adx, ady, xs, ys, sx, sy, + rem, n, clipCode1, clipCount1, clipCode1, clipCount2, + rClipRect.getMinX(), basegfx::tools::RectClipFlags::LEFT, + rClipRect.getMaxX(), basegfx::tools::RectClipFlags::RIGHT, + rClipRect.getMinY(), basegfx::tools::RectClipFlags::TOP, + rClipRect.getMaxY(), basegfx::tools::RectClipFlags::BOTTOM, + bRoundTowardsPt2 )); + const sal_Int32 diff = 2*(ady - adx); + if( bUseAlternateBresenham ) + { + while(true) + { + plot(xs,ys); + + if( rem >= 0 ) + { + if( --n < 0 ) + break; + rem += diff; + ys += sy; + } + else + rem += 2*ady; + + xs += sx; + } + } + else + { + while(true) + { + plot(xs,ys); + + if( --n < 0 ) + break; + if( rem >= 0 ) + { + rem += diff; + ys += sy; + } + else + rem += 2*ady; + + xs += sx; + } + } + } + else + { + // semi-vertical line + sal_Int32 rem = 2*adx - ady - !bRoundTowardsPt2; + + const bool bUseAlternateBresenham( + prepareClip(y1, y2, x1, ady, adx, ys, xs, sy, sx, + rem, clipCode1, clipCount1, clipCode1, clipCount2, + rClipRect.getMinY(), basegfx::tools::RectClipFlags::TOP, + rClipRect.getMaxY(), basegfx::tools::RectClipFlags::BOTTOM, + rClipRect.getMinX(), basegfx::tools::RectClipFlags::LEFT, + rClipRect.getMaxX(), basegfx::tools::RectClipFlags::RIGHT, + bRoundTowardsPt2 )); + const sal_Int32 diff = 2*(ady - adx); + if( bUseAlternateBresenham ) + { + while(true) + { + plot(xy,ys); + + if( rem >= 0 ) + { + if( --n < 0 ) + break; + rem += diff; + xs += sx; + } + else + rem += 2*adx; + + ys += sy; + } + } + else + { + while(true) + { + plot(xs,ys); + + if( --n < 0 ) + break; + if( rem >= 0 ) + { + rem += diff; + xs += sx; + } + else + rem += 2*adx; + + ys += sy; + } + } + } +} + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_CLIPPEDLINERENDERER_HXX */ diff --git a/basebmp/inc/basebmp/color.hxx b/basebmp/inc/basebmp/color.hxx new file mode 100644 index 000000000000..21ae86e897dd --- /dev/null +++ b/basebmp/inc/basebmp/color.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: color.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:41 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_COLOR_HXX +#define INCLUDED_BASEBMP_COLOR_HXX + +#ifndef _SAL_TYPES_H_ +#include <sal/types.h> +#endif +#include <math.h> + +namespace basebmp +{ + +class Color +{ +private: + sal_uInt32 mnColor; + +public: + Color() : mnColor(0) {} + Color( sal_uInt32 nVal ) : mnColor(nVal) {} + Color( sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue ) : + mnColor( (nRed << 16) | (nGreen << 8) | nBlue ) + {} + + void setRed( sal_uInt8 nRed ) { mnColor |= nRed << 16; mnColor &= ~((sal_uInt32)nRed << 16); } + void setGreen( sal_uInt8 nGreen ) { mnColor |= nGreen << 8; mnColor &= ~((sal_uInt32)nGreen << 8); } + void setBlue( sal_uInt8 nBlue ) { mnColor |= nBlue; mnColor &= ~(sal_uInt32)nBlue; } + + sal_uInt8 getRed() const { return (mnColor & 0x00FF0000U) >> 16; } + sal_uInt8 getGreen() const { return (mnColor & 0x0000FF00U) >> 8; } + sal_uInt8 getBlue() const { return mnColor & 0x000000FFU; } + + sal_uInt32 getValue() const { return mnColor; } + operator sal_uInt32() const { return mnColor; } + + Color operator-( Color col ) const { return Color(getRed()-col.getRed(), + getGreen()-col.getGreen(), + getBlue()-col.getBlue()); } + double magnitude() const { return sqrt(getRed()*getRed() + + getGreen()*getGreen() + + getBlue()*getBlue()); } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_COLOR_HXX */ diff --git a/basebmp/inc/basebmp/debug.hxx b/basebmp/inc/basebmp/debug.hxx new file mode 100644 index 000000000000..62cc8eaeb646 --- /dev/null +++ b/basebmp/inc/basebmp/debug.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: debug.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:42 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_DEBUG_HXX +#define INCLUDED_BASEBMP_DEBUG_HXX + +#include <iostream> +#include <boost/shared_ptr.hpp> + +namespace basebmp +{ + class BitmapDevice; + + /** Dump content of BitmapDevice to given output stream. + + @param rDevice + Device whose content should be dumped. + + @param rOutputStream + Stream to write output to. + */ + void debugDump( const boost::shared_ptr< BitmapDevice >& rDevice, + ::std::ostream& rOutputStream ); +} + +#endif /* INCLUDED_BASEBMP_DEBUG_HXX */ diff --git a/basebmp/inc/basebmp/drawmodes.hxx b/basebmp/inc/basebmp/drawmodes.hxx new file mode 100644 index 000000000000..f09d5c221383 --- /dev/null +++ b/basebmp/inc/basebmp/drawmodes.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * $RCSfile: drawmodes.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:42 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_DRAWMODES_HXX +#define INCLUDED_BASEBMP_DRAWMODES_HXX + +/* Definition of Draw modes */ + +namespace basebmp +{ + enum DrawMode + { + DrawMode_PAINT, + DrawMode_XOR + }; +} + +#endif /* INCLUDED_BASEBMP_DRAWMODES_HXX */ diff --git a/basebmp/inc/basebmp/linerenderer.hxx b/basebmp/inc/basebmp/linerenderer.hxx new file mode 100644 index 000000000000..0493e9571b8a --- /dev/null +++ b/basebmp/inc/basebmp/linerenderer.hxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: linerenderer.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:42 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_LINERENDERER_HXX +#define INCLUDED_BASEBMP_LINERENDERER_HXX + +#ifndef _BGFX_POINT_B2IPOINT_HXX +#include <basegfx/point/b2ipoint.hxx> +#endif + +/* Scan-converting lines */ + +namespace basebmp +{ + +/** Render line with Bresenham + + This function renders the line given by rPt1 and rPt2 using the + Bresenham algorithm with the specified color value. Make sure rPt1 + and rPt1 are valid coordinates in the image given by begin and + end, since no clipping takes place. + + @param aPt1 + Start point of the line + + @param aPt2 + End point of the line + + @param color + Color value to render the line with + + @param begin + left-top image iterator + + @param end + right-bottom image iterator + + @param acc + Image accessor + + @param bRoundTowardsPt2 + Rounding mode to use. Giving false here results in line pixel tend + towards pt1, i.e. when a pixel exactly hits the middle between two + pixel, the pixel closer to pt1 will be chosen. Giving true here + makes renderClippedLine() choose pt2 in those cases. + */ +template< class Iterator, class Accessor > +void renderLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + typename Accessor::value_type color, + Iterator begin, + Iterator end, + Accessor acc, + bool bRoundTowardsPt2=false ) +{ + // code inspired by Paul Heckbert's Digital Line Drawing + // (Graphics Gems, Academic Press 1990) + const sal_Int32 x1 = rPt1.getX(); + const sal_Int32 x2 = rPt2.getX(); + const sal_Int32 y1 = rPt1.getY(); + const sal_Int32 y2 = rPt2.getY(); + + // TODO(E1): This might overflow + sal_Int32 adx = x2 - x1; + int sx = 1; + if( adx < 0 ) + { + adx *= -1; + sx = -1; + } + + // TODO(E1): This might overflow + sal_Int32 ady = y2 - y1; + int sy = 1; + if( ady < 0 ) + { + ady *= -1; + sy = -1; + } + + // TODO(P3): handle horizontal and vertical lines specially + sal_Int32 xs = x1; + sal_Int32 ys = y1; + if( adx >= ady ) + { + // semi-horizontal line + sal_Int32 rem = 2*ady - adx - !bRoundTowardsPt2; + adx *= 2; + ady *= 2; + + Iterator currIter( begin + vigra::Diff2D(0,ys) ); + typename Iterator::row_iterator rowIter( currIter.rowIterator() + xs ); + while(true) + { + acc.set(color, rowIter); + + if( xs == x2 ) + return; + + if( rem >= 0 ) + { + ys += sy; + xs += sx; + currIter.y += sy; + rowIter = currIter.rowIterator() + xs; + rem -= adx; + } + else + { + xs += sx; + rowIter += sx; + } + + rem += ady; + } + } + else + { + // semi-vertical line + sal_Int32 rem = 2*adx - ady - !bRoundTowardsPt2; + adx *= 2; + ady *= 2; + + Iterator currIter( begin + vigra::Diff2D(xs,0) ); + typename Iterator::column_iterator colIter( currIter.columnIterator() + ys ); + while(true) + { + acc.set(color, colIter); + + if( ys == y2 ) + return; + + if( rem >= 0 ) + { + xs += sx; + ys += sy; + currIter.x += sx; + colIter = currIter.columnIterator() + ys; + rem -= ady; + } + else + { + ys += sy; + colIter += sy; + } + + rem += adx; + } + } +} + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_LINERENDERER_HXX */ diff --git a/basebmp/inc/basebmp/metafunctions.hxx b/basebmp/inc/basebmp/metafunctions.hxx new file mode 100644 index 000000000000..cdef37548e7b --- /dev/null +++ b/basebmp/inc/basebmp/metafunctions.hxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: metafunctions.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:42 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_METAFUNCTIONS_HXX +#define INCLUDED_BASEBMP_METAFUNCTIONS_HXX + +namespace basebmp +{ + +// TODO(Q3): move to generic place (o3tl?) + +/// template meta function: add const qualifier, if given 2nd type has it +template<typename A, typename B> struct clone_const +{ + typedef B type; +}; +template<typename A, typename B> struct clone_const<const A,B> +{ + typedef const B type; +}; + +/// template meta function: remove const qualifier from plain type +template <typename T> struct remove_const +{ + typedef T type; +}; +template <typename T> struct remove_const<const T> +{ + typedef T type; +}; + +/// returns true, if given number is strictly less than 0 +template< typename T > inline bool is_negative( T x ) +{ + return x < 0; +} + +/// Overload for ints (branch-free) +inline bool is_negative( int x ) +{ + // force logic shift (result for signed shift right is undefined) + return static_cast<unsigned int>(x) >> (sizeof(int)*8-1); +} + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_METAFUNCTIONS_HXX */ diff --git a/basebmp/inc/basebmp/packedpixeliterator.hxx b/basebmp/inc/basebmp/packedpixeliterator.hxx new file mode 100644 index 000000000000..48330d5c27ad --- /dev/null +++ b/basebmp/inc/basebmp/packedpixeliterator.hxx @@ -0,0 +1,676 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: packedpixeliterator.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:42 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX +#define INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX + +#include "metafunctions.hxx" +#include "stridedarrayiterator.hxx" + +#include <boost/static_assert.hpp> +#include <vigra/metaprogramming.hxx> +#include <vigra/diff2d.hxx> + +namespace basebmp +{ + +/// Get bitmask for data at given intra-word position, for given bit depth +template< typename data_type, int bits_per_pixel, bool MsbFirst, typename difference_type > inline data_type get_mask( difference_type d ) +{ + BOOST_STATIC_ASSERT(bits_per_pixel > 0); + BOOST_STATIC_ASSERT(sizeof(data_type)*8 % bits_per_pixel == 0); + BOOST_STATIC_ASSERT(sizeof(data_type)*8 / bits_per_pixel > 1); + BOOST_STATIC_ASSERT(vigra::TypeTraits<data_type>::isPOD::asBool); + + const unsigned int nIntraWordPositions( sizeof(data_type)*8 / bits_per_pixel ); + + // create bits_per_pixel 1s shift to intra-word position + return ((~(~0 << bits_per_pixel)) << bits_per_pixel*(MsbFirst ? + (nIntraWordPositions-1 - (d % nIntraWordPositions)) : + (d % nIntraWordPositions))); +} + +template< int num_intraword_positions, int bits_per_pixel, bool MsbFirst, typename difference_type > inline difference_type get_shift( difference_type remainder ) +{ + return bits_per_pixel*(MsbFirst ? + (num_intraword_positions - 1 - remainder) : + remainder); +} + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelColumnIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef typename remove_const<data_type>::type mask_type; + typedef data_type* pointer; + typedef StridedArrayIterator< data_type > MoveY; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + +private: + MoveY y; + mask_type mask_; + difference_type shift_; + + void inc() + { + ++y; + } + + void dec() + { + --y; + } + + bool equal( PackedPixelColumnIterator const & rhs ) const + { + return rhs.y == y; + } + + bool less( PackedPixelColumnIterator const & rhs ) const + { + return y < rhs.y; + } + +public: + PackedPixelColumnIterator() : + y(0), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst, difference_type>(0) ) + {} + + PackedPixelColumnIterator( const MoveY& base, difference_type remainder ) : + y(base), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ), + shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder) ) + {} + + PackedPixelColumnIterator& operator+=( difference_type d ) + { + y += d; + return *this; + } + + PackedPixelColumnIterator& operator-=( difference_type d ) + { + y -= d; + return *this; + } + + PackedPixelColumnIterator operator+( difference_type d ) + { + PackedPixelColumnIterator res(*this); + res += d; + return res; + } + + PackedPixelColumnIterator operator-( difference_type d ) + { + PackedPixelColumnIterator res(*this); + res -= d; + return res; + } + + PackedPixelColumnIterator& operator++() + { + inc(); + return *this; + } + + PackedPixelColumnIterator& operator--() + { + dec(); + return *this; + } + + PackedPixelColumnIterator operator++(int) + { + PackedPixelColumnIterator res(*this); + inc(); + return res; + } + + PackedPixelColumnIterator operator--(int) + { + PackedPixelColumnIterator res(*this); + dec(); + return res; + } + + bool operator==(PackedPixelColumnIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PackedPixelColumnIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PackedPixelColumnIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PackedPixelColumnIterator const & rhs) const + { + return !less(rhs); + } + + bool operator>(PackedPixelColumnIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PackedPixelColumnIterator const & rhs) const + { + return !rhs.less(*this); + } + + difference_type operator-(PackedPixelColumnIterator const & rhs) const + { + return y - rhs.y; + } + + value_type get() const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*y() & mask_) >> shift_; + } + + value_type get(difference_type d) const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*y(d) & mask_) >> shift_; + } + + void set( value_type v ) const + { + const value_type pixel_value( (v << shift_) & mask_ ); + *y() = (*y() & ~mask_) | pixel_value; + } + + void set( value_type v, difference_type d ) const + { + const value_type pixel_value( (v << shift_) & mask_ ); + *y(d) = (*y(d) & ~mask_) | pixel_value; + } +}; + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelRowIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef typename remove_const<data_type>::type mask_type; + typedef data_type* pointer; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + +private: + pointer data_; + mask_type mask_; + difference_type remainder_; + + void update_mask() + { + mask_ = get_mask<data_type, bits_per_pixel, MsbFirst>(remainder_); + } + + void inc() + { + const difference_type newValue( remainder_ + 1 ); + const difference_type data_offset( newValue / num_intraword_positions ); + + data_ += data_offset; + remainder_ = newValue % num_intraword_positions; + + const mask_type shifted_mask( + MsbFirst ? + // TODO(Q3): use traits to get unsigned type for data_type + // (if not already) + static_cast<unsigned int>(mask_) >> bits_per_pixel : + mask_ << bits_per_pixel ); + + // data_offset is 0 for shifted mask, and 1 for wrapped-around mask + mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ? + bit_mask << bits_per_pixel*(num_intraword_positions-1) : + bit_mask); + } + + void dec() + { + const difference_type newValue( remainder_ - 1 ); + const bool isNegative( is_negative(newValue) ); + const difference_type newRemainder( newValue % num_intraword_positions ); + + // calc data_ += newValue / num_intraword_positions; + // remainder_ = newRemainder; + // for newValue >= 0, and + // data_ += newValue / num_intraword_positions - 1; + // remainder_ = num_intraword_positions - newRemainder; + // (to force remainder_ to be positive). + // This is branch-free, if is_negative() is branch-free + const difference_type data_offset( newValue / num_intraword_positions - isNegative ); + data_ += data_offset; + remainder_ = newRemainder + isNegative*num_intraword_positions; + + const mask_type shifted_mask( + MsbFirst ? + mask_ << bits_per_pixel : + // TODO(Q3): use traits to get unsigned type for data_type + // (if not already) + static_cast<unsigned int>(mask_) >> bits_per_pixel ); + + // data_offset is 0 for shifted mask, and 1 for wrapped-around mask + mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ? + bit_mask : + bit_mask << bits_per_pixel*(num_intraword_positions-1)); + } + + bool equal( PackedPixelRowIterator const & rhs ) const + { + return rhs.data_ == data_ && rhs.remainder_ == remainder_; + } + + bool less( PackedPixelRowIterator const & rhs ) const + { + return data_ == rhs.data_ ? + (remainder_ < rhs.remainder_) : + (data_ < rhs.data_); + } + +public: + PackedPixelRowIterator() : + data_(0), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + remainder_(0) + {} + + explicit PackedPixelRowIterator( pointer base, int x ) : + data_(base), + mask_(0), + remainder_(x % num_intraword_positions) + { + update_mask(); + } + + PackedPixelRowIterator& operator+=( difference_type d ) + { + const difference_type newValue( remainder_ + d ); + + data_ += newValue / num_intraword_positions; + remainder_ = newValue % num_intraword_positions; + update_mask(); + + return *this; + } + + PackedPixelRowIterator& operator-=( difference_type d ) + { + const difference_type newValue( remainder_ - d ); + const bool isNegative( is_negative(newValue) ); + const difference_type newRemainder( newValue % num_intraword_positions ); + + // calc data_ += newValue / num_intraword_positions; + // remainder_ = newRemainder; + // for newValue >= 0, and + // data_ += newValue / num_intraword_positions - 1; + // remainder_ = num_intraword_positions - newRemainder; + // (to force remainder_ to be positive). + // This is branch-free, if is_negative() is branch-free + data_ += newValue / num_intraword_positions - isNegative; + remainder_ = newRemainder + isNegative*(num_intraword_positions - 2*newRemainder); + update_mask(); + + return *this; + } + + PackedPixelRowIterator operator+( difference_type d ) + { + PackedPixelRowIterator res(*this); + res += d; + return res; + } + + PackedPixelRowIterator operator-( difference_type d ) + { + PackedPixelRowIterator res(*this); + res -= d; + return res; + } + + PackedPixelRowIterator& operator++() + { + inc(); + return *this; + } + + PackedPixelRowIterator& operator--() + { + dec(); + return *this; + } + + PackedPixelRowIterator operator++(int) + { + PackedPixelRowIterator res(*this); + inc(); + return res; + } + + PackedPixelRowIterator operator--(int) + { + PackedPixelRowIterator res(*this); + dec(); + return res; + } + + bool operator==(PackedPixelRowIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PackedPixelRowIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PackedPixelRowIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PackedPixelRowIterator const & rhs) const + { + return !less(rhs); + } + + bool operator>(PackedPixelRowIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PackedPixelRowIterator const & rhs) const + { + return !rhs.less(*this); + } + + difference_type operator-(PackedPixelRowIterator const & rhs) const + { + return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_); + } + + value_type get() const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*data_ & mask_) >> + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_); + } + + value_type get(difference_type d) const + { + PackedPixelRowIterator tmp(*this); + tmp += d; + return tmp.get(); + } + + void set( value_type v ) const + { + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_)) + & mask_ ); + *data_ = (*data_ & ~mask_) | pixel_value; + } + + void set( value_type v, difference_type d ) const + { + PackedPixelRowIterator tmp(*this); + tmp += d; + tmp.set(v); + } +}; + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef vigra::Diff2D difference_type; + typedef image_traverser_tag iterator_category; + typedef PackedPixelRowIterator<data_type, + value_type, + bits_per_pixel, + MsbFirst> row_iterator; + typedef PackedPixelColumnIterator<data_type, + value_type, + bits_per_pixel, + MsbFirst> column_iterator; + + typedef data_type* pointer; + typedef int MoveX; + typedef StridedArrayIterator< data_type > MoveY; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + + // TODO(F2): direction of iteration (ImageIterator can be made to + // run backwards) + +private: + pointer current() const + { + return y() + (x / num_intraword_positions); + } + + pointer current(int dx, int dy) const + { + return y(dy) + ((x+dx)/num_intraword_positions); + } + + bool equal(PackedPixelIterator const & rhs) const + { + return (x == rhs.x) && (y == rhs.y); + } + +public: + PackedPixelIterator() : + x(0), + y(0) + {} + + PackedPixelIterator(pointer base, int ystride) : + x(0), + y(ystride,base) + {} + + bool operator==(PackedPixelIterator const & rhs) const + { + return equal(rhs); + } + + bool operator!=(PackedPixelIterator const & rhs) const + { + return !equal(rhs); + } + + difference_type operator-(PackedPixelIterator const & rhs) const + { + return difference_type(x - rhs.x, y - rhs.y); + } + + MoveX x; + MoveY y; + + PackedPixelIterator & operator+=(difference_type const & s) + { + x += s.x; + y += s.y; + return *this; + } + + PackedPixelIterator & operator-=(difference_type const & s) + { + x -= s.x; + y -= s.y; + return *this; + } + + PackedPixelIterator operator+(difference_type const & s) const + { + PackedPixelIterator ret(*this); + ret += s; + return ret; + } + + PackedPixelIterator operator-(difference_type const & s) const + { + PackedPixelIterator ret(*this); + ret -= s; + return ret; + } + + row_iterator rowIterator() const + { + return row_iterator(current(),x); + } + + column_iterator columnIterator() const + { + return column_iterator(MoveY(y, + x / num_intraword_positions), + x % num_intraword_positions); + } + + value_type get() const + { + const int remainder( x % num_intraword_positions ); + + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + value_type nTmp0( *current() ); + unsigned int nTmp1(static_cast<unsigned int>(*current() & + get_mask<data_type, bits_per_pixel, MsbFirst>(remainder))); + unsigned int nTmp2( (static_cast<unsigned int>(*current() & + get_mask<data_type, bits_per_pixel, MsbFirst>(remainder)) + >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder))); + + return (static_cast<unsigned int>(*current() & + get_mask<data_type, bits_per_pixel, MsbFirst>(remainder)) + >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)); + } + + value_type get(difference_type const & d) const + { + const int remainder( x(d.x) % num_intraword_positions ); + + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return (static_cast<unsigned int>(*current(d.x,d.y) & + get_mask<data_type, bits_per_pixel, MsbFirst>(remainder)) + >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)); + } + + void set( value_type v ) const + { + const int remainder( x % num_intraword_positions ); + const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ); + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)) + & mask ); + pointer p = current(); + *p = (*p & ~mask) | pixel_value; + } + + void set( value_type v, difference_type const & d ) const + { + const int remainder( (x + d.x) % num_intraword_positions ); + const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ); + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)) + & mask ); + pointer p = current(d.x,d.y); + *p = (*p & ~mask) | pixel_value; + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_PACKEDPIXELITERATOR_HXX */ diff --git a/basebmp/inc/basebmp/paletteimageaccessor.hxx b/basebmp/inc/basebmp/paletteimageaccessor.hxx new file mode 100644 index 000000000000..848ea59d7a50 --- /dev/null +++ b/basebmp/inc/basebmp/paletteimageaccessor.hxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: paletteimageaccessor.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:42 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_PALETTEIMAGEACCESSOR_HXX +#define INCLUDED_BASEBMP_PALETTEIMAGEACCESSOR_HXX + +#include "metafunctions.hxx" + +#include <vigra/numerictraits.hxx> +#include <vigra/mathutil.hxx> + +#include <algorithm> + + +namespace basebmp +{ + +/** Access (possibly packed-pixel) data via palette indirection + */ +template< typename Valuetype, typename Datatype > class PaletteImageAccessor +{ +public: + typedef Valuetype value_type; + typedef Datatype data_type; + typedef typename remove_const<data_type>::type count_type; + + +private: + const value_type* palette; + count_type num_entries; + + double norm( value_type const& rLHS, + value_type const& rRHS ) const + { + return (rRHS - rLHS).magnitude(); + } + + data_type find_best_match(value_type const& v) const + { + // TODO(P3): use table-based/octree approach here! + const value_type* best_entry; + const value_type* palette_end( palette+num_entries ); + if( (best_entry=std::find( palette, palette_end, v)) != palette_end ) + return best_entry-palette; + + // TODO(F3): HACK. Need palette traits, and an error function + // here. We blatantly assume value_type is a normed linear + // space. + const value_type* curr_entry( palette ); + best_entry = curr_entry; + while( curr_entry != palette_end ) + { + if( norm(*curr_entry,*best_entry) > norm(*curr_entry,v) ) + best_entry = curr_entry; + + ++curr_entry; + } + + return best_entry-palette; + } + + value_type toCol( value_type const& rCol ) const + { + return rCol; + } + +public: + PaletteImageAccessor() : + palette(0), + num_entries(0) + {} + + PaletteImageAccessor( const value_type* pPalette, + data_type entries ) : + palette(pPalette), + num_entries(entries) + {} + + template< class Iterator > + value_type operator()(Iterator const& i) const { return toCol(palette[i.get()]); } + value_type operator()(data_type const* i) const { return toCol(palette[*i]); } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return toCol(palette[i.get(diff)]); + } + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + i.set( + find_best_match( + vigra::detail::RequiresExplicitCast<value_type>::cast(value) )); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + i.set( + find_best_match( + vigra::detail::RequiresExplicitCast<value_type>::cast(value)), + diff ); + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_PALETTEIMAGEACCESSOR_HXX */ diff --git a/basebmp/inc/basebmp/pixeliterator.hxx b/basebmp/inc/basebmp/pixeliterator.hxx new file mode 100644 index 000000000000..9f1f3c997ea2 --- /dev/null +++ b/basebmp/inc/basebmp/pixeliterator.hxx @@ -0,0 +1,362 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: pixeliterator.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:43 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_PIXELITERATOR_HXX +#define INCLUDED_BASEBMP_PIXELITERATOR_HXX + +#include "metafunctions.hxx" +#include "stridedarrayiterator.hxx" + +#include <boost/static_assert.hpp> +#include <vigra/metaprogramming.hxx> +#include <vigra/diff2d.hxx> + +namespace basebmp +{ + +template< typename Valuetype > class PixelColumnIterator +{ +public: + typedef Valuetype value_type; + typedef Valuetype& reference; + typedef Valuetype* pointer; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef StridedArrayIterator< value_type > MoveY; + +private: + MoveY y; + + bool equal( PixelColumnIterator const & rhs ) const + { + return rhs.y == y; + } + + bool less( PixelColumnIterator const & rhs ) const + { + return y < rhs.y; + } + +public: + PixelColumnIterator() : + y(0) + {} + + explicit PixelColumnIterator( const MoveY& pos ) : + y(pos) + {} + + PixelColumnIterator( const MoveY& pos, int x ) : + y(pos,x) + {} + + PixelColumnIterator& operator+=( difference_type d ) + { + y += d; + return *this; + } + + PixelColumnIterator& operator-=( difference_type d ) + { + y -= d; + return *this; + } + + PixelColumnIterator operator+( difference_type d ) + { + PixelColumnIterator res(*this); + res += d; + return res; + } + + PixelColumnIterator operator-( difference_type d ) + { + PixelColumnIterator res(*this); + res -= d; + return res; + } + + PixelColumnIterator& operator++() + { + ++y; + return *this; + } + + PixelColumnIterator& operator--() + { + --y; + return *this; + } + + PixelColumnIterator operator++(int) + { + PixelColumnIterator res(*this); + ++y; + return res; + } + + PixelColumnIterator operator--(int) + { + PixelColumnIterator res(*this); + --y; + return res; + } + + bool operator==(PixelColumnIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PixelColumnIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PixelColumnIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PixelColumnIterator const & rhs) const + { + return !less(rhs); + } + + bool operator>(PixelColumnIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PixelColumnIterator const & rhs) const + { + return !rhs.less(*this); + } + + difference_type operator-(PixelColumnIterator const & rhs) const + { + return y - rhs.y; + } + + value_type get() const + { + return *y(); + } + + value_type get(difference_type d) const + { + return *y(d); + } + + void set( value_type v ) const + { + *y() = v; + } + + void set( value_type v, difference_type d ) const + { + *y(d) = v; + } + + reference operator*() const + { + return *y(); + } + + pointer operator->() const + { + return y(); + } + + reference operator[](difference_type d) const + { + return *y(d); + } + + reference operator()(int dy) const + { + return *y(dy); + } +}; + +template< typename Valuetype > class PixelIterator +{ +public: + typedef Valuetype value_type; + typedef Valuetype& reference; + typedef Valuetype* pointer; + typedef vigra::Diff2D difference_type; + typedef image_traverser_tag iterator_category; + typedef pointer row_iterator; + typedef PixelColumnIterator<value_type> column_iterator; + + typedef int MoveX; + typedef StridedArrayIterator< value_type > MoveY; + + // TODO(F2): direction of iteration (ImageIterator can be made to + // run backwards) + +private: + bool equal(PixelIterator const & rhs) const + { + return (x == rhs.x) && (y == rhs.y); + } + + pointer current() const + { + return y() + x; + } + + pointer current(int dx, int dy) const + { + return y(dy) + x+dy; + } + +public: + PixelIterator() : + x(0), + y(0) + {} + + PixelIterator(pointer base, int ystride) : + x(0), + y(ystride,base) + {} + + bool operator==(PixelIterator const & rhs) const + { + return equal(rhs); + } + + bool operator!=(PixelIterator const & rhs) const + { + return !equal(rhs); + } + + difference_type operator-(PixelIterator const & rhs) const + { + return difference_type(x - rhs.x, y - rhs.y); + } + + MoveX x; + MoveY y; + + PixelIterator & operator+=(difference_type const & s) + { + x += s.x; + y += s.y; + return *this; + } + + PixelIterator & operator-=(difference_type const & s) + { + x -= s.x; + y -= s.y; + return *this; + } + + PixelIterator operator+(difference_type const & s) const + { + PixelIterator ret(*this); + ret += s; + return ret; + } + + PixelIterator operator-(difference_type const & s) const + { + PixelIterator ret(*this); + ret -= s; + return ret; + } + + row_iterator rowIterator() const + { + return row_iterator(y()+x); + } + + column_iterator columnIterator() const + { + return column_iterator(y,x); + } + + value_type get() const + { + return *current(); + } + + value_type get(difference_type const & d) const + { + return *current(d.y, d.x); + } + + void set( value_type v ) const + { + *current() = v; + } + + void set( value_type v, difference_type const & d ) const + { + *current(d.y,d.x) = v; + } + + reference operator*() const + { + return *current(); + } + + pointer operator->() const + { + return current(); + } + + reference operator[]( const vigra::Diff2D& d ) const + { + return *current(d.x,d.y); + } + + reference operator()(int dx, int dy) const + { + return *current(dx,dy); + } + + pointer operator[](int dy) const + { + return y(dy) + x; + } +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_PIXELITERATOR_HXX */ diff --git a/basebmp/inc/basebmp/scanlineformats.hxx b/basebmp/inc/basebmp/scanlineformats.hxx new file mode 100644 index 000000000000..c0aef970c1a8 --- /dev/null +++ b/basebmp/inc/basebmp/scanlineformats.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * $RCSfile: scanlineformats.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:43 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_SCANLINEFORMATS_HXX +#define INCLUDED_BASEBMP_SCANLINEFORMATS_HXX + +/* Definition of Scanline formats */ + +namespace basebmp { namespace Format +{ + static const sal_Int32 ONE_BIT_MSB_PAL = (sal_Int32)0x01; + static const sal_Int32 ONE_BIT_LSB_PAL = (sal_Int32)0x02; + static const sal_Int32 TWO_BIT_MSB_PAL = (sal_Int32)0x03; + static const sal_Int32 TWO_BIT_LSB_PAL = (sal_Int32)0x04; + static const sal_Int32 FOUR_BIT_MSB_PAL = (sal_Int32)0x05; + static const sal_Int32 FOUR_BIT_LSB_PAL = (sal_Int32)0x06; + static const sal_Int32 EIGHT_BIT_PAL = (sal_Int32)0x07; + static const sal_Int32 EIGHT_BIT_TC_MASK = (sal_Int32)0x0A; + static const sal_Int32 SIXTEEN_BIT_TC_MASK = (sal_Int32)0x0B; + static const sal_Int32 TWENTYFOUR_BIT_TC_MASK = (sal_Int32)0x0C; + static const sal_Int32 THIRTYTWO_BIT_TC_MASK = (sal_Int32)0x0D; +} } + +#endif /* INCLUDED_BASEBMP_SCANLINEFORMATS_HXX */ diff --git a/basebmp/inc/basebmp/stridedarrayiterator.hxx b/basebmp/inc/basebmp/stridedarrayiterator.hxx new file mode 100644 index 000000000000..bcff5a21c518 --- /dev/null +++ b/basebmp/inc/basebmp/stridedarrayiterator.hxx @@ -0,0 +1,102 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: stridedarrayiterator.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:43 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_BASEBMP_STRIDEDARRAYITERATOR_HXX +#define INCLUDED_BASEBMP_STRIDEDARRAYITERATOR_HXX + +namespace basebmp +{ + +// changed semantics re. DirectionSelector<StridedArrayTag>: stride +// now counts in <em>raw</em> bytes! +template< typename T > class StridedArrayIterator +{ +public: + typedef typename clone_const<T, unsigned char>::type internal_type; + + StridedArrayIterator(int stride, T* ptr = 0) : + stride_(stride), + current_(reinterpret_cast<internal_type*>(ptr)) + {} + + /// Copy from other StridedArrayIterator, plus given offset + StridedArrayIterator( StridedArrayIterator const& rSrc, + int offset ) : + stride_(rSrc.stride_), + current_(reinterpret_cast<internal_type*>( + reinterpret_cast<T*>(rSrc.current_)+offset)) + {} + + void operator++() {current_ += stride_; } + void operator++(int) {current_ += stride_; } + void operator--() {current_ -= stride_; } + void operator--(int) {current_ -= stride_; } + void operator+=(int dy) {current_ += dy*stride_; } + void operator-=(int dy) {current_ -= dy*stride_; } + + bool operator==(StridedArrayIterator const & rhs) const + { return (current_ == rhs.current_); } + + bool operator!=(StridedArrayIterator const & rhs) const + { return (current_ != rhs.current_); } + + bool operator<(StridedArrayIterator const & rhs) const + { return (current_ < rhs.current_); } + + bool operator<=(StridedArrayIterator const & rhs) const + { return (current_ <= rhs.current_); } + + bool operator>(StridedArrayIterator const & rhs) const + { return (current_ > rhs.current_); } + + bool operator>=(StridedArrayIterator const & rhs) const + { return (current_ >= rhs.current_); } + + int operator-(StridedArrayIterator const & rhs) const + { return (current_ - rhs.current_) / stride_; } + + T* operator()() const + { return reinterpret_cast<T*>(current_); } + + T* operator()(int d) const + { return reinterpret_cast<T*>(current_ + d*stride_); } + + int stride_; + internal_type* current_; +}; + +} // namespace basebmp + +#endif /* INCLUDED_BASEBMP_STRIDEDARRAYITERATOR_HXX */ diff --git a/basebmp/prj/build.lst b/basebmp/prj/build.lst new file mode 100644 index 000000000000..36813ae257d8 --- /dev/null +++ b/basebmp/prj/build.lst @@ -0,0 +1,4 @@ +bx basebmp : sal vigra basegfx boost NULL +bx basebmp usr1 - all bx_mkout NULL +bx basebmp\source nmake - all bx_source NULL +bx basebmp\util nmake - all bx_util bx_source NULL diff --git a/basebmp/prj/d.lst b/basebmp/prj/d.lst new file mode 100644 index 000000000000..03cfbcd3fe25 --- /dev/null +++ b/basebmp/prj/d.lst @@ -0,0 +1,10 @@ +..\%__SRC%\lib\ibasebmp.lib %_DEST%\lib%_EXT%\ibasebmp.lib + +..\%__SRC%\bin\basebmp?????.dll %_DEST%\bin%_EXT%\basebmp?????.dll + +..\%__SRC%\lib\libbasebmp?????.* %_DEST%\lib%_EXT%\libbasebmp?????.* +..\%__SRC%\lib\*.a %_DEST%\lib%_EXT%\*.a +..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib + +mkdir: %_DEST%\inc%_EXT%\basebmp +..\inc\basebmp\*.hxx %_DEST%\inc%_EXT%\basebmp\*.hxx diff --git a/basebmp/source/bitmapdevice.cxx b/basebmp/source/bitmapdevice.cxx new file mode 100644 index 000000000000..3ee33010f2b2 --- /dev/null +++ b/basebmp/source/bitmapdevice.cxx @@ -0,0 +1,1023 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: bitmapdevice.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:44 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#include "basebmp/bitmapdevice.hxx" +#include "basebmp/packedpixeliterator.hxx" +#include "basebmp/pixeliterator.hxx" +#include "basebmp/paletteimageaccessor.hxx" +#include "basebmp/color.hxx" +#include "basebmp/accessor.hxx" +#include "basebmp/accessoradapters.hxx" +#include "basebmp/scanlineformats.hxx" +#include "basebmp/linerenderer.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/b2dpolygonclipper.hxx> +#include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/vector/b2ivector.hxx> + +#include <vigra/basicimage.hxx> +#include <vigra/imageiterator.hxx> + + +namespace basebmp +{ + +namespace +{ + typedef PackedPixelIterator< sal_uInt8, + sal_uInt8, + 1, + true > MaskIterator; + typedef StandardAccessor< sal_uInt8 > MaskAccessor; + + typedef vigra::ImageIterator< sal_uInt8 > AlphaMaskIterator; + typedef vigra::AccessorTraits< sal_uInt8 >::default_accessor AlphaMaskAccessor; + + + template< class DestIterator, class DestAccessor > class Renderer : + public basegfx::B2DPolyPolygonRasterConverter + { + private: + basegfx::B2IRange bounds_; + typename DestIterator::value_type fillColor_; + typename DestIterator::value_type clearColor_; + DestIterator begin_; + DestAccessor accessor_; + + public: + Renderer(const basegfx::B2DPolyPolygon& rPolyPolyRaster, + typename DestIterator::value_type fillColor, + const basegfx::B2IRange& bounds, + DestIterator begin, + DestIterator end, + DestAccessor accessor ) : + B2DPolyPolygonRasterConverter(rPolyPolyRaster, + basegfx::B2DRange(bounds) ), + bounds_(bounds), + fillColor_( fillColor ), + begin_( begin ), + accessor_( accessor ) + { + } + + virtual void span(const double& rfXLeft, + const double& rfXRight, + sal_Int32 nY, + bool bOn ) + { + if( !bOn || + nY < bounds_.getMinY() || + nY >= bounds_.getMaxY() || + rfXLeft >= bounds_.getMaxX() || + rfXRight < bounds_.getMinX() ) + { + return; + } + + // clip span to bitmap bounds + const sal_Int32 nStartX( std::max( bounds_.getMinX(), + std::min( bounds_.getMaxX()-1, + basegfx::fround( rfXLeft )))); + const sal_Int32 nEndX ( std::max( bounds_.getMinX(), + std::min( bounds_.getMaxX()-1, + basegfx::fround( rfXRight )))); + + DestIterator currIter( begin_ + vigra::Diff2D(0,nY) ); + typename DestIterator::row_iterator rowIter( currIter.rowIterator() + nStartX); + typename DestIterator::row_iterator rowEnd( currIter.rowIterator() + nEndX ); + + // TODO(P2): Provide specialized span fill methods on the + // iterator/accessor + while( rowIter != rowEnd ) + accessor_.set(fillColor_, rowIter++); + } + }; + + template< class DestIterator, class DestAccessor > + std::auto_ptr< Renderer< DestIterator, DestAccessor > > makeRenderer( + const basegfx::B2DPolyPolygon& rPolyPolyRaster, + typename DestIterator::value_type fillColor, + const basegfx::B2IRange& outRange, + vigra::triple<DestIterator, DestIterator, DestAccessor> dest ) + { + basegfx::B2IRange aBmpRange(0,0, + dest.second.x - dest.first.x, + dest.second.y - dest.first.y ); + aBmpRange.intersect( outRange ); + + return std::auto_ptr< Renderer< DestIterator, DestAccessor > >( + new Renderer< DestIterator, DestAccessor >(rPolyPolyRaster, + fillColor, + aBmpRange, + dest.first, + dest.second, + dest.third)); + } + + template< class DestIterator, class DestAccessor > class BitmapRenderer : public BitmapDevice + { + public: + typedef BitmapRenderer<MaskIterator, + MaskAccessor> MaskBitmap; + typedef BitmapRenderer<AlphaMaskIterator, + AlphaMaskAccessor> AlphaMaskBitmap; + typedef typename xorAccessor<DestAccessor>::type XorAccessor; + typedef typename maskedAccessor<DestAccessor, + MaskAccessor, + DestIterator, + MaskIterator>::type MaskedAccessor; + typedef typename maskedAccessor<XorAccessor, + MaskAccessor, + DestIterator, + MaskIterator>::type MaskedXorAccessor; + + DestIterator maBegin; + DestIterator maEnd; + DestAccessor maAccessor; + XorAccessor maXorAccessor; + MaskedAccessor maMaskedAccessor; + MaskedXorAccessor maMaskedXorAccessor; + int mnWidth; + int mnHeight; + + BitmapRenderer( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + DestIterator begin, + DestIterator end, + DestAccessor accessor, + const RawMemorySharedPtr& rMem ) : + BitmapDevice( rSize, bTopDown, nScanlineFormat, nScanlineStride, rMem ), + maBegin( begin ), + maEnd( end ), + maAccessor( accessor ), + maXorAccessor( accessor ), + maMaskedAccessor( accessor ), + maMaskedXorAccessor( maXorAccessor ), + mnWidth( maEnd.x - maBegin.x ), + mnHeight( maEnd.y - maBegin.y ) + {} + + 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<MaskBitmap> getCompatibleMask( const BitmapDeviceSharedPtr& bmp ) const + { + return boost::dynamic_pointer_cast<MaskBitmap>( bmp ); + } + + virtual bool isCompatibleClipMask( const BitmapDeviceSharedPtr& bmp ) const + { + // TODO(P1): dynamic_cast usually called twice for + // compatible formats + return getCompatibleMask( bmp ).get() != NULL; + } + + boost::shared_ptr<AlphaMaskBitmap> getCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const + { + return boost::dynamic_pointer_cast<AlphaMaskBitmap>( bmp ); + } + + virtual bool isCompatibleAlphaMask( const BitmapDeviceSharedPtr& bmp ) const + { + // TODO(P1): dynamic_cast usually called twice for + // compatible formats + return getCompatibleAlphaMask( bmp ).get() != NULL; + } + + virtual const Color* getPalette_i() const + { + // TODO(F3): Palette + return NULL; + } + + virtual const sal_Int32 getPaletteEntryCount_i() const + { + // TODO(F3): Palette + return 0; + } + + virtual void clear_i( Color fillColor ) + { + DestIterator currIter( maBegin ); + const DestIterator endIter( maBegin + vigra::Diff2D(0,mnHeight) ); + while( currIter != endIter ) + { + typename DestIterator::row_iterator rowIter( currIter.rowIterator() ); + const typename DestIterator::row_iterator rowEnd( rowIter + mnWidth ); + + // TODO(P2): Provide specialized span fill methods on the + // iterator/accessor + while( rowIter != rowEnd ) + maAccessor.set(fillColor, rowIter++); + + currIter += vigra::Diff2D( 0,1 ); + } + } + + virtual void setPixel_i( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode ) + { + const DestIterator pixel( maBegin + + vigra::Diff2D(rPt.getX(), + rPt.getY()) ); + if( drawMode == DrawMode_XOR ) + maXorAccessor.set( lineColor, pixel ); + else + maAccessor.set( lineColor, pixel ); + } + + virtual void setPixel_i( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + boost::shared_ptr<MaskBitmap> pMask( getCompatibleMask(rClip) ); + + const vigra::Diff2D offset(rPt.getX(), + rPt.getY()); + + const DestIterator pixel( maBegin + offset ); + const MaskIterator maskPixel( pMask->maBegin + offset ); + + if( drawMode == DrawMode_XOR ) + maMaskedXorAccessor.set( lineColor, pixel, maskPixel ); + else + maMaskedAccessor.set( lineColor, pixel, maskPixel ); + } + + virtual Color getPixel_i(const basegfx::B2IPoint& rPt ) + { + const DestIterator pixel( maBegin + + vigra::Diff2D(rPt.getX(), + rPt.getY()) ); + return maAccessor(pixel); + } + + virtual void drawLine_i(const basegfx::B2DPoint& rPt1, + const basegfx::B2DPoint& rPt2, + Color lineColor, + DrawMode drawMode ) + { + renderLine( basegfx::fround(rPt1), + basegfx::fround(rPt2), + lineColor, + maBegin, + maEnd, + maAccessor ); + } + + virtual void drawLine_i(const basegfx::B2DPoint& rPt1, + const basegfx::B2DPoint& rPt2, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + OSL_ENSURE( false, "drawLine_i(): Clipped output not yet implemented!" ); + } + + virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode ) + { + const sal_uInt32 nVertices( rPoly.count() ); + for( sal_uInt32 i=1; i<nVertices; ++i ) + { + renderLine( basegfx::fround(rPoly.getB2DPoint(i-1)), + basegfx::fround(rPoly.getB2DPoint(i)), + lineColor, + maBegin, + maEnd, + maAccessor ); + } + + if( nVertices > 1 && rPoly.isClosed() ) + renderLine( basegfx::fround(rPoly.getB2DPoint(nVertices-1)), + basegfx::fround(rPoly.getB2DPoint(0)), + lineColor, + maBegin, + maEnd, + maAccessor ); + } + + virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + OSL_ENSURE( false, "drawPolygon_i(): clipped output not yet implemented!" ); + } + + virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const basegfx::B2IRange& rBounds ) + { +/* + if( drawMode == DrawMode_XOR ) + makeRenderer( rPoly, + fillColor, + rBounds, + maBegin, + maEnd, + maXorAccessor )->rasterConvert( + basegfx::FillRule_NONZERO_WINDING_NUMBER ); + else +*/ + makeRenderer( rPoly, + fillColor, + rBounds, + vigra::make_triple( + maBegin, + maEnd, + maAccessor) )->rasterConvert( + basegfx::FillRule_NONZERO_WINDING_NUMBER ); + } + + virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly, + Color fillColor, + DrawMode drawMode, + const basegfx::B2IRange& rBounds, + const BitmapDeviceSharedPtr& rClip ) + { + OSL_ENSURE( false, "fillPolyPolygon_i(): Clipped output not yet implemented!" ); +/* Need uniform accessor for both plain and masked output. Combine + mask and bitmap iterator into proxy iterator, and pass that one + to the render method + + if( drawMode == DrawMode_XOR ) + makeRenderer( rPoly, + fillColor, + rBounds, + maBegin, + maEnd, + maMaskedXorAccessor )->rasterConvert( + basegfx::FillRule_NONZERO_WINDING_NUMBER ); + else + makeRenderer( rPoly, + fillColor, + rBounds, + maBegin, + maEnd, + maMaskedAccessor )->rasterConvert( + basegfx::FillRule_NONZERO_WINDING_NUMBER ); +*/ + } + + // must work with *this == rSrcBitmap! + virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) + { + OSL_ENSURE( false, "Method not yet implemented!" ); + } + + virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) + { + OSL_ENSURE( false, "Method not yet implemented!" ); + } + + // must work with *this == rSrcBitmap! + virtual void drawMaskedColor_i(Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint ) + { + OSL_ENSURE( false, "Method not yet implemented!" ); + } + + virtual void drawMaskedColor_i(Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint, + const BitmapDeviceSharedPtr& rClip ) + { + OSL_ENSURE( false, "Method not yet implemented!" ); + } + + // must work with *this == rSrcBitmap! + virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode ) + { + OSL_ENSURE( false, "Method not yet implemented!" ); + } + + virtual void drawMaskedBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const + + BitmapDeviceSharedPtr& rClip ) + { + OSL_ENSURE( false, "Method not yet implemented!" ); + } + }; +} // namespace + +struct ImplBitmapDevice +{ + /// Bitmap memory plus deleter + RawMemorySharedPtr mpMem; + + basegfx::B2IRange maBounds; + basegfx::B2DRange maFloatBounds; + sal_Int32 mnScanlineFormat; + sal_Int32 mnScanlineStride; +}; + + +BitmapDevice::BitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat, + sal_Int32 nScanlineStride, + const RawMemorySharedPtr& rMem ) : + mpImpl( new ImplBitmapDevice ) +{ + mpImpl->mpMem = rMem; + mpImpl->maBounds = basegfx::B2IRange( 0,0,rSize.getX(),rSize.getY() ); + mpImpl->maFloatBounds = basegfx::B2DRange( 0,0,rSize.getX(),rSize.getY() ); + mpImpl->mnScanlineFormat = nScanlineFormat; + mpImpl->mnScanlineStride = bTopDown ? nScanlineStride : -nScanlineStride; +} + +BitmapDevice::~BitmapDevice() +{ + // outline, because of internal ImplBitmapDevice +} + +basegfx::B2IVector BitmapDevice::getSize() const +{ + return basegfx::B2IVector( mpImpl->maBounds.getWidth(), + mpImpl->maBounds.getHeight() ); +} + +bool BitmapDevice::isTopDown() const +{ + return mpImpl->mnScanlineStride >= 0; +} + +sal_Int32 BitmapDevice::getScanlineFormat() const +{ + return mpImpl->mnScanlineFormat; +} + +sal_Int32 BitmapDevice::getScanlineStride() const +{ + return mpImpl->mnScanlineStride; +} + +RawMemorySharedPtr BitmapDevice::getBuffer() const +{ + return mpImpl->mpMem; +} + +const Color* BitmapDevice::getPalette() const +{ + return getPalette_i(); +} + +const sal_Int32 BitmapDevice::getPaletteEntryCount() const +{ + return getPaletteEntryCount_i(); +} + +void BitmapDevice::clear( Color fillColor ) +{ + clear_i( fillColor ); +} + +void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode ) +{ + if( mpImpl->maBounds.isInside(rPt) ) + setPixel_i(rPt,lineColor,drawMode); +} + +void BitmapDevice::setPixel( const basegfx::B2IPoint& rPt, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + if( mpImpl->maBounds.isInside(rPt) ) + { + if( isCompatibleClipMask( rClip ) ) + setPixel_i(rPt,lineColor,drawMode,rClip); + else + OSL_ENSURE( false, "Generic output not yet implemented!" ); + } +} + +Color BitmapDevice::getPixel( const basegfx::B2IPoint& rPt ) +{ + if( mpImpl->maBounds.isInside(rPt) ) + return getPixel_i(rPt); + + return Color(); +} + +void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + Color lineColor, + DrawMode drawMode ) +{ + basegfx::B2DPoint aPt1( rPt1 ); + basegfx::B2DPoint aPt2( rPt2 ); + + if( basegfx::tools::liangBarskyClip2D(aPt1,aPt2,mpImpl->maFloatBounds) ) + drawLine_i( aPt1, aPt2, + lineColor, + drawMode ); +} + +void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1, + const basegfx::B2IPoint& rPt2, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ +#if 1 + drawLine( rPt1, rPt2, lineColor, drawMode ); +#else + basegfx::B2DPoint aPt1( rPt1 ); + basegfx::B2DPoint aPt2( rPt2 ); + + if( basegfx::tools::liangBarskyClip2D(aPt1,aPt2,mpImpl->maFloatBounds) ) + { + if( isCompatibleClipMask( rClip ) ) + drawLine_i( aPt1, aPt2, + lineColor, + drawMode, + rClip ); + else + OSL_ENSURE( false, "Generic output not yet implemented!" ); + } +#endif +} + +void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode ) +{ + basegfx::B2DPolyPolygon aPoly( + basegfx::tools::clipPolygonOnRange( rPoly, + mpImpl->maFloatBounds, + true, + true )); + const sal_uInt32 numPolies( aPoly.count() ); + for( sal_uInt32 i=0; i<numPolies; ++i ) + if( aPoly.getB2DPolygon(i).count() ) + drawPolygon_i( aPoly.getB2DPolygon(i), lineColor, drawMode ); +} + +void BitmapDevice::drawPolygon( const basegfx::B2DPolygon& rPoly, + Color lineColor, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ +#if 1 + drawPolygon( rPoly, lineColor, drawMode ); +#else + basegfx::B2DPolyPolygon aPoly( + basegfx::tools::clipPolygonOnRange( rPoly, + mpImpl->maFloatBounds, + true, + true )); + const sal_uInt32 numPolies( aPoly.count() ); + for( sal_uInt32 i=0; i<numPolies; ++i ) + if( aPoly.getB2DPolygon(i).count() ) + if( isCompatibleClipMask( rClip ) ) + drawPolygon_i( aPoly.getB2DPolygon(i), lineColor, drawMode, rClip ); + else + OSL_ENSURE( false, "Generic output not yet implemented!" ); +#endif +} + +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 1 + fillPolyPolygon( rPoly, fillColor, drawMode ); +#else + if( isCompatibleClipMask( rClip ) ) + fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip ); + else + OSL_ENSURE( false, "Generic output not yet implemented!" ); +#endif +} + + +namespace +{ + // TODO(Q3): Move canvas/canvastools.hxx clipBlit() down + // to basegfx, and use here! + bool clipAreaImpl( ::basegfx::B2IRange* o_pDestArea, + ::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(); + + if( o_pDestArea ) + *o_pDestArea = aLocalDestArea; + + 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::B2IPoint aDestPoint( rDstRect.getMinimum() ); + basegfx::B2IRange aDestRange; + + // TODO(F2): Scaling/shrinking + if( clipAreaImpl( &aDestRange, + aSrcRange, + aDestPoint, + aSrcBounds, + mpImpl->maBounds )) + { + if( isCompatibleBitmap( rSrcBitmap ) ) + drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode ); + else + OSL_ENSURE( false, "Generic output not yet implemented!" ); + } +} + +void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() ); + const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() ); + + basegfx::B2IRange aSrcRange( rSrcRect ); + basegfx::B2IPoint aDestPoint( rDstRect.getMinimum() ); + basegfx::B2IRange aDestRange; + + // TODO(F2): Scaling/shrinking + if( clipAreaImpl( &aDestRange, + aSrcRange, + aDestPoint, + aSrcBounds, + mpImpl->maBounds )) + { + if( isCompatibleBitmap( rSrcBitmap ) && + isCompatibleClipMask( rClip ) ) + { + drawBitmap_i( rSrcBitmap, aSrcRange, aDestRange, drawMode, rClip ); + } + else + { + OSL_ENSURE( false, "Generic output not yet implemented!" ); + } + } +} + +void BitmapDevice::drawMaskedColor( Color rSrcColor, + 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( NULL, + aSrcRange, + aDestPoint, + aSrcBounds, + mpImpl->maBounds )) + { + if( isCompatibleAlphaMask( rAlphaMask ) ) + drawMaskedColor_i( rSrcColor, rAlphaMask, aSrcRange, aDestPoint ); + else + OSL_ENSURE( false, "Generic output not yet implemented!" ); + } +} + +void BitmapDevice::drawMaskedColor( Color rSrcColor, + const BitmapDeviceSharedPtr& rAlphaMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IPoint& rDstPoint, + const BitmapDeviceSharedPtr& rClip ) +{ + 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( NULL, + aSrcRange, + aDestPoint, + aSrcBounds, + mpImpl->maBounds )) + { + if( isCompatibleAlphaMask( rAlphaMask ) && + isCompatibleClipMask( rClip ) ) + { + drawMaskedColor_i( rSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip ); + } + else + { + OSL_ENSURE( false, "Generic output not yet implemented!" ); + } + } +} + +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::B2IPoint aDestPoint( rDstRect.getMinimum() ); + basegfx::B2IRange aDestRange; + + // TODO(F2): Scaling/shrinking + if( clipAreaImpl( &aDestRange, + aSrcRange, + aDestPoint, + aSrcBounds, + mpImpl->maBounds )) + { + if( isCompatibleBitmap( rSrcBitmap ) && + isCompatibleClipMask( rMask ) ) + { + drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode ); + } + else + { + OSL_ENSURE( false, "Generic output not yet implemented!" ); + } + } +} + +void BitmapDevice::drawMaskedBitmap( const BitmapDeviceSharedPtr& rSrcBitmap, + const BitmapDeviceSharedPtr& rMask, + const basegfx::B2IRange& rSrcRect, + const basegfx::B2IRange& rDstRect, + DrawMode drawMode, + const BitmapDeviceSharedPtr& rClip ) +{ + 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::B2IPoint aDestPoint( rDstRect.getMinimum() ); + basegfx::B2IRange aDestRange; + + // TODO(F2): Scaling/shrinking + if( clipAreaImpl( &aDestRange, + aSrcRange, + aDestPoint, + aSrcBounds, + mpImpl->maBounds )) + { + if( isCompatibleBitmap( rSrcBitmap ) && + isCompatibleClipMask( rMask ) && + isCompatibleClipMask( rClip ) ) + { + drawMaskedBitmap_i( rSrcBitmap, rMask, aSrcRange, aDestRange, drawMode, rClip ); + } + else + { + OSL_ENSURE( false, "Generic output not yet implemented!" ); + } + } +} + + +//---------------------------------------------------------------------------------- + +typedef PaletteImageAccessor<Color,sal_uInt8> PaletteAccessor; +typedef BitmapRenderer<MaskIterator,PaletteAccessor > OneBitMsbPaletteRenderer; +typedef BitmapRenderer<AlphaMaskIterator,AlphaMaskAccessor> EightBitTrueColorRenderer; +typedef PixelIterator<Color> ThirtyTwoBitPixelIterator; +typedef BitmapRenderer<ThirtyTwoBitPixelIterator, + vigra::AccessorTraits<Color>::default_accessor> ThirtyTwoBitTrueColorRenderer; + +BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize, + bool bTopDown, + sal_Int32 nScanlineFormat ) +{ + sal_Int32 nScanlineStride(0); + + // HACK: 1bpp and 24bpp only, currently + if( nScanlineFormat == Format::ONE_BIT_MSB_PAL ) + nScanlineStride = (rSize.getX() + 7) >> 3; + else if( nScanlineFormat == Format::EIGHT_BIT_TC_MASK ) + nScanlineStride = rSize.getX(); + else if( nScanlineFormat == Format::THIRTYTWO_BIT_TC_MASK ) + nScanlineStride = 4*rSize.getX(); + + nScanlineStride *= bTopDown ? 1 : -1; + + const std::size_t nMemSize( + (nScanlineStride < 0 ? -nScanlineStride : nScanlineStride)*rSize.getY() ); + + boost::shared_ptr< sal_uInt8 > pMem( + reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )), + &rtl_freeMemory ); + sal_uInt8* pFirstScanline = nScanlineStride < 0 ? + pMem.get() + nMemSize : pMem.get(); + + rtl_zeroMemory(pMem.get(),nMemSize); + + switch( nScanlineFormat ) + { + case Format::ONE_BIT_MSB_PAL: + { + static Color bwPalette[] = { Color(0x00000000), + Color(0xFFFFFFFF) }; + + return BitmapDeviceSharedPtr( + new OneBitMsbPaletteRenderer( + rSize, + bTopDown, + nScanlineFormat, + nScanlineStride, + MaskIterator(pFirstScanline, + nScanlineStride), + MaskIterator(pFirstScanline, + nScanlineStride) + + vigra::Diff2D(rSize.getX(), + rSize.getY()), + PaletteAccessor( bwPalette, + sizeof(bwPalette)/sizeof(*bwPalette)), + pMem )); + } + + case Format::EIGHT_BIT_TC_MASK: + { + return BitmapDeviceSharedPtr( + new EightBitTrueColorRenderer( + rSize, + bTopDown, + nScanlineFormat, + nScanlineStride, + AlphaMaskIterator(pFirstScanline, + nScanlineStride), + AlphaMaskIterator(pFirstScanline, + nScanlineStride) + + vigra::Diff2D(rSize.getX(), + rSize.getY()), + AlphaMaskAccessor(), + pMem )); + } + + case Format::THIRTYTWO_BIT_TC_MASK: + { + return BitmapDeviceSharedPtr( + new ThirtyTwoBitTrueColorRenderer( + rSize, + bTopDown, + nScanlineFormat, + nScanlineStride, + ThirtyTwoBitPixelIterator(reinterpret_cast<Color*>(pFirstScanline), + nScanlineStride), + ThirtyTwoBitPixelIterator(reinterpret_cast<Color*>(pFirstScanline), + nScanlineStride) + + vigra::Diff2D(rSize.getX(), + rSize.getY()), + vigra::AccessorTraits<Color>::default_accessor(), + pMem )); + } + + default: + // TODO(F3): other formats not yet implemented + return BitmapDeviceSharedPtr(); + } +} + +} // namespace basebmp diff --git a/basebmp/source/debug.cxx b/basebmp/source/debug.cxx new file mode 100644 index 000000000000..cb168a82db9f --- /dev/null +++ b/basebmp/source/debug.cxx @@ -0,0 +1,117 @@ +/************************************************************************* + * + * $RCSfile: debug.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:44 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#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_PAL: + return "ONE_BIT_MSB_PAL"; + case Format::EIGHT_BIT_TC_MASK: + return "EIGHT_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 memory dump */" << std::endl + << "/* Width = " << aSize.getX() << " */" << std::endl + << "/* Height = " << aSize.getY() << " */" << std::endl + << "/* TopDown = " << bTopDown << " */" << std::endl + << "/* Format = " << getFormatString(nScanlineFormat) << " */" << 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) ) << " "; + rOutputStream << std::endl; + } + } +} diff --git a/basebmp/source/makefile.mk b/basebmp/source/makefile.mk new file mode 100644 index 000000000000..827b53606b07 --- /dev/null +++ b/basebmp/source/makefile.mk @@ -0,0 +1,54 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1 $ +# +# last change: $Author: thb $ $Date: 2006-05-31 09:49:44 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library 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 for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/ + +PRJNAME=basebmp +TARGET=wrapper +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Common ---------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/bitmapdevice.obj \ + $(SLO)$/debug.obj + +# ========================================================================== + +.INCLUDE : target.mk diff --git a/basebmp/test/basictest.cxx b/basebmp/test/basictest.cxx new file mode 100644 index 000000000000..ef819c81ab6e --- /dev/null +++ b/basebmp/test/basictest.cxx @@ -0,0 +1,133 @@ +// autogenerated file with codegen.pl + +#include <cppunit/simpleheader.hxx> + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/point/b2ipoint.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> + +using namespace ::basebmp; + +namespace +{ + +class BasicTest : public CppUnit::TestFixture +{ +public: + void testConstruction() + { + const basegfx::B2ISize aSize(101,101); + basegfx::B2ISize aSize2(aSize); + BitmapDeviceSharedPtr pDevice( createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL )); + CPPUNIT_ASSERT_MESSAGE("right size", + pDevice->getSize() == aSize2 ); + CPPUNIT_ASSERT_MESSAGE("Top down format", + pDevice->isTopDown() == true ); + CPPUNIT_ASSERT_MESSAGE("Scanline format", + pDevice->getScanlineFormat() == Format::ONE_BIT_MSB_PAL ); + CPPUNIT_ASSERT_MESSAGE("Scanline len", + pDevice->getScanlineStride() == (aSize2.getY() + 7)/8 ); + } + + void testPixelFuncs() + { + // 1bpp + const basegfx::B2ISize aSize(101,101); + BitmapDeviceSharedPtr pDevice( createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL )); + + const basegfx::B2IPoint aPt(3,3); + const Color aCol(0xFFFFFFFF); + pDevice->setPixel( aPt, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #1", + pDevice->getPixel(aPt) == aCol); + + const basegfx::B2IPoint aPt2(0,0); + const Color aCol2(0xFFFFFFFF); + pDevice->setPixel( aPt2, aCol2, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #2", + pDevice->getPixel(aPt2) == aCol2); + + const basegfx::B2IPoint aPt3(aSize.getX()-1,aSize.getY()-1); + const Color aCol3(0x00000000); + pDevice->setPixel( aPt3, aCol3, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #3", + pDevice->getPixel(aPt3) == aCol3); + + const basegfx::B2IPoint aPt4(-100000,-100000); + pDevice->setPixel( aPt4, aCol3, DrawMode_PAINT ); + const basegfx::B2IPoint aPt5(100000,100000); + pDevice->setPixel( aPt5, aCol3, DrawMode_PAINT ); + + // 8bpp + { + pDevice = createBitmapDevice( aSize, + true, + Format::EIGHT_BIT_TC_MASK ); + + const Color aCol4(0x01); + pDevice->setPixel( aPt, aCol4, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #4", + pDevice->getPixel(aPt) == aCol4); + + const Color aCol5(0x0F); + pDevice->setPixel( aPt2, aCol5, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #5", + pDevice->getPixel(aPt2) == aCol5); + + const Color aCol6(0xFF); + pDevice->setPixel( aPt3, aCol6, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #6", + pDevice->getPixel(aPt3) == aCol6); + } + + // 32bpp + { + pDevice = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + + const Color aCol4(0x01010101); + pDevice->setPixel( aPt, aCol4, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #7", + pDevice->getPixel(aPt) == aCol4); + + const Color aCol5(0x0F0F0F0F); + pDevice->setPixel( aPt2, aCol5, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #8", + pDevice->getPixel(aPt2) == aCol5); + + const Color aCol6(0xFFFFFFFF); + pDevice->setPixel( aPt3, aCol6, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("get/setPixel roundtrip #9", + pDevice->getPixel(aPt3) == aCol6); + } + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(BasicTest); + CPPUNIT_TEST(testConstruction); + CPPUNIT_TEST(testPixelFuncs); + CPPUNIT_TEST_SUITE_END(); +}; + +// ----------------------------------------------------------------------------- +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(BasicTest, "BasicTest"); +} + + +// ----------------------------------------------------------------------------- + +// this macro creates an empty function, which will called by the RegisterAllFunctions() +// to let the user the possibility to also register some functions by hand. +NOADDITIONAL; + diff --git a/basebmp/test/bmpdemo.cxx b/basebmp/test/bmpdemo.cxx new file mode 100644 index 000000000000..29d5c143b4af --- /dev/null +++ b/basebmp/test/bmpdemo.cxx @@ -0,0 +1,1278 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: bmpdemo.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: thb $ $Date: 2006-05-31 09:49:44 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef _USE_MATH_DEFINES +#define _USE_MATH_DEFINES // needed by Visual C++ for math constants +#endif +#include <math.h> + +#include <comphelper/processfactory.hxx> +#include <comphelper/regpathhelper.hxx> +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> + +#include <ucbhelper/contentbroker.hxx> +#include <ucbhelper/configurationkeys.hxx> + +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/unowrap.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/bmpacc.hxx> + +#include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/point/b2ipoint.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> + +#include <rtl/bootstrap.hxx> + +#include <vigra/metaprogramming.hxx> +#include <vigra/static_assert.hxx> +#include <vigra/resizeimage.hxx> +#include <vigra/basicimageview.hxx> + +#include <boost/static_assert.hpp> +#include <algorithm> + +using namespace ::com::sun::star; + + +namespace +{ + +/// template meta function: add const qualifier, if given 2nd type has it +template<typename A, typename B> struct clone_const +{ + typedef B type; +}; +template<typename A, typename B> struct clone_const<const A,B> +{ + typedef const B type; +}; + +template< class DestIterator, class DestAccessor > class Renderer : + public basegfx::B2DPolyPolygonRasterConverter +{ +private: + typename DestIterator::value_type fillColor_; + typename DestIterator::value_type clearColor_; + DestIterator begin_; + DestAccessor accessor_; + +public: + Renderer(const basegfx::B2DPolyPolygon& rPolyPolyRaster, + typename DestIterator::value_type fillColor, + typename DestIterator::value_type clearColor, + DestIterator begin, + DestIterator end, + DestAccessor accessor ) : + B2DPolyPolygonRasterConverter(rPolyPolyRaster, + basegfx::B2DRange(0,0, + end.x - end.x, + begin.y - begin.y )), + fillColor_( fillColor ), + clearColor_( clearColor ), + begin_( begin ), + accessor_( accessor ) + { + } + + virtual void span(const double& rfXLeft, + const double& rfXRight, + sal_Int32 nY, + bool bOn ) + { + DestIterator currIter( begin_ + vigra::Diff2D(0,nY) ); + typename DestIterator::row_iterator rowIter( currIter.rowIterator() + + basegfx::fround(rfXLeft) ); + typename DestIterator::row_iterator rowEnd( currIter.rowIterator() + + basegfx::fround(rfXRight) ); + if( bOn ) + while( rowIter != rowEnd ) + { + accessor_.set(fillColor_, rowIter); + ++rowIter; + } + else + while( rowIter != rowEnd ) + { + accessor_.set(accessor_(rowIter)*clearColor_, rowIter); + ++rowIter; + } + } +}; + +template< class DestIterator, class DestAccessor > + std::auto_ptr< Renderer< DestIterator, DestAccessor > > makeRenderer( + const basegfx::B2DPolyPolygon& rPolyPolyRaster, + typename DestIterator::value_type fillColor, + typename DestIterator::value_type clearColor, + vigra::triple<DestIterator, DestIterator, DestAccessor> dest ) +{ + return std::auto_ptr< Renderer< DestIterator, DestAccessor > >( + new Renderer< DestIterator, DestAccessor >(rPolyPolyRaster, + fillColor, + clearColor, + dest.first, + dest.second, + dest.third)); +} + + +// changed semantics re. DirectionSelector<StridedArrayTag>: stride +// now counts in <em>raw</em> bytes! +template< typename T > class StridedArrayIterator +{ +public: + typedef typename clone_const<T, unsigned char>::type internal_type; + + StridedArrayIterator(int stride, T* ptr = 0) : + stride_(stride), + current_(reinterpret_cast<internal_type*>(ptr)) + {} + + /// Copy from other StridedArrayIterator, plus given offset + StridedArrayIterator( StridedArrayIterator const& rSrc, + int offset ) : + stride_(rSrc.stride_), + current_(reinterpret_cast<internal_type*>( + reinterpret_cast<T*>(rSrc.current_)+offset)) + {} + + void operator++() {current_ += stride_; } + void operator++(int) {current_ += stride_; } + void operator--() {current_ -= stride_; } + void operator--(int) {current_ -= stride_; } + void operator+=(int dy) {current_ += dy*stride_; } + void operator-=(int dy) {current_ -= dy*stride_; } + + bool operator==(StridedArrayIterator const & rhs) const + { return (current_ == rhs.current_); } + + bool operator!=(StridedArrayIterator const & rhs) const + { return (current_ != rhs.current_); } + + bool operator<(StridedArrayIterator const & rhs) const + { return (current_ < rhs.current_); } + + bool operator<=(StridedArrayIterator const & rhs) const + { return (current_ <= rhs.current_); } + + bool operator>(StridedArrayIterator const & rhs) const + { return (current_ > rhs.current_); } + + bool operator>=(StridedArrayIterator const & rhs) const + { return (current_ >= rhs.current_); } + + int operator-(StridedArrayIterator const & rhs) const + { return (current_ - rhs.current_) / stride_; } + + T* operator()() const + { return reinterpret_cast<T*>(current_); } + + T* operator()(int d) const + { return reinterpret_cast<T*>(current_ + d*stride_); } + + int stride_; + internal_type* current_; +}; + +/// template meta function: remove const qualifier from plain type +template <typename T> struct remove_const +{ + typedef T type; +}; +template <typename T> struct remove_const<const T> +{ + typedef T type; +}; + +/// returns true, if given number is strictly less than 0 +template< typename T > inline bool is_negative( T x ) +{ + return x < 0; +} + +/// Overload for ints (branch-free) +inline bool is_negative( int x ) +{ + // force logic shift (result for signed shift right is undefined) + return static_cast<unsigned int>(x) >> (sizeof(int)*8-1); +} + +/// Get bitmask for data at given intra-word position, for given bit depth +template< typename data_type, int bits_per_pixel, bool MsbFirst, typename difference_type > inline data_type get_mask( difference_type d ) +{ + BOOST_STATIC_ASSERT(bits_per_pixel > 0); + BOOST_STATIC_ASSERT(sizeof(data_type)*8 % bits_per_pixel == 0); + BOOST_STATIC_ASSERT(sizeof(data_type)*8 / bits_per_pixel > 1); + BOOST_STATIC_ASSERT(vigra::TypeTraits<data_type>::isPOD::asBool); + + const unsigned int nIntraWordPositions( sizeof(data_type)*8 / bits_per_pixel ); + + // create bits_per_pixel 1s shift to intra-word position + return ((~(~0 << bits_per_pixel)) << bits_per_pixel*(MsbFirst ? + (nIntraWordPositions-1 - (d % nIntraWordPositions)) : + (d % nIntraWordPositions))); +} + +template< int num_intraword_positions, int bits_per_pixel, bool MsbFirst, typename difference_type > inline difference_type get_shift( difference_type remainder ) +{ + return bits_per_pixel*(MsbFirst ? + (num_intraword_positions - 1 - remainder) : + remainder); +} + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelColumnIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef typename remove_const<data_type>::type mask_type; + typedef data_type* pointer; + typedef StridedArrayIterator< data_type > MoveY; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + +private: + MoveY y; + mask_type mask_; + difference_type shift_; + + void inc() + { + ++y; + } + + void dec() + { + --y; + } + + bool equal( PackedPixelColumnIterator const & rhs ) const + { + return rhs.y == y; + } + + bool less( PackedPixelColumnIterator const & rhs ) const + { + return y < rhs.y; + } + +public: + PackedPixelColumnIterator() : + y(0), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst, difference_type>(0) ) + {} + + PackedPixelColumnIterator( const MoveY& base, difference_type remainder ) : + y(base), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ), + shift_( get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder) ) + {} + + PackedPixelColumnIterator& operator+=( difference_type d ) + { + y += d; + return *this; + } + + PackedPixelColumnIterator& operator-=( difference_type d ) + { + y -= d; + return *this; + } + + PackedPixelColumnIterator operator+( difference_type d ) + { + PackedPixelColumnIterator res(*this); + res += d; + return res; + } + + PackedPixelColumnIterator operator-( difference_type d ) + { + PackedPixelColumnIterator res(*this); + res -= d; + return res; + } + + PackedPixelColumnIterator& operator++() + { + inc(); + return *this; + } + + PackedPixelColumnIterator& operator--() + { + dec(); + return *this; + } + + PackedPixelColumnIterator operator++(int) + { + PackedPixelColumnIterator res(*this); + res.inc(); + return res; + } + + PackedPixelColumnIterator operator--(int) + { + PackedPixelColumnIterator res(*this); + res.dec(); + return res; + } + + bool operator==(PackedPixelColumnIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PackedPixelColumnIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PackedPixelColumnIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PackedPixelColumnIterator const & rhs) const + { + return !less(rhs); + } + + bool operator>(PackedPixelColumnIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PackedPixelColumnIterator const & rhs) const + { + return !rhs.less(*this); + } + + difference_type operator-(PackedPixelColumnIterator const & rhs) const + { + return y - rhs.y; + } + + value_type get() const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*y() & mask_) >> shift_; + } + + value_type get(difference_type d) const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*y(d) & mask_) >> shift_; + } + + void set( value_type v ) const + { + const value_type pixel_value( (v << shift_) & mask_ ); + *y() = (*y() & ~mask_) | pixel_value; + } + + void set( value_type v, difference_type d ) const + { + const value_type pixel_value( (v << shift_) & mask_ ); + *y(d) = (*y(d) & ~mask_) | pixel_value; + } +}; + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelRowIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef int difference_type; + typedef image_traverser_tag iterator_category; + + typedef typename remove_const<data_type>::type mask_type; + typedef data_type* pointer; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + +private: + pointer data_; + mask_type mask_; + difference_type remainder_; + + void update_mask() + { + mask_ = get_mask<data_type, bits_per_pixel, MsbFirst>(remainder_); + } + + void inc() + { + const difference_type newValue( remainder_ + 1 ); + const difference_type data_offset( newValue / num_intraword_positions ); + + data_ += data_offset; + remainder_ = newValue % num_intraword_positions; + + const mask_type shifted_mask( + MsbFirst ? + // TODO(Q3): use traits to get unsigned type for data_type + // (if not already) + static_cast<unsigned int>(mask_) >> bits_per_pixel : + mask_ << bits_per_pixel ); + + // data_offset is 0 for shifted mask, and 1 for wrapped-around mask + mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ? + bit_mask << bits_per_pixel*(num_intraword_positions-1) : + bit_mask); + } + + void dec() + { + const difference_type newValue( remainder_ - 1 ); + const bool isNegative( is_negative(newValue) ); + const difference_type newRemainder( newValue % num_intraword_positions ); + + // calc data_ += newValue / num_intraword_positions; + // remainder_ = newRemainder; + // for newValue >= 0, and + // data_ += newValue / num_intraword_positions - 1; + // remainder_ = num_intraword_positions - newRemainder; + // (to force remainder_ to be positive). + // This is branch-free, if is_negative() is branch-free + const difference_type data_offset( newValue / num_intraword_positions - isNegative ); + data_ += data_offset; + remainder_ = newRemainder + isNegative*num_intraword_positions; + + const mask_type shifted_mask( + MsbFirst ? + mask_ << bits_per_pixel : + // TODO(Q3): use traits to get unsigned type for data_type + // (if not already) + static_cast<unsigned int>(mask_) >> bits_per_pixel ); + + // data_offset is 0 for shifted mask, and 1 for wrapped-around mask + mask_ = (1-data_offset)*shifted_mask + data_offset*(MsbFirst ? + bit_mask : + bit_mask << bits_per_pixel*(num_intraword_positions-1)); + } + + bool equal( PackedPixelRowIterator const & rhs ) const + { + return rhs.data_ == data_ && rhs.remainder_ == remainder_; + } + + bool less( PackedPixelRowIterator const & rhs ) const + { + return data_ == rhs.data_ ? + (remainder_ < rhs.remainder_) : + (data_ < rhs.data_); + } + +public: + PackedPixelRowIterator() : + data_(0), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + remainder_(0) + {} + + explicit PackedPixelRowIterator( pointer base ) : + data_(base), + mask_( get_mask<data_type, bits_per_pixel, MsbFirst, difference_type>(0) ), + remainder_(0) + {} + + PackedPixelRowIterator& operator+=( difference_type d ) + { + const difference_type newValue( remainder_ + d ); + + data_ += newValue / num_intraword_positions; + remainder_ = newValue % num_intraword_positions; + update_mask(); + + return *this; + } + + PackedPixelRowIterator& operator-=( difference_type d ) + { + const difference_type newValue( remainder_ - d ); + const bool isNegative( is_negative(newValue) ); + const difference_type newRemainder( newValue % num_intraword_positions ); + + // calc data_ += newValue / num_intraword_positions; + // remainder_ = newRemainder; + // for newValue >= 0, and + // data_ += newValue / num_intraword_positions - 1; + // remainder_ = num_intraword_positions - newRemainder; + // (to force remainder_ to be positive). + // This is branch-free, if is_negative() is branch-free + data_ += newValue / num_intraword_positions - isNegative; + remainder_ = newRemainder + isNegative*(num_intraword_positions - 2*newRemainder); + update_mask(); + + return *this; + } + + PackedPixelRowIterator operator+( difference_type d ) + { + PackedPixelRowIterator res(*this); + res += d; + return res; + } + + PackedPixelRowIterator operator-( difference_type d ) + { + PackedPixelRowIterator res(*this); + res -= d; + return res; + } + + PackedPixelRowIterator& operator++() + { + inc(); + return *this; + } + + PackedPixelRowIterator& operator--() + { + dec(); + return *this; + } + + PackedPixelRowIterator operator++(int) + { + PackedPixelRowIterator res(*this); + res.inc(); + return res; + } + + PackedPixelRowIterator operator--(int) + { + PackedPixelRowIterator res(*this); + res.dec(); + return res; + } + + bool operator==(PackedPixelRowIterator const & rhs) const + { + return equal( rhs ); + } + + bool operator!=(PackedPixelRowIterator const & rhs) const + { + return !equal( rhs ); + } + + bool operator<(PackedPixelRowIterator const & rhs) const + { + return less(rhs); + } + + bool operator<=(PackedPixelRowIterator const & rhs) const + { + return !less(rhs); + } + + bool operator>(PackedPixelRowIterator const & rhs) const + { + return rhs.less(*this); + } + + bool operator>=(PackedPixelRowIterator const & rhs) const + { + return !rhs.less(*this); + } + + difference_type operator-(PackedPixelRowIterator const & rhs) const + { + return (data_ - rhs.data_)*num_intraword_positions + (remainder_ - rhs.remainder_); + } + + value_type get() const + { + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return static_cast<unsigned int>(*data_ & mask_) >> + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_); + } + + value_type get(difference_type d) const + { + PackedPixelRowIterator tmp(*this); + tmp += d; + return tmp.get(); + } + + void set( value_type v ) const + { + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder_)) + & mask_ ); + *data_ = (*data_ & ~mask_) | pixel_value; + } + + void set( value_type v, difference_type d ) const + { + PackedPixelRowIterator tmp(*this); + tmp += d; + tmp.set(v); + } +}; + +template< typename Datatype, + typename Valuetype, + int bits_per_pixel, + bool MsbFirst > class PackedPixelIterator +{ +public: + // no reference, no index_reference type here + typedef Datatype data_type; + typedef Valuetype value_type; + typedef vigra::Diff2D difference_type; + typedef image_traverser_tag iterator_category; + typedef PackedPixelRowIterator<data_type, + value_type, + bits_per_pixel, + MsbFirst> row_iterator; + typedef PackedPixelColumnIterator<data_type, + value_type, + bits_per_pixel, + MsbFirst> column_iterator; + + typedef data_type* pointer; + typedef int MoveX; + typedef StridedArrayIterator< data_type > MoveY; + + enum { + /** The number of pixel within a single data_type value + */ + num_intraword_positions=sizeof(data_type)*8/bits_per_pixel, + /** Bit mask for one pixel (least significant bits) + */ + bit_mask=~(~0 << bits_per_pixel) + }; + + // TODO(F2): direction of iteration (ImageIterator can be made to + // run backwards) + +private: + pointer current() const + { + return y() + (x / num_intraword_positions); + } + + pointer current(int dx, int dy) const + { + return y(dy) + ((x+dx)/num_intraword_positions); + } + + bool equal(PackedPixelIterator const & rhs) const + { + return (x == rhs.x) && (y == rhs.y); + } + +public: + PackedPixelIterator() : + x(0), + y(0) + {} + + PackedPixelIterator(pointer base, int ystride) : + x(0), + y(ystride,base) + {} + + bool operator==(PackedPixelIterator const & rhs) const + { + return equal(rhs); + } + + bool operator!=(PackedPixelIterator const & rhs) const + { + return !equal(rhs); + } + + difference_type operator-(PackedPixelIterator const & rhs) const + { + return difference_type(x - rhs.x, y - rhs.y); + } + + MoveX x; + MoveY y; + + PackedPixelIterator & operator+=(difference_type const & s) + { + x += s.x; + y += s.y; + return *this; + } + + PackedPixelIterator & operator-=(difference_type const & s) + { + x -= s.x; + y -= s.y; + return *this; + } + + PackedPixelIterator operator+(difference_type const & s) const + { + PackedPixelIterator ret(*this); + ret += s; + return ret; + } + + PackedPixelIterator operator-(difference_type const & s) const + { + PackedPixelIterator ret(*this); + ret -= s; + return ret; + } + + row_iterator rowIterator() const + { + return row_iterator(current()); + } + + column_iterator columnIterator() const + { + return column_iterator(MoveY(y, + x / num_intraword_positions), + x % num_intraword_positions); + } + + value_type get() const + { + const int remainder( x() % num_intraword_positions ); + + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return (static_cast<unsigned int>(*current() & + get_mask<data_type, bits_per_pixel, MsbFirst>(remainder)) + >> (MsbFirst ? + (num_intraword_positions - remainder) : + remainder)); + } + + value_type get(difference_type const & d) const + { + const int remainder( x(d.x) % num_intraword_positions ); + + // TODO(Q3): use traits to get unsigned type for data_type (if + // not already) + return (static_cast<unsigned int>(*current(d.x,d.y) & + get_mask<data_type, bits_per_pixel, MsbFirst>(remainder)) + >> get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)); + } + + void set( value_type v ) const + { + const int remainder( x() % num_intraword_positions ); + const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ); + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)) + & mask ); + pointer p = current(); + *p = (*p & ~mask) | pixel_value; + } + + void set( value_type v, difference_type const & d ) const + { + const int remainder( x(d.x) % num_intraword_positions ); + const int mask( get_mask<data_type, bits_per_pixel, MsbFirst>(remainder) ); + const value_type pixel_value( + (v << + get_shift<num_intraword_positions, bits_per_pixel, MsbFirst>(remainder)) + & mask ); + pointer p = current(d.x,d.y); + *p = (*p & ~mask) | pixel_value; + } +}; + + +/** Access (possibly packed-pixel) data via palette indirection + */ +template< typename Valuetype, typename Datatype > class PaletteImageAccessor +{ + public: + typedef Valuetype value_type; + typedef Datatype data_type; + typedef typename remove_const<data_type>::type count_type; + + +private: + const BitmapColor* palette; + count_type num_entries; + + double norm( BitmapColor const& rLHS, + BitmapColor const& rRHS ) const + { + // convert RGBValue's linear space to a normed linear space + return sqrt( + vigra::sq(rLHS.GetRed()-rRHS.GetRed()) + + vigra::sq(rLHS.GetGreen()-rRHS.GetGreen()) + + vigra::sq(rLHS.GetBlue()-rRHS.GetBlue()) ); + } + + data_type find_best_match(value_type const& v) const + { + // TODO(F3): not generic!!! + const BitmapColor aTmpCol(v.red(), + v.green(), + v.blue()); + + // TODO(P3): use table-based/octree approach here! + const BitmapColor* best_entry; + const BitmapColor* palette_end( palette+num_entries ); + if( (best_entry=std::find( palette, palette_end, aTmpCol)) != palette_end ) + return best_entry-palette; + + // TODO(F3): HACK. Need palette traits, and an error function + // here. We blatantly assume value_type is a normed linear + // space. + const BitmapColor* curr_entry( palette ); + best_entry = curr_entry; + while( curr_entry != palette_end ) + { + if( norm(*curr_entry,*best_entry) > norm(*curr_entry,aTmpCol) ) + best_entry = curr_entry; + + ++curr_entry; + } + + return best_entry-palette; + } + + value_type toCol( BitmapColor const& rCol ) const + { + return value_type(rCol.GetRed(),rCol.GetGreen(),rCol.GetBlue()); + } + +public: + PaletteImageAccessor() : + palette(0), + num_entries(0) + {} + + PaletteImageAccessor( const BitmapColor* pPalette, + data_type entries ) : + palette(pPalette), + num_entries(entries) + {} + + template< class Iterator > + value_type operator()(Iterator const& i) const { return toCol(palette[i.get()]); } + value_type operator()(data_type const* i) const { return toCol(palette[*i]); } + + template< class Iterator, class Difference > + value_type operator()(Iterator const& i, Difference const& diff) const + { + return toCol(palette[i.get(diff)]); + } + + template< typename V, class Iterator > + void set(V const& value, Iterator const& i) const + { + i.set( + find_best_match( + vigra::detail::RequiresExplicitCast<value_type>::cast(value) )); + } + + template< typename V, class Iterator, class Difference > + void set(V const& value, Iterator const& i, Difference const& diff) const + { + i.set( + find_best_match( + vigra::detail::RequiresExplicitCast<value_type>::cast(value)), + diff ); + } +}; + +} + + +class TestApp : public Application +{ +public: + virtual void Main(); + virtual USHORT Exception( USHORT nError ); +}; + +class TestWindow : public Dialog +{ + public: + TestWindow() : Dialog( (Window *) NULL ) + { + SetText( rtl::OUString::createFromAscii( "VIGRA test" ) ); + SetSizePixel( Size( 1024, 500 ) ); + EnablePaint( true ); + Show(); + } + virtual ~TestWindow() {} + virtual void MouseButtonUp( const MouseEvent& rMEvt ) + { + //TODO: do something cool + EndDialog(); + } + virtual void Paint( const Rectangle& rRect ); +}; + +void TestWindow::Paint( const Rectangle& rRect ) +{ + { + const basegfx::B2ISize aSize(11,11); + basebmp::BitmapDeviceSharedPtr pDevice( basebmp::createBitmapDevice( aSize, + true, + basebmp::Format::THIRTYTWO_BIT_TC_MASK )); + + const basegfx::B2IPoint aPt1(1,1); + const basegfx::B2IPoint aPt2(1,9); + const basebmp::Color aCol(0); + pDevice->clear( aCol ); + const basebmp::Color aCol2(0xFFFFFFFF); + pDevice->drawLine( aPt1, aPt2, aCol2, basebmp::DrawMode_PAINT ); + } + + enum{ srcBitDepth=1, dstBitDepth=4 }; + typedef vigra::RGBValue< sal_uInt8 > RGBVal; + + Bitmap aSourceBitmap( Size(100,100), + srcBitDepth ); + DrawBitmap( Point(0,350), aSourceBitmap ); + + // Fill bitmap with rhombus + { + ScopedBitmapWriteAccess pWriteAccess( aSourceBitmap.AcquireWriteAccess(), + aSourceBitmap ); + pWriteAccess->SetFillColor(0xFF0000); + Polygon aPoly(5); + aPoly[0] = Point(50,0); + aPoly[1] = Point(100,50); + aPoly[2] = Point(50,100); + aPoly[3] = Point(0,50); + aPoly[4] = Point(50,0); + pWriteAccess->FillPolygon(aPoly); + } + + Bitmap aDestBitmap( Size(300,300), + dstBitDepth ); + + { + ScopedBitmapReadAccess pReadAccess( aSourceBitmap.AcquireReadAccess(), + aSourceBitmap ); + ScopedBitmapWriteAccess pWriteAccess( aDestBitmap.AcquireWriteAccess(), + aDestBitmap ); + + const sal_Int32 nSrcWidth( pReadAccess->Width() ); + const sal_Int32 nSrcHeight( pReadAccess->Height() ); + const bool bSrcTopDown( pReadAccess->IsTopDown() ); + const sal_uInt32 nSrcScanlineFormat( pReadAccess->GetScanlineFormat() ); + const sal_uInt32 nSrcScanlineStride( pReadAccess->GetScanlineSize() ); + const sal_uInt16 nSrcBitCount( pReadAccess->GetBitCount() ); + const sal_uInt16 nSrcPaletteEntries( pReadAccess->GetPaletteEntryCount() ); + const BitmapColor* pSrcPalette( &pReadAccess->GetPalette()[0] ); + const BYTE* pSrcBuffer = pReadAccess->GetBuffer(); + + const sal_Int32 nDstWidth( pWriteAccess->Width() ); + const sal_Int32 nDstHeight( pWriteAccess->Height() ); + const bool bDstTopDown( pWriteAccess->IsTopDown() ); + const sal_uInt32 nDstScanlineFormat( pWriteAccess->GetScanlineFormat() ); + const sal_uInt32 nDstScanlineStride( pWriteAccess->GetScanlineSize() ); + const sal_uInt16 nDstBitCount( pWriteAccess->GetBitCount() ); + const sal_uInt16 nDstPaletteEntries( pWriteAccess->GetPaletteEntryCount() ); + const BitmapColor* pDstPalette( &pWriteAccess->GetPalette()[0] ); + BYTE* pDstBuffer = pWriteAccess->GetBuffer(); + + typedef PackedPixelIterator< const BYTE, + BYTE, + srcBitDepth, + true > SrcPixelIterator; + typedef PaletteImageAccessor< RGBVal, BYTE > SrcImageAccessor; + + typedef PackedPixelIterator< BYTE, + BYTE, + dstBitDepth, + true > DstPixelIterator; + typedef PaletteImageAccessor< RGBVal, BYTE > DstImageAccessor; + + const SrcPixelIterator aStartImage( pSrcBuffer,nSrcScanlineStride ); + const SrcPixelIterator aEndImage( aStartImage + vigra::Diff2D(nSrcWidth,nSrcHeight) ); + + const DstPixelIterator aStartDstImage( pDstBuffer,nDstScanlineStride ); + const DstPixelIterator aEndDstImage( aStartDstImage + vigra::Diff2D(nDstWidth,nDstHeight) ); + + vigra::resizeImageNoInterpolation( + //vigra::resizeImageLinearInterpolation( + vigra::make_triple( + aStartImage, + aEndImage, + SrcImageAccessor( + pSrcPalette, + nSrcPaletteEntries)), + vigra::make_triple( + aStartDstImage, + aEndDstImage, + DstImageAccessor( + pDstPalette, + nDstPaletteEntries))); + } + + DrawBitmap( Point(), aDestBitmap ); + + + Bitmap aDestBitmap2( Size(300,300), + dstBitDepth ); + + { + ScopedBitmapReadAccess pReadAccess( aSourceBitmap.AcquireReadAccess(), + aSourceBitmap ); + ScopedBitmapWriteAccess pWriteAccess( aDestBitmap2.AcquireWriteAccess(), + aDestBitmap2 ); + + const sal_Int32 nSrcWidth( pReadAccess->Width() ); + const sal_Int32 nSrcHeight( pReadAccess->Height() ); + const bool bSrcTopDown( pReadAccess->IsTopDown() ); + const sal_uInt32 nSrcScanlineFormat( pReadAccess->GetScanlineFormat() ); + const sal_uInt32 nSrcScanlineStride( pReadAccess->GetScanlineSize() ); + const sal_uInt16 nSrcBitCount( pReadAccess->GetBitCount() ); + const sal_uInt16 nSrcPaletteEntries( pReadAccess->GetPaletteEntryCount() ); + const BitmapColor* pSrcPalette( &pReadAccess->GetPalette()[0] ); + const BYTE* pSrcBuffer = pReadAccess->GetBuffer(); + + const sal_Int32 nDstWidth( pWriteAccess->Width() ); + const sal_Int32 nDstHeight( pWriteAccess->Height() ); + const bool bDstTopDown( pWriteAccess->IsTopDown() ); + const sal_uInt32 nDstScanlineFormat( pWriteAccess->GetScanlineFormat() ); + const sal_uInt32 nDstScanlineStride( pWriteAccess->GetScanlineSize() ); + const sal_uInt16 nDstBitCount( pWriteAccess->GetBitCount() ); + const sal_uInt16 nDstPaletteEntries( pWriteAccess->GetPaletteEntryCount() ); + const BitmapColor* pDstPalette( &pWriteAccess->GetPalette()[0] ); + BYTE* pDstBuffer = pWriteAccess->GetBuffer(); + + typedef vigra::RGBValue< sal_uInt8 > RGBVal; + typedef PackedPixelIterator< const BYTE, + BYTE, + srcBitDepth, + true > SrcPixelIterator; + typedef PaletteImageAccessor< RGBVal,BYTE > SrcImageAccessor; + + typedef PackedPixelIterator< BYTE, + BYTE, + dstBitDepth, + true > DstPixelIterator; + typedef PaletteImageAccessor< RGBVal,BYTE > DstImageAccessor; + + const SrcPixelIterator aStartImage( pSrcBuffer,nSrcScanlineStride ); + const SrcPixelIterator aEndImage( aStartImage + vigra::Diff2D(nSrcWidth,nSrcHeight) ); + + const DstPixelIterator aStartDstImage( pDstBuffer,nDstScanlineStride ); + const DstPixelIterator aEndDstImage( aStartDstImage + vigra::Diff2D(nDstWidth,nDstHeight) ); + + vigra::resizeImageLinearInterpolation( + vigra::make_triple( + aStartImage, + aEndImage, + SrcImageAccessor( + pSrcPalette, + nSrcPaletteEntries)), + vigra::make_triple( + aStartDstImage, + aEndDstImage, + DstImageAccessor( + pDstPalette, + nDstPaletteEntries))); + } + + DrawBitmap( Point(310,0), aDestBitmap2 ); + + + Bitmap aDestBitmap3( Size(300,300), + 24 ); + + { + ScopedBitmapReadAccess pReadAccess( aSourceBitmap.AcquireReadAccess(), + aSourceBitmap ); + ScopedBitmapWriteAccess pWriteAccess( aDestBitmap3.AcquireWriteAccess(), + aDestBitmap3 ); + + const sal_Int32 nSrcWidth( pReadAccess->Width() ); + const sal_Int32 nSrcHeight( pReadAccess->Height() ); + const bool bSrcTopDown( pReadAccess->IsTopDown() ); + const sal_uInt32 nSrcScanlineFormat( pReadAccess->GetScanlineFormat() ); + const sal_uInt32 nSrcScanlineStride( pReadAccess->GetScanlineSize() ); + const sal_uInt16 nSrcBitCount( pReadAccess->GetBitCount() ); + const sal_uInt16 nSrcPaletteEntries( pReadAccess->GetPaletteEntryCount() ); + const BitmapColor* pSrcPalette( &pReadAccess->GetPalette()[0] ); + const BYTE* pSrcBuffer = pReadAccess->GetBuffer(); + + const sal_Int32 nDstWidth( pWriteAccess->Width() ); + const sal_Int32 nDstHeight( pWriteAccess->Height() ); + const bool bDstTopDown( pWriteAccess->IsTopDown() ); + const sal_uInt32 nDstScanlineFormat( pWriteAccess->GetScanlineFormat() ); + const sal_uInt32 nDstScanlineStride( pWriteAccess->GetScanlineSize() ); + const sal_uInt16 nDstBitCount( pWriteAccess->GetBitCount() ); + BYTE* pDstBuffer = pWriteAccess->GetBuffer(); + + vigra::BasicImageView< RGBVal > aDestImage( + reinterpret_cast<RGBVal*>(pDstBuffer), + nDstWidth, + nDstHeight, + 0 /*nDstScanlineStride should be an integer multiple of 4*/ ); + + typedef PackedPixelIterator< const BYTE, + BYTE, + srcBitDepth, + true > SrcPixelIterator; + typedef PaletteImageAccessor< RGBVal,BYTE > SrcImageAccessor; + + const SrcPixelIterator aStartImage( pSrcBuffer,nSrcScanlineStride ); + const SrcPixelIterator aEndImage( aStartImage + vigra::Diff2D(nSrcWidth,nSrcHeight) ); + + // resize bitmap + vigra::resizeImageSplineInterpolation( + vigra::make_triple( + aStartImage, + aEndImage, + SrcImageAccessor( + pSrcPalette, + nSrcPaletteEntries)), + vigra::destImageRange(aDestImage)); + + // add ellipse to bitmap + basegfx::B2DPolygon aPoly( + basegfx::tools::createPolygonFromEllipse( + basegfx::B2DPoint(150,150), + 50, 80 )); + aPoly = basegfx::tools::adaptiveSubdivideByCount(aPoly); + makeRenderer( basegfx::B2DPolyPolygon( aPoly ), + RGBVal(0,0xFF,0), + RGBVal(0xFF,0xFF,0xFF), + vigra::destImageRange(aDestImage) )->rasterConvert( + basegfx::FillRule_NONZERO_WINDING_NUMBER ); + } + + DrawBitmap( Point(620,0), aDestBitmap3 ); + DrawBitmap( Point(310,350), aSourceBitmap ); +} + +USHORT TestApp::Exception( USHORT nError ) +{ + switch( nError & EXC_MAJORTYPE ) + { + case EXC_RSCNOTLOADED: + Abort( String::CreateFromAscii( "Error: could not load language resources.\nPlease check your installation.\n" ) ); + break; + } + return 0; +} + +void TestApp::Main() +{ + //------------------------------------------------- + // create the global service-manager + //------------------------------------------------- + uno::Reference< lang::XMultiServiceFactory > xFactory; + try + { + uno::Reference< uno::XComponentContext > xCtx = ::cppu::defaultBootstrap_InitialComponentContext(); + xFactory = uno::Reference< lang::XMultiServiceFactory >( xCtx->getServiceManager(), + uno::UNO_QUERY ); + if( xFactory.is() ) + ::comphelper::setProcessServiceFactory( xFactory ); + } + catch( uno::Exception& ) + { + } + + if( !xFactory.is() ) + { + OSL_TRACE( "Could not bootstrap UNO, installation must be in disorder. Exiting.\n" ); + exit( 1 ); + } + + // Create UCB. + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[ 0 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY1_LOCAL ); + aArgs[ 1 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY2_OFFICE ); + ::ucb::ContentBroker::initialize( xFactory, aArgs ); + + TestWindow pWindow; + pWindow.Execute(); + + // clean up UCB + ::ucb::ContentBroker::deinitialize(); +} + +TestApp aDemoApp; diff --git a/basebmp/test/export.map b/basebmp/test/export.map new file mode 100644 index 000000000000..8cb6caacc51e --- /dev/null +++ b/basebmp/test/export.map @@ -0,0 +1,42 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: export.map,v $ +# +# $Revision: 1.1 $ +# +# last change: $Author: thb $ $Date: 2006-05-31 09:49:44 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library 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 for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +UDK_3.1 { + global: + registerAllTestFunction; + + local: + *; +}; diff --git a/basebmp/test/filltest.cxx b/basebmp/test/filltest.cxx new file mode 100644 index 000000000000..8a458cac573f --- /dev/null +++ b/basebmp/test/filltest.cxx @@ -0,0 +1,113 @@ +// autogenerated file with codegen.pl + +#include <cppunit/simpleheader.hxx> + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include <basebmp/debug.hxx> + +#include <iostream> +#include <fstream> + +using namespace ::basebmp; + +namespace +{ +/* + std::ofstream output("32bpp_test.dump"); + debugDump( mpDevice32bpp, output ); +*/ + +class FillTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + + int countPixel( const BitmapDeviceSharedPtr& rDevice, + Color checkColor ) const + { + int count(0); + const basegfx::B2ISize& rSize( rDevice->getSize() ); + for( sal_Int32 y=0; y<rSize.getY(); ++y ) + for( sal_Int32 x=0; x<rSize.getX(); ++x ) + if( rDevice->getPixel( basegfx::B2IPoint(x,y) ) == checkColor ) + ++count; + + return count; + } + + void implTestRectFill(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2DRange aRect(1,1,10,10); + const basegfx::B2DPolygon aRectPoly( + basegfx::tools::createPolygonFromRect( aRect )); + + const Color aCol(0xFFFFFFFF); + rDevice->fillPolyPolygon( basegfx::B2DPolyPolygon(aRectPoly), + aCol, + DrawMode_PAINT ); + const basegfx::B2IPoint aPt1(1,1); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + const basegfx::B2IPoint aPt2(9,9); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + const basegfx::B2IPoint aPt3(0,0); + CPPUNIT_ASSERT_MESSAGE("topmost pixel not set", + rDevice->getPixel(aPt3) != aCol); + const basegfx::B2IPoint aPt4(10,10); + CPPUNIT_ASSERT_MESSAGE("bottommost pixel not set", + rDevice->getPixel(aPt4) != aCol); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 81", + countPixel( rDevice, aCol ) == 81); + } + +public: + void setUp() + { + const basegfx::B2ISize aSize(11,11); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + } + + void testRectFill() + { + implTestRectFill( mpDevice1bpp ); + implTestRectFill( mpDevice32bpp ); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(FillTest); + CPPUNIT_TEST(testRectFill); + CPPUNIT_TEST_SUITE_END(); +}; + +// ----------------------------------------------------------------------------- +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(FillTest, "FillTest"); +} + + +// ----------------------------------------------------------------------------- + +// this macro creates an empty function, which will called by the RegisterAllFunctions() +// to let the user the possibility to also register some functions by hand. +//NOADDITIONAL; + diff --git a/basebmp/test/linetest.cxx b/basebmp/test/linetest.cxx new file mode 100644 index 000000000000..12e82cd0de3a --- /dev/null +++ b/basebmp/test/linetest.cxx @@ -0,0 +1,178 @@ +// autogenerated file with codegen.pl + +#include <cppunit/simpleheader.hxx> + +#include <basegfx/vector/b2isize.hxx> +#include <basegfx/point/b2ipoint.hxx> + +#include <basebmp/color.hxx> +#include <basebmp/scanlineformats.hxx> +#include <basebmp/bitmapdevice.hxx> +#include <basebmp/debug.hxx> + +#include <iostream> +#include <fstream> + +using namespace ::basebmp; + +namespace +{ +/* + std::ofstream output("32bpp_test.dump"); + debugDump( mpDevice32bpp, output ); +*/ + +class LineTest : public CppUnit::TestFixture +{ +private: + BitmapDeviceSharedPtr mpDevice1bpp; + BitmapDeviceSharedPtr mpDevice32bpp; + + int countPixel( const BitmapDeviceSharedPtr& rDevice, + Color checkColor ) const + { + int count(0); + const basegfx::B2ISize& rSize( rDevice->getSize() ); + for( sal_Int32 y=0; y<rSize.getY(); ++y ) + for( sal_Int32 x=0; x<rSize.getX(); ++x ) + if( rDevice->getPixel( basegfx::B2IPoint(x,y) ) == checkColor ) + ++count; + + return count; + } + + void implTestBasicDiagonalLines(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2IPoint aPt1(1,1); + const basegfx::B2IPoint aPt2(9,9); + const Color aCol(0xFFFFFFFF); + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + const basegfx::B2IPoint aPt3(0,0); + CPPUNIT_ASSERT_MESSAGE("topmost pixel not set", + rDevice->getPixel(aPt3) != aCol); + const basegfx::B2IPoint aPt4(10,10); + CPPUNIT_ASSERT_MESSAGE("bottommost pixel not set", + rDevice->getPixel(aPt4) != aCol); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 9", + countPixel( rDevice, aCol ) == 9); + + rDevice->drawLine( aPt2, aPt1, aCol, DrawMode_PAINT ); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel after " + "reversed paint is not 9", + countPixel( rDevice, aCol ) == 9); + } + + void implTestBasicVerticalLines(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2IPoint aPt1(1,1); + const basegfx::B2IPoint aPt2(1,9); + const Color aCol(0xFFFFFFFF); + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + const basegfx::B2IPoint aPt3(0,0); + CPPUNIT_ASSERT_MESSAGE("topmost pixel not set", + rDevice->getPixel(aPt3) != aCol); + const basegfx::B2IPoint aPt4(0,10); + CPPUNIT_ASSERT_MESSAGE("bottommost pixel not set", + rDevice->getPixel(aPt4) != aCol); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel is not 9", + countPixel( rDevice, aCol ) == 9); + } + + // test pixel rounding (should always tend towards start point of + // the line) + void implTestTieBreaking(const BitmapDeviceSharedPtr& rDevice) + { + rDevice->clear(Color(0)); + + const basegfx::B2IPoint aPt1(1,1); + const basegfx::B2IPoint aPt2(3,2); + const Color aCol(0xFFFFFFFF); + rDevice->drawLine( aPt1, aPt2, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("first pixel set", + rDevice->getPixel(aPt1) == aCol); + CPPUNIT_ASSERT_MESSAGE("second pixel set", + rDevice->getPixel(basegfx::B2IPoint(2,1)) == aCol); + CPPUNIT_ASSERT_MESSAGE("last pixel set", + rDevice->getPixel(aPt2) == aCol); + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel after " + "reversed paint is not 3", + countPixel( rDevice, aCol ) == 3); + + rDevice->drawLine( aPt2, aPt1, aCol, DrawMode_PAINT ); + CPPUNIT_ASSERT_MESSAGE("alternate second pixel set", + rDevice->getPixel(basegfx::B2IPoint(2,2)) == aCol); + + CPPUNIT_ASSERT_MESSAGE("number of rendered pixel after " + "reversed paint is not 4", + countPixel( rDevice, aCol ) == 4); + } + +public: + void setUp() + { + const basegfx::B2ISize aSize(11,11); + mpDevice1bpp = createBitmapDevice( aSize, + true, + Format::ONE_BIT_MSB_PAL ); + mpDevice32bpp = createBitmapDevice( aSize, + true, + Format::THIRTYTWO_BIT_TC_MASK ); + } + + void testBasicDiagonalLines() + { + implTestBasicDiagonalLines( mpDevice1bpp ); + implTestBasicDiagonalLines( mpDevice32bpp ); + } + + void testBasicVerticalLines() + { + implTestBasicVerticalLines( mpDevice1bpp ); + //implTestBasicVerticalLines( mpDevice32bpp ); + } + + // test pixel rounding (should always tend towards start point of + // the line) + void testTieBreaking() + { + implTestTieBreaking( mpDevice1bpp ); + implTestTieBreaking( mpDevice32bpp ); + } + + // Change the following lines only, if you add, remove or rename + // member functions of the current class, + // because these macros are need by auto register mechanism. + + CPPUNIT_TEST_SUITE(LineTest); + CPPUNIT_TEST(testBasicDiagonalLines); + CPPUNIT_TEST(testBasicVerticalLines); + CPPUNIT_TEST(testTieBreaking); + CPPUNIT_TEST_SUITE_END(); +}; + +// ----------------------------------------------------------------------------- +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(LineTest, "LineTest"); +} + + +// ----------------------------------------------------------------------------- + +// this macro creates an empty function, which will called by the RegisterAllFunctions() +// to let the user the possibility to also register some functions by hand. +//NOADDITIONAL; + diff --git a/basebmp/test/makefile.mk b/basebmp/test/makefile.mk new file mode 100644 index 000000000000..e6fec62d9df1 --- /dev/null +++ b/basebmp/test/makefile.mk @@ -0,0 +1,110 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1 $ +# +# last change: $Author: thb $ $Date: 2006-05-31 09:49:45 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library 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 for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=.. + +PRJNAME=basebmp +TARGET=tests +TARGETTYPE=GUI + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +.IF "$(debug)"!="" || "$(DEBUG)"!="" + +.IF "$(COM)"=="MSC" +# disable inlining for MSVC +CFLAGS += -Ob0 +.ENDIF + +.IF "$(COM)"=="GCC" +# disable inlining for gcc +CFLAGS += -fno-inline +.ENDIF + +.ENDIF + +# --- Common ---------------------------------------------------------- + +# BEGIN ---------------------------------------------------------------- +# auto generated Target:tests by codegen.pl +SHL1OBJS= \ + $(SLO)$/basictest.obj \ + $(SLO)$/filltest.obj \ + $(SLO)$/linetest.obj + +SHL1TARGET= tests +SHL1STDLIBS= $(SALLIB) \ + $(CPPUNITLIB) \ + $(BASEGFXLIB) \ + $(BASEBMPLIB) + +SHL1IMPLIB= i$(SHL1TARGET) + +DEF1NAME =$(SHL1TARGET) +SHL1VERSIONMAP = export.map + +# END ------------------------------------------------------------------ + +APP2TARGET= bmpdemo + +APP2OBJS= \ + $(OBJ)$/bmpdemo.obj + +APP2STDLIBS=$(TOOLSLIB) \ + $(COMPHELPERLIB) \ + $(BASEGFXLIB) \ + $(BASEBMPLIB) \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(UCBHELPERLIB) \ + $(SALLIB) \ + $(VCLLIB) + +.IF "$(GUI)"!="UNX" +APP2DEF= $(MISC)$/$(TARGET).def +.ENDIF + +#------------------------------- All object files ------------------------------- +# do this here, so we get right dependencies +SLOFILES=$(SHL1OBJS) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk +.INCLUDE : _cppunit.mk diff --git a/basebmp/util/basebmp.flt b/basebmp/util/basebmp.flt new file mode 100644 index 000000000000..28a1dd1b65c6 --- /dev/null +++ b/basebmp/util/basebmp.flt @@ -0,0 +1,4 @@ +__CT +Impl +IMP +internal
\ No newline at end of file diff --git a/basebmp/util/makefile.mk b/basebmp/util/makefile.mk new file mode 100644 index 000000000000..8f30bf61694b --- /dev/null +++ b/basebmp/util/makefile.mk @@ -0,0 +1,74 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1 $ +# +# last change: $Author: thb $ $Date: 2006-05-31 09:49:45 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library 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 for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=.. + +PRJNAME=basebmp +TARGET=basebmp + +# --- Settings --------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Allgemein --------------------------------------------------- + +LIB1TARGET=$(SLB)$/basebmp.lib +LIB1FILES=\ + $(SLB)$/wrapper.lib + +SHL1TARGET= basebmp$(UPD)$(DLLPOSTFIX) +SHL1IMPLIB= ibasebmp + +SHL1STDLIBS=\ + $(SALLIB) \ + $(BASEGFXLIB) + +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1LIBS= $(SLB)$/basebmp.lib + +DEF1NAME =$(SHL1TARGET) +DEF1DEPN =$(MISC)$/$(SHL1TARGET).flt \ + $(LIB1TARGET) + +DEF1DES =BaseBMP +DEFLIB1NAME =basebmp + +# --- Targets ----------------------------------------------------------- + +.INCLUDE : target.mk + +$(MISC)$/$(SHL1TARGET).flt : makefile.mk + @+$(TYPE) $(TARGET).flt > $@ + |