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