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