diff options
author | Oliver Bolte <obo@openoffice.org> | 2008-10-17 08:40:10 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2008-10-17 08:40:10 +0000 |
commit | a8ac4bc4145e7e558153b58c87b2def339aebe36 (patch) | |
tree | d1f5da0a1b702f12725b2b82117b7ff49872bb21 /drawinglayer | |
parent | ae562e931a98e708a75e8d140cf1ff24854acfc7 (diff) |
CWS-TOOLING: integrate CWS aw057
Diffstat (limited to 'drawinglayer')
35 files changed, 1937 insertions, 788 deletions
diff --git a/drawinglayer/inc/drawinglayer/attribute/materialattribute3d.hxx b/drawinglayer/inc/drawinglayer/attribute/materialattribute3d.hxx index f441e8047193..392f1b0a9113 100644 --- a/drawinglayer/inc/drawinglayer/attribute/materialattribute3d.hxx +++ b/drawinglayer/inc/drawinglayer/attribute/materialattribute3d.hxx @@ -41,7 +41,7 @@ ////////////////////////////////////////////////////////////////////////////// // predefines -namespace drawinglayer { namespace { +namespace drawinglayer { namespace attribute { class ImpMaterialAttribute3D; }} diff --git a/drawinglayer/inc/drawinglayer/geometry/viewinformation2d.hxx b/drawinglayer/inc/drawinglayer/geometry/viewinformation2d.hxx index d38250e7bf47..94a5623a2a77 100644 --- a/drawinglayer/inc/drawinglayer/geometry/viewinformation2d.hxx +++ b/drawinglayer/inc/drawinglayer/geometry/viewinformation2d.hxx @@ -47,7 +47,7 @@ ////////////////////////////////////////////////////////////////////////////// // predefines -namespace drawinglayer { namespace { +namespace drawinglayer { namespace geometry { class ImpViewInformation2D; }} diff --git a/drawinglayer/inc/drawinglayer/geometry/viewinformation3d.hxx b/drawinglayer/inc/drawinglayer/geometry/viewinformation3d.hxx index 6a6cb5d767e5..605c26733cf3 100644 --- a/drawinglayer/inc/drawinglayer/geometry/viewinformation3d.hxx +++ b/drawinglayer/inc/drawinglayer/geometry/viewinformation3d.hxx @@ -46,7 +46,7 @@ ////////////////////////////////////////////////////////////////////////////// // predefines -namespace drawinglayer { namespace { +namespace drawinglayer { namespace geometry { class ImpViewInformation3D; }} diff --git a/drawinglayer/inc/drawinglayer/primitive2d/animatedprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/animatedprimitive2d.hxx index 03f7487c1aa7..41ae18b30fc9 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/animatedprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/animatedprimitive2d.hxx @@ -129,7 +129,7 @@ namespace drawinglayer namespace drawinglayer { - namespace + namespace primitive2d { class BufferedMatrixDecompose { diff --git a/drawinglayer/inc/drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx b/drawinglayer/inc/drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx index c17ca34d733a..f5a851b0b053 100644 --- a/drawinglayer/inc/drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx @@ -63,6 +63,7 @@ #define PRIMITIVE3D_ID_BITMAPTEXTUREPRIMITIVE3D (PRIMITIVE3D_ID_RANGE_DRAWINGLAYER| 15) #define PRIMITIVE3D_ID_ALPHATEXTUREPRIMITIVE3D (PRIMITIVE3D_ID_RANGE_DRAWINGLAYER| 16) #define PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D (PRIMITIVE3D_ID_RANGE_DRAWINGLAYER| 17) +#define PRIMITIVE3D_ID_HITTESTPRIMITIVE3D (PRIMITIVE3D_ID_RANGE_DRAWINGLAYER| 18) ////////////////////////////////////////////////////////////////////////////// diff --git a/drawinglayer/inc/drawinglayer/primitive3d/hittestprimitive3d.hxx b/drawinglayer/inc/drawinglayer/primitive3d/hittestprimitive3d.hxx new file mode 100644 index 000000000000..28029f223b1b --- /dev/null +++ b/drawinglayer/inc/drawinglayer/primitive3d/hittestprimitive3d.hxx @@ -0,0 +1,83 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: hittestprimitive3d.hxx,v $ + * + * $Revision: 1.1.2.1 $ + * + * last change: $Author: aw $ $Date: 2008/09/24 14:27:39 $ + * + * 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_PRIMITIVE3D_HITTESTPRIMITIVE3D_HXX +#define INCLUDED_DRAWINGLAYER_PRIMITIVE3D_HITTESTPRIMITIVE3D_HXX + +#include <drawinglayer/primitive3d/groupprimitive3d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive3d + { + // This primitive is used to represent geometry for non-visible objects, + // e.g. a 3D cube without fill attributes. To still be able to use + // primitives for HitTest functionality, the 3d decompositions produce + // an as much as possible simplified fill geometry encapsulated in this + // primtive when there is no fill geometry. Currently, the 3d hit test + // uses only areas, so maybe in a further enchanced version this will change + // to 'if neither filled nor lines' creation criteria. The whole primitive + // decomposes to nothing, so no one not knowing it will be influenced. Only + // helper processors for hit test (and maybe BoundRect extractors) will + // use it and it's children subcontent. + class HitTestPrimitive3D : public GroupPrimitive3D + { + protected: + // local decomposition. Implementation will return empty Primitive3DSequence + // since this is no visualisation data + virtual Primitive3DSequence createLocalDecomposition(const geometry::ViewInformation3D& rViewInformation) const; + + public: + HitTestPrimitive3D(const Primitive3DSequence& rChildren); + + // despite returning an empty decomposition since it's no visualisation data, + // range calculation is intended to use invisible replacement geometry, so + // the local implementation will return the children's range + virtual basegfx::B3DRange getB3DRange(const geometry::ViewInformation3D& rViewInformation) const; + + // provide unique ID + DeclPrimitrive3DIDBlock() + }; + } // end of namespace primitive3d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE3D_HITTESTPRIMITIVE3D_HXX + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx b/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx index b79f8381c695..0c356e731169 100644 --- a/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx +++ b/drawinglayer/inc/drawinglayer/processor2d/canvasprocessor.hxx @@ -44,6 +44,7 @@ #include <com/sun/star/rendering/RenderState.hpp> #include <i18npool/lang.h> #include <basegfx/polygon/b2dpolypolygon.hxx> +#include <vcl/mapmod.hxx> ////////////////////////////////////////////////////////////////////////////// // forward declaration @@ -58,6 +59,17 @@ namespace com { namespace sun { namespace star { namespace rendering { class XPolyPolygon2D; }}}} +namespace drawinglayer { namespace primitive2d { + class MaskPrimitive2D; + class MetafilePrimitive2D; + class TextSimplePortionPrimitive2D; + class BitmapPrimitive2D; + class AlphaPrimitive2D; + class PolygonStrokePrimitive2D; + class FillBitmapPrimitive2D; + class UnifiedAlphaPrimitive2D; +}} + ////////////////////////////////////////////////////////////////////////////// namespace drawinglayer @@ -67,7 +79,12 @@ namespace drawinglayer class canvasProcessor2D : public BaseProcessor2D { private: - // the destination canvas + // The Pixel renderer resets the original MapMode from the OutputDevice. + // For some situations it is necessary to get it again, so it is rescued here + MapMode maOriginalMapMode; + + // the (current) destination OutDev and canvas + OutputDevice* mpOutputDevice; com::sun::star::uno::Reference< com::sun::star::rendering::XCanvas > mxCanvas; com::sun::star::rendering::ViewState maViewState; com::sun::star::rendering::RenderState maRenderState; @@ -78,7 +95,8 @@ namespace drawinglayer // SvtOptionsDrawinglayer incarnation to react on diverse settings const SvtOptionsDrawinglayer maDrawinglayerOpt; - // the current clipping PolyPolygon from MaskPrimitive2D + // the current clipping PolyPolygon from MaskPrimitive2D, always in + // object coordinates basegfx::B2DPolyPolygon maClipPolyPolygon; // determined LanguageType @@ -88,10 +106,20 @@ namespace drawinglayer // virtual render method when the primitive implementation is BasePrimitive2D-based. virtual void processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate); + // direct primitive renderer support + void impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate); + void impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate); + void impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate); + void impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate); + void impRenderAlphaPrimitive2D(const primitive2d::AlphaPrimitive2D& rAlphaCandidate); + void impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive); + void impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D); + void impRenderUnifiedAlphaPrimitive2D(const primitive2d::UnifiedAlphaPrimitive2D& rUniAlphaCandidate); + public: canvasProcessor2D( const geometry::ViewInformation2D& rViewInformation, - const com::sun::star::uno::Reference< com::sun::star::rendering::XCanvas >& rCanvas); + OutputDevice& rOutDev); virtual ~canvasProcessor2D(); // access to Drawinglayer configuration options diff --git a/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx b/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx index fb9bf24bdb2e..82c65e249c2e 100644 --- a/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx +++ b/drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx @@ -59,11 +59,9 @@ namespace drawinglayer { namespace primitive2d { class MarkerArrayPrimitive2D; class PointArrayPrimitive2D; class ModifiedColorPrimitive2D; - class WrongSpellPrimitive2D; class PolygonStrokePrimitive2D; class ControlPrimitive2D; class PagePreviewPrimitive2D; - class ChartPrimitive2D; }} ////////////////////////////////////////////////////////////////////////////// @@ -110,9 +108,7 @@ namespace drawinglayer void RenderPagePreviewPrimitive2D(const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate); void RenderMarkerArrayPrimitive2D(const primitive2d::MarkerArrayPrimitive2D& rMarkerArrayCandidate); void RenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate); - void RenderWrongSpellPrimitive2D(const primitive2d::WrongSpellPrimitive2D& rWrongSpellCandidate); void RenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate); - void RenderChartPrimitive2D(const primitive2d::ChartPrimitive2D& rChartCandidate); ///////////////////////////////////////////////////////////////////////////// // DrawMode adaption support diff --git a/drawinglayer/prj/d.lst b/drawinglayer/prj/d.lst index 373bf575f916..3e3055d73cfb 100644 --- a/drawinglayer/prj/d.lst +++ b/drawinglayer/prj/d.lst @@ -50,6 +50,7 @@ mkdir: %_DEST%\inc%_EXT%\drawinglayer\primitive3d ..\inc\drawinglayer\primitive3d\baseprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\baseprimitive3d.hxx ..\inc\drawinglayer\primitive3d\groupprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\groupprimitive3d.hxx ..\inc\drawinglayer\primitive3d\hatchtextureprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\hatchtextureprimitive3d.hxx +..\inc\drawinglayer\primitive3d\hittestprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\hittestprimitive3d.hxx ..\inc\drawinglayer\primitive3d\modifiedcolorprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\modifiedcolorprimitive3d.hxx ..\inc\drawinglayer\primitive3d\polygonprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\polygonprimitive3d.hxx ..\inc\drawinglayer\primitive3d\polygontubeprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\polygontubeprimitive3d.hxx diff --git a/drawinglayer/source/attribute/materialattribute3d.cxx b/drawinglayer/source/attribute/materialattribute3d.cxx index a52a81e418e4..bc3e8f3b317b 100644 --- a/drawinglayer/source/attribute/materialattribute3d.cxx +++ b/drawinglayer/source/attribute/materialattribute3d.cxx @@ -43,7 +43,7 @@ namespace drawinglayer { - namespace + namespace attribute { class ImpMaterialAttribute3D { diff --git a/drawinglayer/source/geometry/viewinformation2d.cxx b/drawinglayer/source/geometry/viewinformation2d.cxx index 52fdf12cf3bc..372de9936935 100644 --- a/drawinglayer/source/geometry/viewinformation2d.cxx +++ b/drawinglayer/source/geometry/viewinformation2d.cxx @@ -52,7 +52,7 @@ using namespace com::sun::star; namespace drawinglayer { - namespace + namespace geometry { class ImpViewInformation2D { diff --git a/drawinglayer/source/geometry/viewinformation3d.cxx b/drawinglayer/source/geometry/viewinformation3d.cxx index 61ceddc8396a..a47384485ee7 100644 --- a/drawinglayer/source/geometry/viewinformation3d.cxx +++ b/drawinglayer/source/geometry/viewinformation3d.cxx @@ -51,7 +51,7 @@ using namespace com::sun::star; namespace drawinglayer { - namespace + namespace geometry { /** Implementation class for ViewInformation3D */ diff --git a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx index 70b965e32d67..13f1f699f1ab 100644 --- a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx @@ -176,7 +176,7 @@ namespace drawinglayer namespace drawinglayer { - namespace + namespace primitive2d { BufferedMatrixDecompose::BufferedMatrixDecompose(const basegfx::B2DHomMatrix& rMatrix) : maB2DHomMatrix(rMatrix), diff --git a/drawinglayer/source/primitive2d/controlprimitive2d.cxx b/drawinglayer/source/primitive2d/controlprimitive2d.cxx index 3b1fd70a6964..6241eeb2fa73 100644 --- a/drawinglayer/source/primitive2d/controlprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/controlprimitive2d.cxx @@ -52,6 +52,8 @@ #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> #include <svtools/optionsdrawinglayer.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <vcl/window.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -118,13 +120,6 @@ namespace drawinglayer aScale = basegfx::absolute(aScale); basegfx::B2DVector aDiscreteSize(rViewInformation.getObjectToViewTransformation() * aScale); - // calc screen zoom for text display - basegfx::B2DVector aScreenZoom( - basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : aDiscreteSize.getX() / aScale.getX(), - basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : aDiscreteSize.getY() / aScale.getY()); - static double fZoomScale(26.0); // do not ask for this constant factor, but it gets the zoom right - aScreenZoom *= fZoomScale; - // limit to a maximum square size, e.g. 300x150 pixels (45000) const SvtOptionsDrawinglayer aDrawinglayerOpt; const double fDiscreteMax(aDrawinglayerOpt.GetQuadraticFormControlRenderLimit()); @@ -137,7 +132,6 @@ namespace drawinglayer // get factor and adapt to scaled size fFactor = sqrt(fDiscreteMax / fDiscreteQuadratic); aDiscreteSize *= fFactor; - aScreenZoom *= fFactor; } // go to integer @@ -163,8 +157,57 @@ namespace drawinglayer // link graphics and view xControlView->setGraphics(xGraphics); - // set zoom at control view for text scaling - xControlView->setZoom((float)aScreenZoom.getX(), (float)aScreenZoom.getY()); + { // #i93162# For painting the control setting a Zoom (using setZoom() at the xControlView) + // is needed to define the font size. Normally this is done in + // ViewObjectContactOfUnoControl::createPrimitive2DSequence by using positionControlForPaint(). + // For some reason the difference between MAP_TWIPS and MAP_100TH_MM still plays + // a role there so that for Draw/Impress/Calc (the MAP_100TH_MM users) i need to set a zoom + // here, too. The factor includes the needed scale, but is calculated by pure comparisons. It + // is somehow related to the twips/100thmm relationship. + bool bUserIs100thmm(false); + const uno::Reference< awt::XControl > xControl(xControlView, uno::UNO_QUERY); + + if(xControl.is()) + { + uno::Reference< awt::XWindowPeer > xWindowPeer(xControl->getPeer()); + + if(xWindowPeer.is()) + { + VCLXWindow* pVCLXWindow = VCLXWindow::GetImplementation(xWindowPeer); + + if(pVCLXWindow) + { + Window* pWindow = pVCLXWindow->GetWindow(); + + if(pWindow) + { + pWindow = pWindow->GetParent(); + + if(pWindow) + { + if(MAP_100TH_MM == pWindow->GetMapMode().GetMapUnit()) + { + bUserIs100thmm = true; + } + } + } + } + } + } + + if(bUserIs100thmm) + { + // calc screen zoom for text display. fFactor is already added indirectly in aDiscreteSize + basegfx::B2DVector aScreenZoom( + basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : aDiscreteSize.getX() / aScale.getX(), + basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : aDiscreteSize.getY() / aScale.getY()); + static double fZoomScale(28.0); // do not ask for this constant factor, but it gets the zoom right + aScreenZoom *= fZoomScale; + + // set zoom at control view for text scaling + xControlView->setZoom((float)aScreenZoom.getX(), (float)aScreenZoom.getY()); + } + } try { diff --git a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx index 6246bfb07b87..edb8752d57ba 100644 --- a/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx @@ -336,10 +336,11 @@ namespace drawinglayer { namespace primitive2d { - Primitive2DSequence PolyPolygonGradientPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + Primitive2DSequence PolyPolygonGradientPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const { // create SubSequence with FillGradientPrimitive2D - FillGradientPrimitive2D* pNewGradient = new FillGradientPrimitive2D(getB2DRange(rViewInformation), getFillGradient()); + const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); + FillGradientPrimitive2D* pNewGradient = new FillGradientPrimitive2D(aPolyPolygonRange, getFillGradient()); const Primitive2DReference xSubRef(pNewGradient); const Primitive2DSequence aSubSequence(&xSubRef, 1L); @@ -382,10 +383,11 @@ namespace drawinglayer { namespace primitive2d { - Primitive2DSequence PolyPolygonHatchPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + Primitive2DSequence PolyPolygonHatchPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const { // create SubSequence with FillHatchPrimitive2D - FillHatchPrimitive2D* pNewHatch = new FillHatchPrimitive2D(getB2DRange(rViewInformation), getBColor(), getFillHatch()); + const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); + FillHatchPrimitive2D* pNewHatch = new FillHatchPrimitive2D(aPolyPolygonRange, getBColor(), getFillHatch()); const Primitive2DReference xSubRef(pNewHatch); const Primitive2DSequence aSubSequence(&xSubRef, 1L); @@ -428,15 +430,15 @@ namespace drawinglayer { namespace primitive2d { - Primitive2DSequence PolyPolygonBitmapPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& rViewInformation) const + Primitive2DSequence PolyPolygonBitmapPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const { // create SubSequence with FillBitmapPrimitive2D - const basegfx::B2DRange aOwnRange(getB2DRange(rViewInformation)); + const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange()); basegfx::B2DHomMatrix aNewObjectTransform; - aNewObjectTransform.set(0, 0, aOwnRange.getWidth()); - aNewObjectTransform.set(1, 1, aOwnRange.getHeight()); - aNewObjectTransform.set(0, 2, aOwnRange.getMinX()); - aNewObjectTransform.set(1, 2, aOwnRange.getMinY()); + aNewObjectTransform.set(0, 0, aPolyPolygonRange.getWidth()); + aNewObjectTransform.set(1, 1, aPolyPolygonRange.getHeight()); + aNewObjectTransform.set(0, 2, aPolyPolygonRange.getMinX()); + aNewObjectTransform.set(1, 2, aPolyPolygonRange.getMinY()); FillBitmapPrimitive2D* pNewBitmap = new FillBitmapPrimitive2D(aNewObjectTransform, getFillBitmap()); const Primitive2DReference xSubRef(pNewBitmap); const Primitive2DSequence aSubSequence(&xSubRef, 1L); diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index e994357b5724..8725323c6bf5 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -278,12 +278,8 @@ namespace drawinglayer double fFontScaleX, double fFontScaleY, double fFontRotation, - const OutputDevice& rOutDev) + const OutputDevice& /*rOutDev*/) { -#ifndef WIN32 - // not used under unix, but reference for warning-free - (void)rOutDev; -#endif sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX))); sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY))); Font aRetval( @@ -305,10 +301,26 @@ namespace drawinglayer #ifdef WIN32 if(nWidth != nHeight) { - const FontMetric aFontMetric(rOutDev.GetFontMetric(aRetval)); - const double fCurrentWidth(aFontMetric.GetWidth()); - - aRetval.SetWidth(basegfx::fround(fCurrentWidth * (nWidth/nHeight))); + // #i92757# + // Removed the relative calculation with GetFontMetric() usage again. On + // the one hand it was wrong (integer division always created zero), OTOH + // calculating a scale factor from current to target width and then using + // it to actually scale the current width does nothing but set the target + // value directly. Maybe more is needed here with WIN version of font + // width/height handling, but currently, this works the simple way. + // + // As can be seen, when this can stay the simple way, the OutputDevice + // can be removed from the whole getVclFontFromFontAttributes implementations + // again and make it more VCL-independent. + // + // Adapted nWidth usage to nWidth-1 to be completely compatible with + // non-primitive version. + // + // previous stuff: + // const FontMetric aFontMetric(rOutDev.GetFontMetric(aRetval)); + // const double fCurrentWidth(aFontMetric.GetWidth()); + // aRetval.SetWidth(basegfx::fround(fCurrentWidth * ((double)nWidth/(double)nHeight))); + aRetval.SetWidth(nWidth ? nWidth - 1 : 0); } #endif diff --git a/drawinglayer/source/primitive3d/hittestprimitive3d.cxx b/drawinglayer/source/primitive3d/hittestprimitive3d.cxx new file mode 100644 index 000000000000..50616ab1548b --- /dev/null +++ b/drawinglayer/source/primitive3d/hittestprimitive3d.cxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: hittestprimitive3d.cxx,v $ + * + * $Revision: 1.1.2.1 $ + * + * last change: $Author: aw $ $Date: 2008/09/25 17:12:14 $ + * + * 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/primitive3d/hittestprimitive3d.hxx> +#include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive3d + { + Primitive3DSequence HitTestPrimitive3D::createLocalDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const + { + // return empty sequence + return Primitive3DSequence(); + } + + HitTestPrimitive3D::HitTestPrimitive3D( + const Primitive3DSequence& rChildren) + : GroupPrimitive3D(rChildren) + { + } + + basegfx::B3DRange HitTestPrimitive3D::getB3DRange(const geometry::ViewInformation3D& rViewInformation) const + { + return getB3DRangeFromPrimitive3DSequence(getChildren(), rViewInformation); + } + + // provide unique ID + ImplPrimitrive3DIDBlock(HitTestPrimitive3D, PRIMITIVE3D_ID_HITTESTPRIMITIVE3D) + + } // end of namespace primitive3d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/primitive3d/makefile.mk b/drawinglayer/source/primitive3d/makefile.mk index 325155995acf..fb160fb9bfa7 100644 --- a/drawinglayer/source/primitive3d/makefile.mk +++ b/drawinglayer/source/primitive3d/makefile.mk @@ -48,6 +48,7 @@ SLOFILES= \ $(SLO)$/baseprimitive3d.obj \ $(SLO)$/groupprimitive3d.obj \ $(SLO)$/hatchtextureprimitive3d.obj \ + $(SLO)$/hittestprimitive3d.obj \ $(SLO)$/modifiedcolorprimitive3d.obj \ $(SLO)$/polypolygonprimitive3d.obj \ $(SLO)$/polygonprimitive3d.obj \ diff --git a/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx index af91a74f6591..341d2907a53d 100644 --- a/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrcubeprimitive3d.cxx @@ -43,6 +43,8 @@ #include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx> #include <basegfx/tools/canvastools.hxx> #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> +#include <drawinglayer/primitive3d/hittestprimitive3d.hxx> +#include <drawinglayer/attribute/sdrattribute.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -58,107 +60,127 @@ namespace drawinglayer { const basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); Primitive3DSequence aRetval; + basegfx::B3DPolyPolygon aFill(basegfx::tools::createCubeFillPolyPolygonFromB3DRange(aUnitRange)); - // add fill + // normal creation if(getSdrLFSAttribute().getFill()) { - basegfx::B3DPolyPolygon aFill(basegfx::tools::createCubeFillPolyPolygonFromB3DRange(aUnitRange)); - - // normal creation + if(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind() + || ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind()) { - if(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind() - || ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind()) - { - // create sphere normals - const basegfx::B3DPoint aCenter(basegfx::tools::getRange(aFill).getCenter()); - aFill = basegfx::tools::applyDefaultNormalsSphere(aFill, aCenter); - } - - if(getSdr3DObjectAttribute().getNormalsInvert()) - { - // invert normals - aFill = basegfx::tools::invertNormals(aFill); - } + // create sphere normals + const basegfx::B3DPoint aCenter(basegfx::tools::getRange(aFill).getCenter()); + aFill = basegfx::tools::applyDefaultNormalsSphere(aFill, aCenter); } - // texture coordinates + if(getSdr3DObjectAttribute().getNormalsInvert()) { - // handle texture coordinates X - const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX()); - const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); - const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX())); + // invert normals + aFill = basegfx::tools::invertNormals(aFill); + } + } - // handle texture coordinates Y - const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY()); - const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); - const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY())); + // texture coordinates + if(getSdrLFSAttribute().getFill()) + { + // handle texture coordinates X + const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX()); + const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); + const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX())); - if(bParallelX || bParallelY) - { - // apply parallel texture coordinates in X and/or Y - const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill)); - aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY); - } + // handle texture coordinates Y + const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY()); + const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); + const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY())); - if(bSphereX || bSphereY) - { - // apply spherical texture coordinates in X and/or Y - const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill)); - const basegfx::B3DPoint aCenter(aRange.getCenter()); - aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter, bSphereX, bSphereY); - } + if(bParallelX || bParallelY) + { + // apply parallel texture coordinates in X and/or Y + const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill)); + aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY); + } - if(bObjectSpecificX || bObjectSpecificY) + if(bSphereX || bSphereY) + { + // apply spherical texture coordinates in X and/or Y + const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill)); + const basegfx::B3DPoint aCenter(aRange.getCenter()); + aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter, bSphereX, bSphereY); + } + + if(bObjectSpecificX || bObjectSpecificY) + { + // object-specific + for(sal_uInt32 a(0L); a < aFill.count(); a++) { - // object-specific - for(sal_uInt32 a(0L); a < aFill.count(); a++) - { - basegfx::B3DPolygon aTmpPoly(aFill.getB3DPolygon(a)); + basegfx::B3DPolygon aTmpPoly(aFill.getB3DPolygon(a)); - if(aTmpPoly.count() >= 4L) + if(aTmpPoly.count() >= 4L) + { + for(sal_uInt32 b(0L); b < 4L; b++) { - for(sal_uInt32 b(0L); b < 4L; b++) - { - basegfx::B2DPoint aPoint(aTmpPoly.getTextureCoordinate(b)); - - if(bObjectSpecificX) - { - aPoint.setX((1L == b || 2L == b) ? 1.0 : 0.0); - } + basegfx::B2DPoint aPoint(aTmpPoly.getTextureCoordinate(b)); - if(bObjectSpecificY) - { - aPoint.setY((2L == b || 3L == b) ? 1.0 : 0.0); - } + if(bObjectSpecificX) + { + aPoint.setX((1L == b || 2L == b) ? 1.0 : 0.0); + } - aTmpPoly.setTextureCoordinate(b, aPoint); + if(bObjectSpecificY) + { + aPoint.setY((2L == b || 3L == b) ? 1.0 : 0.0); } - aFill.setB3DPolygon(a, aTmpPoly); + aTmpPoly.setTextureCoordinate(b, aPoint); } + + aFill.setB3DPolygon(a, aTmpPoly); } } - - // transform texture coordinates to texture size - basegfx::B2DHomMatrix aTexMatrix; - aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY()); - aFill.transformTextureCoordiantes(aTexMatrix); } - // build vector of PolyPolygons - ::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector; + // transform texture coordinates to texture size + basegfx::B2DHomMatrix aTexMatrix; + aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY()); + aFill.transformTextureCoordiantes(aTexMatrix); + } - for(sal_uInt32 a(0L); a < aFill.count(); a++) - { - a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a))); - } + // build vector of PolyPolygons + ::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector; - // create single PolyPolygonFill primitives + for(sal_uInt32 a(0L); a < aFill.count(); a++) + { + a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a))); + } + + if(getSdrLFSAttribute().getFill()) + { + // add fill aRetval = create3DPolyPolygonFillPrimitives( - a3DPolyPolygonVector, getTransform(), getTextureSize(), - getSdr3DObjectAttribute(), *getSdrLFSAttribute().getFill(), + a3DPolyPolygonVector, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + *getSdrLFSAttribute().getFill(), getSdrLFSAttribute().getFillFloatTransGradient()); } + else + { + // create simplified 3d hit test geometry + const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0); + + aRetval = create3DPolyPolygonFillPrimitives( + a3DPolyPolygonVector, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + aSimplifiedFillAttribute, + 0); + + // encapsulate in HitTestPrimitive3D and add + const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval)); + aRetval = Primitive3DSequence(&xRef, 1L); + } // add line if(getSdrLFSAttribute().getLine()) diff --git a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx index e7d170b967e5..a83147da5022 100644 --- a/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrextrudeprimitive3d.cxx @@ -44,6 +44,8 @@ #include <basegfx/tools/canvastools.hxx> #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> #include <drawinglayer/geometry/viewinformation3d.hxx> +#include <drawinglayer/primitive3d/hittestprimitive3d.hxx> +#include <drawinglayer/attribute/sdrattribute.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -64,128 +66,149 @@ namespace drawinglayer if(rSliceVector.size()) { - // add fill - if(getSdrLFSAttribute().getFill()) - { - sal_uInt32 a; - basegfx::B3DRange aRange; + sal_uInt32 a; + basegfx::B3DRange aRange; - // decide what to create - const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()); - const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); - const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); - double fRelativeTextureWidth(1.0); - basegfx::B2DHomMatrix aTexTransform; + // decide what to create + const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()); + const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); + const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); + double fRelativeTextureWidth(1.0); + basegfx::B2DHomMatrix aTexTransform; - if(bCreateTextureCoordiantesX || bCreateTextureCoordiantesY) + if(getSdrLFSAttribute().getFill() && (bCreateTextureCoordiantesX || bCreateTextureCoordiantesY)) + { + const basegfx::B2DPolygon aFirstPolygon(maCorrectedPolyPolygon.getB2DPolygon(0L)); + const double fFrontLength(basegfx::tools::getLength(aFirstPolygon)); + const double fFrontArea(basegfx::tools::getArea(aFirstPolygon)); + const double fSqrtFrontArea(sqrt(fFrontArea)); + fRelativeTextureWidth = basegfx::fTools::equalZero(fSqrtFrontArea) ? 1.0 : fFrontLength / fSqrtFrontArea; + fRelativeTextureWidth = (double)((sal_uInt32)(fRelativeTextureWidth - 0.5)); + + if(fRelativeTextureWidth < 1.0) { - const basegfx::B2DPolygon aFirstPolygon(maCorrectedPolyPolygon.getB2DPolygon(0L)); - const double fFrontLength(basegfx::tools::getLength(aFirstPolygon)); - const double fFrontArea(basegfx::tools::getArea(aFirstPolygon)); - const double fSqrtFrontArea(sqrt(fFrontArea)); - fRelativeTextureWidth = basegfx::fTools::equalZero(fSqrtFrontArea) ? 1.0 : fFrontLength / fSqrtFrontArea; - fRelativeTextureWidth = (double)((sal_uInt32)(fRelativeTextureWidth - 0.5)); - - if(fRelativeTextureWidth < 1.0) - { - fRelativeTextureWidth = 1.0; - } - - aTexTransform.translate(-0.5, -0.5); - aTexTransform.scale(-1.0, -1.0); - aTexTransform.translate(0.5, 0.5); - aTexTransform.scale(fRelativeTextureWidth, 1.0); + fRelativeTextureWidth = 1.0; } - // create geometry - ::std::vector< basegfx::B3DPolyPolygon > aFill; - extractPlanesFromSlice(aFill, rSliceVector, - bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), false, - 0.5, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform); + aTexTransform.translate(-0.5, -0.5); + aTexTransform.scale(-1.0, -1.0); + aTexTransform.translate(0.5, 0.5); + aTexTransform.scale(fRelativeTextureWidth, 1.0); + } - // get full range - for(a = 0L; a < aFill.size(); a++) - { - aRange.expand(basegfx::tools::getRange(aFill[a])); - } + // create geometry + ::std::vector< basegfx::B3DPolyPolygon > aFill; + extractPlanesFromSlice(aFill, rSliceVector, + bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), false, + 0.5, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform); - // normal creation + // get full range + for(a = 0L; a < aFill.size(); a++) + { + aRange.expand(basegfx::tools::getRange(aFill[a])); + } + + // normal creation + if(getSdrLFSAttribute().getFill()) + { + if(::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind()) { - if(::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind()) - { - // create sphere normals - const basegfx::B3DPoint aCenter(aRange.getCenter()); + // create sphere normals + const basegfx::B3DPoint aCenter(aRange.getCenter()); - for(a = 0L; a < aFill.size(); a++) - { - aFill[a] = basegfx::tools::applyDefaultNormalsSphere(aFill[a], aCenter); - } - } - else if(::com::sun::star::drawing::NormalsKind_FLAT == getSdr3DObjectAttribute().getNormalsKind()) + for(a = 0L; a < aFill.size(); a++) { - for(a = 0L; a < aFill.size(); a++) - { - aFill[a].clearNormals(); - } + aFill[a] = basegfx::tools::applyDefaultNormalsSphere(aFill[a], aCenter); } - - if(getSdr3DObjectAttribute().getNormalsInvert()) + } + else if(::com::sun::star::drawing::NormalsKind_FLAT == getSdr3DObjectAttribute().getNormalsKind()) + { + for(a = 0L; a < aFill.size(); a++) { - // invert normals - for(a = 0L; a < aFill.size(); a++) - { - aFill[a] = basegfx::tools::invertNormals(aFill[a]); - } + aFill[a].clearNormals(); } } - // texture coordinates + if(getSdr3DObjectAttribute().getNormalsInvert()) { - // handle texture coordinates X - const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX()); - const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX())); + // invert normals + for(a = 0L; a < aFill.size(); a++) + { + aFill[a] = basegfx::tools::invertNormals(aFill[a]); + } + } + } - // handle texture coordinates Y - const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY()); - const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY())); + // texture coordinates + if(getSdrLFSAttribute().getFill()) + { + // handle texture coordinates X + const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX()); + const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX())); - if(bParallelX || bParallelY) - { - // apply parallel texture coordinates in X and/or Y + // handle texture coordinates Y + const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY()); + const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY())); - for(a = 0L; a < aFill.size(); a++) - { - aFill[a] = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill[a], aRange, bParallelX, bParallelY); - } - } + if(bParallelX || bParallelY) + { + // apply parallel texture coordinates in X and/or Y - if(bSphereX || bSphereY) + for(a = 0L; a < aFill.size(); a++) { - // apply spherical texture coordinates in X and/or Y - const basegfx::B3DPoint aCenter(aRange.getCenter()); - - for(a = 0L; a < aFill.size(); a++) - { - aFill[a] = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill[a], aCenter, bSphereX, bSphereY); - } + aFill[a] = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill[a], aRange, bParallelX, bParallelY); } + } - // transform texture coordinates to texture size - basegfx::B2DHomMatrix aTexMatrix; - aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY()); + if(bSphereX || bSphereY) + { + // apply spherical texture coordinates in X and/or Y + const basegfx::B3DPoint aCenter(aRange.getCenter()); for(a = 0L; a < aFill.size(); a++) { - aFill[a].transformTextureCoordiantes(aTexMatrix); + aFill[a] = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill[a], aCenter, bSphereX, bSphereY); } } - // create single PolyPolygonFill primitives + // transform texture coordinates to texture size + basegfx::B2DHomMatrix aTexMatrix; + aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY()); + + for(a = 0L; a < aFill.size(); a++) + { + aFill[a].transformTextureCoordiantes(aTexMatrix); + } + } + + if(getSdrLFSAttribute().getFill()) + { + // add fill aRetval = create3DPolyPolygonFillPrimitives( - aFill, getTransform(), getTextureSize(), - getSdr3DObjectAttribute(), *getSdrLFSAttribute().getFill(), + aFill, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + *getSdrLFSAttribute().getFill(), getSdrLFSAttribute().getFillFloatTransGradient()); } + else + { + // create simplified 3d hit test geometry + const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0); + + aRetval = create3DPolyPolygonFillPrimitives( + aFill, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + aSimplifiedFillAttribute, + 0); + + // encapsulate in HitTestPrimitive3D and add + const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval)); + aRetval = Primitive3DSequence(&xRef, 1L); + } // add line if(getSdrLFSAttribute().getLine()) @@ -200,7 +223,7 @@ namespace drawinglayer // sort out doubles (front and back planes when no edge rounding is done). Since // this is a line geometry merged from PolyPolygons, loop over all Polygons - for(sal_uInt32 a(0); a < nCount; a++) + for(a = 0; a < nCount; a++) { const sal_uInt32 nReducedCount(aReducedLoops.count()); const basegfx::B3DPolygon aCandidate(aVerLine.getB3DPolygon(a)); diff --git a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx index b04c90e07336..f51aa3a85e24 100644 --- a/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrlatheprimitive3d.cxx @@ -44,6 +44,8 @@ #include <basegfx/tools/canvastools.hxx> #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> #include <drawinglayer/geometry/viewinformation3d.hxx> +#include <drawinglayer/primitive3d/hittestprimitive3d.hxx> +#include <drawinglayer/attribute/sdrattribute.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -66,120 +68,140 @@ namespace drawinglayer { const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0)); const bool bClosedRotation(!bBackScale && getHorizontalSegments() && basegfx::fTools::equal(getRotation(), F_2PI)); + sal_uInt32 a; + basegfx::B3DRange aRange; - // add fill - if(getSdrLFSAttribute().getFill()) + // decide what to create + const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()); + const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); + const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); + basegfx::B2DHomMatrix aTexTransform; + + if(getSdrLFSAttribute().getFill() && (bCreateTextureCoordiantesX || bCreateTextureCoordiantesY)) { - sal_uInt32 a; - basegfx::B3DRange aRange; + aTexTransform.set(0, 0, 0.0); + aTexTransform.set(0, 1, 1.0); + aTexTransform.set(1, 0, 1.0); + aTexTransform.set(1, 1, 0.0); + + aTexTransform.translate(0.0, -0.5); + aTexTransform.scale(1.0, -1.0); + aTexTransform.translate(0.0, 0.5); + } - // decide what to create - const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind()); - const bool bCreateTextureCoordiantesX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); - const bool bCreateTextureCoordiantesY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); - basegfx::B2DHomMatrix aTexTransform; + // create geometry + ::std::vector< basegfx::B3DPolyPolygon > aFill; + extractPlanesFromSlice(aFill, rSliceVector, + bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), bClosedRotation, + 0.85, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform); - if(bCreateTextureCoordiantesX || bCreateTextureCoordiantesY) - { - aTexTransform.set(0, 0, 0.0); - aTexTransform.set(0, 1, 1.0); - aTexTransform.set(1, 0, 1.0); - aTexTransform.set(1, 1, 0.0); - - aTexTransform.translate(0.0, -0.5); - aTexTransform.scale(1.0, -1.0); - aTexTransform.translate(0.0, 0.5); - } - - // create geometry - ::std::vector< basegfx::B3DPolyPolygon > aFill; - extractPlanesFromSlice(aFill, rSliceVector, - bCreateNormals, getSmoothHorizontalNormals(), getSmoothNormals(), getSmoothLids(), bClosedRotation, - 0.85, 0.6, bCreateTextureCoordiantesX || bCreateTextureCoordiantesY, aTexTransform); + // get full range + for(a = 0L; a < aFill.size(); a++) + { + aRange.expand(basegfx::tools::getRange(aFill[a])); + } - // get full range - for(a = 0L; a < aFill.size(); a++) + // normal creation + if(getSdrLFSAttribute().getFill()) + { + if(::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind()) { - aRange.expand(basegfx::tools::getRange(aFill[a])); - } + // create sphere normals + const basegfx::B3DPoint aCenter(aRange.getCenter()); - // normal creation - { - if(::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind()) + for(a = 0L; a < aFill.size(); a++) { - // create sphere normals - const basegfx::B3DPoint aCenter(aRange.getCenter()); - - for(a = 0L; a < aFill.size(); a++) - { - aFill[a] = basegfx::tools::applyDefaultNormalsSphere(aFill[a], aCenter); - } + aFill[a] = basegfx::tools::applyDefaultNormalsSphere(aFill[a], aCenter); } - else if(::com::sun::star::drawing::NormalsKind_FLAT == getSdr3DObjectAttribute().getNormalsKind()) + } + else if(::com::sun::star::drawing::NormalsKind_FLAT == getSdr3DObjectAttribute().getNormalsKind()) + { + for(a = 0L; a < aFill.size(); a++) { - for(a = 0L; a < aFill.size(); a++) - { - aFill[a].clearNormals(); - } + aFill[a].clearNormals(); } + } - if(getSdr3DObjectAttribute().getNormalsInvert()) + if(getSdr3DObjectAttribute().getNormalsInvert()) + { + // invert normals + for(a = 0L; a < aFill.size(); a++) { - // invert normals - for(a = 0L; a < aFill.size(); a++) - { - aFill[a] = basegfx::tools::invertNormals(aFill[a]); - } + aFill[a] = basegfx::tools::invertNormals(aFill[a]); } } + } - // texture coordinates - { - // handle texture coordinates X - const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX()); - const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX())); - - // handle texture coordinates Y - const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY()); - const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY())); + // texture coordinates + if(getSdrLFSAttribute().getFill()) + { + // handle texture coordinates X + const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX()); + const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX())); - if(bParallelX || bParallelY) - { - // apply parallel texture coordinates in X and/or Y + // handle texture coordinates Y + const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY()); + const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY())); - for(a = 0L; a < aFill.size(); a++) - { - aFill[a] = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill[a], aRange, bParallelX, bParallelY); - } - } + if(bParallelX || bParallelY) + { + // apply parallel texture coordinates in X and/or Y - if(bSphereX || bSphereY) + for(a = 0L; a < aFill.size(); a++) { - // apply spherical texture coordinates in X and/or Y - const basegfx::B3DPoint aCenter(aRange.getCenter()); - - for(a = 0L; a < aFill.size(); a++) - { - aFill[a] = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill[a], aCenter, bSphereX, bSphereY); - } + aFill[a] = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill[a], aRange, bParallelX, bParallelY); } + } - // transform texture coordinates to texture size - basegfx::B2DHomMatrix aTexMatrix; - aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY()); + if(bSphereX || bSphereY) + { + // apply spherical texture coordinates in X and/or Y + const basegfx::B3DPoint aCenter(aRange.getCenter()); for(a = 0L; a < aFill.size(); a++) { - aFill[a].transformTextureCoordiantes(aTexMatrix); + aFill[a] = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill[a], aCenter, bSphereX, bSphereY); } } - // create single PolyPolygonFill primitives + // transform texture coordinates to texture size + basegfx::B2DHomMatrix aTexMatrix; + aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY()); + + for(a = 0L; a < aFill.size(); a++) + { + aFill[a].transformTextureCoordiantes(aTexMatrix); + } + } + + if(getSdrLFSAttribute().getFill()) + { + // add fill aRetval = create3DPolyPolygonFillPrimitives( - aFill, getTransform(), getTextureSize(), - getSdr3DObjectAttribute(), *getSdrLFSAttribute().getFill(), + aFill, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + *getSdrLFSAttribute().getFill(), getSdrLFSAttribute().getFillFloatTransGradient()); } + else + { + // create simplified 3d hit test geometry + const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0); + + aRetval = create3DPolyPolygonFillPrimitives( + aFill, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + aSimplifiedFillAttribute, + 0); + + // encapsulate in HitTestPrimitive3D and add + const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval)); + aRetval = Primitive3DSequence(&xRef, 1L); + } // add line if(getSdrLFSAttribute().getLine()) @@ -191,7 +213,7 @@ namespace drawinglayer const sal_uInt32 nCount(aHorLine.count()); basegfx::B3DPolyPolygon aNewLineGeometry; - for(sal_uInt32 a(1); a < nCount; a++) + for(a = 1; a < nCount; a++) { // for each loop pair create the connection edges createReducedOutlines( @@ -202,10 +224,10 @@ namespace drawinglayer aNewLineGeometry); } - for(sal_uInt32 b(0); b < nCount; b++) + for(a = 0; a < nCount; a++) { // filter hor lines for empty loops (those who have their defining point on the Y-Axis) - basegfx::B3DPolygon aCandidate(aHorLine.getB3DPolygon(b)); + basegfx::B3DPolygon aCandidate(aHorLine.getB3DPolygon(a)); aCandidate.removeDoublePoints(); if(aCandidate.count()) diff --git a/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx index 639635970c87..e27b8b43fe93 100644 --- a/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrpolypolygonprimitive3d.cxx @@ -41,6 +41,7 @@ #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> #include <basegfx/polygon/b3dpolypolygontools.hxx> #include <drawinglayer/attribute/sdrattribute.hxx> +#include <drawinglayer/primitive3d/hittestprimitive3d.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -58,18 +59,37 @@ namespace drawinglayer if(getPolyPolygon3D().count()) { - // add fill + ::std::vector< basegfx::B3DPolyPolygon > aFill; + aFill.push_back(getPolyPolygon3D()); + if(getSdrLFSAttribute().getFill()) { - // create single PolyPolygonFill primitives - ::std::vector< basegfx::B3DPolyPolygon > aFill; - aFill.push_back(getPolyPolygon3D()); - + // add fill aRetval = create3DPolyPolygonFillPrimitives( - aFill, getTransform(), getTextureSize(), - getSdr3DObjectAttribute(), *getSdrLFSAttribute().getFill(), + aFill, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + *getSdrLFSAttribute().getFill(), getSdrLFSAttribute().getFillFloatTransGradient()); } + else + { + // create simplified 3d hit test geometry + const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0); + + aRetval = create3DPolyPolygonFillPrimitives( + aFill, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + aSimplifiedFillAttribute, + 0); + + // encapsulate in HitTestPrimitive3D and add + const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval)); + aRetval = Primitive3DSequence(&xRef, 1L); + } // add line if(getSdrLFSAttribute().getLine()) diff --git a/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx b/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx index 74a5713b69e8..e7149c611dd9 100644 --- a/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx +++ b/drawinglayer/source/primitive3d/sdrsphereprimitive3d.cxx @@ -43,6 +43,8 @@ #include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx> #include <basegfx/tools/canvastools.hxx> #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> +#include <drawinglayer/primitive3d/hittestprimitive3d.hxx> +#include <drawinglayer/attribute/sdrattribute.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -58,94 +60,116 @@ namespace drawinglayer { Primitive3DSequence aRetval; const basegfx::B3DRange aUnitRange(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); + const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind() + || ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind()); + + // create unit geometry + basegfx::B3DPolyPolygon aFill(basegfx::tools::createSphereFillPolyPolygonFromB3DRange(aUnitRange, + getHorizontalSegments(), getVerticalSegments(), bCreateNormals)); + + // normal inversion + if(getSdrLFSAttribute().getFill() + && bCreateNormals + && getSdr3DObjectAttribute().getNormalsInvert() + && aFill.areNormalsUsed()) + { + // invert normals + aFill = basegfx::tools::invertNormals(aFill); + } - // add fill + // texture coordinates if(getSdrLFSAttribute().getFill()) { - const bool bCreateNormals(::com::sun::star::drawing::NormalsKind_SPECIFIC == getSdr3DObjectAttribute().getNormalsKind() - || ::com::sun::star::drawing::NormalsKind_SPHERE == getSdr3DObjectAttribute().getNormalsKind()); + // handle texture coordinates X + const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX()); + const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); + const bool bSphereX(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX()); - // create unit geometry - basegfx::B3DPolyPolygon aFill(basegfx::tools::createSphereFillPolyPolygonFromB3DRange(aUnitRange, - getHorizontalSegments(), getVerticalSegments(), bCreateNormals)); + // handle texture coordinates Y + const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY()); + const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); + const bool bSphereY(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY()); - // normal inversion - if(bCreateNormals && getSdr3DObjectAttribute().getNormalsInvert() && aFill.areNormalsUsed()) + if(bParallelX || bParallelY) { - // invert normals - aFill = basegfx::tools::invertNormals(aFill); + // apply parallel texture coordinates in X and/or Y + const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill)); + aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY); } - // texture coordinates + if(bSphereX || bObjectSpecificX || bSphereY || bObjectSpecificY) { - // handle texture coordinates X - const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionX()); - const bool bObjectSpecificX(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX()); - const bool bSphereX(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionX()); - - // handle texture coordinates Y - const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == getSdr3DObjectAttribute().getTextureProjectionY()); - const bool bObjectSpecificY(::com::sun::star::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY()); - const bool bSphereY(::com::sun::star::drawing::TextureProjectionMode_SPHERE == getSdr3DObjectAttribute().getTextureProjectionY()); + double fRelativeAngle(0.0); - if(bParallelX || bParallelY) + if(bObjectSpecificX) { - // apply parallel texture coordinates in X and/or Y - const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill)); - aFill = basegfx::tools::applyDefaultTextureCoordinatesParallel(aFill, aRange, bParallelX, bParallelY); + // Since the texture coordinates are (for historical reasons) + // different from forced to sphere texture coordinates, + // create a old version from it by rotating to old state before applying + // the texture coordinates to emulate old behaviour + fRelativeAngle = F_2PI * ((double)((getHorizontalSegments() >> 1L) - 1L) / (double)getHorizontalSegments()); + basegfx::B3DHomMatrix aRot; + aRot.rotate(0.0, fRelativeAngle, 0.0); + aFill.transform(aRot); } - if(bSphereX || bObjectSpecificX || bSphereY || bObjectSpecificY) + // apply spherical texture coordinates in X and/or Y + const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill)); + const basegfx::B3DPoint aCenter(aRange.getCenter()); + aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter, + bSphereX || bObjectSpecificX, bSphereY || bObjectSpecificY); + + if(bObjectSpecificX) { - double fRelativeAngle(0.0); - - if(bObjectSpecificX) - { - // Since the texture coordinates are (for historical reasons) - // different from forced to sphere texture coordinates, - // create a old version from it by rotating to old state before applying - // the texture coordinates to emulate old behaviour - fRelativeAngle = F_2PI * ((double)((getHorizontalSegments() >> 1L) - 1L) / (double)getHorizontalSegments()); - basegfx::B3DHomMatrix aRot; - aRot.rotate(0.0, fRelativeAngle, 0.0); - aFill.transform(aRot); - } - - // apply spherical texture coordinates in X and/or Y - const basegfx::B3DRange aRange(basegfx::tools::getRange(aFill)); - const basegfx::B3DPoint aCenter(aRange.getCenter()); - aFill = basegfx::tools::applyDefaultTextureCoordinatesSphere(aFill, aCenter, - bSphereX || bObjectSpecificX, bSphereY || bObjectSpecificY); - - if(bObjectSpecificX) - { - // rotate back again - basegfx::B3DHomMatrix aRot; - aRot.rotate(0.0, -fRelativeAngle, 0.0); - aFill.transform(aRot); - } + // rotate back again + basegfx::B3DHomMatrix aRot; + aRot.rotate(0.0, -fRelativeAngle, 0.0); + aFill.transform(aRot); } - - // transform texture coordinates to texture size - basegfx::B2DHomMatrix aTexMatrix; - aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY()); - aFill.transformTextureCoordiantes(aTexMatrix); } - // build vector of PolyPolygons - ::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector; + // transform texture coordinates to texture size + basegfx::B2DHomMatrix aTexMatrix; + aTexMatrix.scale(getTextureSize().getX(), getTextureSize().getY()); + aFill.transformTextureCoordiantes(aTexMatrix); + } - for(sal_uInt32 a(0L); a < aFill.count(); a++) - { - a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a))); - } + // build vector of PolyPolygons + ::std::vector< basegfx::B3DPolyPolygon > a3DPolyPolygonVector; - // create single PolyPolygonFill primitives + for(sal_uInt32 a(0L); a < aFill.count(); a++) + { + a3DPolyPolygonVector.push_back(basegfx::B3DPolyPolygon(aFill.getB3DPolygon(a))); + } + + if(getSdrLFSAttribute().getFill()) + { + // add fill aRetval = create3DPolyPolygonFillPrimitives( - a3DPolyPolygonVector, getTransform(), getTextureSize(), - getSdr3DObjectAttribute(), *getSdrLFSAttribute().getFill(), + a3DPolyPolygonVector, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + *getSdrLFSAttribute().getFill(), getSdrLFSAttribute().getFillFloatTransGradient()); } + else + { + // create simplified 3d hit test geometry + const attribute::SdrFillAttribute aSimplifiedFillAttribute(0.0, basegfx::BColor(), 0, 0, 0); + + aRetval = create3DPolyPolygonFillPrimitives( + a3DPolyPolygonVector, + getTransform(), + getTextureSize(), + getSdr3DObjectAttribute(), + aSimplifiedFillAttribute, + 0); + + // encapsulate in HitTestPrimitive3D and add + const Primitive3DReference xRef(new HitTestPrimitive3D(aRetval)); + aRetval = Primitive3DSequence(&xRef, 1L); + } // add line if(getSdrLFSAttribute().getLine()) diff --git a/drawinglayer/source/processor2d/canvasprocessor.cxx b/drawinglayer/source/processor2d/canvasprocessor.cxx index 394f86299b2b..0fe629545900 100644 --- a/drawinglayer/source/processor2d/canvasprocessor.cxx +++ b/drawinglayer/source/processor2d/canvasprocessor.cxx @@ -65,6 +65,17 @@ #include <basegfx/tuple/b2i64tuple.hxx> #include <basegfx/range/b2irange.hxx> #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp> +#include <com/sun/star/rendering/CompositeOperation.hpp> +#include <com/sun/star/rendering/StrokeAttributes.hpp> +#include <com/sun/star/rendering/PathJoinType.hpp> +#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> +#include <com/sun/star/rendering/TexturingMode.hpp> +#include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx> +#include <vclhelperbufferdevice.hxx> +#include <drawinglayer/primitive2d/chartprimitive2d.hxx> +#include <helperchartrenderer.hxx> +#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx> +#include <helperwrongspellrenderer.hxx> ////////////////////////////////////////////////////////////////////////////// @@ -98,13 +109,13 @@ using namespace com::sun::star; return aRetval; } - Bitmap impModifyBitmap(const ::basegfx::BColorModifier& rModifier, const Bitmap& rSource) + Bitmap impModifyBitmap(const basegfx::BColorModifier& rModifier, const Bitmap& rSource) { Bitmap aRetval(rSource); switch(rModifier.getMode()) { - case ::basegfx::BCOLORMODIFYMODE_REPLACE : + case basegfx::BCOLORMODIFYMODE_REPLACE : { aRetval = impCreateEmptyBitmapWithPattern(aRetval, Size(1L, 1L)); aRetval.Erase(Color(rModifier.getBColor())); @@ -122,7 +133,7 @@ using namespace com::sun::star; for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++) { const Color aColor = pContent->GetPixel(y, x); - const ::basegfx::BColor aBColor(rModifier.getModifiedColor(aColor.getBColor())); + const basegfx::BColor aBColor(rModifier.getModifiedColor(aColor.getBColor())); pContent->SetPixel(y, x, BitmapColor(Color(aBColor))); } } @@ -137,20 +148,20 @@ using namespace com::sun::star; return aRetval; } - Bitmap impModifyBitmap(const ::basegfx::BColorModifierStack& rBColorModifierStack, const Bitmap& rSource) + Bitmap impModifyBitmap(const basegfx::BColorModifierStack& rBColorModifierStack, const Bitmap& rSource) { Bitmap aRetval(rSource); for(sal_uInt32 a(rBColorModifierStack.count()); a; ) { - const ::basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a); + const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a); aRetval = impModifyBitmap(rModifier, aRetval); } return aRetval; } - sal_uInt32 impCalcGradientSteps(sal_uInt32 nSteps, const ::basegfx::B2DRange& rRange, sal_uInt32 nMaxDist) + sal_uInt32 impCalcGradientSteps(sal_uInt32 nSteps, const basegfx::B2DRange& rRange, sal_uInt32 nMaxDist) { if(nSteps == 0L) nSteps = (sal_uInt32)(rRange.getWidth() + rRange.getHeight()) / 8; @@ -169,10 +180,10 @@ using namespace com::sun::star; } void canvasProcessor::impDrawGradientSimple( - const ::basegfx::B2DPolyPolygon& rTargetForm, - const ::std::vector< ::basegfx::B2DHomMatrix >& rMatrices, - const ::std::vector< ::basegfx::BColor >& rColors, - const ::basegfx::B2DPolygon& rUnitPolygon) + const basegfx::B2DPolyPolygon& rTargetForm, + const ::std::vector< basegfx::B2DHomMatrix >& rMatrices, + const ::std::vector< basegfx::BColor >& rColors, + const basegfx::B2DPolygon& rUnitPolygon) { uno::Reference< rendering::XPolyPolygon2D > xPoly( basegfx::unotools::xPolyPolygonFromB2DPolygon( @@ -186,7 +197,7 @@ using namespace com::sun::star; for(sal_uInt32 a(0L); a < rColors.size(); a++) { // set correct color - const ::basegfx::BColor aFillColor(rColors[a]); + const basegfx::BColor aFillColor(rColors[a]); maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence( mxCanvas->getDevice(), @@ -211,10 +222,10 @@ using namespace com::sun::star; } void canvasProcessor::impDrawGradientComplex( - const ::basegfx::B2DPolyPolygon& rTargetForm, - const ::std::vector< ::basegfx::B2DHomMatrix >& rMatrices, - const ::std::vector< ::basegfx::BColor >& rColors, - const ::basegfx::B2DPolygon& rUnitPolygon) + const basegfx::B2DPolyPolygon& rTargetForm, + const ::std::vector< basegfx::B2DHomMatrix >& rMatrices, + const ::std::vector< basegfx::BColor >& rColors, + const basegfx::B2DPolygon& rUnitPolygon) { uno::Reference< rendering::XPolyPolygon2D > xPoly( basegfx::unotools::xPolyPolygonFromB2DPolygon( @@ -233,7 +244,7 @@ using namespace com::sun::star; // set correct color if(rColors.size() > a) { - const ::basegfx::BColor aFillColor(rColors[a]); + const basegfx::BColor aFillColor(rColors[a]); maRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence( mxCanvas->getDevice(), @@ -253,19 +264,19 @@ using namespace com::sun::star; } void canvasProcessor::impDrawGradient( - const ::basegfx::B2DPolyPolygon& rTargetForm, + const basegfx::B2DPolyPolygon& rTargetForm, ::drawinglayer::primitive::GradientStyle eGradientStyle, sal_uInt32 nSteps, - const ::basegfx::BColor& rStart, - const ::basegfx::BColor& rEnd, + const basegfx::BColor& rStart, + const basegfx::BColor& rEnd, double fBorder, double fAngle, double fOffsetX, double fOffsetY, bool bSimple) { fprintf(stderr,"impDrawGradient\n"); - ::basegfx::B2DPolyPolygon aTmp(rTargetForm); + basegfx::B2DPolyPolygon aTmp(rTargetForm); aTmp.transform( maWorldToView ); - const ::basegfx::B2DRange aOutlineRangePixel(::basegfx::tools::getRange(aTmp)); - const ::basegfx::B2DRange aOutlineRange(::basegfx::tools::getRange(rTargetForm)); + const basegfx::B2DRange aOutlineRangePixel(basegfx::tools::getRange(aTmp)); + const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(rTargetForm)); fprintf(stderr,"impDrawGradient: #%d\n",nSteps); @@ -283,7 +294,7 @@ using namespace com::sun::star; { fprintf(stderr,"native gradient #1\n"); - ::basegfx::B2DHomMatrix aTextureTransformation; + basegfx::B2DHomMatrix aTextureTransformation; rendering::Texture aTexture; aTexture.RepeatModeX = rendering::TexturingMode::CLAMP; @@ -385,7 +396,7 @@ using namespace com::sun::star; // we multiply with that as above for // nScaleX) const double nScale( - ::basegfx::pruneScaleValue( + basegfx::pruneScaleValue( fabs( rBounds.getHeight()*sin(fAngle) ) + fabs( rBounds.getWidth()*cos(fAngle) ))); @@ -553,7 +564,7 @@ using namespace com::sun::star; aTextureTransformation.translate( rBounds.getMinX(), rBounds.getMinY() ); - ::basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform, + basegfx::unotools::affineMatrixFromHomMatrix( aTexture.AffineTransform, aTextureTransformation ); uno::Sequence< rendering::Texture > aSeq(1); aSeq[0] = aTexture; @@ -578,20 +589,20 @@ using namespace com::sun::star; sal_uInt32((rStart.getMaximumDistance(rEnd) * 127.5) + 0.5)); - ::std::vector< ::basegfx::B2DHomMatrix > aMatrices; - ::std::vector< ::basegfx::BColor > aColors; - ::basegfx::B2DPolygon aUnitPolygon; + ::std::vector< basegfx::B2DHomMatrix > aMatrices; + ::std::vector< basegfx::BColor > aColors; + basegfx::B2DPolygon aUnitPolygon; if( drawinglayer::primitive::GRADIENTSTYLE_RADIAL == eGradientStyle || drawinglayer::primitive::GRADIENTSTYLE_ELLIPTICAL == eGradientStyle) { - const ::basegfx::B2DPoint aCircleCenter(0.5, 0.5); - aUnitPolygon = ::basegfx::tools::createPolygonFromEllipse(aCircleCenter, 0.5, 0.5); - aUnitPolygon = ::basegfx::tools::adaptiveSubdivideByAngle(aUnitPolygon); + const basegfx::B2DPoint aCircleCenter(0.5, 0.5); + aUnitPolygon = basegfx::tools::createPolygonFromEllipse(aCircleCenter, 0.5, 0.5); + aUnitPolygon = basegfx::tools::adaptiveSubdivideByAngle(aUnitPolygon); } else { - aUnitPolygon = ::basegfx::tools::createPolygonFromRect( + aUnitPolygon = basegfx::tools::createPolygonFromRect( basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)); } @@ -705,7 +716,7 @@ using namespace com::sun::star; uno::Sequence<double>(&rTextCandidate.getDXArray()[0], rTextCandidate.getDXArray().size() )); - const ::basegfx::BColor aRGBColor( + const basegfx::BColor aRGBColor( maBColorModifierStack.getModifiedColor( rTextCandidate.getFontColor())); @@ -722,7 +733,7 @@ using namespace com::sun::star; // direct draw of hairline void canvasProcessor::impRender_POHL(const polygonHairlinePrimitive& rPolygonCandidate) { - const ::basegfx::BColor aRGBColor( + const basegfx::BColor aRGBColor( maBColorModifierStack.getModifiedColor( rPolygonCandidate.getBColor())); @@ -815,9 +826,9 @@ using namespace com::sun::star; void canvasProcessor::impRender_PPLG(const polyPolygonGradientPrimitive& rPolygonCandidate) { const fillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient()); - ::basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor())); - ::basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor())); - ::basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); + basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor())); + basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor())); + basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); if(aStartColor == aEndColor) { @@ -847,7 +858,7 @@ using namespace com::sun::star; // direct draw of PolyPolygon with color void canvasProcessor::impRender_PPLC(const polyPolygonColorPrimitive& rPolygonCandidate) { - const ::basegfx::BColor aRGBColor( + const basegfx::BColor aRGBColor( maBColorModifierStack.getModifiedColor( rPolygonCandidate.getBColor())); @@ -872,8 +883,8 @@ using namespace com::sun::star; // vclprocessor.cxx if(maBColorModifierStack.count()) { - const ::basegfx::BColor aRGBBaseColor(0, 0, 0); - const ::basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor)); + const basegfx::BColor aRGBBaseColor(0, 0, 0); + const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor)); aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor)); } else @@ -952,8 +963,8 @@ using namespace com::sun::star; uno::UNO_QUERY_THROW); // remember last worldToView and add pixel offset - ::basegfx::B2DHomMatrix aLastWorldToView(maWorldToView); - ::basegfx::B2DHomMatrix aPixelOffset; + basegfx::B2DHomMatrix aLastWorldToView(maWorldToView); + basegfx::B2DHomMatrix aPixelOffset; aPixelOffset.translate(aRange.getMinX(), aRange.getMinY()); setWorldToView(aPixelOffset * maWorldToView); @@ -994,7 +1005,7 @@ using namespace com::sun::star; void canvasProcessor::impRender_TRN2(const transformPrimitive& rTransformCandidate) { // remember current transformation - ::basegfx::B2DHomMatrix aLastWorldToView(maWorldToView); + basegfx::B2DHomMatrix aLastWorldToView(maWorldToView); // create new transformations setWorldToView(maWorldToView * rTransformCandidate.getTransformation()); @@ -1009,7 +1020,7 @@ using namespace com::sun::star; // marker void canvasProcessor::impRender_MARK(const markerPrimitive& rMarkCandidate) { - const ::basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rMarkCandidate.getRGBColor())); + const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rMarkCandidate.getRGBColor())); canvas::tools::initRenderState(maMarkerRenderState); maMarkerRenderState.DeviceColor = basegfx::unotools::colorToDoubleSequence( @@ -1274,9 +1285,627 @@ namespace drawinglayer { namespace processor2d { + ////////////////////////////////////////////////////////////////////////////// + // single primitive renderers + + void canvasProcessor2D::impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate) + { + const primitive2d::Primitive2DSequence& rChildren = rMaskCandidate.getChildren(); + static bool bUseMaskBitmapMethod(true); + + if(rChildren.hasElements()) + { + basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); + + if(!aMask.count()) + { + // no mask, no clipping. recursively paint content + process(rChildren); + } + else + { + // there are principally two methods for implementing the mask primitive. One + // is to set a clip polygon at the canvas, the other is to create and use a + // alpha-using XBitmap for content and draw the mask as alpha. Both have their + // advantages and disadvantages, so here are both with a bool allowing simple + // change + if(bUseMaskBitmapMethod) + { + // get logic range of transparent part, clip with ViewRange + basegfx::B2DRange aLogicRange(aMask.getB2DRange()); + aLogicRange.intersect(getViewInformation2D().getViewport()); + + if(!aLogicRange.isEmpty()) + { + // get discrete range of transparent part + basegfx::B2DRange aDiscreteRange(aLogicRange); + aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation()); + + // expand to next covering discrete values (pixel bounds) + aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY()))); + aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY()))); + + // use VCL-based buffer device + impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false); + + if(aBufferDevice.isVisible()) + { + // remember current OutDev, Canvas and ViewInformation + OutputDevice* pLastOutputDevice = mpOutputDevice; + uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas); + const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D()); + + // prepare discrete offset for XBitmap + basegfx::B2DHomMatrix aDiscreteOffset; + aDiscreteOffset.translate(-aDiscreteRange.getMinX(), -aDiscreteRange.getMinY()); + + // create new local ViewInformation2D with new transformation + const geometry::ViewInformation2D aViewInformation2D( + getViewInformation2D().getObjectTransformation(), + aDiscreteOffset * getViewInformation2D().getViewTransformation(), + getViewInformation2D().getViewport(), + getViewInformation2D().getVisualizedPage(), + getViewInformation2D().getViewTime(), + getViewInformation2D().getExtendedInformationSequence()); + updateViewInformation(aViewInformation2D); + + // set OutDev and Canvas to content target + mpOutputDevice = &aBufferDevice.getContent(); + mxCanvas = mpOutputDevice->GetCanvas(); + canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation()); + + // if ViewState transform is changed, the clipping polygon needs to be adapted, too + const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon); + + if(maClipPolyPolygon.count()) + { + maClipPolyPolygon.transform(aDiscreteOffset); + maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon); + } + + // paint content + process(rChildren); + + // draw mask + const basegfx::BColor aBlack(0.0, 0.0, 0.0); + maRenderState.DeviceColor = aBlack.colorToDoubleSequence(mxCanvas->getDevice()); + + if(getOptionsDrawinglayer().IsAntiAliasing()) + { + // with AA, use 8bit AlphaMask to get nice borders + VirtualDevice& rAlpha = aBufferDevice.getAlpha(); + rAlpha.GetCanvas()->fillPolyPolygon( + basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask), + maViewState, maRenderState); + } + else + { + // No AA, use 1bit mask + VirtualDevice& rMask = aBufferDevice.getMask(); + rMask.GetCanvas()->fillPolyPolygon( + basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask), + maViewState, maRenderState); + } + + // back to old color stack, OutDev, Canvas and ViewTransform + mpOutputDevice = pLastOutputDevice; + mxCanvas = xLastCanvas; + updateViewInformation(aLastViewInformation2D); + canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation()); + + // restore clipping polygon + maClipPolyPolygon = aOldClipPolyPolygon; + + if(maClipPolyPolygon.count()) + { + maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon); + } + + // dump buffer to outdev + aBufferDevice.paint(); + } + } + } + else + { + // transform new mask polygon to view coordinates for processing. All masks + // are processed in view coordinates and clipped against each other evtl. to + // create multi-clips + aMask.transform(getViewInformation2D().getObjectTransformation()); + + // remember last current clip polygon + const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon); + + if(maClipPolyPolygon.count()) + { + // there is already a clip polygon set; build clipped union of + // current mask polygon and new one + maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false); + } + else + { + // use mask directly + maClipPolyPolygon = aMask; + } + + // set at ViewState + if(maClipPolyPolygon.count()) + { + // set new as clip polygon + maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon); + } + else + { + // empty, reset + maViewState.Clip.clear(); + } + + // paint content + process(rChildren); + + // restore local current to rescued clip polygon + maClipPolyPolygon = aLastClipPolyPolygon; + + // set at ViewState + if(maClipPolyPolygon.count()) + { + // set new as clip polygon + maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon); + } + else + { + // empty, reset + maViewState.Clip.clear(); + } + } + } + } + } + + void canvasProcessor2D::impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate) + { + GDIMetaFile aMetaFile; + + if(maBColorModifierStack.count()) + { + const basegfx::BColor aRGBBaseColor(0, 0, 0); + const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor)); + aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor)); + } + else + { + aMetaFile = rMetaCandidate.getMetaFile(); + } + + cppcanvas::BitmapCanvasSharedPtr pCanvas(cppcanvas::VCLFactory::getInstance().createCanvas( + uno::Reference<rendering::XBitmapCanvas>(mxCanvas, uno::UNO_QUERY_THROW))); + cppcanvas::RendererSharedPtr pMtfRenderer(cppcanvas::VCLFactory::getInstance().createRenderer( + pCanvas, aMetaFile, cppcanvas::Renderer::Parameters())); + + if(pMtfRenderer) + { + pCanvas->setTransformation(getViewInformation2D().getObjectToViewTransformation()); + pMtfRenderer->setTransformation(rMetaCandidate.getTransform()); + pMtfRenderer->draw(); + } + } + + void canvasProcessor2D::impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate) + { + if(rTextCandidate.getTextLength()) + { + double fShearX(0.0); + { + const basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation() * rTextCandidate.getTextTransform()); + basegfx::B2DVector aScale, aTranslate; + double fRotate; + aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX); + } + + if(!basegfx::fTools::equalZero(fShearX)) + { + // text is sheared. As long as the canvas renderers do not support this, + // use the decomposed primitive + process(rTextCandidate.get2DDecomposition(getViewInformation2D())); + } + else + { + const primitive2d::FontAttributes& rFontAttrs(rTextCandidate.getFontAttributes()); + rendering::FontRequest aFontRequest; + + aFontRequest.FontDescription.FamilyName = rFontAttrs.getFamilyName(); + aFontRequest.FontDescription.StyleName = rFontAttrs.getStyleName(); + aFontRequest.FontDescription.IsSymbolFont = rFontAttrs.getSymbol() ? util::TriState_YES : util::TriState_NO; + aFontRequest.FontDescription.IsVertical = rFontAttrs.getVertical() ? util::TriState_YES : util::TriState_NO; + // TODO(F2): improve vclenum->panose conversion + aFontRequest.FontDescription.FontDescription.Weight = static_cast< sal_uInt8 >(rFontAttrs.getWeight()); + aFontRequest.FontDescription.FontDescription.Letterform = rFontAttrs.getItalic() ? 9 : 0; + + // init CellSize to 1.0, else a default font height will be used + aFontRequest.CellSize = 1.0; + aFontRequest.Locale = rTextCandidate.getLocale(); + + // font matrix should only be used for glyph rotations etc. + com::sun::star::geometry::Matrix2D aFontMatrix; + canvas::tools::setIdentityMatrix2D(aFontMatrix); + + uno::Reference<rendering::XCanvasFont> xFont(mxCanvas->createFont( + aFontRequest, uno::Sequence< beans::PropertyValue >(), aFontMatrix)); + + if(xFont.is()) + { + // got a font, now try to get a TextLayout + const rendering::StringContext aStringContext( + rTextCandidate.getText(), rTextCandidate.getTextPosition(), rTextCandidate.getTextLength()); + uno::Reference<rendering::XTextLayout> xLayout(xFont->createTextLayout( + aStringContext, com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0)); + + if(xLayout.is()) + { + // got a text layout, apply DXArray if given + const ::std::vector< double >& rDXArray = rTextCandidate.getDXArray(); + const sal_uInt32 nDXCount(rDXArray.size()); + + if(nDXCount) + { + // DXArray does not need to be adapted to getTextPosition/getTextLength, + // it is already provided correctly + const uno::Sequence< double > aDXSequence(&rDXArray[0], nDXCount); + xLayout->applyLogicalAdvancements(aDXSequence); + } + + // set text color + const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor())); + maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice()); + + // set text transformation + canvas::tools::setRenderStateTransform(maRenderState, + getViewInformation2D().getObjectTransformation() * rTextCandidate.getTextTransform()); + + // paint + mxCanvas->drawTextLayout(xLayout, maViewState, maRenderState); + } + } + } + } + } + + void canvasProcessor2D::impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate) + { + // apply possible color modification to BitmapEx + BitmapEx aModifiedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rBitmapCandidate.getBitmapEx())); + + if(aModifiedBitmapEx.IsEmpty()) + { + // replace with color filled polygon + const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor())); + const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + + maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice()); + canvas::tools::setRenderStateTransform(maRenderState, + getViewInformation2D().getObjectTransformation() * rBitmapCandidate.getTransform()); + + mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( + mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState); + } + else + { + // adapt object's transformation to the correct scale + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + basegfx::B2DHomMatrix aNewMatrix; + const Size aSizePixel(aModifiedBitmapEx.GetSizePixel()); + + if(0 != aSizePixel.Width() && 0 != aSizePixel.Height()) + { + rBitmapCandidate.getTransform().decompose(aScale, aTranslate, fRotate, fShearX); + aNewMatrix.scale(aScale.getX() / aSizePixel.Width(), aScale.getY() / aSizePixel.Height()); + aNewMatrix.shearX(fShearX); + aNewMatrix.rotate(fRotate); + aNewMatrix.translate(aTranslate.getX(), aTranslate.getY()); + + canvas::tools::setRenderStateTransform(maRenderState, + getViewInformation2D().getObjectTransformation() * aNewMatrix); + + mxCanvas->drawBitmap( + vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aModifiedBitmapEx), + maViewState, maRenderState); + } + } + } + + void canvasProcessor2D::impRenderAlphaPrimitive2D(const primitive2d::AlphaPrimitive2D& rAlphaCandidate) + { + const primitive2d::Primitive2DSequence& rChildren = rAlphaCandidate.getChildren(); + const primitive2d::Primitive2DSequence& rAlpha = rAlphaCandidate.getAlpha(); + + if(rChildren.hasElements() && rAlpha.hasElements()) + { + // get logic range of transparent part and clip with ViewRange + basegfx::B2DRange aLogicRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rChildren, getViewInformation2D())); + aLogicRange.intersect(getViewInformation2D().getViewport()); + + if(!aLogicRange.isEmpty()) + { + // get discrete range of transparent part + basegfx::B2DRange aDiscreteRange(aLogicRange); + aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation()); + + // expand to next covering discrete values (pixel bounds) + aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY()))); + aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY()))); + + // use VCL-based buffer device + impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false); + + if(aBufferDevice.isVisible()) + { + // remember current OutDev, Canvas and ViewInformation + OutputDevice* pLastOutputDevice = mpOutputDevice; + uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas); + const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D()); + + // prepare discrete offset for XBitmap + basegfx::B2DHomMatrix aDiscreteOffset; + aDiscreteOffset.translate(-aDiscreteRange.getMinX(), -aDiscreteRange.getMinY()); + + // create new local ViewInformation2D with new transformation + const geometry::ViewInformation2D aViewInformation2D( + getViewInformation2D().getObjectTransformation(), + aDiscreteOffset * getViewInformation2D().getViewTransformation(), + getViewInformation2D().getViewport(), + getViewInformation2D().getVisualizedPage(), + getViewInformation2D().getViewTime(), + getViewInformation2D().getExtendedInformationSequence()); + updateViewInformation(aViewInformation2D); + + // set OutDev and Canvas to content target + mpOutputDevice = &aBufferDevice.getContent(); + mxCanvas = mpOutputDevice->GetCanvas(); + canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation()); + + // if ViewState transform is changed, the clipping polygon needs to be adapted, too + const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon); + + if(maClipPolyPolygon.count()) + { + maClipPolyPolygon.transform(aDiscreteOffset); + maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon); + } + + // paint content + process(rChildren); + + // set to mask + mpOutputDevice = &aBufferDevice.getAlpha(); + mxCanvas = mpOutputDevice->GetCanvas(); + canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation()); + + // when painting alpha masks, reset the color stack + basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack); + maBColorModifierStack = basegfx::BColorModifierStack(); + + // paint mask to it (always with alpha intensities, evtl. with AA) + process(rAlpha); + + // back to old color stack, OutDev, Canvas and ViewTransform + maBColorModifierStack = aLastBColorModifierStack; + mpOutputDevice = pLastOutputDevice; + mxCanvas = xLastCanvas; + updateViewInformation(aLastViewInformation2D); + canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation()); + + // restore clipping polygon + maClipPolyPolygon = aOldClipPolyPolygon; + + if(maClipPolyPolygon.count()) + { + maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon); + } + + // dump buffer to outdev + aBufferDevice.paint(); + } + } + } + } + + void canvasProcessor2D::impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive) + { + // support direct fat line geometry. This moves the decomposition to the canvas. + // As long as our canvases are used (which also use basegfx tooling) this makes + // no difference, but potentially canvases may better support this + static bool bSupportFatLineDirectly(true); + bool bOutputDone(false); + + if(bSupportFatLineDirectly) + { + const attribute::LineAttribute& rLineAttribute = rPolygonStrokePrimitive.getLineAttribute(); + const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokePrimitive.getStrokeAttribute(); + + if(0.0 < rLineAttribute.getWidth() || 0 != rStrokeAttribute.getDotDashArray().size()) + { + rendering::StrokeAttributes aStrokeAttribute; + + aStrokeAttribute.StrokeWidth = rLineAttribute.getWidth(); + aStrokeAttribute.MiterLimit = 15.0; // degrees; maybe here (15.0 * F_PI180) is needed, not clear in the documentation + const ::std::vector< double >& rDotDashArray = rStrokeAttribute.getDotDashArray(); + + if(rDotDashArray.size()) + { + aStrokeAttribute.DashArray = uno::Sequence< double >(&rDotDashArray[0], rDotDashArray.size()); + } + + switch(rLineAttribute.getLineJoin()) + { + default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE + aStrokeAttribute.JoinType = rendering::PathJoinType::NONE; + break; + case basegfx::B2DLINEJOIN_BEVEL: + aStrokeAttribute.JoinType = rendering::PathJoinType::BEVEL; + break; + case basegfx::B2DLINEJOIN_MITER: + aStrokeAttribute.JoinType = rendering::PathJoinType::MITER; + break; + case basegfx::B2DLINEJOIN_ROUND: + aStrokeAttribute.JoinType = rendering::PathJoinType::ROUND; + break; + } + + const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor())); + maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice()); + canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation()); + + mxCanvas->strokePolyPolygon( + basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonStrokePrimitive.getB2DPolygon()), + maViewState, maRenderState, aStrokeAttribute); + + bOutputDone = true; + } + } + + if(!bOutputDone) + { + // process decomposition + process(rPolygonStrokePrimitive.get2DDecomposition(getViewInformation2D())); + } + } + + void canvasProcessor2D::impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D) + { + // support tiled fills directly when tiling is on + static bool bSupportFillBitmapDirectly(true); + bool bOutputDone(false); + + if(bSupportFillBitmapDirectly) + { + const attribute::FillBitmapAttribute& rFillBitmapAttribute = rFillBitmapPrimitive2D.getFillBitmap(); + + if(rFillBitmapAttribute.getTiling()) + { + // apply possible color modification to Bitmap + const BitmapEx aChangedBitmapEx(impModifyBitmapEx(maBColorModifierStack, BitmapEx(rFillBitmapAttribute.getBitmap()))); + + if(aChangedBitmapEx.IsEmpty()) + { + // replace with color filled polygon + const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor())); + const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + + maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice()); + canvas::tools::setRenderStateTransform(maRenderState, + getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation()); + + mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( + mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState); + } + else + { + const Size aSizePixel(aChangedBitmapEx.GetSizePixel()); + + if(0 != aSizePixel.Width() && 0 != aSizePixel.Height()) + { + // create texture matrix from texture to object (where object is unit square here), + // so use values directly + basegfx::B2DHomMatrix aTextureMatrix; + aTextureMatrix.scale( + rFillBitmapAttribute.getSize().getX(), + rFillBitmapAttribute.getSize().getY()); + aTextureMatrix.translate( + rFillBitmapAttribute.getTopLeft().getX(), + rFillBitmapAttribute.getTopLeft().getY()); + + // create and fill texture + rendering::Texture aTexture; + + basegfx::unotools::affineMatrixFromHomMatrix(aTexture.AffineTransform, aTextureMatrix); + aTexture.Alpha = 1.0; + aTexture.Bitmap = vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aChangedBitmapEx); + aTexture.RepeatModeX = rendering::TexturingMode::REPEAT; + aTexture.RepeatModeY = rendering::TexturingMode::REPEAT; + + // canvas needs a polygon to fill, create unit rectangle polygon + const basegfx::B2DPolygon aOutlineRectangle(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + + // set primitive's transformation as render state transform + canvas::tools::setRenderStateTransform(maRenderState, + getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation()); + + // put texture into a uno sequence for handover + uno::Sequence< rendering::Texture > aSeq(1); + aSeq[0] = aTexture; + + // draw textured rectangle + mxCanvas->fillTexturedPolyPolygon( + basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aOutlineRectangle)), + maViewState, maRenderState, aSeq); + } + } + + bOutputDone = true; + } + } + + if(!bOutputDone) + { + // process decomposition + process(rFillBitmapPrimitive2D.get2DDecomposition(getViewInformation2D())); + } + } + + void canvasProcessor2D::impRenderUnifiedAlphaPrimitive2D(const primitive2d::UnifiedAlphaPrimitive2D& rUniAlphaCandidate) + { + const primitive2d::Primitive2DSequence rChildren = rUniAlphaCandidate.getChildren(); + + if(rChildren.hasElements()) + { + bool bOutputDone(false); + + // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case, + // use the fillPolyPolygon method with correctly set alpha. This is a often used + // case, so detectiong it is valuable + if(1 == rChildren.getLength()) + { + const primitive2d::Primitive2DReference xReference(rChildren[0]); + const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get()); + + if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitiveID()) + { + // direct draw of PolyPolygon with color and transparence + const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor())); + + // add alpha modulation value to DeviceColor + uno::Sequence< double > aColor(4); + + aColor[0] = aPolygonColor.getRed(); + aColor[1] = aPolygonColor.getGreen(); + aColor[2] = aPolygonColor.getBlue(); + aColor[3] = 1.0 - rUniAlphaCandidate.getAlpha(); + maRenderState.DeviceColor = aColor; + + canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation()); + mxCanvas->fillPolyPolygon( + basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), pPoPoColor->getB2DPolyPolygon()), + maViewState, maRenderState); + bOutputDone = true; + } + } + + if(!bOutputDone) + { + // process decomposition. This will be decomposed to an AlphaPrimitive2D + // with the same child context and a single polygon for alpha context. This could be + // directly handled here with known VCL-buffer technology, but would only + // make a small difference compared to directly rendering the AlphaPrimitive2D + // using impRenderAlphaPrimitive2D above. + process(rUniAlphaCandidate.get2DDecomposition(getViewInformation2D())); + } + } + } ////////////////////////////////////////////////////////////////////////////// // internal processing support + void canvasProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { switch(rCandidate.getPrimitiveID()) @@ -1288,7 +1917,7 @@ namespace drawinglayer const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice()); - canvas::tools::setIdentityAffineMatrix2D(maRenderState.AffineTransform); + canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation()); mxCanvas->drawPolyPolygon( basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolygon()), maViewState, maRenderState); @@ -1302,7 +1931,7 @@ namespace drawinglayer const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); maRenderState.DeviceColor = aPolygonColor.colorToDoubleSequence(mxCanvas->getDevice()); - canvas::tools::setIdentityAffineMatrix2D(maRenderState.AffineTransform); + canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation()); mxCanvas->fillPolyPolygon( basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolyPolygon()), maViewState, maRenderState); @@ -1325,71 +1954,8 @@ namespace drawinglayer } case PRIMITIVE2D_ID_MASKPRIMITIVE2D : { - // mask group. Special handling for MetaFiles. - const primitive2d::MaskPrimitive2D& rMaskCandidate = static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate); - - if(rMaskCandidate.getChildren().hasElements()) - { - basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); - - if(aMask.count()) - { - // transform new mask polygon to World coordinates for processing. All masks - // are processed in World coordinates and clipped against each other evtl. to - // create multi-clips - aMask.transform(getViewInformation2D().getObjectTransformation()); - - // remember last current clip polygon - const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon); - - if(maClipPolyPolygon.count()) - { - // there is already a clip polygon set; build clipped union of - // current mask polygon and new one - maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false); - } - else - { - // use mask directly - maClipPolyPolygon = aMask; - } - - // set at ViewState - if(maClipPolyPolygon.count()) - { - // set new as clip polygon - maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon); - } - else - { - // empty, reset - maViewState.Clip.clear(); - } - - // recursively paint content - process(rMaskCandidate.getChildren()); - - // restore local current to rescued clip polygon - maClipPolyPolygon = aLastClipPolyPolygon; - - // set at ViewState - if(maClipPolyPolygon.count()) - { - // set new as clip polygon - maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon); - } - else - { - // empty, reset - maViewState.Clip.clear(); - } - } - else - { - // no mask, no clipping. recursively paint content - process(rMaskCandidate.getChildren()); - } - } + // mask group + impRenderMaskPrimitive2D(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate)); break; } @@ -1410,7 +1976,7 @@ namespace drawinglayer updateViewInformation(aViewInformation2D); // set at canvas - canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getObjectToViewTransformation()); + canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation()); // proccess content process(rTransformCandidate.getChildren()); @@ -1419,7 +1985,7 @@ namespace drawinglayer updateViewInformation(aLastViewInformation2D); // restore at canvas - canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getObjectToViewTransformation()); + canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation()); break; } @@ -1451,31 +2017,7 @@ namespace drawinglayer case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D : { // MetaFile primitive - const primitive2d::MetafilePrimitive2D& rMetaCandidate = static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate); - GDIMetaFile aMetaFile; - - if(maBColorModifierStack.count()) - { - const ::basegfx::BColor aRGBBaseColor(0, 0, 0); - const ::basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor)); - aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor)); - } - else - { - aMetaFile = rMetaCandidate.getMetaFile(); - } - - cppcanvas::BitmapCanvasSharedPtr pCanvas(cppcanvas::VCLFactory::getInstance().createCanvas( - uno::Reference<rendering::XBitmapCanvas>(mxCanvas, uno::UNO_QUERY_THROW))); - cppcanvas::RendererSharedPtr pMtfRenderer(cppcanvas::VCLFactory::getInstance().createRenderer( - pCanvas, aMetaFile, cppcanvas::Renderer::Parameters())); - - if(pMtfRenderer) - { - pCanvas->setTransformation(getViewInformation2D().getObjectToViewTransformation()); - pMtfRenderer->setTransformation(rMetaCandidate.getTransform()); - pMtfRenderer->draw(); - } + impRenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate)); break; } @@ -1487,7 +2029,7 @@ namespace drawinglayer // set point color const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor())); maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice()); - canvas::tools::setIdentityAffineMatrix2D(maRenderState.AffineTransform); + canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation()); const std::vector< basegfx::B2DPoint >& rPointVector = rPointArrayCandidate.getPositions(); const sal_uInt32 nPointCount(rPointVector.size()); @@ -1503,259 +2045,90 @@ namespace drawinglayer case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D : { // TextSimplePortion primitive - const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate = static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate); - - if(rTextCandidate.getTextLength()) - { - const primitive2d::FontAttributes& rFontAttrs(rTextCandidate.getFontAttributes()); - rendering::FontRequest aFontRequest; - - aFontRequest.FontDescription.FamilyName = rFontAttrs.getFamilyName(); - aFontRequest.FontDescription.StyleName = rFontAttrs.getStyleName(); - aFontRequest.FontDescription.IsSymbolFont = rFontAttrs.getSymbol() ? util::TriState_YES : util::TriState_NO; - aFontRequest.FontDescription.IsVertical = rFontAttrs.getVertical() ? util::TriState_YES : util::TriState_NO; - // TODO(F2): improve vclenum->panose conversion - aFontRequest.FontDescription.FontDescription.Weight = static_cast< sal_uInt8 >(rFontAttrs.getWeight()); - aFontRequest.FontDescription.FontDescription.Letterform = rFontAttrs.getItalic() ? 9 : 0; - - // init CellSize to 1.0, else a default font height will be used - aFontRequest.CellSize = 1.0; - aFontRequest.Locale = rTextCandidate.getLocale(); - - // font matrix should only be used for glyph rotations etc. - com::sun::star::geometry::Matrix2D aFontMatrix; - canvas::tools::setIdentityMatrix2D(aFontMatrix); - - uno::Reference<rendering::XCanvasFont> xFont(mxCanvas->createFont( - aFontRequest, uno::Sequence< beans::PropertyValue >(), aFontMatrix)); - - if(xFont.is()) - { - // got a font, now try to get a TextLayout - const rendering::StringContext aStringContext( - rTextCandidate.getText(), rTextCandidate.getTextPosition(), rTextCandidate.getTextLength()); - uno::Reference<rendering::XTextLayout> xLayout(xFont->createTextLayout( - aStringContext, com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0)); - - if(xLayout.is()) - { - // got a text layout, apply DXArray if given - const ::std::vector< double >& rDXArray = rTextCandidate.getDXArray(); - const sal_uInt32 nDXCount(rDXArray.size()); - - if(nDXCount) - { - // DXArray does not need to be adapted to getTextPosition/getTextLength, - // it is already provided correctly - const uno::Sequence< double > aDXSequence(&rDXArray[0], nDXCount); - xLayout->applyLogicalAdvancements(aDXSequence); - } - - // set text color - const ::basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor())); - maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice()); - - // set text transformation - canvas::tools::setRenderStateTransform(maRenderState, rTextCandidate.getTextTransform()); - - // paint - mxCanvas->drawTextLayout(xLayout, maViewState, maRenderState); - } - } - } + impRenderTextSimplePortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate)); break; } case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D : { // Bitmap primitive - const primitive2d::BitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate); - - if(rBitmapCandidate.getBitmapEx().IsEmpty()) - { - // replace with color filled polygon - const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor())); - const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); - - maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice()); - canvas::tools::setRenderStateTransform(maRenderState, rBitmapCandidate.getTransform()); - - mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( - mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState); - } - else - { - // apply possible color modification to BitmapEx - BitmapEx aBitmapEx(impModifyBitmapEx(maBColorModifierStack, rBitmapCandidate.getBitmapEx())); - - // adapt object's transformation to the correct scale - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - basegfx::B2DHomMatrix aNewMatrix; - const Size aSizePixel(aBitmapEx.GetSizePixel()); - const double fBitmapWidth(aSizePixel.Width() == 0 ? 1.0 : aSizePixel.Width()); - const double fBitmapHeight(aSizePixel.Height() == 0 ? 1.0 : aSizePixel.Height()); - - rBitmapCandidate.getTransform().decompose(aScale, aTranslate, fRotate, fShearX); - aNewMatrix.scale(aScale.getX() / fBitmapWidth, aScale.getY() / fBitmapHeight); - aNewMatrix.shearX(fShearX); - aNewMatrix.rotate(fRotate); - aNewMatrix.translate(aTranslate.getX(), aTranslate.getY()); - - canvas::tools::setRenderStateTransform(maRenderState, aNewMatrix); - - mxCanvas->drawBitmap( - vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aBitmapEx), - maViewState, maRenderState); - } + impRenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate)); break; } case PRIMITIVE2D_ID_ALPHAPRIMITIVE2D : { // Alpha primitive - const primitive2d::AlphaPrimitive2D& rAlphaCandidate = static_cast< const primitive2d::AlphaPrimitive2D& >(rCandidate); - const primitive2d::Primitive2DSequence& rChildren = rAlphaCandidate.getChildren(); - - if(rChildren.hasElements()) - { - // get logic and discrete range of transparent part - basegfx::B2DRange aLogicRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rChildren, getViewInformation2D())); - basegfx::B2DRange aDiscreteRange(aLogicRange); - aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation()); - - // expand to next covering discrete values (pixel bounds) - aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY()))); - aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY()))); - - // determine integer bitmap size - const com::sun::star::geometry::IntegerSize2D aIntegerSize2D( - basegfx::fround(aDiscreteRange.getWidth()), - basegfx::fround(aDiscreteRange.getHeight())); - - // create XBitmap for rendering child context - uno::Reference< rendering::XCanvas > xChildBitmap( - mxCanvas->getDevice()->createCompatibleBitmap(aIntegerSize2D), - uno::UNO_QUERY_THROW); - - if(xChildBitmap.is()) - { - // create and set ViewInformation2D for Sub-Canvas - const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D()); - - // prepare discrete offset for XBitmap - basegfx::B2DHomMatrix aDiscreteOffset; - aDiscreteOffset.translate(-aDiscreteRange.getMinX(), -aDiscreteRange.getMinY()); - - // create new local ViewInformation2D with new transformation - const geometry::ViewInformation2D aViewInformation2D( - getViewInformation2D().getObjectTransformation(), - aDiscreteOffset * getViewInformation2D().getViewTransformation(), - getViewInformation2D().getViewport(), - getViewInformation2D().getVisualizedPage(), - getViewInformation2D().getViewTime(), - getViewInformation2D().getExtendedInformationSequence()); - updateViewInformation(aViewInformation2D); - canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getObjectToViewTransformation()); - - // remember last canvas - uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas); - - // set child bitmap as target and paint child content - mxCanvas = xChildBitmap; - process(rChildren); - - // check if alpha is simple alpha (just one PolyPolygonColor primitive) - bool bIsSimpleTransparence(false); - const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = 0; - uno::Reference< rendering::XCanvas > xAlphaBitmap; - const primitive2d::Primitive2DSequence& rAlpha = rAlphaCandidate.getAlpha(); - - if(rAlpha.hasElements() && 1 == rAlpha.getLength()) - { - const primitive2d::Primitive2DReference xReference(rAlpha[0]); - pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get()); + impRenderAlphaPrimitive2D(static_cast< const primitive2d::AlphaPrimitive2D& >(rCandidate)); - if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitiveID()) - { - bIsSimpleTransparence = true; - } - } - - if(!bIsSimpleTransparence) - { - // create XBitmap for rendering alpha context - xAlphaBitmap = uno::Reference< rendering::XCanvas >( - mxCanvas->getDevice()->createCompatibleBitmap(aIntegerSize2D), uno::UNO_QUERY_THROW); - - if(xAlphaBitmap.is()) - { - // set alpha bitmap as target and paint child content - mxCanvas = xAlphaBitmap; - process(rAlpha); - } - } + break; + } + case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D: + { + // PolygonStrokePrimitive + impRenderPolygonStrokePrimitive2D(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate)); - // restore old canvas and ViewInformation - mxCanvas = xLastCanvas; - updateViewInformation(aLastViewInformation2D); - canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getObjectToViewTransformation()); + break; + } + case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D : + { + // FillBitmapPrimitive2D + impRenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(rCandidate)); - // prepare bitmap transformation for local painting - const double fBitmapWidth(std::max(1.0, aDiscreteRange.getWidth())); - const double fBitmapHeight(std::max(1.0, aDiscreteRange.getHeight())); - basegfx::B2DHomMatrix aBitmapTransform; + break; + } + case PRIMITIVE2D_ID_UNIFIEDALPHAPRIMITIVE2D : + { + // UnifiedAlphaPrimitive2D + impRenderUnifiedAlphaPrimitive2D(static_cast< const primitive2d::UnifiedAlphaPrimitive2D& >(rCandidate)); - // transform back logic range from discrete range to work on same bounds and - // to have the correct logic width/Height for bitmap render state due to discrete - // roundings (pixel alignments) - aLogicRange = aDiscreteRange; - aLogicRange.transform(getViewInformation2D().getInverseObjectToViewTransformation()); + break; + } + case PRIMITIVE2D_ID_CHARTPRIMITIVE2D : + { + // chart primitive in canvas renderer; restore original DrawMode during call + // since the evtl. used ChartPrettyPainter will use the MapMode + const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate); + mpOutputDevice->Push(PUSH_MAPMODE); + mpOutputDevice->SetMapMode(maOriginalMapMode); - // LogicRange Width/Height is correct - aBitmapTransform.scale(aLogicRange.getWidth() / fBitmapWidth, aLogicRange.getHeight() / fBitmapHeight); - aBitmapTransform.translate(aLogicRange.getMinX(), aLogicRange.getMinY()); - canvas::tools::setRenderStateTransform(maRenderState, aBitmapTransform); + if(!renderChartPrimitive2D(rChartPrimitive, *mpOutputDevice)) + { + // fallback to decomposition (MetaFile) + process(rChartPrimitive.get2DDecomposition(getViewInformation2D())); + } - if(bIsSimpleTransparence) - { - // it's a simple transparence, draw modulated content XBitmap. The alpha - // is contained in the fill color of pPoPoColor, all color channels are - // the same to build a gray value - const basegfx::BColor& rAlphaFill = pPoPoColor->getBColor(); - - // add alpha modulation value to DeviceColor - uno::Sequence< double > aColor(4); - - aColor[0] = 1.0; - aColor[1] = 1.0; - aColor[2] = 1.0; - aColor[3] = rAlphaFill.getRed(); - maRenderState.DeviceColor = aColor; - - // draw child bitmap - mxCanvas->drawBitmapModulated(uno::Reference< rendering::XBitmap >(xChildBitmap, uno::UNO_QUERY_THROW), - maViewState, maRenderState); - } - else - { - // It's a alpha with various geometry, need to combine child and alpha bitmap to a single - // BitmapEx. I konow no other way here than to get the VCL Bitmaps and using VCL functionality - // for this combination. This is very slow and needs to be enchanced ASAP. - const uno::Reference< rendering::XIntegerReadOnlyBitmap > xReadOnlyChild(xChildBitmap, uno::UNO_QUERY_THROW); - const uno::Reference< rendering::XIntegerReadOnlyBitmap > xReadOnlyAlpha(xAlphaBitmap, uno::UNO_QUERY_THROW); - const Bitmap aChildBitmap(vcl::unotools::bitmapExFromXBitmap(xReadOnlyChild).GetBitmap()); - const AlphaMask aAlphaBitmap(vcl::unotools::bitmapExFromXBitmap(xReadOnlyAlpha).GetBitmap()); - - // draw bitmap - mxCanvas->drawBitmap(vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), BitmapEx(aChildBitmap, aAlphaBitmap)), - maViewState, maRenderState); - } - } + mpOutputDevice->Pop(); + break; + } + case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D : + { + // wrong spell primitive. Handled directly here using VCL since VCL has a nice and + // very direct waveline painting which is needed for this. If VCL is to be avoided, + // this can be removed anytime and the decomposition may be used + const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive = static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate); + + if(!renderWrongSpellPrimitive2D( + rWrongSpellPrimitive, + *mpOutputDevice, + getViewInformation2D().getObjectToViewTransformation(), + maBColorModifierStack)) + { + // fallback to decomposition (MetaFile) + process(rWrongSpellPrimitive.get2DDecomposition(getViewInformation2D())); } break; } + + // nice to have: + // + // case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D : + // - support FormControls more direct eventually, not sure if this is needed + // with the canvas renderer. The decomposition provides a bitmap representation + // of the control which will work + // + default : { // process recursively @@ -1771,9 +2144,11 @@ namespace drawinglayer canvasProcessor2D::canvasProcessor2D( const geometry::ViewInformation2D& rViewInformation, - const uno::Reference< rendering::XCanvas >& rCanvas) + OutputDevice& rOutDev) : BaseProcessor2D(rViewInformation), - mxCanvas( rCanvas ), + maOriginalMapMode(rOutDev.GetMapMode()), + mpOutputDevice(&rOutDev), + mxCanvas(rOutDev.GetCanvas()), maViewState(), maRenderState(), maBColorModifierStack(), @@ -1785,8 +2160,10 @@ namespace drawinglayer canvas::tools::initViewState(maViewState); canvas::tools::initRenderState(maRenderState); - canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getObjectToViewTransformation()); + canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation()); + // set digit language, derived from SvtCTLOptions to have the correct + // number display for arabic/hindi numerals if(SvtCTLOptions::NUMERALS_HINDI == aSvtCTLOptions.GetCTLTextNumerals()) { meLang = LANGUAGE_ARABIC; @@ -1799,10 +2176,31 @@ namespace drawinglayer { meLang = (LanguageType)Application::GetSettings().GetLanguage(); } + + rOutDev.SetDigitLanguage(meLang); + + // prepare output directly to pixels + mpOutputDevice->Push(PUSH_MAPMODE); + mpOutputDevice->SetMapMode(); + + // react on AntiAliasing settings + if(getOptionsDrawinglayer().IsAntiAliasing()) + { + mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW); + } + else + { + mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW); + } } canvasProcessor2D::~canvasProcessor2D() { + // restore MapMode + mpOutputDevice->Pop(); + + // restore AntiAliasing + mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW); } } // end of namespace processor2d } // end of namespace drawinglayer diff --git a/drawinglayer/source/processor2d/helperchartrenderer.cxx b/drawinglayer/source/processor2d/helperchartrenderer.cxx new file mode 100644 index 000000000000..c2d99604469b --- /dev/null +++ b/drawinglayer/source/processor2d/helperchartrenderer.cxx @@ -0,0 +1,99 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: helperchartrenderer.cxx,v $ + * + * $Revision: 1.1.2.1 $ + * + * last change: $Author: aw $ $Date: 2008/09/24 14:28:34 $ + * + * 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 <helperchartrenderer.hxx> +#include <drawinglayer/primitive2d/chartprimitive2d.hxx> +#include <svtools/chartprettypainter.hxx> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + bool renderChartPrimitive2D(const primitive2d::ChartPrimitive2D& rChartCandidate, OutputDevice& rOutputDevice) + { + bool bChartRendered(false); + + // code from chart PrettyPrinter + try + { + uno::Reference< lang::XMultiServiceFactory > xFact( rChartCandidate.getChartModel(), uno::UNO_QUERY ); + OSL_ENSURE( xFact.is(), "Chart cannot be painted pretty!\n" ); + + if( xFact.is() ) + { + uno::Reference< lang::XUnoTunnel > xChartRenderer( xFact->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.chart2.ChartRenderer" ) ) ), uno::UNO_QUERY ); + OSL_ENSURE( xChartRenderer.is(), "Chart cannot be painted pretty!\n" ); + + if( xChartRenderer.is() ) + { + ChartPrettyPainter* pPrettyPainter = reinterpret_cast<ChartPrettyPainter*>( + xChartRenderer->getSomething( ChartPrettyPainter::getUnoTunnelId() )); + + if( pPrettyPainter ) + { + // create logic object range + basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0); + aObjectRange.transform(rChartCandidate.getTransformation()); + const Rectangle aRectangle( + (sal_Int32)aObjectRange.getMinX(), (sal_Int32)aObjectRange.getMinY(), + (sal_Int32)aObjectRange.getMaxX(), (sal_Int32)aObjectRange.getMaxY()); + + bChartRendered = pPrettyPainter->DoPaint(&rOutputDevice, aRectangle); + } + } + } + } + catch( uno::Exception& e ) + { + (void)e; + DBG_ERROR( "Chart cannot be painted pretty!" ); + } + + return bChartRendered; + } +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/processor2d/helperchartrenderer.hxx b/drawinglayer/source/processor2d/helperchartrenderer.hxx new file mode 100644 index 000000000000..de13431c79c0 --- /dev/null +++ b/drawinglayer/source/processor2d/helperchartrenderer.hxx @@ -0,0 +1,63 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: helperchartrenderer.hxx,v $ + * + * $Revision: 1.1.2.1 $ + * + * last change: $Author: aw $ $Date: 2008/09/24 14:28:43 $ + * + * 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_PROCESSOR2D_HELPERCHARTRENDER_HXX +#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERCHARTRENDER_HXX + +#include <sal/types.h> + +////////////////////////////////////////////////////////////////////////////// +// predefines + +class OutputDevice; + +namespace drawinglayer { namespace primitive2d { + class ChartPrimitive2D; +}} + +////////////////////////////////////////////////////////////////////////////// +// support chart PrettyPrinter usage from primitives + +namespace drawinglayer +{ + bool renderChartPrimitive2D(const primitive2d::ChartPrimitive2D& rChartCandidate, OutputDevice& rOutputDevice); + +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERCHARTRENDER_HXX + +// eof diff --git a/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx b/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx new file mode 100644 index 000000000000..f832698b18f2 --- /dev/null +++ b/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: helperwrongspellrenderer.cxx,v $ + * + * $Revision: 1.1.2.1 $ + * + * last change: $Author: aw $ $Date: 2008/09/24 14:28:52 $ + * + * 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 <helperwrongspellrenderer.hxx> +#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx> +#include <tools/gen.hxx> +#include <vcl/outdev.hxx> +#include <basegfx/color/bcolormodifier.hxx> + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + bool renderWrongSpellPrimitive2D( + const primitive2d::WrongSpellPrimitive2D& rWrongSpellCandidate, + OutputDevice& rOutputDevice, + const basegfx::B2DHomMatrix& rObjectToViewTransformation, + const basegfx::BColorModifierStack& rBColorModifierStack) + { + const basegfx::B2DHomMatrix aLocalTransform(rObjectToViewTransformation * rWrongSpellCandidate.getTransformation()); + const basegfx::B2DVector aFontVectorPixel(aLocalTransform * basegfx::B2DVector(0.0, 1.0)); + const sal_uInt32 nFontPixelHeight(basegfx::fround(aFontVectorPixel.getLength())); + + static const sal_uInt32 nMinimumFontHeight(5); // #define WRONG_SHOW_MIN 5 + static const sal_uInt32 nSmallFontHeight(11); // #define WRONG_SHOW_SMALL 11 + static const sal_uInt32 nMediumFontHeight(15); // #define WRONG_SHOW_MEDIUM 15 + + if(nFontPixelHeight > nMinimumFontHeight) + { + const basegfx::B2DPoint aStart(aLocalTransform * basegfx::B2DPoint(rWrongSpellCandidate.getStart(), 0.0)); + const basegfx::B2DPoint aStop(aLocalTransform * basegfx::B2DPoint(rWrongSpellCandidate.getStop(), 0.0)); + const Point aVclStart(basegfx::fround(aStart.getX()), basegfx::fround(aStart.getY())); + const Point aVclStop(basegfx::fround(aStop.getX()), basegfx::fround(aStop.getY())); + sal_uInt16 nWaveStyle(WAVE_FLAT); + + if(nFontPixelHeight > nMediumFontHeight) + { + nWaveStyle = WAVE_NORMAL; + } + else if(nFontPixelHeight > nSmallFontHeight) + { + nWaveStyle = WAVE_SMALL; + } + + const basegfx::BColor aProcessedColor(rBColorModifierStack.getModifiedColor(rWrongSpellCandidate.getColor())); + const bool bMapModeEnabledState(rOutputDevice.IsMapModeEnabled()); + + rOutputDevice.EnableMapMode(false); + rOutputDevice.SetLineColor(Color(aProcessedColor)); + rOutputDevice.SetFillColor(); + rOutputDevice.DrawWaveLine(aVclStart, aVclStop, nWaveStyle); + rOutputDevice.EnableMapMode(bMapModeEnabledState); + } + + // cannot really go wrong + return true; + } +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/processor2d/helperwrongspellrenderer.hxx b/drawinglayer/source/processor2d/helperwrongspellrenderer.hxx new file mode 100644 index 000000000000..6d9938a72f4e --- /dev/null +++ b/drawinglayer/source/processor2d/helperwrongspellrenderer.hxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: helperwrongspellrenderer.hxx,v $ + * + * $Revision: 1.1.2.1 $ + * + * last change: $Author: aw $ $Date: 2008/09/24 14:29:02 $ + * + * 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_PROCESSOR2D_HELPERWRONGSPELLRENDER_HXX +#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERWRONGSPELLRENDER_HXX + +#include <sal/types.h> + +////////////////////////////////////////////////////////////////////////////// +// predefines + +class OutputDevice; + +namespace drawinglayer { namespace primitive2d { + class WrongSpellPrimitive2D; +}} + +namespace basegfx { + class B2DHomMatrix; + class BColorModifierStack; +} + +////////////////////////////////////////////////////////////////////////////// +// support WrongSpell rendreing using VCL from primitives due to VCLs nice +// and fast solution with wavelines + +namespace drawinglayer +{ + bool renderWrongSpellPrimitive2D( + const primitive2d::WrongSpellPrimitive2D& rWrongSpellCandidate, + OutputDevice& rOutputDevice, + const basegfx::B2DHomMatrix& rObjectToViewTransformation, + const basegfx::BColorModifierStack& rBColorModifierStack); + +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +#endif // INCLUDED_DRAWINGLAYER_PROCESSOR2D_HELPERWRONGSPELLRENDER_HXX + +// eof diff --git a/drawinglayer/source/processor2d/makefile.mk b/drawinglayer/source/processor2d/makefile.mk index 1ca3aad2e494..38dcb42cd4a0 100644 --- a/drawinglayer/source/processor2d/makefile.mk +++ b/drawinglayer/source/processor2d/makefile.mk @@ -51,7 +51,8 @@ SLOFILES= \ $(SLO)$/vclhelperbitmaprender.obj \ $(SLO)$/vclhelperbufferdevice.obj \ $(SLO)$/vclprocessor2d.obj \ - $(SLO)$/vclchartprocessor2d.obj \ + $(SLO)$/helperchartrenderer.obj \ + $(SLO)$/helperwrongspellrenderer.obj \ $(SLO)$/vclpixelprocessor2d.obj \ $(SLO)$/vclmetafileprocessor2d.obj \ $(SLO)$/contourextractor2d.obj \ diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx index f4e74a949b3a..63ee8108c35c 100644 --- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx +++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx @@ -48,7 +48,8 @@ namespace drawinglayer { impBufferDevice::impBufferDevice( OutputDevice& rOutDev, - const basegfx::B2DRange& rRange) + const basegfx::B2DRange& rRange, + bool bAddOffsetToMapping) : mrOutDev(rOutDev), maContent(rOutDev), mpMask(0L), @@ -73,8 +74,12 @@ namespace drawinglayer rOutDev.EnableMapMode(bWasEnabledSrc); MapMode aNewMapMode(rOutDev.GetMapMode()); - const Point aLogicTopLeft(rOutDev.PixelToLogic(maDestPixel.TopLeft())); - aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y())); + + if(bAddOffsetToMapping) + { + const Point aLogicTopLeft(rOutDev.PixelToLogic(maDestPixel.TopLeft())); + aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y())); + } maContent.SetMapMode(aNewMapMode); diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx index 7c2717c9b1e7..f987585249ad 100644 --- a/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx +++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.hxx @@ -59,7 +59,8 @@ namespace drawinglayer public: impBufferDevice( OutputDevice& rOutDev, - const basegfx::B2DRange& rRange); + const basegfx::B2DRange& rRange, + bool bAddOffsetToMapping); ~impBufferDevice(); void paint(double fTrans = 0.0); diff --git a/drawinglayer/source/processor2d/vclhelpergradient.cxx b/drawinglayer/source/processor2d/vclhelpergradient.cxx index d8857b4bedaf..25d7513006fa 100644 --- a/drawinglayer/source/processor2d/vclhelpergradient.cxx +++ b/drawinglayer/source/processor2d/vclhelpergradient.cxx @@ -89,7 +89,7 @@ namespace drawinglayer if(a) { - if(a - 1L < rMatrices.size()) + if(a - 1L < static_cast< sal_uInt32 >(rMatrices.size())) { basegfx::B2DPolygon aNewPoly(rUnitPolygon); aNewPoly.transform(rMatrices[a - 1L]); diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index ed769b95b4d0..077670481c96 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -72,6 +72,7 @@ #include <drawinglayer/primitive2d/graphicprimitive2d.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx> +#include <helperchartrenderer.hxx> ////////////////////////////////////////////////////////////////////////////// // for PDFExtOutDevData Graphic support @@ -1606,8 +1607,14 @@ namespace drawinglayer } case PRIMITIVE2D_ID_CHARTPRIMITIVE2D : { - // point array - RenderChartPrimitive2D(static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate)); + // ChartPrimitive2D + const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate); + + if(!renderChartPrimitive2D(rChartPrimitive, *mpOutputDevice)) + { + // fallback to decomposition (MetaFile) + process(rChartPrimitive.get2DDecomposition(getViewInformation2D())); + } break; } case PRIMITIVE2D_ID_STRUCTURETAGRIMITIVE2D : diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 000013fa1898..3b3a0f19f612 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -57,6 +57,11 @@ #include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx> #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx> #include <drawinglayer/primitive2d/chartprimitive2d.hxx> +#include <helperchartrenderer.hxx> +#include <helperwrongspellrenderer.hxx> +#include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <vcl/hatch.hxx> #include <cstdio> ////////////////////////////////////////////////////////////////////////////// @@ -107,7 +112,17 @@ namespace drawinglayer if(bHandleWrongSpellDirectly) { - RenderWrongSpellPrimitive2D(static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate)); + const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive = static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate); + + if(!renderWrongSpellPrimitive2D( + rWrongSpellPrimitive, + *mpOutputDevice, + maCurrentTransformation, + maBColorModifierStack)) + { + // fallback to decomposition (MetaFile) + process(rWrongSpellPrimitive.get2DDecomposition(getViewInformation2D())); + } } else { @@ -372,10 +387,78 @@ namespace drawinglayer { // chart primitive in pixel renderer; restore original DrawMode during call // since the evtl. used ChartPrettyPainter will use the MapMode + const primitive2d::ChartPrimitive2D& rChartPrimitive = static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate); mpOutputDevice->Push(PUSH_MAPMODE); mpOutputDevice->SetMapMode(maOriginalMapMode); - RenderChartPrimitive2D(static_cast< const primitive2d::ChartPrimitive2D& >(rCandidate)); - mpOutputDevice->Pop(); + + if(!renderChartPrimitive2D(rChartPrimitive, *mpOutputDevice)) + { + // fallback to decomposition (MetaFile) + process(rChartPrimitive.get2DDecomposition(getViewInformation2D())); + } + + mpOutputDevice->Pop(); + break; + } + case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D : + { + static bool bForceIgnoreHatchSmoothing(false); + + if(bForceIgnoreHatchSmoothing || getOptionsDrawinglayer().IsAntiAliasing()) + { + // if AA is used (or ignore smoothing is on), there is no need to smooth + // hatch painting, use decomposition + process(rCandidate.get2DDecomposition(getViewInformation2D())); + } + else + { + // without AA, use VCL to draw the hatch. It snaps hatch distances to the next pixel + // and forces hatch distance to be >= 3 pixels to make the hatch display look smoother. + // This is wrong in principle, but looks nicer. This could also be done here directly + // without VCL usage if needed + const primitive2d::FillHatchPrimitive2D& rFillHatchPrimitive = static_cast< const primitive2d::FillHatchPrimitive2D& >(rCandidate); + + // create hatch polygon in range size and discrete coordinates + basegfx::B2DRange aHatchRange(rFillHatchPrimitive.getObjectRange()); + aHatchRange.transform(maCurrentTransformation); + const basegfx::B2DPolygon aHatchPolygon(basegfx::tools::createPolygonFromRect(aHatchRange)); + + // set hatch line color + const basegfx::BColor aHatchColor(maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor())); + mpOutputDevice->SetFillColor(); + mpOutputDevice->SetLineColor(Color(aHatchColor)); + + // get hatch style + const attribute::FillHatchAttribute& rFillHatchAttributes = rFillHatchPrimitive.getFillHatch(); + HatchStyle eHatchStyle(HATCH_SINGLE); + + switch(rFillHatchAttributes.getStyle()) + { + default : // HATCHSTYLE_SINGLE + { + break; + } + case attribute::HATCHSTYLE_DOUBLE : + { + eHatchStyle = HATCH_DOUBLE; + break; + } + case attribute::HATCHSTYLE_TRIPLE : + { + eHatchStyle = HATCH_TRIPLE; + break; + } + } + + // create hatch + const basegfx::B2DVector aDiscreteDistance(maCurrentTransformation * basegfx::B2DVector(rFillHatchAttributes.getDistance(), 0.0)); + const sal_uInt32 nDistance(basegfx::fround(aDiscreteDistance.getX())); + const sal_uInt16 nAngle10((sal_uInt16)basegfx::fround(rFillHatchAttributes.getAngle() / F_PI1800)); + ::Hatch aVCLHatch(eHatchStyle, Color(rFillHatchAttributes.getColor()), nDistance, nAngle10); + + // draw hatch using VCL + mpOutputDevice->DrawHatch(PolyPolygon(Polygon(aHatchPolygon)), aVCLHatch); + } break; } default : diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index 817159985f5a..69368fbba2d5 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -659,7 +659,7 @@ namespace drawinglayer { aMask.transform(maCurrentTransformation); const basegfx::B2DRange aRange(basegfx::tools::getRange(aMask)); - impBufferDevice aBufferDevice(*mpOutputDevice, aRange); + impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true); if(aBufferDevice.isVisible()) { @@ -719,7 +719,7 @@ namespace drawinglayer { basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate.getChildren(), getViewInformation2D())); aRange.transform(maCurrentTransformation); - impBufferDevice aBufferDevice(*mpOutputDevice, aRange); + impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true); if(aBufferDevice.isVisible()) { @@ -895,41 +895,6 @@ namespace drawinglayer } } - // wrong spell primitive - void VclProcessor2D::RenderWrongSpellPrimitive2D(const primitive2d::WrongSpellPrimitive2D& rWrongSpellCandidate) - { - const basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rWrongSpellCandidate.getTransformation()); - const basegfx::B2DVector aFontVectorPixel(aLocalTransform * basegfx::B2DVector(0.0, 1.0)); - const sal_uInt32 nFontPixelHeight(basegfx::fround(aFontVectorPixel.getLength())); - - static const sal_uInt32 nMinimumFontHeight(5); // #define WRONG_SHOW_MIN 5 - static const sal_uInt32 nSmallFontHeight(11); // #define WRONG_SHOW_SMALL 11 - static const sal_uInt32 nMediumFontHeight(15); // #define WRONG_SHOW_MEDIUM 15 - - if(nFontPixelHeight > nMinimumFontHeight) - { - const basegfx::B2DPoint aStart(aLocalTransform * basegfx::B2DPoint(rWrongSpellCandidate.getStart(), 0.0)); - const basegfx::B2DPoint aStop(aLocalTransform * basegfx::B2DPoint(rWrongSpellCandidate.getStop(), 0.0)); - const Point aVclStart(basegfx::fround(aStart.getX()), basegfx::fround(aStart.getY())); - const Point aVclStop(basegfx::fround(aStop.getX()), basegfx::fround(aStop.getY())); - sal_uInt16 nWaveStyle(WAVE_FLAT); - - if(nFontPixelHeight > nMediumFontHeight) - { - nWaveStyle = WAVE_NORMAL; - } - else if(nFontPixelHeight > nSmallFontHeight) - { - nWaveStyle = WAVE_SMALL; - } - - const basegfx::BColor aProcessedColor(maBColorModifierStack.getModifiedColor(rWrongSpellCandidate.getColor())); - mpOutputDevice->SetLineColor(Color(aProcessedColor)); - mpOutputDevice->SetFillColor(); - mpOutputDevice->DrawWaveLine(aVclStart, aVclStop, nWaveStyle); - } - } - void VclProcessor2D::RenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate) { const attribute::LineAttribute& rLineAttribute = rPolygonStrokeCandidate.getLineAttribute(); |