1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26
27
28
29 #include <vcl/window.hxx>
30 #include <tools/debug.hxx>
31
32 #include "invmerge.hxx"
33
34 //------------------------------------------------------------------
35
ScInvertMerger(Window * pWindow)36 ScInvertMerger::ScInvertMerger( Window* pWindow ) :
37 pWin( pWindow ),
38 pRects( NULL )
39 {
40 // both rectangles empty
41 }
42
ScInvertMerger(::std::vector<Rectangle> * pRectangles)43 ScInvertMerger::ScInvertMerger( ::std::vector< Rectangle >* pRectangles ) :
44 pWin( NULL ),
45 pRects( pRectangles )
46 {
47 // collect rectangles instead of inverting
48 }
49
~ScInvertMerger()50 ScInvertMerger::~ScInvertMerger()
51 {
52 Flush();
53 }
54
Flush()55 void ScInvertMerger::Flush()
56 {
57 FlushLine();
58 FlushTotal();
59
60 DBG_ASSERT( aLineRect.IsEmpty() && aTotalRect.IsEmpty(), "Flush: not empty" );
61
62 if ( pRects )
63 {
64 //
65 // also join vertically if there are non-adjacent columns involved
66 //
67
68 size_t nComparePos = 0;
69 while ( nComparePos < pRects->size() )
70 {
71 Rectangle aCompRect = (*pRects)[nComparePos];
72 sal_Int32 nBottom = aCompRect.Bottom();
73 size_t nOtherPos = nComparePos + 1;
74
75 while ( nOtherPos < pRects->size() )
76 {
77 Rectangle aOtherRect = (*pRects)[nOtherPos];
78 if ( aOtherRect.Top() > nBottom + 1 )
79 {
80 // rectangles are sorted, so we can stop searching
81 break;
82 }
83 if ( aOtherRect.Top() == nBottom + 1 &&
84 aOtherRect.Left() == aCompRect.Left() &&
85 aOtherRect.Right() == aCompRect.Right() )
86 {
87 // extend first rectangle
88 nBottom = aOtherRect.Bottom();
89 aCompRect.Bottom() = nBottom;
90 (*pRects)[nComparePos].Bottom() = nBottom;
91
92 // remove second rectangle
93 pRects->erase( pRects->begin() + nOtherPos );
94
95 // continue at unmodified nOtherPos
96 }
97 else
98 ++nOtherPos;
99 }
100
101 ++nComparePos;
102 }
103 }
104 }
105
FlushTotal()106 void ScInvertMerger::FlushTotal()
107 {
108 if( aTotalRect.IsEmpty() )
109 return; // nothing to do
110
111 if ( pWin )
112 pWin->Invert( aTotalRect, INVERT_HIGHLIGHT );
113 else if ( pRects )
114 pRects->push_back( aTotalRect );
115
116 aTotalRect.SetEmpty();
117 }
118
FlushLine()119 void ScInvertMerger::FlushLine()
120 {
121 if( aLineRect.IsEmpty() )
122 return; // nothing to do
123
124 if ( aTotalRect.IsEmpty() )
125 {
126 aTotalRect = aLineRect; // start new total rect
127 }
128 else
129 {
130 if ( aLineRect.Left() == aTotalRect.Left() &&
131 aLineRect.Right() == aTotalRect.Right() &&
132 aLineRect.Top() == aTotalRect.Bottom() + 1 )
133 {
134 // extend total rect
135 aTotalRect.Bottom() = aLineRect.Bottom();
136 }
137 else
138 {
139 FlushTotal(); // draw old total rect
140 aTotalRect = aLineRect; // and start new one
141 }
142 }
143
144 aLineRect.SetEmpty();
145 }
146
AddRect(const Rectangle & rRect)147 void ScInvertMerger::AddRect( const Rectangle& rRect )
148 {
149 Rectangle aJustified = rRect;
150 if ( rRect.Left() > rRect.Right() ) // switch for RTL layout
151 {
152 aJustified.Left() = rRect.Right();
153 aJustified.Right() = rRect.Left();
154 }
155
156 if ( aLineRect.IsEmpty() )
157 {
158 aLineRect = aJustified; // start new line rect
159 }
160 else
161 {
162 sal_Bool bDone = sal_False;
163 if ( aJustified.Top() == aLineRect.Top() &&
164 aJustified.Bottom() == aLineRect.Bottom() )
165 {
166 // try to extend line rect
167 if ( aJustified.Left() == aLineRect.Right() + 1 )
168 {
169 aLineRect.Right() = aJustified.Right();
170 bDone = sal_True;
171 }
172 else if ( aJustified.Right() + 1 == aLineRect.Left() ) // for RTL layout
173 {
174 aLineRect.Left() = aJustified.Left();
175 bDone = sal_True;
176 }
177 }
178 if (!bDone)
179 {
180 FlushLine(); // use old line rect for total rect
181 aLineRect = aJustified; // and start new one
182 }
183 }
184 }
185
186
187
188
189