xref: /aoo41x/main/svx/source/svdraw/svdhdl.cxx (revision 2376739d)
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 <algorithm>
28 
29 #include <svx/svdhdl.hxx>
30 #include <svx/svdpagv.hxx>
31 #include <svx/svdetc.hxx>
32 #include <svx/svdmrkv.hxx>
33 #include <vcl/window.hxx>
34 
35 #include <vcl/virdev.hxx>
36 #include <tools/poly.hxx>
37 #include <vcl/bmpacc.hxx>
38 
39 #include <svx/sxekitm.hxx>
40 #include "svx/svdstr.hrc"
41 #include "svx/svdglob.hxx"
42 
43 #include <svx/svdmodel.hxx>
44 #include "gradtrns.hxx"
45 #include <svx/xflgrit.hxx>
46 #include <svx/svdundo.hxx>
47 #include <svx/dialmgr.hxx>
48 #include <svx/xflftrit.hxx>
49 
50 // #105678#
51 #include <svx/svdopath.hxx>
52 #include <basegfx/vector/b2dvector.hxx>
53 #include <basegfx/polygon/b2dpolygon.hxx>
54 #include <svx/sdr/overlay/overlaymanager.hxx>
55 #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
56 #include <svx/sdr/overlay/overlaybitmapex.hxx>
57 #include <svx/sdr/overlay/overlayline.hxx>
58 #include <svx/sdr/overlay/overlaytriangle.hxx>
59 #include <svx/sdr/overlay/overlayrectangle.hxx>
60 #include <svx/sdrpagewindow.hxx>
61 #include <svx/sdrpaintwindow.hxx>
62 #include <vcl/svapp.hxx>
63 #include <svx/sdr/overlay/overlaypolypolygon.hxx>
64 #include <vcl/lazydelete.hxx>
65 
66 #include <basegfx/polygon/b2dpolygontools.hxx>
67 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
68 #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
69 #include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
70 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
71 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
72 
73 ////////////////////////////////////////////////////////////////////////////////////////////////////
74 // #i15222#
75 // Due to the ressource problems in Win95/98 with bitmap ressources i
76 // will change this handle bitmap provinging class. Old version was splitting
77 // and preparing all small handle bitmaps in device bitmap format, now this will
78 // be done on the fly. Thus, tehre is only the one big bitmap remembered. With
79 // three source bitmaps, this will be 3 system bitmap ressources instead of hundreds.
80 // The price for that needs to be evaluated. Maybe we will need another change here
81 // if this is too expensive.
82 class SdrHdlBitmapSet
83 {
84 	// the bitmap holding all infos
85 	BitmapEx				    maMarkersBitmap;
86 
87     // the cropped Bitmaps for reusage
88     ::std::vector< BitmapEx >   maRealMarkers;
89 
90     // elpers
91     BitmapEx& impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const Rectangle& rRectangle);
92 
93 public:
94 	SdrHdlBitmapSet(sal_uInt16 nResId);
95 	~SdrHdlBitmapSet();
96 
97 	const BitmapEx& GetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd=0);
98 };
99 
100 ////////////////////////////////////////////////////////////////////////////////////////////////////
101 #define KIND_COUNT          (14)
102 #define INDEX_COUNT         (6)
103 #define INDIVIDUAL_COUNT    (4)
104 
105 SdrHdlBitmapSet::SdrHdlBitmapSet(sal_uInt16 nResId)
106 :   maMarkersBitmap(ResId(nResId, *ImpGetResMgr())), // just use ressource with alpha channel
107     // 14 kinds (BitmapMarkerKind) use index [0..5], 4 extra
108     maRealMarkers((KIND_COUNT * INDEX_COUNT) + INDIVIDUAL_COUNT)
109 {
110 }
111 
112 SdrHdlBitmapSet::~SdrHdlBitmapSet()
113 {
114 }
115 
116 BitmapEx& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const Rectangle& rRectangle)
117 {
118     BitmapEx& rTargetBitmap = maRealMarkers[nIndex];
119 
120     if(rTargetBitmap.IsEmpty())
121     {
122         rTargetBitmap = maMarkersBitmap;
123         rTargetBitmap.Crop(rRectangle);
124     }
125 
126     return rTargetBitmap;
127 }
128 
129 // change getting of bitmap to use the big ressource bitmap
130 const BitmapEx& SdrHdlBitmapSet::GetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd)
131 {
132 	// fill in size and source position in maMarkersBitmap
133 	const sal_uInt16 nYPos(nInd * 11);
134 
135 	switch(eKindOfMarker)
136 	{
137 		default:
138 		{
139 			DBG_ERROR( "unknown kind of marker" );
140 			// no break here, return Rect_7x7 as default
141 		}
142 		case Rect_7x7:
143 		{
144             return impGetOrCreateTargetBitmap((0 * INDEX_COUNT) + nInd, Rectangle(Point(0, nYPos), Size(7, 7)));
145 		}
146 
147 		case Rect_9x9:
148 		{
149 			return impGetOrCreateTargetBitmap((1 * INDEX_COUNT) + nInd, Rectangle(Point(7, nYPos), Size(9, 9)));
150 		}
151 
152 		case Rect_11x11:
153 		{
154 			return impGetOrCreateTargetBitmap((2 * INDEX_COUNT) + nInd, Rectangle(Point(16, nYPos), Size(11, 11)));
155 		}
156 
157 		case Rect_13x13:
158 		{
159             const sal_uInt16 nIndex((3 * INDEX_COUNT) + nInd);
160 
161 			switch(nInd)
162 			{
163     			case 0:
164                 {
165                     return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(72, 66), Size(13, 13)));
166                 }
167 	    		case 1:
168                 {
169                     return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(85, 66), Size(13, 13)));
170                 }
171 		    	case 2:
172                 {
173                     return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(72, 79), Size(13, 13)));
174                 }
175 			    case 3:
176                 {
177                     return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(85, 79), Size(13, 13)));
178                 }
179     			case 4:
180                 {
181                     return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(98, 79), Size(13, 13)));
182                 }
183                 default: // case 5:
184                 {
185                     return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(98, 66), Size(13, 13)));
186                 }
187 			}
188 		}
189 
190 		case Circ_7x7:
191 		case Customshape_7x7:
192 		{
193 			return impGetOrCreateTargetBitmap((4 * INDEX_COUNT) + nInd, Rectangle(Point(27, nYPos), Size(7, 7)));
194 		}
195 
196 		case Circ_9x9:
197 		case Customshape_9x9:
198 		{
199 			return impGetOrCreateTargetBitmap((5 * INDEX_COUNT) + nInd, Rectangle(Point(34, nYPos), Size(9, 9)));
200 		}
201 
202 		case Circ_11x11:
203 		case Customshape_11x11:
204 		{
205 			return impGetOrCreateTargetBitmap((6 * INDEX_COUNT) + nInd, Rectangle(Point(43, nYPos), Size(11, 11)));
206 		}
207 
208 		case Elli_7x9:
209 		{
210 			return impGetOrCreateTargetBitmap((7 * INDEX_COUNT) + nInd, Rectangle(Point(54, nYPos), Size(7, 9)));
211 		}
212 
213 		case Elli_9x11:
214 		{
215 			return impGetOrCreateTargetBitmap((8 * INDEX_COUNT) + nInd, Rectangle(Point(61, nYPos), Size(9, 11)));
216 		}
217 
218 		case Elli_9x7:
219 		{
220 			return impGetOrCreateTargetBitmap((9 * INDEX_COUNT) + nInd, Rectangle(Point(70, nYPos), Size(9, 7)));
221 		}
222 
223 		case Elli_11x9:
224 		{
225 			return impGetOrCreateTargetBitmap((10 * INDEX_COUNT) + nInd, Rectangle(Point(79, nYPos), Size(11, 9)));
226 		}
227 
228 		case RectPlus_7x7:
229 		{
230 			return impGetOrCreateTargetBitmap((11 * INDEX_COUNT) + nInd, Rectangle(Point(90, nYPos), Size(7, 7)));
231 		}
232 
233 		case RectPlus_9x9:
234 		{
235 			return impGetOrCreateTargetBitmap((12 * INDEX_COUNT) + nInd, Rectangle(Point(97, nYPos), Size(9, 9)));
236 		}
237 
238 		case RectPlus_11x11:
239 		{
240 			return impGetOrCreateTargetBitmap((13 * INDEX_COUNT) + nInd, Rectangle(Point(106, nYPos), Size(11, 11)));
241 		}
242 
243 		case Crosshair:
244 		{
245 			return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 0, Rectangle(Point(0, 68), Size(15, 15)));
246 		}
247 
248 		case Glue:
249 		{
250 			return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 1, Rectangle(Point(15, 74), Size(9, 9)));
251 		}
252 
253 		case Anchor: // #101688# AnchorTR for SW
254 		case AnchorTR:
255 		{
256 			return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 2, Rectangle(Point(24, 68), Size(24, 24)));
257 		}
258 
259 		// #98388# add AnchorPressed to be able to aninate anchor control
260 		case AnchorPressed:
261 		case AnchorPressedTR:
262 		{
263 			return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 3, Rectangle(Point(48, 68), Size(24, 24)));
264 		}
265 	}
266 
267 	// cannot happen since all pathes return something; return Rect_7x7 as default (see switch)
268     return maRealMarkers[0];
269 }
270 
271 ////////////////////////////////////////////////////////////////////////////////////////////////////
272 
273 SdrHdlBitmapSet& getSimpleSet()
274 {
275     static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aSimpleSet(new SdrHdlBitmapSet(SIP_SA_MARKERS));
276     return *aSimpleSet.get();
277 }
278 
279 SdrHdlBitmapSet& getModernSet()
280 {
281     static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aModernSet(new SdrHdlBitmapSet(SIP_SA_FINE_MARKERS));
282     return *aModernSet.get();
283 }
284 
285 SdrHdlBitmapSet& getHighContrastSet()
286 {
287     static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aHighContrastSet(new SdrHdlBitmapSet(SIP_SA_ACCESSIBILITY_MARKERS));
288     return *aHighContrastSet.get();
289 }
290 
291 ////////////////////////////////////////////////////////////////////////////////////////////////////
292 
293 SdrHdl::SdrHdl():
294     pObj(NULL),
295     pPV(NULL),
296     pHdlList(NULL),
297     eKind(HDL_MOVE),
298     nDrehWink(0),
299     nObjHdlNum(0),
300     nPolyNum(0),
301     nPPntNum(0),
302     nSourceHdlNum(0),
303     bSelect(sal_False),
304     b1PixMore(sal_False),
305     bPlusHdl(sal_False),
306 	mbMoveOutside(false),
307 	mbMouseOver(false)
308 {
309 }
310 
311 SdrHdl::SdrHdl(const Point& rPnt, SdrHdlKind eNewKind):
312     pObj(NULL),
313     pPV(NULL),
314     pHdlList(NULL),
315     aPos(rPnt),
316     eKind(eNewKind),
317     nDrehWink(0),
318     nObjHdlNum(0),
319     nPolyNum(0),
320     nPPntNum(0),
321     nSourceHdlNum(0),
322     bSelect(sal_False),
323     b1PixMore(sal_False),
324     bPlusHdl(sal_False),
325 	mbMoveOutside(false),
326 	mbMouseOver(false)
327 {
328 }
329 
330 SdrHdl::~SdrHdl()
331 {
332 	GetRidOfIAObject();
333 }
334 
335 void SdrHdl::Set1PixMore(sal_Bool bJa)
336 {
337 	if(b1PixMore != bJa)
338 	{
339 		b1PixMore = bJa;
340 
341 		// create new display
342 		Touch();
343 	}
344 }
345 
346 void SdrHdl::SetMoveOutside( bool bMoveOutside )
347 {
348 	if(mbMoveOutside != bMoveOutside)
349 	{
350 		mbMoveOutside = bMoveOutside;
351 
352 		// create new display
353 		Touch();
354 	}
355 }
356 
357 void SdrHdl::SetDrehWink(long n)
358 {
359 	if(nDrehWink != n)
360 	{
361 		nDrehWink = n;
362 
363 		// create new display
364 		Touch();
365 	}
366 }
367 
368 void SdrHdl::SetPos(const Point& rPnt)
369 {
370 	if(aPos != rPnt)
371 	{
372 		// remember new position
373 		aPos = rPnt;
374 
375 		// create new display
376 		Touch();
377 	}
378 }
379 
380 void SdrHdl::SetSelected(sal_Bool bJa)
381 {
382 	if(bSelect != bJa)
383 	{
384 		// remember new value
385 		bSelect = bJa;
386 
387 		// create new display
388 		Touch();
389 	}
390 }
391 
392 void SdrHdl::SetHdlList(SdrHdlList* pList)
393 {
394 	if(pHdlList != pList)
395 	{
396 		// rememver list
397 		pHdlList = pList;
398 
399 		// now its possible to create graphic representation
400 		Touch();
401 	}
402 }
403 
404 void SdrHdl::SetObj(SdrObject* pNewObj)
405 {
406 	if(pObj != pNewObj)
407 	{
408 		// remember new object
409 		pObj = pNewObj;
410 
411 		// graphic representation may have changed
412 		Touch();
413 	}
414 }
415 
416 void SdrHdl::Touch()
417 {
418 	// force update of graphic representation
419 	CreateB2dIAObject();
420 }
421 
422 void SdrHdl::GetRidOfIAObject()
423 {
424 	//OLMaIAOGroup.Delete();
425 
426 	// OVERLAYMANAGER
427 	maOverlayGroup.clear();
428 }
429 
430 void SdrHdl::CreateB2dIAObject()
431 {
432 	// first throw away old one
433 	GetRidOfIAObject();
434 
435 	if(pHdlList && pHdlList->GetView() && !pHdlList->GetView()->areMarkHandlesHidden())
436 	{
437 		BitmapColorIndex eColIndex = LightGreen;
438 		BitmapMarkerKind eKindOfMarker = Rect_7x7;
439 
440         sal_Bool bRot = pHdlList->IsRotateShear();
441         if(pObj)
442             eColIndex = (bSelect) ? Cyan : LightCyan;
443         if(bRot)
444 		{
445 			// Drehhandles in Rot
446             if(pObj && bSelect)
447 				eColIndex = Red;
448 			else
449 	            eColIndex = LightRed;
450         }
451 
452 		switch(eKind)
453 		{
454 			case HDL_MOVE:
455 			{
456 				eKindOfMarker = (b1PixMore) ? Rect_9x9 : Rect_7x7;
457 				break;
458 			}
459 			case HDL_UPLFT:
460 			case HDL_UPRGT:
461 			case HDL_LWLFT:
462 			case HDL_LWRGT:
463 			{
464 				// corner handles
465 				if(bRot)
466 				{
467 					eKindOfMarker = Circ_7x7;
468 				}
469 				else
470 				{
471 					eKindOfMarker = Rect_7x7;
472 				}
473 				break;
474 			}
475 			case HDL_UPPER:
476 			case HDL_LOWER:
477 			{
478 				// Upper/Lower handles
479 				if(bRot)
480 				{
481 					eKindOfMarker = Elli_9x7;
482 				}
483 				else
484 				{
485 					eKindOfMarker = Rect_7x7;
486 				}
487 				break;
488 			}
489 			case HDL_LEFT:
490 			case HDL_RIGHT:
491 			{
492 				// Left/Right handles
493 				if(bRot)
494 				{
495 					eKindOfMarker = Elli_7x9;
496 				}
497 				else
498 				{
499 					eKindOfMarker = Rect_7x7;
500 				}
501 				break;
502 			}
503 			case HDL_POLY:
504 			{
505 				if(bRot)
506 				{
507 					eKindOfMarker = (b1PixMore) ? Circ_9x9 : Circ_7x7;
508 				}
509 				else
510 				{
511 					eKindOfMarker = (b1PixMore) ? Rect_9x9 : Rect_7x7;
512 				}
513 				break;
514 			}
515 			case HDL_BWGT: // weight at poly
516 			{
517 				eKindOfMarker = Circ_7x7;
518 				break;
519 			}
520 			case HDL_CIRC:
521 			{
522 				eKindOfMarker = Rect_11x11;
523 				break;
524 			}
525 			case HDL_REF1:
526 			case HDL_REF2:
527 			{
528 				eKindOfMarker = Crosshair;
529 				break;
530 			}
531 			case HDL_GLUE:
532 			{
533 				eKindOfMarker = Glue;
534 				break;
535 			}
536 			case HDL_ANCHOR:
537 			{
538 				eKindOfMarker = Anchor;
539 				break;
540 			}
541 			case HDL_USER:
542 			{
543 				break;
544 			}
545 			// #101688# top right anchor for SW
546 			case HDL_ANCHOR_TR:
547 			{
548 				eKindOfMarker = AnchorTR;
549 				break;
550 			}
551 
552 			// for SJ and the CustomShapeHandles:
553 			case HDL_CUSTOMSHAPE1:
554 			{
555 				eKindOfMarker = (b1PixMore) ? Customshape_9x9 : Customshape_7x7;
556 				eColIndex = Yellow;
557 				break;
558 			}
559             default:
560                 break;
561 		}
562 
563 		SdrMarkView* pView = pHdlList->GetView();
564 		SdrPageView* pPageView = pView->GetSdrPageView();
565 
566 		if(pPageView)
567 		{
568 			for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
569 			{
570 				// const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
571 				const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
572 
573 				if(rPageWindow.GetPaintWindow().OutputToWindow())
574 				{
575 					Point aMoveOutsideOffset(0, 0);
576 
577 					// add offset if necessary
578 					if(pHdlList->IsMoveOutside() || mbMoveOutside)
579 					{
580 						OutputDevice& rOutDev = rPageWindow.GetPaintWindow().GetOutputDevice();
581 						Size aOffset = rOutDev.PixelToLogic(Size(4, 4));
582 
583 						if(eKind == HDL_UPLFT || eKind == HDL_UPPER || eKind == HDL_UPRGT)
584 							aMoveOutsideOffset.Y() -= aOffset.Width();
585 						if(eKind == HDL_LWLFT || eKind == HDL_LOWER || eKind == HDL_LWRGT)
586 							aMoveOutsideOffset.Y() += aOffset.Height();
587 						if(eKind == HDL_UPLFT || eKind == HDL_LEFT  || eKind == HDL_LWLFT)
588 							aMoveOutsideOffset.X() -= aOffset.Width();
589 						if(eKind == HDL_UPRGT || eKind == HDL_RIGHT || eKind == HDL_LWRGT)
590 							aMoveOutsideOffset.X() += aOffset.Height();
591 					}
592 
593 					if(rPageWindow.GetOverlayManager())
594 					{
595 						basegfx::B2DPoint aPosition(aPos.X(), aPos.Y());
596 						::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject(
597 							aPosition,
598 							eColIndex,
599 							eKindOfMarker,
600 							aMoveOutsideOffset);
601 
602 						// OVERLAYMANAGER
603 						if(pNewOverlayObject)
604 						{
605 							rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
606 							maOverlayGroup.append(*pNewOverlayObject);
607 						}
608 					}
609 				}
610 			}
611 		}
612 	}
613 }
614 
615 BitmapMarkerKind SdrHdl::GetNextBigger(BitmapMarkerKind eKnd) const
616 {
617 	BitmapMarkerKind eRetval(eKnd);
618 
619 	switch(eKnd)
620 	{
621 		case Rect_7x7:			eRetval = Rect_9x9;			break;
622 		case Rect_9x9:			eRetval = Rect_11x11;		break;
623 		case Rect_11x11:		eRetval = Rect_13x13;		break;
624 		//case Rect_13x13:		eRetval = ;	break;
625 
626 		case Circ_7x7:			eRetval = Circ_9x9;			break;
627 		case Circ_9x9:			eRetval = Circ_11x11;		break;
628 		//case Circ_11x11:		eRetval = ;	break;
629 
630 		case Customshape_7x7:		eRetval = Customshape_9x9;	    break;
631 		case Customshape_9x9:		eRetval = Customshape_11x11;    break;
632 		//case Customshape_11x11:	eRetval = ;	break;
633 
634 		case Elli_7x9:			eRetval = Elli_9x11;		break;
635 		//case Elli_9x11:			eRetval = ;	break;
636 
637 		case Elli_9x7:			eRetval = Elli_11x9;		break;
638 		//case Elli_11x9:			eRetval = ;	break;
639 
640 		case RectPlus_7x7:		eRetval = RectPlus_9x9;		break;
641 		case RectPlus_9x9:		eRetval = RectPlus_11x11;	break;
642 		//case RectPlus_11x11:	eRetval = ;	break;
643 
644 		//case Crosshair:			eRetval = ;	break;
645 		//case Glue:				eRetval = ;	break;
646 
647 		// #98388# let anchor blink with it's pressed state
648 		case Anchor:			eRetval = AnchorPressed;	break;
649 
650 		// #101688# same for AnchorTR
651 		case AnchorTR:			eRetval = AnchorPressedTR;	break;
652         default:
653             break;
654 	}
655 
656 	return eRetval;
657 }
658 
659 // #101928#
660 BitmapEx SdrHdl::ImpGetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd, sal_Bool bFine, sal_Bool bIsHighContrast)
661 {
662 	if(bIsHighContrast)
663 	{
664 		return getHighContrastSet().GetBitmapEx(eKindOfMarker, nInd);
665 	}
666 	else
667 	{
668 		if(bFine)
669 		{
670 			return getModernSet().GetBitmapEx(eKindOfMarker, nInd);
671 		}
672 		else
673 		{
674 			return getSimpleSet().GetBitmapEx(eKindOfMarker, nInd);
675 		}
676 	}
677 }
678 
679 ::sdr::overlay::OverlayObject* SdrHdl::CreateOverlayObject(
680 	const basegfx::B2DPoint& rPos,
681 	BitmapColorIndex eColIndex, BitmapMarkerKind eKindOfMarker, Point aMoveOutsideOffset)
682 {
683 	::sdr::overlay::OverlayObject* pRetval = 0L;
684 	sal_Bool bIsFineHdl(pHdlList->IsFineHdl());
685 	const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
686 	sal_Bool bIsHighContrast(rStyleSettings.GetHighContrastMode());
687 
688 	// support bigger sizes
689 	sal_Bool bForceBiggerSize(sal_False);
690 
691 	if(pHdlList->GetHdlSize() > 3)
692 	{
693         switch(eKindOfMarker)
694         {
695             case Anchor:
696             case AnchorPressed:
697             case AnchorTR:
698             case AnchorPressedTR:
699             {
700                 // #121463# For anchor, do not simply make bigger because of HdlSize,
701                 // do it dependent of IsSelected() which Writer can set in drag mode
702                 if(IsSelected())
703                 {
704                     bForceBiggerSize = sal_True;
705                 }
706                 break;
707             }
708             default:
709             {
710                 bForceBiggerSize = sal_True;
711                 break;
712             }
713         }
714 	}
715 
716 	// #101928# ...for high contrast, too.
717 	if(!bForceBiggerSize && bIsHighContrast)
718 	{
719 		// #107925#
720 		// ...but not for anchors, else they will not blink when activated
721 		if(Anchor != eKindOfMarker && AnchorTR != eKindOfMarker)
722 		{
723 			bForceBiggerSize = sal_True;
724 		}
725 	}
726 
727 	if(bForceBiggerSize)
728 	{
729 		eKindOfMarker = GetNextBigger(eKindOfMarker);
730 	}
731 
732 	// #97016# II This handle has the focus, visualize it
733 	if(IsFocusHdl() && pHdlList && pHdlList->GetFocusHdl() == this)
734 	{
735 		// create animated handle
736 		BitmapMarkerKind eNextBigger = GetNextBigger(eKindOfMarker);
737 
738 		if(eNextBigger == eKindOfMarker)
739 		{
740 			// this may happen for the not supported getting-bigger types.
741 			// Choose an alternative here
742 			switch(eKindOfMarker)
743 			{
744 				case Rect_13x13:		eNextBigger = Rect_11x11;	break;
745 				case Circ_11x11:		eNextBigger = Elli_11x9;	break;
746 				case Elli_9x11:			eNextBigger = Elli_11x9;	break;
747 				case Elli_11x9:			eNextBigger = Elli_9x11;	break;
748 				case RectPlus_11x11:	eNextBigger = Rect_13x13;	break;
749 
750 				case Crosshair:
751 					eNextBigger = Glue;
752 					break;
753 
754 				case Glue:
755 					eNextBigger = Crosshair;
756 					break;
757                 default:
758                     break;
759 			}
760 		}
761 
762 		// create animated hdl
763 		// #101928# use ImpGetBitmapEx(...) now
764 		BitmapEx aBmpEx1 = ImpGetBitmapEx(eKindOfMarker, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast);
765 		BitmapEx aBmpEx2 = ImpGetBitmapEx(eNextBigger, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast);
766 
767 		// #i53216# Use system cursor blink time. Use the unsigned value.
768 		const sal_uInt32 nBlinkTime((sal_uInt32)Application::GetSettings().GetStyleSettings().GetCursorBlinkTime());
769 
770 		if(eKindOfMarker == Anchor || eKindOfMarker == AnchorPressed)
771 		{
772 			// #98388# when anchor is used take upper left as reference point inside the handle
773 			pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime);
774 		}
775 		else if(eKindOfMarker == AnchorTR || eKindOfMarker == AnchorPressedTR)
776 		{
777 			// #101688# AnchorTR for SW, take top right as (0,0)
778 			pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime,
779 				(sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1), 0,
780 				(sal_uInt16)(aBmpEx2.GetSizePixel().Width() - 1), 0);
781 		}
782 		else
783 		{
784 			// create centered handle as default
785 			pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime,
786 				(sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
787 				(sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1,
788 				(sal_uInt16)(aBmpEx2.GetSizePixel().Width() - 1) >> 1,
789 				(sal_uInt16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1);
790 		}
791 	}
792 	else
793 	{
794 		// create normal handle
795 		// #101928# use ImpGetBitmapEx(...) now
796 		BitmapEx aBmpEx = ImpGetBitmapEx(eKindOfMarker, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast);
797 
798 		if(eKindOfMarker == Anchor || eKindOfMarker == AnchorPressed)
799 		{
800 			// #98388# upper left as reference point inside the handle for AnchorPressed, too
801 			pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx);
802 		}
803 		else if(eKindOfMarker == AnchorTR || eKindOfMarker == AnchorPressedTR)
804 		{
805 			// #101688# AnchorTR for SW, take top right as (0,0)
806 			pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx,
807 				(sal_uInt16)(aBmpEx.GetSizePixel().Width() - 1), 0);
808 		}
809 		else
810 		{
811 			sal_uInt16 nCenX((sal_uInt16)(aBmpEx.GetSizePixel().Width() - 1L) >> 1);
812 			sal_uInt16 nCenY((sal_uInt16)(aBmpEx.GetSizePixel().Height() - 1L) >> 1);
813 
814 			if(aMoveOutsideOffset.X() > 0)
815 			{
816 				nCenX = 0;
817 			}
818 			else if(aMoveOutsideOffset.X() < 0)
819 			{
820 				nCenX = (sal_uInt16)(aBmpEx.GetSizePixel().Width() - 1);
821 			}
822 
823 			if(aMoveOutsideOffset.Y() > 0)
824 			{
825 				nCenY = 0;
826 			}
827 			else if(aMoveOutsideOffset.Y() < 0)
828 			{
829 				nCenY = (sal_uInt16)(aBmpEx.GetSizePixel().Height() - 1);
830 			}
831 
832 			// create centered handle as default
833 			pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx, nCenX, nCenY);
834 		}
835 	}
836 
837 	return pRetval;
838 }
839 
840 bool SdrHdl::IsHdlHit(const Point& rPnt) const
841 {
842 	// OVERLAYMANAGER
843 	basegfx::B2DPoint aPosition(rPnt.X(), rPnt.Y());
844 	return maOverlayGroup.isHitLogic(aPosition);
845 }
846 
847 Pointer SdrHdl::GetPointer() const
848 {
849     PointerStyle ePtr=POINTER_MOVE;
850     const sal_Bool bSize=eKind>=HDL_UPLFT && eKind<=HDL_LWRGT;
851     const sal_Bool bRot=pHdlList!=NULL && pHdlList->IsRotateShear();
852     const sal_Bool bDis=pHdlList!=NULL && pHdlList->IsDistortShear();
853     if (bSize && pHdlList!=NULL && (bRot || bDis)) {
854         switch (eKind) {
855             case HDL_UPLFT: case HDL_UPRGT:
856             case HDL_LWLFT: case HDL_LWRGT: ePtr=bRot ? POINTER_ROTATE : POINTER_REFHAND; break;
857             case HDL_LEFT : case HDL_RIGHT: ePtr=POINTER_VSHEAR; break;
858             case HDL_UPPER: case HDL_LOWER: ePtr=POINTER_HSHEAR; break;
859             default:
860                 break;
861         }
862     } else {
863         // Fuer Resize von gedrehten Rechtecken die Mauszeiger etwas mitdrehen
864         if (bSize && nDrehWink!=0) {
865             long nHdlWink=0;
866             switch (eKind) {
867                 case HDL_LWRGT: nHdlWink=31500; break;
868                 case HDL_LOWER: nHdlWink=27000; break;
869                 case HDL_LWLFT: nHdlWink=22500; break;
870                 case HDL_LEFT : nHdlWink=18000; break;
871                 case HDL_UPLFT: nHdlWink=13500; break;
872                 case HDL_UPPER: nHdlWink=9000;  break;
873                 case HDL_UPRGT: nHdlWink=4500;  break;
874                 case HDL_RIGHT: nHdlWink=0;     break;
875                 default:
876                     break;
877             }
878             nHdlWink+=nDrehWink+2249; // und etwas drauf (zum runden)
879             while (nHdlWink<0) nHdlWink+=36000;
880             while (nHdlWink>=36000) nHdlWink-=36000;
881             nHdlWink/=4500;
882             switch ((sal_uInt8)nHdlWink) {
883                 case 0: ePtr=POINTER_ESIZE;  break;
884                 case 1: ePtr=POINTER_NESIZE; break;
885                 case 2: ePtr=POINTER_NSIZE;  break;
886                 case 3: ePtr=POINTER_NWSIZE; break;
887                 case 4: ePtr=POINTER_WSIZE;  break;
888                 case 5: ePtr=POINTER_SWSIZE; break;
889                 case 6: ePtr=POINTER_SSIZE;  break;
890                 case 7: ePtr=POINTER_SESIZE; break;
891             } // switch
892         } else {
893             switch (eKind) {
894                 case HDL_UPLFT: ePtr=POINTER_NWSIZE;  break;
895                 case HDL_UPPER: ePtr=POINTER_NSIZE;     break;
896                 case HDL_UPRGT: ePtr=POINTER_NESIZE;  break;
897                 case HDL_LEFT : ePtr=POINTER_WSIZE;     break;
898                 case HDL_RIGHT: ePtr=POINTER_ESIZE;     break;
899                 case HDL_LWLFT: ePtr=POINTER_SWSIZE;  break;
900                 case HDL_LOWER: ePtr=POINTER_SSIZE;     break;
901                 case HDL_LWRGT: ePtr=POINTER_SESIZE;  break;
902                 case HDL_POLY : ePtr=POINTER_MOVEPOINT; break;
903                 case HDL_CIRC : ePtr=POINTER_HAND;      break;
904                 case HDL_REF1 : ePtr=POINTER_REFHAND;   break;
905                 case HDL_REF2 : ePtr=POINTER_REFHAND;   break;
906                 case HDL_BWGT : ePtr=POINTER_MOVEBEZIERWEIGHT; break;
907                 case HDL_GLUE : ePtr=POINTER_MOVEPOINT; break;
908 				case HDL_CUSTOMSHAPE1 : ePtr=POINTER_HAND; break;
909                 default:
910                     break;
911             }
912         }
913     }
914     return Pointer(ePtr);
915 }
916 
917 // #97016# II
918 sal_Bool SdrHdl::IsFocusHdl() const
919 {
920 	switch(eKind)
921 	{
922 		case HDL_UPLFT:		// Oben links
923 		case HDL_UPPER:		// Oben
924 		case HDL_UPRGT:		// Oben rechts
925 		case HDL_LEFT:		// Links
926 		case HDL_RIGHT:		// Rechts
927 		case HDL_LWLFT:		// Unten links
928 		case HDL_LOWER:		// Unten
929 		case HDL_LWRGT:		// Unten rechts
930 		{
931 			// if it's a activated TextEdit, it's moved to extended points
932 			if(pHdlList && pHdlList->IsMoveOutside())
933 				return sal_False;
934 			else
935 				return sal_True;
936 		}
937 
938 		case HDL_MOVE:		// Handle zum Verschieben des Objekts
939 		case HDL_POLY:		// Punktselektion an Polygon oder Bezierkurve
940 		case HDL_BWGT:		// Gewicht an einer Bezierkurve
941 		case HDL_CIRC:		// Winkel an Kreissegmenten, Eckenradius am Rect
942 		case HDL_REF1:		// Referenzpunkt 1, z.B. Rotationsmitte
943 		case HDL_REF2:		// Referenzpunkt 2, z.B. Endpunkt der Spiegelachse
944 		//case HDL_MIRX:		// Die Spiegelachse selbst
945 		case HDL_GLUE:		// GluePoint
946 
947 		// #98388# do NOT activate here, let SW implement their own SdrHdl and
948 		// overload IsFocusHdl() there to make the anchor accessible
949 		//case HDL_ANCHOR:		// anchor symbol (SD, SW)
950 		// #101688# same for AnchorTR
951 		//case HDL_ANCHOR_TR:	// anchor symbol (SD, SW)
952 
953 		//case HDL_TRNS:		// interactive transparence
954 		//case HDL_GRAD:		// interactive gradient
955 		//case HDL_COLR:		// interactive color
956 
957 		// for SJ and the CustomShapeHandles:
958 		case HDL_CUSTOMSHAPE1:
959 
960 		case HDL_USER:
961 		{
962 			return sal_True;
963 		}
964 
965 		default:
966 		{
967 			return sal_False;
968 		}
969 	}
970 }
971 
972 void SdrHdl::onMouseEnter(const MouseEvent& /*rMEvt*/)
973 {
974 }
975 
976 void SdrHdl::onMouseLeave()
977 {
978 }
979 
980 bool SdrHdl::isMouseOver() const
981 {
982 	return mbMouseOver;
983 }
984 
985 ////////////////////////////////////////////////////////////////////////////////////////////////////
986 // class SdrHdlColor
987 
988 SdrHdlColor::SdrHdlColor(const Point& rRef, Color aCol, const Size& rSize, sal_Bool bLum)
989 :	SdrHdl(rRef, HDL_COLR),
990 	aMarkerSize(rSize),
991 	bUseLuminance(bLum)
992 {
993 	if(IsUseLuminance())
994 		aCol = GetLuminance(aCol);
995 
996 	// remember color
997 	aMarkerColor = aCol;
998 }
999 
1000 SdrHdlColor::~SdrHdlColor()
1001 {
1002 }
1003 
1004 void SdrHdlColor::CreateB2dIAObject()
1005 {
1006 	// first throw away old one
1007 	GetRidOfIAObject();
1008 
1009 	if(pHdlList)
1010 	{
1011 		SdrMarkView* pView = pHdlList->GetView();
1012 
1013 		if(pView && !pView->areMarkHandlesHidden())
1014 		{
1015 			SdrPageView* pPageView = pView->GetSdrPageView();
1016 
1017 			if(pPageView)
1018 			{
1019 				for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
1020 				{
1021 					// const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
1022 					const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1023 
1024 					if(rPageWindow.GetPaintWindow().OutputToWindow())
1025 					{
1026 						if(rPageWindow.GetOverlayManager())
1027 						{
1028 							Bitmap aBmpCol(CreateColorDropper(aMarkerColor));
1029 							basegfx::B2DPoint aPosition(aPos.X(), aPos.Y());
1030 							::sdr::overlay::OverlayObject* pNewOverlayObject = new
1031 								::sdr::overlay::OverlayBitmapEx(
1032 									aPosition,
1033                                     BitmapEx(aBmpCol),
1034 									(sal_uInt16)(aBmpCol.GetSizePixel().Width() - 1) >> 1,
1035 									(sal_uInt16)(aBmpCol.GetSizePixel().Height() - 1) >> 1
1036 								);
1037 							DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!");
1038 
1039 							// OVERLAYMANAGER
1040 							if(pNewOverlayObject)
1041 							{
1042 								rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1043 								maOverlayGroup.append(*pNewOverlayObject);
1044 							}
1045 						}
1046 					}
1047 				}
1048 			}
1049 		}
1050 	}
1051 }
1052 
1053 Bitmap SdrHdlColor::CreateColorDropper(Color aCol)
1054 {
1055 	// get the Bitmap
1056 	Bitmap aRetval(aMarkerSize, 24);
1057 	aRetval.Erase(aCol);
1058 
1059 	// get write access
1060 	BitmapWriteAccess* pWrite = aRetval.AcquireWriteAccess();
1061 	DBG_ASSERT(pWrite, "Got NO write access to a new Bitmap !!!");
1062 
1063 	if(pWrite)
1064 	{
1065 		// draw outer border
1066 		sal_Int32 nWidth = aMarkerSize.Width();
1067 		sal_Int32 nHeight = aMarkerSize.Height();
1068 
1069 		pWrite->SetLineColor(Color(COL_LIGHTGRAY));
1070 		pWrite->DrawLine(Point(0, 0), Point(0, nHeight - 1));
1071 		pWrite->DrawLine(Point(1, 0), Point(nWidth - 1, 0));
1072 		pWrite->SetLineColor(Color(COL_GRAY));
1073 		pWrite->DrawLine(Point(1, nHeight - 1), Point(nWidth - 1, nHeight - 1));
1074 		pWrite->DrawLine(Point(nWidth - 1, 1), Point(nWidth - 1, nHeight - 2));
1075 
1076 		// draw lighter UpperLeft
1077         const Color aLightColor(
1078             (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetRed() + (sal_Int16)0x0040), (sal_Int16)0x00ff)),
1079             (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetGreen() + (sal_Int16)0x0040), (sal_Int16)0x00ff)),
1080             (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetBlue() + (sal_Int16)0x0040), (sal_Int16)0x00ff)));
1081 		pWrite->SetLineColor(aLightColor);
1082 		pWrite->DrawLine(Point(1, 1), Point(1, nHeight - 2));
1083 		pWrite->DrawLine(Point(2, 1), Point(nWidth - 2, 1));
1084 
1085 		// draw darker LowerRight
1086         const Color aDarkColor(
1087             (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetRed() - (sal_Int16)0x0040), (sal_Int16)0x0000)),
1088             (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetGreen() - (sal_Int16)0x0040), (sal_Int16)0x0000)),
1089             (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetBlue() - (sal_Int16)0x0040), (sal_Int16)0x0000)));
1090 		pWrite->SetLineColor(aDarkColor);
1091 		pWrite->DrawLine(Point(2, nHeight - 2), Point(nWidth - 2, nHeight - 2));
1092 		pWrite->DrawLine(Point(nWidth - 2, 2), Point(nWidth - 2, nHeight - 3));
1093 
1094 		// get rid of write access
1095 		delete pWrite;
1096 	}
1097 
1098 	return aRetval;
1099 }
1100 
1101 Color SdrHdlColor::GetLuminance(const Color& rCol)
1102 {
1103 	sal_uInt8 aLum = rCol.GetLuminance();
1104 	Color aRetval(aLum, aLum, aLum);
1105 	return aRetval;
1106 }
1107 
1108 void SdrHdlColor::CallColorChangeLink()
1109 {
1110 	aColorChangeHdl.Call(this);
1111 }
1112 
1113 void SdrHdlColor::SetColor(Color aNew, sal_Bool bCallLink)
1114 {
1115 	if(IsUseLuminance())
1116 		aNew = GetLuminance(aNew);
1117 
1118 	if(aMarkerColor != aNew)
1119 	{
1120 		// remember new color
1121 		aMarkerColor = aNew;
1122 
1123 		// create new display
1124 		Touch();
1125 
1126 		// tell about change
1127 		if(bCallLink)
1128 			CallColorChangeLink();
1129 	}
1130 }
1131 
1132 void SdrHdlColor::SetSize(const Size& rNew)
1133 {
1134 	if(rNew != aMarkerSize)
1135 	{
1136 		// remember new size
1137 		aMarkerSize = rNew;
1138 
1139 		// create new display
1140 		Touch();
1141 	}
1142 }
1143 
1144 ////////////////////////////////////////////////////////////////////////////////////////////////////
1145 // class SdrHdlGradient
1146 
1147 SdrHdlGradient::SdrHdlGradient(const Point& rRef1, const Point& rRef2, sal_Bool bGrad)
1148 :	SdrHdl(rRef1, bGrad ? HDL_GRAD : HDL_TRNS),
1149 	pColHdl1(NULL),
1150 	pColHdl2(NULL),
1151     a2ndPos(rRef2),
1152     bGradient(bGrad)
1153 {
1154 }
1155 
1156 SdrHdlGradient::~SdrHdlGradient()
1157 {
1158 }
1159 
1160 void SdrHdlGradient::Set2ndPos(const Point& rPnt)
1161 {
1162 	if(a2ndPos != rPnt)
1163 	{
1164 		// remember new position
1165 		a2ndPos = rPnt;
1166 
1167 		// create new display
1168 		Touch();
1169 	}
1170 }
1171 
1172 void SdrHdlGradient::CreateB2dIAObject()
1173 {
1174 	// first throw away old one
1175 	GetRidOfIAObject();
1176 
1177 	if(pHdlList)
1178 	{
1179 		SdrMarkView* pView = pHdlList->GetView();
1180 
1181 		if(pView && !pView->areMarkHandlesHidden())
1182 		{
1183 			SdrPageView* pPageView = pView->GetSdrPageView();
1184 
1185 			if(pPageView)
1186 			{
1187 				for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
1188 				{
1189 					const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1190 
1191 					if(rPageWindow.GetPaintWindow().OutputToWindow())
1192 					{
1193 						if(rPageWindow.GetOverlayManager())
1194 						{
1195 							// striped line in between
1196 							basegfx::B2DVector aVec(a2ndPos.X() - aPos.X(), a2ndPos.Y() - aPos.Y());
1197 							double fVecLen = aVec.getLength();
1198 							double fLongPercentArrow = (1.0 - 0.05) * fVecLen;
1199 							double fHalfArrowWidth = (0.05 * 0.5) * fVecLen;
1200 							aVec.normalize();
1201 							basegfx::B2DVector aPerpend(-aVec.getY(), aVec.getX());
1202 							sal_Int32 nMidX = (sal_Int32)(aPos.X() + aVec.getX() * fLongPercentArrow);
1203 							sal_Int32 nMidY = (sal_Int32)(aPos.Y() + aVec.getY() * fLongPercentArrow);
1204 							Point aMidPoint(nMidX, nMidY);
1205 
1206 							basegfx::B2DPoint aPosition(aPos.X(), aPos.Y());
1207 							basegfx::B2DPoint aMidPos(aMidPoint.X(), aMidPoint.Y());
1208 
1209 							::sdr::overlay::OverlayObject* pNewOverlayObject = new
1210 								::sdr::overlay::OverlayLineStriped(
1211 									aPosition, aMidPos
1212 								);
1213 							DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!");
1214 
1215 							pNewOverlayObject->setBaseColor(IsGradient() ? Color(COL_BLACK) : Color(COL_BLUE));
1216 							rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1217 							maOverlayGroup.append(*pNewOverlayObject);
1218 
1219 							// arrowhead
1220 							Point aLeft(aMidPoint.X() + (sal_Int32)(aPerpend.getX() * fHalfArrowWidth),
1221 										aMidPoint.Y() + (sal_Int32)(aPerpend.getY() * fHalfArrowWidth));
1222 							Point aRight(aMidPoint.X() - (sal_Int32)(aPerpend.getX() * fHalfArrowWidth),
1223 										aMidPoint.Y() - (sal_Int32)(aPerpend.getY() * fHalfArrowWidth));
1224 
1225 							basegfx::B2DPoint aPositionLeft(aLeft.X(), aLeft.Y());
1226 							basegfx::B2DPoint aPositionRight(aRight.X(), aRight.Y());
1227 							basegfx::B2DPoint aPosition2(a2ndPos.X(), a2ndPos.Y());
1228 
1229 							pNewOverlayObject = new
1230 								::sdr::overlay::OverlayTriangle(
1231 									aPositionLeft,
1232                                     aPosition2,
1233                                     aPositionRight,
1234                                     IsGradient() ? Color(COL_BLACK) : Color(COL_BLUE)
1235 								);
1236 							DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!");
1237 
1238 							rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1239 							maOverlayGroup.append(*pNewOverlayObject);
1240 						}
1241 					}
1242 				}
1243 			}
1244 		}
1245 	}
1246 }
1247 
1248 IMPL_LINK(SdrHdlGradient, ColorChangeHdl, SdrHdl*, /*pHdl*/)
1249 {
1250 	if(GetObj())
1251 		FromIAOToItem(GetObj(), sal_True, sal_True);
1252 	return 0;
1253 }
1254 
1255 void SdrHdlGradient::FromIAOToItem(SdrObject* _pObj, sal_Bool bSetItemOnObject, sal_Bool bUndo)
1256 {
1257 	// from IAO positions and colors to gradient
1258     const SfxItemSet& rSet = _pObj->GetMergedItemSet();
1259 
1260 	GradTransformer aGradTransformer;
1261 	GradTransGradient aOldGradTransGradient;
1262 	GradTransGradient aGradTransGradient;
1263 	GradTransVector aGradTransVector;
1264 
1265 	String aString;
1266 
1267 	aGradTransVector.maPositionA = basegfx::B2DPoint(GetPos().X(), GetPos().Y());
1268 	aGradTransVector.maPositionB = basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y());
1269 	if(pColHdl1)
1270 		aGradTransVector.aCol1 = pColHdl1->GetColor();
1271 	if(pColHdl2)
1272 		aGradTransVector.aCol2 = pColHdl2->GetColor();
1273 
1274 	if(IsGradient())
1275 		aOldGradTransGradient.aGradient = ((XFillGradientItem&)rSet.Get(XATTR_FILLGRADIENT)).GetGradientValue();
1276 	else
1277 		aOldGradTransGradient.aGradient = ((XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE)).GetGradientValue();
1278 
1279 	// transform vector data to gradient
1280     aGradTransformer.VecToGrad(aGradTransVector, aGradTransGradient, aOldGradTransGradient, _pObj, bMoveSingleHandle, bMoveFirstHandle);
1281 
1282 	if(bSetItemOnObject)
1283 	{
1284         SdrModel* pModel = _pObj->GetModel();
1285 		SfxItemSet aNewSet(pModel->GetItemPool());
1286 
1287 		if(IsGradient())
1288 		{
1289 			aString = String();
1290 			XFillGradientItem aNewGradItem(aString, aGradTransGradient.aGradient);
1291 			aNewSet.Put(aNewGradItem);
1292 		}
1293 		else
1294 		{
1295 			aString = String();
1296 			XFillFloatTransparenceItem aNewTransItem(aString, aGradTransGradient.aGradient);
1297 			aNewSet.Put(aNewTransItem);
1298 		}
1299 
1300 		if(bUndo && pModel->IsUndoEnabled())
1301 		{
1302 			pModel->BegUndo(SVX_RESSTR(IsGradient() ? SIP_XA_FILLGRADIENT : SIP_XA_FILLTRANSPARENCE));
1303 			pModel->AddUndo(pModel->GetSdrUndoFactory().CreateUndoAttrObject(*_pObj));
1304 			pModel->EndUndo();
1305 		}
1306 
1307 		pObj->SetMergedItemSetAndBroadcast(aNewSet);
1308 	}
1309 
1310 	// back transformation, set values on pIAOHandle
1311     aGradTransformer.GradToVec(aGradTransGradient, aGradTransVector, _pObj);
1312 
1313 	SetPos(Point(FRound(aGradTransVector.maPositionA.getX()), FRound(aGradTransVector.maPositionA.getY())));
1314 	Set2ndPos(Point(FRound(aGradTransVector.maPositionB.getX()), FRound(aGradTransVector.maPositionB.getY())));
1315 	if(pColHdl1)
1316 	{
1317 		pColHdl1->SetPos(Point(FRound(aGradTransVector.maPositionA.getX()), FRound(aGradTransVector.maPositionA.getY())));
1318 		pColHdl1->SetColor(aGradTransVector.aCol1);
1319 	}
1320 	if(pColHdl2)
1321 	{
1322 		pColHdl2->SetPos(Point(FRound(aGradTransVector.maPositionB.getX()), FRound(aGradTransVector.maPositionB.getY())));
1323 		pColHdl2->SetColor(aGradTransVector.aCol2);
1324 	}
1325 }
1326 
1327 ////////////////////////////////////////////////////////////////////////////////////////////////////
1328 
1329 SdrHdlLine::~SdrHdlLine() {}
1330 
1331 void SdrHdlLine::CreateB2dIAObject()
1332 {
1333 	// first throw away old one
1334 	GetRidOfIAObject();
1335 
1336 	if(pHdlList)
1337 	{
1338 		SdrMarkView* pView = pHdlList->GetView();
1339 
1340 		if(pView && !pView->areMarkHandlesHidden() && pHdl1 && pHdl2)
1341 		{
1342 			SdrPageView* pPageView = pView->GetSdrPageView();
1343 
1344 			if(pPageView)
1345 			{
1346 				for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
1347 				{
1348 					const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1349 
1350 					if(rPageWindow.GetPaintWindow().OutputToWindow())
1351 					{
1352 						if(rPageWindow.GetOverlayManager())
1353 						{
1354 							basegfx::B2DPoint aPosition1(pHdl1->GetPos().X(), pHdl1->GetPos().Y());
1355 							basegfx::B2DPoint aPosition2(pHdl2->GetPos().X(), pHdl2->GetPos().Y());
1356 
1357 							::sdr::overlay::OverlayObject* pNewOverlayObject = new
1358 								::sdr::overlay::OverlayLineStriped(
1359 									aPosition1,
1360 									aPosition2
1361 								);
1362 							DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!");
1363 
1364 							// OVERLAYMANAGER
1365 							if(pNewOverlayObject)
1366 							{
1367 								// color(?)
1368 								pNewOverlayObject->setBaseColor(Color(COL_LIGHTRED));
1369 
1370 								rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1371 								maOverlayGroup.append(*pNewOverlayObject);
1372 							}
1373 						}
1374 					}
1375 				}
1376 			}
1377 		}
1378 	}
1379 }
1380 
1381 Pointer SdrHdlLine::GetPointer() const
1382 {
1383     return Pointer(POINTER_REFHAND);
1384 }
1385 
1386 ////////////////////////////////////////////////////////////////////////////////////////////////////
1387 
1388 SdrHdlBezWgt::~SdrHdlBezWgt() {}
1389 
1390 void SdrHdlBezWgt::CreateB2dIAObject()
1391 {
1392 	// call parent
1393 	SdrHdl::CreateB2dIAObject();
1394 
1395 	// create lines
1396 	if(pHdlList)
1397 	{
1398 		SdrMarkView* pView = pHdlList->GetView();
1399 
1400 		if(pView && !pView->areMarkHandlesHidden())
1401 		{
1402 			SdrPageView* pPageView = pView->GetSdrPageView();
1403 
1404 			if(pPageView)
1405 			{
1406 				for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
1407 				{
1408 					const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1409 
1410 					if(rPageWindow.GetPaintWindow().OutputToWindow())
1411 					{
1412 						if(rPageWindow.GetOverlayManager())
1413 						{
1414 							basegfx::B2DPoint aPosition1(pHdl1->GetPos().X(), pHdl1->GetPos().Y());
1415 							basegfx::B2DPoint aPosition2(aPos.X(), aPos.Y());
1416 
1417 							if(!aPosition1.equal(aPosition2))
1418 							{
1419 								::sdr::overlay::OverlayObject* pNewOverlayObject = new
1420 									::sdr::overlay::OverlayLineStriped(
1421 										aPosition1,
1422 										aPosition2
1423 									);
1424 								DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!");
1425 
1426 								// OVERLAYMANAGER
1427 								if(pNewOverlayObject)
1428 								{
1429 									// line part is not hittable
1430 									pNewOverlayObject->setHittable(sal_False);
1431 
1432 									// color(?)
1433 									pNewOverlayObject->setBaseColor(Color(COL_LIGHTBLUE));
1434 
1435 									rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1436 									maOverlayGroup.append(*pNewOverlayObject);
1437 								}
1438 							}
1439 						}
1440 					}
1441 				}
1442 			}
1443 		}
1444 	}
1445 }
1446 
1447 ////////////////////////////////////////////////////////////////////////////////////////////////////
1448 
1449 E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon& rWireframePoly)
1450 {
1451 	aWireframePoly = rWireframePoly;
1452 }
1453 
1454 void E3dVolumeMarker::CreateB2dIAObject()
1455 {
1456 	// create lines
1457 	if(pHdlList)
1458 	{
1459 		SdrMarkView* pView = pHdlList->GetView();
1460 
1461 		if(pView && !pView->areMarkHandlesHidden())
1462 		{
1463 			SdrPageView* pPageView = pView->GetSdrPageView();
1464 
1465 			if(pPageView)
1466 			{
1467 				for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
1468 				{
1469 					const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1470 
1471 					if(rPageWindow.GetPaintWindow().OutputToWindow())
1472 					{
1473 						if(rPageWindow.GetOverlayManager() && aWireframePoly.count())
1474 							{
1475 								::sdr::overlay::OverlayObject* pNewOverlayObject = new
1476 								::sdr::overlay::OverlayPolyPolygonStripedAndFilled(
1477                                     aWireframePoly);
1478 								DBG_ASSERT(pNewOverlayObject, "Got NO new IAO!");
1479 
1480 								// OVERLAYMANAGER
1481 								if(pNewOverlayObject)
1482 								{
1483 									pNewOverlayObject->setBaseColor(Color(COL_BLACK));
1484 
1485 									rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1486 									maOverlayGroup.append(*pNewOverlayObject);
1487 								}
1488 							}
1489 						}
1490 					}
1491 				}
1492 			}
1493 		}
1494 	}
1495 
1496 ////////////////////////////////////////////////////////////////////////////////////////////////////
1497 
1498 ImpEdgeHdl::~ImpEdgeHdl()
1499 {
1500 }
1501 
1502 void ImpEdgeHdl::CreateB2dIAObject()
1503 {
1504 	if(nObjHdlNum <= 1 && pObj)
1505 	{
1506 		// first throw away old one
1507 		GetRidOfIAObject();
1508 
1509 		BitmapColorIndex eColIndex = LightCyan;
1510 		BitmapMarkerKind eKindOfMarker = Rect_7x7;
1511 
1512 		if(pHdlList)
1513 		{
1514 			SdrMarkView* pView = pHdlList->GetView();
1515 
1516 			if(pView && !pView->areMarkHandlesHidden())
1517 			{
1518 				const SdrEdgeObj* pEdge = (SdrEdgeObj*)pObj;
1519 
1520 				if(pEdge->GetConnectedNode(nObjHdlNum == 0) != NULL)
1521 					eColIndex = LightRed;
1522 
1523 				if(nPPntNum < 2)
1524 				{
1525 					// Handle with plus sign inside
1526 					eKindOfMarker = Circ_7x7;
1527 				}
1528 
1529 				SdrPageView* pPageView = pView->GetSdrPageView();
1530 
1531 				if(pPageView)
1532 				{
1533 					for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1534 					{
1535 						const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1536 
1537 						if(rPageWindow.GetPaintWindow().OutputToWindow())
1538 						{
1539 							if(rPageWindow.GetOverlayManager())
1540 							{
1541 								basegfx::B2DPoint aPosition(aPos.X(), aPos.Y());
1542 
1543 								::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject(
1544 									aPosition,
1545 									eColIndex,
1546 									eKindOfMarker);
1547 
1548 								// OVERLAYMANAGER
1549 								if(pNewOverlayObject)
1550 								{
1551 									rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1552 									maOverlayGroup.append(*pNewOverlayObject);
1553 								}
1554 							}
1555 						}
1556 					}
1557 				}
1558 			}
1559 		}
1560 	}
1561 	else
1562 	{
1563 		// call parent
1564 		SdrHdl::CreateB2dIAObject();
1565 	}
1566 }
1567 
1568 void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode)
1569 {
1570 	if(eLineCode != eCode)
1571 	{
1572 		// remember new value
1573 		eLineCode = eCode;
1574 
1575 		// create new display
1576 		Touch();
1577 	}
1578 }
1579 
1580 Pointer ImpEdgeHdl::GetPointer() const
1581 {
1582     SdrEdgeObj* pEdge=PTR_CAST(SdrEdgeObj,pObj);
1583     if (pEdge==NULL)
1584 		return SdrHdl::GetPointer();
1585     if (nObjHdlNum<=1)
1586 		return Pointer(POINTER_MOVEPOINT); //Pointer(POINTER_DRAW_CONNECT);
1587     if (IsHorzDrag())
1588 		return Pointer(POINTER_ESIZE);
1589     else
1590 		return Pointer(POINTER_SSIZE);
1591 }
1592 
1593 sal_Bool ImpEdgeHdl::IsHorzDrag() const
1594 {
1595     SdrEdgeObj* pEdge=PTR_CAST(SdrEdgeObj,pObj);
1596     if (pEdge==NULL)
1597 		return sal_False;
1598     if (nObjHdlNum<=1)
1599 		return sal_False;
1600 
1601 	SdrEdgeKind eEdgeKind = ((SdrEdgeKindItem&)(pEdge->GetObjectItem(SDRATTR_EDGEKIND))).GetValue();
1602 
1603 	const SdrEdgeInfoRec& rInfo=pEdge->aEdgeInfo;
1604     if (eEdgeKind==SDREDGE_ORTHOLINES || eEdgeKind==SDREDGE_BEZIER)
1605 	{
1606         return !rInfo.ImpIsHorzLine(eLineCode,*pEdge->pEdgeTrack);
1607     }
1608 	else if (eEdgeKind==SDREDGE_THREELINES)
1609 	{
1610         long nWink=nObjHdlNum==2 ? rInfo.nAngle1 : rInfo.nAngle2;
1611         if (nWink==0 || nWink==18000)
1612 			return sal_True;
1613         else
1614 			return sal_False;
1615     }
1616     return sal_False;
1617 }
1618 
1619 ////////////////////////////////////////////////////////////////////////////////////////////////////
1620 
1621 ImpMeasureHdl::~ImpMeasureHdl()
1622 {
1623 }
1624 
1625 void ImpMeasureHdl::CreateB2dIAObject()
1626 {
1627 	// first throw away old one
1628 	GetRidOfIAObject();
1629 
1630 	if(pHdlList)
1631 	{
1632 		SdrMarkView* pView = pHdlList->GetView();
1633 
1634 		if(pView && !pView->areMarkHandlesHidden())
1635 		{
1636 			BitmapColorIndex eColIndex = LightCyan;
1637 			BitmapMarkerKind eKindOfMarker = Rect_9x9;
1638 
1639 			if(nObjHdlNum > 1)
1640 			{
1641 				eKindOfMarker = Rect_7x7;
1642 			}
1643 
1644 			if(bSelect)
1645 			{
1646 				eColIndex = Cyan;
1647 			}
1648 
1649 			SdrPageView* pPageView = pView->GetSdrPageView();
1650 
1651 			if(pPageView)
1652 			{
1653 				for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
1654 				{
1655 					const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1656 
1657 					if(rPageWindow.GetPaintWindow().OutputToWindow())
1658 					{
1659 						if(rPageWindow.GetOverlayManager())
1660 						{
1661 							basegfx::B2DPoint aPosition(aPos.X(), aPos.Y());
1662 
1663 							::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject(
1664 								aPosition,
1665 								eColIndex,
1666 								eKindOfMarker);
1667 
1668 							// OVERLAYMANAGER
1669 							if(pNewOverlayObject)
1670 							{
1671 								rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1672 								maOverlayGroup.append(*pNewOverlayObject);
1673 							}
1674 						}
1675 					}
1676 				}
1677 			}
1678 		}
1679 	}
1680 }
1681 
1682 Pointer ImpMeasureHdl::GetPointer() const
1683 {
1684     switch (nObjHdlNum)
1685 	{
1686         case 0: case 1: return Pointer(POINTER_HAND);
1687         case 2: case 3: return Pointer(POINTER_MOVEPOINT);
1688         case 4: case 5: return SdrHdl::GetPointer(); // wird dann entsprechend gedreht
1689     } // switch
1690     return Pointer(POINTER_NOTALLOWED);
1691 }
1692 
1693 ////////////////////////////////////////////////////////////////////////////////////////////////////
1694 
1695 ImpTextframeHdl::ImpTextframeHdl(const Rectangle& rRect) :
1696     SdrHdl(rRect.TopLeft(),HDL_MOVE),
1697     maRect(rRect)
1698 {
1699 }
1700 
1701 void ImpTextframeHdl::CreateB2dIAObject()
1702 {
1703 	// first throw away old one
1704 	GetRidOfIAObject();
1705 
1706 	if(pHdlList)
1707 	{
1708 		SdrMarkView* pView = pHdlList->GetView();
1709 
1710 		if(pView && !pView->areMarkHandlesHidden())
1711 		{
1712 			SdrPageView* pPageView = pView->GetSdrPageView();
1713 
1714 			if(pPageView)
1715 			{
1716 				for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
1717 				{
1718 					const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1719 
1720 					if(rPageWindow.GetPaintWindow().OutputToWindow())
1721 					{
1722 						if(rPageWindow.GetOverlayManager())
1723 						{
1724                             const basegfx::B2DPoint aTopLeft(maRect.Left(), maRect.Top());
1725                             const basegfx::B2DPoint aBottomRight(maRect.Right(), maRect.Bottom());
1726                             const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
1727                             const Color aHilightColor(aSvtOptionsDrawinglayer.getHilightColor());
1728                             const double fTransparence(aSvtOptionsDrawinglayer.GetTransparentSelectionPercent() * 0.01);
1729 
1730                             ::sdr::overlay::OverlayRectangle* pNewOverlayObject = new ::sdr::overlay::OverlayRectangle(
1731                                 aTopLeft,
1732                                 aBottomRight,
1733                                 aHilightColor,
1734                                 fTransparence,
1735                                 3.0,
1736                                 3.0,
1737                                 nDrehWink * -F_PI18000,
1738                                 500,
1739                                 true); // allow animation; the Handle is not shown at text edit time
1740 
1741                             pNewOverlayObject->setHittable(false);
1742 
1743                             // OVERLAYMANAGER
1744                             if(pNewOverlayObject)
1745                             {
1746                                 rPageWindow.GetOverlayManager()->add(*pNewOverlayObject);
1747                                 maOverlayGroup.append(*pNewOverlayObject);
1748                             }
1749                         }
1750                     }
1751                 }
1752             }
1753 		}
1754 	}
1755 }
1756 
1757 ////////////////////////////////////////////////////////////////////////////////////////////////////
1758 
1759 class ImpSdrHdlListSorter: public ContainerSorter {
1760 public:
1761     ImpSdrHdlListSorter(Container& rNewCont): ContainerSorter(rNewCont) {}
1762     virtual int Compare(const void* pElem1, const void* pElem2) const;
1763 };
1764 
1765 int ImpSdrHdlListSorter::Compare(const void* pElem1, const void* pElem2) const
1766 {
1767     SdrHdlKind eKind1=((SdrHdl*)pElem1)->GetKind();
1768     SdrHdlKind eKind2=((SdrHdl*)pElem2)->GetKind();
1769     // Level 1: Erst normale Handles, dann Glue, dann User, dann Plushandles, dann Retpunkt-Handles
1770     unsigned n1=1;
1771     unsigned n2=1;
1772     if (eKind1!=eKind2)
1773 	{
1774         if (eKind1==HDL_REF1 || eKind1==HDL_REF2 || eKind1==HDL_MIRX) n1=5;
1775         else if (eKind1==HDL_GLUE) n1=2;
1776         else if (eKind1==HDL_USER) n1=3;
1777 		else if (eKind1==HDL_SMARTTAG) n1=0;
1778         if (eKind2==HDL_REF1 || eKind2==HDL_REF2 || eKind2==HDL_MIRX) n2=5;
1779         else if (eKind2==HDL_GLUE) n2=2;
1780         else if (eKind2==HDL_USER) n2=3;
1781 		else if (eKind2==HDL_SMARTTAG) n2=0;
1782     }
1783     if (((SdrHdl*)pElem1)->IsPlusHdl()) n1=4;
1784     if (((SdrHdl*)pElem2)->IsPlusHdl()) n2=4;
1785     if (n1==n2)
1786 	{
1787         // Level 2: PageView (Pointer)
1788         SdrPageView* pPV1=((SdrHdl*)pElem1)->GetPageView();
1789         SdrPageView* pPV2=((SdrHdl*)pElem2)->GetPageView();
1790         if (pPV1==pPV2)
1791 		{
1792             // Level 3: Position (x+y)
1793             SdrObject* pObj1=((SdrHdl*)pElem1)->GetObj();
1794             SdrObject* pObj2=((SdrHdl*)pElem2)->GetObj();
1795             if (pObj1==pObj2)
1796 			{
1797                 sal_uInt32 nNum1=((SdrHdl*)pElem1)->GetObjHdlNum();
1798                 sal_uInt32 nNum2=((SdrHdl*)pElem2)->GetObjHdlNum();
1799                 if (nNum1==nNum2)
1800 				{ // #48763#
1801                     if (eKind1==eKind2)
1802                         return (long)pElem1<(long)pElem2 ? -1 : 1; // Notloesung, um immer die gleiche Sortierung zu haben
1803                     return (sal_uInt16)eKind1<(sal_uInt16)eKind2 ? -1 : 1;
1804                 }
1805 				else
1806 					return nNum1<nNum2 ? -1 : 1;
1807             }
1808 			else
1809 			{
1810                 return (long)pObj1<(long)pObj2 ? -1 : 1;
1811             }
1812         }
1813 		else
1814 		{
1815             return (long)pPV1<(long)pPV2 ? -1 : 1;
1816         }
1817     }
1818 	else
1819 	{
1820         return n1<n2 ? -1 : 1;
1821     }
1822 }
1823 
1824 SdrMarkView* SdrHdlList::GetView() const
1825 {
1826 	return pView;
1827 }
1828 
1829 // #105678# Help struct for re-sorting handles
1830 struct ImplHdlAndIndex
1831 {
1832 	SdrHdl*						mpHdl;
1833 	sal_uInt32					mnIndex;
1834 };
1835 
1836 // #105678# Help method for sorting handles taking care of OrdNums, keeping order in
1837 // single objects and re-sorting polygon handles intuitively
1838 extern "C" int __LOADONCALLAPI ImplSortHdlFunc( const void* pVoid1, const void* pVoid2 )
1839 {
1840 	const ImplHdlAndIndex* p1 = (ImplHdlAndIndex*)pVoid1;
1841 	const ImplHdlAndIndex* p2 = (ImplHdlAndIndex*)pVoid2;
1842 
1843 	if(p1->mpHdl->GetObj() == p2->mpHdl->GetObj())
1844 	{
1845 		if(p1->mpHdl->GetObj() && p1->mpHdl->GetObj()->ISA(SdrPathObj))
1846 		{
1847 			// same object and a path object
1848 			if((p1->mpHdl->GetKind() == HDL_POLY || p1->mpHdl->GetKind() == HDL_BWGT)
1849 				&& (p2->mpHdl->GetKind() == HDL_POLY || p2->mpHdl->GetKind() == HDL_BWGT))
1850 			{
1851 				// both handles are point or control handles
1852 				if(p1->mpHdl->GetPolyNum() == p2->mpHdl->GetPolyNum())
1853 				{
1854 					if(p1->mpHdl->GetPointNum() < p2->mpHdl->GetPointNum())
1855 					{
1856 						return -1;
1857 					}
1858 					else
1859 					{
1860 						return 1;
1861 					}
1862 				}
1863 				else if(p1->mpHdl->GetPolyNum() < p2->mpHdl->GetPolyNum())
1864 				{
1865 					return -1;
1866 				}
1867 				else
1868 				{
1869 					return 1;
1870 				}
1871 			}
1872 		}
1873 	}
1874 	else
1875 	{
1876 		if(!p1->mpHdl->GetObj())
1877 		{
1878 			return -1;
1879 		}
1880 		else if(!p2->mpHdl->GetObj())
1881 		{
1882 			return 1;
1883 		}
1884 		else
1885 		{
1886 			// different objects, use OrdNum for sort
1887 			const sal_uInt32 nOrdNum1 = p1->mpHdl->GetObj()->GetOrdNum();
1888 			const sal_uInt32 nOrdNum2 = p2->mpHdl->GetObj()->GetOrdNum();
1889 
1890 			if(nOrdNum1 < nOrdNum2)
1891 			{
1892 				return -1;
1893 			}
1894 			else
1895 			{
1896 				return 1;
1897 			}
1898 		}
1899 	}
1900 
1901 	// fallback to indices
1902 	if(p1->mnIndex < p2->mnIndex)
1903 	{
1904 		return -1;
1905 	}
1906 	else
1907 	{
1908 		return 1;
1909 	}
1910 }
1911 
1912 ////////////////////////////////////////////////////////////////////////////////////////////////////
1913 // #97016# II
1914 
1915 void SdrHdlList::TravelFocusHdl(sal_Bool bForward)
1916 {
1917 	// security correction
1918 	if(mnFocusIndex != CONTAINER_ENTRY_NOTFOUND && mnFocusIndex >= GetHdlCount())
1919 		mnFocusIndex = CONTAINER_ENTRY_NOTFOUND;
1920 
1921 	if(aList.Count())
1922 	{
1923 		// take care of old handle
1924 		const sal_uIntPtr nOldHdlNum(mnFocusIndex);
1925 		SdrHdl* pOld = GetHdl(nOldHdlNum);
1926 		//SDOsal_Bool bRefresh(sal_False);
1927 
1928 		if(pOld)
1929 		{
1930 			// switch off old handle
1931 			mnFocusIndex = CONTAINER_ENTRY_NOTFOUND;
1932 			pOld->Touch();
1933 			//SDObRefresh = sal_True;
1934 		}
1935 
1936 		// #105678# Alloc pointer array for sorted handle list
1937 		ImplHdlAndIndex* pHdlAndIndex = new ImplHdlAndIndex[aList.Count()];
1938 
1939 		// #105678# build sorted handle list
1940 		sal_uInt32 a;
1941 		for( a = 0; a < aList.Count(); a++)
1942 		{
1943 			pHdlAndIndex[a].mpHdl = (SdrHdl*)aList.GetObject(a);
1944 			pHdlAndIndex[a].mnIndex = a;
1945 		}
1946 
1947 		// #105678# qsort all entries
1948 		qsort(pHdlAndIndex, aList.Count(), sizeof(ImplHdlAndIndex), ImplSortHdlFunc);
1949 
1950 		// #105678# look for old num in sorted array
1951 		sal_uIntPtr nOldHdl(nOldHdlNum);
1952 
1953 		if(nOldHdlNum != CONTAINER_ENTRY_NOTFOUND)
1954 		{
1955 			for(a = 0; a < aList.Count(); a++)
1956 			{
1957 				if(pHdlAndIndex[a].mpHdl == pOld)
1958 				{
1959 					nOldHdl = a;
1960 					break;
1961 				}
1962 			}
1963 		}
1964 
1965 		// #105678# build new HdlNum
1966 		sal_uIntPtr nNewHdl(nOldHdl);
1967 
1968 		// #105678# do the focus travel
1969 		if(bForward)
1970 		{
1971 			if(nOldHdl != CONTAINER_ENTRY_NOTFOUND)
1972 			{
1973 				if(nOldHdl == aList.Count() - 1)
1974 				{
1975 					// end forward run
1976 					nNewHdl = CONTAINER_ENTRY_NOTFOUND;
1977 				}
1978 				else
1979 				{
1980 					// simply the next handle
1981 					nNewHdl++;
1982 				}
1983 			}
1984 			else
1985 			{
1986 				// start forward run at first entry
1987 				nNewHdl = 0;
1988 			}
1989 		}
1990 		else
1991 		{
1992 			if(nOldHdl == CONTAINER_ENTRY_NOTFOUND)
1993 			{
1994 				// start backward run at last entry
1995 				nNewHdl = aList.Count() - 1;
1996 
1997 			}
1998 			else
1999 			{
2000 				if(nOldHdl == 0)
2001 				{
2002 					// end backward run
2003 					nNewHdl = CONTAINER_ENTRY_NOTFOUND;
2004 				}
2005 				else
2006 				{
2007 					// simply the previous handle
2008 					nNewHdl--;
2009 				}
2010 			}
2011 		}
2012 
2013 		// #105678# build new HdlNum
2014 		sal_uInt32 nNewHdlNum(nNewHdl);
2015 
2016 		// look for old num in sorted array
2017 		if(nNewHdl != CONTAINER_ENTRY_NOTFOUND)
2018 		{
2019 			SdrHdl* pNew = pHdlAndIndex[nNewHdl].mpHdl;
2020 
2021 			for(a = 0; a < aList.Count(); a++)
2022 			{
2023 				if((SdrHdl*)aList.GetObject(a) == pNew)
2024 				{
2025 					nNewHdlNum = a;
2026 					break;
2027 				}
2028 			}
2029 		}
2030 
2031 		// take care of next handle
2032 		if(nOldHdlNum != nNewHdlNum)
2033 		{
2034 			mnFocusIndex = nNewHdlNum;
2035 			SdrHdl* pNew = GetHdl(mnFocusIndex);
2036 
2037 			if(pNew)
2038 			{
2039 				pNew->Touch();
2040 				//SDObRefresh = sal_True;
2041 			}
2042 		}
2043 
2044 		// #105678# free mem again
2045 		delete [] pHdlAndIndex;
2046 	}
2047 }
2048 
2049 SdrHdl* SdrHdlList::GetFocusHdl() const
2050 {
2051 	if(mnFocusIndex != CONTAINER_ENTRY_NOTFOUND && mnFocusIndex < GetHdlCount())
2052 		return GetHdl(mnFocusIndex);
2053 	else
2054 		return 0L;
2055 }
2056 
2057 void SdrHdlList::SetFocusHdl(SdrHdl* pNew)
2058 {
2059 	if(pNew)
2060 	{
2061 		SdrHdl* pActual = GetFocusHdl();
2062 
2063 		if(!pActual || pActual != pNew)
2064 		{
2065 			sal_uIntPtr nNewHdlNum = GetHdlNum(pNew);
2066 
2067 			if(nNewHdlNum != CONTAINER_ENTRY_NOTFOUND)
2068 			{
2069 				//SDOsal_Bool bRefresh(sal_False);
2070 				mnFocusIndex = nNewHdlNum;
2071 
2072 				if(pActual)
2073 				{
2074 					pActual->Touch();
2075 					//SDObRefresh = sal_True;
2076 				}
2077 
2078 				if(pNew)
2079 				{
2080 					pNew->Touch();
2081 					//SDObRefresh = sal_True;
2082 				}
2083 
2084 				//OLMif(bRefresh)
2085 				//OLM{
2086 				//OLM	if(pView)
2087 				//OLM		pView->RefreshAllIAOManagers();
2088 				//OLM}
2089 			}
2090 		}
2091 	}
2092 }
2093 
2094 void SdrHdlList::ResetFocusHdl()
2095 {
2096 	SdrHdl* pHdl = GetFocusHdl();
2097 
2098 	mnFocusIndex = CONTAINER_ENTRY_NOTFOUND;
2099 
2100 	if(pHdl)
2101 	{
2102 		pHdl->Touch();
2103 	}
2104 }
2105 
2106 ////////////////////////////////////////////////////////////////////////////////////////////////////
2107 
2108 SdrHdlList::SdrHdlList(SdrMarkView* pV)
2109 :	mnFocusIndex(CONTAINER_ENTRY_NOTFOUND),
2110 	pView(pV),
2111 	aList(1024,32,32)
2112 {
2113 	nHdlSize = 3;
2114 	bRotateShear = sal_False;
2115 	bMoveOutside = sal_False;
2116 	bDistortShear = sal_False;
2117 	bFineHandles = sal_True;    // new default: Handles are fine handles
2118 }
2119 
2120 SdrHdlList::~SdrHdlList()
2121 {
2122 	Clear();
2123 }
2124 
2125 void SdrHdlList::SetHdlSize(sal_uInt16 nSiz)
2126 {
2127 	if(nHdlSize != nSiz)
2128 	{
2129 		// remember new value
2130 		nHdlSize = nSiz;
2131 
2132 		// propagate change to IAOs
2133 		for(sal_uInt32 i=0; i<GetHdlCount(); i++)
2134 		{
2135 			SdrHdl* pHdl = GetHdl(i);
2136 			pHdl->Touch();
2137 		}
2138 	}
2139 }
2140 
2141 void SdrHdlList::SetMoveOutside(sal_Bool bOn)
2142 {
2143 	if(bMoveOutside != bOn)
2144 	{
2145 		// remember new value
2146 		bMoveOutside = bOn;
2147 
2148 		// propagate change to IAOs
2149 		for(sal_uInt32 i=0; i<GetHdlCount(); i++)
2150 		{
2151 			SdrHdl* pHdl = GetHdl(i);
2152 			pHdl->Touch();
2153 		}
2154 	}
2155 }
2156 
2157 void SdrHdlList::SetRotateShear(sal_Bool bOn)
2158 {
2159 	bRotateShear = bOn;
2160 }
2161 
2162 void SdrHdlList::SetDistortShear(sal_Bool bOn)
2163 {
2164 	bDistortShear = bOn;
2165 }
2166 
2167 void SdrHdlList::SetFineHdl(sal_Bool bOn)
2168 {
2169 	if(bFineHandles != bOn)
2170 	{
2171 		// remember new state
2172 		bFineHandles = bOn;
2173 
2174 		// propagate change to IAOs
2175 		for(sal_uInt32 i=0; i<GetHdlCount(); i++)
2176 		{
2177 			SdrHdl* pHdl = GetHdl(i);
2178 			pHdl->Touch();
2179 		}
2180 	}
2181 }
2182 
2183 SdrHdl* SdrHdlList::RemoveHdl(sal_uIntPtr nNum)
2184 {
2185 	SdrHdl* pRetval = (SdrHdl*)aList.Remove(nNum);
2186 
2187 	return pRetval;
2188 }
2189 
2190 void SdrHdlList::Clear()
2191 {
2192 	for (sal_uIntPtr i=0; i<GetHdlCount(); i++)
2193 	{
2194 		SdrHdl* pHdl=GetHdl(i);
2195 		delete pHdl;
2196 	}
2197 	aList.Clear();
2198 
2199 	bRotateShear=sal_False;
2200 	bDistortShear=sal_False;
2201 }
2202 
2203 void SdrHdlList::Sort()
2204 {
2205 	// #97016# II: remember current focused handle
2206 	SdrHdl* pPrev = GetFocusHdl();
2207 
2208     ImpSdrHdlListSorter aSort(aList);
2209     aSort.DoSort();
2210 
2211 	// #97016# II: get now and compare
2212 	SdrHdl* pNow = GetFocusHdl();
2213 
2214 	if(pPrev != pNow)
2215 	{
2216 		//SDOsal_Bool bRefresh(sal_False);
2217 
2218 		if(pPrev)
2219 		{
2220 			pPrev->Touch();
2221 			//SDObRefresh = sal_True;
2222 		}
2223 
2224 		if(pNow)
2225 		{
2226 			pNow->Touch();
2227 			//SDObRefresh = sal_True;
2228 		}
2229 	}
2230 }
2231 
2232 sal_uIntPtr SdrHdlList::GetHdlNum(const SdrHdl* pHdl) const
2233 {
2234     if (pHdl==NULL)
2235 		return CONTAINER_ENTRY_NOTFOUND;
2236     sal_uIntPtr nPos=aList.GetPos(pHdl);
2237     return nPos;
2238 }
2239 
2240 void SdrHdlList::AddHdl(SdrHdl* pHdl, sal_Bool bAtBegin)
2241 {
2242     if (pHdl!=NULL)
2243 	{
2244         if (bAtBegin)
2245 		{
2246             aList.Insert(pHdl,sal_uIntPtr(0));
2247         }
2248 		else
2249 		{
2250             aList.Insert(pHdl,CONTAINER_APPEND);
2251         }
2252         pHdl->SetHdlList(this);
2253     }
2254 }
2255 
2256 SdrHdl* SdrHdlList::IsHdlListHit(const Point& rPnt, sal_Bool bBack, sal_Bool bNext, SdrHdl* pHdl0) const
2257 {
2258    SdrHdl* pRet=NULL;
2259    sal_uIntPtr nAnz=GetHdlCount();
2260    sal_uIntPtr nNum=bBack ? 0 : nAnz;
2261    while ((bBack ? nNum<nAnz : nNum>0) && pRet==NULL)
2262    {
2263        if (!bBack)
2264 		   nNum--;
2265        SdrHdl* pHdl=GetHdl(nNum);
2266        if (bNext)
2267 	   {
2268            if (pHdl==pHdl0)
2269 			   bNext=sal_False;
2270        }
2271 	   else
2272 	   {
2273            if (pHdl->IsHdlHit(rPnt))
2274 			   pRet=pHdl;
2275        }
2276        if (bBack)
2277 		   nNum++;
2278    }
2279    return pRet;
2280 }
2281 
2282 SdrHdl* SdrHdlList::GetHdl(SdrHdlKind eKind1) const
2283 {
2284    SdrHdl* pRet=NULL;
2285    for (sal_uIntPtr i=0; i<GetHdlCount() && pRet==NULL; i++)
2286    {
2287        SdrHdl* pHdl=GetHdl(i);
2288        if (pHdl->GetKind()==eKind1)
2289 		   pRet=pHdl;
2290    }
2291    return pRet;
2292 }
2293 
2294 // --------------------------------------------------------------------
2295 // SdrCropHdl
2296 // --------------------------------------------------------------------
2297 
2298 SdrCropHdl::SdrCropHdl(const Point& rPnt, SdrHdlKind eNewKind)
2299 : SdrHdl( rPnt, eNewKind )
2300 {
2301 }
2302 
2303 // --------------------------------------------------------------------
2304 
2305 BitmapEx SdrCropHdl::GetHandlesBitmap( bool bIsFineHdl, bool bIsHighContrast )
2306 {
2307 	if( bIsHighContrast )
2308 	{
2309 		static BitmapEx* pHighContrastBitmap = 0;
2310 		if( pHighContrastBitmap == 0 )
2311 			pHighContrastBitmap = new BitmapEx(ResId(SIP_SA_ACCESSIBILITY_CROP_MARKERS, *ImpGetResMgr()));
2312 		return *pHighContrastBitmap;
2313 	}
2314 	else if( bIsFineHdl )
2315 	{
2316 		static BitmapEx* pModernBitmap = 0;
2317 		if( pModernBitmap == 0 )
2318 			pModernBitmap = new BitmapEx(ResId(SIP_SA_CROP_FINE_MARKERS, *ImpGetResMgr()));
2319 		return *pModernBitmap;
2320 	}
2321 	else
2322 	{
2323 		static BitmapEx* pSimpleBitmap = 0;
2324 		if( pSimpleBitmap == 0 )
2325 			pSimpleBitmap = new BitmapEx(ResId(SIP_SA_CROP_MARKERS, *ImpGetResMgr()));
2326 		return *pSimpleBitmap;
2327 	}
2328 }
2329 
2330 // --------------------------------------------------------------------
2331 
2332 BitmapEx SdrCropHdl::GetBitmapForHandle( const BitmapEx& rBitmap, int nSize )
2333 {
2334 	int nPixelSize = 0, nX = 0, nY = 0, nOffset = 0;
2335 
2336 	if( nSize <= 3 )
2337 	{
2338 		nPixelSize = 13;
2339 		nOffset = 0;
2340 	}
2341 	else if( nSize <=4 )
2342 	{
2343 		nPixelSize = 17;
2344 		nOffset = 36;
2345 	}
2346 	else
2347 	{
2348 		nPixelSize = 21;
2349 		nOffset = 84;
2350 	}
2351 
2352 	switch( eKind )
2353 	{
2354 		case HDL_UPLFT: nX = 0; nY = 0; break;
2355 		case HDL_UPPER: nX = 1; nY = 0; break;
2356 		case HDL_UPRGT: nX = 2; nY = 0; break;
2357 		case HDL_LEFT:  nX = 0; nY = 1; break;
2358 		case HDL_RIGHT: nX = 2; nY = 1; break;
2359 		case HDL_LWLFT: nX = 0; nY = 2; break;
2360 		case HDL_LOWER: nX = 1; nY = 2; break;
2361 		case HDL_LWRGT: nX = 2; nY = 2; break;
2362 		default: break;
2363 	}
2364 
2365 	Rectangle aSourceRect( Point( nX * (nPixelSize-1) + nOffset,  nY * (nPixelSize-1)), Size(nPixelSize, nPixelSize) );
2366 
2367 	BitmapEx aRetval(rBitmap);
2368 	aRetval.Crop(aSourceRect);
2369 	return aRetval;
2370 }
2371 
2372 // --------------------------------------------------------------------
2373 
2374 void SdrCropHdl::CreateB2dIAObject()
2375 {
2376 	// first throw away old one
2377 	GetRidOfIAObject();
2378 
2379 	SdrMarkView* pView = pHdlList ? pHdlList->GetView() : 0;
2380 	SdrPageView* pPageView = pView ? pView->GetSdrPageView() : 0;
2381 
2382 	if( pPageView && !pView->areMarkHandlesHidden() )
2383 	{
2384 		sal_Bool bIsFineHdl(pHdlList->IsFineHdl());
2385 		const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2386 		sal_Bool bIsHighContrast(rStyleSettings.GetHighContrastMode());
2387 		int nHdlSize = pHdlList->GetHdlSize();
2388 		if( bIsHighContrast )
2389 			nHdlSize = 4;
2390 
2391 		const BitmapEx aHandlesBitmap( GetHandlesBitmap( bIsFineHdl, bIsHighContrast ) );
2392 		BitmapEx aBmpEx1( GetBitmapForHandle( aHandlesBitmap, nHdlSize ) );
2393 
2394 		for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
2395 		{
2396 			// const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
2397 			const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
2398 
2399 			if(rPageWindow.GetPaintWindow().OutputToWindow())
2400 			{
2401 				if(rPageWindow.GetOverlayManager())
2402 				{
2403 					basegfx::B2DPoint aPosition(aPos.X(), aPos.Y());
2404 
2405 					::sdr::overlay::OverlayObject* pOverlayObject = 0L;
2406 
2407 					// animate focused handles
2408 					if(IsFocusHdl() && (pHdlList->GetFocusHdl() == this))
2409 					{
2410 						if( nHdlSize >= 2 )
2411 							nHdlSize = 1;
2412 
2413 						BitmapEx aBmpEx2( GetBitmapForHandle( aHandlesBitmap, nHdlSize + 1 ) );
2414 
2415 						const sal_uInt32 nBlinkTime = sal::static_int_cast<sal_uInt32>(rStyleSettings.GetCursorBlinkTime());
2416 
2417 						pOverlayObject = new ::sdr::overlay::OverlayAnimatedBitmapEx(aPosition, aBmpEx1, aBmpEx2, nBlinkTime,
2418 							(sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
2419 							(sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1,
2420 							(sal_uInt16)(aBmpEx2.GetSizePixel().Width() - 1) >> 1,
2421 							(sal_uInt16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1);
2422 					}
2423 					else
2424 					{
2425 						// create centered handle as default
2426 						pOverlayObject = new ::sdr::overlay::OverlayBitmapEx(aPosition, aBmpEx1,
2427 							(sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
2428 							(sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1);
2429 					}
2430 
2431 					// OVERLAYMANAGER
2432 					if(pOverlayObject)
2433 					{
2434 						rPageWindow.GetOverlayManager()->add(*pOverlayObject);
2435 						maOverlayGroup.append(*pOverlayObject);
2436 					}
2437 				}
2438 			}
2439 		}
2440 	}
2441 }
2442 
2443 ////////////////////////////////////////////////////////////////////////////////////////////////////
2444 
2445 SdrCropViewHdl::SdrCropViewHdl(
2446     const basegfx::B2DHomMatrix& rObjectTransform,
2447     const Graphic& rGraphic,
2448     double fCropLeft,
2449     double fCropTop,
2450     double fCropRight,
2451     double fCropBottom,
2452     bool bExtraMirrorXFromGraphic)
2453 :   SdrHdl(Point(), HDL_USER),
2454     maObjectTransform(rObjectTransform),
2455     maGraphic(rGraphic),
2456     mfCropLeft(fCropLeft),
2457     mfCropTop(fCropTop),
2458     mfCropRight(fCropRight),
2459     mfCropBottom(fCropBottom),
2460     mbExtraMirrorXFromGraphic(bExtraMirrorXFromGraphic)
2461 {
2462 }
2463 
2464 void SdrCropViewHdl::CreateB2dIAObject()
2465 {
2466     GetRidOfIAObject();
2467     SdrMarkView* pView = pHdlList ? pHdlList->GetView() : 0;
2468     SdrPageView* pPageView = pView ? pView->GetSdrPageView() : 0;
2469 
2470     if(pPageView && pView->areMarkHandlesHidden())
2471     {
2472         return;
2473     }
2474 
2475     // decompose to have current translate and scale
2476     basegfx::B2DVector aScale, aTranslate;
2477     double fRotate, fShearX;
2478 
2479     maObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
2480 
2481     if(aScale.equalZero())
2482     {
2483         return;
2484     }
2485 
2486     // detect 180 degree rotation, this is the same as mirrored in X and Y,
2487     // thus change to mirroring. Prefer mirroring here. Use the equal call
2488     // with getSmallValue here, the original which uses rtl::math::approxEqual
2489     // is too correct here. Maybe this changes with enhanced precision in aw080
2490     // to the better so that this can be reduced to the more precise call again
2491     if(basegfx::fTools::equal(fabs(fRotate), F_PI, 0.000000001))
2492     {
2493         aScale.setX(aScale.getX() * -1.0);
2494         aScale.setY(aScale.getY() * -1.0);
2495         fRotate = 0.0;
2496     }
2497 
2498     // remember mirroring, reset at Scale and adapt crop values for usage;
2499     // mirroring can stay in the object transformation, so do not have to
2500     // cope with it here (except later for the CroppedImage transformation,
2501     // see below)
2502     const bool bMirroredX(aScale.getX() < 0.0);
2503     const bool bMirroredY(aScale.getY() < 0.0);
2504     double fCropLeft(mfCropLeft);
2505     double fCropTop(mfCropTop);
2506     double fCropRight(mfCropRight);
2507     double fCropBottom(mfCropBottom);
2508 
2509     if(bMirroredX)
2510     {
2511         aScale.setX(-aScale.getX());
2512         fCropLeft = mfCropRight;
2513         fCropRight = mfCropLeft;
2514     }
2515 
2516     if(bMirroredY)
2517     {
2518         aScale.setY(-aScale.getY());
2519         fCropTop = mfCropBottom;
2520         fCropBottom = mfCropTop;
2521     }
2522 
2523     // create target translate and scale
2524     const basegfx::B2DVector aTargetScale(
2525         aScale.getX() + fCropRight + fCropLeft,
2526         aScale.getY() + fCropBottom + fCropTop);
2527     const basegfx::B2DVector aTargetTranslate(
2528         aTranslate.getX() - fCropLeft,
2529         aTranslate.getY() - fCropTop);
2530 
2531     // create ranges to make comparisons
2532     const basegfx::B2DRange aCurrentForCompare(
2533         aTranslate.getX(), aTranslate.getY(),
2534         aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
2535     basegfx::B2DRange aCropped(
2536         aTargetTranslate.getX(), aTargetTranslate.getY(),
2537         aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY());
2538 
2539     if(aCropped.isEmpty())
2540     {
2541         // nothing to return since cropped content is completely empty
2542         return;
2543     }
2544 
2545     if(aCurrentForCompare.equal(aCropped))
2546     {
2547         // no crop at all
2548         return;
2549     }
2550 
2551     // back-transform to have values in unit coordinates
2552     basegfx::B2DHomMatrix aBackToUnit;
2553     aBackToUnit.translate(-aTranslate.getX(), -aTranslate.getY());
2554     aBackToUnit.scale(
2555         basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : 1.0 / aScale.getX(),
2556         basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : 1.0 / aScale.getY());
2557 
2558     // transform cropped back to unit coordinates
2559     aCropped.transform(aBackToUnit);
2560 
2561     // prepare crop PolyPolygon
2562     basegfx::B2DPolyPolygon aCropPolyPolygon(
2563         basegfx::tools::createPolygonFromRect(
2564             aCropped));
2565 
2566     // current range is unit range
2567     basegfx::B2DRange aOverlap(0.0, 0.0, 1.0, 1.0);
2568 
2569     aOverlap.intersect(aCropped);
2570 
2571     if(!aOverlap.isEmpty())
2572     {
2573         aCropPolyPolygon.append(
2574             basegfx::tools::createPolygonFromRect(
2575                 aOverlap));
2576     }
2577 
2578     // transform to object coordinates to prepare for clip
2579     aCropPolyPolygon.transform(maObjectTransform);
2580 
2581     // create cropped transformation
2582     basegfx::B2DHomMatrix aCroppedTransform;
2583     const bool bCombinedMirrorX(mbExtraMirrorXFromGraphic || bMirroredX);
2584 
2585     aCroppedTransform.scale(
2586         bCombinedMirrorX ? -aCropped.getWidth() : aCropped.getWidth(),
2587         bMirroredY ? -aCropped.getHeight() : aCropped.getHeight());
2588     aCroppedTransform.translate(
2589         bCombinedMirrorX ? aCropped.getMaxX() : aCropped.getMinX(),
2590         bMirroredY ? aCropped.getMaxY() : aCropped.getMinY());
2591     aCroppedTransform = maObjectTransform * aCroppedTransform;
2592 
2593     // prepare graphic primitive (tranformed)
2594     const drawinglayer::primitive2d::Primitive2DReference aGraphic(
2595         new drawinglayer::primitive2d::GraphicPrimitive2D(
2596             aCroppedTransform,
2597             maGraphic));
2598 
2599     // embed to MaskPrimitive2D
2600     const drawinglayer::primitive2d::Primitive2DReference aMaskedGraphic(
2601         new drawinglayer::primitive2d::MaskPrimitive2D(
2602             aCropPolyPolygon,
2603             drawinglayer::primitive2d::Primitive2DSequence(&aGraphic, 1)));
2604 
2605     // embed to UnifiedTransparencePrimitive2D
2606     const drawinglayer::primitive2d::Primitive2DReference aTransparenceMaskedGraphic(
2607         new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
2608             drawinglayer::primitive2d::Primitive2DSequence(&aMaskedGraphic, 1),
2609             0.8));
2610 
2611     const drawinglayer::primitive2d::Primitive2DSequence aSequence(&aTransparenceMaskedGraphic, 1);
2612 
2613     for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
2614     {
2615         // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
2616         const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
2617 
2618         if(rPageWindow.GetPaintWindow().OutputToWindow())
2619         {
2620             if(rPageWindow.GetOverlayManager())
2621             {
2622                 ::sdr::overlay::OverlayObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence);
2623                 DBG_ASSERT(pNew, "Got NO new IAO!");
2624 
2625                 if(pNew)
2626                 {
2627                     // only informative object, no hit
2628                     pNew->setHittable(false);
2629 
2630                     rPageWindow.GetOverlayManager()->add(*pNew);
2631                     maOverlayGroup.append(*pNew);
2632                 }
2633             }
2634         }
2635     }
2636 }
2637 
2638 ////////////////////////////////////////////////////////////////////////////////////////////////////
2639 // eof
2640