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