1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx> 32*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygon.hxx> 33*cdf0e10cSrcweir #include <drawinglayer/attribute/strokeattribute.hxx> 34*cdf0e10cSrcweir #include <drawinglayer/primitive3d/baseprimitive3d.hxx> 35*cdf0e10cSrcweir #include <drawinglayer/primitive3d/polygonprimitive3d.hxx> 36*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygon.hxx> 37*cdf0e10cSrcweir #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx> 38*cdf0e10cSrcweir #include <vcl/vclenum.hxx> 39*cdf0e10cSrcweir #include <drawinglayer/attribute/fillbitmapattribute.hxx> 40*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrfillbitmapattribute.hxx> 41*cdf0e10cSrcweir #include <vcl/bmpacc.hxx> 42*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolypolygontools.hxx> 43*cdf0e10cSrcweir #include <drawinglayer/primitive3d/textureprimitive3d.hxx> 44*cdf0e10cSrcweir #include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx> 45*cdf0e10cSrcweir #include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx> 46*cdf0e10cSrcweir #include <drawinglayer/primitive3d/shadowprimitive3d.hxx> 47*cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx> 48*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrlineattribute.hxx> 49*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrobjectattribute3d.hxx> 50*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrfillattribute.hxx> 51*cdf0e10cSrcweir #include <drawinglayer/attribute/sdrshadowattribute.hxx> 52*cdf0e10cSrcweir #include <drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx> 53*cdf0e10cSrcweir 54*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir namespace drawinglayer 57*cdf0e10cSrcweir { 58*cdf0e10cSrcweir namespace primitive3d 59*cdf0e10cSrcweir { 60*cdf0e10cSrcweir basegfx::B3DRange getRangeFrom3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill) 61*cdf0e10cSrcweir { 62*cdf0e10cSrcweir basegfx::B3DRange aRetval; 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir for(sal_uInt32 a(0); a < rFill.size(); a++) 65*cdf0e10cSrcweir { 66*cdf0e10cSrcweir aRetval.expand(basegfx::tools::getRange(rFill[a])); 67*cdf0e10cSrcweir } 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir return aRetval; 70*cdf0e10cSrcweir } 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir void applyNormalsKindSphereTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill, const basegfx::B3DRange& rRange) 73*cdf0e10cSrcweir { 74*cdf0e10cSrcweir // create sphere normals 75*cdf0e10cSrcweir const basegfx::B3DPoint aCenter(rRange.getCenter()); 76*cdf0e10cSrcweir 77*cdf0e10cSrcweir for(sal_uInt32 a(0); a < rFill.size(); a++) 78*cdf0e10cSrcweir { 79*cdf0e10cSrcweir rFill[a] = basegfx::tools::applyDefaultNormalsSphere(rFill[a], aCenter); 80*cdf0e10cSrcweir } 81*cdf0e10cSrcweir } 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir void applyNormalsKindFlatTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill) 84*cdf0e10cSrcweir { 85*cdf0e10cSrcweir for(sal_uInt32 a(0); a < rFill.size(); a++) 86*cdf0e10cSrcweir { 87*cdf0e10cSrcweir rFill[a].clearNormals(); 88*cdf0e10cSrcweir } 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir void applyNormalsInvertTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill) 92*cdf0e10cSrcweir { 93*cdf0e10cSrcweir // invert normals 94*cdf0e10cSrcweir for(sal_uInt32 a(0); a < rFill.size(); a++) 95*cdf0e10cSrcweir { 96*cdf0e10cSrcweir rFill[a] = basegfx::tools::invertNormals(rFill[a]); 97*cdf0e10cSrcweir } 98*cdf0e10cSrcweir } 99*cdf0e10cSrcweir 100*cdf0e10cSrcweir void applyTextureTo3DGeometry( 101*cdf0e10cSrcweir ::com::sun::star::drawing::TextureProjectionMode eModeX, 102*cdf0e10cSrcweir ::com::sun::star::drawing::TextureProjectionMode eModeY, 103*cdf0e10cSrcweir ::std::vector< basegfx::B3DPolyPolygon >& rFill, 104*cdf0e10cSrcweir const basegfx::B3DRange& rRange, 105*cdf0e10cSrcweir const basegfx::B2DVector& rTextureSize) 106*cdf0e10cSrcweir { 107*cdf0e10cSrcweir sal_uInt32 a; 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir // handle texture coordinates X 110*cdf0e10cSrcweir const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == eModeX); 111*cdf0e10cSrcweir const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == eModeX)); 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir // handle texture coordinates Y 114*cdf0e10cSrcweir const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == eModeY); 115*cdf0e10cSrcweir const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == eModeY)); 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir if(bParallelX || bParallelY) 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir // apply parallel texture coordinates in X and/or Y 120*cdf0e10cSrcweir for(a = 0; a < rFill.size(); a++) 121*cdf0e10cSrcweir { 122*cdf0e10cSrcweir rFill[a] = basegfx::tools::applyDefaultTextureCoordinatesParallel(rFill[a], rRange, bParallelX, bParallelY); 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir } 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir if(bSphereX || bSphereY) 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir // apply spherical texture coordinates in X and/or Y 129*cdf0e10cSrcweir const basegfx::B3DPoint aCenter(rRange.getCenter()); 130*cdf0e10cSrcweir 131*cdf0e10cSrcweir for(a = 0; a < rFill.size(); a++) 132*cdf0e10cSrcweir { 133*cdf0e10cSrcweir rFill[a] = basegfx::tools::applyDefaultTextureCoordinatesSphere(rFill[a], aCenter, bSphereX, bSphereY); 134*cdf0e10cSrcweir } 135*cdf0e10cSrcweir } 136*cdf0e10cSrcweir 137*cdf0e10cSrcweir // transform texture coordinates to texture size 138*cdf0e10cSrcweir basegfx::B2DHomMatrix aTexMatrix; 139*cdf0e10cSrcweir aTexMatrix.scale(rTextureSize.getX(), rTextureSize.getY()); 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir for(a = 0; a < rFill.size(); a++) 142*cdf0e10cSrcweir { 143*cdf0e10cSrcweir rFill[a].transformTextureCoordiantes(aTexMatrix); 144*cdf0e10cSrcweir } 145*cdf0e10cSrcweir } 146*cdf0e10cSrcweir 147*cdf0e10cSrcweir Primitive3DSequence create3DPolyPolygonLinePrimitives( 148*cdf0e10cSrcweir const basegfx::B3DPolyPolygon& rUnitPolyPolygon, 149*cdf0e10cSrcweir const basegfx::B3DHomMatrix& rObjectTransform, 150*cdf0e10cSrcweir const attribute::SdrLineAttribute& rLine) 151*cdf0e10cSrcweir { 152*cdf0e10cSrcweir // prepare fully scaled polyPolygon 153*cdf0e10cSrcweir basegfx::B3DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon); 154*cdf0e10cSrcweir aScaledPolyPolygon.transform(rObjectTransform); 155*cdf0e10cSrcweir 156*cdf0e10cSrcweir // create line and stroke attribute 157*cdf0e10cSrcweir const attribute::LineAttribute aLineAttribute(rLine.getColor(), rLine.getWidth(), rLine.getJoin()); 158*cdf0e10cSrcweir const attribute::StrokeAttribute aStrokeAttribute(rLine.getDotDashArray(), rLine.getFullDotDashLen()); 159*cdf0e10cSrcweir 160*cdf0e10cSrcweir // create primitives 161*cdf0e10cSrcweir Primitive3DSequence aRetval(aScaledPolyPolygon.count()); 162*cdf0e10cSrcweir 163*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < aScaledPolyPolygon.count(); a++) 164*cdf0e10cSrcweir { 165*cdf0e10cSrcweir const Primitive3DReference xRef(new PolygonStrokePrimitive3D(aScaledPolyPolygon.getB3DPolygon(a), aLineAttribute, aStrokeAttribute)); 166*cdf0e10cSrcweir aRetval[a] = xRef; 167*cdf0e10cSrcweir } 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir if(0.0 != rLine.getTransparence()) 170*cdf0e10cSrcweir { 171*cdf0e10cSrcweir // create UnifiedTransparenceTexturePrimitive3D, add created primitives and exchange 172*cdf0e10cSrcweir const Primitive3DReference xRef(new UnifiedTransparenceTexturePrimitive3D(rLine.getTransparence(), aRetval)); 173*cdf0e10cSrcweir aRetval = Primitive3DSequence(&xRef, 1L); 174*cdf0e10cSrcweir } 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir return aRetval; 177*cdf0e10cSrcweir } 178*cdf0e10cSrcweir 179*cdf0e10cSrcweir Primitive3DSequence create3DPolyPolygonFillPrimitives( 180*cdf0e10cSrcweir const ::std::vector< basegfx::B3DPolyPolygon >& r3DPolyPolygonVector, 181*cdf0e10cSrcweir const basegfx::B3DHomMatrix& rObjectTransform, 182*cdf0e10cSrcweir const basegfx::B2DVector& rTextureSize, 183*cdf0e10cSrcweir const attribute::Sdr3DObjectAttribute& aSdr3DObjectAttribute, 184*cdf0e10cSrcweir const attribute::SdrFillAttribute& rFill, 185*cdf0e10cSrcweir const attribute::FillGradientAttribute& rFillGradient) 186*cdf0e10cSrcweir { 187*cdf0e10cSrcweir Primitive3DSequence aRetval; 188*cdf0e10cSrcweir 189*cdf0e10cSrcweir if(r3DPolyPolygonVector.size()) 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir // create list of simple fill primitives 192*cdf0e10cSrcweir aRetval.realloc(r3DPolyPolygonVector.size()); 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir for(sal_uInt32 a(0L); a < r3DPolyPolygonVector.size(); a++) 195*cdf0e10cSrcweir { 196*cdf0e10cSrcweir // get scaled PolyPolygon 197*cdf0e10cSrcweir basegfx::B3DPolyPolygon aScaledPolyPolygon(r3DPolyPolygonVector[a]); 198*cdf0e10cSrcweir aScaledPolyPolygon.transform(rObjectTransform); 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir if(aScaledPolyPolygon.areNormalsUsed()) 201*cdf0e10cSrcweir { 202*cdf0e10cSrcweir aScaledPolyPolygon.transformNormals(rObjectTransform); 203*cdf0e10cSrcweir } 204*cdf0e10cSrcweir 205*cdf0e10cSrcweir const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D( 206*cdf0e10cSrcweir aScaledPolyPolygon, 207*cdf0e10cSrcweir aSdr3DObjectAttribute.getMaterial(), 208*cdf0e10cSrcweir aSdr3DObjectAttribute.getDoubleSided())); 209*cdf0e10cSrcweir aRetval[a] = xRef; 210*cdf0e10cSrcweir } 211*cdf0e10cSrcweir 212*cdf0e10cSrcweir // look for and evtl. build texture sub-group primitive 213*cdf0e10cSrcweir if(!rFill.getGradient().isDefault() 214*cdf0e10cSrcweir || !rFill.getHatch().isDefault() 215*cdf0e10cSrcweir || !rFill.getBitmap().isDefault()) 216*cdf0e10cSrcweir { 217*cdf0e10cSrcweir bool bModulate(::com::sun::star::drawing::TextureMode_MODULATE == aSdr3DObjectAttribute.getTextureMode()); 218*cdf0e10cSrcweir bool bFilter(aSdr3DObjectAttribute.getTextureFilter()); 219*cdf0e10cSrcweir BasePrimitive3D* pNewTexturePrimitive3D = 0; 220*cdf0e10cSrcweir 221*cdf0e10cSrcweir if(!rFill.getGradient().isDefault()) 222*cdf0e10cSrcweir { 223*cdf0e10cSrcweir // create gradientTexture3D with sublist, add to local aRetval 224*cdf0e10cSrcweir pNewTexturePrimitive3D = new GradientTexturePrimitive3D( 225*cdf0e10cSrcweir rFill.getGradient(), 226*cdf0e10cSrcweir aRetval, 227*cdf0e10cSrcweir rTextureSize, 228*cdf0e10cSrcweir bModulate, 229*cdf0e10cSrcweir bFilter); 230*cdf0e10cSrcweir } 231*cdf0e10cSrcweir else if(!rFill.getHatch().isDefault()) 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir // create hatchTexture3D with sublist, add to local aRetval 234*cdf0e10cSrcweir pNewTexturePrimitive3D = new HatchTexturePrimitive3D( 235*cdf0e10cSrcweir rFill.getHatch(), 236*cdf0e10cSrcweir aRetval, 237*cdf0e10cSrcweir rTextureSize, 238*cdf0e10cSrcweir bModulate, 239*cdf0e10cSrcweir bFilter); 240*cdf0e10cSrcweir } 241*cdf0e10cSrcweir else // if(!rFill.getBitmap().isDefault()) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir // create bitmapTexture3D with sublist, add to local aRetval 244*cdf0e10cSrcweir basegfx::B2DRange aTexRange(0.0, 0.0, rTextureSize.getX(), rTextureSize.getY()); 245*cdf0e10cSrcweir 246*cdf0e10cSrcweir pNewTexturePrimitive3D = new BitmapTexturePrimitive3D( 247*cdf0e10cSrcweir rFill.getBitmap().getFillBitmapAttribute(aTexRange), 248*cdf0e10cSrcweir aRetval, 249*cdf0e10cSrcweir rTextureSize, 250*cdf0e10cSrcweir bModulate, 251*cdf0e10cSrcweir bFilter); 252*cdf0e10cSrcweir } 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir // exchange aRetval content with texture group 255*cdf0e10cSrcweir const Primitive3DReference xRef(pNewTexturePrimitive3D); 256*cdf0e10cSrcweir aRetval = Primitive3DSequence(&xRef, 1L); 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir if(::com::sun::star::drawing::TextureKind2_LUMINANCE == aSdr3DObjectAttribute.getTextureKind()) 259*cdf0e10cSrcweir { 260*cdf0e10cSrcweir // use modified color primitive to force textures to gray 261*cdf0e10cSrcweir const basegfx::BColorModifier aBColorModifier(basegfx::BColor(), 0.0, basegfx::BCOLORMODIFYMODE_GRAY); 262*cdf0e10cSrcweir const Primitive3DReference xRef2(new ModifiedColorPrimitive3D(aRetval, aBColorModifier)); 263*cdf0e10cSrcweir aRetval = Primitive3DSequence(&xRef2, 1L); 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir } 266*cdf0e10cSrcweir 267*cdf0e10cSrcweir if(0.0 != rFill.getTransparence()) 268*cdf0e10cSrcweir { 269*cdf0e10cSrcweir // create UnifiedTransparenceTexturePrimitive3D with sublist and exchange 270*cdf0e10cSrcweir const Primitive3DReference xRef(new UnifiedTransparenceTexturePrimitive3D(rFill.getTransparence(), aRetval)); 271*cdf0e10cSrcweir aRetval = Primitive3DSequence(&xRef, 1L); 272*cdf0e10cSrcweir } 273*cdf0e10cSrcweir else if(!rFillGradient.isDefault()) 274*cdf0e10cSrcweir { 275*cdf0e10cSrcweir // create TransparenceTexturePrimitive3D with sublist and exchange 276*cdf0e10cSrcweir const Primitive3DReference xRef(new TransparenceTexturePrimitive3D(rFillGradient, aRetval, rTextureSize)); 277*cdf0e10cSrcweir aRetval = Primitive3DSequence(&xRef, 1L); 278*cdf0e10cSrcweir } 279*cdf0e10cSrcweir } 280*cdf0e10cSrcweir 281*cdf0e10cSrcweir return aRetval; 282*cdf0e10cSrcweir } 283*cdf0e10cSrcweir 284*cdf0e10cSrcweir Primitive3DSequence createShadowPrimitive3D( 285*cdf0e10cSrcweir const Primitive3DSequence& rSource, 286*cdf0e10cSrcweir const attribute::SdrShadowAttribute& rShadow, 287*cdf0e10cSrcweir bool bShadow3D) 288*cdf0e10cSrcweir { 289*cdf0e10cSrcweir // create Shadow primitives. Uses already created primitives 290*cdf0e10cSrcweir if(rSource.hasElements() && !basegfx::fTools::moreOrEqual(rShadow.getTransparence(), 1.0)) 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir // prepare new list for shadow geometry 293*cdf0e10cSrcweir basegfx::B2DHomMatrix aShadowOffset; 294*cdf0e10cSrcweir aShadowOffset.set(0, 2, rShadow.getOffset().getX()); 295*cdf0e10cSrcweir aShadowOffset.set(1, 2, rShadow.getOffset().getY()); 296*cdf0e10cSrcweir 297*cdf0e10cSrcweir // create shadow primitive and add primitives 298*cdf0e10cSrcweir const Primitive3DReference xRef(new ShadowPrimitive3D(aShadowOffset, rShadow.getColor(), rShadow.getTransparence(), bShadow3D, rSource)); 299*cdf0e10cSrcweir return Primitive3DSequence(&xRef, 1L); 300*cdf0e10cSrcweir } 301*cdf0e10cSrcweir else 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir return Primitive3DSequence(); 304*cdf0e10cSrcweir } 305*cdf0e10cSrcweir } 306*cdf0e10cSrcweir 307*cdf0e10cSrcweir Primitive3DSequence createHiddenGeometryPrimitives3D( 308*cdf0e10cSrcweir const ::std::vector< basegfx::B3DPolyPolygon >& r3DPolyPolygonVector, 309*cdf0e10cSrcweir const basegfx::B3DHomMatrix& rObjectTransform, 310*cdf0e10cSrcweir const basegfx::B2DVector& rTextureSize, 311*cdf0e10cSrcweir const attribute::Sdr3DObjectAttribute& aSdr3DObjectAttribute) 312*cdf0e10cSrcweir { 313*cdf0e10cSrcweir // create hidden sub-geometry which can be used for HitTest 314*cdf0e10cSrcweir // and BoundRect calculations, but will not be visualized 315*cdf0e10cSrcweir const attribute::SdrFillAttribute aSimplifiedFillAttribute( 316*cdf0e10cSrcweir 0.0, 317*cdf0e10cSrcweir basegfx::BColor(), 318*cdf0e10cSrcweir attribute::FillGradientAttribute(), 319*cdf0e10cSrcweir attribute::FillHatchAttribute(), 320*cdf0e10cSrcweir attribute::SdrFillBitmapAttribute()); 321*cdf0e10cSrcweir 322*cdf0e10cSrcweir const Primitive3DReference aHidden( 323*cdf0e10cSrcweir new HiddenGeometryPrimitive3D( 324*cdf0e10cSrcweir create3DPolyPolygonFillPrimitives( 325*cdf0e10cSrcweir r3DPolyPolygonVector, 326*cdf0e10cSrcweir rObjectTransform, 327*cdf0e10cSrcweir rTextureSize, 328*cdf0e10cSrcweir aSdr3DObjectAttribute, 329*cdf0e10cSrcweir aSimplifiedFillAttribute, 330*cdf0e10cSrcweir attribute::FillGradientAttribute()))); 331*cdf0e10cSrcweir 332*cdf0e10cSrcweir return Primitive3DSequence(&aHidden, 1); 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir } // end of namespace primitive3d 336*cdf0e10cSrcweir } // end of namespace drawinglayer 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 339*cdf0e10cSrcweir // eof 340