Resolves: #i123950# unified and redefined CropPrimitive2D::get2DDecomposition

(cherry picked from commit 08d42c4da0a3f6dc105080102c1b1de4bce987a1)

Change-Id: I2d5f52de8e9fa595012a953affbaba9d54f4f2a9
This commit is contained in:
Armin Le Grand
2014-01-23 02:12:41 +00:00
committed by Caolán McNamara
parent 55d2f55ddf
commit fb0cce507f
3 changed files with 70 additions and 105 deletions

View File

@@ -74,97 +74,62 @@ namespace drawinglayer
if(getChildren().hasElements()) if(getChildren().hasElements())
{ {
// decompose to have current translate and scale // get original object scale in unit coordinates (no mirroring)
basegfx::B2DVector aScale, aTranslate; const basegfx::B2DVector aObjectScale(basegfx::absolute(getTransformation() * basegfx::B2DVector(1.0, 1.0)));
double fRotate, fShearX;
getTransformation().decompose(aScale, aTranslate, fRotate, fShearX); // 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
// detect 180 degree rotation, this is the same as mirrored in X and Y, if(!aObjectScale.equalZero())
// 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); // calculate crop distances in unit coordinates. They are already combined with CropScaleFactor, thus
aScale.setY(aScale.getY() * -1.0); // are relative only to object scale
fRotate = 0.0; 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);
// create target translate and scale // calc new unit range for comparisons; the original range is the unit range
const bool bMirroredX(aScale.getX() < 0.0); const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
const bool bMirroredY(aScale.getY() < 0.0); const basegfx::B2DRange aNewRange(
basegfx::B2DVector aTargetScale(aScale); -fLeft,
basegfx::B2DVector aTargetTranslate(aTranslate); -fTop,
1.0 + fRight,
1.0 + fBottom);
if(bMirroredX) // 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))
{ {
aTargetTranslate.setX(aTargetTranslate.getX() + getCropRight()); // create new transform; first take out old transform to get
aTargetScale.setX(aTargetScale.getX() - getCropLeft() - getCropRight()); // to unit coordinates by inverting. Inverting should be flawless
} // since we already cheched that object size is not zero in X or Y
else basegfx::B2DHomMatrix aNewTransform(getTransformation());
{
aTargetTranslate.setX(aTargetTranslate.getX() - getCropLeft());
aTargetScale.setX(aTargetScale.getX() + getCropRight() + getCropLeft());
}
if(bMirroredY) aNewTransform.invert();
{
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 // apply crop enlargement in unit coordinates
const basegfx::B2DRange aCurrent( aNewTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
aTranslate.getX(), aTranslate.getY(), aNewRange.getRange(),
aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); aNewRange.getMinimum()) * aNewTransform;
const basegfx::B2DRange aCropped(
aTargetTranslate.getX(), aTargetTranslate.getY(),
aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY());
if(aCropped.isEmpty()) // apply original transformation. Since we have manipulated the crop
{ // in unit coordinates we do not need to care about mirroring or
// nothing to return since cropped content is completely empty // a corrected point for eventual shear or rotation, this all comes for
} // free
else if(aCurrent.equal(aCropped)) aNewTransform = getTransformation() * aNewTransform;
{
// 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 // prepare TransformPrimitive2D with xPrimitive
const Primitive2DReference xTransformPrimitive( const Primitive2DReference xTransformPrimitive(
new TransformPrimitive2D( new TransformPrimitive2D(
aNewObjectTransform, aNewTransform,
getChildren())); getChildren()));
if(aCurrent.isInside(aCropped)) if(aUnitRange.isInside(aNewRange))
{ {
// crop just shrunk so that its inside content, // the new range is completely inside the old range (unit range),
// no need to use a mask since not really cropped. // so no masking is needed
xRetval = Primitive2DSequence(&xTransformPrimitive, 1); xRetval = Primitive2DSequence(&xTransformPrimitive, 1);
} }
else else
@@ -183,6 +148,7 @@ namespace drawinglayer
} }
} }
} }
}
return xRetval; return xRetval;
} }

View File

@@ -42,8 +42,7 @@ namespace sdr
// helpers for constructing various primitive visualisations in various states // helpers for constructing various primitive visualisations in various states
drawinglayer::primitive2d::Primitive2DSequence createVIP2DSForPresObj( drawinglayer::primitive2d::Primitive2DSequence createVIP2DSForPresObj(
const basegfx::B2DHomMatrix& rObjectMatrix, const basegfx::B2DHomMatrix& rObjectMatrix,
const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute, const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute) const;
const GraphicAttr& rLocalGrafInfo) const;
drawinglayer::primitive2d::Primitive2DSequence createVIP2DSForDraft( drawinglayer::primitive2d::Primitive2DSequence createVIP2DSForDraft(
const basegfx::B2DHomMatrix& rObjectMatrix, const basegfx::B2DHomMatrix& rObjectMatrix,
const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute) const; const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute) const;

View File

@@ -83,8 +83,7 @@ namespace sdr
drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createVIP2DSForPresObj( drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createVIP2DSForPresObj(
const basegfx::B2DHomMatrix& rObjectMatrix, const basegfx::B2DHomMatrix& rObjectMatrix,
const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute, const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute) const
const GraphicAttr& rLocalGrafInfo) const
{ {
drawinglayer::primitive2d::Primitive2DSequence xRetval; drawinglayer::primitive2d::Primitive2DSequence xRetval;
GraphicObject aEmptyGraphicObject; GraphicObject aEmptyGraphicObject;
@@ -133,11 +132,12 @@ namespace sdr
* aSmallerMatrix; * aSmallerMatrix;
const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false); const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false);
const GraphicAttr aLocalGrafInfo;
const drawinglayer::primitive2d::Primitive2DReference xReferenceB(new drawinglayer::primitive2d::SdrGrafPrimitive2D( const drawinglayer::primitive2d::Primitive2DReference xReferenceB(new drawinglayer::primitive2d::SdrGrafPrimitive2D(
aSmallerMatrix, aSmallerMatrix,
drawinglayer::attribute::SdrLineFillShadowTextAttribute(), drawinglayer::attribute::SdrLineFillShadowTextAttribute(),
rGraphicObject, rGraphicObject,
rLocalGrafInfo)); aLocalGrafInfo));
drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xReferenceB); drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xReferenceB);
} }
@@ -373,7 +373,7 @@ namespace sdr
{ {
// it's an EmptyPresObj, create the SdrGrafPrimitive2D without content and another scaled one // it's an EmptyPresObj, create the SdrGrafPrimitive2D without content and another scaled one
// with the content which is the placeholder graphic // with the content which is the placeholder graphic
xRetval = createVIP2DSForPresObj(aObjectMatrix, aAttribute, aLocalGrafInfo); xRetval = createVIP2DSForPresObj(aObjectMatrix, aAttribute);
} }
else if(visualisationUsesDraft()) else if(visualisationUsesDraft())
{ {