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  tools::Long nTmp = aInter.Top() - aTmp.Top();
78  if ( 0 < nTmp )
79  {
80  const tools::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  nTmp = aInter.Left() - aTmp.Left();
93  if ( 0 < nTmp )
94  {
95  const tools::Long nOldVal = aTmp.Width();
96  aTmp.Width( nTmp );
97  InsertRect( aTmp, i, bDel );
98  aTmp.Width( nOldVal );
99  }
100 
101  aTmp.Left( aInter.Left() + aInter.Width() ); //+1?
102  if ( aTmp.Width() > 0 )
103  InsertRect( aTmp, i, bDel );
104 
105  if( bDel )
106  {
107  erase( begin() + i );
108  --i; // so that we don't forget any
109  --nMax; // so that we don't check too much
110  }
111  }
112  }
113 }
114 
123 {
124  // not very elegant and fast, but efficient:
125  // Create a new region and remove all areas that are left over. Afterwards
126  // copy all values.
127 
128  // To avoid unnecessary memory requirements, create a "useful" initial size:
129  // Number of rectangles in this area * 2 + 2 for the special case of a
130  // single hole (so four Rects in the inverse case).
131  SwRegionRects aInvRegion( m_aOrigin, size()*2+2 );
132  for( const_iterator it = begin(); it != end(); ++it )
133  aInvRegion -= *it;
134 
135  // overwrite all existing
136  swap( aInvRegion );
137 }
138 
139 static SwTwips CalcArea( const SwRect &rRect )
140 {
141  return rRect.Width() * rRect.Height();
142 }
143 
144 // combine all adjacent rectangles
146 {
147  for (size_type i = 0; i < size(); )
148  {
149  bool bRestart(false);
150  for ( size_type j = i+1; j < size(); ++j )
151  {
152  // If one rectangle contains a second completely than the latter
153  // does not need to be stored and can be deleted
154  if ( (*this)[i].IsInside( (*this)[j] ) )
155  {
156  erase( begin() + j );
157  --j;
158  }
159  else if ( (*this)[j].IsInside( (*this)[i] ) )
160  {
161  (*this)[i] = (*this)[j];
162  erase( begin() + j );
163  bRestart = true;
164  break;
165  }
166  else
167  {
168  // If two rectangles have the same area of their union minus the
169  // intersection then one of them can be deleted.
170  // For combining as much as possible (and for having less single
171  // paints), the area of the union can be a little bit larger:
172  // ( 9622 * 141.5 = 1361513 ~= a quarter (1/4) centimeter wider
173  // than the width of an A4 page
174  const tools::Long nFuzzy = 1361513;
175  SwRect aUnion( (*this)[i] );
176  aUnion.Union( (*this)[j] );
177  SwRect aInter( (*this)[i] );
178  aInter.Intersection( (*this)[j] );
179  if ( (::CalcArea( (*this)[i] ) +
180  ::CalcArea( (*this)[j] ) + nFuzzy) >=
181  (::CalcArea( aUnion ) - CalcArea( aInter )) )
182  {
183  (*this)[i] = aUnion;
184  erase( begin() + j );
185  bRestart = true;
186  break;
187  }
188  }
189  }
190  i = bRestart ? 0 : i+1;
191  }
192 }
193 
194 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwRect & Union(const SwRect &rRect)
Definition: swrect.cxx:41
void Compress()
Definition: swregion.cxx:145
void operator-=(const SwRect &rRect)
Delete all overlaps of the Rects in array with the given
Definition: swregion.cxx:60
void Left(const tools::Long nLeft)
Definition: swrect.hxx:195
long Long
SwRegionRects(const SwRect &rStartRect, sal_uInt16 nInit=20)
Definition: swregion.cxx:24
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
SwRect & Intersection_(const SwRect &rRect)
Definition: swrect.cxx:80
enumrange< T >::Iterator begin(enumrange< T >)
SwRect m_aOrigin
Definition: swregion.hxx:30
SwRect & Intersection(const SwRect &rRect)
Definition: swrect.cxx:56
void operator+=(const SwRect &rRect)
Definition: swregion.cxx:48
void Invert()
invert current rectangle
Definition: swregion.cxx:122
void Width(tools::Long nNew)
Definition: swrect.hxx:187
void swap(cow_wrapper< T, P > &a, cow_wrapper< T, P > &b)
int i
size
tools::Long SwTwips
Definition: swtypes.hxx:49
enumrange< T >::Iterator end(enumrange< T >)
void Bottom(const tools::Long nBottom)
Definition: swrect.hxx:209
std::vector< SwRect > SwRects
Definition: swregion.hxx:26
static SwTwips CalcArea(const SwRect &rRect)
Definition: swregion.cxx:139
void Top(const tools::Long nTop)
Definition: swrect.hxx:204
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:123
void Height(tools::Long nNew)
Definition: swrect.hxx:191