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