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: swregion.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_sw.hxx"
37 #include <tools/debug.hxx>
38 #include "swtypes.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
,
56 SwRects( (BYTE
)nInit
, (BYTE
)nGrow
),
62 /*************************************************************************
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
,
75 pData
= (SwRect
*)pData
; // looks weird but seems to help gcc ->i78417
76 *(pData
+nPos
) = rRect
;
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
90 |* Dazu muessen die vorhandenen Rechtecke entweder aufgeteilt oder
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().
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
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();
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
);
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
)
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
);
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
219 if ( (*(pData
+ i
)).IsInside( *(pData
+ j
) ) )
221 Remove( static_cast<USHORT
>(j
), 1 );
224 else if ( (*(pData
+ j
)).IsInside( *(pData
+ i
) ) )
226 *(pData
+ i
) = *(pData
+ j
);
227 Remove( static_cast<USHORT
>(j
), 1 );
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 );