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

Generated by: LCOV version 1.10