Resolves: #i123950# unified and redefined CropPrimitive2D::get2DDecomposition
(cherry picked from commit 08d42c4da0a3f6dc105080102c1b1de4bce987a1) Change-Id: I2d5f52de8e9fa595012a953affbaba9d54f4f2a9
This commit is contained in:
parent
55d2f55ddf
commit
fb0cce507f
@ -74,112 +74,78 @@ 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
|
||||||
aTargetTranslate.setX(aTargetTranslate.getX() + getCropRight());
|
if(aNewRange.overlaps(aUnitRange))
|
||||||
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());
|
|
||||||
|
|
||||||
if(aCropped.isEmpty())
|
|
||||||
{
|
|
||||||
// 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,
|
// create new transform; first take out old transform to get
|
||||||
// no need to use a mask since not really cropped.
|
// to unit coordinates by inverting. Inverting should be flawless
|
||||||
xRetval = Primitive2DSequence(&xTransformPrimitive, 1);
|
// since we already cheched that object size is not zero in X or Y
|
||||||
}
|
basegfx::B2DHomMatrix aNewTransform(getTransformation());
|
||||||
else
|
|
||||||
{
|
|
||||||
// mask with original object's bounds
|
|
||||||
basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon());
|
|
||||||
aMaskPolyPolygon.transform(getTransformation());
|
|
||||||
|
|
||||||
// create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
|
aNewTransform.invert();
|
||||||
const Primitive2DReference xMask(
|
|
||||||
new MaskPrimitive2D(
|
|
||||||
aMaskPolyPolygon,
|
|
||||||
Primitive2DSequence(&xTransformPrimitive, 1)));
|
|
||||||
|
|
||||||
xRetval = Primitive2DSequence(&xMask, 1);
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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())
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user