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