summaryrefslogtreecommitdiff
path: root/drawinglayer
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2014-01-23 02:12:41 +0000
committerCaolán McNamara <caolanm@redhat.com>2014-01-23 14:10:59 +0000
commitfb0cce507f9c83485da56847529d2fae4d53d9a3 (patch)
treededdb4d09bab5e1a3d3f41f6ecaee97444f47f8b /drawinglayer
parent55d2f55ddfb50f8e111194d8d2fd29e98de5e861 (diff)
Resolves: #i123950# unified and redefined CropPrimitive2D::get2DDecomposition
(cherry picked from commit 08d42c4da0a3f6dc105080102c1b1de4bce987a1) Change-Id: I2d5f52de8e9fa595012a953affbaba9d54f4f2a9
Diffstat (limited to 'drawinglayer')
-rw-r--r--drawinglayer/source/primitive2d/cropprimitive2d.cxx172
1 files changed, 69 insertions, 103 deletions
diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx
index 042710c516e3..2ea6a1a3901c 100644
--- a/drawinglayer/source/primitive2d/cropprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx
@@ -74,112 +74,78 @@ namespace drawinglayer
if(getChildren().hasElements())
{
- // decompose to have current translate and scale
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
-
- getTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
-
- // detect 180 degree rotation, this is the same as mirrored in X and Y,
- // thus change to mirroring. Prefer mirroring here. Use the equal call
- // with getSmallValue here, the original which uses rtl::math::approxEqual
- // is too correct here. Maybe this changes with enhanced precision in aw080
- // to the better so that this can be reduced to the more precise call again
- if(basegfx::fTools::equal(fabs(fRotate), F_PI, 0.000000001))
- {
- aScale.setX(aScale.getX() * -1.0);
- aScale.setY(aScale.getY() * -1.0);
- fRotate = 0.0;
- }
-
- // create target translate and scale
- const bool bMirroredX(aScale.getX() < 0.0);
- const bool bMirroredY(aScale.getY() < 0.0);
- basegfx::B2DVector aTargetScale(aScale);
- basegfx::B2DVector aTargetTranslate(aTranslate);
-
- if(bMirroredX)
- {
- aTargetTranslate.setX(aTargetTranslate.getX() + getCropRight());
- aTargetScale.setX(aTargetScale.getX() - getCropLeft() - getCropRight());
- }
- else
- {
- aTargetTranslate.setX(aTargetTranslate.getX() - getCropLeft());
- aTargetScale.setX(aTargetScale.getX() + getCropRight() + getCropLeft());
- }
-
- if(bMirroredY)
- {
- aTargetTranslate.setY(aTargetTranslate.getY() + getCropBottom());
- aTargetScale.setY(aTargetScale.getY() - getCropTop() - getCropBottom());
- }
- else
- {
- aTargetTranslate.setY(aTargetTranslate.getY() - getCropTop());
- aTargetScale.setY(aTargetScale.getY() + getCropBottom() + getCropTop());
- }
-
- // create ranges to make comparisons
- const basegfx::B2DRange aCurrent(
- aTranslate.getX(), aTranslate.getY(),
- aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
- const basegfx::B2DRange aCropped(
- aTargetTranslate.getX(), aTargetTranslate.getY(),
- aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY());
+ // get original object scale in unit coordinates (no mirroring)
+ const basegfx::B2DVector aObjectScale(basegfx::absolute(getTransformation() * basegfx::B2DVector(1.0, 1.0)));
- if(aCropped.isEmpty())
+ // we handle cropping, so when no width or no height, content will be empty,
+ // so only do something when we have a width and a height
+ if(!aObjectScale.equalZero())
{
- // nothing to return since cropped content is completely empty
- }
- else if(aCurrent.equal(aCropped))
- {
- // no crop, just use content
- xRetval = getChildren();
- }
- else
- {
- // build new combined content transformation
- basegfx::B2DHomMatrix aNewObjectTransform(getTransformation());
-
- // remove content transform by inverting
- aNewObjectTransform.invert();
-
- // add target values and original shear/rotate
- aNewObjectTransform = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
- aTargetScale.getX(),
- aTargetScale.getY(),
- fShearX,
- fRotate,
- aTargetTranslate.getX(),
- aTargetTranslate.getY())
- * aNewObjectTransform;
-
- // prepare TransformPrimitive2D with xPrimitive
- const Primitive2DReference xTransformPrimitive(
- new TransformPrimitive2D(
- aNewObjectTransform,
- getChildren()));
-
- if(aCurrent.isInside(aCropped))
- {
- // crop just shrunk so that its inside content,
- // no need to use a mask since not really cropped.
- xRetval = Primitive2DSequence(&xTransformPrimitive, 1);
- }
- else
+ // calculate crop distances in unit coordinates. They are already combined with CropScaleFactor, thus
+ // are relative only to object scale
+ const double fBackScaleX(basegfx::fTools::equalZero(aObjectScale.getX()) ? 1.0 : 1.0 / fabs(aObjectScale.getX()));
+ const double fBackScaleY(basegfx::fTools::equalZero(aObjectScale.getY()) ? 1.0 : 1.0 / fabs(aObjectScale.getY()));
+ const double fLeft(getCropLeft() * fBackScaleX);
+ const double fTop(getCropTop() * fBackScaleY);
+ const double fRight(getCropRight() * fBackScaleX);
+ const double fBottom(getCropBottom() * fBackScaleY);
+
+ // calc new unit range for comparisons; the original range is the unit range
+ const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
+ const basegfx::B2DRange aNewRange(
+ -fLeft,
+ -fTop,
+ 1.0 + fRight,
+ 1.0 + fBottom);
+
+ // if we have no overlap the crop has removed everything, so we do only
+ // have to create content if this is not the case
+ if(aNewRange.overlaps(aUnitRange))
{
- // mask with original object's bounds
- basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon());
- aMaskPolyPolygon.transform(getTransformation());
-
- // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
- const Primitive2DReference xMask(
- new MaskPrimitive2D(
- aMaskPolyPolygon,
- Primitive2DSequence(&xTransformPrimitive, 1)));
-
- xRetval = Primitive2DSequence(&xMask, 1);
+ // create new transform; first take out old transform to get
+ // to unit coordinates by inverting. Inverting should be flawless
+ // since we already cheched that object size is not zero in X or Y
+ basegfx::B2DHomMatrix aNewTransform(getTransformation());
+
+ aNewTransform.invert();
+
+ // apply crop enlargement in unit coordinates
+ aNewTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aNewRange.getRange(),
+ aNewRange.getMinimum()) * aNewTransform;
+
+ // apply original transformation. Since we have manipulated the crop
+ // in unit coordinates we do not need to care about mirroring or
+ // a corrected point for eventual shear or rotation, this all comes for
+ // free
+ aNewTransform = getTransformation() * aNewTransform;
+
+ // prepare TransformPrimitive2D with xPrimitive
+ const Primitive2DReference xTransformPrimitive(
+ new TransformPrimitive2D(
+ aNewTransform,
+ getChildren()));
+
+ if(aUnitRange.isInside(aNewRange))
+ {
+ // the new range is completely inside the old range (unit range),
+ // so no masking is needed
+ xRetval = Primitive2DSequence(&xTransformPrimitive, 1);
+ }
+ else
+ {
+ // mask with original object's bounds
+ basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon());
+ aMaskPolyPolygon.transform(getTransformation());
+
+ // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
+ const Primitive2DReference xMask(
+ new MaskPrimitive2D(
+ aMaskPolyPolygon,
+ Primitive2DSequence(&xTransformPrimitive, 1)));
+
+ xRetval = Primitive2DSequence(&xMask, 1);
+ }
}
}
}