Update ooo320-m1
[ooovba.git] / vcl / source / gdi / implncvt.cxx
blobbac229db56986fc8339f2f85c580013a42094530
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: implncvt.cxx,v $
10 * $Revision: 1.10.136.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <vcl/salbtype.hxx>
34 #ifndef _SV_IMPLNCVT_HXX
35 #include "implncvt.hxx"
36 #endif
38 // -----------
39 // - Defines -
40 // -----------
42 #define CURVE_LEFT 1
43 #define CURVE_RIGHT 2
44 #define CURVE_STRAIGHTON 3
46 // -----------------
47 // - ImplFloatPoint
48 // -----------------
50 struct ImplFloatPoint
52 double fX;
53 double fY;
55 inline ImplFloatPoint() {}
56 inline ImplFloatPoint( const Point& rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
57 inline ImplFloatPoint( double _fX, double _fY ) { fX = _fX; fY = _fY; }
58 inline ImplFloatPoint( const ImplFloatPoint& rPoint ) { fX = rPoint.fX; fY = rPoint.fY; }
59 inline ~ImplFloatPoint() {}
61 void operator+=( const ImplFloatPoint& rPoint ) { fX += rPoint.fX; fY += rPoint.fY; }
62 void operator-=( const ImplFloatPoint& rPoint ) { fX -= rPoint.fX; fY -= rPoint.fY; }
63 void operator*=( const double& rD ) { fX *= rD; fY *= rD; }
64 BOOL operator==( const ImplFloatPoint& rPoint ) const { return ( ( rPoint.fX == fX ) && ( rPoint.fY == fY ) ); }
65 void operator=( const Point& rPoint ) { fX = rPoint.X(); fY = rPoint.Y(); }
67 ImplFloatPoint GetOVec( const ImplFloatPoint& rPoint ) const;
68 ImplFloatPoint GetNVec( const ImplFloatPoint& rPoint ) const;
71 // -----------------------------------------------------------------------------
73 ImplFloatPoint ImplFloatPoint::GetOVec( const ImplFloatPoint& rPoint ) const
75 double fxt = rPoint.fX - fX;
76 double fyt = rPoint.fY - fY;
77 double fL;
79 if( fyt != 0.0 )
81 fyt = -fxt / fyt;
82 fL = sqrt( 1 + fyt * fyt );
84 return ImplFloatPoint( 1.0 / fL, fyt / fL );
86 else
87 return ImplFloatPoint( fyt, ( fxt > 0.0 ) ? 1.0 : -1.0 );
90 // -----------------------------------------------------------------------------
92 ImplFloatPoint ImplFloatPoint::GetNVec( const ImplFloatPoint& rPoint ) const
94 const double fxt = rPoint.fX - fX;
95 const double fyt = rPoint.fY - fY;
96 const double fL = hypot( fxt, fyt );
98 return ImplFloatPoint( fxt / fL, fyt / fL );
101 // --------------------
102 // - ImplLineConverter
103 // --------------------
105 ImplLineConverter::ImplLineConverter( const Polygon& rPolygon, const LineInfo& rLineInfo, const Point* pRefPoint ) :
106 mbRefPoint ( FALSE ),
107 mfWidthHalf ( rLineInfo.GetWidth() >> 1 ),
108 maLineInfo ( rLineInfo ),
109 mpFloat0 ( new ImplFloatPoint[ 6 ] ),
110 mpFloat1 ( new ImplFloatPoint[ 6 ] ),
111 mnLines ( 0 ),
112 mpFloatPoint ( NULL )
114 UINT16 nIndex, nPolySize = rPolygon.GetSize();
115 if ( nPolySize )
117 if( rPolygon.GetFlags( 0 ) == POLY_NORMAL )
119 mpFloatPoint = new ImplFloatPoint[ nPolySize ];
120 mpFloatPoint[ 0 ] = rPolygon[ 0 ];
122 nIndex = 0;
124 while( ++nIndex < nPolySize ) // doppelte Punkte eliminieren und ein FloatPointArray anlegen
126 if( rPolygon.GetFlags( nIndex ) == POLY_NORMAL )
128 double nxt = mpFloatPoint[ mnLines ].fX;
129 double nyt = mpFloatPoint[ mnLines ].fY;
131 if ( ( nxt == rPolygon[ nIndex ].X() ) && ( nyt == rPolygon[ nIndex ].Y() ) )
132 continue;
134 mpFloatPoint[ ++mnLines ] = rPolygon[ nIndex ];
136 else
138 DBG_ERROR( "Bezier points not supported!" );
141 mbClosed = ( mpFloatPoint[ 0 ] == mpFloatPoint[ mnLines ] ) ;
143 if ( ( mnLines == 1 ) && ( maLineInfo.GetStyle() == LINE_DASH ) )
145 BOOL bX = mpFloatPoint[ 0 ].fY == mpFloatPoint[ 1 ].fY;
146 BOOL bY = mpFloatPoint[ 0 ].fX == mpFloatPoint[ 1 ].fX;
147 mbRefPoint = pRefPoint && ( bX || bY );
148 if ( mbRefPoint )
150 if ( !maLineInfo.GetDashCount() )
152 maLineInfo.SetDashCount( maLineInfo.GetDotCount() );
153 maLineInfo.SetDashLen( maLineInfo.GetDotLen() );
154 maLineInfo.SetDotCount( 0 );
156 INT32 nDistance = maLineInfo.GetDistance();
157 INT32 nDashLen = maLineInfo.GetDashCount() * ( maLineInfo.GetDashLen() + nDistance );
158 INT32 nDotLen = maLineInfo.GetDotCount() * ( maLineInfo.GetDotLen() + nDistance );
159 if ( bX )
161 if ( mpFloatPoint[ 1 ].fX > mpFloatPoint[ 0 ].fX )
163 ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
164 mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
165 mpFloatPoint[ 1 ] = aFloat;
167 mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X();
169 else
171 if ( mpFloatPoint[ 1 ].fY > mpFloatPoint[ 0 ].fY )
173 ImplFloatPoint aFloat = mpFloatPoint[ 0 ];
174 mpFloatPoint[ 0 ] = mpFloatPoint[ 1 ];
175 mpFloatPoint[ 1 ] = aFloat;
177 mnRefDistance = (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y();
180 // mnRefDistance = ( (INT32)mpFloatPoint[ mnLines ].fX - pRefPoint->X() ) +
181 // ( (INT32)mpFloatPoint[ mnLines ].fY - pRefPoint->Y() );
183 mnRefDistance = mnRefDistance % ( nDashLen + nDotLen );
184 if ( mnRefDistance < 0 )
185 mnRefDistance = ( nDashLen + nDotLen ) + mnRefDistance;
192 //------------------------------------------------------------------------
194 ImplLineConverter::~ImplLineConverter()
196 delete[] mpFloat0;
197 delete[] mpFloat1;
198 delete[] mpFloatPoint;
201 //------------------------------------------------------------------------
203 const Polygon* ImplLineConverter::ImplGetFirst()
205 mnFloat1Points = 0;
206 mnLinesAvailable = mnLines;
208 if ( mnLines )
210 if ( maLineInfo.GetStyle() == LINE_DASH )
212 mnDashCount = maLineInfo.GetDashCount();
213 mnDotCount = maLineInfo.GetDotCount();
214 mfDashDotLenght = mnDashCount ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
216 if ( mbRefPoint )
218 INT32 nDistance = maLineInfo.GetDistance();
219 INT32 nDashLen = maLineInfo.GetDashLen() + nDistance;
220 INT32 nDashesLen = maLineInfo.GetDashCount() * nDashLen;
221 INT32 nDotLen = maLineInfo.GetDotLen() + nDistance;
223 if ( mnRefDistance >= nDashesLen )
225 // get dotcount
226 if ( nDotLen )
228 INT32 nLen = ( mnRefDistance - nDashesLen ) % nDotLen;
229 if ( nLen >= maLineInfo.GetDotLen() )
231 mnDotCount -= 1 + ( mnRefDistance - nDashesLen ) / nDotLen;
232 if ( mnDotCount )
233 mnDashCount = 0;
234 else
235 mnDotCount = maLineInfo.GetDotCount();
236 mfDashDotLenght = 0.0;
237 mfDistanceLenght = ( maLineInfo.GetDotLen() + nDistance ) - nLen;
239 else
241 mnDashCount = 0;
242 mfDashDotLenght = maLineInfo.GetDotLen() - nLen;
243 mnDotCount -= ( mnRefDistance - nDashesLen ) / nDotLen;
247 else
249 if ( nDashLen )
251 // get dashcount
252 INT32 nLen = mnRefDistance % nDashLen;
253 if ( nLen >= maLineInfo.GetDashLen() )
255 mfDashDotLenght = 0.0;
256 mfDistanceLenght = ( maLineInfo.GetDashLen() + nDistance ) - nLen;
257 mnDashCount -= 1 + ( mnRefDistance / nDashLen );
259 else
261 mfDashDotLenght = maLineInfo.GetDashLen() - nLen;
262 mnDashCount -= ( mnRefDistance / nDashLen );
266 if ( ! ( mnDashCount | mnDotCount ) )
268 mnDashCount = maLineInfo.GetDashCount();
269 mnDotCount = maLineInfo.GetDotCount();
271 if ( ( mfDashDotLenght == 0.0 ) && ( mfDistanceLenght == 0.0 ) )
272 mfDistanceLenght = maLineInfo.GetDistance();
276 return ImplGetNext();
279 //------------------------------------------------------------------------
281 const Polygon* ImplLineConverter::ImplGetNext()
283 while( mnFloat1Points || mnLinesAvailable )
285 if ( maLineInfo.GetWidth() > 1 )
287 if ( !mnFloat1Points )
289 ImplFloatPoint aPointA( mpFloatPoint[ mnLinesAvailable-- ] );
290 ImplFloatPoint aPointB( mpFloatPoint[ mnLinesAvailable ] );
291 ImplFloatPoint aOVecAB( aPointA.GetOVec( aPointB ) );
292 ImplFloatPoint aN1Vec( aPointA.GetNVec( aPointB ) );
293 aN1Vec *= mfWidthHalf;
295 if ( !mbClosed && ( ( mnLinesAvailable + 1 ) == mnLines ) )
296 aPointA -= aN1Vec;
298 aOVecAB *= mfWidthHalf;
299 mpFloat0[ 0 ] = aPointA;
300 mpFloat0[ 0 ] -= aOVecAB;
301 mpFloat0[ 3 ] = aPointA;
302 mpFloat0[ 3 ] += aOVecAB;
303 mpFloat0[ 1 ] = aPointB;
304 mpFloat0[ 1 ] -= aOVecAB;
305 mpFloat0[ 2 ] = aPointB;
306 mpFloat0[ 2 ] += aOVecAB;
308 double f1D = ( aN1Vec.fX == 0 ) ? 1 : ( aN1Vec.fY / aN1Vec.fX );
309 double f2D = -f1D;
311 mnFloat0Points = 4;
313 int nDirection;
315 BOOL bContinues = ( mnLinesAvailable || mbClosed );
316 if ( bContinues )
318 ImplFloatPoint aPointC;
320 if ( mnLinesAvailable )
321 aPointC = mpFloatPoint[ mnLinesAvailable - 1 ];
322 else
323 aPointC = mpFloatPoint[ mnLines - 1 ];
325 ImplFloatPoint aOVecBC( aPointB.GetOVec( aPointC ) );
326 aOVecBC *= mfWidthHalf;
327 ImplFloatPoint aPointR0( aPointB );
328 aPointR0 -= aOVecBC;
329 ImplFloatPoint aPointR1( aPointB );
330 aPointR1 += aOVecBC;
331 ImplFloatPoint aN2Vec( aPointB.GetNVec( aPointC ) );
332 aN2Vec *= mfWidthHalf;
334 f2D = ( fabs( aN2Vec.fX ) < 0.00000001 ) ? 1 : ( aN2Vec.fY / aN2Vec.fX );
335 if ( fabs( f1D - f2D ) < 0.00000001 )
336 nDirection = CURVE_STRAIGHTON;
337 else
339 if ( ( aN1Vec.fX * aN2Vec.fY - aN1Vec.fY * aN2Vec.fX ) > 0 )
340 nDirection = CURVE_LEFT;
341 else
342 nDirection = CURVE_RIGHT;
344 if ( nDirection != CURVE_STRAIGHTON )
346 double fWidth;
347 ImplFloatPoint aDestPoint;
348 if ( hypot( aPointR0.fX - aPointA.fX, aPointR0.fY - aPointA.fY ) > hypot( aPointR1.fX - aPointA.fX, aPointR1.fY - aPointA.fY ) )
349 aDestPoint = aPointR0;
350 else
351 aDestPoint = aPointR1;
353 UINT16 nFirst = 0;
354 if ( aN1Vec.fY > 0 )
356 if ( nDirection != CURVE_RIGHT )
357 nFirst++;
359 else
361 if ( nDirection == CURVE_RIGHT )
362 nFirst++;
364 fWidth = hypot( mpFloat0[ 1 + nFirst ].fX - aDestPoint.fX, mpFloat0[ 1 + nFirst ].fY - aDestPoint.fY );
365 fWidth = sqrt( fWidth * fWidth / 2 );
366 if ( fWidth > mfWidthHalf )
368 // Spitzer Winkel :
369 mnFloat0Points = 6;
370 mpFloat0[ (4 + nFirst) ^ 1 ] = aDestPoint;
371 aDestPoint -= aN2Vec;
372 mpFloat0[ 4 + nFirst ] = aDestPoint;
373 mpFloat0[ 1 + nFirst ] += aN1Vec;
375 else
377 // Stumpferwinkel : Schnittpunkt wird berechnet
378 mnFloat0Points = 5;
379 ImplFloatPoint aSourcePoint;
380 double fX = 0;
381 double fY;
382 double fBDest = 0;
383 double fBSource = 0;
384 aSourcePoint = mpFloat0[ 1 + nFirst ];
386 int nValid = 0;
388 if ( fabs( aN2Vec.fX ) < 0.00000001 )
390 fX = aDestPoint.fX;
391 nValid = 1;
393 else
394 fBDest = aDestPoint.fY - ( aN2Vec.fY / aN2Vec.fX * aDestPoint.fX );
396 if ( fabs( aN1Vec.fX ) < 0.000000001 )
398 fX = aSourcePoint.fX;
399 nValid = 2;
401 else
402 fBSource = aSourcePoint.fY - ( aN1Vec.fY / aN1Vec.fX * aSourcePoint.fX );
404 if ( !nValid )
405 fX = ( fBSource - fBDest ) / ( aN2Vec.fY / aN2Vec.fX - aN1Vec.fY / aN1Vec.fX );
406 if ( nValid < 2 )
407 fY = aN1Vec.fY / aN1Vec.fX * fX + fBSource;
408 else
409 fY = aN2Vec.fY / aN2Vec.fX * fX + fBDest;
411 mpFloat0[ 1 + nFirst ].fX = fX;
412 mpFloat0[ 1 + nFirst ].fY = fY;
413 mpFloat0[ 4 ] = aDestPoint;
416 else if ( ( aN1Vec.fX - aN2Vec.fX + aN1Vec.fY - aN2Vec.fY ) != 0 ) // besitzt zweiter Richtungsvektor die gleiche Steigung aber andere
417 bContinues = FALSE; // Richtung, dann wird hinten noch eine halbe Linienbreite angehaengt
419 if ( !bContinues )
421 mpFloat0[ 1 ] += aN1Vec;
422 mpFloat0[ 2 ] += aN1Vec;
425 else
427 mnFloat0Points = mnFloat1Points;
428 ImplFloatPoint* pTemp = mpFloat1;
429 mpFloat1 = mpFloat0;
430 mpFloat0 = pTemp;
432 if ( maLineInfo.GetStyle() == LINE_DASH )
434 double fLenghtDone = 0;
435 double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
437 double fDistance;
439 fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
440 if ( mnFloat0Points == 5 )
442 double fDist = hypot( mpFloat0[ 2 ].fX - mpFloat0[ 3 ].fX, mpFloat0[ 2 ].fY - mpFloat0[ 3 ].fY );
443 if ( fDist < fDistance )
444 fDistance = fDist;
447 if ( fDistance > fLenght )
449 fLenghtDone = fLenght;
451 ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
452 aNVec *= fLenght;
453 mnFloat1Points = mnFloat0Points;
454 ImplFloatPoint* pTemp = mpFloat1;
455 mpFloat1 = mpFloat0;
456 mpFloat0 = pTemp;
457 mnFloat0Points = 4;
458 mpFloat0[ 0 ] = mpFloat0[ 1 ] = mpFloat1[ 0 ];
459 mpFloat0[ 1 ] += aNVec;
460 mpFloat0[ 2 ] = mpFloat0[ 3 ] = mpFloat1[ 3 ];
461 mpFloat0[ 2 ] += aNVec;
463 mpFloat1[ 0 ] = mpFloat0[ 1 ];
464 mpFloat1[ 3 ] = mpFloat0[ 2 ];
466 else
468 mnFloat1Points = 0;
469 fLenghtDone = fDistance;
472 if ( mfDashDotLenght > 0.0 )
473 { // Ein Dash oder Dot wurde erzeugt
474 mfDashDotLenght -= fLenghtDone;
475 if ( mfDashDotLenght == 0.0 )
476 { // Komplett erzeugt
477 if ( mnDashCount )
478 mnDashCount--;
479 else
480 mnDotCount--;
482 if ( ! ( mnDashCount | mnDotCount ) )
484 mnDashCount = maLineInfo.GetDashCount();
485 mnDotCount = maLineInfo.GetDotCount();
487 mfDistanceLenght = maLineInfo.GetDistance();
490 else
491 { // Das erzeugte Polygon muessen wir ignorieren
492 mfDistanceLenght -= fLenghtDone;
493 if ( mfDistanceLenght == 0.0 )
494 mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
495 continue;
498 maPolygon.SetSize( (UINT16)mnFloat0Points );
499 UINT16 i = 0;
500 maPolygon[ i++ ] = Point( FRound( mpFloat0[ 0 ].fX ), FRound( mpFloat0[ 0 ].fY ) );
501 maPolygon[ i++ ] = Point( FRound( mpFloat0[ 1 ].fX ), FRound( mpFloat0[ 1 ].fY ) );
502 if ( mnFloat0Points > 4 )
503 maPolygon[ i++ ] = Point( FRound( mpFloat0[ 4 ].fX ), FRound( mpFloat0[ 4 ].fY ) );
504 if ( mnFloat0Points > 5 )
505 maPolygon[ i++ ] = Point( FRound( mpFloat0[ 5 ].fX ), FRound( mpFloat0[ 5 ].fY ) );
506 maPolygon[ i++ ] = Point( FRound( mpFloat0[ 2 ].fX ), FRound( mpFloat0[ 2 ].fY ) );
507 maPolygon[ i ] = Point( FRound( mpFloat0[ 3 ].fX ), FRound( mpFloat0[ 3 ].fY ) );
510 else
512 if ( !mnFloat1Points )
514 mpFloat0[ 0 ] = mpFloatPoint[ mnLinesAvailable-- ];
515 mpFloat0[ 1 ] = mpFloatPoint[ mnLinesAvailable ];
517 else
519 mpFloat0[ 0 ] = mpFloat1[ 0 ];
520 mpFloat0[ 1 ] = mpFloat1[ 1 ];
522 if ( maLineInfo.GetStyle() == LINE_DASH )
524 double fLenghtDone = 0;
525 double fLenght = ( mfDashDotLenght > 0.0 ) ? mfDashDotLenght : mfDistanceLenght;
526 double fDistance;
527 fDistance = hypot( mpFloat0[ 0 ].fX - mpFloat0[ 1 ].fX, mpFloat0[ 0 ].fY - mpFloat0[ 1 ].fY );
528 if ( fDistance > fLenght )
530 fLenghtDone = fLenght;
531 ImplFloatPoint aNVec( mpFloat0[ 0 ].GetNVec( mpFloat0[ 1 ] ) );
532 aNVec *= fLenght;
533 mpFloat1[ 1 ] = mpFloat0[ 1 ];
534 mpFloat0[ 1 ] = mpFloat0[ 0 ];
535 mpFloat0[ 1 ] += aNVec;
536 mpFloat1[ 0 ] = mpFloat0[ 1 ];
537 mnFloat1Points = 2;
539 else
541 mnFloat1Points = 0;
542 fLenghtDone = fDistance;
544 if ( mfDashDotLenght > 0.0 )
545 { // Ein Dash oder Dot wurde erzeugt
546 mfDashDotLenght -= fLenghtDone;
547 if ( mfDashDotLenght == 0.0 )
548 { // Komplett erzeugt
549 if ( mnDashCount )
550 mnDashCount--;
551 else
552 mnDotCount--;
554 if ( ! ( mnDashCount | mnDotCount ) )
556 mnDashCount = maLineInfo.GetDashCount();
557 mnDotCount = maLineInfo.GetDotCount();
559 mfDistanceLenght = maLineInfo.GetDistance();
562 else
563 { // Das erzeugte Polygon muessen wir ignorieren
564 mfDistanceLenght -= fLenghtDone;
565 if ( mfDistanceLenght == 0.0 )
566 mfDashDotLenght = ( mnDashCount ) ? maLineInfo.GetDashLen() : maLineInfo.GetDotLen();
567 continue;
570 maPolygon.SetSize( 2 );
571 maPolygon[ 0 ] = Point( (long)mpFloat0[ 0 ].fX, (long)mpFloat0[ 0 ].fY );
572 maPolygon[ 1 ] = Point( (long)mpFloat0[ 1 ].fX, (long)mpFloat0[ 1 ].fY );
574 return &maPolygon;
576 return NULL;