1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basegfx.hxx"
30 
31 #include "basegfx/tools/tools.hxx"
32 #include "basegfx/numeric/ftools.hxx"
33 #include "basegfx/range/b2drange.hxx"
34 
35 
36 namespace basegfx
37 {
38     namespace tools
39     {
40         namespace
41         {
42             // see Foley/vanDam, pp. 122 for the Liang-Barsky line
43             // clipping algorithm
44             inline bool liangBarskyClipT( double  nDenom,
45                                           double  nNumerator,
46                                           double& io_rTE,
47                                           double& io_rTL )
48             {
49                 double t;
50                 if( nDenom > 0 )
51                 {
52                     t = nNumerator / nDenom;
53                     if( t > io_rTL )
54                         return false;
55                     else if( t > io_rTE )
56                         io_rTE = t;
57                 }
58                 else if( nDenom < 0 )
59                 {
60                     t = nNumerator / nDenom;
61                     if( t < io_rTE )
62                         return false;
63                     else
64                         io_rTL = t;
65                 }
66                 else if( nNumerator > 0 )
67                 {
68                     return false;
69                 }
70 
71                 return true;
72             }
73         }
74 
75         // see Foley/vanDam, pp. 122 for the Liang-Barsky line
76         // clipping algorithm
77         bool liangBarskyClip2D( ::basegfx::B2DPoint& 		io_rStart,
78                                 ::basegfx::B2DPoint& 		io_rEnd,
79                                 const ::basegfx::B2DRange&	rClipRect )
80         {
81             const double nDX( io_rEnd.getX() - io_rStart.getX() );
82             const double nDY( io_rEnd.getY() - io_rStart.getY() );
83 
84             if( ::basegfx::fTools::equalZero( nDX ) &&
85                 ::basegfx::fTools::equalZero( nDY ) )
86             {
87                 return rClipRect.isInside( io_rStart );
88             }
89             else
90             {
91                 double nTE( 0.0 );
92                 double nTL( 1.0 );
93                 if( liangBarskyClipT(nDX, rClipRect.getMinX() - io_rStart.getX(),
94                                      nTE, nTL ) ) 					// inside wrt. left edge
95                 {
96                     if( liangBarskyClipT(-nDX, io_rStart.getX() - rClipRect.getMaxX(),
97                                          nTE, nTL ) ) 				// inside wrt. right edge
98                     {
99                         if( liangBarskyClipT(nDY, rClipRect.getMinY() - io_rStart.getY(),
100                                              nTE, nTL ) ) 			// inside wrt. bottom edge
101                         {
102                             if( liangBarskyClipT(-nDY, io_rStart.getY() - rClipRect.getMaxY(),
103                                                  nTE, nTL ) ) 		// inside wrt. top edge
104                             {
105                                 // compute actual intersection points,
106                                 // if nTL has changed
107                                 if( nTL < 1.0 )
108                                 {
109                                     io_rEnd.setX( io_rStart.getX() + nTL*nDX );
110                                     io_rEnd.setY( io_rStart.getY() + nTL*nDY );
111                                 }
112 
113                                 // compute actual intersection points,
114                                 // if nTE has changed
115                                 if( nTE > 0.0 )
116                                 {
117                                     io_rStart.setX( io_rStart.getX() + nTE*nDX );
118                                     io_rStart.setY( io_rStart.getY() + nTE*nDY );
119                                 }
120 
121                                 // line is (at least partially) visible
122                                 return true;
123                             }
124                         }
125                     }
126                 }
127             }
128 
129             return false;
130         }
131     }
132 }
133