1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: gridprimitive2d.cxx,v $
9 * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
39 #include <drawinglayer/primitive2d/gridprimitive2d.hxx>
40 #include <basegfx/tools/canvastools.hxx>
41 #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
42 #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
43 #include <drawinglayer/geometry/viewinformation2d.hxx>
44 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
46 //////////////////////////////////////////////////////////////////////////////
48 using namespace com::sun::star
;
50 //////////////////////////////////////////////////////////////////////////////
52 namespace drawinglayer
56 Primitive2DSequence
GridPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D
& rViewInformation
) const
58 Primitive2DSequence aRetval
;
60 if(!rViewInformation
.getViewport().isEmpty() && getWidth() > 0.0 && getHeight() > 0.0)
62 // decompose grid matrix to get logic size
63 basegfx::B2DVector aScale
, aTranslate
;
64 double fRotate
, fShearX
;
65 getTransform().decompose(aScale
, aTranslate
, fRotate
, fShearX
);
67 // create grid matrix which transforms from scaled logic to view
68 basegfx::B2DHomMatrix aRST
;
71 aRST
.translate(aTranslate
.getX(), aTranslate
.getY());
72 aRST
*= rViewInformation
.getObjectToViewTransformation();
75 double fStepX(getWidth());
76 double fStepY(getHeight());
77 const double fMinimalStep(10.0);
79 // guarantee a step width of 10.0
80 if(basegfx::fTools::less(fStepX
, fMinimalStep
))
82 fStepX
= fMinimalStep
;
85 if(basegfx::fTools::less(fStepY
, fMinimalStep
))
87 fStepY
= fMinimalStep
;
90 // get relative distances in view coordinates
91 double fViewStepX((rViewInformation
.getObjectToViewTransformation() * basegfx::B2DVector(fStepX
, 0.0)).getLength());
92 double fViewStepY((rViewInformation
.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fStepY
)).getLength());
93 double fSmallStepX(1.0), fViewSmallStepX(1.0), fSmallStepY(1.0), fViewSmallStepY(1.0);
94 sal_uInt32
nSmallStepsX(0L), nSmallStepsY(0L);
97 if(getSubdivisionsX())
99 fSmallStepX
= fStepX
/ getSubdivisionsX();
100 fViewSmallStepX
= fViewStepX
/ getSubdivisionsX();
103 if(getSubdivisionsY())
105 fSmallStepY
= fStepY
/ getSubdivisionsY();
106 fViewSmallStepY
= fViewStepY
/ getSubdivisionsY();
109 // correct step width
110 while(fViewStepX
< getSmallestViewDistance())
116 while(fViewStepY
< getSmallestViewDistance())
122 // correct small step width
123 if(getSubdivisionsX())
125 while(fViewSmallStepX
< getSmallestSubdivisionViewDistance())
127 fViewSmallStepX
*= 2.0;
131 nSmallStepsX
= (sal_uInt32
)(fStepX
/ fSmallStepX
);
134 if(getSubdivisionsY())
136 while(fViewSmallStepY
< getSmallestSubdivisionViewDistance())
138 fViewSmallStepY
*= 2.0;
142 nSmallStepsY
= (sal_uInt32
)(fStepY
/ fSmallStepY
);
145 // prepare point vectors for point and cross markers
146 std::vector
< basegfx::B2DPoint
> aPositionsPoint
;
147 std::vector
< basegfx::B2DPoint
> aPositionsCross
;
149 for(double fX(0.0); fX
< aScale
.getX(); fX
+= fStepX
)
151 const bool bXZero(basegfx::fTools::equalZero(fX
));
153 for(double fY(0.0); fY
< aScale
.getY(); fY
+= fStepY
)
155 const bool bYZero(basegfx::fTools::equalZero(fY
));
157 if(!bXZero
&& !bYZero
)
159 // get discrete position and test against 3x3 area surrounding it
160 // since it's a cross
161 const double fHalfCrossSize(3.0 * 0.5);
162 const basegfx::B2DPoint
aViewPos(aRST
* basegfx::B2DPoint(fX
, fY
));
163 const basegfx::B2DRange
aDiscreteRangeCross(
164 aViewPos
.getX() - fHalfCrossSize
, aViewPos
.getY() - fHalfCrossSize
,
165 aViewPos
.getX() + fHalfCrossSize
, aViewPos
.getY() + fHalfCrossSize
);
167 if(rViewInformation
.getDiscreteViewport().overlaps(aDiscreteRangeCross
))
169 const basegfx::B2DPoint
aLogicPos(rViewInformation
.getInverseObjectToViewTransformation() * aViewPos
);
170 aPositionsCross
.push_back(aLogicPos
);
174 if(getSubdivisionsX() && !bYZero
)
176 double fF(fX
+ fSmallStepX
);
178 for(sal_uInt32
a(1L); a
< nSmallStepsX
&& fF
< aScale
.getX(); a
++, fF
+= fSmallStepX
)
180 const basegfx::B2DPoint
aViewPos(aRST
* basegfx::B2DPoint(fF
, fY
));
182 if(rViewInformation
.getDiscreteViewport().isInside(aViewPos
))
184 const basegfx::B2DPoint
aLogicPos(rViewInformation
.getInverseObjectToViewTransformation() * aViewPos
);
185 aPositionsPoint
.push_back(aLogicPos
);
190 if(getSubdivisionsY() && !bXZero
)
192 double fF(fY
+ fSmallStepY
);
194 for(sal_uInt32
a(1L); a
< nSmallStepsY
&& fF
< aScale
.getY(); a
++, fF
+= fSmallStepY
)
196 const basegfx::B2DPoint
aViewPos(aRST
* basegfx::B2DPoint(fX
, fF
));
198 if(rViewInformation
.getDiscreteViewport().isInside(aViewPos
))
200 const basegfx::B2DPoint
aLogicPos(rViewInformation
.getInverseObjectToViewTransformation() * aViewPos
);
201 aPositionsPoint
.push_back(aLogicPos
);
208 // prepare return value
209 const sal_uInt32
nCountPoint(aPositionsPoint
.size());
210 const sal_uInt32
nCountCross(aPositionsCross
.size());
211 const sal_uInt32
nRetvalCount((nCountPoint
? 1 : 0) + (nCountCross
? 1 : 0));
212 sal_uInt32
nInsertCounter(0);
214 aRetval
.realloc(nRetvalCount
);
216 // add PointArrayPrimitive2D if point markers were added
219 aRetval
[nInsertCounter
++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsPoint
, getBColor()));
222 // add MarkerArrayPrimitive2D if cross markers were added
225 if(!getSubdivisionsX() && !getSubdivisionsY())
227 // no subdivisions, so fall back to points at grid positions, no need to
228 // visualize a difference between divisions and sub-divisions
229 aRetval
[nInsertCounter
++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsCross
, getBColor()));
233 aRetval
[nInsertCounter
++] = Primitive2DReference(new MarkerArrayPrimitive2D(aPositionsCross
, getCrossMarker()));
241 GridPrimitive2D::GridPrimitive2D(
242 const basegfx::B2DHomMatrix
& rTransform
,
245 double fSmallestViewDistance
,
246 double fSmallestSubdivisionViewDistance
,
247 sal_uInt32 nSubdivisionsX
,
248 sal_uInt32 nSubdivisionsY
,
249 const basegfx::BColor
& rBColor
,
250 const BitmapEx
& rCrossMarker
)
252 maTransform(rTransform
),
255 mfSmallestViewDistance(fSmallestViewDistance
),
256 mfSmallestSubdivisionViewDistance(fSmallestSubdivisionViewDistance
),
257 mnSubdivisionsX(nSubdivisionsX
),
258 mnSubdivisionsY(nSubdivisionsY
),
260 maCrossMarker(rCrossMarker
),
261 maLastObjectToViewTransformation(),
266 bool GridPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
268 if(BasePrimitive2D::operator==(rPrimitive
))
270 const GridPrimitive2D
& rCompare
= (GridPrimitive2D
&)rPrimitive
;
272 return (getTransform() == rCompare
.getTransform()
273 && getWidth() == rCompare
.getWidth()
274 && getHeight() == rCompare
.getHeight()
275 && getSmallestViewDistance() == rCompare
.getSmallestViewDistance()
276 && getSmallestSubdivisionViewDistance() == rCompare
.getSmallestSubdivisionViewDistance()
277 && getSubdivisionsX() == rCompare
.getSubdivisionsX()
278 && getSubdivisionsY() == rCompare
.getSubdivisionsY()
279 && getBColor() == rCompare
.getBColor()
280 && getCrossMarker() == rCompare
.getCrossMarker());
286 basegfx::B2DRange
GridPrimitive2D::getB2DRange(const geometry::ViewInformation2D
& rViewInformation
) const
288 // get object's range
289 basegfx::B2DRange
aUnitRange(0.0, 0.0, 1.0, 1.0);
290 aUnitRange
.transform(getTransform());
292 // intersect with visible part
293 aUnitRange
.intersect(rViewInformation
.getViewport());
298 Primitive2DSequence
GridPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D
& rViewInformation
) const
300 ::osl::MutexGuard
aGuard( m_aMutex
);
302 if(getLocalDecomposition().hasElements())
304 if(maLastViewport
!= rViewInformation
.getViewport() || maLastObjectToViewTransformation
!= rViewInformation
.getObjectToViewTransformation())
306 // conditions of last local decomposition have changed, delete
307 const_cast< GridPrimitive2D
* >(this)->setLocalDecomposition(Primitive2DSequence());
311 if(!getLocalDecomposition().hasElements())
313 // remember ViewRange and ViewTransformation
314 const_cast< GridPrimitive2D
* >(this)->maLastObjectToViewTransformation
= rViewInformation
.getObjectToViewTransformation();
315 const_cast< GridPrimitive2D
* >(this)->maLastViewport
= rViewInformation
.getViewport();
318 // use parent implementation
319 return BasePrimitive2D::get2DDecomposition(rViewInformation
);
323 ImplPrimitrive2DIDBlock(GridPrimitive2D
, PRIMITIVE2D_ID_GRIDPRIMITIVE2D
)
325 } // end of namespace primitive2d
326 } // end of namespace drawinglayer
328 //////////////////////////////////////////////////////////////////////////////