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/hatchtextureprimitive3d.hxx> 32*cdf0e10cSrcweir #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx> 33*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx> 34*cdf0e10cSrcweir #include <basegfx/polygon/b3dpolygon.hxx> 35*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx> 36*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx> 37*cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx> 38*cdf0e10cSrcweir #include <drawinglayer/texture/texture.hxx> 39*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygonclipper.hxx> 40*cdf0e10cSrcweir #include <basegfx/matrix/b3dhommatrix.hxx> 41*cdf0e10cSrcweir #include <drawinglayer/primitive3d/polygonprimitive3d.hxx> 42*cdf0e10cSrcweir #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 45*cdf0e10cSrcweir 46*cdf0e10cSrcweir using namespace com::sun::star; 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir namespace drawinglayer 51*cdf0e10cSrcweir { 52*cdf0e10cSrcweir namespace primitive3d 53*cdf0e10cSrcweir { 54*cdf0e10cSrcweir Primitive3DSequence HatchTexturePrimitive3D::impCreate3DDecomposition() const 55*cdf0e10cSrcweir { 56*cdf0e10cSrcweir Primitive3DSequence aRetval; 57*cdf0e10cSrcweir 58*cdf0e10cSrcweir if(getChildren().hasElements()) 59*cdf0e10cSrcweir { 60*cdf0e10cSrcweir const Primitive3DSequence aSource(getChildren()); 61*cdf0e10cSrcweir const sal_uInt32 nSourceCount(aSource.getLength()); 62*cdf0e10cSrcweir std::vector< Primitive3DReference > aDestination; 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir for(sal_uInt32 a(0); a < nSourceCount; a++) 65*cdf0e10cSrcweir { 66*cdf0e10cSrcweir // get reference 67*cdf0e10cSrcweir const Primitive3DReference xReference(aSource[a]); 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir if(xReference.is()) 70*cdf0e10cSrcweir { 71*cdf0e10cSrcweir // try to cast to BasePrimitive2D implementation 72*cdf0e10cSrcweir const BasePrimitive3D* pBasePrimitive = dynamic_cast< const BasePrimitive3D* >(xReference.get()); 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir if(pBasePrimitive) 75*cdf0e10cSrcweir { 76*cdf0e10cSrcweir // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch 77*cdf0e10cSrcweir // not all content is needed, remove transparencies and ModifiedColorPrimitives 78*cdf0e10cSrcweir switch(pBasePrimitive->getPrimitive3DID()) 79*cdf0e10cSrcweir { 80*cdf0e10cSrcweir case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D : 81*cdf0e10cSrcweir { 82*cdf0e10cSrcweir // polyPolygonMaterialPrimitive3D, check texturing and hatching 83*cdf0e10cSrcweir const PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const PolyPolygonMaterialPrimitive3D& >(*pBasePrimitive); 84*cdf0e10cSrcweir const basegfx::B3DPolyPolygon aFillPolyPolygon(rPrimitive.getB3DPolyPolygon()); 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir if(maHatch.isFillBackground()) 87*cdf0e10cSrcweir { 88*cdf0e10cSrcweir // add original primitive for background 89*cdf0e10cSrcweir aDestination.push_back(xReference); 90*cdf0e10cSrcweir } 91*cdf0e10cSrcweir 92*cdf0e10cSrcweir if(aFillPolyPolygon.areTextureCoordinatesUsed()) 93*cdf0e10cSrcweir { 94*cdf0e10cSrcweir const sal_uInt32 nPolyCount(aFillPolyPolygon.count()); 95*cdf0e10cSrcweir basegfx::B2DPolyPolygon aTexPolyPolygon; 96*cdf0e10cSrcweir basegfx::B2DPoint a2N; 97*cdf0e10cSrcweir basegfx::B2DVector a2X, a2Y; 98*cdf0e10cSrcweir basegfx::B3DPoint a3N; 99*cdf0e10cSrcweir basegfx::B3DVector a3X, a3Y; 100*cdf0e10cSrcweir bool b2N(false), b2X(false), b2Y(false); 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir for(sal_uInt32 b(0); b < nPolyCount; b++) 103*cdf0e10cSrcweir { 104*cdf0e10cSrcweir const basegfx::B3DPolygon aPartPoly(aFillPolyPolygon.getB3DPolygon(b)); 105*cdf0e10cSrcweir const sal_uInt32 nPointCount(aPartPoly.count()); 106*cdf0e10cSrcweir basegfx::B2DPolygon aTexPolygon; 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir for(sal_uInt32 c(0); c < nPointCount; c++) 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir const basegfx::B2DPoint a2Candidate(aPartPoly.getTextureCoordinate(c)); 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir if(!b2N) 113*cdf0e10cSrcweir { 114*cdf0e10cSrcweir a2N = a2Candidate; 115*cdf0e10cSrcweir a3N = aPartPoly.getB3DPoint(c); 116*cdf0e10cSrcweir b2N = true; 117*cdf0e10cSrcweir } 118*cdf0e10cSrcweir else if(!b2X && !a2N.equal(a2Candidate)) 119*cdf0e10cSrcweir { 120*cdf0e10cSrcweir a2X = a2Candidate - a2N; 121*cdf0e10cSrcweir a3X = aPartPoly.getB3DPoint(c) - a3N; 122*cdf0e10cSrcweir b2X = true; 123*cdf0e10cSrcweir } 124*cdf0e10cSrcweir else if(!b2Y && !a2N.equal(a2Candidate) && !a2X.equal(a2Candidate)) 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir a2Y = a2Candidate - a2N; 127*cdf0e10cSrcweir 128*cdf0e10cSrcweir const double fCross(a2X.cross(a2Y)); 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir if(!basegfx::fTools::equalZero(fCross)) 131*cdf0e10cSrcweir { 132*cdf0e10cSrcweir a3Y = aPartPoly.getB3DPoint(c) - a3N; 133*cdf0e10cSrcweir b2Y = true; 134*cdf0e10cSrcweir } 135*cdf0e10cSrcweir } 136*cdf0e10cSrcweir 137*cdf0e10cSrcweir aTexPolygon.append(a2Candidate); 138*cdf0e10cSrcweir } 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir aTexPolygon.setClosed(true); 141*cdf0e10cSrcweir aTexPolyPolygon.append(aTexPolygon); 142*cdf0e10cSrcweir } 143*cdf0e10cSrcweir 144*cdf0e10cSrcweir if(b2N && b2X && b2Y) 145*cdf0e10cSrcweir { 146*cdf0e10cSrcweir // found two linearly independent 2D vectors 147*cdf0e10cSrcweir // get 2d range of texture coordinates 148*cdf0e10cSrcweir const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aTexPolyPolygon)); 149*cdf0e10cSrcweir const basegfx::BColor aHatchColor(getHatch().getColor()); 150*cdf0e10cSrcweir const double fAngle(getHatch().getAngle()); 151*cdf0e10cSrcweir ::std::vector< basegfx::B2DHomMatrix > aMatrices; 152*cdf0e10cSrcweir 153*cdf0e10cSrcweir // get hatch transformations 154*cdf0e10cSrcweir switch(getHatch().getStyle()) 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir case attribute::HATCHSTYLE_TRIPLE: 157*cdf0e10cSrcweir { 158*cdf0e10cSrcweir // rotated 45 degrees 159*cdf0e10cSrcweir texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle - F_PI4); 160*cdf0e10cSrcweir aHatch.appendTransformations(aMatrices); 161*cdf0e10cSrcweir } 162*cdf0e10cSrcweir case attribute::HATCHSTYLE_DOUBLE: 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir // rotated 90 degrees 165*cdf0e10cSrcweir texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle - F_PI2); 166*cdf0e10cSrcweir aHatch.appendTransformations(aMatrices); 167*cdf0e10cSrcweir } 168*cdf0e10cSrcweir case attribute::HATCHSTYLE_SINGLE: 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir // angle as given 171*cdf0e10cSrcweir texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle); 172*cdf0e10cSrcweir aHatch.appendTransformations(aMatrices); 173*cdf0e10cSrcweir } 174*cdf0e10cSrcweir } 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir // create geometry from unit line 177*cdf0e10cSrcweir basegfx::B2DPolyPolygon a2DHatchLines; 178*cdf0e10cSrcweir basegfx::B2DPolygon a2DUnitLine; 179*cdf0e10cSrcweir a2DUnitLine.append(basegfx::B2DPoint(0.0, 0.0)); 180*cdf0e10cSrcweir a2DUnitLine.append(basegfx::B2DPoint(1.0, 0.0)); 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir for(sal_uInt32 c(0); c < aMatrices.size(); c++) 183*cdf0e10cSrcweir { 184*cdf0e10cSrcweir const basegfx::B2DHomMatrix& rMatrix = aMatrices[c]; 185*cdf0e10cSrcweir basegfx::B2DPolygon aNewLine(a2DUnitLine); 186*cdf0e10cSrcweir aNewLine.transform(rMatrix); 187*cdf0e10cSrcweir a2DHatchLines.append(aNewLine); 188*cdf0e10cSrcweir } 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir if(a2DHatchLines.count()) 191*cdf0e10cSrcweir { 192*cdf0e10cSrcweir // clip against texture polygon 193*cdf0e10cSrcweir a2DHatchLines = basegfx::tools::clipPolyPolygonOnPolyPolygon(a2DHatchLines, aTexPolyPolygon, true, true); 194*cdf0e10cSrcweir } 195*cdf0e10cSrcweir 196*cdf0e10cSrcweir if(a2DHatchLines.count()) 197*cdf0e10cSrcweir { 198*cdf0e10cSrcweir // create 2d matrix with 2d vectors as column vectors and 2d point as offset, this represents 199*cdf0e10cSrcweir // a coordinate system transformation from unit coordinates to the new coordinate system 200*cdf0e10cSrcweir basegfx::B2DHomMatrix a2D; 201*cdf0e10cSrcweir a2D.set(0, 0, a2X.getX()); 202*cdf0e10cSrcweir a2D.set(1, 0, a2X.getY()); 203*cdf0e10cSrcweir a2D.set(0, 1, a2Y.getX()); 204*cdf0e10cSrcweir a2D.set(1, 1, a2Y.getY()); 205*cdf0e10cSrcweir a2D.set(0, 2, a2N.getX()); 206*cdf0e10cSrcweir a2D.set(1, 2, a2N.getY()); 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir // invert that transformation, so we have a back-transformation from texture coordinates 209*cdf0e10cSrcweir // to unit coordinates 210*cdf0e10cSrcweir a2D.invert(); 211*cdf0e10cSrcweir a2DHatchLines.transform(a2D); 212*cdf0e10cSrcweir 213*cdf0e10cSrcweir // expand back-transformated geometry tpo 3D 214*cdf0e10cSrcweir basegfx::B3DPolyPolygon a3DHatchLines(basegfx::tools::createB3DPolyPolygonFromB2DPolyPolygon(a2DHatchLines, 0.0)); 215*cdf0e10cSrcweir 216*cdf0e10cSrcweir // create 3d matrix with 3d vectors as column vectors (0,0,1 as Z) and 3d point as offset, this represents 217*cdf0e10cSrcweir // a coordinate system transformation from unit coordinates to the object's 3d coordinate system 218*cdf0e10cSrcweir basegfx::B3DHomMatrix a3D; 219*cdf0e10cSrcweir a3D.set(0, 0, a3X.getX()); 220*cdf0e10cSrcweir a3D.set(1, 0, a3X.getY()); 221*cdf0e10cSrcweir a3D.set(2, 0, a3X.getZ()); 222*cdf0e10cSrcweir a3D.set(0, 1, a3Y.getX()); 223*cdf0e10cSrcweir a3D.set(1, 1, a3Y.getY()); 224*cdf0e10cSrcweir a3D.set(2, 1, a3Y.getZ()); 225*cdf0e10cSrcweir a3D.set(0, 3, a3N.getX()); 226*cdf0e10cSrcweir a3D.set(1, 3, a3N.getY()); 227*cdf0e10cSrcweir a3D.set(2, 3, a3N.getZ()); 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir // transform hatch lines to 3D object coordinates 230*cdf0e10cSrcweir a3DHatchLines.transform(a3D); 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir // build primitives from this geometry 233*cdf0e10cSrcweir const sal_uInt32 nHatchLines(a3DHatchLines.count()); 234*cdf0e10cSrcweir 235*cdf0e10cSrcweir for(sal_uInt32 d(0); d < nHatchLines; d++) 236*cdf0e10cSrcweir { 237*cdf0e10cSrcweir const Primitive3DReference xRef(new PolygonHairlinePrimitive3D(a3DHatchLines.getB3DPolygon(d), aHatchColor)); 238*cdf0e10cSrcweir aDestination.push_back(xRef); 239*cdf0e10cSrcweir } 240*cdf0e10cSrcweir } 241*cdf0e10cSrcweir } 242*cdf0e10cSrcweir } 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir break; 245*cdf0e10cSrcweir } 246*cdf0e10cSrcweir default : 247*cdf0e10cSrcweir { 248*cdf0e10cSrcweir // add reference to result 249*cdf0e10cSrcweir aDestination.push_back(xReference); 250*cdf0e10cSrcweir break; 251*cdf0e10cSrcweir } 252*cdf0e10cSrcweir } 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir else 255*cdf0e10cSrcweir { 256*cdf0e10cSrcweir // unknown implementation, add to result 257*cdf0e10cSrcweir aDestination.push_back(xReference); 258*cdf0e10cSrcweir } 259*cdf0e10cSrcweir } 260*cdf0e10cSrcweir } 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir // prepare return value 263*cdf0e10cSrcweir const sal_uInt32 nDestSize(aDestination.size()); 264*cdf0e10cSrcweir aRetval.realloc(nDestSize); 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir for(sal_uInt32 b(0); b < nDestSize; b++) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir aRetval[b] = aDestination[b]; 269*cdf0e10cSrcweir } 270*cdf0e10cSrcweir } 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir return aRetval; 273*cdf0e10cSrcweir } 274*cdf0e10cSrcweir 275*cdf0e10cSrcweir HatchTexturePrimitive3D::HatchTexturePrimitive3D( 276*cdf0e10cSrcweir const attribute::FillHatchAttribute& rHatch, 277*cdf0e10cSrcweir const Primitive3DSequence& rChildren, 278*cdf0e10cSrcweir const basegfx::B2DVector& rTextureSize, 279*cdf0e10cSrcweir bool bModulate, 280*cdf0e10cSrcweir bool bFilter) 281*cdf0e10cSrcweir : TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter), 282*cdf0e10cSrcweir maHatch(rHatch), 283*cdf0e10cSrcweir maBuffered3DDecomposition() 284*cdf0e10cSrcweir { 285*cdf0e10cSrcweir } 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir bool HatchTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const 288*cdf0e10cSrcweir { 289*cdf0e10cSrcweir if(TexturePrimitive3D::operator==(rPrimitive)) 290*cdf0e10cSrcweir { 291*cdf0e10cSrcweir const HatchTexturePrimitive3D& rCompare = (HatchTexturePrimitive3D&)rPrimitive; 292*cdf0e10cSrcweir 293*cdf0e10cSrcweir return (getHatch() == rCompare.getHatch()); 294*cdf0e10cSrcweir } 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir return false; 297*cdf0e10cSrcweir } 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir Primitive3DSequence HatchTexturePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const 300*cdf0e10cSrcweir { 301*cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 302*cdf0e10cSrcweir 303*cdf0e10cSrcweir if(!getBuffered3DDecomposition().hasElements()) 304*cdf0e10cSrcweir { 305*cdf0e10cSrcweir const Primitive3DSequence aNewSequence(impCreate3DDecomposition()); 306*cdf0e10cSrcweir const_cast< HatchTexturePrimitive3D* >(this)->setBuffered3DDecomposition(aNewSequence); 307*cdf0e10cSrcweir } 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir return getBuffered3DDecomposition(); 310*cdf0e10cSrcweir } 311*cdf0e10cSrcweir 312*cdf0e10cSrcweir // provide unique ID 313*cdf0e10cSrcweir ImplPrimitrive3DIDBlock(HatchTexturePrimitive3D, PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D) 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir } // end of namespace primitive3d 316*cdf0e10cSrcweir } // end of namespace drawinglayer 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 319*cdf0e10cSrcweir // eof 320