Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <tools/urlobj.hxx>
22 : #include <vcl/svapp.hxx>
23 : #include <vcl/mapmod.hxx>
24 : #include <vcl/window.hxx>
25 : #include <o3tl/numeric.hxx>
26 : #include <svl/urihelper.hxx>
27 : #include <svtools/imap.hxx>
28 : #include <svtools/imapobj.hxx>
29 : #include <svtools/imapcirc.hxx>
30 : #include <svtools/imaprect.hxx>
31 : #include <svtools/imappoly.hxx>
32 :
33 : #include <string.h>
34 : #include <math.h>
35 : #include <boost/scoped_ptr.hpp>
36 :
37 :
38 : #define SCALEPOINT(aPT,aFracX,aFracY) (aPT).X()=((aPT).X()*(aFracX).GetNumerator())/(aFracX).GetDenominator(); \
39 : (aPT).Y()=((aPT).Y()*(aFracY).GetNumerator())/(aFracY).GetDenominator();
40 :
41 :
42 : /******************************************************************************/
43 :
44 : sal_uInt16 IMapObject::nActualTextEncoding = (sal_uInt16) RTL_TEXTENCODING_DONTKNOW;
45 :
46 : /******************************************************************************/
47 :
48 :
49 0 : IMapObject::IMapObject()
50 : : bActive( false )
51 0 : , nReadVersion( 0 )
52 : {
53 0 : }
54 :
55 4 : IMapObject::IMapObject( const OUString& rURL, const OUString& rAltText, const OUString& rDesc,
56 : const OUString& rTarget, const OUString& rName, bool bURLActive )
57 : : aURL( rURL )
58 : , aAltText( rAltText )
59 : , aDesc( rDesc )
60 : , aTarget( rTarget )
61 : , aName( rName )
62 : , bActive( bURLActive )
63 4 : , nReadVersion( 0 )
64 : {
65 4 : }
66 :
67 :
68 : /******************************************************************************
69 : |*
70 : |* release internal memory
71 : |*
72 : \******************************************************************************/
73 :
74 0 : sal_uInt16 IMapObject::GetVersion() const
75 : {
76 0 : return IMAP_OBJ_VERSION;
77 : }
78 :
79 0 : void IMapObject::Write( SvStream& rOStm, const OUString& rBaseURL ) const
80 : {
81 0 : const rtl_TextEncoding eEncoding = osl_getThreadTextEncoding();
82 :
83 0 : rOStm.WriteUInt16( GetType() );
84 0 : rOStm.WriteUInt16( GetVersion() );
85 0 : rOStm.WriteUInt16( eEncoding );
86 :
87 : const OString aRelURL = OUStringToOString(
88 0 : URIHelper::simpleNormalizedMakeRelative(rBaseURL, aURL), eEncoding);
89 0 : write_uInt16_lenPrefixed_uInt8s_FromOString(rOStm, aRelURL);
90 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, aAltText, eEncoding);
91 0 : rOStm.WriteUChar( bActive );
92 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, aTarget, eEncoding);
93 :
94 0 : boost::scoped_ptr<IMapCompat> pCompat(new IMapCompat( rOStm, STREAM_WRITE ));
95 :
96 0 : WriteIMapObject( rOStm );
97 0 : aEventList.Write( rOStm ); // V4
98 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, aName, eEncoding); // V5
99 0 : }
100 :
101 :
102 : /******************************************************************************
103 : |*
104 : |* Binary import
105 : |*
106 : \******************************************************************************/
107 :
108 0 : void IMapObject::Read( SvStream& rIStm, const OUString& rBaseURL )
109 : {
110 : rtl_TextEncoding nTextEncoding;
111 :
112 : // read on type and version
113 0 : rIStm.SeekRel( 2 );
114 0 : rIStm.ReadUInt16( nReadVersion );
115 0 : rIStm.ReadUInt16( nTextEncoding );
116 0 : aURL = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStm, nTextEncoding);
117 0 : aAltText = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStm, nTextEncoding);
118 0 : rIStm.ReadCharAsBool( bActive );
119 0 : aTarget = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStm, nTextEncoding);
120 :
121 : // make URL absolute
122 0 : aURL = URIHelper::SmartRel2Abs( INetURLObject(rBaseURL), aURL, URIHelper::GetMaybeFileHdl(), true, false, INetURLObject::WAS_ENCODED, INetURLObject::DECODE_UNAMBIGUOUS );
123 0 : boost::scoped_ptr<IMapCompat> pCompat(new IMapCompat( rIStm, STREAM_READ ));
124 :
125 0 : ReadIMapObject( rIStm );
126 :
127 : // from version 4 onwards we read a eventlist
128 0 : if ( nReadVersion >= 0x0004 )
129 : {
130 0 : aEventList.Read(rIStm);
131 :
132 : // from version 5 onwards an objectname could be available
133 0 : if ( nReadVersion >= 0x0005 )
134 0 : aName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStm, nTextEncoding);
135 0 : }
136 0 : }
137 :
138 4 : bool IMapObject::IsEqual( const IMapObject& rEqObj )
139 : {
140 8 : return ( ( aURL == rEqObj.aURL ) &&
141 8 : ( aAltText == rEqObj.aAltText ) &&
142 8 : ( aDesc == rEqObj.aDesc ) &&
143 8 : ( aTarget == rEqObj.aTarget ) &&
144 12 : ( aName == rEqObj.aName ) &&
145 8 : ( bActive == rEqObj.bActive ) );
146 : }
147 :
148 2 : IMapRectangleObject::IMapRectangleObject( const Rectangle& rRect,
149 : const OUString& rURL,
150 : const OUString& rAltText,
151 : const OUString& rDesc,
152 : const OUString& rTarget,
153 : const OUString& rName,
154 : bool bURLActive,
155 : bool bPixelCoords ) :
156 2 : IMapObject ( rURL, rAltText, rDesc, rTarget, rName, bURLActive )
157 : {
158 2 : ImpConstruct( rRect, bPixelCoords );
159 2 : }
160 :
161 2 : void IMapRectangleObject::ImpConstruct( const Rectangle& rRect, bool bPixel )
162 : {
163 2 : if ( bPixel )
164 0 : aRect = Application::GetDefaultDevice()->PixelToLogic( rRect, MapMode( MAP_100TH_MM ) );
165 : else
166 2 : aRect = rRect;
167 2 : }
168 :
169 :
170 : /******************************************************************************
171 : |*
172 : |* Binary export
173 : |*
174 : \******************************************************************************/
175 :
176 0 : void IMapRectangleObject::WriteIMapObject( SvStream& rOStm ) const
177 : {
178 0 : WriteRectangle( rOStm, aRect );
179 0 : }
180 :
181 :
182 : /******************************************************************************
183 : |*
184 : |* Binary import
185 : |*
186 : \******************************************************************************/
187 :
188 0 : void IMapRectangleObject::ReadIMapObject( SvStream& rIStm )
189 : {
190 0 : ReadRectangle( rIStm, aRect );
191 0 : }
192 :
193 :
194 : /******************************************************************************
195 : |*
196 : |* return type
197 : |*
198 : \******************************************************************************/
199 :
200 18 : sal_uInt16 IMapRectangleObject::GetType() const
201 : {
202 18 : return IMAP_OBJ_RECTANGLE;
203 : }
204 :
205 :
206 : /******************************************************************************
207 : |*
208 : |* Hit test
209 : |*
210 : \******************************************************************************/
211 :
212 0 : bool IMapRectangleObject::IsHit( const Point& rPoint ) const
213 : {
214 0 : return aRect.IsInside( rPoint );
215 : }
216 :
217 2 : Rectangle IMapRectangleObject::GetRectangle( bool bPixelCoords ) const
218 : {
219 2 : Rectangle aNewRect;
220 :
221 2 : if ( bPixelCoords )
222 0 : aNewRect = Application::GetDefaultDevice()->LogicToPixel( aRect, MapMode( MAP_100TH_MM ) );
223 : else
224 2 : aNewRect = aRect;
225 :
226 2 : return aNewRect;
227 : }
228 :
229 2 : void IMapRectangleObject::Scale( const Fraction& rFracX, const Fraction& rFracY )
230 : {
231 2 : Point aTL( aRect.TopLeft() );
232 2 : Point aBR( aRect.BottomRight() );
233 :
234 2 : if ( rFracX.GetDenominator() && rFracY.GetDenominator() )
235 : {
236 2 : SCALEPOINT( aTL, rFracX, rFracY );
237 2 : SCALEPOINT( aBR, rFracX, rFracY );
238 : }
239 :
240 2 : aRect = Rectangle( aTL, aBR );
241 2 : }
242 :
243 2 : bool IMapRectangleObject::IsEqual( const IMapRectangleObject& rEqObj )
244 : {
245 2 : return ( IMapObject::IsEqual( rEqObj ) && ( aRect == rEqObj.aRect ) );
246 : }
247 :
248 0 : IMapCircleObject::IMapCircleObject( const Point& rCenter, sal_uLong nCircleRadius,
249 : const OUString& rURL,
250 : const OUString& rAltText,
251 : const OUString& rDesc,
252 : const OUString& rTarget,
253 : const OUString& rName,
254 : bool bURLActive,
255 : bool bPixelCoords ) :
256 0 : IMapObject ( rURL, rAltText, rDesc, rTarget, rName, bURLActive )
257 : {
258 0 : ImpConstruct( rCenter, nCircleRadius, bPixelCoords );
259 0 : }
260 :
261 0 : void IMapCircleObject::ImpConstruct( const Point& rCenter, sal_uLong nRad, bool bPixel )
262 : {
263 0 : if ( bPixel )
264 : {
265 0 : MapMode aMap100( MAP_100TH_MM );
266 :
267 0 : aCenter = Application::GetDefaultDevice()->PixelToLogic( rCenter, aMap100 );
268 0 : nRadius = Application::GetDefaultDevice()->PixelToLogic( Size( nRad, 0 ), aMap100 ).Width();
269 : }
270 : else
271 : {
272 0 : aCenter = rCenter;
273 0 : nRadius = nRad;
274 : }
275 0 : }
276 :
277 :
278 : /******************************************************************************
279 : |*
280 : |* Binary export
281 : |*
282 : \******************************************************************************/
283 :
284 0 : void IMapCircleObject::WriteIMapObject( SvStream& rOStm ) const
285 : {
286 0 : sal_uInt32 nTmp = nRadius;
287 :
288 0 : WritePair( rOStm, aCenter );
289 0 : rOStm.WriteUInt32( nTmp );
290 0 : }
291 :
292 :
293 : /******************************************************************************
294 : |*
295 : |* Binary import
296 : |*
297 : \******************************************************************************/
298 :
299 0 : void IMapCircleObject::ReadIMapObject( SvStream& rIStm )
300 : {
301 : sal_uInt32 nTmp;
302 :
303 0 : ReadPair( rIStm, aCenter );
304 0 : rIStm.ReadUInt32( nTmp );
305 :
306 0 : nRadius = nTmp;
307 0 : }
308 :
309 :
310 : /******************************************************************************
311 : |*
312 : |* return type
313 : |*
314 : \******************************************************************************/
315 :
316 0 : sal_uInt16 IMapCircleObject::GetType() const
317 : {
318 0 : return IMAP_OBJ_CIRCLE;
319 : }
320 :
321 :
322 : /******************************************************************************
323 : |*
324 : |* Hit-Test
325 : |*
326 : \******************************************************************************/
327 :
328 0 : bool IMapCircleObject::IsHit( const Point& rPoint ) const
329 : {
330 0 : const Point aPoint( aCenter - rPoint );
331 0 : bool bRet = false;
332 :
333 0 : if ( (sal_Int32) sqrt( (double) aPoint.X() * aPoint.X() +
334 0 : aPoint.Y() * aPoint.Y() ) <= nRadius )
335 : {
336 0 : bRet = true;
337 : }
338 :
339 0 : return bRet;
340 : }
341 :
342 0 : Point IMapCircleObject::GetCenter( bool bPixelCoords ) const
343 : {
344 0 : Point aNewPoint;
345 :
346 0 : if ( bPixelCoords )
347 0 : aNewPoint = Application::GetDefaultDevice()->LogicToPixel( aCenter, MapMode( MAP_100TH_MM ) );
348 : else
349 0 : aNewPoint = aCenter;
350 :
351 0 : return aNewPoint;
352 : }
353 :
354 0 : sal_uLong IMapCircleObject::GetRadius( bool bPixelCoords ) const
355 : {
356 : sal_uLong nNewRadius;
357 :
358 0 : if ( bPixelCoords )
359 0 : nNewRadius = Application::GetDefaultDevice()->LogicToPixel( Size( nRadius, 0 ), MapMode( MAP_100TH_MM ) ).Width();
360 : else
361 0 : nNewRadius = nRadius;
362 :
363 0 : return nNewRadius;
364 : }
365 :
366 0 : Rectangle IMapCircleObject::GetBoundRect() const
367 : {
368 0 : long nWidth = nRadius << 1;
369 :
370 0 : return Rectangle( Point( aCenter.X() - nRadius, aCenter.Y() - nRadius ),
371 0 : Size( nWidth, nWidth ) );
372 : }
373 :
374 0 : void IMapCircleObject::Scale( const Fraction& rFracX, const Fraction& rFracY )
375 : {
376 0 : Fraction aAverage( rFracX );
377 :
378 0 : aAverage += rFracY;
379 0 : aAverage *= Fraction( 1, 2 );
380 :
381 0 : if ( rFracX.GetDenominator() && rFracY.GetDenominator() )
382 : {
383 0 : SCALEPOINT( aCenter, rFracX, rFracY );
384 : }
385 :
386 0 : if (!aAverage.GetDenominator())
387 0 : throw o3tl::divide_by_zero();
388 :
389 0 : nRadius = ( nRadius * aAverage.GetNumerator() ) / aAverage.GetDenominator();
390 0 : }
391 :
392 0 : bool IMapCircleObject::IsEqual( const IMapCircleObject& rEqObj )
393 : {
394 0 : return ( IMapObject::IsEqual( rEqObj ) &&
395 0 : ( aCenter == rEqObj.aCenter ) &&
396 0 : ( nRadius == rEqObj.nRadius ) );
397 : }
398 :
399 2 : IMapPolygonObject::IMapPolygonObject( const Polygon& rPoly,
400 : const OUString& rURL,
401 : const OUString& rAltText,
402 : const OUString& rDesc,
403 : const OUString& rTarget,
404 : const OUString& rName,
405 : bool bURLActive,
406 : bool bPixelCoords ) :
407 : IMapObject ( rURL, rAltText, rDesc, rTarget, rName, bURLActive ),
408 2 : bEllipse ( false )
409 : {
410 2 : ImpConstruct( rPoly, bPixelCoords );
411 2 : }
412 :
413 2 : void IMapPolygonObject::ImpConstruct( const Polygon& rPoly, bool bPixel )
414 : {
415 2 : if ( bPixel )
416 0 : aPoly = Application::GetDefaultDevice()->PixelToLogic( rPoly, MapMode( MAP_100TH_MM ) );
417 : else
418 2 : aPoly = rPoly;
419 2 : }
420 :
421 :
422 : /******************************************************************************
423 : |*
424 : |* Binary export
425 : |*
426 : \******************************************************************************/
427 :
428 0 : void IMapPolygonObject::WriteIMapObject( SvStream& rOStm ) const
429 : {
430 0 : WritePolygon( rOStm, aPoly );
431 0 : rOStm.WriteUChar( bEllipse ); // >= Version 2
432 0 : WriteRectangle( rOStm, aEllipse ); // >= Version 2
433 0 : }
434 :
435 :
436 : /******************************************************************************
437 : |*
438 : |* Binary import
439 : |*
440 : \******************************************************************************/
441 :
442 0 : void IMapPolygonObject::ReadIMapObject( SvStream& rIStm )
443 : {
444 0 : ReadPolygon( rIStm, aPoly );
445 :
446 : // Version >= 2 has additional ellipses information
447 0 : if ( nReadVersion >= 2 )
448 : {
449 0 : rIStm.ReadCharAsBool( bEllipse );
450 0 : ReadRectangle( rIStm, aEllipse );
451 : }
452 0 : }
453 :
454 :
455 : /******************************************************************************
456 : |*
457 : |* return type
458 : |*
459 : \******************************************************************************/
460 :
461 30 : sal_uInt16 IMapPolygonObject::GetType() const
462 : {
463 30 : return IMAP_OBJ_POLYGON;
464 : }
465 :
466 :
467 : /******************************************************************************
468 : |*
469 : |* hit test
470 : |*
471 : \******************************************************************************/
472 :
473 0 : bool IMapPolygonObject::IsHit( const Point& rPoint ) const
474 : {
475 0 : return aPoly.IsInside( rPoint );
476 : }
477 :
478 2 : Polygon IMapPolygonObject::GetPolygon( bool bPixelCoords ) const
479 : {
480 2 : Polygon aNewPoly;
481 :
482 2 : if ( bPixelCoords )
483 2 : aNewPoly = Application::GetDefaultDevice()->LogicToPixel( aPoly, MapMode( MAP_100TH_MM ) );
484 : else
485 0 : aNewPoly = aPoly;
486 :
487 2 : return aNewPoly;
488 : }
489 :
490 0 : void IMapPolygonObject::SetExtraEllipse( const Rectangle& rEllipse )
491 : {
492 0 : if ( aPoly.GetSize() )
493 : {
494 0 : bEllipse = true;
495 0 : aEllipse = rEllipse;
496 : }
497 0 : }
498 :
499 2 : void IMapPolygonObject::Scale( const Fraction& rFracX, const Fraction& rFracY )
500 : {
501 2 : sal_uInt16 nCount = aPoly.GetSize();
502 :
503 196 : for ( sal_uInt16 i = 0; i < nCount; i++ )
504 : {
505 194 : Point aScaledPt( aPoly[ i ] );
506 :
507 194 : if ( rFracX.GetDenominator() && rFracY.GetDenominator() )
508 : {
509 194 : SCALEPOINT( aScaledPt, rFracX, rFracY );
510 : }
511 :
512 194 : aPoly[ i ] = aScaledPt;
513 : }
514 :
515 2 : if ( bEllipse )
516 : {
517 0 : Point aTL( aEllipse.TopLeft() );
518 0 : Point aBR( aEllipse.BottomRight() );
519 :
520 0 : if ( rFracX.GetDenominator() && rFracY.GetDenominator() )
521 : {
522 0 : SCALEPOINT( aTL, rFracX, rFracY );
523 0 : SCALEPOINT( aBR, rFracX, rFracY );
524 : }
525 :
526 0 : aEllipse = Rectangle( aTL, aBR );
527 : }
528 2 : }
529 :
530 2 : bool IMapPolygonObject::IsEqual( const IMapPolygonObject& rEqObj )
531 : {
532 2 : bool bRet = false;
533 :
534 2 : if ( IMapObject::IsEqual( rEqObj ) )
535 : {
536 2 : const Polygon& rEqPoly = rEqObj.aPoly;
537 2 : const sal_uInt16 nCount = aPoly.GetSize();
538 2 : const sal_uInt16 nEqCount = rEqPoly.GetSize();
539 2 : bool bDifferent = false;
540 :
541 2 : if ( nCount == nEqCount )
542 : {
543 196 : for ( sal_uInt16 i = 0; i < nCount; i++ )
544 : {
545 194 : if ( aPoly[ i ] != rEqPoly[ i ] )
546 : {
547 0 : bDifferent = true;
548 0 : break;
549 : }
550 : }
551 :
552 2 : if ( !bDifferent )
553 2 : bRet = true;
554 : }
555 : }
556 :
557 2 : return bRet;
558 : }
559 :
560 : /******************************************************************************
561 : |*
562 : |* Ctor
563 : |*
564 : \******************************************************************************/
565 :
566 0 : ImageMap::ImageMap( const OUString& rName )
567 0 : : aName( rName )
568 : {
569 0 : }
570 :
571 :
572 : /******************************************************************************
573 : |*
574 : |* Copy-Ctor
575 : |*
576 : \******************************************************************************/
577 :
578 22 : ImageMap::ImageMap( const ImageMap& rImageMap )
579 : {
580 :
581 22 : size_t nCount = rImageMap.GetIMapObjectCount();
582 :
583 44 : for ( size_t i = 0; i < nCount; i++ )
584 : {
585 22 : IMapObject* pCopyObj = rImageMap.GetIMapObject( i );
586 :
587 22 : switch( pCopyObj->GetType() )
588 : {
589 : case( IMAP_OBJ_RECTANGLE ):
590 4 : maList.push_back( new IMapRectangleObject( *static_cast<IMapRectangleObject*>( pCopyObj ) ) );
591 4 : break;
592 :
593 : case( IMAP_OBJ_CIRCLE ):
594 0 : maList.push_back( new IMapCircleObject( *static_cast<IMapCircleObject*>( pCopyObj ) ) );
595 0 : break;
596 :
597 : case( IMAP_OBJ_POLYGON ):
598 18 : maList.push_back( new IMapPolygonObject( *static_cast<IMapPolygonObject*>( pCopyObj ) ) );
599 18 : break;
600 :
601 : default:
602 0 : break;
603 : }
604 : }
605 :
606 22 : aName = rImageMap.aName;
607 22 : }
608 :
609 :
610 : /******************************************************************************
611 : |*
612 : |* Dtor
613 : |*
614 : \******************************************************************************/
615 :
616 200 : ImageMap::~ImageMap()
617 : {
618 :
619 88 : ClearImageMap();
620 112 : }
621 :
622 :
623 : /******************************************************************************
624 : |*
625 : |* release internal memory
626 : |*
627 : \******************************************************************************/
628 :
629 92 : void ImageMap::ClearImageMap()
630 : {
631 118 : for( size_t i = 0, n = maList.size(); i < n; ++i )
632 26 : delete maList[ i ];
633 92 : maList.clear();
634 :
635 92 : aName = "";
636 92 : }
637 :
638 :
639 : /******************************************************************************
640 : |*
641 : |* assignment operator
642 : |*
643 : \******************************************************************************/
644 :
645 0 : ImageMap& ImageMap::operator=( const ImageMap& rImageMap )
646 : {
647 0 : size_t nCount = rImageMap.GetIMapObjectCount();
648 :
649 0 : ClearImageMap();
650 :
651 0 : for ( size_t i = 0; i < nCount; i++ )
652 : {
653 0 : IMapObject* pCopyObj = rImageMap.GetIMapObject( i );
654 :
655 0 : switch( pCopyObj->GetType() )
656 : {
657 : case( IMAP_OBJ_RECTANGLE ):
658 0 : maList.push_back( new IMapRectangleObject( *static_cast<IMapRectangleObject*>(pCopyObj) ) );
659 0 : break;
660 :
661 : case( IMAP_OBJ_CIRCLE ):
662 0 : maList.push_back( new IMapCircleObject( *static_cast<IMapCircleObject*>(pCopyObj) ) );
663 0 : break;
664 :
665 : case( IMAP_OBJ_POLYGON ):
666 0 : maList.push_back( new IMapPolygonObject( *static_cast<IMapPolygonObject*>(pCopyObj) ) );
667 0 : break;
668 :
669 : default:
670 0 : break;
671 : }
672 : }
673 :
674 0 : aName = rImageMap.aName;
675 :
676 0 : return *this;
677 : }
678 :
679 :
680 : /******************************************************************************
681 : |*
682 : |* compare operator I
683 : |*
684 : \******************************************************************************/
685 :
686 4 : bool ImageMap::operator==( const ImageMap& rImageMap )
687 : {
688 4 : const size_t nCount = maList.size();
689 4 : const size_t nEqCount = rImageMap.GetIMapObjectCount();
690 4 : bool bRet = false;
691 :
692 4 : if ( nCount == nEqCount )
693 : {
694 4 : bool bDifferent = ( aName != rImageMap.aName );
695 :
696 8 : for ( size_t i = 0; ( i < nCount ) && !bDifferent; i++ )
697 : {
698 4 : IMapObject* pObj = maList[ i ];
699 4 : IMapObject* pEqObj = rImageMap.GetIMapObject( i );
700 :
701 4 : if ( pObj->GetType() == pEqObj->GetType() )
702 : {
703 4 : switch( pObj->GetType() )
704 : {
705 : case( IMAP_OBJ_RECTANGLE ):
706 : {
707 2 : if ( !( static_cast<IMapRectangleObject*>(pObj) )->IsEqual( *static_cast<IMapRectangleObject*>(pEqObj) ) )
708 0 : bDifferent = true;
709 : }
710 2 : break;
711 :
712 : case( IMAP_OBJ_CIRCLE ):
713 : {
714 0 : if ( !( static_cast<IMapCircleObject*>(pObj) )->IsEqual( *static_cast<IMapCircleObject*>(pEqObj) ) )
715 0 : bDifferent = true;
716 : }
717 0 : break;
718 :
719 : case( IMAP_OBJ_POLYGON ):
720 : {
721 2 : if ( !( static_cast<IMapPolygonObject*>(pObj) )->IsEqual( *static_cast<IMapPolygonObject*>(pEqObj) ) )
722 0 : bDifferent = true;
723 : }
724 2 : break;
725 :
726 : default:
727 0 : break;
728 : }
729 : }
730 : else
731 0 : bDifferent = true;
732 : }
733 :
734 4 : if ( !bDifferent )
735 4 : bRet = true;
736 : }
737 :
738 4 : return bRet;
739 : }
740 :
741 :
742 : /******************************************************************************
743 : |*
744 : |* compare operator II
745 : |*
746 : \******************************************************************************/
747 :
748 0 : bool ImageMap::operator!=( const ImageMap& rImageMap )
749 : {
750 0 : return !( *this == rImageMap );
751 : }
752 :
753 :
754 : /******************************************************************************
755 : |*
756 : |* release internal memory
757 : |*
758 : \******************************************************************************/
759 :
760 0 : sal_uInt16 ImageMap::GetVersion() const
761 : {
762 0 : return IMAGE_MAP_VERSION;
763 : }
764 :
765 :
766 : /******************************************************************************
767 : |*
768 : |* insert new object
769 : |*
770 : \******************************************************************************/
771 :
772 4 : void ImageMap::InsertIMapObject( const IMapObject& rIMapObject )
773 : {
774 4 : switch( rIMapObject.GetType() )
775 : {
776 : case( IMAP_OBJ_RECTANGLE ):
777 2 : maList.push_back( new IMapRectangleObject( static_cast<const IMapRectangleObject&>( rIMapObject ) ) );
778 2 : break;
779 :
780 : case( IMAP_OBJ_CIRCLE ):
781 0 : maList.push_back( new IMapCircleObject( static_cast<const IMapCircleObject&>( rIMapObject ) ) );
782 0 : break;
783 :
784 : case( IMAP_OBJ_POLYGON ):
785 2 : maList.push_back( new IMapPolygonObject( static_cast<const IMapPolygonObject&>( rIMapObject ) ) );
786 2 : break;
787 :
788 : default:
789 0 : break;
790 : }
791 4 : }
792 :
793 :
794 : /******************************************************************************
795 : |*
796 : |* hit test
797 : |*
798 : \******************************************************************************/
799 :
800 0 : IMapObject* ImageMap::GetHitIMapObject( const Size& rTotalSize,
801 : const Size& rDisplaySize,
802 : const Point& rRelHitPoint,
803 : sal_uLong nFlags )
804 : {
805 0 : Point aRelPoint( rTotalSize.Width() * rRelHitPoint.X() / rDisplaySize.Width(),
806 0 : rTotalSize.Height() * rRelHitPoint.Y() / rDisplaySize.Height() );
807 :
808 : // transform point to check before checking if flags to mirror etc. are set,
809 0 : if ( nFlags )
810 : {
811 0 : if ( nFlags & IMAP_MIRROR_HORZ )
812 0 : aRelPoint.X() = rTotalSize.Width() - aRelPoint.X();
813 :
814 0 : if ( nFlags & IMAP_MIRROR_VERT )
815 0 : aRelPoint.Y() = rTotalSize.Height() - aRelPoint.Y();
816 : }
817 :
818 : // walk over all objects and execute HitTest
819 0 : IMapObject* pObj = NULL;
820 0 : for( size_t i = 0, n = maList.size(); i < n; ++i ) {
821 0 : if ( maList[ i ]->IsHit( aRelPoint ) ) {
822 0 : pObj = maList[ i ];
823 0 : break;
824 : }
825 : }
826 :
827 0 : return( pObj ? ( pObj->IsActive() ? pObj : NULL ) : NULL );
828 : }
829 :
830 4 : void ImageMap::Scale( const Fraction& rFracX, const Fraction& rFracY )
831 : {
832 4 : size_t nCount = maList.size();
833 :
834 8 : for ( size_t i = 0; i < nCount; i++ )
835 : {
836 4 : IMapObject* pObj = maList[ i ];
837 :
838 4 : switch( pObj->GetType() )
839 : {
840 : case( IMAP_OBJ_RECTANGLE ):
841 2 : static_cast<IMapRectangleObject*>( pObj )->Scale( rFracX, rFracY );
842 2 : break;
843 :
844 : case( IMAP_OBJ_CIRCLE ):
845 0 : static_cast<IMapCircleObject*>( pObj )->Scale( rFracX, rFracY );
846 0 : break;
847 :
848 : case( IMAP_OBJ_POLYGON ):
849 2 : static_cast<IMapPolygonObject*>( pObj )->Scale( rFracX, rFracY );
850 2 : break;
851 :
852 : default:
853 0 : break;
854 : }
855 : }
856 4 : }
857 :
858 :
859 : /******************************************************************************
860 : |*
861 : |* sequentially write objects
862 : |*
863 : \******************************************************************************/
864 :
865 0 : void ImageMap::ImpWriteImageMap( SvStream& rOStm, const OUString& rBaseURL ) const
866 : {
867 : IMapObject* pObj;
868 0 : size_t nCount = maList.size();
869 :
870 0 : for ( size_t i = 0; i < nCount; i++ )
871 : {
872 0 : pObj = maList[ i ];
873 0 : pObj->Write( rOStm, rBaseURL );
874 : }
875 0 : }
876 :
877 :
878 : /******************************************************************************
879 : |*
880 : |* sequentially read objects
881 : |*
882 : \******************************************************************************/
883 :
884 0 : void ImageMap::ImpReadImageMap( SvStream& rIStm, size_t nCount, const OUString& rBaseURL )
885 : {
886 : // neue Objekte einlesen
887 0 : for ( size_t i = 0; i < nCount; i++ )
888 : {
889 : sal_uInt16 nType;
890 :
891 0 : rIStm.ReadUInt16( nType );
892 0 : rIStm.SeekRel( -2 );
893 :
894 0 : switch( nType )
895 : {
896 : case ( IMAP_OBJ_RECTANGLE ):
897 : {
898 0 : IMapRectangleObject* pObj = new IMapRectangleObject;
899 0 : pObj->Read( rIStm, rBaseURL );
900 0 : maList.push_back( pObj );
901 : }
902 0 : break;
903 :
904 : case ( IMAP_OBJ_CIRCLE ):
905 : {
906 0 : IMapCircleObject* pObj = new IMapCircleObject;
907 0 : pObj->Read( rIStm, rBaseURL );
908 0 : maList.push_back( pObj );
909 : }
910 0 : break;
911 :
912 : case ( IMAP_OBJ_POLYGON ):
913 : {
914 0 : IMapPolygonObject* pObj = new IMapPolygonObject;
915 0 : pObj->Read( rIStm, rBaseURL );
916 0 : maList.push_back( pObj );
917 : }
918 0 : break;
919 :
920 : default:
921 0 : break;
922 : }
923 : }
924 0 : }
925 :
926 :
927 : /******************************************************************************
928 : |*
929 : |* store binary
930 : |*
931 : \******************************************************************************/
932 :
933 0 : void ImageMap::Write( SvStream& rOStm, const OUString& rBaseURL ) const
934 : {
935 : IMapCompat* pCompat;
936 0 : OUString aImageName( GetName() );
937 0 : sal_uInt16 nOldFormat = rOStm.GetNumberFormatInt();
938 0 : sal_uInt16 nCount = (sal_uInt16) GetIMapObjectCount();
939 0 : const rtl_TextEncoding eEncoding = osl_getThreadTextEncoding(); //vomit!
940 :
941 0 : rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
942 :
943 : // write MagicCode
944 0 : rOStm.WriteCharPtr( IMAPMAGIC );
945 0 : rOStm.WriteUInt16( GetVersion() );
946 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, aImageName, eEncoding);
947 0 : write_uInt16_lenPrefixed_uInt8s_FromOString(rOStm, OString()); //dummy
948 0 : rOStm.WriteUInt16( nCount );
949 0 : write_uInt16_lenPrefixed_uInt8s_FromOUString(rOStm, aImageName, eEncoding);
950 :
951 0 : pCompat = new IMapCompat( rOStm, STREAM_WRITE );
952 :
953 : // here one can insert in newer versions
954 :
955 0 : delete pCompat;
956 :
957 0 : ImpWriteImageMap( rOStm, rBaseURL );
958 :
959 0 : rOStm.SetNumberFormatInt( nOldFormat );
960 0 : }
961 :
962 :
963 : /******************************************************************************
964 : |*
965 : |* load binary
966 : |*
967 : \******************************************************************************/
968 :
969 0 : void ImageMap::Read( SvStream& rIStm, const OUString& rBaseURL )
970 : {
971 : char cMagic[6];
972 0 : sal_uInt16 nOldFormat = rIStm.GetNumberFormatInt();
973 : sal_uInt16 nCount;
974 :
975 0 : rIStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
976 0 : rIStm.Read( cMagic, sizeof( cMagic ) );
977 :
978 0 : if ( !memcmp( cMagic, IMAPMAGIC, sizeof( cMagic ) ) )
979 : {
980 : IMapCompat* pCompat;
981 :
982 : // delete old content
983 0 : ClearImageMap();
984 :
985 : // read on version
986 0 : rIStm.SeekRel( 2 );
987 :
988 0 : aName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIStm, osl_getThreadTextEncoding());
989 0 : read_uInt16_lenPrefixed_uInt8s_ToOString(rIStm); // Dummy
990 0 : rIStm.ReadUInt16( nCount );
991 0 : read_uInt16_lenPrefixed_uInt8s_ToOString(rIStm); // Dummy
992 :
993 0 : pCompat = new IMapCompat( rIStm, STREAM_READ );
994 :
995 : // here one can read in newer versions
996 :
997 0 : delete pCompat;
998 0 : ImpReadImageMap( rIStm, nCount, rBaseURL );
999 :
1000 : }
1001 : else
1002 0 : rIStm.SetError( SVSTREAM_GENERALERROR );
1003 :
1004 0 : rIStm.SetNumberFormatInt( nOldFormat );
1005 1227 : }
1006 :
1007 :
1008 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|