cropprimitive2d.cxx (2376739d) | cropprimitive2d.cxx (c0d661f1) |
---|---|
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 --- 65 unchanged lines hidden (view full) --- 74 } 75 76 Primitive2DSequence CropPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 77 { 78 Primitive2DSequence xRetval; 79 80 if(getChildren().hasElements()) 81 { | 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 --- 65 unchanged lines hidden (view full) --- 74 } 75 76 Primitive2DSequence CropPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 77 { 78 Primitive2DSequence xRetval; 79 80 if(getChildren().hasElements()) 81 { |
82 // decompose to have current translate and scale 83 basegfx::B2DVector aScale, aTranslate; 84 double fRotate, fShearX; | 82 // get original object scale in unit coordinates (no mirroring) 83 const basegfx::B2DVector aObjectScale(basegfx::absolute(getTransformation() * basegfx::B2DVector(1.0, 1.0))); |
85 | 84 |
86 getTransformation().decompose(aScale, aTranslate, fRotate, fShearX); 87 88 // detect 180 degree rotation, this is the same as mirrored in X and Y, 89 // thus change to mirroring. Prefer mirroring here. Use the equal call 90 // with getSmallValue here, the original which uses rtl::math::approxEqual 91 // is too correct here. Maybe this changes with enhanced precision in aw080 92 // to the better so that this can be reduced to the more precise call again 93 if(basegfx::fTools::equal(fabs(fRotate), F_PI, 0.000000001)) | 85 // we handle cropping, so when no width or no height, content will be empty, 86 // so only do something when we have a width and a height 87 if(!aObjectScale.equalZero()) |
94 { | 88 { |
95 aScale.setX(aScale.getX() * -1.0); 96 aScale.setY(aScale.getY() * -1.0); 97 fRotate = 0.0; 98 } | 89 // calculate crop distances in unit coordinates. They are already combined with CropScaleFactor, thus 90 // are relative only to object scale 91 const double fBackScaleX(basegfx::fTools::equalZero(aObjectScale.getX()) ? 1.0 : 1.0 / fabs(aObjectScale.getX())); 92 const double fBackScaleY(basegfx::fTools::equalZero(aObjectScale.getY()) ? 1.0 : 1.0 / fabs(aObjectScale.getY())); 93 const double fLeft(getCropLeft() * fBackScaleX); 94 const double fTop(getCropTop() * fBackScaleY); 95 const double fRight(getCropRight() * fBackScaleX); 96 const double fBottom(getCropBottom() * fBackScaleY); |
99 | 97 |
100 // create target translate and scale 101 const bool bMirroredX(aScale.getX() < 0.0); 102 const bool bMirroredY(aScale.getY() < 0.0); 103 basegfx::B2DVector aTargetScale(aScale); 104 basegfx::B2DVector aTargetTranslate(aTranslate); | 98 // calc new unit range for comparisons; the original range is the unit range 99 const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); 100 const basegfx::B2DRange aNewRange( 101 -fLeft, 102 -fTop, 103 1.0 + fRight, 104 1.0 + fBottom); |
105 | 105 |
106 if(bMirroredX) 107 { 108 aTargetTranslate.setX(aTargetTranslate.getX() + getCropRight()); 109 aTargetScale.setX(aTargetScale.getX() - getCropLeft() - getCropRight()); 110 } 111 else 112 { 113 aTargetTranslate.setX(aTargetTranslate.getX() - getCropLeft()); 114 aTargetScale.setX(aTargetScale.getX() + getCropRight() + getCropLeft()); 115 } | 106 // if we have no overlap the crop has removed everything, so we do only 107 // have to create content if this is not the case 108 if(aNewRange.overlaps(aUnitRange)) 109 { 110 // create new transform; first take out old transform to get 111 // to unit coordinates by inverting. Inverting should be flawless 112 // since we already cheched that object size is not zero in X or Y 113 basegfx::B2DHomMatrix aNewTransform(getTransformation()); |
116 | 114 |
117 if(bMirroredY) 118 { 119 aTargetTranslate.setY(aTargetTranslate.getY() + getCropBottom()); 120 aTargetScale.setY(aTargetScale.getY() - getCropTop() - getCropBottom()); 121 } 122 else 123 { 124 aTargetTranslate.setY(aTargetTranslate.getY() - getCropTop()); 125 aTargetScale.setY(aTargetScale.getY() + getCropBottom() + getCropTop()); 126 } | 115 aNewTransform.invert(); |
127 | 116 |
128 // create ranges to make comparisons 129 const basegfx::B2DRange aCurrent( 130 aTranslate.getX(), aTranslate.getY(), 131 aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); 132 const basegfx::B2DRange aCropped( 133 aTargetTranslate.getX(), aTargetTranslate.getY(), 134 aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY()); | 117 // apply crop enlargement in unit coordinates 118 aNewTransform = basegfx::tools::createScaleTranslateB2DHomMatrix( 119 aNewRange.getRange(), 120 aNewRange.getMinimum()) * aNewTransform; |
135 | 121 |
136 if(aCropped.isEmpty()) 137 { 138 // nothing to return since cropped content is completely empty 139 } 140 else if(aCurrent.equal(aCropped)) 141 { 142 // no crop, just use content 143 xRetval = getChildren(); 144 } 145 else 146 { 147 // build new combined content transformation 148 basegfx::B2DHomMatrix aNewObjectTransform(getTransformation()); | 122 // apply original transformation. Since we have manipulated the crop 123 // in unit coordinates we do not need to care about mirroring or 124 // a corrected point for eventual shear or rotation, this all comes for 125 // free 126 aNewTransform = getTransformation() * aNewTransform; |
149 | 127 |
150 // remove content transform by inverting 151 aNewObjectTransform.invert(); | 128 // prepare TransformPrimitive2D with xPrimitive 129 const Primitive2DReference xTransformPrimitive( 130 new TransformPrimitive2D( 131 aNewTransform, 132 getChildren())); |
152 | 133 |
153 // add target values and original shear/rotate 154 aNewObjectTransform = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( 155 aTargetScale.getX(), 156 aTargetScale.getY(), 157 fShearX, 158 fRotate, 159 aTargetTranslate.getX(), 160 aTargetTranslate.getY()) 161 * aNewObjectTransform; | 134 if(aUnitRange.isInside(aNewRange)) 135 { 136 // the new range is completely inside the old range (unit range), 137 // so no masking is needed 138 xRetval = Primitive2DSequence(&xTransformPrimitive, 1); 139 } 140 else 141 { 142 // mask with original object's bounds 143 basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon()); 144 aMaskPolyPolygon.transform(getTransformation()); |
162 | 145 |
163 // prepare TransformPrimitive2D with xPrimitive 164 const Primitive2DReference xTransformPrimitive( 165 new TransformPrimitive2D( 166 aNewObjectTransform, 167 getChildren())); | 146 // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector 147 const Primitive2DReference xMask( 148 new MaskPrimitive2D( 149 aMaskPolyPolygon, 150 Primitive2DSequence(&xTransformPrimitive, 1))); |
168 | 151 |
169 if(aCurrent.isInside(aCropped)) 170 { 171 // crop just shrunk so that its inside content, 172 // no need to use a mask since not really cropped. 173 xRetval = Primitive2DSequence(&xTransformPrimitive, 1); | 152 xRetval = Primitive2DSequence(&xMask, 1); 153 } |
174 } | 154 } |
175 else 176 { 177 // mask with original object's bounds 178 basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon()); 179 aMaskPolyPolygon.transform(getTransformation()); 180 181 // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector 182 const Primitive2DReference xMask( 183 new MaskPrimitive2D( 184 aMaskPolyPolygon, 185 Primitive2DSequence(&xTransformPrimitive, 1))); 186 187 xRetval = Primitive2DSequence(&xMask, 1); 188 } | |
189 } 190 } 191 192 return xRetval; 193 } 194 195 // provide unique ID 196 ImplPrimitrive2DIDBlock(CropPrimitive2D, PRIMITIVE2D_ID_CROPPRIMITIVE2D) 197 198 } // end of namespace primitive2d 199} // end of namespace drawinglayer 200 201////////////////////////////////////////////////////////////////////////////// 202// eof | 155 } 156 } 157 158 return xRetval; 159 } 160 161 // provide unique ID 162 ImplPrimitrive2DIDBlock(CropPrimitive2D, PRIMITIVE2D_ID_CROPPRIMITIVE2D) 163 164 } // end of namespace primitive2d 165} // end of namespace drawinglayer 166 167////////////////////////////////////////////////////////////////////////////// 168// eof |