1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basegfx.hxx"
26 
27 #include "basegfx/tools/tools.hxx"
28 #include "basegfx/numeric/ftools.hxx"
29 #include "basegfx/range/b2drange.hxx"
30 
31 
32 namespace basegfx
33 {
34     namespace tools
35     {
36         namespace
37         {
38             // see Foley/vanDam, pp. 122 for the Liang-Barsky line
39             // clipping algorithm
liangBarskyClipT(double nDenom,double nNumerator,double & io_rTE,double & io_rTL)40             inline bool liangBarskyClipT( double  nDenom,
41                                           double  nNumerator,
42                                           double& io_rTE,
43                                           double& io_rTL )
44             {
45                 double t;
46                 if( nDenom > 0 )
47                 {
48                     t = nNumerator / nDenom;
49                     if( t > io_rTL )
50                         return false;
51                     else if( t > io_rTE )
52                         io_rTE = t;
53                 }
54                 else if( nDenom < 0 )
55                 {
56                     t = nNumerator / nDenom;
57                     if( t < io_rTE )
58                         return false;
59                     else
60                         io_rTL = t;
61                 }
62                 else if( nNumerator > 0 )
63                 {
64                     return false;
65                 }
66 
67                 return true;
68             }
69         }
70 
71         // see Foley/vanDam, pp. 122 for the Liang-Barsky line
72         // clipping algorithm
liangBarskyClip2D(::basegfx::B2DPoint & io_rStart,::basegfx::B2DPoint & io_rEnd,const::basegfx::B2DRange & rClipRect)73         bool liangBarskyClip2D( ::basegfx::B2DPoint& 		io_rStart,
74                                 ::basegfx::B2DPoint& 		io_rEnd,
75                                 const ::basegfx::B2DRange&	rClipRect )
76         {
77             const double nDX( io_rEnd.getX() - io_rStart.getX() );
78             const double nDY( io_rEnd.getY() - io_rStart.getY() );
79 
80             if( ::basegfx::fTools::equalZero( nDX ) &&
81                 ::basegfx::fTools::equalZero( nDY ) )
82             {
83                 return rClipRect.isInside( io_rStart );
84             }
85             else
86             {
87                 double nTE( 0.0 );
88                 double nTL( 1.0 );
89                 if( liangBarskyClipT(nDX, rClipRect.getMinX() - io_rStart.getX(),
90                                      nTE, nTL ) ) 					// inside wrt. left edge
91                 {
92                     if( liangBarskyClipT(-nDX, io_rStart.getX() - rClipRect.getMaxX(),
93                                          nTE, nTL ) ) 				// inside wrt. right edge
94                     {
95                         if( liangBarskyClipT(nDY, rClipRect.getMinY() - io_rStart.getY(),
96                                              nTE, nTL ) ) 			// inside wrt. bottom edge
97                         {
98                             if( liangBarskyClipT(-nDY, io_rStart.getY() - rClipRect.getMaxY(),
99                                                  nTE, nTL ) ) 		// inside wrt. top edge
100                             {
101                                 // compute actual intersection points,
102                                 // if nTL has changed
103                                 if( nTL < 1.0 )
104                                 {
105                                     io_rEnd.setX( io_rStart.getX() + nTL*nDX );
106                                     io_rEnd.setY( io_rStart.getY() + nTL*nDY );
107                                 }
108 
109                                 // compute actual intersection points,
110                                 // if nTE has changed
111                                 if( nTE > 0.0 )
112                                 {
113                                     io_rStart.setX( io_rStart.getX() + nTE*nDX );
114                                     io_rStart.setY( io_rStart.getY() + nTE*nDY );
115                                 }
116 
117                                 // line is (at least partially) visible
118                                 return true;
119                             }
120                         }
121                     }
122                 }
123             }
124 
125             return false;
126         }
127     }
128 }
129