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