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