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_svx.hxx"
30 #include <svx/e3dsceneupdater.hxx>
31 #include <drawinglayer/geometry/viewinformation3d.hxx>
32 #include <svx/obj3d.hxx>
33 #include <svx/scene3d.hxx>
34 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
35 
36 //////////////////////////////////////////////////////////////////////////////
37 
38 E3DModifySceneSnapRectUpdater::E3DModifySceneSnapRectUpdater(const SdrObject* pObject)
39 :	mpScene(0),
40 	mpViewInformation3D(0)
41 {
42 	// Secure old 3D transformation stack before modification
43     if(pObject)
44     {
45         const E3dObject* pE3dObject = dynamic_cast< const E3dObject* >(pObject);
46 
47         if(pE3dObject)
48         {
49             mpScene = pE3dObject->GetScene();
50 
51             if(mpScene && mpScene->GetScene() == mpScene)
52 	        {
53 		        // if there is a scene and it's the outmost scene, get current 3D range
54 		        const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(mpScene->GetViewContact());
55 		        const basegfx::B3DRange aAllContentRange(rVCScene.getAllContentRange3D());
56 
57 		        if(aAllContentRange.isEmpty())
58 		        {
59 			        // no content, nothing to do
60 			        mpScene = 0;
61 		        }
62 		        else
63 		        {
64 			        // secure current 3D transformation stack
65 			        mpViewInformation3D = new drawinglayer::geometry::ViewInformation3D(rVCScene.getViewInformation3D(aAllContentRange));
66 		        }
67 	        }
68         }
69     }
70 }
71 
72 E3DModifySceneSnapRectUpdater::~E3DModifySceneSnapRectUpdater()
73 {
74 	if(mpScene && mpViewInformation3D)
75 	{
76 		// after changing parts of the scene, use the secured last 3d transformation stack and the new content
77 		// range to calculate a new, eventually expanded or shrunk, 2D geometry for the scene and apply it.
78 		// Get new content range
79 		const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(mpScene->GetViewContact());
80 		basegfx::B3DRange aAllContentRange(rVCScene.getAllContentRange3D());
81 
82         // only change when there is still content; else let scene stay at old SnapRect
83         if(!aAllContentRange.isEmpty())
84         {
85 		    // check if object transform of scene has changed
86 		    if(mpViewInformation3D->getObjectTransformation() != mpScene->GetTransform())
87 		    {
88 			    // If Yes, it needs to be updated since it's - for historical reasons -
89 			    // part of the basic 3d transformation stack of the scene
90 			    drawinglayer::geometry::ViewInformation3D* pNew = new drawinglayer::geometry::ViewInformation3D(
91 				    mpScene->GetTransform(), // replace object transformation with new local transform
92 				    mpViewInformation3D->getOrientation(),
93 				    mpViewInformation3D->getProjection(),
94 				    mpViewInformation3D->getDeviceToView(),
95 				    mpViewInformation3D->getViewTime(),
96 				    mpViewInformation3D->getExtendedInformationSequence());
97                 delete mpViewInformation3D;
98                 mpViewInformation3D = pNew;
99             }
100 
101 		    // transform content range to scene-relative coordinates using old 3d transformation stack
102 		    aAllContentRange.transform(mpViewInformation3D->getObjectToView());
103 
104 		    // build 2d relative content range
105 		    basegfx::B2DRange aSnapRange(
106 			    aAllContentRange.getMinX(), aAllContentRange.getMinY(),
107 			    aAllContentRange.getMaxX(), aAllContentRange.getMaxY());
108 
109 		    // transform to 2D world coordiantes using scene's 2D transformation
110 		    aSnapRange.transform(rVCScene.getObjectTransformation());
111 
112 		    // snap to (old) integer
113 		    const Rectangle aNewSnapRect(
114 			    sal_Int32(floor(aSnapRange.getMinX())), sal_Int32(floor(aSnapRange.getMinY())),
115 			    sal_Int32(ceil(aSnapRange.getMaxX())), sal_Int32(ceil(aSnapRange.getMaxY())));
116 
117 		    // set as new SnapRect and invalidate bound volume
118             if(mpScene->GetSnapRect() != aNewSnapRect)
119             {
120     	        mpScene->SetSnapRect(aNewSnapRect);
121 	    	    mpScene->InvalidateBoundVolume();
122             }
123         }
124 	}
125 
126     delete mpViewInformation3D;
127 }
128 
129 //////////////////////////////////////////////////////////////////////////////
130 // eof
131