xref: /trunk/main/svtools/source/misc/imap.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #include <tools/urlobj.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/mapmod.hxx>
34 #include <vcl/window.hxx>
35 
36 #include "svl/urihelper.hxx"
37 #include <svtools/imap.hxx>
38 #include <svtools/imapobj.hxx>
39 #include <svtools/imapcirc.hxx>
40 #include <svtools/imaprect.hxx>
41 #include <svtools/imappoly.hxx>
42 
43 #include <string.h>
44 #include <math.h>
45 
46 DBG_NAME( ImageMap )
47 
48 
49 #define SCALEPOINT(aPT,aFracX,aFracY) (aPT).X()=((aPT).X()*(aFracX).GetNumerator())/(aFracX).GetDenominator();  \
50                                       (aPT).Y()=((aPT).Y()*(aFracY).GetNumerator())/(aFracY).GetDenominator();
51 
52 
53 /******************************************************************************/
54 
55 sal_uInt16 IMapObject::nActualTextEncoding = (sal_uInt16) RTL_TEXTENCODING_DONTKNOW;
56 
57 /******************************************************************************/
58 
59 
60 IMapObject::IMapObject()
61     : bActive( false )
62     , nReadVersion( 0 )
63 {
64 }
65 
66 IMapObject::IMapObject( const String& rURL, const String& rAltText, const String& rDesc,
67                         const String& rTarget, const String& rName, sal_Bool bURLActive )
68 : aURL( rURL )
69 , aAltText( rAltText )
70 , aDesc( rDesc )
71 , aTarget( rTarget )
72 , aName( rName )
73 , bActive( bURLActive )
74 , nReadVersion( 0 )
75 {
76 }
77 
78 
79 /******************************************************************************
80 |*
81 |* Freigabe des internen Speichers
82 |*
83 \******************************************************************************/
84 
85 sal_uInt16 IMapObject::GetVersion() const
86 {
87     return IMAP_OBJ_VERSION;
88 }
89 
90 
91 /******************************************************************************
92 |*
93 |*
94 |*
95 \******************************************************************************/
96 
97 void IMapObject::Write( SvStream& rOStm, const String& rBaseURL ) const
98 {
99     IMapCompat*             pCompat;
100     const rtl_TextEncoding  eEncoding = gsl_getSystemTextEncoding();
101 
102     rOStm << GetType();
103     rOStm << GetVersion();
104     rOStm << ( (sal_uInt16) eEncoding );
105 
106     const ByteString aRelURL = ByteString( String(URIHelper::simpleNormalizedMakeRelative( rBaseURL, aURL )), eEncoding );
107     rOStm.WriteByteString( aRelURL );
108     rOStm.WriteByteString( ByteString( aAltText, eEncoding ) );
109     rOStm << bActive;
110     rOStm.WriteByteString( ByteString( aTarget, eEncoding ) );
111 
112     pCompat = new IMapCompat( rOStm, STREAM_WRITE );
113 
114     WriteIMapObject( rOStm );
115     aEventList.Write( rOStm );                                 // V4
116     rOStm.WriteByteString( ByteString( aName, eEncoding ) );   // V5
117 
118     delete pCompat;
119 }
120 
121 
122 /******************************************************************************
123 |*
124 |*  Binaer-Import
125 |*
126 \******************************************************************************/
127 
128 void IMapObject::Read( SvStream& rIStm, const String& rBaseURL )
129 {
130     IMapCompat*         pCompat;
131     rtl_TextEncoding    nTextEncoding;
132     ByteString          aString;
133 
134     // Typ und Version ueberlesen wir
135     rIStm.SeekRel( 2 );
136     rIStm >> nReadVersion;
137     rIStm >> nTextEncoding;
138     rIStm.ReadByteString( aString ); aURL = String( aString.GetBuffer(), nTextEncoding );
139     rIStm.ReadByteString( aString ); aAltText = String( aString.GetBuffer(), nTextEncoding );
140     rIStm >> bActive;
141     rIStm.ReadByteString( aString ); aTarget = String( aString.GetBuffer(), nTextEncoding );
142 
143     // URL absolut machen
144     aURL = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), aURL, URIHelper::GetMaybeFileHdl(), true, false, INetURLObject::WAS_ENCODED, INetURLObject::DECODE_UNAMBIGUOUS );
145     pCompat = new IMapCompat( rIStm, STREAM_READ );
146 
147     ReadIMapObject( rIStm );
148 
149     // ab Version 4 lesen wir eine EventListe
150     if ( nReadVersion >= 0x0004 )
151     {
152         aEventList.Read(rIStm);
153 
154         // ab Version 5 kann ein Objektname vorhanden sein
155         if ( nReadVersion >= 0x0005 )
156         {
157             rIStm.ReadByteString( aString ); aName = String( aString.GetBuffer(), nTextEncoding );
158         }
159     }
160 
161     delete pCompat;
162 }
163 
164 
165 /******************************************************************************
166 |*
167 |* Konvertierung der logischen Koordianten in Pixel
168 |*
169 \******************************************************************************/
170 
171 Point IMapObject::GetPixelPoint( const Point& rLogPoint )
172 {
173     return Application::GetDefaultDevice()->LogicToPixel( rLogPoint, MapMode( MAP_100TH_MM ) );
174 }
175 
176 
177 /******************************************************************************
178 |*
179 |* Konvertierung der logischen Koordianten in Pixel
180 |*
181 \******************************************************************************/
182 
183 Point IMapObject::GetLogPoint( const Point& rPixelPoint )
184 {
185     return Application::GetDefaultDevice()->PixelToLogic( rPixelPoint, MapMode( MAP_100TH_MM ) );
186 }
187 
188 
189 /******************************************************************************
190 |*
191 |*
192 |*
193 \******************************************************************************/
194 
195 sal_Bool IMapObject::IsEqual( const IMapObject& rEqObj )
196 {
197     return ( ( aURL == rEqObj.aURL ) &&
198              ( aAltText == rEqObj.aAltText ) &&
199              ( aDesc == rEqObj.aDesc ) &&
200              ( aTarget == rEqObj.aTarget ) &&
201              ( aName == rEqObj.aName ) &&
202              ( bActive == rEqObj.bActive ) );
203 }
204 
205 
206 /******************************************************************************/
207 /******************************************************************************/
208 /******************************************************************************/
209 
210 IMapRectangleObject::IMapRectangleObject( const Rectangle& rRect,
211                                           const String& rURL,
212                                           const String& rAltText,
213                                           const String& rDesc,
214                                           const String& rTarget,
215                                           const String& rName,
216                                           sal_Bool bURLActive,
217                                           sal_Bool bPixelCoords ) :
218             IMapObject  ( rURL, rAltText, rDesc, rTarget, rName, bURLActive )
219 {
220     ImpConstruct( rRect, bPixelCoords );
221 }
222 
223 
224 /******************************************************************************
225 |*
226 |*
227 |*
228 \******************************************************************************/
229 
230 void IMapRectangleObject::ImpConstruct( const Rectangle& rRect, sal_Bool bPixel )
231 {
232     if ( bPixel )
233         aRect = Application::GetDefaultDevice()->PixelToLogic( rRect, MapMode( MAP_100TH_MM ) );
234     else
235         aRect = rRect;
236 }
237 
238 
239 /******************************************************************************
240 |*
241 |* Binaer-Export
242 |*
243 \******************************************************************************/
244 
245 void IMapRectangleObject::WriteIMapObject( SvStream& rOStm ) const
246 {
247     rOStm << aRect;
248 }
249 
250 
251 /******************************************************************************
252 |*
253 |* Binaer-Import
254 |*
255 \******************************************************************************/
256 
257 void IMapRectangleObject::ReadIMapObject( SvStream& rIStm )
258 {
259     rIStm >> aRect;
260 }
261 
262 
263 /******************************************************************************
264 |*
265 |* Typ-Rueckgabe
266 |*
267 \******************************************************************************/
268 
269 sal_uInt16 IMapRectangleObject::GetType() const
270 {
271     return IMAP_OBJ_RECTANGLE;
272 }
273 
274 
275 /******************************************************************************
276 |*
277 |* Hit-Test
278 |*
279 \******************************************************************************/
280 
281 sal_Bool IMapRectangleObject::IsHit( const Point& rPoint ) const
282 {
283     return aRect.IsInside( rPoint );
284 }
285 
286 
287 /******************************************************************************
288 |*
289 |*
290 |*
291 \******************************************************************************/
292 
293 Rectangle IMapRectangleObject::GetRectangle( sal_Bool bPixelCoords ) const
294 {
295     Rectangle   aNewRect;
296 
297     if ( bPixelCoords )
298         aNewRect = Application::GetDefaultDevice()->LogicToPixel( aRect, MapMode( MAP_100TH_MM ) );
299     else
300         aNewRect = aRect;
301 
302     return aNewRect;
303 }
304 
305 
306 /******************************************************************************
307 |*
308 |*
309 |*
310 \******************************************************************************/
311 
312 void IMapRectangleObject::Scale( const Fraction& rFracX, const Fraction& rFracY )
313 {
314     Point   aTL( aRect.TopLeft() );
315     Point   aBR( aRect.BottomRight() );
316 
317     if ( rFracX.GetDenominator() && rFracY.GetDenominator() )
318     {
319         SCALEPOINT( aTL, rFracX, rFracY );
320         SCALEPOINT( aBR, rFracX, rFracY );
321     }
322 
323     aRect = Rectangle( aTL, aBR );
324 }
325 
326 
327 /******************************************************************************
328 |*
329 |*
330 |*
331 \******************************************************************************/
332 
333 sal_Bool IMapRectangleObject::IsEqual( const IMapRectangleObject& rEqObj )
334 {
335     return ( IMapObject::IsEqual( rEqObj ) && ( aRect == rEqObj.aRect ) );
336 }
337 
338 
339 /******************************************************************************/
340 /******************************************************************************/
341 /******************************************************************************/
342 
343 IMapCircleObject::IMapCircleObject( const Point& rCenter, sal_uLong nCircleRadius,
344                                     const String& rURL,
345                                     const String& rAltText,
346                                     const String& rDesc,
347                                     const String& rTarget,
348                                     const String& rName,
349                                     sal_Bool bURLActive,
350                                     sal_Bool bPixelCoords ) :
351             IMapObject  ( rURL, rAltText, rDesc, rTarget, rName, bURLActive )
352 {
353     ImpConstruct( rCenter, nCircleRadius, bPixelCoords );
354 }
355 
356 
357 /******************************************************************************
358 |*
359 |*
360 |*
361 \******************************************************************************/
362 
363 void IMapCircleObject::ImpConstruct( const Point& rCenter, sal_uLong nRad, sal_Bool bPixel )
364 {
365     if ( bPixel )
366     {
367         MapMode aMap100( MAP_100TH_MM );
368 
369         aCenter = Application::GetDefaultDevice()->PixelToLogic( rCenter, aMap100 );
370         nRadius = Application::GetDefaultDevice()->PixelToLogic( Size( nRad, 0 ), aMap100 ).Width();
371     }
372     else
373     {
374         aCenter = rCenter;
375         nRadius = nRad;
376     }
377 }
378 
379 
380 /******************************************************************************
381 |*
382 |* Binaer-Export
383 |*
384 \******************************************************************************/
385 
386 void IMapCircleObject::WriteIMapObject( SvStream& rOStm ) const
387 {
388     sal_uInt32 nTmp = nRadius;
389 
390     rOStm << aCenter;
391     rOStm << nTmp;
392 }
393 
394 
395 /******************************************************************************
396 |*
397 |* Binaer-Import
398 |*
399 \******************************************************************************/
400 
401 void IMapCircleObject::ReadIMapObject( SvStream& rIStm )
402 {
403     sal_uInt32 nTmp;
404 
405     rIStm >> aCenter;
406     rIStm >> nTmp;
407 
408     nRadius = nTmp;
409 }
410 
411 
412 /******************************************************************************
413 |*
414 |* Typ-Rueckgabe
415 |*
416 \******************************************************************************/
417 
418 sal_uInt16 IMapCircleObject::GetType() const
419 {
420     return IMAP_OBJ_CIRCLE;
421 }
422 
423 
424 /******************************************************************************
425 |*
426 |* Hit-Test
427 |*
428 \******************************************************************************/
429 
430 sal_Bool IMapCircleObject::IsHit( const Point& rPoint ) const
431 {
432     const Point aPoint( aCenter - rPoint );
433     sal_Bool        bRet = sal_False;
434 
435     if ( (sal_uLong) sqrt( (double) aPoint.X() * aPoint.X() +
436                        aPoint.Y() * aPoint.Y() ) <= nRadius )
437     {
438         bRet = sal_True;
439     }
440 
441     return bRet;
442 }
443 
444 
445 /******************************************************************************
446 |*
447 |*
448 |*
449 \******************************************************************************/
450 
451 Point IMapCircleObject::GetCenter( sal_Bool bPixelCoords ) const
452 {
453     Point aNewPoint;
454 
455     if ( bPixelCoords )
456         aNewPoint = Application::GetDefaultDevice()->LogicToPixel( aCenter, MapMode( MAP_100TH_MM ) );
457     else
458         aNewPoint = aCenter;
459 
460     return aNewPoint;
461 }
462 
463 
464 /******************************************************************************
465 |*
466 |*
467 |*
468 \******************************************************************************/
469 
470 sal_uLong IMapCircleObject::GetRadius( sal_Bool bPixelCoords ) const
471 {
472     sal_uLong nNewRadius;
473 
474     if ( bPixelCoords )
475         nNewRadius = Application::GetDefaultDevice()->LogicToPixel( Size( nRadius, 0 ), MapMode( MAP_100TH_MM ) ).Width();
476     else
477         nNewRadius = nRadius;
478 
479     return nNewRadius;
480 }
481 
482 
483 /******************************************************************************
484 |*
485 |*
486 |*
487 \******************************************************************************/
488 
489 Rectangle IMapCircleObject::GetBoundRect() const
490 {
491     long nWidth = nRadius << 1;
492 
493     return Rectangle( Point(  aCenter.X() - nRadius, aCenter.Y() - nRadius ),
494                       Size( nWidth, nWidth ) );
495 }
496 
497 
498 /******************************************************************************
499 |*
500 |*
501 |*
502 \******************************************************************************/
503 
504 void IMapCircleObject::Scale( const Fraction& rFracX, const Fraction& rFracY )
505 {
506     Fraction aAverage( rFracX );
507 
508     aAverage += rFracY;
509     aAverage *= Fraction( 1, 2 );
510 
511     if ( rFracX.GetDenominator() && rFracY.GetDenominator() )
512     {
513         SCALEPOINT( aCenter, rFracX, rFracY );
514     }
515 
516     nRadius = ( nRadius * aAverage.GetNumerator() ) / aAverage.GetDenominator();
517 }
518 
519 
520 /******************************************************************************
521 |*
522 |*
523 |*
524 \******************************************************************************/
525 
526 sal_Bool IMapCircleObject::IsEqual( const IMapCircleObject& rEqObj )
527 {
528     return ( IMapObject::IsEqual( rEqObj ) &&
529              ( aCenter == rEqObj.aCenter ) &&
530              ( nRadius == rEqObj.nRadius ) );
531 }
532 
533 
534 /******************************************************************************/
535 /******************************************************************************/
536 /******************************************************************************/
537 IMapPolygonObject::IMapPolygonObject( const Polygon& rPoly,
538                                       const String& rURL,
539                                       const String& rAltText,
540                                       const String& rDesc,
541                                       const String& rTarget,
542                                       const String& rName,
543                                       sal_Bool bURLActive,
544                                       sal_Bool bPixelCoords ) :
545             IMapObject  ( rURL, rAltText, rDesc, rTarget, rName, bURLActive ),
546             bEllipse    ( sal_False )
547 {
548     ImpConstruct( rPoly, bPixelCoords );
549 }
550 
551 
552 /******************************************************************************
553 |*
554 |*
555 |*
556 \******************************************************************************/
557 
558 void IMapPolygonObject::ImpConstruct( const Polygon& rPoly, sal_Bool bPixel )
559 {
560     if ( bPixel )
561         aPoly = Application::GetDefaultDevice()->PixelToLogic( rPoly, MapMode( MAP_100TH_MM ) );
562     else
563         aPoly = rPoly;
564 }
565 
566 
567 /******************************************************************************
568 |*
569 |* Binaer-Export
570 |*
571 \******************************************************************************/
572 
573 void IMapPolygonObject::WriteIMapObject( SvStream& rOStm ) const
574 {
575     rOStm << aPoly;
576     rOStm << bEllipse;  // >= Version 2
577     rOStm << aEllipse;  // >= Version 2
578 }
579 
580 
581 /******************************************************************************
582 |*
583 |* Binaer-Import
584 |*
585 \******************************************************************************/
586 
587 void IMapPolygonObject::ReadIMapObject( SvStream& rIStm )
588 {
589     rIStm >> aPoly;
590 
591     // Version >= 2 hat zusaetzlich Ellipsen-Information
592     if ( nReadVersion >= 2 )
593     {
594         rIStm >> bEllipse;
595         rIStm >> aEllipse;
596     }
597 }
598 
599 
600 /******************************************************************************
601 |*
602 |* Typ-Rueckgabe
603 |*
604 \******************************************************************************/
605 
606 sal_uInt16 IMapPolygonObject::GetType() const
607 {
608     return IMAP_OBJ_POLYGON;
609 }
610 
611 
612 /******************************************************************************
613 |*
614 |* Hit-Test
615 |*
616 \******************************************************************************/
617 
618 sal_Bool IMapPolygonObject::IsHit( const Point& rPoint ) const
619 {
620     return aPoly.IsInside( rPoint );
621 }
622 
623 
624 /******************************************************************************
625 |*
626 |*
627 |*
628 \******************************************************************************/
629 
630 Polygon IMapPolygonObject::GetPolygon( sal_Bool bPixelCoords ) const
631 {
632     Polygon aNewPoly;
633 
634     if ( bPixelCoords )
635         aNewPoly = Application::GetDefaultDevice()->LogicToPixel( aPoly, MapMode( MAP_100TH_MM ) );
636     else
637         aNewPoly = aPoly;
638 
639     return aNewPoly;
640 }
641 
642 
643 /******************************************************************************
644 |*
645 |*
646 |*
647 \******************************************************************************/
648 
649 void IMapPolygonObject::SetExtraEllipse( const Rectangle& rEllipse )
650 {
651     if ( aPoly.GetSize() )
652     {
653         bEllipse = sal_True;
654         aEllipse = rEllipse;
655     }
656 }
657 
658 
659 /******************************************************************************
660 |*
661 |*
662 |*
663 \******************************************************************************/
664 
665 void IMapPolygonObject::Scale( const Fraction& rFracX, const Fraction& rFracY )
666 {
667     sal_uInt16 nCount = aPoly.GetSize();
668 
669     for ( sal_uInt16 i = 0; i < nCount; i++ )
670     {
671         Point aScaledPt( aPoly[ i ] );
672 
673         if ( rFracX.GetDenominator() && rFracY.GetDenominator() )
674         {
675             SCALEPOINT( aScaledPt, rFracX, rFracY );
676         }
677 
678         aPoly[ i ] = aScaledPt;
679     }
680 
681     if ( bEllipse )
682     {
683         Point   aTL( aEllipse.TopLeft() );
684         Point   aBR( aEllipse.BottomRight() );
685 
686         if ( rFracX.GetDenominator() && rFracY.GetDenominator() )
687         {
688             SCALEPOINT( aTL, rFracX, rFracY );
689             SCALEPOINT( aBR, rFracX, rFracY );
690         }
691 
692         aEllipse = Rectangle( aTL, aBR );
693     }
694 }
695 
696 
697 /******************************************************************************
698 |*
699 |*
700 |*
701 \******************************************************************************/
702 
703 sal_Bool IMapPolygonObject::IsEqual( const IMapPolygonObject& rEqObj )
704 {
705     sal_Bool bRet = sal_False;
706 
707     if ( IMapObject::IsEqual( rEqObj ) )
708     {
709         const Polygon&  rEqPoly = rEqObj.aPoly;
710         const sal_uInt16    nCount = aPoly.GetSize();
711         const sal_uInt16    nEqCount = rEqPoly.GetSize();
712         sal_Bool            bDifferent = sal_False;
713 
714         if ( nCount == nEqCount )
715         {
716             for ( sal_uInt16 i = 0; i < nCount; i++ )
717             {
718                 if ( aPoly[ i ] != rEqPoly[ i ] )
719                 {
720                     bDifferent = sal_True;
721                     break;
722                 }
723             }
724 
725             if ( !bDifferent )
726                 bRet = sal_True;
727         }
728     }
729 
730     return bRet;
731 }
732 
733 
734 /******************************************************************************/
735 /******************************************************************************/
736 /******************************************************************************/
737 
738 
739 /******************************************************************************
740 |*
741 |* Ctor
742 |*
743 \******************************************************************************/
744 
745 ImageMap::ImageMap( const String& rName ) :
746             aName   ( rName )
747 {
748 }
749 
750 
751 /******************************************************************************
752 |*
753 |* Copy-Ctor
754 |*
755 \******************************************************************************/
756 
757 ImageMap::ImageMap( const ImageMap& rImageMap )
758 {
759     DBG_CTOR( ImageMap, NULL );
760 
761     sal_uInt16 nCount = rImageMap.GetIMapObjectCount();
762 
763     for ( sal_uInt16 i = 0; i < nCount; i++ )
764     {
765         IMapObject* pCopyObj = rImageMap.GetIMapObject( i );
766 
767         switch( pCopyObj->GetType() )
768         {
769             case( IMAP_OBJ_RECTANGLE ):
770                 maList.Insert( new IMapRectangleObject( *(IMapRectangleObject*) pCopyObj ), LIST_APPEND );
771             break;
772 
773             case( IMAP_OBJ_CIRCLE ):
774                 maList.Insert( new IMapCircleObject( *(IMapCircleObject*) pCopyObj ), LIST_APPEND );
775             break;
776 
777             case( IMAP_OBJ_POLYGON ):
778                 maList.Insert( new IMapPolygonObject( *(IMapPolygonObject*) pCopyObj ), LIST_APPEND );
779             break;
780 
781             default:
782             break;
783         }
784     }
785 
786     aName = rImageMap.aName;
787 }
788 
789 
790 /******************************************************************************
791 |*
792 |* Dtor
793 |*
794 \******************************************************************************/
795 
796 ImageMap::~ImageMap()
797 {
798     DBG_DTOR( ImageMap, NULL );
799 
800     ClearImageMap();
801 }
802 
803 
804 /******************************************************************************
805 |*
806 |* Freigabe des internen Speichers
807 |*
808 \******************************************************************************/
809 
810 void ImageMap::ClearImageMap()
811 {
812     IMapObject* pObj = (IMapObject*) maList.First();
813 
814     while ( pObj )
815     {
816         delete pObj;
817         pObj = (IMapObject*) maList.Next();
818     }
819 
820     maList.Clear();
821 
822     aName = String();
823 }
824 
825 
826 /******************************************************************************
827 |*
828 |* Zuweisungsoperator
829 |*
830 \******************************************************************************/
831 
832 ImageMap& ImageMap::operator=( const ImageMap& rImageMap )
833 {
834     sal_uInt16 nCount = rImageMap.GetIMapObjectCount();
835 
836     ClearImageMap();
837 
838     for ( sal_uInt16 i = 0; i < nCount; i++ )
839     {
840         IMapObject* pCopyObj = rImageMap.GetIMapObject( i );
841 
842         switch( pCopyObj->GetType() )
843         {
844             case( IMAP_OBJ_RECTANGLE ):
845                 maList.Insert( new IMapRectangleObject( *(IMapRectangleObject*) pCopyObj ), LIST_APPEND );
846             break;
847 
848             case( IMAP_OBJ_CIRCLE ):
849                 maList.Insert( new IMapCircleObject( *(IMapCircleObject*) pCopyObj ), LIST_APPEND );
850             break;
851 
852             case( IMAP_OBJ_POLYGON ):
853                 maList.Insert( new IMapPolygonObject( *(IMapPolygonObject*) pCopyObj ), LIST_APPEND );
854             break;
855 
856             default:
857             break;
858         }
859     }
860 
861     aName = rImageMap.aName;
862 
863     return *this;
864 }
865 
866 
867 /******************************************************************************
868 |*
869 |* Vergleichsoperator I
870 |*
871 \******************************************************************************/
872 
873 sal_Bool ImageMap::operator==( const ImageMap& rImageMap )
874 {
875     const sal_uInt16    nCount = (sal_uInt16) maList.Count();
876     const sal_uInt16    nEqCount = rImageMap.GetIMapObjectCount();
877     sal_Bool            bRet = sal_False;
878 
879     if ( nCount == nEqCount )
880     {
881         sal_Bool bDifferent = ( aName != rImageMap.aName );
882 
883         for ( sal_uInt16 i = 0; ( i < nCount ) && !bDifferent; i++ )
884         {
885             IMapObject* pObj = (IMapObject*) maList.GetObject( i );
886             IMapObject* pEqObj = rImageMap.GetIMapObject( i );
887 
888             if ( pObj->GetType() == pEqObj->GetType() )
889             {
890                 switch( pObj->GetType() )
891                 {
892                     case( IMAP_OBJ_RECTANGLE ):
893                     {
894                         if ( !( (IMapRectangleObject*) pObj )->IsEqual( *(IMapRectangleObject*) pEqObj ) )
895                             bDifferent = sal_True;
896                     }
897                     break;
898 
899                     case( IMAP_OBJ_CIRCLE ):
900                     {
901                         if ( !( (IMapCircleObject*) pObj )->IsEqual( *(IMapCircleObject*) pEqObj ) )
902                             bDifferent = sal_True;
903                     }
904                     break;
905 
906                     case( IMAP_OBJ_POLYGON ):
907                     {
908                         if ( !( (IMapPolygonObject*) pObj )->IsEqual( *(IMapPolygonObject*) pEqObj ) )
909                             bDifferent = sal_True;
910                     }
911                     break;
912 
913                     default:
914                     break;
915                 }
916             }
917             else
918                 bDifferent = sal_True;
919         }
920 
921         if ( !bDifferent )
922             bRet = sal_True;
923     }
924 
925     return bRet;
926 }
927 
928 
929 /******************************************************************************
930 |*
931 |* Vergleichsoperator II
932 |*
933 \******************************************************************************/
934 
935 sal_Bool ImageMap::operator!=( const ImageMap& rImageMap )
936 {
937     return !( *this == rImageMap );
938 }
939 
940 
941 /******************************************************************************
942 |*
943 |* Freigabe des internen Speichers
944 |*
945 \******************************************************************************/
946 
947 sal_uInt16 ImageMap::GetVersion() const
948 {
949     return IMAGE_MAP_VERSION;
950 }
951 
952 
953 /******************************************************************************
954 |*
955 |* Einfuegen eines neuen Objekts
956 |*
957 \******************************************************************************/
958 
959 void ImageMap::InsertIMapObject( const IMapObject& rIMapObject )
960 {
961     switch( rIMapObject.GetType() )
962     {
963         case( IMAP_OBJ_RECTANGLE ):
964             maList.Insert( new IMapRectangleObject( (IMapRectangleObject&) rIMapObject ), LIST_APPEND );
965         break;
966 
967         case( IMAP_OBJ_CIRCLE ):
968             maList.Insert( new IMapCircleObject( (IMapCircleObject&) rIMapObject ), LIST_APPEND );
969         break;
970 
971         case( IMAP_OBJ_POLYGON ):
972             maList.Insert( new IMapPolygonObject( (IMapPolygonObject&) rIMapObject ), LIST_APPEND );
973         break;
974 
975         default:
976         break;
977     }
978 }
979 
980 
981 /******************************************************************************
982 |*
983 |* Hit-Test
984 |*
985 \******************************************************************************/
986 
987 IMapObject* ImageMap::GetHitIMapObject( const Size& rTotalSize,
988                                         const Size& rDisplaySize,
989                                         const Point& rRelHitPoint,
990                                         sal_uLong nFlags )
991 {
992     Point aRelPoint( rTotalSize.Width() * rRelHitPoint.X() / rDisplaySize.Width(),
993                      rTotalSize.Height() * rRelHitPoint.Y() / rDisplaySize.Height() );
994 
995     // Falls Flags zur Spiegelung etc. angegeben sind, wird
996     // der zu pruefende Punkt vor der Pruefung entspr. transformiert
997     if ( nFlags )
998     {
999         if ( nFlags & IMAP_MIRROR_HORZ )
1000             aRelPoint.X() = rTotalSize.Width() - aRelPoint.X();
1001 
1002         if ( nFlags & IMAP_MIRROR_VERT )
1003             aRelPoint.Y() = rTotalSize.Height() - aRelPoint.Y();
1004     }
1005 
1006     // Alle Objekte durchlaufen und HitTest ausfuehren
1007     IMapObject* pObj = (IMapObject*) maList.First();
1008     while ( pObj )
1009     {
1010         if ( pObj->IsHit( aRelPoint ) )
1011             break;
1012 
1013         pObj = (IMapObject*) maList.Next();
1014     }
1015 
1016     return( pObj ? ( pObj->IsActive() ? pObj : NULL ) : NULL );
1017 }
1018 
1019 
1020 /******************************************************************************
1021 |*
1022 |*
1023 |*
1024 \******************************************************************************/
1025 
1026 Rectangle ImageMap::GetBoundRect() const
1027 {
1028     Rectangle   aBoundRect;
1029     sal_uLong       nCount = maList.Count();
1030 
1031     for ( sal_uLong i = 0; i < nCount; i++ )
1032         aBoundRect.Union( ( (IMapObject*) maList.GetObject( i ) )->GetBoundRect() );
1033 
1034     return aBoundRect;
1035 }
1036 
1037 
1038 /******************************************************************************
1039 |*
1040 |*
1041 |*
1042 \******************************************************************************/
1043 
1044 void ImageMap::Scale( const Fraction& rFracX, const Fraction& rFracY )
1045 {
1046     sal_uInt16 nCount = (sal_uInt16) maList.Count();
1047 
1048     for ( sal_uInt16 i = 0; i < nCount; i++ )
1049     {
1050         IMapObject* pObj = GetIMapObject( i );
1051 
1052         switch( pObj->GetType() )
1053         {
1054             case( IMAP_OBJ_RECTANGLE ):
1055                 ( (IMapRectangleObject*) pObj )->Scale( rFracX, rFracY );
1056             break;
1057 
1058             case( IMAP_OBJ_CIRCLE ):
1059                 ( (IMapCircleObject*) pObj )->Scale( rFracX, rFracY );
1060             break;
1061 
1062             case( IMAP_OBJ_POLYGON ):
1063                 ( (IMapPolygonObject*) pObj )->Scale( rFracX, rFracY );
1064             break;
1065 
1066             default:
1067             break;
1068         }
1069     }
1070 }
1071 
1072 
1073 /******************************************************************************
1074 |*
1075 |* Objekte nacheinander wegschreiben
1076 |*
1077 \******************************************************************************/
1078 
1079 void ImageMap::ImpWriteImageMap( SvStream& rOStm, const String& rBaseURL ) const
1080 {
1081     IMapObject* pObj;
1082     sal_uInt16      nCount = (sal_uInt16) maList.Count();
1083 
1084     for ( sal_uInt16 i = 0; i < nCount; i++ )
1085     {
1086         pObj = (IMapObject*) maList.GetObject( i );
1087         pObj->Write( rOStm, rBaseURL );
1088     }
1089 }
1090 
1091 
1092 /******************************************************************************
1093 |*
1094 |* Objekte nacheinander lesen
1095 |*
1096 \******************************************************************************/
1097 
1098 void ImageMap::ImpReadImageMap( SvStream& rIStm, sal_uInt16 nCount, const String& rBaseURL )
1099 {
1100     // neue Objekte einlesen
1101     for ( sal_uInt16 i = 0; i < nCount; i++ )
1102     {
1103         sal_uInt16 nType;
1104 
1105         rIStm >> nType;
1106         rIStm.SeekRel( -2 );
1107 
1108         switch( nType )
1109         {
1110             case ( IMAP_OBJ_RECTANGLE ):
1111             {
1112                 IMapRectangleObject* pObj = new IMapRectangleObject;
1113                 pObj->Read( rIStm, rBaseURL );
1114                 maList.Insert( pObj, LIST_APPEND );
1115             }
1116             break;
1117 
1118             case ( IMAP_OBJ_CIRCLE ):
1119             {
1120                 IMapCircleObject* pObj = new IMapCircleObject;
1121                 pObj->Read( rIStm, rBaseURL );
1122                 maList.Insert( pObj, LIST_APPEND );
1123             }
1124             break;
1125 
1126             case ( IMAP_OBJ_POLYGON ):
1127             {
1128                 IMapPolygonObject* pObj = new IMapPolygonObject;
1129                 pObj->Read( rIStm, rBaseURL );
1130                 maList.Insert( pObj, LIST_APPEND );
1131             }
1132             break;
1133 
1134             default:
1135             break;
1136         }
1137     }
1138 }
1139 
1140 
1141 /******************************************************************************
1142 |*
1143 |* Binaer speichern
1144 |*
1145 \******************************************************************************/
1146 
1147 void ImageMap::Write( SvStream& rOStm, const String& rBaseURL ) const
1148 {
1149     IMapCompat*             pCompat;
1150     String                  aImageName( GetName() );
1151     String                  aDummy;
1152     sal_uInt16                  nOldFormat = rOStm.GetNumberFormatInt();
1153     sal_uInt16                  nCount = (sal_uInt16) GetIMapObjectCount();
1154     const rtl_TextEncoding  eEncoding = gsl_getSystemTextEncoding();
1155 
1156     rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1157 
1158     // MagicCode schreiben
1159     rOStm << IMAPMAGIC;
1160     rOStm << GetVersion();
1161     rOStm.WriteByteString( ByteString( aImageName, eEncoding ) );
1162     rOStm.WriteByteString( ByteString( aDummy, eEncoding ) );
1163     rOStm << nCount;
1164     rOStm.WriteByteString( ByteString( aImageName, eEncoding ) );
1165 
1166     pCompat = new IMapCompat( rOStm, STREAM_WRITE );
1167 
1168     // hier kann in neueren Versionen eingefuegt werden
1169 
1170     delete pCompat;
1171 
1172     ImpWriteImageMap( rOStm, rBaseURL );
1173 
1174     rOStm.SetNumberFormatInt( nOldFormat );
1175 }
1176 
1177 
1178 /******************************************************************************
1179 |*
1180 |* Binaer laden
1181 |*
1182 \******************************************************************************/
1183 
1184 void ImageMap::Read( SvStream& rIStm, const String& rBaseURL )
1185 {
1186     ByteString  aString;
1187     char        cMagic[6];
1188     sal_uInt16      nOldFormat = rIStm.GetNumberFormatInt();
1189     sal_uInt16      nCount;
1190 
1191     rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
1192     rIStm.Read( cMagic, sizeof( cMagic ) );
1193 
1194     if ( !memcmp( cMagic, IMAPMAGIC, sizeof( cMagic ) ) )
1195     {
1196         IMapCompat* pCompat;
1197 
1198         // alten Inhalt loeschen
1199         ClearImageMap();
1200 
1201         // Version ueberlesen wir
1202         rIStm.SeekRel( 2 );
1203 
1204         rIStm.ReadByteString( aString ); aName = String( aString, gsl_getSystemTextEncoding() );
1205         rIStm.ReadByteString( aString ); // Dummy
1206         rIStm >> nCount;
1207         rIStm.ReadByteString( aString ); // Dummy
1208 
1209         pCompat = new IMapCompat( rIStm, STREAM_READ );
1210 
1211         // hier kann in neueren Versionen gelesen werden
1212 
1213         delete pCompat;
1214         ImpReadImageMap( rIStm, nCount, rBaseURL );
1215 
1216     }
1217     else
1218         rIStm.SetError( SVSTREAM_GENERALERROR );
1219 
1220     rIStm.SetNumberFormatInt( nOldFormat );
1221 }
1222 
1223