fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / drawinglayer / source / primitive2d / gridprimitive2d.cxx
blob414f3ad1077d11b372962795b4a2d11efe817acc
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/primitive2d/gridprimitive2d.hxx>
21 #include <basegfx/tools/canvastools.hxx>
22 #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
23 #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
24 #include <drawinglayer/geometry/viewinformation2d.hxx>
25 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
26 #include <basegfx/matrix/b2dhommatrixtools.hxx>
28 //////////////////////////////////////////////////////////////////////////////
30 using namespace com::sun::star;
32 //////////////////////////////////////////////////////////////////////////////
34 namespace drawinglayer
36 namespace primitive2d
38 Primitive2DSequence GridPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
40 Primitive2DSequence aRetval;
42 if(!rViewInformation.getViewport().isEmpty() && getWidth() > 0.0 && getHeight() > 0.0)
44 // decompose grid matrix to get logic size
45 basegfx::B2DVector aScale, aTranslate;
46 double fRotate, fShearX;
47 getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
49 // create grid matrix which transforms from scaled logic to view
50 basegfx::B2DHomMatrix aRST(basegfx::tools::createShearXRotateTranslateB2DHomMatrix(
51 fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
52 aRST *= rViewInformation.getObjectToViewTransformation();
54 // get step widths
55 double fStepX(getWidth());
56 double fStepY(getHeight());
57 const double fMinimalStep(10.0);
59 // guarantee a step width of 10.0
60 if(basegfx::fTools::less(fStepX, fMinimalStep))
62 fStepX = fMinimalStep;
65 if(basegfx::fTools::less(fStepY, fMinimalStep))
67 fStepY = fMinimalStep;
70 // get relative distances in view coordinates
71 double fViewStepX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fStepX, 0.0)).getLength());
72 double fViewStepY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fStepY)).getLength());
73 double fSmallStepX(1.0), fViewSmallStepX(1.0), fSmallStepY(1.0), fViewSmallStepY(1.0);
74 sal_uInt32 nSmallStepsX(0L), nSmallStepsY(0L);
76 // setup subdivisions
77 if(getSubdivisionsX())
79 fSmallStepX = fStepX / getSubdivisionsX();
80 fViewSmallStepX = fViewStepX / getSubdivisionsX();
83 if(getSubdivisionsY())
85 fSmallStepY = fStepY / getSubdivisionsY();
86 fViewSmallStepY = fViewStepY / getSubdivisionsY();
89 // correct step width
90 while(fViewStepX < getSmallestViewDistance())
92 fViewStepX *= 2.0;
93 fStepX *= 2.0;
96 while(fViewStepY < getSmallestViewDistance())
98 fViewStepY *= 2.0;
99 fStepY *= 2.0;
102 // correct small step width
103 if(getSubdivisionsX())
105 while(fViewSmallStepX < getSmallestSubdivisionViewDistance())
107 fViewSmallStepX *= 2.0;
108 fSmallStepX *= 2.0;
111 nSmallStepsX = (sal_uInt32)(fStepX / fSmallStepX);
114 if(getSubdivisionsY())
116 while(fViewSmallStepY < getSmallestSubdivisionViewDistance())
118 fViewSmallStepY *= 2.0;
119 fSmallStepY *= 2.0;
122 nSmallStepsY = (sal_uInt32)(fStepY / fSmallStepY);
125 // calculate extended viewport in which grid points may lie at all
126 basegfx::B2DRange aExtendedViewport;
128 if(rViewInformation.getDiscreteViewport().isEmpty())
130 // not set, use logic size to travel over all potentioal grid points
131 aExtendedViewport = basegfx::B2DRange(0.0, 0.0, aScale.getX(), aScale.getY());
133 else
135 // transform unit range to discrete view
136 aExtendedViewport = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0);
137 basegfx::B2DHomMatrix aTrans(rViewInformation.getObjectToViewTransformation() * getTransform());
138 aExtendedViewport.transform(aTrans);
140 // intersect with visible part
141 aExtendedViewport.intersect(rViewInformation.getDiscreteViewport());
143 if(!aExtendedViewport.isEmpty())
145 // convert back and apply scale
146 aTrans.invert();
147 aTrans.scale(aScale.getX(), aScale.getY());
148 aExtendedViewport.transform(aTrans);
150 // crop start/end in X/Y to multiples of logical step width
151 const double fHalfCrossSize((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(3.0, 0.0)).getLength());
152 const double fMinX(floor((aExtendedViewport.getMinX() - fHalfCrossSize) / fStepX) * fStepX);
153 const double fMaxX(ceil((aExtendedViewport.getMaxX() + fHalfCrossSize) / fStepX) * fStepX);
154 const double fMinY(floor((aExtendedViewport.getMinY() - fHalfCrossSize) / fStepY) * fStepY);
155 const double fMaxY(ceil((aExtendedViewport.getMaxY() + fHalfCrossSize) / fStepY) * fStepY);
157 // put to aExtendedViewport and crop on object logic size
158 aExtendedViewport = basegfx::B2DRange(
159 std::max(fMinX, 0.0),
160 std::max(fMinY, 0.0),
161 std::min(fMaxX, aScale.getX()),
162 std::min(fMaxY, aScale.getY()));
166 if(!aExtendedViewport.isEmpty())
168 // prepare point vectors for point and cross markers
169 std::vector< basegfx::B2DPoint > aPositionsPoint;
170 std::vector< basegfx::B2DPoint > aPositionsCross;
172 for(double fX(aExtendedViewport.getMinX()); fX < aExtendedViewport.getMaxX(); fX += fStepX)
174 const bool bXZero(basegfx::fTools::equalZero(fX));
176 for(double fY(aExtendedViewport.getMinY()); fY < aExtendedViewport.getMaxY(); fY += fStepY)
178 const bool bYZero(basegfx::fTools::equalZero(fY));
180 if(!bXZero && !bYZero)
182 // get discrete position and test against 3x3 area surrounding it
183 // since it's a cross
184 const double fHalfCrossSize(3.0 * 0.5);
185 const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fY));
186 const basegfx::B2DRange aDiscreteRangeCross(
187 aViewPos.getX() - fHalfCrossSize, aViewPos.getY() - fHalfCrossSize,
188 aViewPos.getX() + fHalfCrossSize, aViewPos.getY() + fHalfCrossSize);
190 if(rViewInformation.getDiscreteViewport().overlaps(aDiscreteRangeCross))
192 const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
193 aPositionsCross.push_back(aLogicPos);
197 if(getSubdivisionsX() && !bYZero)
199 double fF(fX + fSmallStepX);
201 for(sal_uInt32 a(1); a < nSmallStepsX && fF < aExtendedViewport.getMaxX(); a++, fF += fSmallStepX)
203 const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fF, fY));
205 if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
207 const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
208 aPositionsPoint.push_back(aLogicPos);
213 if(getSubdivisionsY() && !bXZero)
215 double fF(fY + fSmallStepY);
217 for(sal_uInt32 a(1); a < nSmallStepsY && fF < aExtendedViewport.getMaxY(); a++, fF += fSmallStepY)
219 const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fF));
221 if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
223 const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
224 aPositionsPoint.push_back(aLogicPos);
231 // prepare return value
232 const sal_uInt32 nCountPoint(aPositionsPoint.size());
233 const sal_uInt32 nCountCross(aPositionsCross.size());
234 const sal_uInt32 nRetvalCount((nCountPoint ? 1 : 0) + (nCountCross ? 1 : 0));
235 sal_uInt32 nInsertCounter(0);
237 aRetval.realloc(nRetvalCount);
239 // add PointArrayPrimitive2D if point markers were added
240 if(nCountPoint)
242 aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsPoint, getBColor()));
245 // add MarkerArrayPrimitive2D if cross markers were added
246 if(nCountCross)
248 if(!getSubdivisionsX() && !getSubdivisionsY())
250 // no subdivisions, so fall back to points at grid positions, no need to
251 // visualize a difference between divisions and sub-divisions
252 aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsCross, getBColor()));
254 else
256 aRetval[nInsertCounter++] = Primitive2DReference(new MarkerArrayPrimitive2D(aPositionsCross, getCrossMarker()));
262 return aRetval;
265 GridPrimitive2D::GridPrimitive2D(
266 const basegfx::B2DHomMatrix& rTransform,
267 double fWidth,
268 double fHeight,
269 double fSmallestViewDistance,
270 double fSmallestSubdivisionViewDistance,
271 sal_uInt32 nSubdivisionsX,
272 sal_uInt32 nSubdivisionsY,
273 const basegfx::BColor& rBColor,
274 const BitmapEx& rCrossMarker)
275 : BufferedDecompositionPrimitive2D(),
276 maTransform(rTransform),
277 mfWidth(fWidth),
278 mfHeight(fHeight),
279 mfSmallestViewDistance(fSmallestViewDistance),
280 mfSmallestSubdivisionViewDistance(fSmallestSubdivisionViewDistance),
281 mnSubdivisionsX(nSubdivisionsX),
282 mnSubdivisionsY(nSubdivisionsY),
283 maBColor(rBColor),
284 maCrossMarker(rCrossMarker),
285 maLastObjectToViewTransformation(),
286 maLastViewport()
290 bool GridPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
292 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
294 const GridPrimitive2D& rCompare = (GridPrimitive2D&)rPrimitive;
296 return (getTransform() == rCompare.getTransform()
297 && getWidth() == rCompare.getWidth()
298 && getHeight() == rCompare.getHeight()
299 && getSmallestViewDistance() == rCompare.getSmallestViewDistance()
300 && getSmallestSubdivisionViewDistance() == rCompare.getSmallestSubdivisionViewDistance()
301 && getSubdivisionsX() == rCompare.getSubdivisionsX()
302 && getSubdivisionsY() == rCompare.getSubdivisionsY()
303 && getBColor() == rCompare.getBColor()
304 && getCrossMarker() == rCompare.getCrossMarker());
307 return false;
310 basegfx::B2DRange GridPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
312 // get object's range
313 basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
314 aUnitRange.transform(getTransform());
316 // intersect with visible part
317 aUnitRange.intersect(rViewInformation.getViewport());
319 return aUnitRange;
322 Primitive2DSequence GridPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
324 ::osl::MutexGuard aGuard( m_aMutex );
326 if(getBuffered2DDecomposition().hasElements())
328 if(maLastViewport != rViewInformation.getViewport() || maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation())
330 // conditions of last local decomposition have changed, delete
331 const_cast< GridPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
335 if(!getBuffered2DDecomposition().hasElements())
337 // remember ViewRange and ViewTransformation
338 const_cast< GridPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation();
339 const_cast< GridPrimitive2D* >(this)->maLastViewport = rViewInformation.getViewport();
342 // use parent implementation
343 return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
346 // provide unique ID
347 ImplPrimitive2DIDBlock(GridPrimitive2D, PRIMITIVE2D_ID_GRIDPRIMITIVE2D)
349 } // end of namespace primitive2d
350 } // end of namespace drawinglayer
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */