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