1ddde725dSArmin Le Grand /**************************************************************
2*a6c67450Smseidel  *
3ddde725dSArmin Le Grand  * Licensed to the Apache Software Foundation (ASF) under one
4ddde725dSArmin Le Grand  * or more contributor license agreements.  See the NOTICE file
5ddde725dSArmin Le Grand  * distributed with this work for additional information
6ddde725dSArmin Le Grand  * regarding copyright ownership.  The ASF licenses this file
7ddde725dSArmin Le Grand  * to you under the Apache License, Version 2.0 (the
8ddde725dSArmin Le Grand  * "License"); you may not use this file except in compliance
9ddde725dSArmin Le Grand  * with the License.  You may obtain a copy of the License at
10*a6c67450Smseidel  *
11ddde725dSArmin Le Grand  *   http://www.apache.org/licenses/LICENSE-2.0
12*a6c67450Smseidel  *
13ddde725dSArmin Le Grand  * Unless required by applicable law or agreed to in writing,
14ddde725dSArmin Le Grand  * software distributed under the License is distributed on an
15ddde725dSArmin Le Grand  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16ddde725dSArmin Le Grand  * KIND, either express or implied.  See the License for the
17ddde725dSArmin Le Grand  * specific language governing permissions and limitations
18ddde725dSArmin Le Grand  * under the License.
19*a6c67450Smseidel  *
20ddde725dSArmin Le Grand  *************************************************************/
21ddde725dSArmin Le Grand 
22*a6c67450Smseidel 
23*a6c67450Smseidel 
24ddde725dSArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove
25ddde725dSArmin Le Grand #include "precompiled_drawinglayer.hxx"
26ddde725dSArmin Le Grand 
27ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/cropprimitive2d.hxx>
28ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
29ddde725dSArmin Le Grand #include <basegfx/matrix/b2dhommatrix.hxx>
30ddde725dSArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx>
31ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
32ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolygon.hxx>
33ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolygontools.hxx>
34ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
35ddde725dSArmin Le Grand 
36ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
37ddde725dSArmin Le Grand 
38ddde725dSArmin Le Grand using namespace com::sun::star;
39ddde725dSArmin Le Grand 
40ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
41ddde725dSArmin Le Grand 
42ddde725dSArmin Le Grand namespace drawinglayer
43ddde725dSArmin Le Grand {
44ddde725dSArmin Le Grand     namespace primitive2d
45ddde725dSArmin Le Grand     {
CropPrimitive2D(const Primitive2DSequence & rChildren,const basegfx::B2DHomMatrix & rTransformation,double fCropLeft,double fCropTop,double fCropRight,double fCropBottom)46ddde725dSArmin Le Grand         CropPrimitive2D::CropPrimitive2D(
47ddde725dSArmin Le Grand             const Primitive2DSequence& rChildren,
48*a6c67450Smseidel             const basegfx::B2DHomMatrix& rTransformation,
49ddde725dSArmin Le Grand             double fCropLeft,
50ddde725dSArmin Le Grand             double fCropTop,
51ddde725dSArmin Le Grand             double fCropRight,
52ddde725dSArmin Le Grand             double fCropBottom)
53ddde725dSArmin Le Grand         :   GroupPrimitive2D(rChildren),
54ddde725dSArmin Le Grand             maTransformation(rTransformation),
55ddde725dSArmin Le Grand             mfCropLeft(fCropLeft),
56ddde725dSArmin Le Grand             mfCropTop(fCropTop),
57ddde725dSArmin Le Grand             mfCropRight(fCropRight),
58ddde725dSArmin Le Grand             mfCropBottom(fCropBottom)
59ddde725dSArmin Le Grand         {
60ddde725dSArmin Le Grand         }
61ddde725dSArmin Le Grand 
operator ==(const BasePrimitive2D & rPrimitive) const62ddde725dSArmin Le Grand         bool CropPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
63ddde725dSArmin Le Grand         {
64ddde725dSArmin Le Grand             if(GroupPrimitive2D::operator==(rPrimitive))
65ddde725dSArmin Le Grand             {
66ddde725dSArmin Le Grand                 const CropPrimitive2D& rCompare = static_cast< const CropPrimitive2D& >(rPrimitive);
67ddde725dSArmin Le Grand 
68ddde725dSArmin Le Grand                 return (getTransformation() == rCompare.getTransformation()
69ddde725dSArmin Le Grand                     && getCropLeft() == rCompare.getCropLeft()
70ddde725dSArmin Le Grand                     && getCropTop() == rCompare.getCropTop()
71ddde725dSArmin Le Grand                     && getCropRight() == rCompare.getCropRight()
72ddde725dSArmin Le Grand                     && getCropBottom() == rCompare.getCropBottom());
73ddde725dSArmin Le Grand             }
74ddde725dSArmin Le Grand 
75ddde725dSArmin Le Grand             return false;
76ddde725dSArmin Le Grand         }
77ddde725dSArmin Le Grand 
get2DDecomposition(const geometry::ViewInformation2D &) const78ddde725dSArmin Le Grand         Primitive2DSequence CropPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
79ddde725dSArmin Le Grand         {
80ddde725dSArmin Le Grand             Primitive2DSequence xRetval;
81ddde725dSArmin Le Grand 
82ddde725dSArmin Le Grand             if(getChildren().hasElements())
83ddde725dSArmin Le Grand             {
84c0d661f1SArmin Le Grand                 // get original object scale in unit coordinates (no mirroring)
85c0d661f1SArmin Le Grand                 const basegfx::B2DVector aObjectScale(basegfx::absolute(getTransformation() * basegfx::B2DVector(1.0, 1.0)));
86ddde725dSArmin Le Grand 
87c0d661f1SArmin Le Grand                 // we handle cropping, so when no width or no height, content will be empty,
88c0d661f1SArmin Le Grand                 // so only do something when we have a width and a height
89c0d661f1SArmin Le Grand                 if(!aObjectScale.equalZero())
90ddde725dSArmin Le Grand                 {
91c0d661f1SArmin Le Grand                     // calculate crop distances in unit coordinates. They are already combined with CropScaleFactor, thus
92c0d661f1SArmin Le Grand                     // are relative only to object scale
93c0d661f1SArmin Le Grand                     const double fBackScaleX(basegfx::fTools::equalZero(aObjectScale.getX()) ? 1.0 : 1.0 / fabs(aObjectScale.getX()));
94c0d661f1SArmin Le Grand                     const double fBackScaleY(basegfx::fTools::equalZero(aObjectScale.getY()) ? 1.0 : 1.0 / fabs(aObjectScale.getY()));
95c0d661f1SArmin Le Grand                     const double fLeft(getCropLeft() * fBackScaleX);
96c0d661f1SArmin Le Grand                     const double fTop(getCropTop() * fBackScaleY);
97c0d661f1SArmin Le Grand                     const double fRight(getCropRight() * fBackScaleX);
98c0d661f1SArmin Le Grand                     const double fBottom(getCropBottom() * fBackScaleY);
99c0d661f1SArmin Le Grand 
100*a6c67450Smseidel                     // calculate new unit range for comparisons; the original range is the unit range
101c0d661f1SArmin Le Grand                     const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
102c0d661f1SArmin Le Grand                     const basegfx::B2DRange aNewRange(
103c0d661f1SArmin Le Grand                         -fLeft,
104c0d661f1SArmin Le Grand                         -fTop,
105c0d661f1SArmin Le Grand                         1.0 + fRight,
106c0d661f1SArmin Le Grand                         1.0 + fBottom);
107c0d661f1SArmin Le Grand 
108c0d661f1SArmin Le Grand                     // if we have no overlap the crop has removed everything, so we do only
109c0d661f1SArmin Le Grand                     // have to create content if this is not the case
110c0d661f1SArmin Le Grand                     if(aNewRange.overlaps(aUnitRange))
111ddde725dSArmin Le Grand                     {
112c0d661f1SArmin Le Grand                         // create new transform; first take out old transform to get
113c0d661f1SArmin Le Grand                         // to unit coordinates by inverting. Inverting should be flawless
114*a6c67450Smseidel                         // since we already checked that object size is not zero in X or Y
115c0d661f1SArmin Le Grand                         basegfx::B2DHomMatrix aNewTransform(getTransformation());
116c0d661f1SArmin Le Grand 
117c0d661f1SArmin Le Grand                         aNewTransform.invert();
118c0d661f1SArmin Le Grand 
119c0d661f1SArmin Le Grand                         // apply crop enlargement in unit coordinates
120c0d661f1SArmin Le Grand                         aNewTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
121c0d661f1SArmin Le Grand                             aNewRange.getRange(),
122c0d661f1SArmin Le Grand                             aNewRange.getMinimum()) * aNewTransform;
123c0d661f1SArmin Le Grand 
124c0d661f1SArmin Le Grand                         // apply original transformation. Since we have manipulated the crop
125c0d661f1SArmin Le Grand                         // in unit coordinates we do not need to care about mirroring or
126c0d661f1SArmin Le Grand                         // a corrected point for eventual shear or rotation, this all comes for
127c0d661f1SArmin Le Grand                         // free
128c0d661f1SArmin Le Grand                         aNewTransform = getTransformation() * aNewTransform;
129c0d661f1SArmin Le Grand 
130c0d661f1SArmin Le Grand                         // prepare TransformPrimitive2D with xPrimitive
131c0d661f1SArmin Le Grand                         const Primitive2DReference xTransformPrimitive(
132c0d661f1SArmin Le Grand                             new TransformPrimitive2D(
133*a6c67450Smseidel                                 aNewTransform,
134c0d661f1SArmin Le Grand                                 getChildren()));
135c0d661f1SArmin Le Grand 
136c0d661f1SArmin Le Grand                         if(aUnitRange.isInside(aNewRange))
137c0d661f1SArmin Le Grand                         {
138c0d661f1SArmin Le Grand                             // the new range is completely inside the old range (unit range),
139c0d661f1SArmin Le Grand                             // so no masking is needed
140c0d661f1SArmin Le Grand                             xRetval = Primitive2DSequence(&xTransformPrimitive, 1);
141c0d661f1SArmin Le Grand                         }
142c0d661f1SArmin Le Grand                         else
143c0d661f1SArmin Le Grand                         {
144c0d661f1SArmin Le Grand                             // mask with original object's bounds
145c0d661f1SArmin Le Grand                             basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon());
146c0d661f1SArmin Le Grand                             aMaskPolyPolygon.transform(getTransformation());
147c0d661f1SArmin Le Grand 
148c0d661f1SArmin Le Grand                             // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
149c0d661f1SArmin Le Grand                             const Primitive2DReference xMask(
150c0d661f1SArmin Le Grand                                 new MaskPrimitive2D(
151*a6c67450Smseidel                                     aMaskPolyPolygon,
152c0d661f1SArmin Le Grand                                     Primitive2DSequence(&xTransformPrimitive, 1)));
153c0d661f1SArmin Le Grand 
154c0d661f1SArmin Le Grand                             xRetval = Primitive2DSequence(&xMask, 1);
155c0d661f1SArmin Le Grand                         }
156ddde725dSArmin Le Grand                     }
157ddde725dSArmin Le Grand                 }
158ddde725dSArmin Le Grand             }
159ddde725dSArmin Le Grand 
160ddde725dSArmin Le Grand             return xRetval;
161ddde725dSArmin Le Grand         }
162ddde725dSArmin Le Grand 
163ddde725dSArmin Le Grand         // provide unique ID
164ddde725dSArmin Le Grand         ImplPrimitrive2DIDBlock(CropPrimitive2D, PRIMITIVE2D_ID_CROPPRIMITIVE2D)
165ddde725dSArmin Le Grand 
166ddde725dSArmin Le Grand     } // end of namespace primitive2d
167ddde725dSArmin Le Grand } // end of namespace drawinglayer
168ddde725dSArmin Le Grand 
169*a6c67450Smseidel /* vim: set noet sw=4 ts=4: */
170