1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 32 33 #include <vcl/window.hxx> 34 #include <tools/debug.hxx> 35 36 #include "invmerge.hxx" 37 38 //------------------------------------------------------------------ 39 40 ScInvertMerger::ScInvertMerger( Window* pWindow ) : 41 pWin( pWindow ), 42 pRects( NULL ) 43 { 44 // both rectangles empty 45 } 46 47 ScInvertMerger::ScInvertMerger( ::std::vector< Rectangle >* pRectangles ) : 48 pWin( NULL ), 49 pRects( pRectangles ) 50 { 51 // collect rectangles instead of inverting 52 } 53 54 ScInvertMerger::~ScInvertMerger() 55 { 56 Flush(); 57 } 58 59 void ScInvertMerger::Flush() 60 { 61 FlushLine(); 62 FlushTotal(); 63 64 DBG_ASSERT( aLineRect.IsEmpty() && aTotalRect.IsEmpty(), "Flush: not empty" ); 65 66 if ( pRects ) 67 { 68 // 69 // also join vertically if there are non-adjacent columns involved 70 // 71 72 size_t nComparePos = 0; 73 while ( nComparePos < pRects->size() ) 74 { 75 Rectangle aCompRect = (*pRects)[nComparePos]; 76 sal_Int32 nBottom = aCompRect.Bottom(); 77 size_t nOtherPos = nComparePos + 1; 78 79 while ( nOtherPos < pRects->size() ) 80 { 81 Rectangle aOtherRect = (*pRects)[nOtherPos]; 82 if ( aOtherRect.Top() > nBottom + 1 ) 83 { 84 // rectangles are sorted, so we can stop searching 85 break; 86 } 87 if ( aOtherRect.Top() == nBottom + 1 && 88 aOtherRect.Left() == aCompRect.Left() && 89 aOtherRect.Right() == aCompRect.Right() ) 90 { 91 // extend first rectangle 92 nBottom = aOtherRect.Bottom(); 93 aCompRect.Bottom() = nBottom; 94 (*pRects)[nComparePos].Bottom() = nBottom; 95 96 // remove second rectangle 97 pRects->erase( pRects->begin() + nOtherPos ); 98 99 // continue at unmodified nOtherPos 100 } 101 else 102 ++nOtherPos; 103 } 104 105 ++nComparePos; 106 } 107 } 108 } 109 110 void ScInvertMerger::FlushTotal() 111 { 112 if( aTotalRect.IsEmpty() ) 113 return; // nothing to do 114 115 if ( pWin ) 116 pWin->Invert( aTotalRect, INVERT_HIGHLIGHT ); 117 else if ( pRects ) 118 pRects->push_back( aTotalRect ); 119 120 aTotalRect.SetEmpty(); 121 } 122 123 void ScInvertMerger::FlushLine() 124 { 125 if( aLineRect.IsEmpty() ) 126 return; // nothing to do 127 128 if ( aTotalRect.IsEmpty() ) 129 { 130 aTotalRect = aLineRect; // start new total rect 131 } 132 else 133 { 134 if ( aLineRect.Left() == aTotalRect.Left() && 135 aLineRect.Right() == aTotalRect.Right() && 136 aLineRect.Top() == aTotalRect.Bottom() + 1 ) 137 { 138 // extend total rect 139 aTotalRect.Bottom() = aLineRect.Bottom(); 140 } 141 else 142 { 143 FlushTotal(); // draw old total rect 144 aTotalRect = aLineRect; // and start new one 145 } 146 } 147 148 aLineRect.SetEmpty(); 149 } 150 151 void ScInvertMerger::AddRect( const Rectangle& rRect ) 152 { 153 Rectangle aJustified = rRect; 154 if ( rRect.Left() > rRect.Right() ) // switch for RTL layout 155 { 156 aJustified.Left() = rRect.Right(); 157 aJustified.Right() = rRect.Left(); 158 } 159 160 if ( aLineRect.IsEmpty() ) 161 { 162 aLineRect = aJustified; // start new line rect 163 } 164 else 165 { 166 sal_Bool bDone = sal_False; 167 if ( aJustified.Top() == aLineRect.Top() && 168 aJustified.Bottom() == aLineRect.Bottom() ) 169 { 170 // try to extend line rect 171 if ( aJustified.Left() == aLineRect.Right() + 1 ) 172 { 173 aLineRect.Right() = aJustified.Right(); 174 bDone = sal_True; 175 } 176 else if ( aJustified.Right() + 1 == aLineRect.Left() ) // for RTL layout 177 { 178 aLineRect.Left() = aJustified.Left(); 179 bDone = sal_True; 180 } 181 } 182 if (!bDone) 183 { 184 FlushLine(); // use old line rect for total rect 185 aLineRect = aJustified; // and start new one 186 } 187 } 188 } 189 190 191 192 193