Files
libreoffice/canvas/source/vcl/impltools.cxx

415 lines
17 KiB
C++

/*************************************************************************
*
* $RCSfile: impltools.cxx,v $
*
* $Revision: 1.2 $
*
* last change: $Author: thb $ $Date: 2004-03-18 10:38: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
*
*
* 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 _DRAFTS_COM_SUN_STAR_GEOMETRY_REALSIZE2D_HPP__
#include <drafts/com/sun/star/geometry/RealSize2D.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_GEOMETRY_REALPOINT2D_HPP__
#include <drafts/com/sun/star/geometry/RealPoint2D.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_GEOMETRY_REALRECTANGLE2D_HPP__
#include <drafts/com/sun/star/geometry/RealRectangle2D.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_RENDERSTATE_HPP__
#include <drafts/com/sun/star/rendering/RenderState.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XCANVAS_HPP__
#include <drafts/com/sun/star/rendering/XCanvas.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XBITMAP_HPP__
#include <drafts/com/sun/star/rendering/XBitmap.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XPOLYPOLYGON2D_HPP__
#include <drafts/com/sun/star/rendering/XPolyPolygon2D.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_GEOMETRY_REALBEZIERSEGMENT2D_HPP__
#include <drafts/com/sun/star/geometry/RealBezierSegment2D.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_RENDERING_XINTEGERBITMAP_HPP__
#include <drafts/com/sun/star/rendering/XIntegerBitmap.hpp>
#endif
#ifndef _TL_POLY_HXX
#include <tools/poly.hxx>
#endif
#ifndef _SV_SALBTYPE_HXX
#include <vcl/salbtype.hxx>
#endif
#ifndef _SV_BMPACC_HXX
#include <vcl/bmpacc.hxx>
#endif
#ifndef _SV_BITMAPEX_HXX
#include <vcl/bitmapex.hxx>
#endif
#ifndef _SV_METRIC_HXX
#include <vcl/metric.hxx>
#endif
#ifndef _VCL_CANVASTOOLS_HXX
#include <vcl/canvastools.hxx>
#endif
#ifndef _BGFX_TUPLE_B2DTUPLE_HXX
#include <basegfx/tuple/b2dtuple.hxx>
#endif
#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif
#ifndef _BGFX_TOOLS_CANVASTOOLS_HXX
#include <basegfx/tools/canvastools.hxx>
#endif
#ifndef INCLUDED_RTL_MATH_HXX
#include <rtl/math.hxx>
#endif
#include <cmath> // for fmod
#include <canvas/canvastools.hxx>
#include "impltools.hxx"
#include "linepolypolygon.hxx"
#include "canvasbitmap.hxx"
using namespace ::com::sun::star;
using namespace ::drafts::com::sun::star;
namespace vclcanvas
{
namespace tools
{
::PolyPolygon polyPolygonFromXPolyPolygon2D( const uno::Reference< rendering::XPolyPolygon2D >& xPoly )
{
uno::Reference< lang::XServiceInfo > xRef( xPoly,
uno::UNO_QUERY );
if( xRef.is() &&
xRef->getImplementationName().equals( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(LINEPOLYPOLYGON_IMPLEMENTATION_NAME))) )
{
// TODO: Maybe use dynamic_cast here
// TODO: Provide true beziers here!
return static_cast<LinePolyPolygon*>(xPoly.get())->getVCLPolyPolygon();
}
else
{
// TODO: extract points from polygon interface
}
return ::PolyPolygon();
}
::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
{
uno::Reference< lang::XServiceInfo > xRef( xBitmap,
uno::UNO_QUERY );
if( xRef.is() &&
xRef->getImplementationName().equals( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CANVASBITMAP_IMPLEMENTATION_NAME))) )
{
// TODO: Maybe use dynamic_cast here
VirtualDevice& rVDev( static_cast<CanvasBitmap*>(xBitmap.get())->getVirDev() );
const Point aEmptyPoint(0,0);
const Size aBmpSize(rVDev.GetOutputSizePixel());
// TODO: handle alpha vDev here
return rVDev.GetBitmap(aEmptyPoint, aBmpSize);
}
else
{
// TODO: extract points from polygon interface
}
return ::BitmapEx();
}
::Point setupFontTransform( ::Font& aVCLFont,
const rendering::ViewState& rViewState,
const rendering::RenderState& rRenderState,
OutputDevice& rOutDev )
{
::basegfx::B2DHomMatrix aMatrix;
::canvas::tools::mergeViewAndRenderTransform(aMatrix,
rViewState,
rRenderState);
::basegfx::B2DTuple aScale;
::basegfx::B2DTuple aTranslate;
double nRotate, nShearX;
aMatrix.decompose( aScale, aTranslate, nRotate, nShearX );
// query font metric _before_ tampering with width and height
if( !::rtl::math::approxEqual(aScale.getX(), aScale.getY()) )
{
// retrieve true font width
const int aFontWidth( rOutDev.GetFontMetric( aVCLFont ).GetWidth() );
aVCLFont.SetWidth( static_cast<long>(aFontWidth * aScale.getX() + .5) );
}
if( !::rtl::math::approxEqual(aScale.getY(), 1.0) )
{
const int nFontHeight( aVCLFont.GetHeight() );
aVCLFont.SetHeight( static_cast<long>(nFontHeight * aScale.getY() + .5) );
}
aVCLFont.SetOrientation( static_cast< short >(-fmod(nRotate, 2*F_PI)*(1800.0/F_PI) + .5) );
// TODO: Missing functionality in VCL: shearing
return ::Point( static_cast<long>(aTranslate.getX() + .5),
static_cast<long>(aTranslate.getY() + .5) );
}
// VCL-Canvas related
//---------------------------------------------------------------------
::Point mapRealPoint2D( const geometry::RealPoint2D& rPoint,
const rendering::ViewState& rViewState,
const rendering::RenderState& rRenderState )
{
::basegfx::B2DPoint aPoint( ::basegfx::unotools::b2DPointFromRealPoint2D(rPoint) );
::basegfx::B2DHomMatrix aMatrix;
aPoint *= ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
rViewState,
rRenderState);
return ::vcl::unotools::pointFromB2DPoint( aPoint );
}
::PolyPolygon mapPolyPolygon( const ::PolyPolygon& rPoly,
const rendering::ViewState& rViewState,
const rendering::RenderState& rRenderState )
{
PolyPolygon aRes;
::basegfx::B2DHomMatrix aMatrix;
::canvas::tools::mergeViewAndRenderTransform(aMatrix,
rViewState,
rRenderState);
int nCurrPoly, nCurrPoint;
for( nCurrPoly=0; nCurrPoly<rPoly.Count(); ++nCurrPoly )
{
Polygon aDest(rPoly[nCurrPoly].GetSize());
for( nCurrPoint=0; nCurrPoint<aDest.GetSize(); ++nCurrPoint )
{
::basegfx::B2DPoint aPoint( ::vcl::unotools::b2DPointFromPoint( rPoly[nCurrPoly][nCurrPoint] ) );
aPoint *= aMatrix;
aDest[nCurrPoint] = ::vcl::unotools::pointFromB2DPoint( aPoint );
}
aRes.Insert(aDest);
}
return aRes;
}
::BitmapEx transformBitmap( const BitmapEx& rBitmap,
const rendering::ViewState& rViewState,
const rendering::RenderState& rRenderState )
{
// calc transformation and size of bitmap to be
// generated. Note, that the translational components are
// deleted from the transformation; this can be handled by
// an offset when painting the bitmap
::basegfx::B2DHomMatrix aTransform;
::canvas::tools::mergeViewAndRenderTransform(aTransform,
rViewState,
rRenderState);
aTransform.set(0,2,0.0);
aTransform.set(1,2,0.0);
const Size aBmpSize( rBitmap.GetSizePixel() );
::basegfx::B2DRectangle aDestRect;
bool bCopyBack( false );
::canvas::tools::calcTransformedRectBounds( aDestRect,
::basegfx::B2DRectangle(0,
0,
aBmpSize.Width(),
aBmpSize.Height()),
aTransform );
Bitmap aSrcBitmap( rBitmap.GetBitmap() );
Bitmap aSrcAlpha;
// differentiate mask and alpha channel (on-off
// vs. multi-level transparency)
if( rBitmap.IsTransparent() )
{
if( rBitmap.IsAlpha() )
aSrcAlpha = rBitmap.GetAlpha().GetBitmap();
else
aSrcAlpha = rBitmap.GetMask();
}
Bitmap aDstBitmap( aSrcBitmap );
Bitmap aDstAlpha( rBitmap.IsTransparent() ? aSrcAlpha : Bitmap( Size(1,1), 8) );
aDstBitmap.SetSizePixel( Size( FRound( aDestRect.getMaxX() ),
FRound( aDestRect.getMaxY() ) ) );
aDstAlpha.SetSizePixel( Size(FRound( aDestRect.getMaxX() ),
FRound( aDestRect.getMaxY() ) ) );
{
// just to be on the safe side: let the
// ScopedAccessors get destructed before
// copy-constructing the resulting bitmap. This will
// rule out the possibility that cached accessor data
// is not yet written back.
ScopedBitmapReadAccess pReadAccess( aSrcBitmap.AcquireReadAccess(),
aSrcBitmap );
ScopedBitmapReadAccess pAlphaReadAccess( rBitmap.IsTransparent() ? aSrcAlpha.AcquireReadAccess() : NULL,
aSrcAlpha );
ScopedBitmapWriteAccess pWriteAccess( aDstBitmap.AcquireWriteAccess(),
aDstBitmap );
ScopedBitmapWriteAccess pAlphaWriteAccess( aDstAlpha.AcquireWriteAccess(),
aDstAlpha );
if( pReadAccess.get() != NULL &&
(pAlphaReadAccess.get() != NULL || !rBitmap.IsTransparent()) &&
pWriteAccess.get() != NULL &&
pAlphaWriteAccess.get() != NULL &&
aTransform.isInvertible() )
{
// we're doing inverse mapping here, i.e. mapping
// points from the destination bitmap back to the
// source
aTransform.invert();
const Size aDestBmpSize( aDstBitmap.GetSizePixel() );
// for the time being, always read as ARGB
for( int y=0; y<aDestBmpSize.Height(); ++y )
{
// differentiate mask and alpha channel (on-off
// vs. multi-level transparency)
if( rBitmap.IsTransparent() )
{
// Handling alpha and mask just the same...
for( int x=0; x<aDestBmpSize.Width(); ++x )
{
::basegfx::B2DPoint aPoint(x,y);
aPoint *= aTransform;
const int nSrcX( FRound( aPoint.getX() + .5 ) );
const int nSrcY( FRound( aPoint.getY() + .5 ) );
if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
nSrcY < 0 || nSrcX >= aBmpSize.Height() )
{
pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
}
else
{
pAlphaWriteAccess->SetPixel( y, x, pAlphaReadAccess->GetPixel( nSrcY,
nSrcX ) );
pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY,
nSrcX ) );
}
}
}
else
{
for( int x=0; x<aDestBmpSize.Width(); ++x )
{
::basegfx::B2DPoint aPoint(x,y);
aPoint *= aTransform;
const int nSrcX( FRound( aPoint.getX() + .5 ) );
const int nSrcY( FRound( aPoint.getY() + .5 ) );
if( nSrcX < 0 || nSrcX >= aBmpSize.Width() ||
nSrcY < 0 || nSrcX >= aBmpSize.Height() )
{
pAlphaWriteAccess->SetPixel( y, x, BitmapColor(255) );
}
else
{
pAlphaWriteAccess->SetPixel( y, x, BitmapColor(0) );
pWriteAccess->SetPixel( y, x, pReadAccess->GetPixel( nSrcY,
nSrcX ) );
}
}
}
}
bCopyBack = true;
}
else
{
// TODO: Error handling!
}
}
if( bCopyBack )
return BitmapEx( aDstBitmap, AlphaMask( aDstAlpha ) );
else
return BitmapEx();
}
}
}