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: polyscan.cxx,v $
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"
35 #include <tools/new.hxx>
36 #include <vcl/salbtype.hxx>
37 #include "polyscan.hxx"
38 #include <tools/poly.hxx>
44 PolyScanline::PolyScanline() :
53 // ------------------------------------------------------------------------
55 PolyScanline::~PolyScanline()
60 // ------------------------------------------------------------------------
62 void PolyScanline::ImplDelete()
64 ScanlinePoint
* pAct
= mpFirst
;
68 ScanlinePoint
* pNext
= pAct
->mpNext
;
73 mnLeft
= mnRight
= 0L;
74 mpFirst
= mpAct
= mpLast
= NULL
;
77 // ------------------------------------------------------------------------
79 void PolyScanline::Insert( long nX
)
81 // first point to insert?
83 mpLast
= mpFirst
= new ScanlinePoint( mnLeft
= mnRight
= nX
, NULL
);
86 // insert at the beginning of the scanline
87 if( nX
<= mpFirst
->mnX
)
88 mpFirst
= new ScanlinePoint( mnLeft
= nX
, mpFirst
);
89 else if( nX
>= mnRight
)
90 mpLast
= mpLast
->mpNext
= new ScanlinePoint( mnRight
= nX
, NULL
);
93 ScanlinePoint
* pLast
= mpFirst
;
94 ScanlinePoint
* pAct
= mpFirst
->mpNext
;
98 // insert in the midlle of the scanline?
101 pLast
->mpNext
= new ScanlinePoint( nX
, pAct
);
112 // ------------------------------------------------------------------------
114 void PolyScanline::Set( long nStart
, long nEnd
)
120 mpFirst
= new ScanlinePoint( mnLeft
= nStart
, mpLast
= new ScanlinePoint( mnRight
= nEnd
, NULL
) );
122 mpFirst
= new ScanlinePoint( mnLeft
= nEnd
, mpLast
= new ScanlinePoint( mnRight
= nStart
, NULL
) );
125 // ------------------------------------------------------------------------
127 BOOL
PolyScanline::GetFirstSegment( PolyScanSegment
& rSegment
)
129 BOOL bRet
= GetFirstX( rSegment
.mnStart
);
131 if( bRet
&& !GetNextX( rSegment
.mnEnd
) )
132 rSegment
.mnEnd
= rSegment
.mnStart
;
137 // ------------------------------------------------------------------------
139 BOOL
PolyScanline::GetNextSegment( PolyScanSegment
& rSegment
)
141 BOOL bRet
= GetNextX( rSegment
.mnStart
);
143 if( bRet
&& !GetNextX( rSegment
.mnEnd
) )
144 rSegment
.mnEnd
= rSegment
.mnStart
;
153 PolyScanner::PolyScanner( const Rectangle
& rRect
)
155 if( !rRect
.IsEmpty() )
157 Rectangle
aRect( rRect
);
161 mnLeft
= aRect
.Left();
163 mnRight
= aRect
.Right();
164 mnBottom
= aRect
.Bottom();
165 mpArray
= new PolyScanline
[ nHeight
= Height() ];
167 for( ULONG i
= 0UL; i
< nHeight
; i
++ )
168 mpArray
[ i
].Set( mnLeft
, mnRight
);
172 mnLeft
= mnTop
= mnRight
= mnBottom
= 0L;
177 // ------------------------------------------------------------------------
179 PolyScanner::PolyScanner( const Polygon
& rPoly
)
181 const long nCount
= rPoly
.GetSize();
185 long nLast
= nCount
- 1;
186 Point
aFirst( rPoly
[ 0 ] );
187 Point
aLast( rPoly
[ (USHORT
) nLast
] );
189 while( nLast
&& ( aLast
== aFirst
) )
190 aLast
= rPoly
[ (USHORT
) --nLast
];
195 mnLeft
= mnRight
= aLast
.X();
196 mnTop
= mnBottom
= aLast
.Y();
197 mpArray
= new PolyScanline
[ 1UL ];
198 mpArray
[ 0 ].Set( mnLeft
, mnRight
);
202 const Rectangle
aRect( rPoly
.GetBoundRect() );
205 mnLeft
= aRect
.Left();
207 mnRight
= aRect
.Right();
208 mnBottom
= aRect
.Bottom();
210 mpArray
= new PolyScanline
[ nHeight
= Height() ];
212 for( long i
= 1L; i
<= nLast
; i
++ )
214 const Point
& rPt
= rPoly
[ (USHORT
) i
];
218 InsertLine( aLast
, rPt
);
223 InsertLine( aLast
, aFirst
);
230 // ------------------------------------------------------------------------
232 PolyScanner::PolyScanner( const PolyPolygon
& rPolyPoly
)
237 // ------------------------------------------------------------------------
239 PolyScanner::~PolyScanner()
244 // ------------------------------------------------------------------------
246 PolyScanline
* PolyScanner::operator[]( ULONG nPos
) const
248 DBG_ASSERT( nPos
< Count(), "nPos out of range!" );
249 return( mpArray
? ( mpArray
+ nPos
) : NULL
);
252 // ------------------------------------------------------------------------
254 void PolyScanner::InsertLine( const Point
& rStart
, const Point
& rEnd
)
258 if( rStart
.Y() == rEnd
.Y() )
259 mpArray
[ rStart
.Y() - mnTop
].Insert( rStart
.X() );
260 else if( rStart
.X() == rEnd
.X() )
263 const long nEndY
= rEnd
.Y();
270 mpArray
[ nY
++ - mnTop
].Insert( nX
);
273 mpArray
[ nY
-- - mnTop
].Insert( nX
);
277 const long nDX
= labs( rEnd
.X() - rStart
.X() );
278 const long nDY
= labs( rEnd
.Y() - rStart
.Y() );
279 const long nStartX
= rStart
.X();
280 const long nStartY
= rStart
.Y();
281 const long nEndX
= rEnd
.X();
282 const long nEndY
= rEnd
.Y();
283 const long nXInc
= ( nStartX
< nEndX
) ? 1L : -1L;
284 const long nYInc
= ( nStartY
< nEndY
) ? 1L : -1L;
285 long nLastX
= nStartX
;
286 long nLastY
= nStartY
;
289 mpArray
[ nStartY
- mnTop
].Insert( nStartX
);
293 const long nDYX
= ( nDY
- nDX
) << 1;
294 const long nDY2
= nDY
<< 1;
295 long nD
= nDY2
- nDX
;
297 for( nX
= nStartX
, nY
= nLastY
= nStartY
; nX
!= nEndX
; )
302 mpArray
[ nLastY
- mnTop
].Insert( nLastX
);
304 mpArray
[ nY
- mnTop
].Insert( nX
);
326 const long nDYX
= ( nDX
- nDY
) << 1;
327 const long nDY2
= nDX
<< 1;
328 long nD
= nDY2
- nDY
;
330 for( nX
= nStartX
, nY
= nStartY
; nY
!= nEndY
; )
335 mpArray
[ nLastY
- mnTop
].Insert( nLastX
);
337 mpArray
[ nY
- mnTop
].Insert( nX
);
359 mpArray
[ nLastY
- mnTop
].Insert( nLastX
);