1*464702f4SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*464702f4SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*464702f4SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*464702f4SAndrew Rist * distributed with this work for additional information 6*464702f4SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*464702f4SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*464702f4SAndrew Rist * "License"); you may not use this file except in compliance 9*464702f4SAndrew Rist * with the License. You may obtain a copy of the License at 10*464702f4SAndrew Rist * 11*464702f4SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*464702f4SAndrew Rist * 13*464702f4SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*464702f4SAndrew Rist * software distributed under the License is distributed on an 15*464702f4SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*464702f4SAndrew Rist * KIND, either express or implied. See the License for the 17*464702f4SAndrew Rist * specific language governing permissions and limitations 18*464702f4SAndrew Rist * under the License. 19*464702f4SAndrew Rist * 20*464702f4SAndrew Rist *************************************************************/ 21*464702f4SAndrew Rist 22*464702f4SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include <drawinglayer/primitive2d/gridprimitive2d.hxx> 28cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx> 29cdf0e10cSrcweir #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx> 30cdf0e10cSrcweir #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx> 31cdf0e10cSrcweir #include <drawinglayer/geometry/viewinformation2d.hxx> 32cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> 33cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx> 34cdf0e10cSrcweir 35cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 36cdf0e10cSrcweir 37cdf0e10cSrcweir using namespace com::sun::star; 38cdf0e10cSrcweir 39cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 40cdf0e10cSrcweir 41cdf0e10cSrcweir namespace drawinglayer 42cdf0e10cSrcweir { 43cdf0e10cSrcweir namespace primitive2d 44cdf0e10cSrcweir { 45cdf0e10cSrcweir Primitive2DSequence GridPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const 46cdf0e10cSrcweir { 47cdf0e10cSrcweir Primitive2DSequence aRetval; 48cdf0e10cSrcweir 49cdf0e10cSrcweir if(!rViewInformation.getViewport().isEmpty() && getWidth() > 0.0 && getHeight() > 0.0) 50cdf0e10cSrcweir { 51cdf0e10cSrcweir // decompose grid matrix to get logic size 52cdf0e10cSrcweir basegfx::B2DVector aScale, aTranslate; 53cdf0e10cSrcweir double fRotate, fShearX; 54cdf0e10cSrcweir getTransform().decompose(aScale, aTranslate, fRotate, fShearX); 55cdf0e10cSrcweir 56cdf0e10cSrcweir // create grid matrix which transforms from scaled logic to view 57cdf0e10cSrcweir basegfx::B2DHomMatrix aRST(basegfx::tools::createShearXRotateTranslateB2DHomMatrix( 58cdf0e10cSrcweir fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); 59cdf0e10cSrcweir aRST *= rViewInformation.getObjectToViewTransformation(); 60cdf0e10cSrcweir 61cdf0e10cSrcweir // get step widths 62cdf0e10cSrcweir double fStepX(getWidth()); 63cdf0e10cSrcweir double fStepY(getHeight()); 64cdf0e10cSrcweir const double fMinimalStep(10.0); 65cdf0e10cSrcweir 66cdf0e10cSrcweir // guarantee a step width of 10.0 67cdf0e10cSrcweir if(basegfx::fTools::less(fStepX, fMinimalStep)) 68cdf0e10cSrcweir { 69cdf0e10cSrcweir fStepX = fMinimalStep; 70cdf0e10cSrcweir } 71cdf0e10cSrcweir 72cdf0e10cSrcweir if(basegfx::fTools::less(fStepY, fMinimalStep)) 73cdf0e10cSrcweir { 74cdf0e10cSrcweir fStepY = fMinimalStep; 75cdf0e10cSrcweir } 76cdf0e10cSrcweir 77cdf0e10cSrcweir // get relative distances in view coordinates 78cdf0e10cSrcweir double fViewStepX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fStepX, 0.0)).getLength()); 79cdf0e10cSrcweir double fViewStepY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fStepY)).getLength()); 80cdf0e10cSrcweir double fSmallStepX(1.0), fViewSmallStepX(1.0), fSmallStepY(1.0), fViewSmallStepY(1.0); 81cdf0e10cSrcweir sal_uInt32 nSmallStepsX(0L), nSmallStepsY(0L); 82cdf0e10cSrcweir 83cdf0e10cSrcweir // setup subdivisions 84cdf0e10cSrcweir if(getSubdivisionsX()) 85cdf0e10cSrcweir { 86cdf0e10cSrcweir fSmallStepX = fStepX / getSubdivisionsX(); 87cdf0e10cSrcweir fViewSmallStepX = fViewStepX / getSubdivisionsX(); 88cdf0e10cSrcweir } 89cdf0e10cSrcweir 90cdf0e10cSrcweir if(getSubdivisionsY()) 91cdf0e10cSrcweir { 92cdf0e10cSrcweir fSmallStepY = fStepY / getSubdivisionsY(); 93cdf0e10cSrcweir fViewSmallStepY = fViewStepY / getSubdivisionsY(); 94cdf0e10cSrcweir } 95cdf0e10cSrcweir 96cdf0e10cSrcweir // correct step width 97cdf0e10cSrcweir while(fViewStepX < getSmallestViewDistance()) 98cdf0e10cSrcweir { 99cdf0e10cSrcweir fViewStepX *= 2.0; 100cdf0e10cSrcweir fStepX *= 2.0; 101cdf0e10cSrcweir } 102cdf0e10cSrcweir 103cdf0e10cSrcweir while(fViewStepY < getSmallestViewDistance()) 104cdf0e10cSrcweir { 105cdf0e10cSrcweir fViewStepY *= 2.0; 106cdf0e10cSrcweir fStepY *= 2.0; 107cdf0e10cSrcweir } 108cdf0e10cSrcweir 109cdf0e10cSrcweir // correct small step width 110cdf0e10cSrcweir if(getSubdivisionsX()) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir while(fViewSmallStepX < getSmallestSubdivisionViewDistance()) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir fViewSmallStepX *= 2.0; 115cdf0e10cSrcweir fSmallStepX *= 2.0; 116cdf0e10cSrcweir } 117cdf0e10cSrcweir 118cdf0e10cSrcweir nSmallStepsX = (sal_uInt32)(fStepX / fSmallStepX); 119cdf0e10cSrcweir } 120cdf0e10cSrcweir 121cdf0e10cSrcweir if(getSubdivisionsY()) 122cdf0e10cSrcweir { 123cdf0e10cSrcweir while(fViewSmallStepY < getSmallestSubdivisionViewDistance()) 124cdf0e10cSrcweir { 125cdf0e10cSrcweir fViewSmallStepY *= 2.0; 126cdf0e10cSrcweir fSmallStepY *= 2.0; 127cdf0e10cSrcweir } 128cdf0e10cSrcweir 129cdf0e10cSrcweir nSmallStepsY = (sal_uInt32)(fStepY / fSmallStepY); 130cdf0e10cSrcweir } 131cdf0e10cSrcweir 132cdf0e10cSrcweir // prepare point vectors for point and cross markers 133cdf0e10cSrcweir std::vector< basegfx::B2DPoint > aPositionsPoint; 134cdf0e10cSrcweir std::vector< basegfx::B2DPoint > aPositionsCross; 135cdf0e10cSrcweir 136cdf0e10cSrcweir for(double fX(0.0); fX < aScale.getX(); fX += fStepX) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir const bool bXZero(basegfx::fTools::equalZero(fX)); 139cdf0e10cSrcweir 140cdf0e10cSrcweir for(double fY(0.0); fY < aScale.getY(); fY += fStepY) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir const bool bYZero(basegfx::fTools::equalZero(fY)); 143cdf0e10cSrcweir 144cdf0e10cSrcweir if(!bXZero && !bYZero) 145cdf0e10cSrcweir { 146cdf0e10cSrcweir // get discrete position and test against 3x3 area surrounding it 147cdf0e10cSrcweir // since it's a cross 148cdf0e10cSrcweir const double fHalfCrossSize(3.0 * 0.5); 149cdf0e10cSrcweir const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fY)); 150cdf0e10cSrcweir const basegfx::B2DRange aDiscreteRangeCross( 151cdf0e10cSrcweir aViewPos.getX() - fHalfCrossSize, aViewPos.getY() - fHalfCrossSize, 152cdf0e10cSrcweir aViewPos.getX() + fHalfCrossSize, aViewPos.getY() + fHalfCrossSize); 153cdf0e10cSrcweir 154cdf0e10cSrcweir if(rViewInformation.getDiscreteViewport().overlaps(aDiscreteRangeCross)) 155cdf0e10cSrcweir { 156cdf0e10cSrcweir const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); 157cdf0e10cSrcweir aPositionsCross.push_back(aLogicPos); 158cdf0e10cSrcweir } 159cdf0e10cSrcweir } 160cdf0e10cSrcweir 161cdf0e10cSrcweir if(getSubdivisionsX() && !bYZero) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir double fF(fX + fSmallStepX); 164cdf0e10cSrcweir 165cdf0e10cSrcweir for(sal_uInt32 a(1L); a < nSmallStepsX && fF < aScale.getX(); a++, fF += fSmallStepX) 166cdf0e10cSrcweir { 167cdf0e10cSrcweir const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fF, fY)); 168cdf0e10cSrcweir 169cdf0e10cSrcweir if(rViewInformation.getDiscreteViewport().isInside(aViewPos)) 170cdf0e10cSrcweir { 171cdf0e10cSrcweir const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); 172cdf0e10cSrcweir aPositionsPoint.push_back(aLogicPos); 173cdf0e10cSrcweir } 174cdf0e10cSrcweir } 175cdf0e10cSrcweir } 176cdf0e10cSrcweir 177cdf0e10cSrcweir if(getSubdivisionsY() && !bXZero) 178cdf0e10cSrcweir { 179cdf0e10cSrcweir double fF(fY + fSmallStepY); 180cdf0e10cSrcweir 181cdf0e10cSrcweir for(sal_uInt32 a(1L); a < nSmallStepsY && fF < aScale.getY(); a++, fF += fSmallStepY) 182cdf0e10cSrcweir { 183cdf0e10cSrcweir const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fF)); 184cdf0e10cSrcweir 185cdf0e10cSrcweir if(rViewInformation.getDiscreteViewport().isInside(aViewPos)) 186cdf0e10cSrcweir { 187cdf0e10cSrcweir const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); 188cdf0e10cSrcweir aPositionsPoint.push_back(aLogicPos); 189cdf0e10cSrcweir } 190cdf0e10cSrcweir } 191cdf0e10cSrcweir } 192cdf0e10cSrcweir } 193cdf0e10cSrcweir } 194cdf0e10cSrcweir 195cdf0e10cSrcweir // prepare return value 196cdf0e10cSrcweir const sal_uInt32 nCountPoint(aPositionsPoint.size()); 197cdf0e10cSrcweir const sal_uInt32 nCountCross(aPositionsCross.size()); 198cdf0e10cSrcweir const sal_uInt32 nRetvalCount((nCountPoint ? 1 : 0) + (nCountCross ? 1 : 0)); 199cdf0e10cSrcweir sal_uInt32 nInsertCounter(0); 200cdf0e10cSrcweir 201cdf0e10cSrcweir aRetval.realloc(nRetvalCount); 202cdf0e10cSrcweir 203cdf0e10cSrcweir // add PointArrayPrimitive2D if point markers were added 204cdf0e10cSrcweir if(nCountPoint) 205cdf0e10cSrcweir { 206cdf0e10cSrcweir aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsPoint, getBColor())); 207cdf0e10cSrcweir } 208cdf0e10cSrcweir 209cdf0e10cSrcweir // add MarkerArrayPrimitive2D if cross markers were added 210cdf0e10cSrcweir if(nCountCross) 211cdf0e10cSrcweir { 212cdf0e10cSrcweir if(!getSubdivisionsX() && !getSubdivisionsY()) 213cdf0e10cSrcweir { 214cdf0e10cSrcweir // no subdivisions, so fall back to points at grid positions, no need to 215cdf0e10cSrcweir // visualize a difference between divisions and sub-divisions 216cdf0e10cSrcweir aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsCross, getBColor())); 217cdf0e10cSrcweir } 218cdf0e10cSrcweir else 219cdf0e10cSrcweir { 220cdf0e10cSrcweir aRetval[nInsertCounter++] = Primitive2DReference(new MarkerArrayPrimitive2D(aPositionsCross, getCrossMarker())); 221cdf0e10cSrcweir } 222cdf0e10cSrcweir } 223cdf0e10cSrcweir } 224cdf0e10cSrcweir 225cdf0e10cSrcweir return aRetval; 226cdf0e10cSrcweir } 227cdf0e10cSrcweir 228cdf0e10cSrcweir GridPrimitive2D::GridPrimitive2D( 229cdf0e10cSrcweir const basegfx::B2DHomMatrix& rTransform, 230cdf0e10cSrcweir double fWidth, 231cdf0e10cSrcweir double fHeight, 232cdf0e10cSrcweir double fSmallestViewDistance, 233cdf0e10cSrcweir double fSmallestSubdivisionViewDistance, 234cdf0e10cSrcweir sal_uInt32 nSubdivisionsX, 235cdf0e10cSrcweir sal_uInt32 nSubdivisionsY, 236cdf0e10cSrcweir const basegfx::BColor& rBColor, 237cdf0e10cSrcweir const BitmapEx& rCrossMarker) 238cdf0e10cSrcweir : BufferedDecompositionPrimitive2D(), 239cdf0e10cSrcweir maTransform(rTransform), 240cdf0e10cSrcweir mfWidth(fWidth), 241cdf0e10cSrcweir mfHeight(fHeight), 242cdf0e10cSrcweir mfSmallestViewDistance(fSmallestViewDistance), 243cdf0e10cSrcweir mfSmallestSubdivisionViewDistance(fSmallestSubdivisionViewDistance), 244cdf0e10cSrcweir mnSubdivisionsX(nSubdivisionsX), 245cdf0e10cSrcweir mnSubdivisionsY(nSubdivisionsY), 246cdf0e10cSrcweir maBColor(rBColor), 247cdf0e10cSrcweir maCrossMarker(rCrossMarker), 248cdf0e10cSrcweir maLastObjectToViewTransformation(), 249cdf0e10cSrcweir maLastViewport() 250cdf0e10cSrcweir { 251cdf0e10cSrcweir } 252cdf0e10cSrcweir 253cdf0e10cSrcweir bool GridPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const 254cdf0e10cSrcweir { 255cdf0e10cSrcweir if(BufferedDecompositionPrimitive2D::operator==(rPrimitive)) 256cdf0e10cSrcweir { 257cdf0e10cSrcweir const GridPrimitive2D& rCompare = (GridPrimitive2D&)rPrimitive; 258cdf0e10cSrcweir 259cdf0e10cSrcweir return (getTransform() == rCompare.getTransform() 260cdf0e10cSrcweir && getWidth() == rCompare.getWidth() 261cdf0e10cSrcweir && getHeight() == rCompare.getHeight() 262cdf0e10cSrcweir && getSmallestViewDistance() == rCompare.getSmallestViewDistance() 263cdf0e10cSrcweir && getSmallestSubdivisionViewDistance() == rCompare.getSmallestSubdivisionViewDistance() 264cdf0e10cSrcweir && getSubdivisionsX() == rCompare.getSubdivisionsX() 265cdf0e10cSrcweir && getSubdivisionsY() == rCompare.getSubdivisionsY() 266cdf0e10cSrcweir && getBColor() == rCompare.getBColor() 267cdf0e10cSrcweir && getCrossMarker() == rCompare.getCrossMarker()); 268cdf0e10cSrcweir } 269cdf0e10cSrcweir 270cdf0e10cSrcweir return false; 271cdf0e10cSrcweir } 272cdf0e10cSrcweir 273cdf0e10cSrcweir basegfx::B2DRange GridPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const 274cdf0e10cSrcweir { 275cdf0e10cSrcweir // get object's range 276cdf0e10cSrcweir basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); 277cdf0e10cSrcweir aUnitRange.transform(getTransform()); 278cdf0e10cSrcweir 279cdf0e10cSrcweir // intersect with visible part 280cdf0e10cSrcweir aUnitRange.intersect(rViewInformation.getViewport()); 281cdf0e10cSrcweir 282cdf0e10cSrcweir return aUnitRange; 283cdf0e10cSrcweir } 284cdf0e10cSrcweir 285cdf0e10cSrcweir Primitive2DSequence GridPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const 286cdf0e10cSrcweir { 287cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex ); 288cdf0e10cSrcweir 289cdf0e10cSrcweir if(getBuffered2DDecomposition().hasElements()) 290cdf0e10cSrcweir { 291cdf0e10cSrcweir if(maLastViewport != rViewInformation.getViewport() || maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation()) 292cdf0e10cSrcweir { 293cdf0e10cSrcweir // conditions of last local decomposition have changed, delete 294cdf0e10cSrcweir const_cast< GridPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence()); 295cdf0e10cSrcweir } 296cdf0e10cSrcweir } 297cdf0e10cSrcweir 298cdf0e10cSrcweir if(!getBuffered2DDecomposition().hasElements()) 299cdf0e10cSrcweir { 300cdf0e10cSrcweir // remember ViewRange and ViewTransformation 301cdf0e10cSrcweir const_cast< GridPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation(); 302cdf0e10cSrcweir const_cast< GridPrimitive2D* >(this)->maLastViewport = rViewInformation.getViewport(); 303cdf0e10cSrcweir } 304cdf0e10cSrcweir 305cdf0e10cSrcweir // use parent implementation 306cdf0e10cSrcweir return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation); 307cdf0e10cSrcweir } 308cdf0e10cSrcweir 309cdf0e10cSrcweir // provide unique ID 310cdf0e10cSrcweir ImplPrimitrive2DIDBlock(GridPrimitive2D, PRIMITIVE2D_ID_GRIDPRIMITIVE2D) 311cdf0e10cSrcweir 312cdf0e10cSrcweir } // end of namespace primitive2d 313cdf0e10cSrcweir } // end of namespace drawinglayer 314cdf0e10cSrcweir 315cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////////////// 316cdf0e10cSrcweir // eof 317