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 36 ScInvertMerger::ScInvertMerger( Window* pWindow ) : 37 pWin( pWindow ), 38 pRects( NULL ) 39 { 40 // both rectangles empty 41 } 42 43 ScInvertMerger::ScInvertMerger( ::std::vector< Rectangle >* pRectangles ) : 44 pWin( NULL ), 45 pRects( pRectangles ) 46 { 47 // collect rectangles instead of inverting 48 } 49 50 ScInvertMerger::~ScInvertMerger() 51 { 52 Flush(); 53 } 54 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 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 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 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