| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_drawinglayer.hxx" |
| |
| #include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx> |
| #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx> |
| #include <basegfx/polygon/b2dpolypolygon.hxx> |
| #include <basegfx/polygon/b3dpolygon.hxx> |
| #include <basegfx/polygon/b2dpolygon.hxx> |
| #include <basegfx/polygon/b2dpolypolygontools.hxx> |
| #include <basegfx/range/b2drange.hxx> |
| #include <drawinglayer/texture/texture.hxx> |
| #include <basegfx/polygon/b2dpolygonclipper.hxx> |
| #include <basegfx/matrix/b3dhommatrix.hxx> |
| #include <drawinglayer/primitive3d/polygonprimitive3d.hxx> |
| #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx> |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| using namespace com::sun::star; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| namespace drawinglayer |
| { |
| namespace primitive3d |
| { |
| Primitive3DSequence HatchTexturePrimitive3D::impCreate3DDecomposition() const |
| { |
| Primitive3DSequence aRetval; |
| |
| if(getChildren().hasElements()) |
| { |
| const Primitive3DSequence aSource(getChildren()); |
| const sal_uInt32 nSourceCount(aSource.getLength()); |
| std::vector< Primitive3DReference > aDestination; |
| |
| for(sal_uInt32 a(0); a < nSourceCount; a++) |
| { |
| // get reference |
| const Primitive3DReference xReference(aSource[a]); |
| |
| if(xReference.is()) |
| { |
| // try to cast to BasePrimitive2D implementation |
| const BasePrimitive3D* pBasePrimitive = dynamic_cast< const BasePrimitive3D* >(xReference.get()); |
| |
| if(pBasePrimitive) |
| { |
| // it is a BasePrimitive3D implementation, use getPrimitive3DID() call for switch |
| // not all content is needed, remove transparencies and ModifiedColorPrimitives |
| switch(pBasePrimitive->getPrimitive3DID()) |
| { |
| case PRIMITIVE3D_ID_POLYPOLYGONMATERIALPRIMITIVE3D : |
| { |
| // polyPolygonMaterialPrimitive3D, check texturing and hatching |
| const PolyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const PolyPolygonMaterialPrimitive3D& >(*pBasePrimitive); |
| const basegfx::B3DPolyPolygon aFillPolyPolygon(rPrimitive.getB3DPolyPolygon()); |
| |
| if(maHatch.isFillBackground()) |
| { |
| // add original primitive for background |
| aDestination.push_back(xReference); |
| } |
| |
| if(aFillPolyPolygon.areTextureCoordinatesUsed()) |
| { |
| const sal_uInt32 nPolyCount(aFillPolyPolygon.count()); |
| basegfx::B2DPolyPolygon aTexPolyPolygon; |
| basegfx::B2DPoint a2N; |
| basegfx::B2DVector a2X, a2Y; |
| basegfx::B3DPoint a3N; |
| basegfx::B3DVector a3X, a3Y; |
| bool b2N(false), b2X(false), b2Y(false); |
| |
| for(sal_uInt32 b(0); b < nPolyCount; b++) |
| { |
| const basegfx::B3DPolygon aPartPoly(aFillPolyPolygon.getB3DPolygon(b)); |
| const sal_uInt32 nPointCount(aPartPoly.count()); |
| basegfx::B2DPolygon aTexPolygon; |
| |
| for(sal_uInt32 c(0); c < nPointCount; c++) |
| { |
| const basegfx::B2DPoint a2Candidate(aPartPoly.getTextureCoordinate(c)); |
| |
| if(!b2N) |
| { |
| a2N = a2Candidate; |
| a3N = aPartPoly.getB3DPoint(c); |
| b2N = true; |
| } |
| else if(!b2X && !a2N.equal(a2Candidate)) |
| { |
| a2X = a2Candidate - a2N; |
| a3X = aPartPoly.getB3DPoint(c) - a3N; |
| b2X = true; |
| } |
| else if(!b2Y && !a2N.equal(a2Candidate) && !a2X.equal(a2Candidate)) |
| { |
| a2Y = a2Candidate - a2N; |
| |
| const double fCross(a2X.cross(a2Y)); |
| |
| if(!basegfx::fTools::equalZero(fCross)) |
| { |
| a3Y = aPartPoly.getB3DPoint(c) - a3N; |
| b2Y = true; |
| } |
| } |
| |
| aTexPolygon.append(a2Candidate); |
| } |
| |
| aTexPolygon.setClosed(true); |
| aTexPolyPolygon.append(aTexPolygon); |
| } |
| |
| if(b2N && b2X && b2Y) |
| { |
| // found two linearly independent 2D vectors |
| // get 2d range of texture coordinates |
| const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aTexPolyPolygon)); |
| const basegfx::BColor aHatchColor(getHatch().getColor()); |
| const double fAngle(getHatch().getAngle()); |
| ::std::vector< basegfx::B2DHomMatrix > aMatrices; |
| |
| // get hatch transformations |
| switch(getHatch().getStyle()) |
| { |
| case attribute::HATCHSTYLE_TRIPLE: |
| { |
| // rotated 45 degrees |
| texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle - F_PI4); |
| aHatch.appendTransformations(aMatrices); |
| } |
| case attribute::HATCHSTYLE_DOUBLE: |
| { |
| // rotated 90 degrees |
| texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle - F_PI2); |
| aHatch.appendTransformations(aMatrices); |
| } |
| case attribute::HATCHSTYLE_SINGLE: |
| { |
| // angle as given |
| texture::GeoTexSvxHatch aHatch(aOutlineRange, getHatch().getDistance(), fAngle); |
| aHatch.appendTransformations(aMatrices); |
| } |
| } |
| |
| // create geometry from unit line |
| basegfx::B2DPolyPolygon a2DHatchLines; |
| basegfx::B2DPolygon a2DUnitLine; |
| a2DUnitLine.append(basegfx::B2DPoint(0.0, 0.0)); |
| a2DUnitLine.append(basegfx::B2DPoint(1.0, 0.0)); |
| |
| for(sal_uInt32 c(0); c < aMatrices.size(); c++) |
| { |
| const basegfx::B2DHomMatrix& rMatrix = aMatrices[c]; |
| basegfx::B2DPolygon aNewLine(a2DUnitLine); |
| aNewLine.transform(rMatrix); |
| a2DHatchLines.append(aNewLine); |
| } |
| |
| if(a2DHatchLines.count()) |
| { |
| // clip against texture polygon |
| a2DHatchLines = basegfx::tools::clipPolyPolygonOnPolyPolygon(a2DHatchLines, aTexPolyPolygon, true, true); |
| } |
| |
| if(a2DHatchLines.count()) |
| { |
| // create 2d matrix with 2d vectors as column vectors and 2d point as offset, this represents |
| // a coordinate system transformation from unit coordinates to the new coordinate system |
| basegfx::B2DHomMatrix a2D; |
| a2D.set(0, 0, a2X.getX()); |
| a2D.set(1, 0, a2X.getY()); |
| a2D.set(0, 1, a2Y.getX()); |
| a2D.set(1, 1, a2Y.getY()); |
| a2D.set(0, 2, a2N.getX()); |
| a2D.set(1, 2, a2N.getY()); |
| |
| // invert that transformation, so we have a back-transformation from texture coordinates |
| // to unit coordinates |
| a2D.invert(); |
| a2DHatchLines.transform(a2D); |
| |
| // expand back-transformated geometry tpo 3D |
| basegfx::B3DPolyPolygon a3DHatchLines(basegfx::tools::createB3DPolyPolygonFromB2DPolyPolygon(a2DHatchLines, 0.0)); |
| |
| // create 3d matrix with 3d vectors as column vectors (0,0,1 as Z) and 3d point as offset, this represents |
| // a coordinate system transformation from unit coordinates to the object's 3d coordinate system |
| basegfx::B3DHomMatrix a3D; |
| a3D.set(0, 0, a3X.getX()); |
| a3D.set(1, 0, a3X.getY()); |
| a3D.set(2, 0, a3X.getZ()); |
| a3D.set(0, 1, a3Y.getX()); |
| a3D.set(1, 1, a3Y.getY()); |
| a3D.set(2, 1, a3Y.getZ()); |
| a3D.set(0, 3, a3N.getX()); |
| a3D.set(1, 3, a3N.getY()); |
| a3D.set(2, 3, a3N.getZ()); |
| |
| // transform hatch lines to 3D object coordinates |
| a3DHatchLines.transform(a3D); |
| |
| // build primitives from this geometry |
| const sal_uInt32 nHatchLines(a3DHatchLines.count()); |
| |
| for(sal_uInt32 d(0); d < nHatchLines; d++) |
| { |
| const Primitive3DReference xRef(new PolygonHairlinePrimitive3D(a3DHatchLines.getB3DPolygon(d), aHatchColor)); |
| aDestination.push_back(xRef); |
| } |
| } |
| } |
| } |
| |
| break; |
| } |
| default : |
| { |
| // add reference to result |
| aDestination.push_back(xReference); |
| break; |
| } |
| } |
| } |
| else |
| { |
| // unknown implementation, add to result |
| aDestination.push_back(xReference); |
| } |
| } |
| } |
| |
| // prepare return value |
| const sal_uInt32 nDestSize(aDestination.size()); |
| aRetval.realloc(nDestSize); |
| |
| for(sal_uInt32 b(0); b < nDestSize; b++) |
| { |
| aRetval[b] = aDestination[b]; |
| } |
| } |
| |
| return aRetval; |
| } |
| |
| HatchTexturePrimitive3D::HatchTexturePrimitive3D( |
| const attribute::FillHatchAttribute& rHatch, |
| const Primitive3DSequence& rChildren, |
| const basegfx::B2DVector& rTextureSize, |
| bool bModulate, |
| bool bFilter) |
| : TexturePrimitive3D(rChildren, rTextureSize, bModulate, bFilter), |
| maHatch(rHatch), |
| maBuffered3DDecomposition() |
| { |
| } |
| |
| bool HatchTexturePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const |
| { |
| if(TexturePrimitive3D::operator==(rPrimitive)) |
| { |
| const HatchTexturePrimitive3D& rCompare = (HatchTexturePrimitive3D&)rPrimitive; |
| |
| return (getHatch() == rCompare.getHatch()); |
| } |
| |
| return false; |
| } |
| |
| Primitive3DSequence HatchTexturePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const |
| { |
| ::osl::MutexGuard aGuard( m_aMutex ); |
| |
| if(!getBuffered3DDecomposition().hasElements()) |
| { |
| const Primitive3DSequence aNewSequence(impCreate3DDecomposition()); |
| const_cast< HatchTexturePrimitive3D* >(this)->setBuffered3DDecomposition(aNewSequence); |
| } |
| |
| return getBuffered3DDecomposition(); |
| } |
| |
| // provide unique ID |
| ImplPrimitrive3DIDBlock(HatchTexturePrimitive3D, PRIMITIVE3D_ID_HATCHTEXTUREPRIMITIVE3D) |
| |
| } // end of namespace primitive3d |
| } // end of namespace drawinglayer |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // eof |