| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| |
| |
| #include <vcl/window.hxx> |
| #include <tools/debug.hxx> |
| |
| #include "invmerge.hxx" |
| |
| //------------------------------------------------------------------ |
| |
| ScInvertMerger::ScInvertMerger( Window* pWindow ) : |
| pWin( pWindow ), |
| pRects( NULL ) |
| { |
| // both rectangles empty |
| } |
| |
| ScInvertMerger::ScInvertMerger( ::std::vector< Rectangle >* pRectangles ) : |
| pWin( NULL ), |
| pRects( pRectangles ) |
| { |
| // collect rectangles instead of inverting |
| } |
| |
| ScInvertMerger::~ScInvertMerger() |
| { |
| Flush(); |
| } |
| |
| void ScInvertMerger::Flush() |
| { |
| FlushLine(); |
| FlushTotal(); |
| |
| DBG_ASSERT( aLineRect.IsEmpty() && aTotalRect.IsEmpty(), "Flush: not empty" ); |
| |
| if ( pRects ) |
| { |
| // |
| // also join vertically if there are non-adjacent columns involved |
| // |
| |
| size_t nComparePos = 0; |
| while ( nComparePos < pRects->size() ) |
| { |
| Rectangle aCompRect = (*pRects)[nComparePos]; |
| sal_Int32 nBottom = aCompRect.Bottom(); |
| size_t nOtherPos = nComparePos + 1; |
| |
| while ( nOtherPos < pRects->size() ) |
| { |
| Rectangle aOtherRect = (*pRects)[nOtherPos]; |
| if ( aOtherRect.Top() > nBottom + 1 ) |
| { |
| // rectangles are sorted, so we can stop searching |
| break; |
| } |
| if ( aOtherRect.Top() == nBottom + 1 && |
| aOtherRect.Left() == aCompRect.Left() && |
| aOtherRect.Right() == aCompRect.Right() ) |
| { |
| // extend first rectangle |
| nBottom = aOtherRect.Bottom(); |
| aCompRect.Bottom() = nBottom; |
| (*pRects)[nComparePos].Bottom() = nBottom; |
| |
| // remove second rectangle |
| pRects->erase( pRects->begin() + nOtherPos ); |
| |
| // continue at unmodified nOtherPos |
| } |
| else |
| ++nOtherPos; |
| } |
| |
| ++nComparePos; |
| } |
| } |
| } |
| |
| void ScInvertMerger::FlushTotal() |
| { |
| if( aTotalRect.IsEmpty() ) |
| return; // nothing to do |
| |
| if ( pWin ) |
| pWin->Invert( aTotalRect, INVERT_HIGHLIGHT ); |
| else if ( pRects ) |
| pRects->push_back( aTotalRect ); |
| |
| aTotalRect.SetEmpty(); |
| } |
| |
| void ScInvertMerger::FlushLine() |
| { |
| if( aLineRect.IsEmpty() ) |
| return; // nothing to do |
| |
| if ( aTotalRect.IsEmpty() ) |
| { |
| aTotalRect = aLineRect; // start new total rect |
| } |
| else |
| { |
| if ( aLineRect.Left() == aTotalRect.Left() && |
| aLineRect.Right() == aTotalRect.Right() && |
| aLineRect.Top() == aTotalRect.Bottom() + 1 ) |
| { |
| // extend total rect |
| aTotalRect.Bottom() = aLineRect.Bottom(); |
| } |
| else |
| { |
| FlushTotal(); // draw old total rect |
| aTotalRect = aLineRect; // and start new one |
| } |
| } |
| |
| aLineRect.SetEmpty(); |
| } |
| |
| void ScInvertMerger::AddRect( const Rectangle& rRect ) |
| { |
| Rectangle aJustified = rRect; |
| if ( rRect.Left() > rRect.Right() ) // switch for RTL layout |
| { |
| aJustified.Left() = rRect.Right(); |
| aJustified.Right() = rRect.Left(); |
| } |
| |
| if ( aLineRect.IsEmpty() ) |
| { |
| aLineRect = aJustified; // start new line rect |
| } |
| else |
| { |
| sal_Bool bDone = sal_False; |
| if ( aJustified.Top() == aLineRect.Top() && |
| aJustified.Bottom() == aLineRect.Bottom() ) |
| { |
| // try to extend line rect |
| if ( aJustified.Left() == aLineRect.Right() + 1 ) |
| { |
| aLineRect.Right() = aJustified.Right(); |
| bDone = sal_True; |
| } |
| else if ( aJustified.Right() + 1 == aLineRect.Left() ) // for RTL layout |
| { |
| aLineRect.Left() = aJustified.Left(); |
| bDone = sal_True; |
| } |
| } |
| if (!bDone) |
| { |
| FlushLine(); // use old line rect for total rect |
| aLineRect = aJustified; // and start new one |
| } |
| } |
| } |
| |
| |
| |
| |