xref: /trunk/main/drawinglayer/source/primitive3d/hatchtextureprimitive3d.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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