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