LibreOffice Module sw (master)  1
swregion.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <swrect.hxx>
21 #include <swregion.hxx>
22 #include <swtypes.hxx>
23 
24 SwRegionRects::SwRegionRects( const SwRect &rStartRect, sal_uInt16 nInit ) :
25  SwRects(),
26  m_aOrigin( rStartRect )
27 {
28  reserve(nInit);
29  push_back( m_aOrigin );
30 }
31 
32 // If <rDel> is true then this Rect will be overwritten by <rRect> at
33 // position <nPos>. Otherwise <rRect> is attached at the end.
34 inline void SwRegionRects::InsertRect( const SwRect &rRect,
35  const sal_uInt16 nPos, bool &rDel )
36 {
37  if( rDel )
38  {
39  (*this)[nPos] = rRect;
40  rDel = false;
41  }
42  else
43  {
44  push_back( rRect );
45  }
46 }
47 
48 void SwRegionRects::operator+=( const SwRect &rRect )
49 {
50  bool f = false;
51  InsertRect( rRect, 0, f );
52 }
53 
60 void SwRegionRects::operator-=( const SwRect &rRect )
61 {
62  sal_uInt16 nMax = size();
63  for ( sal_uInt16 i = 0; i < nMax; ++i )
64  {
65  if ( rRect.IsOver( (*this)[i] ) )
66  {
67  SwRect aTmp( (*this)[i] );
68  SwRect aInter( aTmp );
69  aInter.Intersection_( rRect );
70 
71  // The first Rect that should be inserted takes position of i.
72  // This avoids one Delete() call.
73  bool bDel = true;
74 
75  // now split; only those rectangles should be left over that are in
76  // the "old" but not in the "new" area; hence, not in intersection.
77  long nTmp;
78  if ( 0 < (nTmp = aInter.Top() - aTmp.Top()) )
79  {
80  const long nOldVal = aTmp.Height();
81  aTmp.Height(nTmp);
82  InsertRect( aTmp, i, bDel );
83  aTmp.Height( nOldVal );
84  }
85 
86  aTmp.Top( aInter.Top() + aInter.Height() );
87  if ( aTmp.Height() > 0 )
88  InsertRect( aTmp, i, bDel );
89 
90  aTmp.Top( aInter.Top() );
91  aTmp.Bottom( aInter.Bottom() );
92  if ( 0 < (nTmp = aInter.Left() - aTmp.Left()) )
93  {
94  const long nOldVal = aTmp.Width();
95  aTmp.Width( nTmp );
96  InsertRect( aTmp, i, bDel );
97  aTmp.Width( nOldVal );
98  }
99 
100  aTmp.Left( aInter.Left() + aInter.Width() ); //+1?
101  if ( aTmp.Width() > 0 )
102  InsertRect( aTmp, i, bDel );
103 
104  if( bDel )
105  {
106  erase( begin() + i );
107  --i; // so that we don't forget any
108  --nMax; // so that we don't check too much
109  }
110  }
111  }
112 }
113 
122 {
123  // not very elegant and fast, but efficient:
124  // Create a new region and remove all areas that are left over. Afterwards
125  // copy all values.
126 
127  // To avoid unnecessary memory requirements, create a "useful" initial size:
128  // Number of rectangles in this area * 2 + 2 for the special case of a
129  // single hole (so four Rects in the inverse case).
130  SwRegionRects aInvRegion( m_aOrigin, size()*2+2 );
131  for( const_iterator it = begin(); it != end(); ++it )
132  aInvRegion -= *it;
133 
134  // overwrite all existing
135  swap( aInvRegion );
136 }
137 
138 static SwTwips CalcArea( const SwRect &rRect )
139 {
140  return rRect.Width() * rRect.Height();
141 }
142 
143 // combine all adjacent rectangles
145 {
146  for (size_type i = 0; i < size(); )
147  {
148  bool bRestart(false);
149  for ( size_type j = i+1; j < size(); ++j )
150  {
151  // If one rectangle contains a second completely than the latter
152  // does not need to be stored and can be deleted
153  if ( (*this)[i].IsInside( (*this)[j] ) )
154  {
155  erase( begin() + j );
156  --j;
157  }
158  else if ( (*this)[j].IsInside( (*this)[i] ) )
159  {
160  (*this)[i] = (*this)[j];
161  erase( begin() + j );
162  bRestart = true;
163  break;
164  }
165  else
166  {
167  // If two rectangles have the same area of their union minus the
168  // intersection then one of them can be deleted.
169  // For combining as much as possible (and for having less single
170  // paints), the area of the union can be a little bit larger:
171  // ( 9622 * 141.5 = 1361513 ~= a quarter (1/4) centimeter wider
172  // than the width of a A4 page
173  const long nFuzzy = 1361513;
174  SwRect aUnion( (*this)[i] );
175  aUnion.Union( (*this)[j] );
176  SwRect aInter( (*this)[i] );
177  aInter.Intersection( (*this)[j] );
178  if ( (::CalcArea( (*this)[i] ) +
179  ::CalcArea( (*this)[j] ) + nFuzzy) >=
180  (::CalcArea( aUnion ) - CalcArea( aInter )) )
181  {
182  (*this)[i] = aUnion;
183  erase( begin() + j );
184  bRestart = true;
185  break;
186  }
187  }
188  }
189  i = bRestart ? 0 : i+1;
190  }
191 }
192 
193 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwRect & Union(const SwRect &rRect)
Definition: swrect.cxx:42
void Compress()
Definition: swregion.cxx:144
void operator-=(const SwRect &rRect)
Delete all overlaps of the Rects in array with the given
Definition: swregion.cxx:60
SwRegionRects(const SwRect &rStartRect, sal_uInt16 nInit=20)
Definition: swregion.cxx:24
void Height(long nNew)
Definition: swrect.hxx:189
long SwTwips
Definition: swtypes.hxx:49
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
SwRect & Intersection_(const SwRect &rRect)
Definition: swrect.cxx:81
void Top(const long nTop)
Definition: swrect.hxx:202
enumrange< T >::Iterator begin(enumrange< T >)
SwRect m_aOrigin
Definition: swregion.hxx:30
SwRect & Intersection(const SwRect &rRect)
Definition: swrect.cxx:57
void operator+=(const SwRect &rRect)
Definition: swregion.cxx:48
void Invert()
invert current rectangle
Definition: swregion.cxx:121
void swap(cow_wrapper< T, P > &a, cow_wrapper< T, P > &b)
int i
size
enumrange< T >::Iterator end(enumrange< T >)
void Left(const long nLeft)
Definition: swrect.hxx:193
void Bottom(const long nBottom)
Definition: swrect.hxx:207
std::vector< SwRect > SwRects
Definition: swregion.hxx:26
void Width(long nNew)
Definition: swrect.hxx:185
static SwTwips CalcArea(const SwRect &rRect)
Definition: swregion.cxx:138
void InsertRect(const SwRect &rRect, const sal_uInt16 nPos, bool &rDel)
Definition: swregion.cxx:34
void(* f)(TrueTypeTable *)
bool IsOver(const SwRect &rRect) const
Definition: swrect.cxx:128