diff options
author | Vladimir Glazunov <vg@openoffice.org> | 2009-11-24 13:08:55 +0100 |
---|---|---|
committer | Vladimir Glazunov <vg@openoffice.org> | 2009-11-24 13:08:55 +0100 |
commit | dd859bb9c743d62dbab7cd286672046bf757bbfa (patch) | |
tree | 28138eae4e9a8677a50d391ac84cdaa118b06816 /drawinglayer | |
parent | CWS-TOOLING: integrate CWS sw33bf01 (diff) | |
parent | #i105856# Corrected error with not taking into account that getB2DRange may b... (diff) | |
download | core-dd859bb9c743d62dbab7cd286672046bf757bbfa.tar.gz core-dd859bb9c743d62dbab7cd286672046bf757bbfa.zip |
CWS-TOOLING: integrate CWS ooo32gsl02_DEV300
Diffstat (limited to 'drawinglayer')
14 files changed, 700 insertions, 72 deletions
diff --git a/drawinglayer/inc/drawinglayer/geometry/viewinformation2d.hxx b/drawinglayer/inc/drawinglayer/geometry/viewinformation2d.hxx index 94a5623a2a77..0a87b268c8b1 100644 --- a/drawinglayer/inc/drawinglayer/geometry/viewinformation2d.hxx +++ b/drawinglayer/inc/drawinglayer/geometry/viewinformation2d.hxx @@ -149,6 +149,13 @@ namespace drawinglayer /// On-demand prepared Viewport in discrete units for convenience const basegfx::B2DRange& getDiscreteViewport() const; + /** support reduced DisplayQuality, PropertyName is 'ReducedDisplayQuality'. This + is used e.g. to allow to lower display quality for OverlayPrimitives and + may lead to simpler decompositions in the local create2DDecomposition + implementations of the primitives + */ + bool getReducedDisplayQuality() const; + /** Get the uno::Sequence< beans::PropertyValue > which contains all ViewInformation Use this call if You need to extract all contained ViewInformation. The ones diff --git a/drawinglayer/inc/drawinglayer/primitive2d/sceneprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/sceneprimitive2d.hxx index d7fbfd4deaee..8ffc9a332e5c 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/sceneprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/sceneprimitive2d.hxx @@ -41,6 +41,7 @@ #include <drawinglayer/attribute/sdrattribute3d.hxx> #include <drawinglayer/geometry/viewinformation3d.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> +#include <vcl/bitmapex.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -70,9 +71,13 @@ namespace drawinglayer double mfOldDiscreteSizeY; basegfx::B2DRange maOldUnitVisiblePart; + // the last created BitmapEx, e.g. for fast HitTest. This does not really need + // memory since BitmapEx is internally RefCounted + BitmapEx maOldRenderedBitmap; + // private helpers bool impGetShadow3D(const geometry::ViewInformation2D& rViewInformation) const; - void calculateDsicreteSizes( + void calculateDiscreteSizes( const geometry::ViewInformation2D& rViewInformation, basegfx::B2DRange& rDiscreteRange, basegfx::B2DRange& rVisibleDiscreteRange, @@ -87,7 +92,18 @@ namespace drawinglayer // Geometry extractor. Shadow will be added as in createLocalDecomposition, but // the 3D content is not converted to a bitmap visualisation but to projected 2D gemetry. This // helper is useful e.g. for Contour extraction or HitTests. - Primitive2DSequence getGeometry2D(const geometry::ViewInformation2D& rViewInformation) const; + Primitive2DSequence getGeometry2D() const; + Primitive2DSequence getShadow2D(const geometry::ViewInformation2D& rViewInformation) const; + + // Fast HitTest which uses the last buffered BitmapEx from the last + // rendered area if available. The return value describes if the check + // could be done with the current information, so do NOT use o_rResult + // when it returns false. o_rResult will be changed on return true and + // then contains a definitive answer if content of this scene is hit or + // not. On return false, it is normally necessary to use the geometric + // HitTest (see CutFindProcessor usages). The given HitPoint + // has to be in logic coordinates in scene's ObjectCoordinateSystem. + bool tryToCheckLastVisualisationDirectHit(const basegfx::B2DPoint& rLogicHitPoint, bool& o_rResult) const; // constructor/destructor ScenePrimitive2D( diff --git a/drawinglayer/inc/drawinglayer/processor2d/hittestprocessor2d.hxx b/drawinglayer/inc/drawinglayer/processor2d/hittestprocessor2d.hxx index 1eeaefd2dade..c0ab33052883 100644 --- a/drawinglayer/inc/drawinglayer/processor2d/hittestprocessor2d.hxx +++ b/drawinglayer/inc/drawinglayer/processor2d/hittestprocessor2d.hxx @@ -43,6 +43,7 @@ namespace basegfx { class B2DPolygon; } namespace basegfx { class B2DPolyPolygon; } +namespace drawinglayer { namespace primitive2d { class ScenePrimitive2D; }} ////////////////////////////////////////////////////////////////////////////// @@ -80,6 +81,7 @@ namespace drawinglayer bool checkFillHitWithTolerance( const basegfx::B2DPolyPolygon& rPolyPolygon, double fDiscreteHitTolerance); + void check3DHit(const primitive2d::ScenePrimitive2D& rCandidate); public: HitTestProcessor2D( diff --git a/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx b/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx index e29b413190ab..66ca140c2e56 100644 --- a/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx +++ b/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx @@ -51,6 +51,7 @@ namespace drawinglayer { namespace primitive2d { class BitmapPrimitive2D; class FillBitmapPrimitive2D; class PolyPolygonGradientPrimitive2D; + class PolyPolygonBitmapPrimitive2D; class PolyPolygonColorPrimitive2D; class MetafilePrimitive2D; class MaskPrimitive2D; @@ -100,6 +101,7 @@ namespace drawinglayer void RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate); void RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapCandidate); void RenderPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate); + void RenderPolyPolygonBitmapPrimitive2D(const primitive2d::PolyPolygonBitmapPrimitive2D& rPolygonCandidate); void RenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate); void RenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rPolygonCandidate); void RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate); diff --git a/drawinglayer/inc/drawinglayer/processor3d/cutfindprocessor3d.hxx b/drawinglayer/inc/drawinglayer/processor3d/cutfindprocessor3d.hxx new file mode 100644 index 000000000000..8a800d6d24b1 --- /dev/null +++ b/drawinglayer/inc/drawinglayer/processor3d/cutfindprocessor3d.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: zbufferprocessor3d.hxx,v $ + * + * $Revision: 1.4 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:30:18 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR3D_CUTFINDPROCESSOR3D_HXX +#define INCLUDED_DRAWINGLAYER_PROCESSOR3D_CUTFINDPROCESSOR3D_HXX + +#include <drawinglayer/processor3d/defaultprocessor3d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace processor3d + { + class CutFindProcessor : public BaseProcessor3D + { + private: + // the start and stop point for the cut vector + basegfx::B3DPoint maFront; + basegfx::B3DPoint maBack; + + // the found cut points + ::std::vector< basegfx::B3DPoint > maResult; + + // #i102956# the transformation change from TransformPrimitive3D processings + // needs to be remembered to be able to transform found cuts to the + // basic coordinate system the processor starts with + basegfx::B3DHomMatrix maCombinedTransform; + + // bitfield + bool mbAnyHit : 1; + + // as tooling, the process() implementation takes over API handling and calls this + // virtual render method when the primitive implementation is BasePrimitive3D-based. + virtual void processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate); + + public: + CutFindProcessor(const geometry::ViewInformation3D& rViewInformation, + const basegfx::B3DPoint& rFront, + const basegfx::B3DPoint& rBack, + bool bAnyHit); + + // data access + const ::std::vector< basegfx::B3DPoint >& getCutPoints() const { return maResult; } + bool getAnyHit() const { return mbAnyHit; } + }; + } // end of namespace processor3d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_DRAWINGLAYER_PROCESSOR3D_CUTFINDPROCESSOR3D_HXX + +// eof diff --git a/drawinglayer/prj/d.lst b/drawinglayer/prj/d.lst index 0068b32c24ae..1ba3c2e7b614 100644 --- a/drawinglayer/prj/d.lst +++ b/drawinglayer/prj/d.lst @@ -90,6 +90,8 @@ mkdir: %_DEST%\inc%_EXT%\drawinglayer\processor2d mkdir: %_DEST%\inc%_EXT%\drawinglayer\processor3d ..\inc\drawinglayer\processor3d\baseprocessor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor3d\baseprocessor3d.hxx +..\inc\drawinglayer\processor3d\cutfindprocessor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor3d\cutfindprocessor3d.hxx +..\inc\drawinglayer\processor3d\defaultprocessor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor3d\defaultprocessor3d.hxx ..\inc\drawinglayer\processor3d\zbufferprocessor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor3d\zbufferprocessor3d.hxx ..\inc\drawinglayer\processor3d\tbufferprocessor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor3d\tbufferprocessor3d.hxx diff --git a/drawinglayer/source/geometry/viewinformation2d.cxx b/drawinglayer/source/geometry/viewinformation2d.cxx index 372de9936935..706684c5f7d8 100644 --- a/drawinglayer/source/geometry/viewinformation2d.cxx +++ b/drawinglayer/source/geometry/viewinformation2d.cxx @@ -81,12 +81,18 @@ namespace drawinglayer basegfx::B2DRange maDiscreteViewport; // the DrawPage which is target of visualisation. This is needed e.g. for - // the view-dependent decomposition of PageNumber TextFields + // the view-dependent decomposition of PageNumber TextFields. + // This parameter is buffered here, but mainly resides in mxExtendedInformation, + // so it will be interpreted, but held there. It will also not be added + // to mxExtendedInformation in impFillViewInformationFromContent (it's there already) uno::Reference< drawing::XDrawPage > mxVisualizedPage; // the point in time double mfViewTime; + // bitfield + bool mbReducedDisplayQuality : 1; + // the complete PropertyValue representation (if already created) uno::Sequence< beans::PropertyValue > mxViewInformation; @@ -125,6 +131,12 @@ namespace drawinglayer return s_sNameProperty; } + const ::rtl::OUString& getNamePropertyReducedDisplayQuality() + { + static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ReducedDisplayQuality")); + return s_sNameProperty; + } + void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters) { if(rViewParameters.hasElements()) @@ -139,7 +151,17 @@ namespace drawinglayer { const beans::PropertyValue& rProp = rViewParameters[a]; - if(rProp.Name == getNamePropertyObjectTransformation()) + if(rProp.Name == getNamePropertyReducedDisplayQuality()) + { + // extra information; add to filtered information + mxExtendedInformation[nExtendedInsert++] = rProp; + + // for performance reasons, also cache content locally + sal_Bool bSalBool = sal_True; + rProp.Value >>= bSalBool; + mbReducedDisplayQuality = bSalBool; + } + else if(rProp.Name == getNamePropertyObjectTransformation()) { com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D; rProp.Value >>= aAffineMatrix2D; @@ -185,6 +207,7 @@ namespace drawinglayer const bool bViewportUsed(!maViewport.isEmpty()); const bool bTimeUsed(0.0 < mfViewTime); const bool bVisualizedPageUsed(mxVisualizedPage.is()); + const bool bReducedDisplayQualityUsed(true == mbReducedDisplayQuality); const bool bExtraInformation(mxExtendedInformation.hasElements()); sal_uInt32 nIndex(0); const sal_uInt32 nCount( @@ -193,6 +216,7 @@ namespace drawinglayer (bViewportUsed ? 1 : 0) + (bTimeUsed ? 1 : 0) + (bVisualizedPageUsed ? 1 : 0) + + (bReducedDisplayQualityUsed ? 1 : 0) + (bExtraInformation ? mxExtendedInformation.getLength() : 0)); mxViewInformation.realloc(nCount); @@ -265,6 +289,7 @@ namespace drawinglayer maDiscreteViewport(), mxVisualizedPage(rxDrawPage), mfViewTime(fViewTime), + mbReducedDisplayQuality(false), mxViewInformation(), mxExtendedInformation() { @@ -281,6 +306,7 @@ namespace drawinglayer maDiscreteViewport(), mxVisualizedPage(), mfViewTime(), + mbReducedDisplayQuality(false), mxViewInformation(rViewParameters), mxExtendedInformation() { @@ -355,6 +381,11 @@ namespace drawinglayer return mxVisualizedPage; } + bool getReducedDisplayQuality() const + { + return mbReducedDisplayQuality; + } + const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const { if(!mxViewInformation.hasElements()) @@ -501,6 +532,11 @@ namespace drawinglayer return mpViewInformation2D->getDiscreteViewport(); } + bool ViewInformation2D::getReducedDisplayQuality() const + { + return mpViewInformation2D->getReducedDisplayQuality(); + } + const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getViewInformationSequence() const { return mpViewInformation2D->getViewInformationSequence(); diff --git a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx index f52af2da6a6d..ad36a40ea996 100644 --- a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx @@ -100,7 +100,7 @@ namespace drawinglayer return maShadowPrimitives.hasElements(); } - void ScenePrimitive2D::calculateDsicreteSizes( + void ScenePrimitive2D::calculateDiscreteSizes( const geometry::ViewInformation2D& rViewInformation, basegfx::B2DRange& rDiscreteRange, basegfx::B2DRange& rVisibleDiscreteRange, @@ -110,23 +110,12 @@ namespace drawinglayer rDiscreteRange = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0); rDiscreteRange.transform(rViewInformation.getObjectToViewTransformation() * getObjectTransformation()); - // force to discrete expanded bounds (it grows, so expanding works perfectly well) - rDiscreteRange.expand(basegfx::B2DTuple(floor(rDiscreteRange.getMinX()), floor(rDiscreteRange.getMinY()))); - rDiscreteRange.expand(basegfx::B2DTuple(ceil(rDiscreteRange.getMaxX()), ceil(rDiscreteRange.getMaxY()))); - // clip it against discrete Viewport (if set) rVisibleDiscreteRange = rDiscreteRange; if(!rViewInformation.getViewport().isEmpty()) { rVisibleDiscreteRange.intersect(rViewInformation.getDiscreteViewport()); - - if(!rVisibleDiscreteRange.isEmpty()) - { - // force to discrete expanded bounds, too - rVisibleDiscreteRange.expand(basegfx::B2DTuple(floor(rVisibleDiscreteRange.getMinX()), floor(rVisibleDiscreteRange.getMinY()))); - rVisibleDiscreteRange.expand(basegfx::B2DTuple(ceil(rVisibleDiscreteRange.getMaxX()), ceil(rVisibleDiscreteRange.getMaxY()))); - } } if(rVisibleDiscreteRange.isEmpty()) @@ -177,11 +166,11 @@ namespace drawinglayer } } - // get the involved ranges (see helper method calculateDsicreteSizes for details) + // get the involved ranges (see helper method calculateDiscreteSizes for details) basegfx::B2DRange aDiscreteRange; basegfx::B2DRange aVisibleDiscreteRange; basegfx::B2DRange aUnitVisibleRange; - calculateDsicreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); + calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); if(!aVisibleDiscreteRange.isEmpty()) { @@ -200,6 +189,31 @@ namespace drawinglayer fViewSizeY *= fReduceFactor; } + if(rViewInformation.getReducedDisplayQuality()) + { + // when reducing the visualisation is allowed (e.g. an OverlayObject + // only needed for dragging), reduce resolution extra + // to speed up dragging interactions + const double fArea(fViewSizeX * fViewSizeY); + double fReducedVisualisationFactor(1.0 / (sqrt(fArea) * (1.0 / 170.0))); + + if(fReducedVisualisationFactor > 1.0) + { + fReducedVisualisationFactor = 1.0; + } + else if(fReducedVisualisationFactor < 0.20) + { + fReducedVisualisationFactor = 0.20; + } + + if(fReducedVisualisationFactor != 1.0) + { + fReduceFactor *= fReducedVisualisationFactor; + fViewSizeX *= fReducedVisualisationFactor; + fViewSizeY *= fReducedVisualisationFactor; + } + } + // calculate logic render size in world coordinates for usage in renderer basegfx::B2DVector aLogicRenderSize( aDiscreteRange.getWidth() * fReduceFactor, @@ -207,9 +221,8 @@ namespace drawinglayer aLogicRenderSize *= rViewInformation.getInverseObjectToViewTransformation(); // determine the oversample value - static bool bDoOversample(false); static sal_uInt16 nDefaultOversampleValue(3); - const sal_uInt16 nOversampleValue((bDoOversample || aDrawinglayerOpt.IsAntiAliasing()) ? nDefaultOversampleValue : 0); + const sal_uInt16 nOversampleValue(aDrawinglayerOpt.IsAntiAliasing() ? nDefaultOversampleValue : 0); // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process processor3d::ZBufferProcessor3D aZBufferProcessor3D( @@ -224,18 +237,16 @@ namespace drawinglayer aZBufferProcessor3D.processNonTransparent(getChildren3D()); aZBufferProcessor3D.processTransparent(getChildren3D()); - const BitmapEx aNewBitmap(aZBufferProcessor3D.getBitmapEx()); - const Size aBitmapSizePixel(aNewBitmap.GetSizePixel()); + const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = aZBufferProcessor3D.getBitmapEx(); + const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight()) { // create transform for the created bitmap in discrete coordinates first. - // #i97772# Do not forget to apply evtl. render size reduction to scaling basegfx::B2DHomMatrix aNew2DTransform; - const double fSizeReductionFactor(1.0 / fReduceFactor); - aNew2DTransform.set(0, 0, (double)(aBitmapSizePixel.getWidth() - 1) * fSizeReductionFactor); - aNew2DTransform.set(1, 1, (double)(aBitmapSizePixel.getHeight() - 1) * fSizeReductionFactor); + aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth()); + aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight()); aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX()); aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY()); @@ -243,7 +254,7 @@ namespace drawinglayer aNew2DTransform *= rViewInformation.getInverseObjectToViewTransformation(); // create bitmap primitive and add - const Primitive2DReference xRef(new BitmapPrimitive2D(aNewBitmap, aNew2DTransform)); + const Primitive2DReference xRef(new BitmapPrimitive2D(maOldRenderedBitmap, aNew2DTransform)); appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, xRef); // test: Allow to add an outline in the debugger when tests are needed @@ -262,17 +273,10 @@ namespace drawinglayer return aRetval; } - Primitive2DSequence ScenePrimitive2D::getGeometry2D(const geometry::ViewInformation2D& rViewInformation) const + Primitive2DSequence ScenePrimitive2D::getGeometry2D() const { Primitive2DSequence aRetval; - // create 2D shadows from contained 3D primitives - if(impGetShadow3D(rViewInformation)) - { - // add extracted 2d shadows (before 3d scene creations itself) - aRetval = maShadowPrimitives; - } - // create 2D projected geometry from 3D geometry if(getChildren3D().hasElements()) { @@ -284,14 +288,68 @@ namespace drawinglayer // process local primitives aGeometryProcessor.process(getChildren3D()); - // fetch result and append - Primitive2DSequence a2DExtractedPrimitives(aGeometryProcessor.getPrimitive2DSequence()); - appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, a2DExtractedPrimitives); + // fetch result + aRetval = aGeometryProcessor.getPrimitive2DSequence(); } return aRetval; } + Primitive2DSequence ScenePrimitive2D::getShadow2D(const geometry::ViewInformation2D& rViewInformation) const + { + Primitive2DSequence aRetval; + + // create 2D shadows from contained 3D primitives + if(impGetShadow3D(rViewInformation)) + { + // add extracted 2d shadows (before 3d scene creations itself) + aRetval = maShadowPrimitives; + } + + return aRetval; + } + + bool ScenePrimitive2D::tryToCheckLastVisualisationDirectHit(const basegfx::B2DPoint& rLogicHitPoint, bool& o_rResult) const + { + if(!maOldRenderedBitmap.IsEmpty() && !maOldUnitVisiblePart.isEmpty()) + { + basegfx::B2DHomMatrix aInverseSceneTransform(getObjectTransformation()); + aInverseSceneTransform.invert(); + const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * rLogicHitPoint); + + if(maOldUnitVisiblePart.isInside(aRelativePoint)) + { + // calculate coordinates relative to visualized part + double fDivisorX(maOldUnitVisiblePart.getWidth()); + double fDivisorY(maOldUnitVisiblePart.getHeight()); + + if(basegfx::fTools::equalZero(fDivisorX)) + { + fDivisorX = 1.0; + } + + if(basegfx::fTools::equalZero(fDivisorY)) + { + fDivisorY = 1.0; + } + + const double fRelativeX((aRelativePoint.getX() - maOldUnitVisiblePart.getMinX()) / fDivisorX); + const double fRelativeY((aRelativePoint.getY() - maOldUnitVisiblePart.getMinY()) / fDivisorY); + + // combine with real BitmapSizePixel to get bitmap coordinates + const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); + const sal_Int32 nX(basegfx::fround(fRelativeX * aBitmapSizePixel.Width())); + const sal_Int32 nY(basegfx::fround(fRelativeY * aBitmapSizePixel.Height())); + + // try to get a statement about transparency in that pixel + o_rResult = (0xff != maOldRenderedBitmap.GetTransparency(nX, nY)); + return true; + } + } + + return false; + } + ScenePrimitive2D::ScenePrimitive2D( const primitive3d::Primitive3DSequence& rxChildren3D, const attribute::SdrSceneAttribute& rSdrSceneAttribute, @@ -308,7 +366,8 @@ namespace drawinglayer mbShadow3DChecked(false), mfOldDiscreteSizeX(0.0), mfOldDiscreteSizeY(0.0), - maOldUnitVisiblePart() + maOldUnitVisiblePart(), + maOldRenderedBitmap() { } @@ -359,7 +418,7 @@ namespace drawinglayer { ::osl::MutexGuard aGuard( m_aMutex ); - // get the involved ranges (see helper method calculateDsicreteSizes for details) + // get the involved ranges (see helper method calculateDiscreteSizes for details) basegfx::B2DRange aDiscreteRange; basegfx::B2DRange aUnitVisibleRange; bool bNeedNewDecomposition(false); @@ -368,21 +427,22 @@ namespace drawinglayer if(getLocalDecomposition().hasElements()) { basegfx::B2DRange aVisibleDiscreteRange; - calculateDsicreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); + calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); bDiscreteSizesAreCalculated = true; - // display has changed and cannot be reused when resolution did change - if(!basegfx::fTools::equal(aDiscreteRange.getWidth(), mfOldDiscreteSizeX) || - !basegfx::fTools::equal(aDiscreteRange.getHeight(), mfOldDiscreteSizeY)) + // needs to be painted when the new part is not part of the last + // decomposition + if(!maOldUnitVisiblePart.isInside(aUnitVisibleRange)) { bNeedNewDecomposition = true; } + // display has changed and cannot be reused when resolution got bigger. It + // can be reused when resolution got smaller, though. if(!bNeedNewDecomposition) { - // needs to be painted when the new part is not part of the last - // decomposition - if(!maOldUnitVisiblePart.isInside(aUnitVisibleRange)) + if(basegfx::fTools::more(aDiscreteRange.getWidth(), mfOldDiscreteSizeX) || + basegfx::fTools::more(aDiscreteRange.getHeight(), mfOldDiscreteSizeY)) { bNeedNewDecomposition = true; } @@ -400,7 +460,7 @@ namespace drawinglayer if(!bDiscreteSizesAreCalculated) { basegfx::B2DRange aVisibleDiscreteRange; - calculateDsicreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); + calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); } // remember last used NewDiscreteSize and NewUnitVisiblePart diff --git a/drawinglayer/source/processor2d/contourextractor2d.cxx b/drawinglayer/source/processor2d/contourextractor2d.cxx index b7931aed5c27..1f629cb25c9c 100644 --- a/drawinglayer/source/processor2d/contourextractor2d.cxx +++ b/drawinglayer/source/processor2d/contourextractor2d.cxx @@ -162,7 +162,8 @@ namespace drawinglayer { // 2D Scene primitive containing 3D stuff; extract 2D contour in world coordinates const primitive2d::ScenePrimitive2D& rScenePrimitive2DCandidate(static_cast< const primitive2d::ScenePrimitive2D& >(rCandidate)); - const primitive2d::Primitive2DSequence xExtracted2DSceneGeometry(rScenePrimitive2DCandidate.getGeometry2D(getViewInformation2D())); + const primitive2d::Primitive2DSequence xExtracted2DSceneGeometry(rScenePrimitive2DCandidate.getGeometry2D()); + const primitive2d::Primitive2DSequence xExtracted2DSceneShadow(rScenePrimitive2DCandidate.getShadow2D(getViewInformation2D())); // proccess content if(xExtracted2DSceneGeometry.hasElements()) @@ -170,6 +171,12 @@ namespace drawinglayer process(xExtracted2DSceneGeometry); } + // proccess content + if(xExtracted2DSceneShadow.hasElements()) + { + process(xExtracted2DSceneShadow); + } + break; } case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D : diff --git a/drawinglayer/source/processor2d/hittestprocessor2d.cxx b/drawinglayer/source/processor2d/hittestprocessor2d.cxx index 8a2d732cbb2f..4ffef7515389 100644 --- a/drawinglayer/source/processor2d/hittestprocessor2d.cxx +++ b/drawinglayer/source/processor2d/hittestprocessor2d.cxx @@ -48,6 +48,8 @@ #include <drawinglayer/primitive2d/sceneprimitive2d.hxx> #include <drawinglayer/primitive2d/hittestprimitive2d.hxx> #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx> +#include <basegfx/matrix/b3dhommatrix.hxx> +#include <drawinglayer/processor3d/cutfindprocessor3d.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -164,6 +166,121 @@ namespace drawinglayer return bRetval; } + void HitTestProcessor2D::check3DHit(const primitive2d::ScenePrimitive2D& rCandidate) + { + // calculate relative point in unified 2D scene + const basegfx::B2DPoint aLogicHitPosition(getViewInformation2D().getInverseObjectToViewTransformation() * getDiscreteHitPosition()); + + // use bitmap check in ScenePrimitive2D + bool bTryFastResult(false); + + if(rCandidate.tryToCheckLastVisualisationDirectHit(aLogicHitPosition, bTryFastResult)) + { + mbHit = bTryFastResult; + } + else + { + basegfx::B2DHomMatrix aInverseSceneTransform(rCandidate.getObjectTransformation()); + aInverseSceneTransform.invert(); + const basegfx::B2DPoint aRelativePoint(aInverseSceneTransform * aLogicHitPosition); + + // check if test point is inside scene's unified area at all + if(aRelativePoint.getX() >= 0.0 && aRelativePoint.getX() <= 1.0 + && aRelativePoint.getY() >= 0.0 && aRelativePoint.getY() <= 1.0) + { + // get 3D view information + const geometry::ViewInformation3D& rObjectViewInformation3D = rCandidate.getViewInformation3D(); + + // create HitPoint Front and Back, transform to object coordinates + basegfx::B3DHomMatrix aViewToObject(rObjectViewInformation3D.getObjectToView()); + aViewToObject.invert(); + const basegfx::B3DPoint aFront(aViewToObject * basegfx::B3DPoint(aRelativePoint.getX(), aRelativePoint.getY(), 0.0)); + const basegfx::B3DPoint aBack(aViewToObject * basegfx::B3DPoint(aRelativePoint.getX(), aRelativePoint.getY(), 1.0)); + + if(!aFront.equal(aBack)) + { + const primitive3d::Primitive3DSequence& rPrimitives = rCandidate.getChildren3D(); + + if(rPrimitives.hasElements()) + { + // make BoundVolume empty and overlapping test for speedup + const basegfx::B3DRange aObjectRange( + drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence( + rPrimitives, rObjectViewInformation3D)); + + if(!aObjectRange.isEmpty()) + { + const basegfx::B3DRange aFrontBackRange(aFront, aBack); + + if(aObjectRange.overlaps(aFrontBackRange)) + { + // bound volumes hit, geometric cut tests needed + drawinglayer::processor3d::CutFindProcessor aCutFindProcessor( + rObjectViewInformation3D, + aFront, + aBack, + true); + aCutFindProcessor.process(rPrimitives); + + mbHit = (0 != aCutFindProcessor.getCutPoints().size()); + } + } + } + } + } + + // This is needed to check hit with 3D shadows, too. HitTest is without shadow + // to keep compatible with previous versions. Keeping here as reference + // + // if(!getHit()) + // { + // // if scene has shadow, check hit with shadow, too + // const primitive2d::Primitive2DSequence xExtracted2DSceneShadow(rCandidate.getShadow2D(getViewInformation2D())); + // + // if(xExtracted2DSceneShadow.hasElements()) + // { + // // proccess extracted 2D content + // process(xExtracted2DSceneShadow); + // } + // } + + if(!getHit()) + { + // empty 3D scene; Check for border hit + basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aOutline.transform(rCandidate.getObjectTransformation()); + + mbHit = checkHairlineHitWithTolerance(aOutline, getDiscreteHitTolerance()); + } + + // This is what the previous version did. Keeping it here for reference + // + // // 2D Scene primitive containing 3D stuff; extract 2D contour in world coordinates + // // This may be refined later to an own 3D HitTest renderer which processes the 3D + // // geometry directly + // const primitive2d::ScenePrimitive2D& rScenePrimitive2DCandidate(static_cast< const primitive2d::ScenePrimitive2D& >(rCandidate)); + // const primitive2d::Primitive2DSequence xExtracted2DSceneGeometry(rScenePrimitive2DCandidate.getGeometry2D()); + // const primitive2d::Primitive2DSequence xExtracted2DSceneShadow(rScenePrimitive2DCandidate.getShadow2D(getViewInformation2D())); + // + // if(xExtracted2DSceneGeometry.hasElements() || xExtracted2DSceneShadow.hasElements()) + // { + // // proccess extracted 2D content + // process(xExtracted2DSceneGeometry); + // process(xExtracted2DSceneShadow); + // } + // else + // { + // // empty 3D scene; Check for border hit + // const basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D())); + // if(!aRange.isEmpty()) + // { + // const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); + // mbHit = checkHairlineHitWithTolerance(aOutline, getDiscreteHitTolerance()); + // } + // } + } + } + void HitTestProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { if(getHit()) @@ -334,25 +451,8 @@ namespace drawinglayer { if(!getHitTextOnly()) { - // 2D Scene primitive containing 3D stuff; extract 2D contour in world coordinates - // This may be refined later to an own 3D HitTest renderer which processes the 3D - // geometry directly - const primitive2d::ScenePrimitive2D& rScenePrimitive2DCandidate(static_cast< const primitive2d::ScenePrimitive2D& >(rCandidate)); - const primitive2d::Primitive2DSequence xExtracted2DSceneGeometry(rScenePrimitive2DCandidate.getGeometry2D(getViewInformation2D())); - - if(xExtracted2DSceneGeometry.hasElements()) - { - // proccess extracted 2D content - process(xExtracted2DSceneGeometry); - } - else - { - // empty 3D scene; Check for border hit - const basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D())); - basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); - - mbHit = checkHairlineHitWithTolerance(aOutline, getDiscreteHitTolerance()); - } + const primitive2d::ScenePrimitive2D& rSceneCandidate(static_cast< const primitive2d::ScenePrimitive2D& >(rCandidate)); + check3DHit(rSceneCandidate); } break; @@ -365,14 +465,23 @@ namespace drawinglayer // ignorable primitives break; } + case PRIMITIVE2D_ID_SHADOWPRIMITIVE2D : + { + // Ignore shadows; we do not want to have shadows hittable. + // Remove this one to make shadows hittable on demand. + break; + } case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D : case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D : { // for text use the BoundRect of the primitive itself const basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D())); - basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); - mbHit = checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), getDiscreteHitTolerance()); + if(!aRange.isEmpty()) + { + const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); + mbHit = checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), getDiscreteHitTolerance()); + } break; } @@ -392,9 +501,12 @@ namespace drawinglayer // - For Bitamps, the mask and/or alpha information may be used // - For MetaFiles, the MetaFile content may be used const basegfx::B2DRange aRange(rCandidate.getB2DRange(getViewInformation2D())); - basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); - mbHit = checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), getDiscreteHitTolerance()); + if(!aRange.isEmpty()) + { + const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aRange)); + mbHit = checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), getDiscreteHitTolerance()); + } } break; diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 8e2f89bb82a6..ef351002a1ea 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -218,6 +218,12 @@ namespace drawinglayer } break; } + case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D : + { + // direct draw of bitmap + RenderPolyPolygonBitmapPrimitive2D(static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate)); + break; + } case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D : { // direct draw of PolyPolygon with color diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index e5a88812dd10..ede5aee730cf 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -565,6 +565,98 @@ namespace drawinglayer } } + // direct draw of bitmap + void VclProcessor2D::RenderPolyPolygonBitmapPrimitive2D(const primitive2d::PolyPolygonBitmapPrimitive2D& rPolygonCandidate) + { + bool bDone(false); + const basegfx::B2DPolyPolygon& rPolyPolygon = rPolygonCandidate.getB2DPolyPolygon(); + + if(rPolyPolygon.count()) + { + const attribute::FillBitmapAttribute& rFillBitmapAttribute = rPolygonCandidate.getFillBitmap(); + const Bitmap& rBitmap = rFillBitmapAttribute.getBitmap(); + + if(rBitmap.IsEmpty()) + { + // empty bitmap, done + bDone = true; + } + else + { + // try to catch cases where the bitmap will be color-modified to a single + // color (e.g. shadow). This would NOT be optimizable with an alpha channel + // at the Bitmap which we do not have here. When this should change, this + // optimization has to be reworked accordingly. + const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count()); + + if(nBColorModifierStackCount) + { + const basegfx::BColorModifier& rTopmostModifier = maBColorModifierStack.getBColorModifier(nBColorModifierStackCount - 1); + + if(basegfx::BCOLORMODIFYMODE_REPLACE == rTopmostModifier.getMode()) + { + // the bitmap fill is in unified color, so we can replace it with + // a single polygon fill. The form of the fill depends on tiling + if(rFillBitmapAttribute.getTiling()) + { + // with tiling, fill the whole PolyPolygon with the modifier color + basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolyPolygon); + + aLocalPolyPolygon.transform(maCurrentTransformation); + mpOutputDevice->SetLineColor(); + mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor())); + mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); + } + else + { + // without tiling, only the area common to the bitmap tile and the + // PolyPolygon is filled. Create the bitmap tile area in object + // coordinates. For this, the object transformation needs to be created + // from the already scaled PolyPolygon. The tile area in object + // coordinates wil always be non-rotated, so it's not necessary to + // work with a polygon here + basegfx::B2DRange aTileRange(rFillBitmapAttribute.getTopLeft(), + rFillBitmapAttribute.getTopLeft() + rFillBitmapAttribute.getSize()); + const basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.getB2DRange()); + basegfx::B2DHomMatrix aNewObjectTransform; + + aNewObjectTransform.set(0, 0, aPolyPolygonRange.getWidth()); + aNewObjectTransform.set(1, 1, aPolyPolygonRange.getHeight()); + aNewObjectTransform.set(0, 2, aPolyPolygonRange.getMinX()); + aNewObjectTransform.set(1, 2, aPolyPolygonRange.getMinY()); + aTileRange.transform(aNewObjectTransform); + + // now clip the object polyPolygon against the tile range + // to get the common area (OR) + basegfx::B2DPolyPolygon aTarget = basegfx::tools::clipPolyPolygonOnRange(rPolyPolygon, aTileRange, true, false); + + if(aTarget.count()) + { + aTarget.transform(maCurrentTransformation); + mpOutputDevice->SetLineColor(); + mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor())); + mpOutputDevice->DrawPolyPolygon(aTarget); + } + } + + bDone = true; + } + } + } + } + else + { + // empty polyPolygon, done + bDone = true; + } + + if(!bDone) + { + // use default decomposition + process(rPolygonCandidate.get2DDecomposition(getViewInformation2D())); + } + } + // direct draw of PolyPolygon with color void VclProcessor2D::RenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate) { diff --git a/drawinglayer/source/processor3d/cutfindprocessor3d.cxx b/drawinglayer/source/processor3d/cutfindprocessor3d.cxx new file mode 100644 index 000000000000..99f5801c60e3 --- /dev/null +++ b/drawinglayer/source/processor3d/cutfindprocessor3d.cxx @@ -0,0 +1,199 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: zbufferprocessor3d.cxx,v $ + * + * $Revision: 1.5 $ + * + * last change: $Author: aw $ $Date: 2008-06-24 15:31:09 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_drawinglayer.hxx" + +#include <drawinglayer/processor3d/cutfindprocessor3d.hxx> +#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> +#include <drawinglayer/primitive3d/transformprimitive3d.hxx> +#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx> +#include <drawinglayer/primitive3d/hittestprimitive3d.hxx> +#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx> +#include <basegfx/polygon/b3dpolygon.hxx> +#include <basegfx/polygon/b3dpolygontools.hxx> +#include <basegfx/polygon/b3dpolypolygontools.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace processor3d + { + CutFindProcessor::CutFindProcessor(const geometry::ViewInformation3D& rViewInformation, + const basegfx::B3DPoint& rFront, + const basegfx::B3DPoint& rBack, + bool bAnyHit) + : BaseProcessor3D(rViewInformation), + maFront(rFront), + maBack(rBack), + maResult(), + maCombinedTransform(), + mbAnyHit(bAnyHit) + { + } + + void CutFindProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate) + { + if(getAnyHit() && maResult.size()) + { + // stop processing as soon as a hit was recognized + return; + } + + // it is a BasePrimitive3D implementation, use getPrimitiveID() call for switch + switch(rCandidate.getPrimitiveID()) + { + case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D : + { + // transform group. + const primitive3d::TransformPrimitive3D& rPrimitive = static_cast< const primitive3d::TransformPrimitive3D& >(rCandidate); + + // remember old and transform front, back to object coordinates + const basegfx::B3DPoint aLastFront(maFront); + const basegfx::B3DPoint aLastBack(maBack); + basegfx::B3DHomMatrix aInverseTrans(rPrimitive.getTransformation()); + aInverseTrans.invert(); + maFront *= aInverseTrans; + maBack *= aInverseTrans; + + // remember current and create new transformation; add new object transform from right side + const geometry::ViewInformation3D aLastViewInformation3D(getViewInformation3D()); + const geometry::ViewInformation3D aNewViewInformation3D( + aLastViewInformation3D.getObjectTransformation() * rPrimitive.getTransformation(), + aLastViewInformation3D.getOrientation(), + aLastViewInformation3D.getProjection(), + aLastViewInformation3D.getDeviceToView(), + aLastViewInformation3D.getViewTime(), + aLastViewInformation3D.getExtendedInformationSequence()); + updateViewInformation(aNewViewInformation3D); + + // #i102956# remember needed back-transform for found cuts (combine from right side) + const basegfx::B3DHomMatrix aLastCombinedTransform(maCombinedTransform); + maCombinedTransform = maCombinedTransform * rPrimitive.getTransformation(); + + // let break down + process(rPrimitive.getChildren()); + + // restore transformations and front, back + maCombinedTransform = aLastCombinedTransform; + updateViewInformation(aLastViewInformation3D); + maFront = aLastFront; + maBack = aLastBack; + break; + } + case PRIMITIVE3D_ID_POLYGONHAIRLINEPRIMITIVE3D : + { + // PolygonHairlinePrimitive3D, not used for hit test with planes, ignore. This + // means that also thick line expansion will not be hit-tested as + // PolyPolygonMaterialPrimitive3D + break; + } + case PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D : + { + // #i97321# + // For HatchTexturePrimitive3D, do not use the decomposition since it will produce + // clipped hatch lines in 3D. It can be used when the hatch also has a filling, but for + // simplicity, just use the children which are the PolyPolygonMaterialPrimitive3D + // which define the hatched areas anyways; for HitTest this is more than adequate + const primitive3d::HatchTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::HatchTexturePrimitive3D& >(rCandidate); + process(rPrimitive.getChildren()); + break; + } + case PRIMITIVE3D_ID_HITTESTPRIMITIVE3D : + { + // HitTestPrimitive3D, force usage due to we are doing a hit test and this + // primitive only gets generated on 3d objects without fill, exactly for this + // purpose + const primitive3d::HitTestPrimitive3D& rPrimitive = static_cast< const primitive3d::HitTestPrimitive3D& >(rCandidate); + process(rPrimitive.getChildren()); + break; + } + case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D : + { + // PolyPolygonMaterialPrimitive3D + const primitive3d::PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::PolyPolygonMaterialPrimitive3D& >(rCandidate); + + if(!maFront.equal(maBack)) + { + const basegfx::B3DPolyPolygon& rPolyPolygon = rPrimitive.getB3DPolyPolygon(); + const sal_uInt32 nPolyCount(rPolyPolygon.count()); + + if(nPolyCount) + { + const basegfx::B3DPolygon aPolygon(rPolyPolygon.getB3DPolygon(0)); + const sal_uInt32 nPointCount(aPolygon.count()); + + if(nPointCount > 2) + { + const basegfx::B3DVector aPlaneNormal(aPolygon.getNormal()); + + if(!aPlaneNormal.equalZero()) + { + const basegfx::B3DPoint aPointOnPlane(aPolygon.getB3DPoint(0)); + double fCut(0.0); + + if(basegfx::tools::getCutBetweenLineAndPlane(aPlaneNormal, aPointOnPlane, maFront, maBack, fCut)) + { + const basegfx::B3DPoint aCutPoint(basegfx::interpolate(maFront, maBack, fCut)); + + if(basegfx::tools::isInside(rPolyPolygon, aCutPoint, false)) + { + // #i102956# add result. Do not forget to do this in the coordinate + // system the processor get started with, so use the collected + // combined transformation from processed TransformPrimitive3D's + maResult.push_back(maCombinedTransform * aCutPoint); + } + } + } + } + } + } + + break; + } + default : + { + // process recursively + process(rCandidate.get3DDecomposition(getViewInformation3D())); + break; + } + } + } + } // end of namespace processor3d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/processor3d/makefile.mk b/drawinglayer/source/processor3d/makefile.mk index 8ca0097c435a..2ae2ae52f2f2 100644 --- a/drawinglayer/source/processor3d/makefile.mk +++ b/drawinglayer/source/processor3d/makefile.mk @@ -46,6 +46,7 @@ ENABLE_EXCEPTIONS=TRUE SLOFILES= \ $(SLO)$/baseprocessor3d.obj \ + $(SLO)$/cutfindprocessor3d.obj \ $(SLO)$/defaultprocessor3d.obj \ $(SLO)$/shadow3dextractor.obj \ $(SLO)$/geometry2dextractor.obj \ |