Files
libreoffice/basebmp/source/bitmapdevice.cxx

1483 lines
59 KiB
C++
Raw Normal View History

2006-05-31 08:49:45 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: bitmapdevice.cxx,v $
*
* $Revision: 1.11 $
2006-05-31 08:49:45 +00:00
*
* last change: $Author: thb $ $Date: 2006-06-08 16:39:02 $
2006-05-31 08:49:45 +00:00
*
* 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 "basebmp/compositeiterator.hxx"
2006-05-31 08:49:45 +00:00
#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/b2dpolypolygontools.hxx>
2006-05-31 08:49:45 +00:00
#include <basegfx/polygon/b2dpolypolygonrasterconverter.hxx>
#include <basegfx/point/b2ipoint.hxx>
#include <basegfx/vector/b2ivector.hxx>
#include <vigra/basicimage.hxx>
#include <vigra/imageiterator.hxx>
#include <vigra/resizeimage.hxx>
#include <vigra/copyimage.hxx>
#include <vigra/tuple.hxx>
2006-05-31 08:49:45 +00:00
namespace basebmp
{
namespace
{
// Common accessor and iterator types
//------------------------------------------------------------------------
typedef PaletteImageAccessor<Color,sal_uInt8> PaletteAccessor;
2006-05-31 08:49:45 +00:00
typedef PackedPixelIterator< sal_uInt8,
1,
true > MaskIterator;
typedef StandardAccessor< sal_uInt8 > MaskAccessor;
typedef PixelIterator< sal_uInt8 > AlphaMaskIterator;
typedef vigra::AccessorTraits< sal_uInt8 >::default_accessor AlphaMaskAccessor;
typedef PixelIterator<Color> ThirtyTwoBitPixelIterator;
typedef vigra::AccessorTraits<Color>::default_accessor ThirtyTwoBitAccessor;
2006-05-31 08:49:45 +00:00
// metafunctions to retrieve correct POD from/to basebmp::Color
//------------------------------------------------------------------------
/// type-safe conversion between color and pod
template< typename DataType > struct GreyScaleFromColor
{
typedef DataType value_type;
DataType operator()( Color c ) { return c.getGrayscale(); }
};
/// type-safe conversion between pod and color
template< typename DataType > struct ColorFromGreyScale
{
typedef DataType value_type;
Color operator()( DataType c ) { return Color(c,c,c); }
};
/// Get converter from color to given data type
template< typename DataType > struct fromColorConverter;
template<> struct fromColorConverter< sal_uInt8 >
{
typedef GreyScaleFromColor<sal_uInt8> type;
};
template<> struct fromColorConverter< Color >
{
typedef std::identity<Color> type;
};
/// Get converter from given data type to Color
template< typename DataType > struct toColorConverter;
template<> struct toColorConverter< sal_uInt8 >
{
typedef ColorFromGreyScale<sal_uInt8> type;
};
template<> struct toColorConverter< Color >
{
typedef std::identity<Color> type;
};
// Polygon scanline conversion
//------------------------------------------------------------------------
2006-05-31 08:49:45 +00:00
template< class DestIterator, class DestAccessor > class Renderer :
public basegfx::B2DPolyPolygonRasterConverter
{
private:
basegfx::B2IRange bounds_;
typename DestAccessor::value_type fillColor_;
typename DestAccessor::value_type clearColor_;
2006-05-31 08:49:45 +00:00
DestIterator begin_;
DestAccessor accessor_;
public:
Renderer(const basegfx::B2DPolyPolygon& rPolyPolyRaster,
typename DestAccessor::value_type fillColor,
2006-05-31 08:49:45 +00:00
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(),
2006-05-31 08:49:45 +00:00
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 DestAccessor::value_type fillColor,
2006-05-31 08:49:45 +00:00
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));
}
// Actual BitmapDevice implementation (templatized by accessor and iterator)
//--------------------------------------------------------------------------
template< class DestIterator,
class DestAccessor > class BitmapRenderer : public BitmapDevice
2006-05-31 08:49:45 +00:00
{
public:
typedef BitmapRenderer<MaskIterator,
MaskAccessor> MaskBitmap;
typedef BitmapRenderer<AlphaMaskIterator,
AlphaMaskAccessor> AlphaMaskBitmap;
typedef typename colorLookup<DestAccessor>::type ColorLookupFunctor;
typedef typename fromColorConverter<
typename DestAccessor::value_type>::type FromColorFunctor;
typedef typename toColorConverter<
typename DestAccessor::value_type>::type ToColorFunctor;
typedef typename rawAccessor<DestAccessor>::type RawAccessor;
2006-05-31 08:49:45 +00:00
typedef typename xorAccessor<DestAccessor>::type XorAccessor;
typedef typename xorAccessor<RawAccessor>::type RawXorAccessor;
2006-05-31 08:49:45 +00:00
typedef typename maskedAccessor<DestAccessor,
MaskAccessor,
DestIterator,
MaskIterator>::type MaskedAccessor;
typedef typename maskedAccessor<RawAccessor,
MaskAccessor,
DestIterator,
MaskIterator>::type RawMaskedAccessor;
2006-05-31 08:49:45 +00:00
typedef typename maskedAccessor<XorAccessor,
MaskAccessor,
DestIterator,
MaskIterator>::type MaskedXorAccessor;
typedef typename maskedAccessor<RawXorAccessor,
MaskAccessor,
DestIterator,
MaskIterator>::type RawMaskedXorAccessor;
typedef DestIterator dest_iterator;
typedef DestAccessor dest_accessor;
typedef CompositeIterator2D< DestIterator,
MaskIterator > composite_iterator_type;
DestIterator maBegin;
DestIterator maEnd;
ColorLookupFunctor maColorLookup;
FromColorFunctor maFromColorConverter;
ToColorFunctor maToColorConverter;
DestAccessor maAccessor;
RawAccessor maRawAccessor;
XorAccessor maXorAccessor;
RawXorAccessor maRawXorAccessor;
MaskedAccessor maMaskedAccessor;
MaskedXorAccessor maMaskedXorAccessor;
RawMaskedAccessor maRawMaskedAccessor;
RawMaskedXorAccessor maRawMaskedXorAccessor;
int mnWidth;
int mnHeight;
2006-05-31 08:49:45 +00:00
BitmapRenderer( const basegfx::B2IVector& rSize,
bool bTopDown,
sal_Int32 nScanlineFormat,
sal_Int32 nScanlineStride,
DestIterator begin,
DestIterator end,
DestAccessor accessor,
const RawMemorySharedArray& rMem,
const PaletteMemorySharedVector& rPalette ) :
BitmapDevice( rSize, bTopDown, nScanlineFormat, nScanlineStride, rMem, rPalette ),
2006-05-31 08:49:45 +00:00
maBegin( begin ),
maEnd( end ),
maColorLookup(),
maFromColorConverter(),
maToColorConverter(),
2006-05-31 08:49:45 +00:00
maAccessor( accessor ),
maRawAccessor( accessor ),
2006-05-31 08:49:45 +00:00
maXorAccessor( accessor ),
maRawXorAccessor( maRawAccessor ),
2006-05-31 08:49:45 +00:00
maMaskedAccessor( accessor ),
maMaskedXorAccessor( maXorAccessor ),
maRawMaskedAccessor( maRawAccessor ),
maRawMaskedXorAccessor( maRawXorAccessor ),
2006-05-31 08:49:45 +00:00
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 void clear_i( Color fillColor )
{
const typename dest_iterator::value_type colorIndex( maColorLookup(
maAccessor,
maFromColorConverter(
fillColor)));
DestIterator currIter( maBegin );
const DestIterator endIter ( maBegin + vigra::Diff2D(0,mnHeight) );
2006-05-31 08:49:45 +00:00
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 )
maRawAccessor.set(colorIndex, rowIter++);
2006-05-31 08:49:45 +00:00
++currIter.y;
2006-05-31 08:49:45 +00:00
}
}
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( maFromColorConverter(
lineColor),
pixel );
2006-05-31 08:49:45 +00:00
else
maAccessor.set( maFromColorConverter(
lineColor),
pixel );
2006-05-31 08:49:45 +00:00
}
virtual void setPixel_i( const basegfx::B2IPoint& rPt,
Color lineColor,
DrawMode drawMode,
const BitmapDeviceSharedPtr& rClip )
{
boost::shared_ptr<MaskBitmap> pMask( getCompatibleMask(rClip) );
OSL_ASSERT( pMask );
2006-05-31 08:49:45 +00:00
const vigra::Diff2D offset(rPt.getX(),
rPt.getY());
const composite_iterator_type aIter(
maBegin + offset,
pMask->maBegin + offset );
2006-05-31 08:49:45 +00:00
if( drawMode == DrawMode_XOR )
maMaskedXorAccessor.set( maFromColorConverter(
lineColor),
aIter );
2006-05-31 08:49:45 +00:00
else
maMaskedAccessor.set( maFromColorConverter(
lineColor),
aIter );
2006-05-31 08:49:45 +00:00
}
virtual Color getPixel_i(const basegfx::B2IPoint& rPt )
{
const DestIterator pixel( maBegin +
vigra::Diff2D(rPt.getX(),
rPt.getY()) );
return maToColorConverter(maAccessor(pixel));
2006-05-31 08:49:45 +00:00
}
virtual sal_uInt32 getPixelData_i( const basegfx::B2IPoint& rPt )
{
const DestIterator pixel( maBegin +
vigra::Diff2D(rPt.getX(),
rPt.getY()) );
// xxx TODO
return 0; // return maRawAccessor(pixel);
}
template< typename Range, typename Col, typename RawAccessor >
void implRenderLine2( const basegfx::B2DPoint& rPt1,
const basegfx::B2DPoint& rPt2,
Col col,
const Range& range,
const RawAccessor& rawAcc )
{
renderLine( basegfx::fround(rPt1),
basegfx::fround(rPt2),
col,
range.first,
range.second,
rawAcc );
}
template< typename Range, typename Accessor, typename RawAccessor >
void implRenderLine( const basegfx::B2DPoint& rPt1,
const basegfx::B2DPoint& rPt2,
Color col,
const Range& range,
const Accessor& acc,
const RawAccessor& rawAcc )
{
implRenderLine2( rPt1,rPt2,
maColorLookup( acc,
maFromColorConverter(
col)),
range,
rawAcc );
}
template< typename Range, typename RawAccessor, typename XorAccessor >
void implDrawLine( const basegfx::B2DPoint& rPt1,
const basegfx::B2DPoint& rPt2,
Color col,
const Range& range,
const RawAccessor& rawAcc,
const XorAccessor& xorAcc,
DrawMode drawMode )
{
if( drawMode == DrawMode_XOR )
implRenderLine( rPt1, rPt2, col,
range, maAccessor, xorAcc );
else
implRenderLine( rPt1, rPt2, col,
range, maAccessor, rawAcc );
}
2006-05-31 08:49:45 +00:00
virtual void drawLine_i(const basegfx::B2DPoint& rPt1,
const basegfx::B2DPoint& rPt2,
Color lineColor,
DrawMode drawMode )
{
implDrawLine(rPt1,rPt2,lineColor,
std::make_pair(maBegin,maEnd),
maRawAccessor,maRawXorAccessor,drawMode);
}
vigra::pair<composite_iterator_type,composite_iterator_type>
getMaskedRange( const BitmapDeviceSharedPtr& rClip ) const
{
boost::shared_ptr<MaskBitmap> pMask( getCompatibleMask(rClip) );
OSL_ASSERT( pMask );
return std::make_pair(
composite_iterator_type(
maBegin,
pMask->maBegin ),
composite_iterator_type(
maEnd,
pMask->maEnd ));
2006-05-31 08:49:45 +00:00
}
virtual void drawLine_i(const basegfx::B2DPoint& rPt1,
const basegfx::B2DPoint& rPt2,
Color lineColor,
DrawMode drawMode,
const BitmapDeviceSharedPtr& rClip )
{
implDrawLine(rPt1,rPt2,lineColor,
getMaskedRange(rClip),
maRawMaskedAccessor,maRawMaskedXorAccessor,drawMode);
2006-05-31 08:49:45 +00:00
}
template< typename Range, typename RawAccessor >
void implDrawPolygon( const basegfx::B2DPolygon& rPoly,
Color col,
const Range& range,
const RawAccessor& acc )
2006-05-31 08:49:45 +00:00
{
basegfx::B2DPolygon aPoly( rPoly );
if( rPoly.areControlVectorsUsed() )
aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
const typename dest_iterator::value_type colorIndex( maColorLookup(
maAccessor,
maFromColorConverter(
col)));
const sal_uInt32 nVertices( aPoly.count() );
2006-05-31 08:49:45 +00:00
for( sal_uInt32 i=1; i<nVertices; ++i )
implRenderLine2( aPoly.getB2DPoint(i-1),
aPoly.getB2DPoint(i),
colorIndex,
range,
acc );
if( nVertices > 1 && aPoly.isClosed() )
implRenderLine2( aPoly.getB2DPoint(nVertices-1),
aPoly.getB2DPoint(0),
colorIndex,
range,
acc );
}
2006-05-31 08:49:45 +00:00
virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
Color lineColor,
DrawMode drawMode )
{
if( drawMode == DrawMode_XOR )
implDrawPolygon( rPoly, lineColor,
std::make_pair(maBegin,
maEnd),
maRawXorAccessor );
else
implDrawPolygon( rPoly, lineColor,
std::make_pair(maBegin,
maEnd),
maRawAccessor );
2006-05-31 08:49:45 +00:00
}
virtual void drawPolygon_i(const basegfx::B2DPolygon& rPoly,
Color lineColor,
DrawMode drawMode,
const BitmapDeviceSharedPtr& rClip )
{
if( drawMode == DrawMode_XOR )
implDrawPolygon( rPoly, lineColor,
getMaskedRange(rClip),
maRawMaskedXorAccessor );
else
implDrawPolygon( rPoly, lineColor,
getMaskedRange(rClip),
maRawMaskedAccessor );
}
template< typename Range, typename RawAccessor >
void implFillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
Color col,
const Range& range,
const RawAccessor& acc,
const basegfx::B2IRange& rBounds )
{
basegfx::B2DPolyPolygon aPoly( rPoly );
if( rPoly.areControlVectorsUsed() )
aPoly = basegfx::tools::adaptiveSubdivideByCount( rPoly );
makeRenderer( aPoly,
maColorLookup( maAccessor,
maFromColorConverter(
col)),
rBounds,
vigra::make_triple(
range.first,
range.second,
acc) )->rasterConvert(
basegfx::FillRule_NONZERO_WINDING_NUMBER );
2006-05-31 08:49:45 +00:00
}
virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
Color fillColor,
DrawMode drawMode,
const basegfx::B2IRange& rBounds )
{
if( drawMode == DrawMode_XOR )
implFillPolyPolygon( rPoly, fillColor,
std::make_pair(maBegin,maEnd),
maRawXorAccessor,
rBounds );
2006-05-31 08:49:45 +00:00
else
implFillPolyPolygon( rPoly, fillColor,
std::make_pair(maBegin,maEnd),
maRawAccessor,
rBounds );
2006-05-31 08:49:45 +00:00
}
virtual void fillPolyPolygon_i(const basegfx::B2DPolyPolygon& rPoly,
Color fillColor,
DrawMode drawMode,
const basegfx::B2IRange& rBounds,
const BitmapDeviceSharedPtr& rClip )
{
if( drawMode == DrawMode_XOR )
implFillPolyPolygon( rPoly, fillColor,
getMaskedRange(rClip),
maRawMaskedXorAccessor,
rBounds );
2006-05-31 08:49:45 +00:00
else
implFillPolyPolygon( rPoly, fillColor,
getMaskedRange(rClip),
maRawMaskedAccessor,
rBounds );
2006-05-31 08:49:45 +00:00
}
template< typename Range, typename RawAccessor >
void implDrawBitmap(const BitmapDeviceSharedPtr& rSrcBitmap,
const basegfx::B2IRange& rSrcRect,
const basegfx::B2IRange& rDstRect,
const Range& range,
const RawAccessor& acc)
2006-05-31 08:49:45 +00:00
{
boost::shared_ptr<BitmapRenderer> pSrcBmp( getCompatibleBitmap(rSrcBitmap) );
OSL_ASSERT( pSrcBmp );
// since resizeImageNoInterpolation() internally copyies
// to a temporary buffer, also works with *this == rSrcBitmap
vigra::resizeImageNoInterpolation(
vigra::make_triple(
pSrcBmp->maBegin + vigra::Diff2D(rSrcRect.getMinX(),
rSrcRect.getMinY()),
pSrcBmp->maBegin + vigra::Diff2D(rSrcRect.getMaxX(),
rSrcRect.getMaxY()),
pSrcBmp->maRawAccessor),
vigra::make_triple(
range.first + vigra::Diff2D(rDstRect.getMinX(),
rDstRect.getMinY()),
range.first + vigra::Diff2D(rDstRect.getMaxX(),
rDstRect.getMaxY()),
acc));
}
virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
const basegfx::B2IRange& rSrcRect,
const basegfx::B2IRange& rDstRect,
DrawMode drawMode )
{
if( drawMode == DrawMode_XOR )
implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
std::make_pair(maBegin,maEnd),
maRawXorAccessor);
else
implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
std::make_pair(maBegin,maEnd),
maRawAccessor);
2006-05-31 08:49:45 +00:00
}
virtual void drawBitmap_i(const BitmapDeviceSharedPtr& rSrcBitmap,
const basegfx::B2IRange& rSrcRect,
const basegfx::B2IRange& rDstRect,
DrawMode drawMode,
const BitmapDeviceSharedPtr& rClip )
{
if( drawMode == DrawMode_XOR )
implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
getMaskedRange(rClip),
maRawMaskedXorAccessor);
else
implDrawBitmap(rSrcBitmap, rSrcRect, rDstRect,
getMaskedRange(rClip),
maRawMaskedAccessor);
2006-05-31 08:49:45 +00:00
}
template< typename Range, typename Accessor >
void implDrawMaskedColor(Color rSrcColor,
const BitmapDeviceSharedPtr& rAlphaMask,
const basegfx::B2IRange& rSrcRect,
const basegfx::B2IPoint& rDstPoint,
const Range& range,
const Accessor& acc)
2006-05-31 08:49:45 +00:00
{
boost::shared_ptr<AlphaMaskBitmap> pAlpha( getCompatibleAlphaMask(rAlphaMask) );
OSL_ASSERT( pAlpha );
vigra::copyImage( pAlpha->maBegin + vigra::Diff2D(rSrcRect.getMinX(),
rSrcRect.getMinY()),
pAlpha->maBegin + vigra::Diff2D(rSrcRect.getMaxX(),
rSrcRect.getMaxY()),
pAlpha->maAccessor,
range.first + vigra::Diff2D(rDstPoint.getX(),
rDstPoint.getY()),
ConstantColorBlendAccessorAdapter<
Accessor,
typename DestAccessor::value_type>(
acc,
maFromColorConverter(rSrcColor)) );
2006-05-31 08:49:45 +00:00
}
virtual void drawMaskedColor_i(Color aSrcColor,
const BitmapDeviceSharedPtr& rAlphaMask,
const basegfx::B2IRange& rSrcRect,
const basegfx::B2IPoint& rDstPoint )
{
implDrawMaskedColor(aSrcColor, rAlphaMask, rSrcRect, rDstPoint,
std::make_pair(maBegin,maEnd),
maAccessor);
}
virtual void drawMaskedColor_i(Color aSrcColor,
2006-05-31 08:49:45 +00:00
const BitmapDeviceSharedPtr& rAlphaMask,
const basegfx::B2IRange& rSrcRect,
const basegfx::B2IPoint& rDstPoint,
const BitmapDeviceSharedPtr& rClip )
{
implDrawMaskedColor(aSrcColor, rAlphaMask, rSrcRect, rDstPoint,
getMaskedRange(rClip),
maMaskedAccessor);
2006-05-31 08:49:45 +00:00
}
// 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 )
2006-05-31 08:49:45 +00:00
{
OSL_ENSURE( false, "Method not yet implemented!" );
}
};
} // namespace
struct ImplBitmapDevice
{
/// Bitmap memory plus deleter
RawMemorySharedArray mpMem;
/// Palette memory plus deleter (might be NULL)
PaletteMemorySharedVector mpPalette;
basegfx::B2IRange maBounds;
basegfx::B2DRange maFloatBounds;
sal_Int32 mnScanlineFormat;
sal_Int32 mnScanlineStride;
2006-05-31 08:49:45 +00:00
};
BitmapDevice::BitmapDevice( const basegfx::B2IVector& rSize,
bool bTopDown,
sal_Int32 nScanlineFormat,
sal_Int32 nScanlineStride,
const RawMemorySharedArray& rMem,
const PaletteMemorySharedVector& rPalette ) :
2006-05-31 08:49:45 +00:00
mpImpl( new ImplBitmapDevice )
{
mpImpl->mpMem = rMem;
mpImpl->mpPalette = rPalette;
2006-05-31 08:49:45 +00:00
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;
}
RawMemorySharedArray BitmapDevice::getBuffer() const
2006-05-31 08:49:45 +00:00
{
return mpImpl->mpMem;
}
PaletteMemorySharedVector BitmapDevice::getPalette() const
2006-05-31 08:49:45 +00:00
{
return mpImpl->mpPalette;
2006-05-31 08:49:45 +00:00
}
const sal_Int32 BitmapDevice::getPaletteEntryCount() const
{
return mpImpl->mpPalette ? mpImpl->mpPalette->size() : 0;
2006-05-31 08:49:45 +00:00
}
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( !rClip )
{
setPixel(rPt,lineColor,drawMode);
return;
}
2006-05-31 08:49:45 +00:00
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();
}
sal_uInt32 BitmapDevice::getPixelData( const basegfx::B2IPoint& rPt )
{
if( mpImpl->maBounds.isInside(rPt) )
return getPixelData_i(rPt);
return 0;
}
2006-05-31 08:49:45 +00:00
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) )
{
2006-05-31 08:49:45 +00:00
drawLine_i( aPt1, aPt2,
lineColor,
drawMode );
}
2006-05-31 08:49:45 +00:00
}
void BitmapDevice::drawLine( const basegfx::B2IPoint& rPt1,
const basegfx::B2IPoint& rPt2,
Color lineColor,
DrawMode drawMode,
const BitmapDeviceSharedPtr& rClip )
{
if( !rClip )
{
drawLine(rPt1,rPt2,lineColor,drawMode);
return;
}
2006-05-31 08:49:45 +00:00
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!" );
}
}
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( !rClip )
{
drawPolygon(rPoly,lineColor,drawMode);
return;
}
2006-05-31 08:49:45 +00:00
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!" );
}
void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
Color fillColor,
DrawMode drawMode )
{
fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds );
}
void BitmapDevice::fillPolyPolygon( const basegfx::B2DPolyPolygon& rPoly,
Color fillColor,
DrawMode drawMode,
const BitmapDeviceSharedPtr& rClip )
{
if( !rClip )
{
fillPolyPolygon(rPoly,fillColor,drawMode);
return;
}
2006-05-31 08:49:45 +00:00
if( isCompatibleClipMask( rClip ) )
fillPolyPolygon_i( rPoly, fillColor, drawMode, mpImpl->maBounds, rClip );
else
OSL_ENSURE( false, "Generic output not yet implemented!" );
}
namespace
{
void assertImagePoint( const basegfx::B2IPoint& rPt,
const basegfx::B2IRange& rPermittedRange )
{
OSL_ASSERT( rPermittedRange.isInside(rPt) );
}
void assertImageRange( const basegfx::B2IRange& rRange,
const basegfx::B2IRange& rPermittedRange )
{
#if OSL_DEBUG_LEVEL > 0
basegfx::B2IRange aRange( rRange );
aRange.intersect( rPermittedRange );
OSL_ASSERT( aRange == rRange );
#endif
}
2006-05-31 08:49:45 +00:00
// TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
// to basegfx, and use here!
bool clipAreaImpl( ::basegfx::B2IRange& io_rSourceArea,
2006-05-31 08:49:45 +00:00
::basegfx::B2IPoint& io_rDestPoint,
const ::basegfx::B2IRange& rSourceBounds,
const ::basegfx::B2IRange& rDestBounds )
{
const ::basegfx::B2IPoint aSourceTopLeft(
io_rSourceArea.getMinimum() );
::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
// clip source area (which must be inside rSourceBounds)
aLocalSourceArea.intersect( rSourceBounds );
if( aLocalSourceArea.isEmpty() )
return false;
// calc relative new source area points (relative to orig
// source area)
const ::basegfx::B2IVector aUpperLeftOffset(
aLocalSourceArea.getMinimum()-aSourceTopLeft );
const ::basegfx::B2IVector aLowerRightOffset(
aLocalSourceArea.getMaximum()-aSourceTopLeft );
::basegfx::B2IRange aLocalDestArea( io_rDestPoint + aUpperLeftOffset,
io_rDestPoint + aLowerRightOffset );
// clip dest area (which must be inside rDestBounds)
aLocalDestArea.intersect( rDestBounds );
if( aLocalDestArea.isEmpty() )
return false;
// calc relative new dest area points (relative to orig
// source area)
const ::basegfx::B2IVector aDestUpperLeftOffset(
aLocalDestArea.getMinimum()-io_rDestPoint );
const ::basegfx::B2IVector aDestLowerRightOffset(
aLocalDestArea.getMaximum()-io_rDestPoint );
io_rSourceArea = ::basegfx::B2IRange( aSourceTopLeft + aDestUpperLeftOffset,
aSourceTopLeft + aDestLowerRightOffset );
io_rDestPoint = aLocalDestArea.getMinimum();
return true;
}
// TODO(Q3): Move canvas/canvastools.hxx clipBlit() down
// to basegfx, and use here!
bool clipAreaImpl( ::basegfx::B2IRange& io_rDestArea,
::basegfx::B2IRange& io_rSourceArea,
const ::basegfx::B2IRange& rDestBounds,
const ::basegfx::B2IRange& rSourceBounds )
{
// extract inherent scale
const double nScaleX( io_rDestArea.getWidth() / (double)io_rSourceArea.getWidth() );
const double nScaleY( io_rDestArea.getHeight() / (double)io_rSourceArea.getHeight() );
// extract range origins
const basegfx::B2IPoint aDestTopLeft(
io_rDestArea.getMinimum() );
const ::basegfx::B2IPoint aSourceTopLeft(
io_rSourceArea.getMinimum() );
::basegfx::B2IRange aLocalSourceArea( io_rSourceArea );
// clip source area (which must be inside rSourceBounds)
aLocalSourceArea.intersect( rSourceBounds );
if( aLocalSourceArea.isEmpty() )
return false;
// calc relative new source area points (relative to orig
// source area)
const ::basegfx::B2IVector aUpperLeftOffset(
aLocalSourceArea.getMinimum()-aSourceTopLeft );
const ::basegfx::B2IVector aLowerRightOffset(
aLocalSourceArea.getMaximum()-aSourceTopLeft );
::basegfx::B2IRange aLocalDestArea( basegfx::fround(aDestTopLeft.getX() + nScaleX*aUpperLeftOffset.getX()),
basegfx::fround(aDestTopLeft.getY() + nScaleY*aUpperLeftOffset.getY()),
basegfx::fround(aDestTopLeft.getX() + nScaleX*aLowerRightOffset.getX()),
basegfx::fround(aDestTopLeft.getY() + nScaleY*aLowerRightOffset.getY()) );
// clip dest area (which must be inside rDestBounds)
aLocalDestArea.intersect( rDestBounds );
if( aLocalDestArea.isEmpty() )
return false;
// calc relative new dest area points (relative to orig
// source area)
const ::basegfx::B2IVector aDestUpperLeftOffset(
aLocalDestArea.getMinimum()-aDestTopLeft );
const ::basegfx::B2IVector aDestLowerRightOffset(
aLocalDestArea.getMaximum()-aDestTopLeft );
io_rSourceArea = ::basegfx::B2IRange( basegfx::fround(aSourceTopLeft.getX() + aDestUpperLeftOffset.getX()/nScaleX),
basegfx::fround(aSourceTopLeft.getY() + aDestUpperLeftOffset.getY()/nScaleY),
basegfx::fround(aSourceTopLeft.getX() + aDestLowerRightOffset.getX()/nScaleX),
basegfx::fround(aSourceTopLeft.getY() + aDestLowerRightOffset.getY()/nScaleY) );
io_rDestArea = aLocalDestArea;
// final source area clip (chopping round-offs)
io_rSourceArea.intersect( rSourceBounds );
if( io_rSourceArea.isEmpty() )
return false;
2006-05-31 08:49:45 +00:00
return true;
}
}
void BitmapDevice::drawBitmap( const BitmapDeviceSharedPtr& rSrcBitmap,
const basegfx::B2IRange& rSrcRect,
const basegfx::B2IRange& rDstRect,
DrawMode drawMode )
{
const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
basegfx::B2IRange aSrcRange( rSrcRect );
basegfx::B2IRange aDestRange( rDstRect );
2006-05-31 08:49:45 +00:00
if( clipAreaImpl( aDestRange,
2006-05-31 08:49:45 +00:00
aSrcRange,
mpImpl->maBounds,
aSrcBounds ))
2006-05-31 08:49:45 +00:00
{
assertImageRange(aDestRange,mpImpl->maBounds);
assertImageRange(aSrcRange,aSrcBounds);
2006-05-31 08:49:45 +00:00
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 )
{
if( !rClip )
{
drawBitmap(rSrcBitmap,rSrcRect,rDstRect,drawMode);
return;
}
2006-05-31 08:49:45 +00:00
const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
basegfx::B2IRange aSrcRange( rSrcRect );
basegfx::B2IRange aDestRange( rDstRect );
2006-05-31 08:49:45 +00:00
if( clipAreaImpl( aDestRange,
2006-05-31 08:49:45 +00:00
aSrcRange,
mpImpl->maBounds,
aSrcBounds ))
2006-05-31 08:49:45 +00:00
{
assertImageRange(aDestRange,mpImpl->maBounds);
assertImageRange(aSrcRange,aSrcBounds);
2006-05-31 08:49:45 +00:00
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 );
2006-05-31 08:49:45 +00:00
if( clipAreaImpl( aSrcRange,
2006-05-31 08:49:45 +00:00
aDestPoint,
aSrcBounds,
mpImpl->maBounds ))
2006-05-31 08:49:45 +00:00
{
assertImagePoint(aDestPoint,mpImpl->maBounds);
assertImageRange(aSrcRange,aSrcBounds);
2006-05-31 08:49:45 +00:00
if( isCompatibleAlphaMask( rAlphaMask ) )
drawMaskedColor_i( rSrcColor, rAlphaMask, aSrcRange, aDestPoint );
else
OSL_ENSURE( false, "Generic output not yet implemented!" );
}
}
void BitmapDevice::drawMaskedColor( Color aSrcColor,
2006-05-31 08:49:45 +00:00
const BitmapDeviceSharedPtr& rAlphaMask,
const basegfx::B2IRange& rSrcRect,
const basegfx::B2IPoint& rDstPoint,
const BitmapDeviceSharedPtr& rClip )
{
if( !rClip )
{
drawMaskedColor(aSrcColor,rAlphaMask,rSrcRect,rDstPoint);
return;
}
2006-05-31 08:49:45 +00:00
const basegfx::B2IVector& rSrcSize( rAlphaMask->getSize() );
const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
basegfx::B2IRange aSrcRange( rSrcRect );
basegfx::B2IPoint aDestPoint( rDstPoint );
2006-05-31 08:49:45 +00:00
if( clipAreaImpl( aSrcRange,
2006-05-31 08:49:45 +00:00
aDestPoint,
aSrcBounds,
mpImpl->maBounds ))
2006-05-31 08:49:45 +00:00
{
assertImagePoint(aDestPoint,mpImpl->maBounds);
assertImageRange(aSrcRange,aSrcBounds);
2006-05-31 08:49:45 +00:00
if( isCompatibleAlphaMask( rAlphaMask ) &&
isCompatibleClipMask( rClip ) )
{
drawMaskedColor_i( aSrcColor, rAlphaMask, aSrcRange, aDestPoint, rClip );
2006-05-31 08:49:45 +00:00
}
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::B2IRange aDestRange( rDstRect );
2006-05-31 08:49:45 +00:00
if( clipAreaImpl( aDestRange,
2006-05-31 08:49:45 +00:00
aSrcRange,
mpImpl->maBounds,
aSrcBounds ))
2006-05-31 08:49:45 +00:00
{
assertImageRange(aDestRange,mpImpl->maBounds);
assertImageRange(aSrcRange,aSrcBounds);
2006-05-31 08:49:45 +00:00
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 )
{
if( !rClip )
{
drawMaskedBitmap(rSrcBitmap,rMask,rSrcRect,rDstRect,drawMode);
return;
}
2006-05-31 08:49:45 +00:00
OSL_ASSERT( rMask->getSize() == rSrcBitmap->getSize() );
const basegfx::B2IVector& rSrcSize( rSrcBitmap->getSize() );
const basegfx::B2IRange aSrcBounds( 0,0,rSrcSize.getX(),rSrcSize.getY() );
basegfx::B2IRange aSrcRange( rSrcRect );
basegfx::B2IRange aDestRange( rDstRect );
2006-05-31 08:49:45 +00:00
if( clipAreaImpl( aDestRange,
2006-05-31 08:49:45 +00:00
aSrcRange,
mpImpl->maBounds,
aSrcBounds ))
2006-05-31 08:49:45 +00:00
{
assertImageRange(aDestRange,mpImpl->maBounds);
assertImageRange(aSrcRange,aSrcBounds);
2006-05-31 08:49:45 +00:00
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 BitmapRenderer<MaskIterator,
MaskAccessor > OneBitMsbMaskRenderer;
typedef BitmapRenderer<MaskIterator,PaletteAccessor> OneBitMsbPaletteRenderer;
typedef BitmapRenderer<AlphaMaskIterator,
AlphaMaskAccessor > EightBitGrayRenderer;
2006-05-31 08:49:45 +00:00
typedef BitmapRenderer<ThirtyTwoBitPixelIterator,
ThirtyTwoBitAccessor> ThirtyTwoBitTrueColorRenderer;
2006-05-31 08:49:45 +00:00
namespace
{
BitmapDeviceSharedPtr createBitmapDeviceImpl( const basegfx::B2IVector& rSize,
bool bTopDown,
sal_Int32 nScanlineFormat,
boost::shared_array< sal_uInt8 > pMem,
PaletteMemorySharedVector pPal )
2006-05-31 08:49:45 +00:00
{
sal_Int32 nScanlineStride(0);
// HACK: 1bpp and 32bpp only, currently
if( nScanlineFormat == Format::ONE_BIT_MSB_PAL
|| nScanlineFormat == Format::ONE_BIT_MSB_GRAY )
2006-05-31 08:49:45 +00:00
nScanlineStride = (rSize.getX() + 7) >> 3;
else if( nScanlineFormat == Format::EIGHT_BIT_GRAY )
2006-05-31 08:49:45 +00:00
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() );
if( !pMem )
{
pMem.reset(
reinterpret_cast<sal_uInt8*>(rtl_allocateMemory( nMemSize )),
&rtl_freeMemory );
rtl_zeroMemory(pMem.get(),nMemSize);
}
2006-05-31 08:49:45 +00:00
sal_uInt8* pFirstScanline = nScanlineStride < 0 ?
pMem.get() + nMemSize : pMem.get();
switch( nScanlineFormat )
{
case Format::ONE_BIT_MSB_GRAY:
{
return BitmapDeviceSharedPtr(
new OneBitMsbMaskRenderer(
rSize,
bTopDown,
nScanlineFormat,
nScanlineStride,
MaskIterator(pFirstScanline,
nScanlineStride),
MaskIterator(pFirstScanline,
nScanlineStride)
+ vigra::Diff2D(rSize.getX(),
rSize.getY()),
MaskAccessor(),
pMem,
pPal ));
}
2006-05-31 08:49:45 +00:00
case Format::ONE_BIT_MSB_PAL:
{
if( !pPal )
{
boost::shared_ptr< std::vector<Color> > pLocalPal(
new std::vector<Color>(2) );
pLocalPal->at(0) = Color(0x00000000);
pLocalPal->at(1) = Color(0xFFFFFFFF);
pPal = pLocalPal;
}
return BitmapDeviceSharedPtr(
new OneBitMsbPaletteRenderer(
rSize,
bTopDown,
nScanlineFormat,
nScanlineStride,
MaskIterator(pFirstScanline,
nScanlineStride),
MaskIterator(pFirstScanline,
nScanlineStride)
+ vigra::Diff2D(rSize.getX(),
rSize.getY()),
PaletteAccessor( &pPal->at(0),
pPal->size() ),
pMem,
pPal ));
}
case Format::EIGHT_BIT_GRAY:
{
return BitmapDeviceSharedPtr(
new EightBitGrayRenderer(
rSize,
bTopDown,
nScanlineFormat,
nScanlineStride,
AlphaMaskIterator(pFirstScanline,
nScanlineStride),
AlphaMaskIterator(pFirstScanline,
nScanlineStride)
+ vigra::Diff2D(rSize.getX(),
rSize.getY()),
AlphaMaskAccessor(),
pMem,
pPal ));
}
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()),
ThirtyTwoBitAccessor(),
pMem,
pPal ));
}
default:
// TODO(F3): other formats not yet implemented
return BitmapDeviceSharedPtr();
}
}
} // namespace
BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
bool bTopDown,
sal_Int32 nScanlineFormat )
{
return createBitmapDeviceImpl( rSize,
bTopDown,
nScanlineFormat,
boost::shared_array< sal_uInt8 >(),
PaletteMemorySharedVector() );
}
BitmapDeviceSharedPtr createBitmapDevice( const basegfx::B2IVector& rSize,
bool bTopDown,
sal_Int32 nScanlineFormat,
const RawMemorySharedArray& rMem,
const PaletteMemorySharedVector& rPalette )
{
return createBitmapDeviceImpl( rSize,
bTopDown,
nScanlineFormat,
rMem,
rPalette );
2006-05-31 08:49:45 +00:00
}
BitmapDeviceSharedPtr cloneBitmapDevice( const basegfx::B2IVector& rSize,
const BitmapDeviceSharedPtr& rProto )
{
return createBitmapDeviceImpl( rSize,
rProto->isTopDown(),
rProto->getScanlineFormat(),
boost::shared_array< sal_uInt8 >(),
rProto->getPalette() );
}
2006-05-31 08:49:45 +00:00
} // namespace basebmp