xref: /aoo42x/main/svx/source/svdraw/svdhdl.cxx (revision 3452c2f1)
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 resource problems in Win95/98 with bitmap resources I
77 // will change this handle bitmap providing 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, there is only the one big bitmap remembered. With
80 // three source bitmaps, this will be 3 system bitmap resources 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 resource 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 resource 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 animate 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 paths 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 		// remember list
398 		pHdlList = pList;
399 
400 		// now it's 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 			// Rotation handles in red
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 its 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:		// top left
924 		case HDL_UPPER:		// top
925 		case HDL_UPRGT:		// top right
926 		case HDL_LEFT:		// left
927 		case HDL_RIGHT:		// right
928 		case HDL_LWLFT:		// bottom left
929 		case HDL_LOWER:		// bottom
930 		case HDL_LWRGT:		// bottom right
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 transparency
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(); // will be rotated accordingly
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(
2300 	const Point& rPnt,
2301 	SdrHdlKind eNewKind,
2302 	double fShearX,
2303 	double fRotation)
2304 :	SdrHdl(rPnt, eNewKind),
2305 	mfShearX(fShearX),
2306 	mfRotation(fRotation)
2307 {
2308 }
2309 
2310 // --------------------------------------------------------------------
2311 
2312 BitmapEx SdrCropHdl::GetHandlesBitmap( bool bIsFineHdl, bool bIsHighContrast )
2313 {
2314 	if( bIsHighContrast )
2315 	{
2316 		static BitmapEx* pHighContrastBitmap = 0;
2317 		if( pHighContrastBitmap == 0 )
2318 			pHighContrastBitmap = new BitmapEx(ResId(SIP_SA_ACCESSIBILITY_CROP_MARKERS, *ImpGetResMgr()));
2319 		return *pHighContrastBitmap;
2320 	}
2321 	else if( bIsFineHdl )
2322 	{
2323 		static BitmapEx* pModernBitmap = 0;
2324 		if( pModernBitmap == 0 )
2325 			pModernBitmap = new BitmapEx(ResId(SIP_SA_CROP_FINE_MARKERS, *ImpGetResMgr()));
2326 		return *pModernBitmap;
2327 	}
2328 	else
2329 	{
2330 		static BitmapEx* pSimpleBitmap = 0;
2331 		if( pSimpleBitmap == 0 )
2332 			pSimpleBitmap = new BitmapEx(ResId(SIP_SA_CROP_MARKERS, *ImpGetResMgr()));
2333 		return *pSimpleBitmap;
2334 	}
2335 }
2336 
2337 // --------------------------------------------------------------------
2338 
2339 BitmapEx SdrCropHdl::GetBitmapForHandle( const BitmapEx& rBitmap, int nSize )
2340 {
2341 	int nPixelSize = 0, nX = 0, nY = 0, nOffset = 0;
2342 
2343 	if( nSize <= 3 )
2344 	{
2345 		nPixelSize = 13;
2346 		nOffset = 0;
2347 	}
2348 	else if( nSize <=4 )
2349 	{
2350 		nPixelSize = 17;
2351 		nOffset = 36;
2352 	}
2353 	else
2354 	{
2355 		nPixelSize = 21;
2356 		nOffset = 84;
2357 	}
2358 
2359 	switch( eKind )
2360 	{
2361 		case HDL_UPLFT: nX = 0; nY = 0; break;
2362 		case HDL_UPPER: nX = 1; nY = 0; break;
2363 		case HDL_UPRGT: nX = 2; nY = 0; break;
2364 		case HDL_LEFT:  nX = 0; nY = 1; break;
2365 		case HDL_RIGHT: nX = 2; nY = 1; break;
2366 		case HDL_LWLFT: nX = 0; nY = 2; break;
2367 		case HDL_LOWER: nX = 1; nY = 2; break;
2368 		case HDL_LWRGT: nX = 2; nY = 2; break;
2369 		default: break;
2370 	}
2371 
2372 	Rectangle aSourceRect( Point( nX * (nPixelSize-1) + nOffset, nY * (nPixelSize-1)), Size(nPixelSize, nPixelSize) );
2373 
2374 	BitmapEx aRetval(rBitmap);
2375 	aRetval.Crop(aSourceRect);
2376 	return aRetval;
2377 }
2378 
2379 // --------------------------------------------------------------------
2380 
2381 void SdrCropHdl::CreateB2dIAObject()
2382 {
2383 	// first throw away old one
2384 	GetRidOfIAObject();
2385 
2386 	SdrMarkView* pView = pHdlList ? pHdlList->GetView() : 0;
2387 	SdrPageView* pPageView = pView ? pView->GetSdrPageView() : 0;
2388 
2389 	if( pPageView && !pView->areMarkHandlesHidden() )
2390 	{
2391 		sal_Bool bIsFineHdl(pHdlList->IsFineHdl());
2392 		const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2393 		sal_Bool bIsHighContrast(rStyleSettings.GetHighContrastMode());
2394 		int nHdlSize = pHdlList->GetHdlSize();
2395 		if( bIsHighContrast )
2396 			nHdlSize = 4;
2397 
2398 		const BitmapEx aHandlesBitmap( GetHandlesBitmap( bIsFineHdl, bIsHighContrast ) );
2399 		BitmapEx aBmpEx1( GetBitmapForHandle( aHandlesBitmap, nHdlSize ) );
2400 
2401 		for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
2402 		{
2403 			// const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
2404 			const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
2405 
2406 			if(rPageWindow.GetPaintWindow().OutputToWindow())
2407 			{
2408 				if(rPageWindow.GetOverlayManager())
2409 				{
2410 					basegfx::B2DPoint aPosition(aPos.X(), aPos.Y());
2411 
2412 					::sdr::overlay::OverlayObject* pOverlayObject = 0L;
2413 
2414 					// animate focused handles
2415 					if(IsFocusHdl() && (pHdlList->GetFocusHdl() == this))
2416 					{
2417 						if( nHdlSize >= 2 )
2418 							nHdlSize = 1;
2419 
2420 						BitmapEx aBmpEx2( GetBitmapForHandle( aHandlesBitmap, nHdlSize + 1 ) );
2421 
2422 						const sal_uInt32 nBlinkTime = sal::static_int_cast<sal_uInt32>(rStyleSettings.GetCursorBlinkTime());
2423 
2424 						pOverlayObject = new ::sdr::overlay::OverlayAnimatedBitmapEx(
2425 							aPosition,
2426 							aBmpEx1,
2427 							aBmpEx2,
2428 							nBlinkTime,
2429 							(sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
2430 							(sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1,
2431 							(sal_uInt16)(aBmpEx2.GetSizePixel().Width() - 1) >> 1,
2432 							(sal_uInt16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1,
2433 							mfShearX,
2434 							mfRotation);
2435 					}
2436 					else
2437 					{
2438 						// create centered handle as default
2439 						pOverlayObject = new ::sdr::overlay::OverlayBitmapEx(
2440 							aPosition,
2441 							aBmpEx1,
2442 							(sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1,
2443 							(sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1,
2444 							0.0,
2445 							mfShearX,
2446 							mfRotation);
2447 					}
2448 
2449 					// OVERLAYMANAGER
2450 					if(pOverlayObject)
2451 					{
2452 						rPageWindow.GetOverlayManager()->add(*pOverlayObject);
2453 						maOverlayGroup.append(*pOverlayObject);
2454 					}
2455 				}
2456 			}
2457 		}
2458 	}
2459 }
2460 
2461 ////////////////////////////////////////////////////////////////////////////////////////////////////
2462 // with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff
2463 // accordingly
2464 
2465 SdrCropViewHdl::SdrCropViewHdl(
2466 	const basegfx::B2DHomMatrix& rObjectTransform,
2467 	const Graphic& rGraphic,
2468 	double fCropLeft,
2469 	double fCropTop,
2470 	double fCropRight,
2471 	double fCropBottom)
2472 :	SdrHdl(Point(), HDL_USER),
2473 	maObjectTransform(rObjectTransform),
2474 	maGraphic(rGraphic),
2475 	mfCropLeft(fCropLeft),
2476 	mfCropTop(fCropTop),
2477 	mfCropRight(fCropRight),
2478 	mfCropBottom(fCropBottom)
2479 {
2480 }
2481 
2482 void SdrCropViewHdl::CreateB2dIAObject()
2483 {
2484 	GetRidOfIAObject();
2485 	SdrMarkView* pView = pHdlList ? pHdlList->GetView() : 0;
2486 	SdrPageView* pPageView = pView ? pView->GetSdrPageView() : 0;
2487 
2488 	if(pPageView && pView->areMarkHandlesHidden())
2489 	{
2490 		return;
2491 	}
2492 
2493 	// decompose to have current translate and scale
2494 	basegfx::B2DVector aScale, aTranslate;
2495 	double fRotate, fShearX;
2496 
2497 	maObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
2498 
2499 	if(aScale.equalZero())
2500 	{
2501 		return;
2502 	}
2503 
2504 	// detect 180 degree rotation, this is the same as mirrored in X and Y,
2505 	// thus change to mirroring. Prefer mirroring here. Use the equal call
2506 	// with getSmallValue here, the original which uses rtl::math::approxEqual
2507 	// is too correct here. Maybe this changes with enhanced precision in aw080
2508 	// to the better so that this can be reduced to the more precise call again
2509 	if(basegfx::fTools::equal(fabs(fRotate), F_PI, 0.000000001))
2510 	{
2511 		aScale.setX(aScale.getX() * -1.0);
2512 		aScale.setY(aScale.getY() * -1.0);
2513 		fRotate = 0.0;
2514 	}
2515 
2516 	// remember mirroring, reset at Scale and adapt crop values for usage;
2517 	// mirroring can stay in the object transformation, so do not have to
2518 	// cope with it here (except later for the CroppedImage transformation,
2519 	// see below)
2520 	const bool bMirroredX(aScale.getX() < 0.0);
2521 	const bool bMirroredY(aScale.getY() < 0.0);
2522 	double fCropLeft(mfCropLeft);
2523 	double fCropTop(mfCropTop);
2524 	double fCropRight(mfCropRight);
2525 	double fCropBottom(mfCropBottom);
2526 
2527 	if(bMirroredX)
2528 	{
2529 		aScale.setX(-aScale.getX());
2530 	}
2531 
2532 	if(bMirroredY)
2533 	{
2534 		aScale.setY(-aScale.getY());
2535 	}
2536 
2537 	// create target translate and scale
2538 	const basegfx::B2DVector aTargetScale(
2539 		aScale.getX() + fCropRight + fCropLeft,
2540 		aScale.getY() + fCropBottom + fCropTop);
2541 	const basegfx::B2DVector aTargetTranslate(
2542 		aTranslate.getX() - fCropLeft,
2543 		aTranslate.getY() - fCropTop);
2544 
2545 	// create ranges to make comparisons
2546 	const basegfx::B2DRange aCurrentForCompare(
2547 		aTranslate.getX(), aTranslate.getY(),
2548 		aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
2549 	basegfx::B2DRange aCropped(
2550 		aTargetTranslate.getX(), aTargetTranslate.getY(),
2551 		aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY());
2552 
2553 	if(aCropped.isEmpty())
2554 	{
2555 		// nothing to return since cropped content is completely empty
2556 		return;
2557 	}
2558 
2559 	if(aCurrentForCompare.equal(aCropped))
2560 	{
2561 		// no crop at all
2562 		return;
2563 	}
2564 
2565 	// back-transform to have values in unit coordinates
2566 	basegfx::B2DHomMatrix aBackToUnit;
2567 	aBackToUnit.translate(-aTranslate.getX(), -aTranslate.getY());
2568 	aBackToUnit.scale(
2569 		basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : 1.0 / aScale.getX(),
2570 		basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : 1.0 / aScale.getY());
2571 
2572 	// transform cropped back to unit coordinates
2573 	aCropped.transform(aBackToUnit);
2574 
2575 	// prepare crop PolyPolygon
2576 	basegfx::B2DPolygon aGraphicOutlinePolygon(
2577 		basegfx::tools::createPolygonFromRect(
2578 			aCropped));
2579 	basegfx::B2DPolyPolygon aCropPolyPolygon(aGraphicOutlinePolygon);
2580 
2581 	// current range is unit range
2582 	basegfx::B2DRange aOverlap(0.0, 0.0, 1.0, 1.0);
2583 
2584 	aOverlap.intersect(aCropped);
2585 
2586 	if(!aOverlap.isEmpty())
2587 	{
2588 		aCropPolyPolygon.append(
2589 			basegfx::tools::createPolygonFromRect(
2590 				aOverlap));
2591 	}
2592 
2593 	// transform to object coordinates to prepare for clip
2594 	aCropPolyPolygon.transform(maObjectTransform);
2595 	aGraphicOutlinePolygon.transform(maObjectTransform);
2596 
2597 	// create cropped transformation
2598 	basegfx::B2DHomMatrix aCroppedTransform;
2599 	const bool bCombinedMirrorX(bMirroredX);
2600 
2601 	aCroppedTransform.scale(
2602 		aCropped.getWidth(),
2603 		aCropped.getHeight());
2604 	aCroppedTransform.translate(
2605 		aCropped.getMinX(),
2606 		aCropped.getMinY());
2607 	aCroppedTransform = maObjectTransform * aCroppedTransform;
2608 
2609 	// prepare graphic primitive (transformed)
2610 	const drawinglayer::primitive2d::Primitive2DReference aGraphic(
2611 		new drawinglayer::primitive2d::GraphicPrimitive2D(
2612 			aCroppedTransform,
2613 			maGraphic));
2614 
2615 	// prepare outline polygon for whole graphic
2616 	const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
2617 	const basegfx::BColor aHilightColor(aSvtOptionsDrawinglayer.getHilightColor().getBColor());
2618 	const drawinglayer::primitive2d::Primitive2DReference aGraphicOutline(
2619 		new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
2620 		aGraphicOutlinePolygon,
2621 		aHilightColor));
2622 
2623 	// combine these
2624 	drawinglayer::primitive2d::Primitive2DSequence aCombination(2);
2625 	aCombination[0] = aGraphic;
2626 	aCombination[1] = aGraphicOutline;
2627 
2628 	// embed to MaskPrimitive2D
2629 	const drawinglayer::primitive2d::Primitive2DReference aMaskedGraphic(
2630 		new drawinglayer::primitive2d::MaskPrimitive2D(
2631 			aCropPolyPolygon,
2632 			aCombination));
2633 
2634 	// embed to UnifiedTransparencePrimitive2D
2635 	const drawinglayer::primitive2d::Primitive2DReference aTransparenceMaskedGraphic(
2636 		new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
2637 			drawinglayer::primitive2d::Primitive2DSequence(&aMaskedGraphic, 1),
2638 			0.8));
2639 
2640 	const drawinglayer::primitive2d::Primitive2DSequence aSequence(&aTransparenceMaskedGraphic, 1);
2641 
2642 	for(sal_uInt32 b(0L); b < pPageView->PageWindowCount(); b++)
2643 	{
2644 		// const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
2645 		const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
2646 
2647 		if(rPageWindow.GetPaintWindow().OutputToWindow())
2648 		{
2649 			if(rPageWindow.GetOverlayManager())
2650 			{
2651 				::sdr::overlay::OverlayObject* pNew = new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence);
2652 				DBG_ASSERT(pNew, "Got NO new IAO!");
2653 
2654 				if(pNew)
2655 				{
2656 					// only informative object, no hit
2657 					pNew->setHittable(false);
2658 
2659 					rPageWindow.GetOverlayManager()->add(*pNew);
2660 					maOverlayGroup.append(*pNew);
2661 				}
2662 			}
2663 		}
2664 	}
2665 }
2666 
2667 ////////////////////////////////////////////////////////////////////////////////////////////////////
2668 // eof
2669