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