tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / drawinglayer / source / primitive3d / sdrlatheprimitive3d.cxx
blob682ea0c54042ea0e476d191461182e26a4cd4dd5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <drawinglayer/primitive3d/sdrlatheprimitive3d.hxx>
21 #include <basegfx/matrix/b2dhommatrix.hxx>
22 #include <basegfx/polygon/b3dpolygon.hxx>
23 #include <primitive3d/sdrdecompositiontools3d.hxx>
24 #include <drawinglayer/primitive3d/drawinglayer_primitivetypes3d.hxx>
25 #include <drawinglayer/geometry/viewinformation3d.hxx>
26 #include <drawinglayer/attribute/sdrfillattribute.hxx>
27 #include <drawinglayer/attribute/sdrlineattribute.hxx>
28 #include <drawinglayer/attribute/sdrshadowattribute.hxx>
29 #include <utility>
32 using namespace com::sun::star;
35 namespace drawinglayer::primitive3d
37 Primitive3DContainer SdrLathePrimitive3D::create3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
39 Primitive3DContainer aRetval;
41 // get slices
42 const Slice3DVector& rSliceVector = getSlices();
44 if(!rSliceVector.empty())
46 const bool bBackScale(!basegfx::fTools::equal(getBackScale(), 1.0));
47 const bool bClosedRotation(!bBackScale && getHorizontalSegments() && basegfx::fTools::equal(getRotation(), 2 * M_PI));
48 sal_uInt32 a;
50 // decide what to create
51 const css::drawing::NormalsKind eNormalsKind(getSdr3DObjectAttribute().getNormalsKind());
52 const bool bCreateNormals(css::drawing::NormalsKind_SPECIFIC == eNormalsKind);
53 const bool bCreateTextureCoordinatesX(css::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionX());
54 const bool bCreateTextureCoordinatesY(css::drawing::TextureProjectionMode_OBJECTSPECIFIC == getSdr3DObjectAttribute().getTextureProjectionY());
55 basegfx::B2DHomMatrix aTexTransform;
57 if(!getSdrLFSAttribute().getFill().isDefault()
58 && (bCreateTextureCoordinatesX || bCreateTextureCoordinatesY))
60 aTexTransform.set(0, 0, 0.0);
61 aTexTransform.set(0, 1, 1.0);
62 aTexTransform.set(1, 0, 1.0);
63 aTexTransform.set(1, 1, 0.0);
65 aTexTransform.translate(0.0, -0.5);
66 aTexTransform.scale(1.0, -1.0);
67 aTexTransform.translate(0.0, 0.5);
70 // create geometry
71 std::vector< basegfx::B3DPolyPolygon > aFill;
72 extractPlanesFromSlice(aFill, rSliceVector,
73 bCreateNormals, getSmoothNormals(), getSmoothLids(), bClosedRotation,
74 0.85, 0.6, bCreateTextureCoordinatesX || bCreateTextureCoordinatesY, aTexTransform);
76 // get full range
77 const basegfx::B3DRange aRange(getRangeFrom3DGeometry(aFill));
79 // normal creation
80 if(!getSdrLFSAttribute().getFill().isDefault())
82 if(css::drawing::NormalsKind_SPHERE == eNormalsKind)
84 applyNormalsKindSphereTo3DGeometry(aFill, aRange);
86 else if(css::drawing::NormalsKind_FLAT == eNormalsKind)
88 applyNormalsKindFlatTo3DGeometry(aFill);
91 if(getSdr3DObjectAttribute().getNormalsInvert())
93 applyNormalsInvertTo3DGeometry(aFill);
97 // texture coordinates
98 if(!getSdrLFSAttribute().getFill().isDefault())
100 applyTextureTo3DGeometry(
101 getSdr3DObjectAttribute().getTextureProjectionX(),
102 getSdr3DObjectAttribute().getTextureProjectionY(),
103 aFill,
104 aRange,
105 getTextureSize());
108 if(!getSdrLFSAttribute().getFill().isDefault())
110 // add fill
111 aRetval = create3DPolyPolygonFillPrimitives(
112 aFill,
113 getTransform(),
114 getTextureSize(),
115 getSdr3DObjectAttribute(),
116 getSdrLFSAttribute().getFill(),
117 getSdrLFSAttribute().getFillFloatTransGradient());
119 else
121 // create simplified 3d hit test geometry
122 aRetval = createHiddenGeometryPrimitives3D(
123 aFill,
124 getTransform(),
125 getTextureSize(),
126 getSdr3DObjectAttribute());
129 // add line
130 if(!getSdrLFSAttribute().getLine().isDefault())
132 if(getSdr3DObjectAttribute().getReducedLineGeometry())
134 // create geometric outlines with reduced line geometry for chart
135 const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
136 const sal_uInt32 nCount(aHorLine.count());
137 basegfx::B3DPolyPolygon aNewLineGeometry;
139 for(a = 1; a < nCount; a++)
141 // for each loop pair create the connection edges
142 createReducedOutlines(
143 rViewInformation,
144 getTransform(),
145 aHorLine.getB3DPolygon(a - 1),
146 aHorLine.getB3DPolygon(a),
147 aNewLineGeometry);
150 for(a = 0; a < nCount; a++)
152 // filter hor lines for empty loops (those who have their defining point on the Y-Axis)
153 basegfx::B3DPolygon aCandidate(aHorLine.getB3DPolygon(a));
154 aCandidate.removeDoublePoints();
156 if(aCandidate.count())
158 aNewLineGeometry.append(aCandidate);
162 if(aNewLineGeometry.count())
164 const Primitive3DContainer aLines(create3DPolyPolygonLinePrimitives(
165 aNewLineGeometry, getTransform(), getSdrLFSAttribute().getLine()));
166 aRetval.append(aLines);
169 else
171 // extract line geometry from slices
172 const basegfx::B3DPolyPolygon aHorLine(extractHorizontalLinesFromSlice(rSliceVector, bClosedRotation));
173 const basegfx::B3DPolyPolygon aVerLine(extractVerticalLinesFromSlice(rSliceVector));
175 // add horizontal lines
176 const Primitive3DContainer aHorLines(create3DPolyPolygonLinePrimitives(
177 aHorLine, getTransform(), getSdrLFSAttribute().getLine()));
178 aRetval.append(aHorLines);
180 // add vertical lines
181 const Primitive3DContainer aVerLines(create3DPolyPolygonLinePrimitives(
182 aVerLine, getTransform(), getSdrLFSAttribute().getLine()));
183 aRetval.append(aVerLines);
187 // add shadow
188 if(!getSdrLFSAttribute().getShadow().isDefault()
189 && !aRetval.empty())
191 const Primitive3DContainer aShadow(createShadowPrimitive3D(
192 aRetval, getSdrLFSAttribute().getShadow(), getSdr3DObjectAttribute().getShadow3D()));
193 aRetval.append(aShadow);
197 return aRetval;
200 void SdrLathePrimitive3D::impCreateSlices()
202 // prepare the polygon. No double points, correct orientations and a correct
203 // outmost polygon are needed
204 // Also important: subdivide here to ensure equal point count for all slices (!)
205 maCorrectedPolyPolygon = basegfx::utils::adaptiveSubdivideByAngle(getPolyPolygon());
206 maCorrectedPolyPolygon.removeDoublePoints();
207 maCorrectedPolyPolygon = basegfx::utils::correctOrientations(maCorrectedPolyPolygon);
208 maCorrectedPolyPolygon = basegfx::utils::correctOutmostPolygon(maCorrectedPolyPolygon);
210 // check edge count of first sub-polygon. If different, reSegment polyPolygon. This ensures
211 // that for polyPolygons, the subPolys 1..n only get reSegmented when polygon 0 is different
212 // at all (and not always)
213 const basegfx::B2DPolygon aSubCandidate(maCorrectedPolyPolygon.getB2DPolygon(0));
214 const sal_uInt32 nSubEdgeCount(aSubCandidate.isClosed() ? aSubCandidate.count() : (aSubCandidate.count() ? aSubCandidate.count() - 1 : 0));
216 if(nSubEdgeCount != getVerticalSegments())
218 maCorrectedPolyPolygon = basegfx::utils::reSegmentPolyPolygon(maCorrectedPolyPolygon, getVerticalSegments());
221 // prepare slices as geometry
222 createLatheSlices(maSlices, maCorrectedPolyPolygon, getBackScale(), getDiagonal(), getRotation(), getHorizontalSegments(), getCharacterMode(), getCloseFront(), getCloseBack());
225 const Slice3DVector& SdrLathePrimitive3D::getSlices() const
227 // This can be made dependent of getSdrLFSAttribute().getFill() and getSdrLFSAttribute().getLine()
228 // again when no longer geometry is needed for non-visible 3D objects as it is now for chart
229 if(getPolyPolygon().count() && maSlices.empty())
231 std::unique_lock aGuard( m_aMutex );
233 const_cast< SdrLathePrimitive3D& >(*this).impCreateSlices();
236 return maSlices;
239 SdrLathePrimitive3D::SdrLathePrimitive3D(
240 const basegfx::B3DHomMatrix& rTransform,
241 const basegfx::B2DVector& rTextureSize,
242 const attribute::SdrLineFillShadowAttribute3D& rSdrLFSAttribute,
243 const attribute::Sdr3DObjectAttribute& rSdr3DObjectAttribute,
244 basegfx::B2DPolyPolygon aPolyPolygon,
245 sal_uInt32 nHorizontalSegments,
246 sal_uInt32 nVerticalSegments,
247 double fDiagonal,
248 double fBackScale,
249 double fRotation,
250 bool bSmoothNormals,
251 bool bSmoothLids,
252 bool bCharacterMode,
253 bool bCloseFront,
254 bool bCloseBack)
255 : SdrPrimitive3D(rTransform, rTextureSize, rSdrLFSAttribute, rSdr3DObjectAttribute),
256 maPolyPolygon(std::move(aPolyPolygon)),
257 mnHorizontalSegments(nHorizontalSegments),
258 mnVerticalSegments(nVerticalSegments),
259 mfDiagonal(fDiagonal),
260 mfBackScale(fBackScale),
261 mfRotation(fRotation),
262 mbSmoothNormals(bSmoothNormals),
263 mbSmoothLids(bSmoothLids),
264 mbCharacterMode(bCharacterMode),
265 mbCloseFront(bCloseFront),
266 mbCloseBack(bCloseBack)
268 // make sure Rotation is positive
269 if(getRotation() <= 0.0)
271 mfRotation = 0.0;
274 // make sure the percentage value getDiagonal() is between 0.0 and 1.0
275 if(getDiagonal() <= 0.0)
277 mfDiagonal = 0.0;
279 else if(basegfx::fTools::moreOrEqual(getDiagonal(), 1.0))
281 mfDiagonal = 1.0;
284 // no close front/back when polygon is not closed
285 if(getPolyPolygon().count() && !getPolyPolygon().getB2DPolygon(0).isClosed())
287 mbCloseFront = mbCloseBack = false;
290 // no edge rounding when not closing
291 if(!getCloseFront() && !getCloseBack())
293 mfDiagonal = 0.0;
297 SdrLathePrimitive3D::~SdrLathePrimitive3D()
301 bool SdrLathePrimitive3D::operator==(const BasePrimitive3D& rPrimitive) const
303 if(SdrPrimitive3D::operator==(rPrimitive))
305 const SdrLathePrimitive3D& rCompare = static_cast< const SdrLathePrimitive3D& >(rPrimitive);
307 return (getPolyPolygon() == rCompare.getPolyPolygon()
308 && getHorizontalSegments() == rCompare.getHorizontalSegments()
309 && getVerticalSegments() == rCompare.getVerticalSegments()
310 && getDiagonal() == rCompare.getDiagonal()
311 && getBackScale() == rCompare.getBackScale()
312 && getRotation() == rCompare.getRotation()
313 && getSmoothNormals() == rCompare.getSmoothNormals()
314 && getSmoothLids() == rCompare.getSmoothLids()
315 && getCharacterMode() == rCompare.getCharacterMode()
316 && getCloseFront() == rCompare.getCloseFront()
317 && getCloseBack() == rCompare.getCloseBack());
320 return false;
323 basegfx::B3DRange SdrLathePrimitive3D::getB3DRange(const geometry::ViewInformation3D& /*rViewInformation*/) const
325 // use default from sdrPrimitive3D which uses transformation expanded by line width/2
326 // The parent implementation which uses the ranges of the decomposition would be more
327 // correct, but for historical reasons it is necessary to do the old method: To get
328 // the range of the non-transformed geometry and transform it then. This leads to different
329 // ranges where the new method is more correct, but the need to keep the old behaviour
330 // has priority here.
331 return get3DRangeFromSlices(getSlices());
334 Primitive3DContainer SdrLathePrimitive3D::get3DDecomposition(const geometry::ViewInformation3D& rViewInformation) const
336 if(getSdr3DObjectAttribute().getReducedLineGeometry())
338 if(!mpLastRLGViewInformation ||
339 (!getBuffered3DDecomposition().empty()
340 && *mpLastRLGViewInformation != rViewInformation))
342 std::unique_lock aGuard( m_aMutex );
344 // conditions of last local decomposition with reduced lines have changed. Remember
345 // new one and clear current decompositiopn
346 SdrLathePrimitive3D* pThat = const_cast< SdrLathePrimitive3D* >(this);
347 pThat->setBuffered3DDecomposition(Primitive3DContainer());
348 pThat->mpLastRLGViewInformation = rViewInformation;
352 // no test for buffering needed, call parent
353 return SdrPrimitive3D::get3DDecomposition(rViewInformation);
356 // provide unique ID
357 ImplPrimitive3DIDBlock(SdrLathePrimitive3D, PRIMITIVE3D_ID_SDRLATHEPRIMITIVE3D)
359 } // end of namespace
361 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */