xref: /aoo41x/main/svtools/source/misc/imap.cxx (revision cdf0e10c)
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