1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_svx.hxx" 26 27 #include <svx/sdr/overlay/overlaytools.hxx> 28 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx> 29 #include <basegfx/matrix/b2dhommatrix.hxx> 30 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> 31 #include <basegfx/polygon/b2dpolygon.hxx> 32 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> 33 #include <basegfx/polygon/b2dpolygontools.hxx> 34 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> 35 #include <drawinglayer/geometry/viewinformation2d.hxx> 36 #include <basegfx/matrix/b2dhommatrixtools.hxx> 37 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> 38 #include <vcl/svapp.hxx> 39 40 ////////////////////////////////////////////////////////////////////////////// 41 42 namespace drawinglayer 43 { 44 namespace primitive2d 45 { 46 OverlayBitmapExPrimitive::OverlayBitmapExPrimitive( 47 const BitmapEx& rBitmapEx, 48 const basegfx::B2DPoint& rBasePosition, 49 sal_uInt16 nCenterX, 50 sal_uInt16 nCenterY) 51 : DiscreteMetricDependentPrimitive2D(), 52 maBitmapEx(rBitmapEx), 53 maBasePosition(rBasePosition), 54 mnCenterX(nCenterX), 55 mnCenterY(nCenterY) 56 {} 57 58 Primitive2DSequence OverlayBitmapExPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 59 { 60 Primitive2DSequence aRetval; 61 const Size aBitmapSize(getBitmapEx().GetSizePixel()); 62 63 if(aBitmapSize.Width() && aBitmapSize.Height() && basegfx::fTools::more(getDiscreteUnit(), 0.0)) 64 { 65 // calculate back from internal bitmap's extreme coordinates (the edges) 66 // to logical coordinates. Only use a unified scaling value (getDiscreteUnit(), 67 // the prepared one which expresses how many logic units form a discrete unit) 68 // for this step. This primitive is to be displayed always unscaled (in it's pixel size) 69 // and unrotated, more like a marker 70 const double fLeft(((0.0 - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX()); 71 const double fTop(((0.0 - getCenterY()) * getDiscreteUnit()) + getBasePosition().getY()); 72 const double fRight(((aBitmapSize.getWidth() - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX()); 73 const double fBottom(((aBitmapSize.getHeight() - getCenterY()) * getDiscreteUnit()) + getBasePosition().getY()); 74 75 // create a BitmapPrimitive2D using those positions 76 basegfx::B2DHomMatrix aTransform; 77 78 aTransform.set(0, 0, fRight - fLeft); 79 aTransform.set(1, 1, fBottom - fTop); 80 aTransform.set(0, 2, fLeft); 81 aTransform.set(1, 2, fTop); 82 83 const Primitive2DReference aPrimitive(new BitmapPrimitive2D(getBitmapEx(), aTransform)); 84 aRetval = Primitive2DSequence(&aPrimitive, 1); 85 } 86 87 return aRetval; 88 } 89 90 bool OverlayBitmapExPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const 91 { 92 if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) 93 { 94 const OverlayBitmapExPrimitive& rCompare = static_cast< const OverlayBitmapExPrimitive& >(rPrimitive); 95 96 return (getBitmapEx() == rCompare.getBitmapEx() 97 && getBasePosition() == rCompare.getBasePosition() 98 && getCenterX() == rCompare.getCenterX() 99 && getCenterY() == rCompare.getCenterY()); 100 } 101 102 return false; 103 } 104 105 ImplPrimitrive2DIDBlock(OverlayBitmapExPrimitive, PRIMITIVE2D_ID_OVERLAYBITMAPEXPRIMITIVE) 106 107 } // end of namespace primitive2d 108 } // end of namespace drawinglayer 109 110 ////////////////////////////////////////////////////////////////////////////// 111 112 namespace drawinglayer 113 { 114 namespace primitive2d 115 { 116 OverlayCrosshairPrimitive::OverlayCrosshairPrimitive( 117 const basegfx::B2DPoint& rBasePosition, 118 const basegfx::BColor& rRGBColorA, 119 const basegfx::BColor& rRGBColorB, 120 double fDiscreteDashLength) 121 : ViewportDependentPrimitive2D(), 122 maBasePosition(rBasePosition), 123 maRGBColorA(rRGBColorA), 124 maRGBColorB(rRGBColorB), 125 mfDiscreteDashLength(fDiscreteDashLength) 126 {} 127 128 Primitive2DSequence OverlayCrosshairPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 129 { 130 // use the prepared Viewport information accessible using getViewport() 131 Primitive2DSequence aRetval; 132 133 if(!getViewport().isEmpty()) 134 { 135 aRetval.realloc(2); 136 basegfx::B2DPolygon aPolygon; 137 138 aPolygon.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY())); 139 aPolygon.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY())); 140 141 aRetval[0] = Primitive2DReference( 142 new PolygonMarkerPrimitive2D( 143 aPolygon, 144 getRGBColorA(), 145 getRGBColorB(), 146 getDiscreteDashLength())); 147 148 aPolygon.clear(); 149 aPolygon.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY())); 150 aPolygon.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY())); 151 152 aRetval[1] = Primitive2DReference( 153 new PolygonMarkerPrimitive2D( 154 aPolygon, 155 getRGBColorA(), 156 getRGBColorB(), 157 getDiscreteDashLength())); 158 } 159 160 return aRetval; 161 } 162 163 bool OverlayCrosshairPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const 164 { 165 if(ViewportDependentPrimitive2D::operator==(rPrimitive)) 166 { 167 const OverlayCrosshairPrimitive& rCompare = static_cast< const OverlayCrosshairPrimitive& >(rPrimitive); 168 169 return (getBasePosition() == rCompare.getBasePosition() 170 && getRGBColorA() == rCompare.getRGBColorA() 171 && getRGBColorB() == rCompare.getRGBColorB() 172 && getDiscreteDashLength() == rCompare.getDiscreteDashLength()); 173 } 174 175 return false; 176 } 177 178 ImplPrimitrive2DIDBlock(OverlayCrosshairPrimitive, PRIMITIVE2D_ID_OVERLAYCROSSHAIRPRIMITIVE) 179 180 } // end of namespace primitive2d 181 } // end of namespace drawinglayer 182 183 ////////////////////////////////////////////////////////////////////////////// 184 185 namespace drawinglayer 186 { 187 namespace primitive2d 188 { 189 OverlayRectanglePrimitive::OverlayRectanglePrimitive( 190 const basegfx::B2DRange& rObjectRange, 191 const basegfx::BColor& rColor, 192 double fTransparence, 193 double fDiscreteGrow, 194 double fDiscreteShrink, 195 double fRotation) 196 : DiscreteMetricDependentPrimitive2D(), 197 maObjectRange(rObjectRange), 198 maColor(rColor), 199 mfTransparence(fTransparence), 200 mfDiscreteGrow(fDiscreteGrow), 201 mfDiscreteShrink(fDiscreteShrink), 202 mfRotation(fRotation) 203 {} 204 205 Primitive2DSequence OverlayRectanglePrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 206 { 207 Primitive2DSequence aRetval; 208 basegfx::B2DRange aInnerRange(getObjectRange()); 209 210 if(!aInnerRange.isEmpty() && basegfx::fTools::more(getDiscreteUnit(), 0.0) && getTransparence() <= 1.0) 211 { 212 basegfx::B2DRange aInnerRange(getObjectRange()); 213 basegfx::B2DRange aOuterRange(getObjectRange()); 214 215 // grow/shrink inner/outer polygons 216 aOuterRange.grow(getDiscreteUnit() * getDiscreteGrow()); 217 aInnerRange.grow(getDiscreteUnit() * -getDiscreteShrink()); 218 219 // convert to polygons 220 const double fFullGrow(getDiscreteGrow() + getDiscreteShrink()); 221 const double fRelativeRadiusX(fFullGrow / aOuterRange.getWidth()); 222 const double fRelativeRadiusY(fFullGrow / aOuterRange.getHeight()); 223 basegfx::B2DPolygon aOuterPolygon( 224 basegfx::tools::createPolygonFromRect( 225 aOuterRange, 226 fRelativeRadiusX, 227 fRelativeRadiusY)); 228 basegfx::B2DPolygon aInnerPolygon( 229 basegfx::tools::createPolygonFromRect( 230 aInnerRange)); 231 232 // apply evtl. existing rotation 233 if(!basegfx::fTools::equalZero(getRotation())) 234 { 235 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createRotateAroundPoint( 236 getObjectRange().getMinX(), getObjectRange().getMinY(), getRotation())); 237 238 aOuterPolygon.transform(aTransform); 239 aInnerPolygon.transform(aTransform); 240 } 241 242 // create filled primitive 243 basegfx::B2DPolyPolygon aPolyPolygon; 244 245 aPolyPolygon.append(aOuterPolygon); 246 aPolyPolygon.append(aInnerPolygon); 247 248 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode()) 249 { 250 // for high contrast, use hatch 251 const basegfx::BColor aHighContrastLineColor(Application::GetSettings().GetStyleSettings().GetFontColor().getBColor()); 252 const basegfx::BColor aEmptyColor(0.0, 0.0, 0.0); 253 const double fHatchRotation(45 * F_PI180); 254 const double fDiscreteHatchDistance(3.0); 255 const drawinglayer::attribute::FillHatchAttribute aFillHatchAttribute( 256 drawinglayer::attribute::HATCHSTYLE_SINGLE, 257 fDiscreteHatchDistance * getDiscreteUnit(), 258 fHatchRotation - getRotation(), 259 aHighContrastLineColor, 260 3, // same default as VCL, a minimum of three discrete units (pixels) offset 261 false); 262 const Primitive2DReference aHatch( 263 new PolyPolygonHatchPrimitive2D( 264 aPolyPolygon, 265 aEmptyColor, 266 aFillHatchAttribute)); 267 268 aRetval = Primitive2DSequence(&aHatch, 1); 269 } 270 else 271 { 272 // create fill primitive 273 const Primitive2DReference aFill( 274 new PolyPolygonColorPrimitive2D( 275 aPolyPolygon, 276 getColor())); 277 278 aRetval = Primitive2DSequence(&aFill, 1); 279 280 // embed filled to transparency (if used) 281 if(getTransparence() > 0.0) 282 { 283 const Primitive2DReference aFillTransparent( 284 new UnifiedTransparencePrimitive2D( 285 aRetval, 286 getTransparence())); 287 288 aRetval = Primitive2DSequence(&aFillTransparent, 1); 289 } 290 } 291 } 292 293 return aRetval; 294 } 295 296 bool OverlayRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const 297 { 298 if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) 299 { 300 const OverlayRectanglePrimitive& rCompare = static_cast< const OverlayRectanglePrimitive& >(rPrimitive); 301 302 return (getObjectRange() == rCompare.getObjectRange() 303 && getColor() == rCompare.getColor() 304 && getTransparence() == rCompare.getTransparence() 305 && getDiscreteGrow() == rCompare.getDiscreteGrow() 306 && getDiscreteShrink() == rCompare.getDiscreteShrink() 307 && getRotation() == rCompare.getRotation()); 308 } 309 310 return false; 311 } 312 313 ImplPrimitrive2DIDBlock(OverlayRectanglePrimitive, PRIMITIVE2D_ID_OVERLAYRECTANGLEPRIMITIVE) 314 315 } // end of namespace primitive2d 316 } // end of namespace drawinglayer 317 318 ////////////////////////////////////////////////////////////////////////////// 319 320 namespace drawinglayer 321 { 322 namespace primitive2d 323 { 324 OverlayHelplineStripedPrimitive::OverlayHelplineStripedPrimitive( 325 const basegfx::B2DPoint& rBasePosition, 326 HelplineStyle eStyle, 327 const basegfx::BColor& rRGBColorA, 328 const basegfx::BColor& rRGBColorB, 329 double fDiscreteDashLength) 330 : ViewportDependentPrimitive2D(), 331 maBasePosition(rBasePosition), 332 meStyle(eStyle), 333 maRGBColorA(rRGBColorA), 334 maRGBColorB(rRGBColorB), 335 mfDiscreteDashLength(fDiscreteDashLength) 336 {} 337 338 Primitive2DSequence OverlayHelplineStripedPrimitive::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const 339 { 340 // use the prepared Viewport information accessible using getViewport() 341 Primitive2DSequence aRetval; 342 343 if(!getViewport().isEmpty()) 344 { 345 switch(getStyle()) 346 { 347 case HELPLINESTYLE_VERTICAL : 348 { 349 aRetval.realloc(1); 350 basegfx::B2DPolygon aLine; 351 352 aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY())); 353 aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY())); 354 355 aRetval[0] = Primitive2DReference( 356 new PolygonMarkerPrimitive2D( 357 aLine, 358 getRGBColorA(), 359 getRGBColorB(), 360 getDiscreteDashLength())); 361 break; 362 } 363 364 case HELPLINESTYLE_HORIZONTAL : 365 { 366 aRetval.realloc(1); 367 basegfx::B2DPolygon aLine; 368 369 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY())); 370 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY())); 371 372 aRetval[0] = Primitive2DReference( 373 new PolygonMarkerPrimitive2D( 374 aLine, 375 getRGBColorA(), 376 getRGBColorB(), 377 getDiscreteDashLength())); 378 break; 379 } 380 381 default: // case HELPLINESTYLE_POINT : 382 { 383 const double fDiscreteUnit((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength()); 384 aRetval.realloc(2); 385 basegfx::B2DPolygon aLineA, aLineB; 386 387 aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() - fDiscreteUnit)); 388 aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() + fDiscreteUnit)); 389 390 aRetval[0] = Primitive2DReference( 391 new PolygonMarkerPrimitive2D( 392 aLineA, 393 getRGBColorA(), 394 getRGBColorB(), 395 getDiscreteDashLength())); 396 397 aLineB.append(basegfx::B2DPoint(getBasePosition().getX() - fDiscreteUnit, getBasePosition().getY())); 398 aLineB.append(basegfx::B2DPoint(getBasePosition().getX() + fDiscreteUnit, getBasePosition().getY())); 399 400 aRetval[1] = Primitive2DReference( 401 new PolygonMarkerPrimitive2D( 402 aLineB, 403 getRGBColorA(), 404 getRGBColorB(), 405 getDiscreteDashLength())); 406 407 break; 408 } 409 } 410 } 411 412 return aRetval; 413 } 414 415 bool OverlayHelplineStripedPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const 416 { 417 if(ViewportDependentPrimitive2D::operator==(rPrimitive)) 418 { 419 const OverlayHelplineStripedPrimitive& rCompare = static_cast< const OverlayHelplineStripedPrimitive& >(rPrimitive); 420 421 return (getBasePosition() == rCompare.getBasePosition() 422 && getStyle() == rCompare.getStyle() 423 && getRGBColorA() == rCompare.getRGBColorA() 424 && getRGBColorB() == rCompare.getRGBColorB() 425 && getDiscreteDashLength() == rCompare.getDiscreteDashLength()); 426 } 427 428 return false; 429 } 430 431 ImplPrimitrive2DIDBlock(OverlayHelplineStripedPrimitive, PRIMITIVE2D_ID_OVERLAYHELPLINESTRIPEDPRIMITIVE) 432 433 } // end of namespace primitive2d 434 } // end of namespace drawinglayer 435 436 ////////////////////////////////////////////////////////////////////////////// 437 438 namespace drawinglayer 439 { 440 namespace primitive2d 441 { 442 OverlayRollingRectanglePrimitive::OverlayRollingRectanglePrimitive( 443 const basegfx::B2DRange& aRollingRectangle, 444 const basegfx::BColor& rRGBColorA, 445 const basegfx::BColor& rRGBColorB, 446 double fDiscreteDashLength) 447 : ViewportDependentPrimitive2D(), 448 maRollingRectangle(aRollingRectangle), 449 maRGBColorA(rRGBColorA), 450 maRGBColorB(rRGBColorB), 451 mfDiscreteDashLength(fDiscreteDashLength) 452 {} 453 454 Primitive2DSequence OverlayRollingRectanglePrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const 455 { 456 // use the prepared Viewport information accessible using getViewport() 457 Primitive2DSequence aRetval; 458 459 if(!getViewport().isEmpty()) 460 { 461 basegfx::B2DPolygon aLine; 462 aRetval.realloc(8); 463 464 // Left lines 465 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMinY())); 466 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY())); 467 aRetval[0] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); 468 469 aLine.clear(); 470 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMaxY())); 471 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY())); 472 aRetval[1] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); 473 474 // Right lines 475 aLine.clear(); 476 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY())); 477 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMinY())); 478 aRetval[2] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); 479 480 aLine.clear(); 481 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY())); 482 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMaxY())); 483 aRetval[3] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); 484 485 // Top lines 486 aLine.clear(); 487 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMinY())); 488 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY())); 489 aRetval[4] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); 490 491 aLine.clear(); 492 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMinY())); 493 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY())); 494 aRetval[5] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); 495 496 // Bottom lines 497 aLine.clear(); 498 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY())); 499 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMaxY())); 500 aRetval[6] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); 501 502 aLine.clear(); 503 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY())); 504 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMaxY())); 505 aRetval[7] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength())); 506 } 507 508 return aRetval; 509 } 510 511 bool OverlayRollingRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const 512 { 513 if(ViewportDependentPrimitive2D::operator==(rPrimitive)) 514 { 515 const OverlayRollingRectanglePrimitive& rCompare = static_cast< const OverlayRollingRectanglePrimitive& >(rPrimitive); 516 517 return (getRollingRectangle() == rCompare.getRollingRectangle() 518 && getRGBColorA() == rCompare.getRGBColorA() 519 && getRGBColorB() == rCompare.getRGBColorB() 520 && getDiscreteDashLength() == rCompare.getDiscreteDashLength()); 521 } 522 523 return false; 524 } 525 526 ImplPrimitrive2DIDBlock(OverlayRollingRectanglePrimitive, PRIMITIVE2D_ID_OVERLAYROLLINGRECTANGLEPRIMITIVE) 527 528 } // end of namespace primitive2d 529 } // end of namespace drawinglayer 530 531 ////////////////////////////////////////////////////////////////////////////// 532 // eof 533