Files
libreoffice/vcl/source/gdi/implncvt.cxx
Oliver Bolte 0ea2f6682e INTEGRATION: CWS pchfix02 (1.7.112); FILE MERGED
2006/09/01 17:57:43 kaib 1.7.112.1: #i68856# Added header markers and pch files
2006-09-17 11:03:48 +00:00

586 lines
23 KiB
C++

/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: implncvt.cxx,v $
*
* $Revision: 1.8 $
*
* last change: $Author: obo $ $Date: 2006-09-17 12:03:48 $
*
* 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
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
#ifndef _SV_SALBTYPE_HXX
#include "salbtype.hxx"
#endif
#ifndef _SV_IMPLNCVT_HXX
#include "implncvt.hxx"
#endif
// -----------
// - Defines -
// -----------
#define CURVE_LEFT 1
#define CURVE_RIGHT 2
#define CURVE_STRAIGHTON 3
// -----------------
// - ImplFloatPoint
// -----------------
struct ImplFloatPoint
{
double fX;
double fY;
inline ImplFloatPoint() {}
inline ImplFloatPoint( const Point& rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
inline ImplFloatPoint( double _fX, double _fY ) { fX = _fX; fY = _fY; }
inline ImplFloatPoint( const ImplFloatPoint& rPoint ) { fX = rPoint.fX; fY = rPoint.fY; }
inline ~ImplFloatPoint() {}
void operator+=( const ImplFloatPoint& rPoint ) { fX += rPoint.fX; fY += rPoint.fY; }
void operator-=( const ImplFloatPoint& rPoint ) { fX -= rPoint.fX; fY -= rPoint.fY; }
void operator*=( const double& rD ) { fX *= rD; fY *= rD; }
BOOL operator==( const ImplFloatPoint& rPoint ) const { return ( ( rPoint.fX == fX ) && ( rPoint.fY == fY ) ); } const
void operator=( const Point rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
ImplFloatPoint GetOVec( const ImplFloatPoint& rPoint ) const;
ImplFloatPoint GetNVec( const ImplFloatPoint& rPoint ) const;
};
// -----------------------------------------------------------------------------
ImplFloatPoint ImplFloatPoint::GetOVec( const ImplFloatPoint& rPoint ) const
{
double fxt = rPoint.fX - fX;
double fyt = rPoint.fY - fY;
double fL;
if( fyt != 0.0 )
{
fyt = -fxt / fyt;
fL = sqrt( 1 + fyt * fyt );
return ImplFloatPoint( 1.0 / fL, fyt / fL );
}
else
return ImplFloatPoint( fyt, ( fxt > 0.0 ) ? 1.0 : -1.0 );
};
// -----------------------------------------------------------------------------
ImplFloatPoint ImplFloatPoint::GetNVec( const ImplFloatPoint& rPoint ) const
{
const double fxt = rPoint.fX - fX;
const double fyt = rPoint.fY - fY;
const double fL = hypot( fxt, fyt );
return ImplFloatPoint( fxt / fL, fyt / fL );
};
// --------------------
// - ImplLineConverter
// --------------------
ImplLineConverter::ImplLineConverter( const Polygon& rPolygon, const LineInfo& rLineInfo, const Point* pRefPoint ) :
mbRefPoint ( FALSE ),
mfWidthHalf ( rLineInfo.GetWidth() >> 1 ),
maLineInfo ( rLineInfo ),
mpFloat0 ( new ImplFloatPoint[ 6 ] ),
mpFloat1 ( new ImplFloatPoint[ 6 ] ),
mnLines ( 0 ),
mpFloatPoint ( NULL )
{
UINT16 nIndex, nPolySize = rPolygon.GetSize();
if ( nPolySize )
{
if( rPolygon.GetFlags( 0 ) == POLY_NORMAL )
{
mpFloatPoint = new ImplFloatPoint[ nPolySize ];
mpFloatPoint[ 0 ] = rPolygon[ 0 ];
nIndex = 0;
while( ++nIndex < nPolySize ) // doppelte Punkte eliminieren und ein FloatPointArray anlegen
{
if( rPolygon.GetFlags( nIndex ) == POLY_NORMAL )
{
double nxt = mpFloatPoint[ mnLines ].fX;
double nyt = mpFloatPoint[ mnLines ].fY;
if ( ( nxt == rPolygon[ nIndex ].X() ) && ( nyt == rPolygon[ nIndex ].Y() ) )
continue;
mpFloatPoint[ ++mnLines ] = rPolygon[ nIndex ];
}
else
{
DBG_ERROR( "Bezier points not supported!" );
}
}
mbClosed = ( mpFloatPoint[ 0 ] == mpFloatPoint[ mnLines ] ) ;
if ( ( mnLines == 1 ) && ( maLineInfo.GetStyle() == LINE_DASH ) )
{
BOOL bX = mpFloatPoint[ 0 ].fY == mpFloatPoint[ 1 ].fY;
BOOL bY = mpFloatPoint[ 0 ].fX == mpFloatPoint[ 1 ].fX;
mbRefPoint = pRefPoint && ( bX || bY );
if ( mbRefPoint )
{
if ( !maLineInfo.GetDashCount() )
{
maLineInfo.SetDashCount( maLineInfo.GetDotCount() );
maLineInfo.SetDashLen( maLineInfo.GetDotLen() );
maLineInfo.SetDotCount( 0 );
}
INT32 nDistance = maLineInfo.GetDistance();
INT32 nDashLen = maLineInfo.GetDashCount() * ( maLineInfo.GetDashLen() + nDistance );
INT32 nDotLen = maLineInfo.GetDotCount() * ( maLineInfo.GetDotLen() + nDistance );
if ( bX )
{
if ( mpFloatPoint[ 1 ].fX > mpFloatPoint[ 0 ].fX )
{
ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
mpFloatPoint[ 1 ] = aFloat;
}
mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X();
}
else
{
if ( mpFloatPoint[ 1 ].fY > mpFloatPoint[ 0 ].fY )
{
ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
mpFloatPoint[ 1 ] = aFloat;
}
mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y();
}
// mnRefDistance = ( (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X() ) +
// ( (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y() );
mnRefDistance = mnRefDistance % ( nDashLen + nDotLen );
if ( mnRefDistance < 0 )
mnRefDistance = ( nDashLen + nDotLen ) + mnRefDistance;
}
}
}
}
};
//------------------------------------------------------------------------
ImplLineConverter::~ImplLineConverter()
{
delete[] mpFloat0;
delete[] mpFloat1;
delete[] mpFloatPoint;
};
//------------------------------------------------------------------------
const Polygon* ImplLineConverter::ImplGetFirst()
{
mnFloat1Points = 0;
mnLinesAvailable = mnLines;
if ( mnLines )
{
if ( maLineInfo.GetStyle() == LINE_DASH )
{
mnDashCount = maLineInfo.GetDashCount();
mnDotCount = maLineInfo.GetDotCount();
mfDashDotLenght = mnDashCount ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
if ( mbRefPoint )
{
INT32 nDistance = maLineInfo.GetDistance();
INT32 nDashLen = maLineInfo.GetDashLen() + nDistance;
INT32 nDashesLen = maLineInfo.GetDashCount() * nDashLen;
INT32 nDotLen = maLineInfo.GetDotLen() + nDistance;
if ( mnRefDistance >= nDashesLen )
{
// get dotcount
if ( nDotLen )
{
INT32 nLen = ( mnRefDistance - nDashesLen ) % nDotLen;
if ( nLen >= maLineInfo.GetDotLen() )
{
mnDotCount -= 1 + ( mnRefDistance - nDashesLen ) / nDotLen;
if ( mnDotCount )
mnDashCount = 0;
else
mnDotCount = maLineInfo.GetDotCount();
mfDashDotLenght = 0.0;
mfDistanceLenght = ( maLineInfo.GetDotLen() + nDistance ) - nLen;
}
else
{
mnDashCount = 0;
mfDashDotLenght = maLineInfo.GetDotLen() - nLen;
mnDotCount -= ( mnRefDistance - nDashesLen ) / nDotLen;
}
}
}
else
{
if ( nDashLen )
{
// get dashcount
INT32 nLen = mnRefDistance % nDashLen;
if ( nLen >= maLineInfo.GetDashLen() )
{
mfDashDotLenght = 0.0;
mfDistanceLenght = ( maLineInfo.GetDashLen() + nDistance ) - nLen;
mnDashCount -= 1 + ( mnRefDistance / nDashLen );
}
else
{
mfDashDotLenght = maLineInfo.GetDashLen() - nLen;
mnDashCount -= ( mnRefDistance / nDashLen );
}
}
}
if ( ! ( mnDashCount | mnDotCount ) )
{
mnDashCount = maLineInfo.GetDashCount();
mnDotCount = maLineInfo.GetDotCount();
}
if ( ( mfDashDotLenght == 0.0 ) && ( mfDistanceLenght == 0.0 ) )
mfDistanceLenght = maLineInfo.GetDistance();
}
}
}
return ImplGetNext();
};
//------------------------------------------------------------------------
const Polygon* ImplLineConverter::ImplGetNext()
{
while( mnFloat1Points || mnLinesAvailable )
{
if ( maLineInfo.GetWidth() > 1 )
{
if ( !mnFloat1Points )
{
ImplFloatPoint aPointA( mpFloatPoint[ mnLinesAvailable-- ] );
ImplFloatPoint aPointB( mpFloatPoint[ mnLinesAvailable ] );
ImplFloatPoint aOVecAB( aPointA.GetOVec( aPointB ) );
ImplFloatPoint aN1Vec( aPointA.GetNVec( aPointB ) );
aN1Vec *= mfWidthHalf;
if ( !mbClosed && ( ( mnLinesAvailable + 1 ) == mnLines ) )
aPointA -= aN1Vec;
aOVecAB *= mfWidthHalf;
mpFloat0[ 0 ] = aPointA;
mpFloat0[ 0 ] -= aOVecAB;
mpFloat0[ 3 ] = aPointA;
mpFloat0[ 3 ] += aOVecAB;
mpFloat0[ 1 ] = aPointB;
mpFloat0[ 1 ] -= aOVecAB;
mpFloat0[ 2 ] = aPointB;
mpFloat0[ 2 ] += aOVecAB;
double f1D = ( aN1Vec.fX == 0 ) ? 1 : ( aN1Vec.fY / aN1Vec.fX );
double f2D = -f1D;
mnFloat0Points = 4;
int nDirection;
BOOL bContinues = ( mnLinesAvailable || mbClosed );
if ( bContinues )
{
ImplFloatPoint aPointC;
if ( mnLinesAvailable )
aPointC = mpFloatPoint[ mnLinesAvailable - 1 ];
else
aPointC = mpFloatPoint[ mnLines - 1 ];
ImplFloatPoint aOVecBC( aPointB.GetOVec( aPointC ) );
aOVecBC *= mfWidthHalf;
ImplFloatPoint aPointR0( aPointB );
aPointR0 -= aOVecBC;
ImplFloatPoint aPointR1( aPointB );
aPointR1 += aOVecBC;
ImplFloatPoint aN2Vec( aPointB.GetNVec( aPointC ) );
aN2Vec *= mfWidthHalf;
f2D = ( fabs( aN2Vec.fX ) < 0.00000001 ) ? 1 : ( aN2Vec.fY / aN2Vec.fX );
if ( fabs( f1D - f2D ) < 0.00000001 )
nDirection = CURVE_STRAIGHTON;
else
{
if ( ( aN1Vec.fX * aN2Vec.fY - aN1Vec.fY * aN2Vec.fX ) > 0 )
nDirection = CURVE_LEFT;
else
nDirection = CURVE_RIGHT;
}
if ( nDirection != CURVE_STRAIGHTON )
{
double fWidth;
ImplFloatPoint aDestPoint;
if ( hypot( aPointR0.fX - aPointA.fX, aPointR0.fY - aPointA.fY ) > hypot( aPointR1.fX - aPointA.fX, aPointR1.fY - aPointA.fY ) )
aDestPoint = aPointR0;
else
aDestPoint = aPointR1;
UINT16 nFirst = 0;
if ( aN1Vec.fY > 0 )
{
if ( nDirection != CURVE_RIGHT )
nFirst++;
}
else
{
if ( nDirection == CURVE_RIGHT )
nFirst++;
}
fWidth = hypot( mpFloat0[ 1 + nFirst ].fX - aDestPoint.fX, mpFloat0[ 1 + nFirst ].fY - aDestPoint.fY );
fWidth = sqrt( fWidth * fWidth / 2 );
if ( fWidth > mfWidthHalf )
{
// Spitzer Winkel :
mnFloat0Points = 6;
mpFloat0[ 4 + nFirst ^ 1 ] = aDestPoint;
aDestPoint -= aN2Vec;
mpFloat0[ 4 + nFirst ] = aDestPoint;
mpFloat0[ 1 + nFirst ] += aN1Vec;
}
else
{
// Stumpferwinkel : Schnittpunkt wird berechnet
mnFloat0Points = 5;
ImplFloatPoint aSourcePoint;
double fX = 0;
double fY;
double fBDest = 0;
double fBSource = 0;
aSourcePoint = mpFloat0[ 1 + nFirst ];
int nValid = 0;
if ( fabs( aN2Vec.fX ) < 0.00000001 )
{
fX = aDestPoint.fX;
nValid = 1;
}
else
fBDest = aDestPoint.fY - ( aN2Vec.fY / aN2Vec.fX * aDestPoint.fX );
if ( fabs( aN1Vec.fX ) < 0.000000001 )
{
fX = aSourcePoint.fX;
nValid = 2;
}
else
fBSource = aSourcePoint.fY - ( aN1Vec.fY / aN1Vec.fX * aSourcePoint.fX );
if ( !nValid )
fX = ( fBSource - fBDest ) / ( aN2Vec.fY / aN2Vec.fX - aN1Vec.fY / aN1Vec.fX );
if ( nValid < 2 )
fY = aN1Vec.fY / aN1Vec.fX * fX + fBSource;
else
fY = aN2Vec.fY / aN2Vec.fX * fX + fBDest;
mpFloat0[ 1 + nFirst ].fX = fX;
mpFloat0[ 1 + nFirst ].fY = fY;
mpFloat0[ 4 ] = aDestPoint;
}
}
else if ( ( aN1Vec.fX - aN2Vec.fX + aN1Vec.fY - aN2Vec.fY ) != 0 ) // besitzt zweiter Richtungsvektor die gleiche Steigung aber andere
bContinues = FALSE; // Richtung, dann wird hinten noch eine halbe Linienbreite angehaengt
}
if ( !bContinues )
{
mpFloat0[ 1 ] += aN1Vec;
mpFloat0[ 2 ] += aN1Vec;
}
}
else
{
mnFloat0Points = mnFloat1Points;
ImplFloatPoint* pTemp = mpFloat1;
mpFloat1 = mpFloat0;
mpFloat0 = pTemp;
}
if ( maLineInfo.GetStyle() == LINE_DASH )
{
double fLenghtDone = 0;
double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
double fDistance;
fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
if ( mnFloat0Points == 5 )
{
double fDist = hypot( mpFloat0[ 2 ].fX - mpFloat0[ 3 ].fX, mpFloat0[ 2 ].fY - mpFloat0[ 3 ].fY );
if ( fDist < fDistance )
fDistance = fDist;
}
if ( fDistance > fLenght )
{
fLenghtDone = fLenght;
ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
aNVec *= fLenght;
mnFloat1Points = mnFloat0Points;
ImplFloatPoint* pTemp = mpFloat1;
mpFloat1 = mpFloat0;
mpFloat0 = pTemp;
mnFloat0Points = 4;
mpFloat0[ 0 ] = mpFloat0[ 1 ] = mpFloat1[ 0 ];
mpFloat0[ 1 ] += aNVec;
mpFloat0[ 2 ] = mpFloat0[ 3 ] = mpFloat1[ 3 ];
mpFloat0[ 2 ] += aNVec;
mpFloat1[ 0 ] = mpFloat0[ 1 ];
mpFloat1[ 3 ] = mpFloat0[ 2 ];
}
else
{
mnFloat1Points = 0;
fLenghtDone = fDistance;
}
if ( mfDashDotLenght > 0.0 )
{ // Ein Dash oder Dot wurde erzeugt
mfDashDotLenght -= fLenghtDone;
if ( mfDashDotLenght == 0.0 )
{ // Komplett erzeugt
if ( mnDashCount )
mnDashCount--;
else
mnDotCount--;
if ( ! ( mnDashCount | mnDotCount ) )
{
mnDashCount = maLineInfo.GetDashCount();
mnDotCount = maLineInfo.GetDotCount();
}
mfDistanceLenght = maLineInfo.GetDistance();
}
}
else
{ // Das erzeugte Polygon muessen wir ignorieren
mfDistanceLenght -= fLenghtDone;
if ( mfDistanceLenght == 0.0 )
mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
continue;
}
}
maPolygon.SetSize( (UINT16)mnFloat0Points );
UINT16 i = 0;
maPolygon[ i++ ] = Point( FRound( mpFloat0[ 0 ].fX ), FRound( mpFloat0[ 0 ].fY ) );
maPolygon[ i++ ] = Point( FRound( mpFloat0[ 1 ].fX ), FRound( mpFloat0[ 1 ].fY ) );
if ( mnFloat0Points > 4 )
maPolygon[ i++ ] = Point( FRound( mpFloat0[ 4 ].fX ), FRound( mpFloat0[ 4 ].fY ) );
if ( mnFloat0Points > 5 )
maPolygon[ i++ ] = Point( FRound( mpFloat0[ 5 ].fX ), FRound( mpFloat0[ 5 ].fY ) );
maPolygon[ i++ ] = Point( FRound( mpFloat0[ 2 ].fX ), FRound( mpFloat0[ 2 ].fY ) );
maPolygon[ i ] = Point( FRound( mpFloat0[ 3 ].fX ), FRound( mpFloat0[ 3 ].fY ) );
}
else
{
if ( !mnFloat1Points )
{
mpFloat0[ 0 ] = mpFloatPoint[ mnLinesAvailable-- ];
mpFloat0[ 1 ] = mpFloatPoint[ mnLinesAvailable ];
}
else
{
mpFloat0[ 0 ] = mpFloat1[ 0 ];
mpFloat0[ 1 ] = mpFloat1[ 1 ];
}
if ( maLineInfo.GetStyle() == LINE_DASH )
{
double fLenghtDone = 0;
double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
double fDistance;
fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
if ( fDistance > fLenght )
{
fLenghtDone = fLenght;
ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
aNVec *= fLenght;
mpFloat1[ 1 ] = mpFloat0[ 1 ];
mpFloat0[ 1 ] = mpFloat0[ 0 ];
mpFloat0[ 1 ] += aNVec;
mpFloat1[ 0 ] = mpFloat0[ 1 ];
mnFloat1Points = 2;
}
else
{
mnFloat1Points = 0;
fLenghtDone = fDistance;
}
if ( mfDashDotLenght > 0.0 )
{ // Ein Dash oder Dot wurde erzeugt
mfDashDotLenght -= fLenghtDone;
if ( mfDashDotLenght == 0.0 )
{ // Komplett erzeugt
if ( mnDashCount )
mnDashCount--;
else
mnDotCount--;
if ( ! ( mnDashCount | mnDotCount ) )
{
mnDashCount = maLineInfo.GetDashCount();
mnDotCount = maLineInfo.GetDotCount();
}
mfDistanceLenght = maLineInfo.GetDistance();
}
}
else
{ // Das erzeugte Polygon muessen wir ignorieren
mfDistanceLenght -= fLenghtDone;
if ( mfDistanceLenght == 0.0 )
mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
continue;
}
}
maPolygon.SetSize( 2 );
maPolygon[ 0 ] = Point( (long)mpFloat0[ 0 ].fX, (long)mpFloat0[ 0 ].fY );
maPolygon[ 1 ] = Point( (long)mpFloat0[ 1 ].fX, (long)mpFloat0[ 1 ].fY );
}
return &maPolygon;
}
return NULL;
};