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