xref: /trunk/main/sw/source/core/bastyp/swregion.cxx (revision efeef26f)
1*efeef26fSAndrew Rist /**************************************************************
2*efeef26fSAndrew Rist  *
3*efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*efeef26fSAndrew Rist  * distributed with this work for additional information
6*efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9*efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*efeef26fSAndrew Rist  *
11*efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15*efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17*efeef26fSAndrew Rist  * specific language governing permissions and limitations
18*efeef26fSAndrew Rist  * under the License.
19*efeef26fSAndrew Rist  *
20*efeef26fSAndrew Rist  *************************************************************/
21*efeef26fSAndrew Rist 
22*efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir 
28cdf0e10cSrcweir 
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <tools/debug.hxx>
31cdf0e10cSrcweir #include "swtypes.hxx"
32cdf0e10cSrcweir #include "swrect.hxx"
33cdf0e10cSrcweir #include "swregion.hxx"
34cdf0e10cSrcweir 
35cdf0e10cSrcweir 
36cdf0e10cSrcweir SV_IMPL_VARARR( SwRects, SwRect );
37cdf0e10cSrcweir 
38cdf0e10cSrcweir /*************************************************************************
39cdf0e10cSrcweir |*
40cdf0e10cSrcweir |*	SwRegionRects::SwRegionRects()
41cdf0e10cSrcweir |*
42cdf0e10cSrcweir |*	Ersterstellung		MA 28. Oct. 92
43cdf0e10cSrcweir |*	Letzte Aenderung	MA 01. Feb. 93
44cdf0e10cSrcweir |*
45cdf0e10cSrcweir |*************************************************************************/
46cdf0e10cSrcweir 
SwRegionRects(const SwRect & rStartRect,sal_uInt16 nInit,sal_uInt16 nGrow)47cdf0e10cSrcweir SwRegionRects::SwRegionRects( const SwRect &rStartRect, sal_uInt16 nInit,
48cdf0e10cSrcweir 														sal_uInt16 nGrow ) :
49cdf0e10cSrcweir 	SwRects( (sal_uInt8)nInit, (sal_uInt8)nGrow ),
50cdf0e10cSrcweir 	aOrigin( rStartRect )
51cdf0e10cSrcweir {
52cdf0e10cSrcweir 	Insert( aOrigin, 0 );
53cdf0e10cSrcweir }
54cdf0e10cSrcweir 
55cdf0e10cSrcweir /*************************************************************************
56cdf0e10cSrcweir  *						inline InsertRect()
57cdf0e10cSrcweir  *
58cdf0e10cSrcweir  * InsertRect() wird nur von operator-=() gerufen.
59cdf0e10cSrcweir  * Wenn bDel == sal_True ist, dann wird das Rect an der Position nPos mit
60cdf0e10cSrcweir  * rRect ueberschrieben, ansonsten wird rRect hinten angehaengt.
61cdf0e10cSrcweir  *************************************************************************/
62cdf0e10cSrcweir 
InsertRect(const SwRect & rRect,const sal_uInt16 nPos,sal_Bool & rDel)63cdf0e10cSrcweir inline void SwRegionRects::InsertRect( const SwRect &rRect, const sal_uInt16 nPos,
64cdf0e10cSrcweir 									   sal_Bool &rDel )
65cdf0e10cSrcweir {
66cdf0e10cSrcweir 	if( rDel )
67cdf0e10cSrcweir 	{
68cdf0e10cSrcweir         pData = (SwRect*)pData; // looks weird but seems to help gcc ->i78417
69cdf0e10cSrcweir 		*(pData+nPos) = rRect;
70cdf0e10cSrcweir 		rDel = sal_False;
71cdf0e10cSrcweir 	}
72cdf0e10cSrcweir 	else
73cdf0e10cSrcweir 		Insert( rRect, Count() );
74cdf0e10cSrcweir }
75cdf0e10cSrcweir 
76cdf0e10cSrcweir /*************************************************************************
77cdf0e10cSrcweir |*
78cdf0e10cSrcweir |*	SwRegionRects::operator-=()
79cdf0e10cSrcweir |*
80cdf0e10cSrcweir |*	Beschreibung		Alle Ueberschneidungen der Rechtecke, die sich
81cdf0e10cSrcweir |*		gerade im Array befinden, mit dem uebergebenen Rechteck werden
82cdf0e10cSrcweir |*		entfernt.
83cdf0e10cSrcweir |*		Dazu muessen die vorhandenen Rechtecke entweder aufgeteilt oder
84cdf0e10cSrcweir |*		geloescht werden.
85cdf0e10cSrcweir |*	Ersterstellung		MA 28. Oct. 92
86cdf0e10cSrcweir |*	Letzte Aenderung	MA 09. Sep. 93
87cdf0e10cSrcweir |*
88cdf0e10cSrcweir |*************************************************************************/
89cdf0e10cSrcweir 
operator -=(const SwRect & rRect)90cdf0e10cSrcweir void SwRegionRects::operator-=( const SwRect &rRect )
91cdf0e10cSrcweir {
92cdf0e10cSrcweir 	sal_uInt16 nMax = Count();
93cdf0e10cSrcweir 	for ( sal_uInt16 i = 0; i < nMax; ++i )
94cdf0e10cSrcweir 	{
95cdf0e10cSrcweir 		if ( rRect.IsOver( *(pData+i) ) )
96cdf0e10cSrcweir 		{
97cdf0e10cSrcweir 			SwRect aTmp( *(pData+i) );
98cdf0e10cSrcweir 			SwRect aInter( aTmp );
99cdf0e10cSrcweir 			aInter._Intersection( rRect );
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 			// Das erste Rect, das wir inserten wollen, nimmt die
102cdf0e10cSrcweir 			// Stelle von i ein. So ersparen wir uns das Delete().
103cdf0e10cSrcweir 			sal_Bool bDel = sal_True;
104cdf0e10cSrcweir 
105cdf0e10cSrcweir 			//Jetzt aufteilen das Teil: Es sollen diejenigen Rechtecke
106cdf0e10cSrcweir 			//zurueckbleiben, die im alten aber nicht im neuen liegen.
107cdf0e10cSrcweir 			//Sprich alle Rechtecke die im alten aber nicht in der Intersection
108cdf0e10cSrcweir 			//liegen.
109cdf0e10cSrcweir 			long nTmp;
110cdf0e10cSrcweir 			if ( 0 < (nTmp = aInter.Top() - aTmp.Top()) )
111cdf0e10cSrcweir 			{
112cdf0e10cSrcweir 				const long nOldVal = aTmp.Height();
113cdf0e10cSrcweir 				aTmp.Height(nTmp);
114cdf0e10cSrcweir 				InsertRect( aTmp, i, bDel );
115cdf0e10cSrcweir 				aTmp.Height( nOldVal );
116cdf0e10cSrcweir 			}
117cdf0e10cSrcweir 
118cdf0e10cSrcweir 			aTmp.Top( aInter.Top() + aInter.Height() );
119cdf0e10cSrcweir 			if ( aTmp.Height() > 0 )
120cdf0e10cSrcweir 				InsertRect( aTmp, i, bDel );
121cdf0e10cSrcweir 
122cdf0e10cSrcweir 			aTmp.Top( aInter.Top() );
123cdf0e10cSrcweir 			aTmp.Bottom( aInter.Bottom() );
124cdf0e10cSrcweir 			if ( 0 < (nTmp = aInter.Left() - aTmp.Left()) )
125cdf0e10cSrcweir 			{
126cdf0e10cSrcweir 				const long nOldVal = aTmp.Width();
127cdf0e10cSrcweir 				aTmp.Width( nTmp );
128cdf0e10cSrcweir 				InsertRect( aTmp, i, bDel );
129cdf0e10cSrcweir 				aTmp.Width( nOldVal );
130cdf0e10cSrcweir 			}
131cdf0e10cSrcweir 
132cdf0e10cSrcweir 			aTmp.Left( aInter.Left() + aInter.Width() ); //+1?
133cdf0e10cSrcweir 			if ( aTmp.Width() > 0 )
134cdf0e10cSrcweir 				InsertRect( aTmp, i, bDel );
135cdf0e10cSrcweir 
136cdf0e10cSrcweir 			if( bDel )
137cdf0e10cSrcweir 			{
138cdf0e10cSrcweir 				Remove( i );
139cdf0e10cSrcweir 				--i;			  //Damit wir keinen uebergehen.
140cdf0e10cSrcweir 				--nMax; 		  //Damit wir keinen zuviel verarbeiten.
141cdf0e10cSrcweir 			}
142cdf0e10cSrcweir 		}
143cdf0e10cSrcweir 	}
144cdf0e10cSrcweir 
145cdf0e10cSrcweir }
146cdf0e10cSrcweir 
147cdf0e10cSrcweir /*************************************************************************
148cdf0e10cSrcweir  *						SwRegionRects::Invert()
149cdf0e10cSrcweir  *
150cdf0e10cSrcweir  * Bezugspunkt ist aOrigin, das Original-SRectangle.
151cdf0e10cSrcweir  * Aus Loechern werden Flaechen, aus Flaechen werden Loecher.
152cdf0e10cSrcweir  * Ein Hinweis: Wenn keine Rects abgezogen wurden, so ist das enthaltene
153cdf0e10cSrcweir  * Rechteck identisch mit aOrigin. Nach Invert() besteht die Region aus
154cdf0e10cSrcweir  * einem Null-SRectangle.
155cdf0e10cSrcweir  *************************************************************************/
156cdf0e10cSrcweir 
Invert()157cdf0e10cSrcweir void SwRegionRects::Invert()
158cdf0e10cSrcweir {
159cdf0e10cSrcweir 	// Nicht besonders elegant und schnell, aber wirkungsvoll:
160cdf0e10cSrcweir 	// Wir legen eine weitere Region an und ziehen alle Flaechen ab,
161cdf0e10cSrcweir 	// die in uns noch uebrig geblieben sind. Danach werden alle
162cdf0e10cSrcweir 	// Werte uebertragen.
163cdf0e10cSrcweir 
164cdf0e10cSrcweir 	// Um unuetze Speicheranforderungen zu vermeiden versuchen wir die
165cdf0e10cSrcweir 	// iniale Groesse moeglichst brauchbar anzulegen:
166cdf0e10cSrcweir 	// Anzahl der Rechtecke in der Region * 2 + 2
167cdf0e10cSrcweir 	// plus zwei um den Sonderfall eines einzelnen Loches (macht vier
168cdf0e10cSrcweir 	// Rechtecke im inversen Fall) abzudecken.
169cdf0e10cSrcweir 
170cdf0e10cSrcweir 	SwRegionRects aInvRegion( aOrigin, Count()*2+2 );
171cdf0e10cSrcweir 	const SwRect *pDat = GetData();
172cdf0e10cSrcweir 	for( sal_uInt16 i = 0; i < Count(); ++pDat, ++i )
173cdf0e10cSrcweir 		aInvRegion -= *pDat;
174cdf0e10cSrcweir 
175cdf0e10cSrcweir 	sal_uInt16 nCpy = Count(), nDel = 0;
176cdf0e10cSrcweir 	if( aInvRegion.Count() < Count() )
177cdf0e10cSrcweir 	{
178cdf0e10cSrcweir 		nDel = Count() - aInvRegion.Count();
179cdf0e10cSrcweir 		nCpy = aInvRegion.Count();
180cdf0e10cSrcweir 	}
181cdf0e10cSrcweir 	// alle vorhandenen ueberschreiben
182cdf0e10cSrcweir 	memcpy( pData, aInvRegion.GetData(), nCpy * sizeof( SwRect ));
183cdf0e10cSrcweir 
184cdf0e10cSrcweir 	if( nCpy < aInvRegion.Count() )
185cdf0e10cSrcweir 		Insert( &aInvRegion, nCpy, nCpy );
186cdf0e10cSrcweir 	else if( nDel )
187cdf0e10cSrcweir 		Remove( nCpy, nDel );
188cdf0e10cSrcweir }
189cdf0e10cSrcweir /*************************************************************************
190cdf0e10cSrcweir |*
191cdf0e10cSrcweir |*	SwRegionRects::Compress()
192cdf0e10cSrcweir |*
193cdf0e10cSrcweir |*	Beschreibung		Zusammenfassen von benachbarten Rechtecken.
194cdf0e10cSrcweir |*	Ersterstellung		MA 16. Apr. 93
195cdf0e10cSrcweir |*	Letzte Aenderung	MA 21. Apr. 93
196cdf0e10cSrcweir |*
197cdf0e10cSrcweir |*************************************************************************/
CalcArea(const SwRect & rRect)198cdf0e10cSrcweir inline SwTwips CalcArea( const SwRect &rRect )
199cdf0e10cSrcweir {
200cdf0e10cSrcweir 	return rRect.Width() * rRect.Height();
201cdf0e10cSrcweir }
202cdf0e10cSrcweir 
203cdf0e10cSrcweir 
Compress(sal_Bool bFuzzy)204cdf0e10cSrcweir void SwRegionRects::Compress( sal_Bool bFuzzy )
205cdf0e10cSrcweir {
206cdf0e10cSrcweir 	for ( int i = 0; i < Count(); ++i )
207cdf0e10cSrcweir 	{
208cdf0e10cSrcweir 		for ( int j = i+1; j < Count(); ++j )
209cdf0e10cSrcweir 		{
210cdf0e10cSrcweir 			//Wenn zwei Rechtecke ineinanderliegen, so ist eins davon
211cdf0e10cSrcweir 			//uberfluessig.
212cdf0e10cSrcweir 			if ( (*(pData + i)).IsInside( *(pData + j) ) )
213cdf0e10cSrcweir 			{
214cdf0e10cSrcweir 				Remove( static_cast<sal_uInt16>(j), 1 );
215cdf0e10cSrcweir 				--j;
216cdf0e10cSrcweir 			}
217cdf0e10cSrcweir 			else if ( (*(pData + j)).IsInside( *(pData + i) ) )
218cdf0e10cSrcweir 			{
219cdf0e10cSrcweir 				*(pData + i) = *(pData + j);
220cdf0e10cSrcweir 				Remove( static_cast<sal_uInt16>(j), 1 );
221cdf0e10cSrcweir 				i = -1;
222cdf0e10cSrcweir 				break;
223cdf0e10cSrcweir 			}
224cdf0e10cSrcweir 			else
225cdf0e10cSrcweir 			{
226cdf0e10cSrcweir 				//Wenn zwei Rechtecke dieselbe Flaeche haben wie deren
227cdf0e10cSrcweir 				//Union abzueglich deren Intersection, so ist eines
228cdf0e10cSrcweir 				//davon ueberfluessig.
229cdf0e10cSrcweir 				//Um moeglichst viel zusammenzufassen und in der Folge
230cdf0e10cSrcweir 				//moeglichst wenig einzelne Paints zu haben darf die Flaeche
231cdf0e10cSrcweir 				//der Union ruhig ein bischen groesser sein
232cdf0e10cSrcweir 				//( 9622 * 141.5 = 1361513 ~= ein virtel Zentimeter ueber die
233cdf0e10cSrcweir 				//						      Breite einer DINA4 Seite)
234cdf0e10cSrcweir 				const long nFuzzy = bFuzzy ? 1361513 : 0;
235cdf0e10cSrcweir 				SwRect aUnion( *(pData + i) );aUnion.Union( *(pData + j) );
236cdf0e10cSrcweir 				SwRect aInter( *(pData + i) );aInter.Intersection( *(pData + j));
237cdf0e10cSrcweir 				if ( (::CalcArea( *(pData + i) ) +
238cdf0e10cSrcweir 					  ::CalcArea( *(pData + j) ) + nFuzzy) >=
239cdf0e10cSrcweir 					 (::CalcArea( aUnion ) - CalcArea( aInter )) )
240cdf0e10cSrcweir 				{
241cdf0e10cSrcweir 					*(pData + i) = aUnion;
242cdf0e10cSrcweir 					Remove( static_cast<sal_uInt16>(j), 1 );
243cdf0e10cSrcweir 					i = -1;
244cdf0e10cSrcweir 					break;
245cdf0e10cSrcweir 				}
246cdf0e10cSrcweir 			}
247cdf0e10cSrcweir 		}
248cdf0e10cSrcweir 	}
249cdf0e10cSrcweir }
250cdf0e10cSrcweir 
251