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