diff options
Diffstat (limited to 'svx/source/sdr/contact')
-rw-r--r-- | svx/source/sdr/contact/viewcontactofe3dpolygon.cxx | 17 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewcontactofgraphic.cxx | 335 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewcontactofsdrole2obj.cxx | 97 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewcontactofsdrpathobj.cxx | 119 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewcontactofsdrrectobj.cxx | 10 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewobjectcontactofgraphic.cxx | 46 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewobjectcontactofpageobj.cxx | 3 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewobjectcontactofsdrole2obj.cxx | 240 | ||||
-rw-r--r-- | svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx | 593 |
9 files changed, 872 insertions, 588 deletions
diff --git a/svx/source/sdr/contact/viewcontactofe3dpolygon.cxx b/svx/source/sdr/contact/viewcontactofe3dpolygon.cxx index 851ee1f3da58..9ae265d29362 100644 --- a/svx/source/sdr/contact/viewcontactofe3dpolygon.cxx +++ b/svx/source/sdr/contact/viewcontactofe3dpolygon.cxx @@ -75,8 +75,8 @@ namespace sdr basegfx::B3DPolyPolygon aPolyPolygon3D(GetE3dPolygonObj().GetPolyPolygon3D()); const basegfx::B3DPolyPolygon aPolyNormals3D(GetE3dPolygonObj().GetPolyNormals3D()); const basegfx::B2DPolyPolygon aPolyTexture2D(GetE3dPolygonObj().GetPolyTexture2D()); - const bool bNormals(aPolyNormals3D.count()); - const bool bTexture(aPolyTexture2D.count()); + const bool bNormals(aPolyNormals3D.count() && aPolyNormals3D.count() == aPolyPolygon3D.count());
+ const bool bTexture(aPolyTexture2D.count() && aPolyTexture2D.count() == aPolyPolygon3D.count());
if(bNormals || bTexture) { @@ -100,12 +100,19 @@ namespace sdr { if(bNormals) { - aCandidate3D.setNormal(b, aNormals3D.getB3DPoint(b)); + sal_uInt32 nNormalCount = aNormals3D.count(); + if( b < nNormalCount ) + aCandidate3D.setNormal(b, aNormals3D.getB3DPoint(b)); + else if( nNormalCount > 0 ) + aCandidate3D.setNormal(b, aNormals3D.getB3DPoint(0)); } - if(bTexture) { - aCandidate3D.setTextureCoordinate(b, aTexture2D.getB2DPoint(b)); + sal_uInt32 nTextureCount = aTexture2D.count(); + if( b < nTextureCount ) + aCandidate3D.setTextureCoordinate(b, aTexture2D.getB2DPoint(b)); + else if( nTextureCount > 0 ) + aCandidate3D.setTextureCoordinate(b, aTexture2D.getB2DPoint(0)); } } diff --git a/svx/source/sdr/contact/viewcontactofgraphic.cxx b/svx/source/sdr/contact/viewcontactofgraphic.cxx index aae01c5d24ff..b083a1014299 100644 --- a/svx/source/sdr/contact/viewcontactofgraphic.cxx +++ b/svx/source/sdr/contact/viewcontactofgraphic.cxx @@ -53,6 +53,18 @@ #include <svdglob.hxx> #include <vcl/svapp.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/maskprimitive2d.hxx> + +#include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx> +#include <svx/eeitem.hxx> +#include <svx/colritem.hxx> +//#include <svx/xtable.hxx> + ////////////////////////////////////////////////////////////////////////////// namespace sdr @@ -78,6 +90,238 @@ namespace sdr { } + void ViewContactOfGraphic::flushGraphicObjects() + { + // #i102380# The graphic is swapped out. To let that have an effect ist is necessary to + // delete copies of the GraphicObject which are not swapped out and have no SwapHandler set + // (this is what happnes when the GraphicObject gets copied to a SdrGrafPrimitive2D). This + // is best achieved for the VC by clearing the local decomposition cache. It would be possible + // to also do this for the VOC cache, but that VOCs exist exactly expresss that the object + // gets visualised, so this would be wrong. + flushViewIndependentPrimitive2DSequence(); + } + + drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createVIP2DSForPresObj( + const basegfx::B2DHomMatrix& rObjectMatrix, + const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute, + const GraphicAttr& rLocalGrafInfo) const + { + drawinglayer::primitive2d::Primitive2DSequence xRetval; + GraphicObject aEmptyGraphicObject; + GraphicAttr aEmptyGraphicAttr; + + // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts + const drawinglayer::primitive2d::Primitive2DReference xReferenceA(new drawinglayer::primitive2d::SdrGrafPrimitive2D( + rObjectMatrix, + rAttribute, + aEmptyGraphicObject, + aEmptyGraphicAttr)); + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReferenceA, 1); + + // SdrGrafPrimitive2D with content (which is the preview graphic) scaled to smaller size and + // without attributes + basegfx::B2DHomMatrix aSmallerMatrix; + + // #i94431# for some reason, i forgot to take the PrefMapMode of the graphic + // into account. Since EmptyPresObj's are only used in Draw/Impress, it is + // safe to assume 100th mm as target. + Size aPrefSize(GetGrafObject().GetGrafPrefSize()); + + if(MAP_PIXEL == GetGrafObject().GetGrafPrefMapMode().GetMapUnit()) + { + aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MAP_100TH_MM); + } + else + { + aPrefSize = Application::GetDefaultDevice()->LogicToLogic(aPrefSize, GetGrafObject().GetGrafPrefMapMode(), MAP_100TH_MM); + } + + // decompose object matrix to get single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + const double fOffsetX((aScale.getX() - aPrefSize.getWidth()) / 2.0); + const double fOffsetY((aScale.getY() - aPrefSize.getHeight()) / 2.0); + + if(basegfx::fTools::moreOrEqual(fOffsetX, 0.0) && basegfx::fTools::moreOrEqual(fOffsetY, 0.0)) + { + // create the EmptyPresObj fallback visualisation. The fallback graphic + // is already provided in rGraphicObject in this case, use it + aSmallerMatrix.scale(aPrefSize.getWidth(), aPrefSize.getHeight()); + aSmallerMatrix.translate(fOffsetX, fOffsetY); + aSmallerMatrix.shearX(fShearX); + aSmallerMatrix.rotate(fRotate); + aSmallerMatrix.translate(aTranslate.getX(), aTranslate.getY()); + + const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false); + const drawinglayer::attribute::SdrLineFillShadowTextAttribute aEmptyAttributes(0, 0, 0, 0, 0, 0); + const drawinglayer::primitive2d::Primitive2DReference xReferenceB(new drawinglayer::primitive2d::SdrGrafPrimitive2D( + aSmallerMatrix, + aEmptyAttributes, + rGraphicObject, + rLocalGrafInfo)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xReferenceB); + } + + return xRetval; + } + + drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createVIP2DSForDraft( + const basegfx::B2DHomMatrix& rObjectMatrix, + const drawinglayer::attribute::SdrLineFillShadowTextAttribute& rAttribute) const + { + drawinglayer::primitive2d::Primitive2DSequence xRetval; + GraphicObject aEmptyGraphicObject; + GraphicAttr aEmptyGraphicAttr; + + // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts + const drawinglayer::primitive2d::Primitive2DReference xReferenceA(new drawinglayer::primitive2d::SdrGrafPrimitive2D( + rObjectMatrix, + rAttribute, + aEmptyGraphicObject, + aEmptyGraphicAttr)); + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReferenceA, 1); + + if(!rAttribute.getLine()) + { + // create a surrounding frame when no linestyle given + const Color aColor(Application::GetSettings().GetStyleSettings().GetShadowColor()); + const basegfx::BColor aBColor(aColor.getBColor()); + const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); + + basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aUnitRange)); + aOutline.transform(rObjectMatrix); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, + drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( + aOutline, + aBColor))); + } + + // decompose object matrix to get single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + rObjectMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + + // define a distance value, used for distance from bitmap to borders and from bitmap + // to text, too (2 mm) + const double fDistance(200.0); + + // consume borders from values + aScale.setX(std::max(0.0, aScale.getX() - (2.0 * fDistance))); + aScale.setY(std::max(0.0, aScale.getY() - (2.0 * fDistance))); + aTranslate.setX(aTranslate.getX() + fDistance); + aTranslate.setY(aTranslate.getY() + fDistance); + + // draw a draft bitmap + const Bitmap aDraftBitmap(ResId(BMAP_GrafikEi, *ImpGetResMgr())); + + if(!aDraftBitmap.IsEmpty()) + { + Size aPrefSize(aDraftBitmap.GetPrefSize()); + + if(MAP_PIXEL == aDraftBitmap.GetPrefMapMode().GetMapUnit()) + { + aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aDraftBitmap.GetSizePixel(), MAP_100TH_MM); + } + else + { + aPrefSize = Application::GetDefaultDevice()->LogicToLogic(aPrefSize, aDraftBitmap.GetPrefMapMode(), MAP_100TH_MM); + } + + const double fBitmapScaling(2.0); + const double fWidth(aPrefSize.getWidth() * fBitmapScaling); + const double fHeight(aPrefSize.getHeight() * fBitmapScaling); + + if(basegfx::fTools::more(fWidth, 1.0) + && basegfx::fTools::more(fHeight, 1.0) + && basegfx::fTools::lessOrEqual(fWidth, aScale.getX()) + && basegfx::fTools::lessOrEqual(fHeight, aScale.getY())) + { + basegfx::B2DHomMatrix aBitmapMatrix; + + aBitmapMatrix.scale(fWidth, fHeight); + aBitmapMatrix.shearX(fShearX); + aBitmapMatrix.rotate(fRotate); + aBitmapMatrix.translate(aTranslate.getX(), aTranslate.getY()); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, + drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::BitmapPrimitive2D( + BitmapEx(aDraftBitmap), + aBitmapMatrix))); + + // consume bitmap size in X + aScale.setX(std::max(0.0, aScale.getX() - (fWidth + fDistance))); + aTranslate.setX(aTranslate.getX() + fWidth + fDistance); + } + } + + // Build the text for the draft object + XubString aDraftText = GetGrafObject().GetFileName(); + + if(!aDraftText.Len()) + { + aDraftText = GetGrafObject().GetName(); + aDraftText.AppendAscii(" ..."); + } + + if(aDraftText.Len() && GetGrafObject().GetModel()) + { + // #i103255# Goal is to produce TextPrimitives which hold the given text as + // BlockText in the available space. It would be very tricky to do + // an own word wrap/line layout here. + // Using SdrBlockTextPrimitive2D OTOH is critical since it internally + // uses the SdrObject it references. To solve this, create a temp + // SdrObject with Attributes and Text, generate a SdrBlockTextPrimitive2D + // directly and immediately decompose it. After that, it is no longer + // needed and can be deleted. + + // create temp RectObj as TextObj and set needed attributes + SdrRectObj aRectObj(OBJ_TEXT); + aRectObj.SetModel(GetGrafObject().GetModel()); + aRectObj.NbcSetText(aDraftText); + aRectObj.SetMergedItem(SvxColorItem(Color(COL_LIGHTRED), EE_CHAR_COLOR)); + + // get SdrText and OPO + SdrText* pSdrText = aRectObj.getText(0); + OutlinerParaObject* pOPO = aRectObj.GetOutlinerParaObject(); + + if(pSdrText && pOPO) + { + // directly use the remaining space as TextRangeTransform + basegfx::B2DHomMatrix aTextRangeTransform; + + aTextRangeTransform.scale(aScale.getX(), aScale.getY()); + aTextRangeTransform.shearX(fShearX); + aTextRangeTransform.rotate(fRotate); + aTextRangeTransform.translate(aTranslate.getX(), aTranslate.getY()); + + // directly create temp SdrBlockTextPrimitive2D + drawinglayer::primitive2d::SdrBlockTextPrimitive2D aBlockTextPrimitive( + pSdrText, + *pOPO, + aTextRangeTransform, + false, + false, + false); + + // decompose immediately with neutral ViewInformation. This will + // layout the text to more simple TextPrimitives from drawinglayer + const drawinglayer::geometry::ViewInformation2D aViewInformation2D(0); + + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence( + xRetval, + aBlockTextPrimitive.get2DDecomposition(aViewInformation2D)); + } + } + + return xRetval; + } + drawinglayer::primitive2d::Primitive2DSequence ViewContactOfGraphic::createViewIndependentPrimitive2DSequence() const { drawinglayer::primitive2d::Primitive2DSequence xRetval; @@ -86,7 +330,8 @@ namespace sdr if(pSdrText) { const SfxItemSet& rItemSet = GetGrafObject().GetMergedItemSet(); - drawinglayer::attribute::SdrLineFillShadowTextAttribute* pAttribute = drawinglayer::primitive2d::createNewSdrLineFillShadowTextAttribute(rItemSet, *pSdrText); + drawinglayer::attribute::SdrLineFillShadowTextAttribute* pAttribute = + drawinglayer::primitive2d::createNewSdrLineFillShadowTextAttribute(rItemSet, *pSdrText); bool bVisible(pAttribute && pAttribute->isVisible()); // create and fill GraphicAttr @@ -131,7 +376,7 @@ namespace sdr // which will use the primitive data we just create in the near future const Rectangle& rRectangle = GetGrafObject().GetGeoRect(); const ::basegfx::B2DRange aObjectRange(rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom()); - ::basegfx::B2DHomMatrix aObjectMatrix; + basegfx::B2DHomMatrix aObjectMatrix; // look for mirroring const GeoStat& rGeoStat(GetGrafObject().GetGeoStat()); @@ -170,60 +415,25 @@ namespace sdr // get the current, unchenged graphic obect from SdrGrafObj const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false); - if(GetGrafObject().IsEmptyPresObj()) + if(visualisationUsesPresObj()) { // it's an EmptyPresObj, create the SdrGrafPrimitive2D without content and another scaled one // with the content which is the placeholder graphic - GraphicObject aEmptyGraphicObject; - GraphicAttr aEmptyGraphicAttr; - drawinglayer::attribute::SdrLineFillShadowTextAttribute aEmptyAttributes(0, 0, 0, 0, 0, 0); - - // SdrGrafPrimitive2D without content in original size which carries all eventual attributes and texts - const drawinglayer::primitive2d::Primitive2DReference xReferenceA(new drawinglayer::primitive2d::SdrGrafPrimitive2D( - aObjectMatrix, *pAttribute, aEmptyGraphicObject, aEmptyGraphicAttr)); - xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReferenceA, 1); - - // SdrGrafPrimitive2D with content (which is the preview graphic) scaled to smaller size and - // without attributes - basegfx::B2DHomMatrix aSmallerMatrix; - - // #i94431# for some reason, i forgot to take the PrefMapMode of the graphic - // into account. Since EmptyPresObj's are only used in Draw/Impress, it is - // safe to assume 100th mm as target. - Size aPrefSize(GetGrafObject().GetGrafPrefSize()); - - if(MAP_PIXEL == GetGrafObject().GetGrafPrefMapMode().GetMapUnit()) - { - aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MAP_100TH_MM); - } - else - { - aPrefSize = Application::GetDefaultDevice()->LogicToLogic(aPrefSize, GetGrafObject().GetGrafPrefMapMode(), MAP_100TH_MM); - } - - const double fOffsetX((aObjectRange.getWidth() - aPrefSize.getWidth()) / 2.0); - const double fOffsetY((aObjectRange.getHeight() - aPrefSize.getHeight()) / 2.0); - - if(basegfx::fTools::moreOrEqual(fOffsetX, 0.0) && basegfx::fTools::moreOrEqual(fOffsetY, 0.0)) - { - aSmallerMatrix.scale(aPrefSize.getWidth(), aPrefSize.getHeight()); - aSmallerMatrix.translate(fOffsetX, fOffsetY); - aSmallerMatrix.shearX(fShearX); - aSmallerMatrix.rotate(fRotate); - aSmallerMatrix.translate(aObjectRange.getMinX(), aObjectRange.getMinY()); - - const drawinglayer::primitive2d::Primitive2DReference xReferenceB(new drawinglayer::primitive2d::SdrGrafPrimitive2D( - aSmallerMatrix, - aEmptyAttributes, - rGraphicObject, - aLocalGrafInfo)); - - drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xReferenceB); - } + xRetval = createVIP2DSForPresObj(aObjectMatrix, *pAttribute, aLocalGrafInfo); + } + else if(visualisationUsesDraft()) + { + // #i102380# The graphic is swapped out. To not force a swap-in here, there is a mechanism + // which shows a swapped-out-visualisation (which gets created here now) and an asynchronious + // visual update mechanism for swapped-out grapgics when they were loaded (see AsynchGraphicLoadingEvent + // and ViewObjectContactOfGraphic implementation). Not forcing the swap-in here allows faster + // (non-blocking) processing here and thus in the effect e.g. fast scrolling through pages + xRetval = createVIP2DSForDraft(aObjectMatrix, *pAttribute); } else { - // create primitive + // create primitive. Info: Calling the copy-constructor of GraphicObject in this + // SdrGrafPrimitive2D constructor will force a full swap-in of the graphic const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::SdrGrafPrimitive2D( aObjectMatrix, *pAttribute, @@ -241,6 +451,31 @@ namespace sdr return xRetval; } + bool ViewContactOfGraphic::visualisationUsesPresObj() const + { + return GetGrafObject().IsEmptyPresObj(); + } + + bool ViewContactOfGraphic::visualisationUsesDraft() const + { + // no draft when already PresObj + if(visualisationUsesPresObj()) + return false; + + // draft when swapped out + const GraphicObject& rGraphicObject = GetGrafObject().GetGraphicObject(false); + static bool bAllowReplacements(true); + + if(rGraphicObject.IsSwappedOut() && bAllowReplacements) + return true; + + // draft when no graphic + if(GRAPHIC_NONE == rGraphicObject.GetType() || GRAPHIC_DEFAULT == rGraphicObject.GetType()) + return true; + + return false; + } + } // end of namespace contact } // end of namespace sdr diff --git a/svx/source/sdr/contact/viewcontactofsdrole2obj.cxx b/svx/source/sdr/contact/viewcontactofsdrole2obj.cxx index e1b2867b0d66..3c239b12113c 100644 --- a/svx/source/sdr/contact/viewcontactofsdrole2obj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrole2obj.cxx @@ -45,6 +45,7 @@ #include <svtools/colorcfg.hxx> #include <svx/sdr/primitive2d/sdrattributecreator.hxx> #include <vcl/svapp.hxx> +#include <svx/sdr/primitive2d/sdrolecontentprimitive2d.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -71,7 +72,8 @@ namespace sdr { } - drawinglayer::primitive2d::Primitive2DSequence ViewContactOfSdrOle2Obj::createPrimitive2DSequenceWithGivenGraphic(const Graphic& rOLEGraphic, bool bScaleContent) const + drawinglayer::primitive2d::Primitive2DSequence ViewContactOfSdrOle2Obj::createPrimitive2DSequenceWithParameters( + bool bHighContrast) const { drawinglayer::primitive2d::Primitive2DSequence xRetval; SdrText* pSdrText = GetOle2Obj().getText(0); @@ -103,80 +105,24 @@ namespace sdr pAttribute = new drawinglayer::attribute::SdrLineFillShadowTextAttribute(0, 0, 0, 0, 0, 0); } - // Prepare OLE filling. This is normally the metafile describing OLE content, but may also - // be the empty OLE bitmap for empty/not loaded OLEs - const GraphicObject aGraphicObject(rOLEGraphic); - const GraphicAttr aGraphicAttr; - drawinglayer::primitive2d::Primitive2DSequence xOLEContent; - - if(bScaleContent) - { - // Create outline and placeholder graphic with some scaling - // #i94431# for some reason, i forgot to take the PrefMapMode of the graphic - // into account. Since EmptyPresObj's are only used in Draw/Impress, it is - // safe to assume 100th mm as target. - Size aPrefSize(rOLEGraphic.GetPrefSize()); - - if(MAP_PIXEL == rOLEGraphic.GetPrefMapMode().GetMapUnit()) - { - aPrefSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MAP_100TH_MM); - } - else - { - aPrefSize = Application::GetDefaultDevice()->LogicToLogic(aPrefSize, rOLEGraphic.GetPrefMapMode(), MAP_100TH_MM); - } - - const double fOffsetX((aObjectRange.getWidth() - aPrefSize.getWidth()) / 2.0); - const double fOffsetY((aObjectRange.getHeight() - aPrefSize.getHeight()) / 2.0); - - if(basegfx::fTools::moreOrEqual(fOffsetX, 0.0) && basegfx::fTools::moreOrEqual(fOffsetY, 0.0)) - { - // if content fits into frame, create it - basegfx::B2DHomMatrix aInnerObjectMatrix; - - aInnerObjectMatrix.scale(aPrefSize.getWidth(), aPrefSize.getHeight()); - aInnerObjectMatrix.translate(fOffsetX, fOffsetY); - aInnerObjectMatrix.shearX(fShearX); - aInnerObjectMatrix.rotate(fRotate); - aInnerObjectMatrix.translate(aObjectRange.getMinX(), aObjectRange.getMinY()); - - drawinglayer::primitive2d::Primitive2DReference xScaledContent( - new drawinglayer::primitive2d::GraphicPrimitive2D(aInnerObjectMatrix, aGraphicObject, aGraphicAttr)); - xOLEContent = drawinglayer::primitive2d::Primitive2DSequence(&xScaledContent, 1); - } - } - else - { - // create graphic primitive for content - drawinglayer::primitive2d::Primitive2DReference xDirectContent( - new drawinglayer::primitive2d::GraphicPrimitive2D(aObjectMatrix, aGraphicObject, aGraphicAttr)); - xOLEContent = drawinglayer::primitive2d::Primitive2DSequence(&xDirectContent, 1); - } + // #i102063# embed OLE content in an own primitive; this will be able to decompose accessing + // the weak SdrOle2 reference and will also implement getB2DRange() for fast BoundRect + // calculations without OLE Graphic access (which may trigger e.g. chart recalculation). + // It will also take care of HighContrast and ScaleContent + const drawinglayer::primitive2d::Primitive2DReference xOleContent( + new drawinglayer::primitive2d::SdrOleContentPrimitive2D( + GetOle2Obj(), + aObjectMatrix, + bHighContrast)); // create primitive. Use Ole2 primitive here. Prepare attribute settings, will be used soon anyways. + const drawinglayer::primitive2d::Primitive2DSequence xOLEContent(&xOleContent, 1); const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::SdrOle2Primitive2D( xOLEContent, aObjectMatrix, *pAttribute)); xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); delete pAttribute; - - // a standard gray outline is created for scaled content - if(bScaleContent) - { - const svtools::ColorConfig aColorConfig; - const svtools::ColorConfigValue aColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES)); - - if(aColor.bIsVisible) - { - basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0, 0, 1, 1))); - const Color aVclColor(aColor.nColor); - aOutline.transform(aObjectMatrix); - const drawinglayer::primitive2d::Primitive2DReference xOutline( - new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOutline, aVclColor.getBColor())); - drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xOutline); - } - } } return xRetval; @@ -184,21 +130,8 @@ namespace sdr drawinglayer::primitive2d::Primitive2DSequence ViewContactOfSdrOle2Obj::createViewIndependentPrimitive2DSequence() const { - const Graphic* pOLEGraphic = GetOle2Obj().GetGraphic(); - - if(pOLEGraphic) - { - // there is a graphic set, use it - return createPrimitive2DSequenceWithGivenGraphic(*pOLEGraphic, GetOle2Obj().IsEmptyPresObj()); - } - else - { - // no graphic, use default empty OLE bitmap - const Bitmap aEmptyOLEBitmap(GetOle2Obj().GetEmtyOLEReplacementBitmap()); - const Graphic aEmtyOLEGraphic(aEmptyOLEBitmap); - - return createPrimitive2DSequenceWithGivenGraphic(aEmtyOLEGraphic, true); - } + // do as if no HC and call standard creator + return createPrimitive2DSequenceWithParameters(false); } } // end of namespace contact } // end of namespace sdr diff --git a/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx b/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx index dc3fbcfaaa61..0f818ff40f7a 100644 --- a/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrpathobj.cxx @@ -62,59 +62,86 @@ namespace sdr if(pSdrText) { - drawinglayer::attribute::SdrLineFillShadowTextAttribute* pAttribute = drawinglayer::primitive2d::createNewSdrLineFillShadowTextAttribute(rItemSet, *pSdrText); + drawinglayer::attribute::SdrLineFillShadowTextAttribute* pAttribute = + drawinglayer::primitive2d::createNewSdrLineFillShadowTextAttribute( + rItemSet, + *pSdrText); if(pAttribute) { if(pAttribute->isVisible()) { - // prepare object transformation and unit polygon (direct model data) - ::basegfx::B2DHomMatrix aObjectMatrix; - ::basegfx::B2DPolyPolygon aUnitPolyPolygon(GetPathObj().GetPathPoly()); - const bool bIsLine( - !aUnitPolyPolygon.areControlPointsUsed() - && 1L == aUnitPolyPolygon.count() - && 2L == aUnitPolyPolygon.getB2DPolygon(0L).count()); - - if(bIsLine) - { - // special handling for single line mode (2 points) - const ::basegfx::B2DPolygon aSubPolygon(aUnitPolyPolygon.getB2DPolygon(0L)); - const ::basegfx::B2DPoint aStart(aSubPolygon.getB2DPoint(0L)); - const ::basegfx::B2DPoint aEnd(aSubPolygon.getB2DPoint(1L)); - const ::basegfx::B2DVector aLine(aEnd - aStart); - - // create new polygon - ::basegfx::B2DPolygon aNewPolygon; - aNewPolygon.append(::basegfx::B2DPoint(0.0, 0.0)); - aNewPolygon.append(::basegfx::B2DPoint(aLine.getLength(), 0.0)); - aUnitPolyPolygon.setB2DPolygon(0L, aNewPolygon); - - // fill objectMatrix with rotation and offset (no shear for lines, scale in polygon) - aObjectMatrix.rotate(atan2(aLine.getY(), aLine.getX())); - aObjectMatrix.translate(aStart.getX(), aStart.getY()); - } - else + basegfx::B2DPolyPolygon aUnitPolyPolygon(GetPathObj().GetPathPoly()); + const sal_uInt32 nPolyCount(aUnitPolyPolygon.count()); + + if(nPolyCount) { - // create scaled, but unsheared, unrotated and untranslated polygon - // by creating the object matrix and back-transforming the polygon - const ::basegfx::B2DRange aObjectRange(::basegfx::tools::getRange(aUnitPolyPolygon)); - const GeoStat& rGeoStat(GetPathObj().GetGeoStat()); - - aObjectMatrix.shearX(tan((36000 - rGeoStat.nShearWink) * F_PI18000)); - aObjectMatrix.rotate((36000 - rGeoStat.nDrehWink) * F_PI18000); - aObjectMatrix.translate(aObjectRange.getMinX(), aObjectRange.getMinY()); - - // ceate scaled unit polygon from object's absolute path - ::basegfx::B2DHomMatrix aInverse(aObjectMatrix); - aInverse.invert(); - aUnitPolyPolygon.transform(aInverse); + // prepare object transformation and unit polygon (direct model data) + basegfx::B2DHomMatrix aObjectMatrix; + const bool bIsLine( + !aUnitPolyPolygon.areControlPointsUsed() + && 1 == nPolyCount + && 2 == aUnitPolyPolygon.getB2DPolygon(0).count()); + + if(bIsLine) + { + // special handling for single line mode (2 points) + const basegfx::B2DPolygon aSubPolygon(aUnitPolyPolygon.getB2DPolygon(0)); + const basegfx::B2DPoint aStart(aSubPolygon.getB2DPoint(0)); + const basegfx::B2DPoint aEnd(aSubPolygon.getB2DPoint(1)); + const basegfx::B2DVector aLine(aEnd - aStart); + + // #i102548# create new unit polygon for line (horizontal) + basegfx::B2DPolygon aNewPolygon; + aNewPolygon.append(basegfx::B2DPoint(0.0, 0.0)); + aNewPolygon.append(basegfx::B2DPoint(1.0, 0.0)); + aUnitPolyPolygon.setB2DPolygon(0, aNewPolygon); + + // #i102548# fill objectMatrix with rotation and offset (no shear for lines) + aObjectMatrix.scale(aLine.getLength(), 1.0); + aObjectMatrix.rotate(atan2(aLine.getY(), aLine.getX())); + aObjectMatrix.translate(aStart.getX(), aStart.getY()); + } + else + { + // #i102548# create unscaled, unsheared, unrotated and untranslated polygon + // (unit polygon) by creating the object matrix and back-transforming the polygon + const basegfx::B2DRange aObjectRange(basegfx::tools::getRange(aUnitPolyPolygon)); + const GeoStat& rGeoStat(GetPathObj().GetGeoStat()); + const double fWidth(aObjectRange.getWidth()); + const double fHeight(aObjectRange.getHeight()); + + aObjectMatrix.scale( + basegfx::fTools::equalZero(fWidth) ? 1.0 : fWidth, + basegfx::fTools::equalZero(fHeight) ? 1.0 : fHeight); + + if(rGeoStat.nShearWink) + { + aObjectMatrix.shearX(tan((36000 - rGeoStat.nShearWink) * F_PI18000)); + } + + if(rGeoStat.nDrehWink) + { + aObjectMatrix.rotate((36000 - rGeoStat.nDrehWink) * F_PI18000); + } + + aObjectMatrix.translate(aObjectRange.getMinX(), aObjectRange.getMinY()); + + // ceate unit polygon from object's absolute path + basegfx::B2DHomMatrix aInverse(aObjectMatrix); + aInverse.invert(); + aUnitPolyPolygon.transform(aInverse); + } + + // create primitive + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::SdrPathPrimitive2D( + aObjectMatrix, + *pAttribute, + aUnitPolyPolygon)); + + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); } - - // create primitive - const drawinglayer::primitive2d::Primitive2DReference xReference( - new drawinglayer::primitive2d::SdrPathPrimitive2D(aObjectMatrix, *pAttribute, aUnitPolyPolygon)); - xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); } delete pAttribute; diff --git a/svx/source/sdr/contact/viewcontactofsdrrectobj.cxx b/svx/source/sdr/contact/viewcontactofsdrrectobj.cxx index c48d110faaf2..8ba8ae8ab4c9 100644 --- a/svx/source/sdr/contact/viewcontactofsdrrectobj.cxx +++ b/svx/source/sdr/contact/viewcontactofsdrrectobj.cxx @@ -105,8 +105,14 @@ namespace sdr drawinglayer::primitive2d::calculateRelativeCornerRadius(nCornerRadius, aObjectRange, fCornerRadiusX, fCornerRadiusY); // create primitive - const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::SdrRectanglePrimitive2D( - aObjectMatrix, *pAttribute, fCornerRadiusX, fCornerRadiusY)); + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::SdrRectanglePrimitive2D( + aObjectMatrix, + *pAttribute, + fCornerRadiusX, + fCornerRadiusY, + GetRectObj().IsTextFrame())); + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); } diff --git a/svx/source/sdr/contact/viewobjectcontactofgraphic.cxx b/svx/source/sdr/contact/viewobjectcontactofgraphic.cxx index 394ae3141182..5e9ab788e392 100644 --- a/svx/source/sdr/contact/viewobjectcontactofgraphic.cxx +++ b/svx/source/sdr/contact/viewobjectcontactofgraphic.cxx @@ -38,6 +38,7 @@ #include <svx/svdograf.hxx> #include <svx/sdr/contact/objectcontact.hxx> #include <svx/svdmodel.hxx> +#include <svx/svdpage.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -219,6 +220,11 @@ namespace sdr SdrGrafObj& rGrafObj = getSdrGrafObj(); rGrafObj.ForceSwapIn(); + // #i103720# forget event to avoid possible deletion by the following ActionChanged call + // which may use createPrimitive2DSequence/impPrepareGraphicWithAsynchroniousLoading again. + // Deletion is actally done by the scheduler who leaded to coming here + mpAsynchLoadEvent = 0; + // Invalidate all paint areas and check existing animation (which may have changed). GetViewContact().ActionChanged(); } @@ -229,11 +235,15 @@ namespace sdr void ViewObjectContactOfGraphic::forgetAsynchGraphicLoadingEvent(sdr::event::AsynchGraphicLoadingEvent* pEvent) { (void) pEvent; // suppress warning - DBG_ASSERT(mpAsynchLoadEvent, "ViewObjectContactOfGraphic::forgetAsynchGraphicLoadingEvent: I did not trigger a event, why am i called (?)"); - DBG_ASSERT(mpAsynchLoadEvent == pEvent, "ViewObjectContactOfGraphic::forgetAsynchGraphicLoadingEvent: Forced to forget another event then i have scheduled (?)"); - // forget event - mpAsynchLoadEvent = 0; + if(mpAsynchLoadEvent) + { + OSL_ENSURE(!pEvent || mpAsynchLoadEvent == pEvent, + "ViewObjectContactOfGraphic::forgetAsynchGraphicLoadingEvent: Forced to forget another event then i have scheduled (?)"); + + // forget event + mpAsynchLoadEvent = 0; + } } SdrGrafObj& ViewObjectContactOfGraphic::getSdrGrafObj() @@ -245,10 +255,19 @@ namespace sdr { // prepare primitive generation with evtl. loading the graphic when it's swapped out SdrGrafObj& rGrafObj = const_cast< ViewObjectContactOfGraphic* >(this)->getSdrGrafObj(); - const bool bDoAsynchronGraphicLoading(rGrafObj.GetModel() && rGrafObj.GetModel()->IsSwapGraphics()); + bool bDoAsynchronGraphicLoading(rGrafObj.GetModel() && rGrafObj.GetModel()->IsSwapGraphics()); static bool bSuppressAsynchLoading(false); bool bSwapInDone(false); + if(bDoAsynchronGraphicLoading + && rGrafObj.IsSwappedOut() + && rGrafObj.GetPage() + && rGrafObj.GetPage()->IsMasterPage()) + { + // #i102380# force Swap-In for GraphicObjects on MasterPage to have a nicer visualisation + bDoAsynchronGraphicLoading = false; + } + if(bDoAsynchronGraphicLoading && !bSuppressAsynchLoading) { bSwapInDone = const_cast< ViewObjectContactOfGraphic* >(this)->impPrepareGraphicWithAsynchroniousLoading(); @@ -261,6 +280,23 @@ namespace sdr // get return value by calling parent drawinglayer::primitive2d::Primitive2DSequence xRetval = ViewObjectContactOfSdrObj::createPrimitive2DSequence(rDisplayInfo); + if(xRetval.hasElements()) + { + // #i103255# suppress when graphic needs draft visualisation and output + // is for PDF export/Printer + const ViewContactOfGraphic& rVCOfGraphic = static_cast< const ViewContactOfGraphic& >(GetViewContact()); + + if(rVCOfGraphic.visualisationUsesDraft()) + { + const ObjectContact& rObjectContact = GetObjectContact(); + + if(rObjectContact.isOutputToPDFFile() || rObjectContact.isOutputToPrinter()) + { + xRetval = drawinglayer::primitive2d::Primitive2DSequence(); + } + } + } + // if swap in was forced only for printing, swap out again const bool bSwapInExclusiveForPrinting(bSwapInDone && GetObjectContact().isOutputToPrinter()); diff --git a/svx/source/sdr/contact/viewobjectcontactofpageobj.cxx b/svx/source/sdr/contact/viewobjectcontactofpageobj.cxx index 87288882995e..34fddf088c98 100644 --- a/svx/source/sdr/contact/viewobjectcontactofpageobj.cxx +++ b/svx/source/sdr/contact/viewobjectcontactofpageobj.cxx @@ -291,7 +291,8 @@ namespace sdr } // add a gray outline frame, except not when printing - if(!GetObjectContact().isOutputToPrinter()) + // #i102637# add frame also when printing and page exists (handout pages) + if(!GetObjectContact().isOutputToPrinter() || pPage) { const Color aFrameColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES).nColor); basegfx::B2DPolygon aOwnOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); diff --git a/svx/source/sdr/contact/viewobjectcontactofsdrole2obj.cxx b/svx/source/sdr/contact/viewobjectcontactofsdrole2obj.cxx index d5681c60463e..635ae9c7fcc8 100644 --- a/svx/source/sdr/contact/viewobjectcontactofsdrole2obj.cxx +++ b/svx/source/sdr/contact/viewobjectcontactofsdrole2obj.cxx @@ -37,10 +37,13 @@ #include <svx/sdr/contact/viewcontactofsdrole2obj.hxx> #include <svx/svdoole2.hxx> #include <svx/sdr/contact/objectcontact.hxx> +#include <svx/svdview.hxx> #include <drawinglayer/primitive2d/chartprimitive2d.hxx> #include <drawinglayer/attribute/fillattribute.hxx> #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> +#include <com/sun/star/embed/EmbedMisc.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
////////////////////////////////////////////////////////////////////////////// @@ -57,136 +60,173 @@ namespace sdr return static_cast< ViewContactOfSdrOle2Obj& >(GetViewContact()).GetOle2Obj(); } - drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfSdrOle2Obj::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const + drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfSdrOle2Obj::createPrimitive2DSequence( + const DisplayInfo& /*rDisplayInfo*/) const { // this method is overloaded to do some things the old SdrOle2Obj::DoPaintObject did. // In the future, some of these may be solved different, but ATM try to stay compatible // with the old behaviour drawinglayer::primitive2d::Primitive2DSequence xRetval; const SdrOle2Obj& rSdrOle2 = getSdrOle2Object(); - const bool bIsActive(rSdrOle2.executeOldDoPaintPreparations(GetObjectContact().TryToGetSdrPageView())); - const Rectangle& rObjectRectangle(rSdrOle2.GetGeoRect()); - const basegfx::B2DRange aObjectRange(rObjectRectangle.Left(), rObjectRectangle.Top(), rObjectRectangle.Right(), rObjectRectangle.Bottom()); - - // create object transform - basegfx::B2DHomMatrix aObjectTransform; - aObjectTransform.set(0, 0, aObjectRange.getWidth()); - aObjectTransform.set(1, 1, aObjectRange.getHeight()); - aObjectTransform.set(0, 2, aObjectRange.getMinX()); - aObjectTransform.set(1, 2, aObjectRange.getMinY()); - - if(GetObjectContact().isDrawModeHighContrast()) - { - // directly call at the corresponding VC and force OLE Graphic to HighContrast - const ViewContactOfSdrOle2Obj& rVC = static_cast< const ViewContactOfSdrOle2Obj& >(GetViewContact()); - Graphic* pOLEHighContrastGraphic = rSdrOle2.getEmbeddedObjectRef().GetHCGraphic(); + sal_Int32 nState(-1); - if(pOLEHighContrastGraphic) - { - // there is a graphic set, use it - xRetval = rVC.createPrimitive2DSequenceWithGivenGraphic(*pOLEHighContrastGraphic, rSdrOle2.IsEmptyPresObj()); - } - else - { - // no HighContrast graphic, use default empty OLE bitmap - const Bitmap aEmptyOLEBitmap(rSdrOle2.GetEmtyOLEReplacementBitmap()); - const Graphic aEmtyOLEGraphic(aEmptyOLEBitmap); - - xRetval = rVC.createPrimitive2DSequenceWithGivenGraphic(aEmtyOLEGraphic, true); - } - } - else { - // call parent which will use the regular createViewIndependentPrimitive2DSequence - // at the corresponding VC - xRetval = ViewObjectContactOfSdrObj::createPrimitive2DSequence(rDisplayInfo); + const svt::EmbeddedObjectRef& xObjRef = rSdrOle2.getEmbeddedObjectRef(); + if ( xObjRef.is() ) + nState = xObjRef->getCurrentState(); } - if(rSdrOle2.getEmbeddedObjectRef().IsChart()) + const bool bIsOutplaceActive(nState == embed::EmbedStates::ACTIVE); + const bool bIsInplaceActive((nState == embed::EmbedStates::INPLACE_ACTIVE) || (nState == embed::EmbedStates::UI_ACTIVE)); + const bool bIsChart(rSdrOle2.IsChart()); + bool bDone(false); + + if(!bDone && bIsInplaceActive) { - // for chart, to not lose the current better quality visualisation which - // uses a direct paint, use a primtive wrapper for that exceptional case. The renderers - // will then ATM paint it to an OutputDevice directly. - // In later versions this should be replaced by getting the Primitive2DSequnce from - // the chart and using it. - // to be able to render something in non-VCL using renderers, the wrapper is a - // GroupPrimitive2D which automatically decomposes to the already created Metafile - // content. - // For being completely compatible, ATM Window and VDEV PrettyPrinting is suppressed. - // It works in the VCL renderers, though. So for activating again with VCL primitive - // renderers, change conditions here. - - // determine if embedding and PrettyPrinting shall be done at all - uno::Reference< frame::XModel > xChartModel; - bool bDoChartPrettyPrinting(true); - static bool bPrettyPrintingForBitmaps(false); - - // the original ChartPrettyPainter does not do it for Window - if(!bPrettyPrintingForBitmaps && bDoChartPrettyPrinting && GetObjectContact().isOutputToWindow()) + if( !GetObjectContact().isOutputToPrinter() && !GetObjectContact().isOutputToRecordingMetaFile() ) { - bDoChartPrettyPrinting = false; + //no need to create a primitive sequence here as the OLE object does render itself + //in case of charts the superfluous creation of a metafile is strongly performance relevant! + bDone = true; } + } + + if( !bDone ) + { + const Rectangle& rObjectRectangle(rSdrOle2.GetGeoRect()); + const basegfx::B2DRange aObjectRange(rObjectRectangle.Left(), rObjectRectangle.Top(), rObjectRectangle.Right(), rObjectRectangle.Bottom()); - // the original ChartPrettyPainter does not do it for VDEV - if(!bPrettyPrintingForBitmaps && bDoChartPrettyPrinting && GetObjectContact().isOutputToVirtualDevice()) + // create object transform + basegfx::B2DHomMatrix aObjectTransform; + aObjectTransform.set(0, 0, aObjectRange.getWidth()); + aObjectTransform.set(1, 1, aObjectRange.getHeight()); + aObjectTransform.set(0, 2, aObjectRange.getMinX()); + aObjectTransform.set(1, 2, aObjectRange.getMinY()); + + if(bIsChart) { - if(GetObjectContact().isOutputToPDFFile()) + //charts must be painted resolution dependent!! #i82893#, #i75867# + + // for chart, to not lose the current better quality visualisation which + // uses a direct paint, use a primtive wrapper for that exceptional case. The renderers + // will then ATM paint it to an OutputDevice directly. + // In later versions this should be replaced by getting the Primitive2DSequnce from + // the chart and using it. + // to be able to render something in non-VCL using renderers, the wrapper is a + // GroupPrimitive2D which automatically decomposes to the already created Metafile + // content. + // For being completely compatible, ATM Window and VDEV PrettyPrinting is suppressed. + // It works in the VCL renderers, though. So for activating again with VCL primitive + // renderers, change conditions here. + + // determine if embedding and PrettyPrinting shall be done at all + uno::Reference< frame::XModel > xChartModel; + bool bDoChartPrettyPrinting(true); + + // the original ChartPrettyPainter does not do it for Window + if(bDoChartPrettyPrinting && GetObjectContact().isOutputToWindow()) { - // #i97982# - // For PDF files, allow PrettyPrinting + bDoChartPrettyPrinting = false; } - else + + // the original ChartPrettyPainter does not do it for VDEV + if(bDoChartPrettyPrinting && GetObjectContact().isOutputToVirtualDevice()) { - bDoChartPrettyPrinting = false; + if(GetObjectContact().isOutputToPDFFile()) + { + // #i97982# + // For PDF files, allow PrettyPrinting + } + else + { + bDoChartPrettyPrinting = false; + } } - } - // the chart model is needed. Check if it's available - if(bDoChartPrettyPrinting) - { - // get chart model - xChartModel = rSdrOle2.getXModel(); + // the chart model is needed. Check if it's available + if(bDoChartPrettyPrinting) + { + // get chart model + xChartModel = rSdrOle2.getXModel(); - if(!xChartModel.is()) + if(!xChartModel.is()) + { + bDoChartPrettyPrinting = false; + } + } + + if(bDoChartPrettyPrinting) { - bDoChartPrettyPrinting = false; + // embed MetaFile data in a specialized Wrapper Primitive which holds also the ChartModel needed + // for PrettyPrinting + const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::ChartPrimitive2D( + xChartModel, aObjectTransform, xRetval)); + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); + bDone = true; } } - if(bDoChartPrettyPrinting) + if( !bDone ) { - // embed MetaFile data in a specialized Wrapper Primitive which holds also the ChartModel needed - // for PrettyPrinting - const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::ChartPrimitive2D( - xChartModel, aObjectTransform, xRetval)); - xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); + //old stuff that should be reworked + { + //if no replacement image is available load the OLE object + if(!rSdrOle2.GetGraphic()) //try to fetch the metafile - this can lead to the actual creation of the metafile what can be extremely expensive (e.g. for big charts)!!! #i101925# + { + // try to create embedded object + rSdrOle2.GetObjRef(); //this loads the OLE object if it is not loaded already + } + const svt::EmbeddedObjectRef& xObjRef = rSdrOle2.getEmbeddedObjectRef(); + if(xObjRef.is()) + { + const sal_Int64 nMiscStatus(xObjRef->getStatus(rSdrOle2.GetAspect())); + + // this hack (to change model data during PAINT argh(!)) should be reworked + if(!rSdrOle2.IsResizeProtect() && (nMiscStatus & embed::EmbedMisc::EMBED_NEVERRESIZE)) + { + const_cast< SdrOle2Obj* >(&rSdrOle2)->SetResizeProtect(true); + } + + SdrPageView* pPageView = GetObjectContact().TryToGetSdrPageView(); + if(pPageView && (nMiscStatus & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE)) + { + // connect plugin object + pPageView->GetView().DoConnect(const_cast< SdrOle2Obj* >(&rSdrOle2)); + } + } + }//end old stuff to rework + + // create OLE primitive stuff directly at VC with HC as parameter + const ViewContactOfSdrOle2Obj& rVC = static_cast< const ViewContactOfSdrOle2Obj& >(GetViewContact()); + xRetval = rVC.createPrimitive2DSequenceWithParameters(GetObjectContact().isDrawModeHighContrast()); } - } - if(bIsActive) - { - // do not shade when printing or PDF exporting - if(!GetObjectContact().isOutputToPrinter() && !GetObjectContact().isOutputToRecordingMetaFile()) + if(bIsOutplaceActive) { - // shade the representation if the object is activated outplace - basegfx::B2DPolygon aObjectOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); - aObjectOutline.transform(aObjectTransform); - - // Use a FillHatchPrimitive2D with necessary attributes - const drawinglayer::attribute::FillHatchAttribute aFillHatch( - drawinglayer::attribute::HATCHSTYLE_SINGLE, // single hatch - 125.0, // 1.25 mm - 45.0 * F_PI180, // 45 degree diagonal - Color(COL_BLACK).getBColor(), // black color - false); // no filling - - const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::PolyPolygonHatchPrimitive2D( - basegfx::B2DPolyPolygon(aObjectOutline), - Color(COL_BLACK).getBColor(), - aFillHatch)); - - drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xReference); + // do not shade when printing or PDF exporting + if(!GetObjectContact().isOutputToPrinter() && !GetObjectContact().isOutputToRecordingMetaFile()) + { + // shade the representation if the object is activated outplace + basegfx::B2DPolygon aObjectOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aObjectOutline.transform(aObjectTransform); + + // Use a FillHatchPrimitive2D with necessary attributes + const drawinglayer::attribute::FillHatchAttribute aFillHatch( + drawinglayer::attribute::HATCHSTYLE_SINGLE, // single hatch + 125.0, // 1.25 mm + 45.0 * F_PI180, // 45 degree diagonal + Color(COL_BLACK).getBColor(), // black color + false); // no filling + + const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::PolyPolygonHatchPrimitive2D( + basegfx::B2DPolyPolygon(aObjectOutline), + Color(COL_BLACK).getBColor(), + aFillHatch)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(xRetval, xReference); + } } + } return xRetval; diff --git a/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx b/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx index ea260f3285f7..92003865fde0 100644 --- a/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx +++ b/svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx @@ -35,6 +35,7 @@ #include <svx/sdr/contact/displayinfo.hxx> #include <svx/sdr/properties/properties.hxx> #include <svx/sdr/contact/objectcontactofpageview.hxx> +#include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx> /** === begin UNO includes === **/ #include <com/sun/star/lang/XMultiServiceFactory.hpp> @@ -80,6 +81,7 @@ namespace sdr { namespace contact { using ::com::sun::star::uno::XInterface; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::awt::XControl; @@ -175,7 +177,11 @@ namespace sdr { namespace contact { inline void addWindowListener( const Reference< XWindowListener >& _l ) const { m_xControlWindow->addWindowListener( _l ); } inline void removeWindowListener( const Reference< XWindowListener >& _l ) const { m_xControlWindow->removeWindowListener( _l ); } void setPosSize( const Rectangle& _rPosSize ) const; - void setZoom( const MapMode& _rMapMode ) const; + Rectangle + getPosSize() const; + void setZoom( const ::basegfx::B2DVector& _rScale ) const; + ::basegfx::B2DVector + getZoom() const; inline void setGraphics( const Reference< XGraphics >& _g ) const { m_xControlView->setGraphics( _g ); } inline Reference< XGraphics > @@ -221,10 +227,36 @@ namespace sdr { namespace contact { } //-------------------------------------------------------------------- - void ControlHolder::setZoom( const MapMode& _rMapMode ) const + ::Rectangle ControlHolder::getPosSize() const { // no check whether we're valid, this is the responsibility of the caller - m_xControlView->setZoom( (float)double( _rMapMode.GetScaleX() ), (float)double( _rMapMode.GetScaleY() ) ); + return VCLUnoHelper::ConvertToVCLRect( m_xControlWindow->getPosSize() ); + } + + //-------------------------------------------------------------------- + void ControlHolder::setZoom( const ::basegfx::B2DVector& _rScale ) const + { + // no check whether we're valid, this is the responsibility of the caller + m_xControlView->setZoom( (float)_rScale.getX(), (float)_rScale.getY() ); + } + + //-------------------------------------------------------------------- + ::basegfx::B2DVector ControlHolder::getZoom() const + { + // no check whether we're valid, this is the responsibility of the caller + + // Argh. Why does XView have a setZoom only, but not a getZoom? + Window* pWindow = VCLUnoHelper::GetWindow( m_xControlWindow ); + OSL_ENSURE( pWindow, "ControlHolder::setZoom: no implementation access!" ); + + ::basegfx::B2DVector aZoom( 1, 1 ); + if ( pWindow ) + { + const Fraction& rZoom( pWindow->GetZoom() ); + aZoom.setX( (double)rZoom ); + aZoom.setY( (double)rZoom ); + } + return aZoom; } //==================================================================== @@ -233,37 +265,13 @@ namespace sdr { namespace contact { class UnoControlContactHelper { public: - /** positions a control relative to a device - - @precond <arg>_pDevice</arg> is not <NULL/> + /** positions a control, and sets its zoom mode, using a given transformation and output device */ - static void positionControl_throw( + static void adjustControlGeometry_throw( const ControlHolder& _rControl, const Rectangle& _rLogicBoundingRect, - const OutputDevice* _pDevice - ); - - /** sets the zoom at a UNO control, according to a Device's MapMode - - @precond <arg>_pDevice</arg> is not <NULL/> - */ - static void setControlZoom( - const ControlHolder& _rControl, - const OutputDevice* _pDevice - ); - - /** draws a given control onto it's current XGraphics, at given coordinates - - Note that the control is not drawn onto the given device, instead you must - use ->XView::setGraphics yourself, before calling this method. The given ->OutputDevice - is only used to calculate pixel coordinates from logic coordinates - - @precond <arg>_pDevice</arg> is not <NULL/> - */ - static void drawControl( - const ControlHolder& _rControl, - const Point& _rLogicTopLeft, - const OutputDevice* _pDevice + const ::basegfx::B2DHomMatrix& _rViewTransformation, + const ::basegfx::B2DHomMatrix& _rZoomLevelNormalization ); /** disposes the given control @@ -279,50 +287,28 @@ namespace sdr { namespace contact { }; //-------------------------------------------------------------------- - void UnoControlContactHelper::positionControl_throw( const ControlHolder& _rControl, const Rectangle& _rLogicBoundingRect, - const OutputDevice* _pDevice ) + void UnoControlContactHelper::adjustControlGeometry_throw( const ControlHolder& _rControl, const Rectangle& _rLogicBoundingRect, + const basegfx::B2DHomMatrix& _rViewTransformation, const ::basegfx::B2DHomMatrix& _rZoomLevelNormalization ) { - OSL_PRECOND( _pDevice, "UnoControlContactHelper::positionControl_throw: no device -> no survival!" ); - - if ( _rControl.is() ) - { - const Rectangle aPaintRectPixel( - _pDevice->LogicToPixel( _rLogicBoundingRect.TopLeft() ), - _pDevice->LogicToPixel( _rLogicBoundingRect.GetSize() ) - ); - - _rControl.setPosSize( aPaintRectPixel ); - } - } - - //-------------------------------------------------------------------- - void UnoControlContactHelper::setControlZoom( const ControlHolder& _rControl, const OutputDevice* _pDevice ) - { - OSL_PRECOND( _pDevice, "UnoControlContactHelper::setControlZoom: no device -> no survival!" ); - OSL_PRECOND( _rControl.is(), "UnoControlContactHelper::setControlZoom: illegal control!" ); - - if ( _rControl.is() ) - _rControl.setZoom( _pDevice->GetMapMode() ); - } - - //-------------------------------------------------------------------- - void UnoControlContactHelper::drawControl( const ControlHolder& _rControl, const Point& _rLogicTopLeft, - const OutputDevice* _pDevice ) - { - OSL_PRECOND( _rControl.is(), "UnoControlContactHelper::drawControl: invalid control!" ); + OSL_PRECOND( _rControl.is(), "UnoControlContactHelper::adjustControlGeometry_throw: illegal control!" ); if ( !_rControl.is() ) return; - try - { - _rControl.draw( - _pDevice->LogicToPixel( _rLogicTopLeft ) - ); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } + // transform the logic bound rect, using the view transformation, to pixel coordinates + ::basegfx::B2DPoint aTopLeft( _rLogicBoundingRect.Left(), _rLogicBoundingRect.Top() ); + aTopLeft *= _rViewTransformation; + ::basegfx::B2DPoint aBottomRight( _rLogicBoundingRect.Right(), _rLogicBoundingRect.Bottom() ); + aBottomRight *= _rViewTransformation; + + const Rectangle aPaintRectPixel( (long)aTopLeft.getX(), (long)aTopLeft.getY(), (long)aBottomRight.getX(), (long)aBottomRight.getY() ); + _rControl.setPosSize( aPaintRectPixel ); + + // determine the scale from the current view transformation, and the normalization matrix + ::basegfx::B2DHomMatrix aObtainResolutionDependentScale( _rViewTransformation * _rZoomLevelNormalization ); + ::basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + aObtainResolutionDependentScale.decompose( aScale, aTranslate, fRotate, fShearX ); + _rControl.setZoom( aScale ); } //-------------------------------------------------------------------- @@ -402,40 +388,7 @@ namespace sdr { namespace contact { } //==================================================================== - //= DummyPageViewAccess - //==================================================================== - /** is a ->IPageViewAccess implementation which defaults all attribute access, and thus can be - operated without an actual ->SdrPageView - */ - class DummyPageViewAccess : public IPageViewAccess - { - public: - virtual bool isDesignMode() const; - virtual Reference< XControlContainer > - getControlContainer( const OutputDevice& _rDevice ) const; - virtual bool isLayerVisible( SdrLayerID _nLayerID ) const; - }; - - //-------------------------------------------------------------------- - bool DummyPageViewAccess::isDesignMode() const - { - return true; - } - - //-------------------------------------------------------------------- - Reference< XControlContainer > DummyPageViewAccess::getControlContainer( const OutputDevice& /*_rDevice*/ ) const - { - return Reference< XControlContainer >(); - } - - //-------------------------------------------------------------------- - bool DummyPageViewAccess::isLayerVisible( SdrLayerID /*_nLayerID*/ ) const - { - return true; - } - - //==================================================================== - //= DummyPageViewAccess + //= InvisibleControlViewAccess //==================================================================== /** is a ->IPageViewAccess implementation which can be used to create an invisble control for an arbitrary device @@ -510,7 +463,7 @@ namespace sdr { namespace contact { Reference< XContainer > m_xContainer; /// the output device for which the control was created - OutputDevice const* m_pOutputDeviceForWindow; + const OutputDevice* m_pOutputDeviceForWindow; /// flag indicating whether the control is currently visible bool m_bControlIsVisible; @@ -527,6 +480,8 @@ namespace sdr { namespace contact { /// is the control currently in design mode? mutable ViewControlMode m_eControlDesignMode; + ::basegfx::B2DHomMatrix m_aZoomLevelNormalization; + public: ViewObjectContactOfUnoControl_Impl( ViewObjectContactOfUnoControl* _pAntiImpl ); @@ -549,17 +504,13 @@ namespace sdr { namespace contact { */ bool getUnoObject( SdrUnoObj*& _out_rpObject ) const; - /** ensures that we have an XControl which can be painted onto the given display - */ - bool ensureControl( const DisplayInfo& _rDisplayInfo ); - /** ensures that we have an ->XControl Must only be called if a control is needed when no DisplayInfo is present, yet. - For creating a control, an ->OutputDevice is needed, and an ->SdrPageView. Both can only be - obtained from a ->DisplayInfo struct, or alternatively a ->ObjectContactOfPageView. So, if - our (anti-impl's) object contact is not a ->ObjectContactOfPageView, this method fill fail. + For creating a control, an ->OutputDevice is needed, and an ->SdrPageView. Both will be obtained + from a ->ObjectContactOfPageView. So, if our (anti-impl's) object contact is not a ->ObjectContactOfPageView, + this method fill fail. Failure of this method will be reported via an assertion in a non-product version. */ @@ -572,22 +523,16 @@ namespace sdr { namespace contact { inline const ControlHolder& getExistentControl() const { return m_aControl; } - /** positions our XControl according to the geometry settings in the SdrUnoObj, - and sets proper zoom settings according to our device + inline bool + hasControl() const { return m_aControl.is(); } + + /** positions our XControl according to the geometry settings in the SdrUnoObj, modified by the given + transformation, and sets proper zoom settings according to our device @precond ->m_pOutputDeviceForWindow and ->m_aControl are not <NULL/> - @tolerant - If the preconditions are not met, nothing is done at all */ - void positionAndZoomControl() const; - - /** positions the control for a paint onto a given device - - If we do not (yet) have a control, or the control does not belong to the - device for which a paint is requested, no positioning happens. - */ - void positionControlForPaint( const DisplayInfo& _rDisplayInfo ) const; + void positionAndZoomControl( const basegfx::B2DHomMatrix& _rViewTransformation ) const; /** determines whether or not our control is printable @@ -626,6 +571,13 @@ namespace sdr { namespace contact { struct GuardAccess { friend class VOCGuard; private: GuardAccess() { } }; ::osl::Mutex& getMutex( GuardAccess ) const { return m_aMutex; } + const ViewContactOfUnoControl& + getViewContact() const + { + ENSURE_OR_THROW( !impl_isDisposed_nofail(), "already disposed" ); + return static_cast< const ViewContactOfUnoControl& >( m_pAntiImpl->GetViewContact() ); + } + protected: ~ViewObjectContactOfUnoControl_Impl(); @@ -797,10 +749,11 @@ namespace sdr { namespace contact { This method cares for this, by retrieving the very original OutputDevice. */ - const OutputDevice& imp_getPageViewDevice_nothrow( const ObjectContactOfPageView& _rObjectContact ) const; + static const OutputDevice& imp_getPageViewDevice_nothrow( const ObjectContactOfPageView& _rObjectContact ); + const OutputDevice& imp_getPageViewDevice_nothrow() const; private: - ViewObjectContactOfUnoControl_Impl(); // never implemented + ViewObjectContactOfUnoControl_Impl(); // never implemented ViewObjectContactOfUnoControl_Impl( const ViewObjectContactOfUnoControl_Impl& ); // never implemented ViewObjectContactOfUnoControl_Impl& operator=( const ViewObjectContactOfUnoControl_Impl& ); // never implemented }; @@ -812,18 +765,65 @@ namespace sdr { namespace contact { */ class VOCGuard { - const ViewObjectContactOfUnoControl_Impl& m_rImpl; - ::osl::MutexGuard m_aMutexGuard; + private: + ::osl::MutexGuard m_aMutexGuard; public: VOCGuard( const ViewObjectContactOfUnoControl_Impl& _rImpl ) - :m_rImpl( _rImpl ) - ,m_aMutexGuard( _rImpl.getMutex( ViewObjectContactOfUnoControl_Impl::GuardAccess() ) ) + :m_aMutexGuard( _rImpl.getMutex( ViewObjectContactOfUnoControl_Impl::GuardAccess() ) ) { } }; //==================================================================== + //= LazyControlCreationPrimitive2D + //==================================================================== + class LazyControlCreationPrimitive2D : public ::drawinglayer::primitive2d::BasePrimitive2D + { + private: + typedef ::drawinglayer::primitive2d::BasePrimitive2D BasePrimitive2D; + + protected: + virtual ::drawinglayer::primitive2d::Primitive2DSequence + get2DDecomposition( + const ::drawinglayer::geometry::ViewInformation2D& rViewInformation + ) const; + + virtual ::drawinglayer::primitive2d::Primitive2DSequence + createLocalDecomposition( + const ::drawinglayer::geometry::ViewInformation2D& rViewInformation + ) const; + + virtual ::basegfx::B2DRange + getB2DRange( + const ::drawinglayer::geometry::ViewInformation2D& rViewInformation + ) const; + + public: + LazyControlCreationPrimitive2D( const ::rtl::Reference< ViewObjectContactOfUnoControl_Impl >& _pVOCImpl ) + :m_pVOCImpl( _pVOCImpl ) + { + ENSURE_OR_THROW( m_pVOCImpl.is(), "Illegal argument." ); + getTransformation( m_pVOCImpl->getViewContact(), m_aTransformation ); + } + + virtual bool operator==(const BasePrimitive2D& rPrimitive) const; + + // declare unique ID for this primitive class + DeclPrimitrive2DIDBlock() + + static void getTransformation( const ViewContactOfUnoControl& _rVOC, ::basegfx::B2DHomMatrix& _out_Transformation ); + + private: + ::rtl::Reference< ViewObjectContactOfUnoControl_Impl > m_pVOCImpl; + /** The geometry is part of the identity of an primitive, so we cannot calculate it on demand + (since the data the calculation is based on might have changed then), but need to calc + it at construction time, and remember it. + */ + ::basegfx::B2DHomMatrix m_aTransformation; + }; + + //==================================================================== //= ViewObjectContactOfUnoControl_Impl //==================================================================== DBG_NAME( ViewObjectContactOfUnoControl_Impl ) @@ -834,10 +834,20 @@ namespace sdr { namespace contact { ,m_bControlIsVisible( false ) ,m_bIsDesignModeListening( false ) ,m_eControlDesignMode( eUnknown ) + ,m_aZoomLevelNormalization() { DBG_CTOR( ViewObjectContactOfUnoControl_Impl, NULL ); DBG_ASSERT( m_pAntiImpl, "ViewObjectContactOfUnoControl_Impl::ViewObjectContactOfUnoControl_Impl: invalid AntiImpl!" ); - } + + const OutputDevice& rPageViewDevice( imp_getPageViewDevice_nothrow() ); + m_aZoomLevelNormalization = rPageViewDevice.GetInverseViewTransformation(); + + ::basegfx::B2DHomMatrix aScaleNormalization; + MapMode aCurrentDeviceMapMode( rPageViewDevice.GetMapMode() ); + aScaleNormalization.set( 0, 0, (double)aCurrentDeviceMapMode.GetScaleX() ); + aScaleNormalization.set( 1, 1, (double)aCurrentDeviceMapMode.GetScaleY() ); + m_aZoomLevelNormalization *= aScaleNormalization; + } //-------------------------------------------------------------------- ViewObjectContactOfUnoControl_Impl::~ViewObjectContactOfUnoControl_Impl() @@ -898,27 +908,21 @@ namespace sdr { namespace contact { } //-------------------------------------------------------------------- - void ViewObjectContactOfUnoControl_Impl::positionControlForPaint( const DisplayInfo& /* #i74769# _rDisplayInfo*/ ) const - { - if ( !m_aControl.is() ) - return; - - positionAndZoomControl(); - } - - //-------------------------------------------------------------------- - void ViewObjectContactOfUnoControl_Impl::positionAndZoomControl() const + void ViewObjectContactOfUnoControl_Impl::positionAndZoomControl( const basegfx::B2DHomMatrix& _rViewTransformation ) const { - OSL_PRECOND( m_pOutputDeviceForWindow && m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::positionAndZoomControl: no output device or no control!" ); - if ( !m_pOutputDeviceForWindow || !m_aControl.is() ) + OSL_PRECOND( ( m_pOutputDeviceForWindow != NULL ) && m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::positionAndZoomControl: no output device or no control!" ); + if ( ( m_pOutputDeviceForWindow == NULL ) || !m_aControl.is() ) return; try { SdrUnoObj* pUnoObject( NULL ); if ( getUnoObject( pUnoObject ) ) - UnoControlContactHelper::positionControl_throw( m_aControl, pUnoObject->GetLogicRect(), m_pOutputDeviceForWindow ); - UnoControlContactHelper::setControlZoom( m_aControl, m_pOutputDeviceForWindow ); + { + UnoControlContactHelper::adjustControlGeometry_throw( m_aControl, pUnoObject->GetLogicRect(), _rViewTransformation, m_aZoomLevelNormalization ); + } + else + OSL_ENSURE( false, "ViewObjectContactOfUnoControl_Impl::positionAndZoomControl: no SdrUnoObj!" ); } catch( const Exception& ) { @@ -927,37 +931,6 @@ namespace sdr { namespace contact { } //-------------------------------------------------------------------- - bool ViewObjectContactOfUnoControl_Impl::ensureControl( const DisplayInfo& /*_rDisplayInfo*/ ) - { - OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::ensureControl: already disposed()" ); - if ( impl_isDisposed_nofail() ) - return false; - - const OutputDevice* pDeviceForControl( NULL ); - - // if we're working for a page view, use the respective OutputDevice at the proper - // PaintWindow. The DisplayInfo might only contain a temporary (virtual) device, which - // is dangerous to remember - // 2006-10-24 / #i70604# / frank.schoenheit@sun.com - ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() ); - if ( pPageViewContact ) - pDeviceForControl = &imp_getPageViewDevice_nothrow( *pPageViewContact ); - - if ( !pDeviceForControl && pPageViewContact) - pDeviceForControl = pPageViewContact->TryToGetOutputDevice(); - - DBG_ASSERT( pDeviceForControl, "ViewObjectContactOfUnoControl_Impl::ensureControl: no output device!" ); - if ( !pDeviceForControl ) - return false; - - SdrPageView* pPageView = m_pAntiImpl->GetObjectContact().TryToGetSdrPageView(); - - ::std::auto_ptr< IPageViewAccess > pPVAccess; - pPVAccess.reset( pPageView ? (IPageViewAccess*)new SdrPageViewAccess( *pPageView ) : (IPageViewAccess*)new DummyPageViewAccess() ); - return impl_ensureControl_nothrow( *pPVAccess, *pDeviceForControl ); - } - - //-------------------------------------------------------------------- bool ViewObjectContactOfUnoControl_Impl::ensureControl() { OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::ensureControl: already disposed()" ); @@ -977,13 +950,21 @@ namespace sdr { namespace contact { } //-------------------------------------------------------------------- - const OutputDevice& ViewObjectContactOfUnoControl_Impl::imp_getPageViewDevice_nothrow( const ObjectContactOfPageView& _rObjectContact ) const + const OutputDevice& ViewObjectContactOfUnoControl_Impl::imp_getPageViewDevice_nothrow() const + { + ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() ); + ENSURE_OR_THROW( pPageViewContact, "need a ObjectContactOfPageView." ); + return imp_getPageViewDevice_nothrow( *pPageViewContact ); + } + + //-------------------------------------------------------------------- + const OutputDevice& ViewObjectContactOfUnoControl_Impl::imp_getPageViewDevice_nothrow( const ObjectContactOfPageView& _rObjectContact ) { // if the PageWindow has a patched PaintWindow, use the original PaintWindow // this ensures that our control is _not_ re-created just because somebody // (temporarily) changed the window to paint onto. // #i72429# / 2007-02-20 / frank.schoenheit@sun.com - const SdrPageWindow& rPageWindow( _rObjectContact.GetPageWindow() ); + SdrPageWindow& rPageWindow( _rObjectContact.GetPageWindow() ); if ( rPageWindow.GetOriginalPaintWindow() ) return rPageWindow.GetOriginalPaintWindow()->GetOutputDevice(); @@ -1001,7 +982,7 @@ namespace sdr { namespace contact { // Somebody requested a control for a new device, which means either of // - our PageView's paint window changed since we were last here // - we don't belong to a page view, and are simply painted onto different devices - // The first sounds strange (doens't it?), the second means we could perhaps + // The first sounds strange (doens't it?), the second means we could perhaps // optimize this in the future - there is no need to re-create the control every time, // is it? // #i74523# / 2007-02-15 / frank.schoenheit@sun.com @@ -1063,44 +1044,37 @@ namespace sdr { namespace contact { bool bSuccess = false; try { - do - { - const ::rtl::OUString sControlServiceName( _rUnoObject.GetUnoControlTypeName() ); + const ::rtl::OUString sControlServiceName( _rUnoObject.GetUnoControlTypeName() ); - Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); - if ( xFactory.is() ) - { - _out_rControl = Reference< XControl >( xFactory->createInstance( sControlServiceName ), UNO_QUERY ); - } - DBG_ASSERT( _out_rControl.is(), "ViewObjectContactOfUnoControl_Impl::createControlForDevice: no control could be created!" ); - if ( !_out_rControl.is() ) - break; + Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_SET_THROW ); + _out_rControl = Reference< XControl >( xFactory->createInstance( sControlServiceName ), UNO_QUERY_THROW ); - // knit the model and the control - _out_rControl.setModel( xControlModel ); + // knit the model and the control + _out_rControl.setModel( xControlModel ); - UnoControlContactHelper::positionControl_throw( _out_rControl, _rUnoObject.GetLogicRect(), &_rDevice ); - - // proper zoom - UnoControlContactHelper::setControlZoom( _out_rControl, &_rDevice ); + // proper geometry + UnoControlContactHelper::adjustControlGeometry_throw( + _out_rControl, + _rUnoObject.GetLogicRect(), + _rDevice.GetViewTransformation(), + _rDevice.GetInverseViewTransformation() + ); - // #107049# set design mode before peer is created, - // this is also needed for accessibility - _out_rControl.setDesignMode( _rPageView.isDesignMode() ); + // #107049# set design mode before peer is created, + // this is also needed for accessibility + _out_rControl.setDesignMode( _rPageView.isDesignMode() ); - // adjust the initial visibility according to the visibility of the layer - // 2003-06-03 - #110592# - fs@openoffice.org - impl_adjustControlVisibilityToLayerVisibility_throw( _out_rControl, _rUnoObject, _rPageView, false, true ); + // adjust the initial visibility according to the visibility of the layer + // 2003-06-03 - #110592# - fs@openoffice.org + impl_adjustControlVisibilityToLayerVisibility_throw( _out_rControl, _rUnoObject, _rPageView, false, true ); - // add the control to the respective control container - // #108327# do this last - Reference< XControlContainer > xControlContainer( _rPageView.getControlContainer( _rDevice ) ); - if ( xControlContainer.is() ) - xControlContainer->addControl( sControlServiceName, _out_rControl.getControl() ); + // add the control to the respective control container + // #108327# do this last + Reference< XControlContainer > xControlContainer( _rPageView.getControlContainer( _rDevice ) ); + if ( xControlContainer.is() ) + xControlContainer->addControl( sControlServiceName, _out_rControl.getControl() ); - bSuccess = true; - } - while ( false ); + bSuccess = true; } catch( const Exception& ) { @@ -1257,18 +1231,16 @@ namespace sdr { namespace contact { //-------------------------------------------------------------------- bool ViewObjectContactOfUnoControl_Impl::isPrintableControl() const { - if ( !m_aControl.is() ) + SdrUnoObj* pUnoObject( NULL ); + if ( !getUnoObject( pUnoObject ) ) return false; bool bIsPrintable = false; try { - Reference< XPropertySet > xModelProperties( m_aControl.getModel(), UNO_QUERY ); - Reference< XPropertySetInfo > xPropertyInfo( xModelProperties.is() ? xModelProperties->getPropertySetInfo() : Reference< XPropertySetInfo >() ); - const ::rtl::OUString sPrintablePropertyName( RTL_CONSTASCII_USTRINGPARAM( "Printable" ) ); - - if ( xPropertyInfo.is() && xPropertyInfo->hasPropertyByName( sPrintablePropertyName ) ) - OSL_VERIFY( xModelProperties->getPropertyValue( sPrintablePropertyName ) >>= bIsPrintable ); + Reference< XPropertySet > xModelProperties( pUnoObject->GetUnoControlModel(), UNO_QUERY_THROW ); + static const ::rtl::OUString s_sPrintablePropertyName( RTL_CONSTASCII_USTRINGPARAM( "Printable" ) ); + OSL_VERIFY( xModelProperties->getPropertyValue( s_sPrintablePropertyName ) >>= bIsPrintable ); } catch( const Exception& ) { @@ -1411,15 +1383,20 @@ namespace sdr { namespace contact { if ( !xNewControl.is() ) return; + ENSURE_OR_THROW( m_pOutputDeviceForWindow, "calling this without /me having an output device should be impossible." ); + DBG_ASSERT( xNewControl->getModel() == m_aControl.getModel(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: another model at the new control?" ); // another model should - in the drawing layer - also imply another SdrUnoObj, which // should also result in new ViewContact, and thus in new ViewObjectContacts impl_switchControlListening_nothrow( false ); + ControlHolder aNewControl( xNewControl ); + aNewControl.setZoom( m_aControl.getZoom() ); + aNewControl.setPosSize( m_aControl.getPosSize() ); + aNewControl.setDesignMode( impl_isControlDesignMode_nothrow() ); + m_aControl = xNewControl; - positionAndZoomControl(); - m_aControl.setDesignMode( impl_isControlDesignMode_nothrow() ); m_bControlIsVisible = m_aControl.isVisible(); impl_switchControlListening_nothrow( true ); @@ -1449,30 +1426,96 @@ namespace sdr { namespace contact { } } + //==================================================================== + //= LazyControlCreationPrimitive2D + //==================================================================== //-------------------------------------------------------------------- - bool ViewObjectContactOfUnoControl_Impl::belongsToDevice( const OutputDevice* _pDevice ) const + bool LazyControlCreationPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const { - DBG_ASSERT( _pDevice, "ViewObjectContactOfUnoControl_Impl::belongsToDevice: invalid device!" ); + if ( !BasePrimitive2D::operator==( rPrimitive ) ) + return false; - OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::belongsToDevice: already disposed!" ); - if ( impl_isDisposed_nofail() ) + const LazyControlCreationPrimitive2D* pRHS = dynamic_cast< const LazyControlCreationPrimitive2D* >( &rPrimitive ); + if ( !pRHS ) return false; - if ( m_pOutputDeviceForWindow ) - { - if ( _pDevice == m_pOutputDeviceForWindow ) - return true; + if ( m_pVOCImpl != pRHS->m_pVOCImpl ) return false; - } - ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() ); - if ( pPageViewContact ) - return ( _pDevice == &imp_getPageViewDevice_nothrow( *pPageViewContact ) ); + if ( m_aTransformation != pRHS->m_aTransformation ) + return false; - DBG_ERROR( "ViewObjectContactOfUnoControl_Impl::belongsToDevice: could not determine the device I belong to!" ); - return false; + return true; + } + + //-------------------------------------------------------------------- + void LazyControlCreationPrimitive2D::getTransformation( const ViewContactOfUnoControl& _rVOC, ::basegfx::B2DHomMatrix& _out_Transformation ) + { + // Do use model data directly to create the correct geometry. Do NOT + // use getBoundRect()/getSnapRect() here; tese will use the sequence of + // primitives themselves in the long run. + const Rectangle aSdrGeoData( _rVOC.GetSdrUnoObj().GetGeoRect() ); + const basegfx::B2DRange aRange( + aSdrGeoData.Left(), + aSdrGeoData.Top(), + aSdrGeoData.Right(), + aSdrGeoData.Bottom() + ); + + _out_Transformation.identity(); + _out_Transformation.set( 0, 0, aRange.getWidth() ); + _out_Transformation.set( 1, 1, aRange.getHeight() ); + _out_Transformation.set( 0, 2, aRange.getMinX() ); + _out_Transformation.set( 1, 2, aRange.getMinY() ); } + //-------------------------------------------------------------------- + ::basegfx::B2DRange LazyControlCreationPrimitive2D::getB2DRange( const ::drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/ ) const + { + ::basegfx::B2DRange aRange( 0.0, 0.0, 1.0, 1.0 ); + aRange.transform( m_aTransformation ); + return aRange; + } + + //-------------------------------------------------------------------- + ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::get2DDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const + { + if ( m_pVOCImpl->hasControl() ) + m_pVOCImpl->positionAndZoomControl( _rViewInformation.getObjectToViewTransformation() ); + return BasePrimitive2D::get2DDecomposition( _rViewInformation ); + } + + //-------------------------------------------------------------------- + ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::createLocalDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const + { + // force control here to make it a VCL ChildWindow. Will be fetched + // and used below by getExistentControl() + m_pVOCImpl->ensureControl(); + m_pVOCImpl->positionAndZoomControl( _rViewInformation.getObjectToViewTransformation() ); + + // get needed data + const ViewContactOfUnoControl& rViewContactOfUnoControl( m_pVOCImpl->getViewContact() ); + Reference< XControlModel > xControlModel( rViewContactOfUnoControl.GetSdrUnoObj().GetUnoControlModel() ); + const ControlHolder& rControl( m_pVOCImpl->getExistentControl() ); + + // check if we already have an XControl. + if ( !xControlModel.is() || !rControl.is() ) + // use the default mechanism. This will create a ControlPrimitive2D without + // handing over a XControl. If not even a XControlModel exists, it will + // create the SdrObject fallback visualisation + return rViewContactOfUnoControl.getViewIndependentPrimitive2DSequence(); + + // create a primitive and hand over the existing xControl. This will + // allow the primitive to not need to create another one on demand. + const drawinglayer::primitive2d::Primitive2DReference xRetval( new ::drawinglayer::primitive2d::ControlPrimitive2D( + m_aTransformation, xControlModel, rControl.getControl() ) ); + + return drawinglayer::primitive2d::Primitive2DSequence(&xRetval, 1); + } + + //-------------------------------------------------------------------- + ImplPrimitrive2DIDBlock( LazyControlCreationPrimitive2D, PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D ) + //==================================================================== //= ViewObjectContactOfUnoControl //==================================================================== @@ -1522,20 +1565,6 @@ namespace sdr { namespace contact { } //-------------------------------------------------------------------- - void ViewObjectContactOfUnoControl::positionControlForPaint( const DisplayInfo& _rDisplayInfo ) const - { - VOCGuard aGuard( *m_pImpl ); - - // ensure we have a control. If we don't, then the Drawing Layer might be tempted to - // never draw the complete form layer. - // #i75095# / 2007-03-05 / frank.schoenheit@sun.com - m_pImpl->ensureControl( _rDisplayInfo ); - - // position the control - m_pImpl->positionControlForPaint( _rDisplayInfo ); - } - - //-------------------------------------------------------------------- void ViewObjectContactOfUnoControl::ensureControlVisibility( bool _bVisible ) const { VOCGuard aGuard( *m_pImpl ); @@ -1582,70 +1611,32 @@ namespace sdr { namespace contact { } //-------------------------------------------------------------------- - bool ViewObjectContactOfUnoControl::belongsToDevice( const OutputDevice* _pDevice ) const + drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfUnoControl::createPrimitive2DSequence(const DisplayInfo& /*rDisplayInfo*/) const { - VOCGuard aGuard( *m_pImpl ); - return m_pImpl->belongsToDevice( _pDevice ); + if ( m_pImpl->isDisposed() ) + // our control already died. + // TODO: Is it worth re-creating the control? Finally, this is a pathological situation, it means some instance + // disposed the control though it doesn't own it. So, /me thinks we should not bother here. + return drawinglayer::primitive2d::Primitive2DSequence();
+
+ ::drawinglayer::primitive2d::Primitive2DReference xPrimitive( new LazyControlCreationPrimitive2D( m_pImpl ) ); + return ::drawinglayer::primitive2d::Primitive2DSequence( &xPrimitive, 1 ); } //-------------------------------------------------------------------- - drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfUnoControl::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const - { - // force control here to make it a VCL ChildWindow. Will be fetched - // and used below by getExistentControl() - m_pImpl->ensureControl(); - m_pImpl->positionControlForPaint(rDisplayInfo); - - // get needed data - const ViewContactOfUnoControl& rViewContactOfUnoControl(static_cast< const ViewContactOfUnoControl& >(GetViewContact())); - Reference< XControlModel > xControlModel(rViewContactOfUnoControl.GetSdrUnoObj().GetUnoControlModel()); - const ControlHolder& rControl(m_pImpl->getExistentControl()); - - // check if we already have a XControl. - if(xControlModel.is() && rControl.is()) - { - // create a primitive and hand over the existing xControl. This will - // allow the primitive to not need to create another one on demand. - // Do use model data directly to create the correct geometry. Do NOT - // use getBoundRect()/getSnapRect() here; tese will use the sequence of - // primitives themselves in the long run. - const Rectangle aUnoControlModelData(rViewContactOfUnoControl.GetSdrUnoObj().GetGeoRect()); - const basegfx::B2DRange aRange(aUnoControlModelData.Left(), aUnoControlModelData.Top(), aUnoControlModelData.Right(), aUnoControlModelData.Bottom()); - - // create object transform - basegfx::B2DHomMatrix aTransform; - aTransform.set(0, 0, aRange.getWidth()); - aTransform.set(1, 1, aRange.getHeight()); - aTransform.set(0, 2, aRange.getMinX()); - aTransform.set(1, 2, aRange.getMinY()); - - // create control primitive with existing XControl - const drawinglayer::primitive2d::Primitive2DReference xRetval(new drawinglayer::primitive2d::ControlPrimitive2D( - aTransform, xControlModel, rControl.getControl())); - - return drawinglayer::primitive2d::Primitive2DSequence(&xRetval, 1); - } - else - { - // use the default mechanism. This will create a ControlPrimitive2D without - // handing over a XControl. If not even a XControlModel exists, it will - // create the SdrObject fallback visualisation - return rViewContactOfUnoControl.getViewIndependentPrimitive2DSequence(); - } - } - void ViewObjectContactOfUnoControl::propertyChange() { // graphical invalidate at all views ActionChanged(); // #i93318# flush Primitive2DSequence to force recreation with updated XControlModel - // since e.g. background color has changed and existing decompositions are evtl. no + // since e.g. background color has changed and existing decompositions are possibly no // longer valid. Unfortunately this is not detected from ControlPrimitive2D::operator== // since it only has a uno reference to the XControlModel flushPrimitive2DSequence(); } + //-------------------------------------------------------------------- void ViewObjectContactOfUnoControl::ActionChanged() { // call parent @@ -1721,6 +1712,14 @@ namespace sdr { namespace contact { DBG_DTOR( UnoControlPrintOrPreviewContact, NULL ); } + //-------------------------------------------------------------------- + drawinglayer::primitive2d::Primitive2DSequence UnoControlPrintOrPreviewContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo ) const + { + if ( !m_pImpl->isPrintableControl() ) + return drawinglayer::primitive2d::Primitive2DSequence(); + return ViewObjectContactOfUnoControl::createPrimitive2DSequence( rDisplayInfo ); + } + //==================================================================== //= UnoControlPDFExportContact //==================================================================== |