merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / bastyp / swregion.cxx
blobf0ee36b12a3cb7a0dd727b82c0c01f666d7344c4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: swregion.cxx,v $
10 * $Revision: 1.8 $
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_sw.hxx"
37 #include <tools/debug.hxx>
38 #include "swtypes.hxx"
39 #include "swrect.hxx"
40 #include "swregion.hxx"
43 SV_IMPL_VARARR( SwRects, SwRect );
45 /*************************************************************************
47 |* SwRegionRects::SwRegionRects()
49 |* Ersterstellung MA 28. Oct. 92
50 |* Letzte Aenderung MA 01. Feb. 93
52 |*************************************************************************/
54 SwRegionRects::SwRegionRects( const SwRect &rStartRect, USHORT nInit,
55 USHORT nGrow ) :
56 SwRects( (BYTE)nInit, (BYTE)nGrow ),
57 aOrigin( rStartRect )
59 Insert( aOrigin, 0 );
62 /*************************************************************************
63 * inline InsertRect()
65 * InsertRect() wird nur von operator-=() gerufen.
66 * Wenn bDel == TRUE ist, dann wird das Rect an der Position nPos mit
67 * rRect ueberschrieben, ansonsten wird rRect hinten angehaengt.
68 *************************************************************************/
70 inline void SwRegionRects::InsertRect( const SwRect &rRect, const USHORT nPos,
71 BOOL &rDel )
73 if( rDel )
75 pData = (SwRect*)pData; // looks weird but seems to help gcc ->i78417
76 *(pData+nPos) = rRect;
77 rDel = FALSE;
79 else
80 Insert( rRect, Count() );
83 /*************************************************************************
85 |* SwRegionRects::operator-=()
87 |* Beschreibung Alle Ueberschneidungen der Rechtecke, die sich
88 |* gerade im Array befinden, mit dem uebergebenen Rechteck werden
89 |* entfernt.
90 |* Dazu muessen die vorhandenen Rechtecke entweder aufgeteilt oder
91 |* geloescht werden.
92 |* Ersterstellung MA 28. Oct. 92
93 |* Letzte Aenderung MA 09. Sep. 93
95 |*************************************************************************/
97 void SwRegionRects::operator-=( const SwRect &rRect )
99 USHORT nMax = Count();
100 for ( USHORT i = 0; i < nMax; ++i )
102 if ( rRect.IsOver( *(pData+i) ) )
104 SwRect aTmp( *(pData+i) );
105 SwRect aInter( aTmp );
106 aInter._Intersection( rRect );
108 // Das erste Rect, das wir inserten wollen, nimmt die
109 // Stelle von i ein. So ersparen wir uns das Delete().
110 BOOL bDel = TRUE;
112 //Jetzt aufteilen das Teil: Es sollen diejenigen Rechtecke
113 //zurueckbleiben, die im alten aber nicht im neuen liegen.
114 //Sprich alle Rechtecke die im alten aber nicht in der Intersection
115 //liegen.
116 long nTmp;
117 if ( 0 < (nTmp = aInter.Top() - aTmp.Top()) )
119 const long nOldVal = aTmp.Height();
120 aTmp.SSize().Height() = nTmp;
121 InsertRect( aTmp, i, bDel );
122 aTmp.Height( nOldVal );
125 aTmp.Top( aInter.Top() + aInter.Height() );
126 if ( aTmp.Height() > 0 )
127 InsertRect( aTmp, i, bDel );
129 aTmp.Top( aInter.Top() );
130 aTmp.Bottom( aInter.Bottom() );
131 if ( 0 < (nTmp = aInter.Left() - aTmp.Left()) )
133 const long nOldVal = aTmp.Width();
134 aTmp.Width( nTmp );
135 InsertRect( aTmp, i, bDel );
136 aTmp.Width( nOldVal );
139 aTmp.Left( aInter.Left() + aInter.Width() ); //+1?
140 if ( aTmp.Width() > 0 )
141 InsertRect( aTmp, i, bDel );
143 if( bDel )
145 Remove( i );
146 --i; //Damit wir keinen uebergehen.
147 --nMax; //Damit wir keinen zuviel verarbeiten.
154 /*************************************************************************
155 * SwRegionRects::Invert()
157 * Bezugspunkt ist aOrigin, das Original-SRectangle.
158 * Aus Loechern werden Flaechen, aus Flaechen werden Loecher.
159 * Ein Hinweis: Wenn keine Rects abgezogen wurden, so ist das enthaltene
160 * Rechteck identisch mit aOrigin. Nach Invert() besteht die Region aus
161 * einem Null-SRectangle.
162 *************************************************************************/
164 void SwRegionRects::Invert()
166 // Nicht besonders elegant und schnell, aber wirkungsvoll:
167 // Wir legen eine weitere Region an und ziehen alle Flaechen ab,
168 // die in uns noch uebrig geblieben sind. Danach werden alle
169 // Werte uebertragen.
171 // Um unuetze Speicheranforderungen zu vermeiden versuchen wir die
172 // iniale Groesse moeglichst brauchbar anzulegen:
173 // Anzahl der Rechtecke in der Region * 2 + 2
174 // plus zwei um den Sonderfall eines einzelnen Loches (macht vier
175 // Rechtecke im inversen Fall) abzudecken.
177 SwRegionRects aInvRegion( aOrigin, Count()*2+2 );
178 const SwRect *pDat = GetData();
179 for( USHORT i = 0; i < Count(); ++pDat, ++i )
180 aInvRegion -= *pDat;
182 USHORT nCpy = Count(), nDel = 0;
183 if( aInvRegion.Count() < Count() )
185 nDel = Count() - aInvRegion.Count();
186 nCpy = aInvRegion.Count();
188 // alle vorhandenen ueberschreiben
189 memcpy( pData, aInvRegion.GetData(), nCpy * sizeof( SwRect ));
191 if( nCpy < aInvRegion.Count() )
192 Insert( &aInvRegion, nCpy, nCpy );
193 else if( nDel )
194 Remove( nCpy, nDel );
196 /*************************************************************************
198 |* SwRegionRects::Compress()
200 |* Beschreibung Zusammenfassen von benachbarten Rechtecken.
201 |* Ersterstellung MA 16. Apr. 93
202 |* Letzte Aenderung MA 21. Apr. 93
204 |*************************************************************************/
205 inline SwTwips CalcArea( const SwRect &rRect )
207 return rRect.Width() * rRect.Height();
211 void SwRegionRects::Compress( BOOL bFuzzy )
213 for ( int i = 0; i < Count(); ++i )
215 for ( int j = i+1; j < Count(); ++j )
217 //Wenn zwei Rechtecke ineinanderliegen, so ist eins davon
218 //uberfluessig.
219 if ( (*(pData + i)).IsInside( *(pData + j) ) )
221 Remove( static_cast<USHORT>(j), 1 );
222 --j;
224 else if ( (*(pData + j)).IsInside( *(pData + i) ) )
226 *(pData + i) = *(pData + j);
227 Remove( static_cast<USHORT>(j), 1 );
228 i = -1;
229 break;
231 else
233 //Wenn zwei Rechtecke dieselbe Flaeche haben wie deren
234 //Union abzueglich deren Intersection, so ist eines
235 //davon ueberfluessig.
236 //Um moeglichst viel zusammenzufassen und in der Folge
237 //moeglichst wenig einzelne Paints zu haben darf die Flaeche
238 //der Union ruhig ein bischen groesser sein
239 //( 9622 * 141.5 = 1361513 ~= ein virtel Zentimeter ueber die
240 // Breite einer DINA4 Seite)
241 const long nFuzzy = bFuzzy ? 1361513 : 0;
242 SwRect aUnion( *(pData + i) );aUnion.Union( *(pData + j) );
243 SwRect aInter( *(pData + i) );aInter.Intersection( *(pData + j));
244 if ( (::CalcArea( *(pData + i) ) +
245 ::CalcArea( *(pData + j) ) + nFuzzy) >=
246 (::CalcArea( aUnion ) - CalcArea( aInter )) )
248 *(pData + i) = aUnion;
249 Remove( static_cast<USHORT>(j), 1 );
250 i = -1;
251 break;