1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
44 #define CURVE_STRAIGHTON 3
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
;
82 fL
= sqrt( 1 + fyt
* fyt
);
84 return ImplFloatPoint( 1.0 / fL
, fyt
/ fL
);
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 ] ),
112 mpFloatPoint ( NULL
)
114 UINT16 nIndex
, nPolySize
= rPolygon
.GetSize();
117 if( rPolygon
.GetFlags( 0 ) == POLY_NORMAL
)
119 mpFloatPoint
= new ImplFloatPoint
[ nPolySize
];
120 mpFloatPoint
[ 0 ] = rPolygon
[ 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() ) )
134 mpFloatPoint
[ ++mnLines
] = rPolygon
[ nIndex
];
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
);
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
);
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();
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()
198 delete[] mpFloatPoint
;
201 //------------------------------------------------------------------------
203 const Polygon
* ImplLineConverter::ImplGetFirst()
206 mnLinesAvailable
= mnLines
;
210 if ( maLineInfo
.GetStyle() == LINE_DASH
)
212 mnDashCount
= maLineInfo
.GetDashCount();
213 mnDotCount
= maLineInfo
.GetDotCount();
214 mfDashDotLenght
= mnDashCount
? maLineInfo
.GetDashLen() : maLineInfo
.GetDotLen();
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
)
228 INT32 nLen
= ( mnRefDistance
- nDashesLen
) % nDotLen
;
229 if ( nLen
>= maLineInfo
.GetDotLen() )
231 mnDotCount
-= 1 + ( mnRefDistance
- nDashesLen
) / nDotLen
;
235 mnDotCount
= maLineInfo
.GetDotCount();
236 mfDashDotLenght
= 0.0;
237 mfDistanceLenght
= ( maLineInfo
.GetDotLen() + nDistance
) - nLen
;
242 mfDashDotLenght
= maLineInfo
.GetDotLen() - nLen
;
243 mnDotCount
-= ( mnRefDistance
- nDashesLen
) / nDotLen
;
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
);
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
) )
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
);
315 BOOL bContinues
= ( mnLinesAvailable
|| mbClosed
);
318 ImplFloatPoint aPointC
;
320 if ( mnLinesAvailable
)
321 aPointC
= mpFloatPoint
[ mnLinesAvailable
- 1 ];
323 aPointC
= mpFloatPoint
[ mnLines
- 1 ];
325 ImplFloatPoint
aOVecBC( aPointB
.GetOVec( aPointC
) );
326 aOVecBC
*= mfWidthHalf
;
327 ImplFloatPoint
aPointR0( aPointB
);
329 ImplFloatPoint
aPointR1( aPointB
);
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
;
339 if ( ( aN1Vec
.fX
* aN2Vec
.fY
- aN1Vec
.fY
* aN2Vec
.fX
) > 0 )
340 nDirection
= CURVE_LEFT
;
342 nDirection
= CURVE_RIGHT
;
344 if ( nDirection
!= CURVE_STRAIGHTON
)
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
;
351 aDestPoint
= aPointR1
;
356 if ( nDirection
!= CURVE_RIGHT
)
361 if ( nDirection
== CURVE_RIGHT
)
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
)
370 mpFloat0
[ (4 + nFirst
) ^ 1 ] = aDestPoint
;
371 aDestPoint
-= aN2Vec
;
372 mpFloat0
[ 4 + nFirst
] = aDestPoint
;
373 mpFloat0
[ 1 + nFirst
] += aN1Vec
;
377 // Stumpferwinkel : Schnittpunkt wird berechnet
379 ImplFloatPoint aSourcePoint
;
384 aSourcePoint
= mpFloat0
[ 1 + nFirst
];
388 if ( fabs( aN2Vec
.fX
) < 0.00000001 )
394 fBDest
= aDestPoint
.fY
- ( aN2Vec
.fY
/ aN2Vec
.fX
* aDestPoint
.fX
);
396 if ( fabs( aN1Vec
.fX
) < 0.000000001 )
398 fX
= aSourcePoint
.fX
;
402 fBSource
= aSourcePoint
.fY
- ( aN1Vec
.fY
/ aN1Vec
.fX
* aSourcePoint
.fX
);
405 fX
= ( fBSource
- fBDest
) / ( aN2Vec
.fY
/ aN2Vec
.fX
- aN1Vec
.fY
/ aN1Vec
.fX
);
407 fY
= aN1Vec
.fY
/ aN1Vec
.fX
* fX
+ fBSource
;
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
421 mpFloat0
[ 1 ] += aN1Vec
;
422 mpFloat0
[ 2 ] += aN1Vec
;
427 mnFloat0Points
= mnFloat1Points
;
428 ImplFloatPoint
* pTemp
= mpFloat1
;
432 if ( maLineInfo
.GetStyle() == LINE_DASH
)
434 double fLenghtDone
= 0;
435 double fLenght
= ( mfDashDotLenght
> 0.0 ) ? mfDashDotLenght
: mfDistanceLenght
;
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
)
447 if ( fDistance
> fLenght
)
449 fLenghtDone
= fLenght
;
451 ImplFloatPoint
aNVec( mpFloat0
[ 0 ].GetNVec( mpFloat0
[ 1 ] ) );
453 mnFloat1Points
= mnFloat0Points
;
454 ImplFloatPoint
* pTemp
= mpFloat1
;
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 ];
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
482 if ( ! ( mnDashCount
| mnDotCount
) )
484 mnDashCount
= maLineInfo
.GetDashCount();
485 mnDotCount
= maLineInfo
.GetDotCount();
487 mfDistanceLenght
= maLineInfo
.GetDistance();
491 { // Das erzeugte Polygon muessen wir ignorieren
492 mfDistanceLenght
-= fLenghtDone
;
493 if ( mfDistanceLenght
== 0.0 )
494 mfDashDotLenght
= ( mnDashCount
) ? maLineInfo
.GetDashLen() : maLineInfo
.GetDotLen();
498 maPolygon
.SetSize( (UINT16
)mnFloat0Points
);
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
) );
512 if ( !mnFloat1Points
)
514 mpFloat0
[ 0 ] = mpFloatPoint
[ mnLinesAvailable
-- ];
515 mpFloat0
[ 1 ] = mpFloatPoint
[ mnLinesAvailable
];
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
;
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 ] ) );
533 mpFloat1
[ 1 ] = mpFloat0
[ 1 ];
534 mpFloat0
[ 1 ] = mpFloat0
[ 0 ];
535 mpFloat0
[ 1 ] += aNVec
;
536 mpFloat1
[ 0 ] = mpFloat0
[ 1 ];
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
554 if ( ! ( mnDashCount
| mnDotCount
) )
556 mnDashCount
= maLineInfo
.GetDashCount();
557 mnDotCount
= maLineInfo
.GetDotCount();
559 mfDistanceLenght
= maLineInfo
.GetDistance();
563 { // Das erzeugte Polygon muessen wir ignorieren
564 mfDistanceLenght
-= fLenghtDone
;
565 if ( mfDistanceLenght
== 0.0 )
566 mfDashDotLenght
= ( mnDashCount
) ? maLineInfo
.GetDashLen() : maLineInfo
.GetDotLen();
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
);