LCOV - code coverage report
Current view: top level - svx/source/svdraw - svdglue.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 141 266 53.0 %
Date: 2015-06-13 12:38:46 Functions: 17 25 68.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <tools/debug.hxx>
      21             : 
      22             : #include <svx/svdglue.hxx>
      23             : #include <svx/svdobj.hxx>
      24             : #include <svx/svdtrans.hxx>
      25             : 
      26         145 : static const Size aGlueHalfSize(4,4);
      27             : 
      28         204 : void SdrGluePoint::SetReallyAbsolute(bool bOn, const SdrObject& rObj)
      29             : {
      30         204 :     if ( bReallyAbsolute != bOn )
      31             :     {
      32         102 :        if ( bOn )
      33             :        {
      34         102 :            aPos=GetAbsolutePos(rObj);
      35         102 :            bReallyAbsolute=bOn;
      36             :        }
      37             :        else
      38             :        {
      39           0 :            bReallyAbsolute=bOn;
      40           0 :            Point aPt(aPos);
      41           0 :            SetAbsolutePos(aPt,rObj);
      42             :        }
      43             :     }
      44         204 : }
      45             : 
      46         204 : Point SdrGluePoint::GetAbsolutePos(const SdrObject& rObj) const
      47             : {
      48         204 :     if (bReallyAbsolute) return aPos;
      49         204 :     Rectangle aSnap(rObj.GetSnapRect());
      50         204 :     Rectangle aBound(rObj.GetSnapRect());
      51         204 :     Point aPt(aPos);
      52             : 
      53         204 :     Point aOfs(aSnap.Center());
      54         204 :     switch (GetHorzAlign()) {
      55         204 :         case SdrAlign::HORZ_LEFT  : aOfs.X()=aSnap.Left(); break;
      56           0 :         case SdrAlign::HORZ_RIGHT : aOfs.X()=aSnap.Right(); break;
      57           0 :         default: break;
      58             :     }
      59         204 :     switch (GetVertAlign()) {
      60         204 :         case SdrAlign::VERT_TOP   : aOfs.Y()=aSnap.Top(); break;
      61           0 :         case SdrAlign::VERT_BOTTOM: aOfs.Y()=aSnap.Bottom(); break;
      62           0 :         default: break;
      63             :     }
      64         204 :     if (!bNoPercent) {
      65           0 :         long nXMul=aSnap.Right()-aSnap.Left();
      66           0 :         long nYMul=aSnap.Bottom()-aSnap.Top();
      67           0 :         long nXDiv=10000;
      68           0 :         long nYDiv=10000;
      69           0 :         if (nXMul!=nXDiv) {
      70           0 :             aPt.X()*=nXMul;
      71           0 :             aPt.X()/=nXDiv;
      72             :         }
      73           0 :         if (nYMul!=nYDiv) {
      74           0 :             aPt.Y()*=nYMul;
      75           0 :             aPt.Y()/=nYDiv;
      76             :         }
      77             :     }
      78         204 :     aPt+=aOfs;
      79             :     // Now limit to the BoundRect of the object
      80         204 :     if (aPt.X()<aBound.Left  ()) aPt.X()=aBound.Left  ();
      81         204 :     if (aPt.X()>aBound.Right ()) aPt.X()=aBound.Right ();
      82         204 :     if (aPt.Y()<aBound.Top   ()) aPt.Y()=aBound.Top   ();
      83         204 :     if (aPt.Y()>aBound.Bottom()) aPt.Y()=aBound.Bottom();
      84         204 :     return aPt;
      85             : }
      86             : 
      87         102 : void SdrGluePoint::SetAbsolutePos(const Point& rNewPos, const SdrObject& rObj)
      88             : {
      89         102 :     if (bReallyAbsolute) {
      90           0 :         aPos=rNewPos;
      91         102 :         return;
      92             :     }
      93         102 :     Rectangle aSnap(rObj.GetSnapRect());
      94         102 :     Point aPt(rNewPos);
      95             : 
      96         102 :     Point aOfs(aSnap.Center());
      97         102 :     switch (GetHorzAlign()) {
      98          81 :         case SdrAlign::HORZ_LEFT  : aOfs.X()=aSnap.Left(); break;
      99          15 :         case SdrAlign::HORZ_RIGHT : aOfs.X()=aSnap.Right(); break;
     100           6 :         default: break;
     101             :     }
     102         102 :     switch (GetVertAlign()) {
     103          72 :         case SdrAlign::VERT_TOP   : aOfs.Y()=aSnap.Top(); break;
     104          30 :         case SdrAlign::VERT_BOTTOM: aOfs.Y()=aSnap.Bottom(); break;
     105           0 :         default: break;
     106             :     }
     107         102 :     aPt-=aOfs;
     108         102 :     if (!bNoPercent) {
     109           0 :         long nXMul=aSnap.Right()-aSnap.Left();
     110           0 :         long nYMul=aSnap.Bottom()-aSnap.Top();
     111           0 :         if (nXMul==0) nXMul=1;
     112           0 :         if (nYMul==0) nYMul=1;
     113           0 :         long nXDiv=10000;
     114           0 :         long nYDiv=10000;
     115           0 :         if (nXMul!=nXDiv) {
     116           0 :             aPt.X()*=nXDiv;
     117           0 :             aPt.X()/=nXMul;
     118             :         }
     119           0 :         if (nYMul!=nYDiv) {
     120           0 :             aPt.Y()*=nYDiv;
     121           0 :             aPt.Y()/=nYMul;
     122             :         }
     123             :     }
     124         102 :     aPos=aPt;
     125             : }
     126             : 
     127         102 : long SdrGluePoint::GetAlignAngle() const
     128             : {
     129         102 :     if (nAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_CENTER))
     130           0 :         return 0; // Invalid!
     131         102 :     else if (nAlign == (SdrAlign::HORZ_RIGHT |SdrAlign::VERT_CENTER))
     132           0 :         return 0;
     133         102 :     else if (nAlign == (SdrAlign::HORZ_RIGHT |SdrAlign::VERT_TOP))
     134           0 :         return 4500;
     135         102 :     else if (nAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_TOP))
     136           0 :         return 9000;
     137         102 :     else if (nAlign == (SdrAlign::HORZ_LEFT  |SdrAlign::VERT_TOP))
     138         102 :         return 13500;
     139           0 :     else if (nAlign == (SdrAlign::HORZ_LEFT  |SdrAlign::VERT_CENTER))
     140           0 :         return 18000;
     141           0 :     else if (nAlign == (SdrAlign::HORZ_LEFT  |SdrAlign::VERT_BOTTOM))
     142           0 :         return 22500;
     143           0 :     else if (nAlign == (SdrAlign::HORZ_CENTER|SdrAlign::VERT_BOTTOM))
     144           0 :         return 27000;
     145           0 :     else if (nAlign == (SdrAlign::HORZ_RIGHT |SdrAlign::VERT_BOTTOM))
     146           0 :         return 31500;
     147           0 :     return 0;
     148             : }
     149             : 
     150         102 : void SdrGluePoint::SetAlignAngle(long nAngle)
     151             : {
     152         102 :     nAngle=NormAngle360(nAngle);
     153         102 :     if (nAngle>=33750 || nAngle<2250) nAlign=SdrAlign::HORZ_RIGHT |SdrAlign::VERT_CENTER;
     154         102 :     else if (nAngle< 6750) nAlign=SdrAlign::HORZ_RIGHT |SdrAlign::VERT_TOP   ;
     155         102 :     else if (nAngle<11250) nAlign=SdrAlign::HORZ_CENTER|SdrAlign::VERT_TOP   ;
     156          96 :     else if (nAngle<15750) nAlign=SdrAlign::HORZ_LEFT  |SdrAlign::VERT_TOP   ;
     157          30 :     else if (nAngle<20250) nAlign=SdrAlign::HORZ_LEFT  |SdrAlign::VERT_CENTER;
     158          30 :     else if (nAngle<24750) nAlign=SdrAlign::HORZ_LEFT  |SdrAlign::VERT_BOTTOM;
     159          15 :     else if (nAngle<29250) nAlign=SdrAlign::HORZ_CENTER|SdrAlign::VERT_BOTTOM;
     160          15 :     else if (nAngle<33750) nAlign=SdrAlign::HORZ_RIGHT |SdrAlign::VERT_BOTTOM;
     161         102 : }
     162             : 
     163           0 : long SdrGluePoint::EscDirToAngle(SdrEscapeDirection nEsc)
     164             : {
     165           0 :     switch (nEsc) {
     166           0 :         case SdrEscapeDirection::RIGHT : return 0;
     167           0 :         case SdrEscapeDirection::TOP   : return 9000;
     168           0 :         case SdrEscapeDirection::LEFT  : return 18000;
     169           0 :         case SdrEscapeDirection::BOTTOM: return 27000;
     170           0 :         default: break;
     171             :     } // switch
     172           0 :     return 0;
     173             : }
     174             : 
     175           0 : SdrEscapeDirection SdrGluePoint::EscAngleToDir(long nAngle)
     176             : {
     177           0 :     nAngle=NormAngle360(nAngle);
     178           0 :     if (nAngle>=31500 || nAngle<4500)
     179           0 :         return SdrEscapeDirection::RIGHT;
     180           0 :     if (nAngle<13500)
     181           0 :         return SdrEscapeDirection::TOP;
     182           0 :     if (nAngle<22500)
     183           0 :         return SdrEscapeDirection::LEFT;
     184             :     /* (nAngle<31500)*/
     185           0 :     return SdrEscapeDirection::BOTTOM;
     186             : }
     187             : 
     188          87 : void SdrGluePoint::Rotate(const Point& rRef, long nAngle, double sn, double cs, const SdrObject* pObj)
     189             : {
     190          87 :     Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos());
     191          87 :     RotatePoint(aPt,rRef,sn,cs);
     192             :     // rotate reference edge
     193          87 :     if(nAlign != (SdrAlign::HORZ_CENTER|SdrAlign::VERT_CENTER))
     194             :     {
     195          87 :         SetAlignAngle(GetAlignAngle()+nAngle);
     196             :     }
     197             :     // rotate exit directions
     198          87 :     SdrEscapeDirection nEscDir0=nEscDir;
     199          87 :     SdrEscapeDirection nEscDir1=SdrEscapeDirection::SMART;
     200          87 :     if (nEscDir0&SdrEscapeDirection::LEFT  ) nEscDir1 |= EscAngleToDir(EscDirToAngle(SdrEscapeDirection::LEFT  )+nAngle);
     201          87 :     if (nEscDir0&SdrEscapeDirection::TOP   ) nEscDir1 |= EscAngleToDir(EscDirToAngle(SdrEscapeDirection::TOP   )+nAngle);
     202          87 :     if (nEscDir0&SdrEscapeDirection::RIGHT ) nEscDir1 |= EscAngleToDir(EscDirToAngle(SdrEscapeDirection::RIGHT )+nAngle);
     203          87 :     if (nEscDir0&SdrEscapeDirection::BOTTOM) nEscDir1 |= EscAngleToDir(EscDirToAngle(SdrEscapeDirection::BOTTOM)+nAngle);
     204          87 :     nEscDir=nEscDir1;
     205          87 :     if (pObj!=NULL) SetAbsolutePos(aPt,*pObj); else SetPos(aPt);
     206          87 : }
     207             : 
     208          15 : void SdrGluePoint::Mirror(const Point& rRef1, const Point& rRef2, long nAngle, const SdrObject* pObj)
     209             : {
     210          15 :     Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos());
     211          15 :     MirrorPoint(aPt,rRef1,rRef2);
     212             :     // mirror reference edge
     213          15 :     if(nAlign != (SdrAlign::HORZ_CENTER|SdrAlign::VERT_CENTER))
     214             :     {
     215          15 :         long nAW=GetAlignAngle();
     216          15 :         nAW+=2*(nAngle-nAW);
     217          15 :         SetAlignAngle(nAW);
     218             :     }
     219             :     // mirror exit directions
     220          15 :     SdrEscapeDirection nEscDir0=nEscDir;
     221          15 :     SdrEscapeDirection nEscDir1=SdrEscapeDirection::SMART;
     222          15 :     if (nEscDir0&SdrEscapeDirection::LEFT) {
     223           0 :         long nEW=EscDirToAngle(SdrEscapeDirection::LEFT);
     224           0 :         nEW+=2*(nAngle-nEW);
     225           0 :         nEscDir1|=EscAngleToDir(nEW);
     226             :     }
     227          15 :     if (nEscDir0&SdrEscapeDirection::TOP) {
     228           0 :         long nEW=EscDirToAngle(SdrEscapeDirection::TOP);
     229           0 :         nEW+=2*(nAngle-nEW);
     230           0 :         nEscDir1|=EscAngleToDir(nEW);
     231             :     }
     232          15 :     if (nEscDir0&SdrEscapeDirection::RIGHT) {
     233           0 :         long nEW=EscDirToAngle(SdrEscapeDirection::RIGHT);
     234           0 :         nEW+=2*(nAngle-nEW);
     235           0 :         nEscDir1|=EscAngleToDir(nEW);
     236             :     }
     237          15 :     if (nEscDir0&SdrEscapeDirection::BOTTOM) {
     238           0 :         long nEW=EscDirToAngle(SdrEscapeDirection::BOTTOM);
     239           0 :         nEW+=2*(nAngle-nEW);
     240           0 :         nEscDir1|=EscAngleToDir(nEW);
     241             :     }
     242          15 :     nEscDir=nEscDir1;
     243          15 :     if (pObj!=NULL) SetAbsolutePos(aPt,*pObj); else SetPos(aPt);
     244          15 : }
     245             : 
     246           0 : void SdrGluePoint::Shear(const Point& rRef, long /*nAngle*/, double tn, bool bVShear, const SdrObject* pObj)
     247             : {
     248           0 :     Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos());
     249           0 :     ShearPoint(aPt,rRef,tn,bVShear);
     250           0 :     if (pObj!=NULL) SetAbsolutePos(aPt,*pObj); else SetPos(aPt);
     251           0 : }
     252             : 
     253           0 : void SdrGluePoint::Invalidate(vcl::Window& rWin, const SdrObject* pObj) const
     254             : {
     255           0 :     bool bMapMerk=rWin.IsMapModeEnabled();
     256           0 :     Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos());
     257           0 :     aPt=rWin.LogicToPixel(aPt);
     258           0 :     rWin.EnableMapMode(false);
     259             : 
     260           0 :     Size aSiz( aGlueHalfSize );
     261           0 :     Rectangle aRect(aPt.X()-aSiz.Width(),aPt.Y()-aSiz.Height(),
     262           0 :                     aPt.X()+aSiz.Width(),aPt.Y()+aSiz.Height());
     263             : 
     264             :     // do not erase background, that causes flicker (!)
     265           0 :     rWin.Invalidate(aRect, InvalidateFlags::NoErase);
     266             : 
     267           0 :     rWin.EnableMapMode(bMapMerk);
     268           0 : }
     269             : 
     270           0 : bool SdrGluePoint::IsHit(const Point& rPnt, const OutputDevice& rOut, const SdrObject* pObj) const
     271             : {
     272           0 :     Point aPt(pObj!=NULL ? GetAbsolutePos(*pObj) : GetPos());
     273           0 :     Size aSiz=rOut.PixelToLogic(aGlueHalfSize);
     274           0 :     Rectangle aRect(aPt.X()-aSiz.Width(),aPt.Y()-aSiz.Height(),aPt.X()+aSiz.Width(),aPt.Y()+aSiz.Height());
     275           0 :     return aRect.IsInside(rPnt);
     276             : }
     277             : 
     278             : 
     279             : 
     280         280 : void SdrGluePointList::Clear()
     281             : {
     282         280 :     sal_uInt16 nCount=GetCount();
     283        1920 :     for (sal_uInt16 i=0; i<nCount; i++) {
     284        1640 :         delete GetObject(i);
     285             :     }
     286         280 :     aList.clear();
     287         280 : }
     288             : 
     289         123 : void SdrGluePointList::operator=(const SdrGluePointList& rSrcList)
     290             : {
     291         123 :     if (GetCount()!=0) Clear();
     292         123 :     sal_uInt16 nCount=rSrcList.GetCount();
     293         835 :     for (sal_uInt16 i=0; i<nCount; i++) {
     294         712 :         Insert(rSrcList[i]);
     295             :     }
     296         123 : }
     297             : 
     298             : // The ID's of the glue points always increase monotonously!
     299             : // If an ID is taken already, the new glue point gets a new ID. ID 0 is reserved.
     300        1640 : sal_uInt16 SdrGluePointList::Insert(const SdrGluePoint& rGP)
     301             : {
     302        1640 :     SdrGluePoint* pGP=new SdrGluePoint(rGP);
     303        1640 :     sal_uInt16 nId=pGP->GetId();
     304        1640 :     sal_uInt16 nCount=GetCount();
     305        1640 :     sal_uInt16 nInsPos=nCount;
     306        1640 :     sal_uInt16 nLastId=nCount!=0 ? GetObject(nCount-1)->GetId() : 0;
     307             :     DBG_ASSERT(nLastId>=nCount,"SdrGluePointList::Insert(): nLastId<nCount");
     308        1640 :     bool bHole = nLastId>nCount;
     309        1640 :     if (nId<=nLastId) {
     310         216 :         if (!bHole || nId==0) {
     311         216 :             nId=nLastId+1;
     312             :         } else {
     313           0 :             bool bBrk = false;
     314           0 :             for (sal_uInt16 nNum=0; nNum<nCount && !bBrk; nNum++) {
     315           0 :                 const SdrGluePoint* pGP2=GetObject(nNum);
     316           0 :                 sal_uInt16 nTmpId=pGP2->GetId();
     317           0 :                 if (nTmpId==nId) {
     318           0 :                     nId=nLastId+1; // already in use
     319           0 :                     bBrk = true;
     320             :                 }
     321           0 :                 if (nTmpId>nId) {
     322           0 :                     nInsPos=nNum; // insert here (sort)
     323           0 :                     bBrk = true;
     324             :                 }
     325             :             }
     326             :         }
     327         216 :         pGP->SetId(nId);
     328             :     }
     329        1640 :     aList.insert(aList.begin()+nInsPos, pGP);
     330        1640 :     return nInsPos;
     331             : }
     332             : 
     333           0 : void SdrGluePointList::Invalidate(vcl::Window& rWin, const SdrObject* pObj) const
     334             : {
     335           0 :     sal_uInt16 nCount=GetCount();
     336           0 :     for (sal_uInt16 nNum=0; nNum<nCount; nNum++) {
     337           0 :         GetObject(nNum)->Invalidate(rWin,pObj);
     338             :     }
     339           0 : }
     340             : 
     341           4 : sal_uInt16 SdrGluePointList::FindGluePoint(sal_uInt16 nId) const
     342             : {
     343             :     // TODO: Implement a better search algorithm
     344             :     // List should be sorted at all times!
     345           4 :     sal_uInt16 nCount=GetCount();
     346           4 :     sal_uInt16 nRet=SDRGLUEPOINT_NOTFOUND;
     347          16 :     for (sal_uInt16 nNum=0; nNum<nCount && nRet==SDRGLUEPOINT_NOTFOUND; nNum++) {
     348          12 :         const SdrGluePoint* pGP=GetObject(nNum);
     349          12 :         if (pGP->GetId()==nId) nRet=nNum;
     350             :     }
     351           4 :     return nRet;
     352             : }
     353             : 
     354           0 : sal_uInt16 SdrGluePointList::HitTest(const Point& rPnt, const OutputDevice& rOut, const SdrObject* pObj, bool bBack, bool bNext, sal_uInt16 nId0) const
     355             : {
     356           0 :     sal_uInt16 nCount=GetCount();
     357           0 :     sal_uInt16 nRet=SDRGLUEPOINT_NOTFOUND;
     358           0 :     sal_uInt16 nNum=bBack ? 0 : nCount;
     359           0 :     while ((bBack ? nNum<nCount : nNum>0) && nRet==SDRGLUEPOINT_NOTFOUND) {
     360           0 :         if (!bBack) nNum--;
     361           0 :         const SdrGluePoint* pGP=GetObject(nNum);
     362           0 :         if (bNext) {
     363           0 :             if (pGP->GetId()==nId0) bNext=false;
     364             :         } else {
     365           0 :             if (pGP->IsHit(rPnt,rOut,pObj)) nRet=nNum;
     366             :         }
     367           0 :         if (bBack) nNum++;
     368             :     }
     369           0 :     return nRet;
     370             : }
     371             : 
     372          36 : void SdrGluePointList::SetReallyAbsolute(bool bOn, const SdrObject& rObj)
     373             : {
     374          36 :     sal_uInt16 nCount=GetCount();
     375         240 :     for (sal_uInt16 nNum=0; nNum<nCount; nNum++) {
     376         204 :         GetObject(nNum)->SetReallyAbsolute(bOn,rObj);
     377             :     }
     378          36 : }
     379             : 
     380          15 : void SdrGluePointList::Rotate(const Point& rRef, long nAngle, double sn, double cs, const SdrObject* pObj)
     381             : {
     382          15 :     sal_uInt16 nCount=GetCount();
     383         102 :     for (sal_uInt16 nNum=0; nNum<nCount; nNum++) {
     384          87 :         GetObject(nNum)->Rotate(rRef,nAngle,sn,cs,pObj);
     385             :     }
     386          15 : }
     387             : 
     388           3 : void SdrGluePointList::Mirror(const Point& rRef1, const Point& rRef2, const SdrObject* pObj)
     389             : {
     390           3 :     Point aPt(rRef2); aPt-=rRef1;
     391           3 :     long nAngle=GetAngle(aPt);
     392           3 :     Mirror(rRef1,rRef2,nAngle,pObj);
     393           3 : }
     394             : 
     395           3 : void SdrGluePointList::Mirror(const Point& rRef1, const Point& rRef2, long nAngle, const SdrObject* pObj)
     396             : {
     397           3 :     sal_uInt16 nCount=GetCount();
     398          18 :     for (sal_uInt16 nNum=0; nNum<nCount; nNum++) {
     399          15 :         GetObject(nNum)->Mirror(rRef1,rRef2,nAngle,pObj);
     400             :     }
     401           3 : }
     402             : 
     403           0 : void SdrGluePointList::Shear(const Point& rRef, long nAngle, double tn, bool bVShear, const SdrObject* pObj)
     404             : {
     405           0 :     sal_uInt16 nCount=GetCount();
     406           0 :     for (sal_uInt16 nNum=0; nNum<nCount; nNum++) {
     407           0 :         GetObject(nNum)->Shear(rRef,nAngle,tn,bVShear,pObj);
     408             :     }
     409         435 : }
     410             : 
     411             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11