xref: /trunk/main/svtools/source/misc/imap2.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #include <string.h>
32 // #include <math.h>
33 #include <vcl/svapp.hxx>
34 #include <tools/urlobj.hxx>
35 #ifndef _WRKWIN_HXX //autogen
36 #include <vcl/wrkwin.hxx>
37 #endif
38 #include <sot/formats.hxx>
39 
40 #include "svl/urihelper.hxx"
41 #include <svtools/imap.hxx>
42 #include <svtools/imap.hxx>
43 #include <svtools/imapobj.hxx>
44 #include <svtools/imaprect.hxx>
45 #include <svtools/imapcirc.hxx>
46 #include <svtools/imappoly.hxx>
47 
48 #include <string.h>
49 #include <math.h>
50 
51 #define NOTEOL(c) ((c)!='\0')
52 
53 
54 TYPEINIT0_AUTOFACTORY( ImageMap );
55 
56 
57 /******************************************************************************/
58 /******************************************************************************/
59 
60 
61 /******************************************************************************
62 |*
63 |*
64 |*
65 \******************************************************************************/
66 
67 void IMapObject::AppendCERNCoords( const Point& rPoint100, ByteString& rStr ) const
68 {
69     const Point aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100, MapMode( MAP_100TH_MM ) ) );
70 
71     rStr += '(';
72     rStr += ByteString::CreateFromInt32( aPixPt.X() );
73     rStr += ',';
74     rStr += ByteString::CreateFromInt32( aPixPt.Y() );
75     rStr += ") ";
76 }
77 
78 
79 /******************************************************************************
80 |*
81 |*
82 |*
83 \******************************************************************************/
84 
85 void IMapObject::AppendNCSACoords( const Point& rPoint100, ByteString& rStr ) const
86 {
87     const Point aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100, MapMode( MAP_100TH_MM ) ) );
88 
89     rStr += ByteString::CreateFromInt32( aPixPt.X() );
90     rStr += ',';
91     rStr += ByteString::CreateFromInt32( aPixPt.Y() );
92     rStr += ' ';
93 }
94 
95 
96 /******************************************************************************
97 |*
98 |*
99 |*
100 \******************************************************************************/
101 
102 void IMapObject::AppendCERNURL( ByteString& rStr, const String& rBaseURL ) const
103 {
104     rStr += ByteString( String(URIHelper::simpleNormalizedMakeRelative( rBaseURL, aURL )), gsl_getSystemTextEncoding() );
105 }
106 
107 
108 /******************************************************************************
109 |*
110 |*
111 |*
112 \******************************************************************************/
113 
114 void IMapObject::AppendNCSAURL( ByteString& rStr, const String& rBaseURL ) const
115 {
116     rStr += ByteString( String(URIHelper::simpleNormalizedMakeRelative( rBaseURL, aURL )), gsl_getSystemTextEncoding() );
117     rStr += ' ';
118 }
119 
120 
121 /******************************************************************************/
122 /******************************************************************************/
123 
124 
125 /******************************************************************************
126 |*
127 |*
128 |*
129 \******************************************************************************/
130 
131 void IMapRectangleObject::WriteCERN( SvStream& rOStm, const String& rBaseURL ) const
132 {
133     ByteString aStr( "rectangle " );
134 
135     AppendCERNCoords( aRect.TopLeft(), aStr );
136     AppendCERNCoords( aRect.BottomRight(), aStr );
137     AppendCERNURL( aStr, rBaseURL );
138 
139     rOStm.WriteLine( aStr );
140 }
141 
142 
143 /******************************************************************************
144 |*
145 |*
146 |*
147 \******************************************************************************/
148 
149 void IMapRectangleObject::WriteNCSA( SvStream& rOStm, const String& rBaseURL ) const
150 {
151     ByteString aStr( "rect " );
152 
153     AppendNCSAURL( aStr, rBaseURL );
154     AppendNCSACoords( aRect.TopLeft(), aStr );
155     AppendNCSACoords( aRect.BottomRight(), aStr );
156 
157     rOStm.WriteLine( aStr );
158 }
159 
160 
161 /******************************************************************************/
162 /******************************************************************************/
163 
164 
165 /******************************************************************************
166 |*
167 |*
168 |*
169 \******************************************************************************/
170 
171 void IMapCircleObject::WriteCERN( SvStream& rOStm, const String& rBaseURL ) const
172 {
173     ByteString aStr( "circle " );
174 
175     AppendCERNCoords( aCenter, aStr );
176     aStr += ByteString::CreateFromInt32(nRadius);
177     aStr += ' ';
178     AppendCERNURL( aStr, rBaseURL );
179 
180     rOStm.WriteLine( aStr );
181 }
182 
183 
184 /******************************************************************************
185 |*
186 |*
187 |*
188 \******************************************************************************/
189 
190 void IMapCircleObject::WriteNCSA( SvStream& rOStm, const String& rBaseURL ) const
191 {
192     ByteString aStr( "circle " );
193 
194     AppendNCSAURL( aStr, rBaseURL );
195     AppendNCSACoords( aCenter, aStr );
196     AppendNCSACoords( aCenter + Point( nRadius, 0 ), aStr );
197 
198     rOStm.WriteLine( aStr );
199 }
200 
201 
202 /******************************************************************************/
203 /******************************************************************************/
204 
205 
206 /******************************************************************************
207 |*
208 |*
209 |*
210 \******************************************************************************/
211 
212 void IMapPolygonObject::WriteCERN( SvStream& rOStm, const String& rBaseURL  ) const
213 {
214     ByteString      aStr( "polygon " );
215     const sal_uInt16    nCount = aPoly.GetSize();
216 
217     for ( sal_uInt16 i = 0; i < nCount; i++ )
218         AppendCERNCoords( aPoly[ i ], aStr );
219 
220     AppendCERNURL( aStr, rBaseURL );
221 
222     rOStm.WriteLine( aStr );
223 }
224 
225 
226 /******************************************************************************
227 |*
228 |*
229 |*
230 \******************************************************************************/
231 
232 void IMapPolygonObject::WriteNCSA( SvStream& rOStm, const String& rBaseURL  ) const
233 {
234     ByteString      aStr( "poly " );
235     const sal_uInt16    nCount = Min( aPoly.GetSize(), (sal_uInt16) 100 );
236 
237     AppendNCSAURL( aStr, rBaseURL );
238 
239     for ( sal_uInt16 i = 0; i < nCount; i++ )
240         AppendNCSACoords( aPoly[ i ], aStr );
241 
242     rOStm.WriteLine( aStr );
243 }
244 
245 
246 /******************************************************************************/
247 /******************************************************************************/
248 
249 
250 /******************************************************************************
251 |*
252 |*
253 |*
254 \******************************************************************************/
255 
256 void ImageMap::Write( SvStream& rOStm, sal_uLong nFormat, const String& rBaseURL ) const
257 {
258     switch( nFormat )
259     {
260         case( IMAP_FORMAT_BIN ) : Write( rOStm, rBaseURL );
261         case( IMAP_FORMAT_CERN ) : ImpWriteCERN( rOStm, rBaseURL ); break;
262         case( IMAP_FORMAT_NCSA ) : ImpWriteNCSA( rOStm, rBaseURL ); break;
263 
264         default:
265         break;
266     }
267 }
268 
269 
270 /******************************************************************************
271 |*
272 |*
273 |*
274 \******************************************************************************/
275 
276 void ImageMap::ImpWriteCERN( SvStream& rOStm, const String& rBaseURL ) const
277 {
278     IMapObject* pObj;
279     sal_uInt16      nCount = (sal_uInt16) maList.Count();
280 
281     for ( sal_uInt16 i = 0; i < nCount; i++ )
282     {
283         pObj = GetIMapObject( i );
284 
285         switch( pObj->GetType() )
286         {
287             case( IMAP_OBJ_RECTANGLE ):
288                 ( (IMapRectangleObject*) pObj )->WriteCERN( rOStm, rBaseURL );
289             break;
290 
291             case( IMAP_OBJ_CIRCLE ):
292                 ( (IMapCircleObject*) pObj )->WriteCERN( rOStm, rBaseURL );
293             break;
294 
295             case( IMAP_OBJ_POLYGON ):
296                 ( (IMapPolygonObject*) pObj )->WriteCERN( rOStm, rBaseURL );
297             break;
298 
299             default:
300             break;
301         }
302     }
303 }
304 
305 
306 /******************************************************************************
307 |*
308 |*
309 |*
310 \******************************************************************************/
311 
312 void ImageMap::ImpWriteNCSA( SvStream& rOStm, const String& rBaseURL  ) const
313 {
314     IMapObject* pObj;
315     sal_uInt16      nCount = (sal_uInt16) maList.Count();
316 
317     for ( sal_uInt16 i = 0; i < nCount; i++ )
318     {
319         pObj = GetIMapObject( i );
320 
321             switch( pObj->GetType() )
322         {
323             case( IMAP_OBJ_RECTANGLE ):
324                 ( (IMapRectangleObject*) pObj )->WriteNCSA( rOStm, rBaseURL );
325             break;
326 
327             case( IMAP_OBJ_CIRCLE ):
328                 ( (IMapCircleObject*) pObj )->WriteNCSA( rOStm, rBaseURL );
329             break;
330 
331             case( IMAP_OBJ_POLYGON ):
332                 ( (IMapPolygonObject*) pObj )->WriteNCSA( rOStm, rBaseURL );
333             break;
334 
335             default:
336             break;
337         }
338     }
339 }
340 
341 
342 /******************************************************************************
343 |*
344 |*
345 |*
346 \******************************************************************************/
347 
348 sal_uLong ImageMap::Read( SvStream& rIStm, sal_uLong nFormat, const String& rBaseURL  )
349 {
350     sal_uLong nRet = IMAP_ERR_FORMAT;
351 
352     if ( nFormat == IMAP_FORMAT_DETECT )
353         nFormat = ImpDetectFormat( rIStm );
354 
355     switch ( nFormat )
356     {
357         case ( IMAP_FORMAT_BIN )    : Read( rIStm, rBaseURL ); break;
358         case ( IMAP_FORMAT_CERN )   : nRet = ImpReadCERN( rIStm, rBaseURL ); break;
359         case ( IMAP_FORMAT_NCSA )   : nRet = ImpReadNCSA( rIStm, rBaseURL ); break;
360 
361         default:
362         break;
363     }
364 
365     if ( !rIStm.GetError() )
366         nRet = IMAP_ERR_OK;
367 
368     return nRet;
369 }
370 
371 
372 /******************************************************************************
373 |*
374 |*
375 |*
376 \******************************************************************************/
377 
378 sal_uLong ImageMap::ImpReadCERN( SvStream& rIStm, const String& rBaseURL )
379 {
380     ByteString aStr;
381 
382     // alten Inhalt loeschen
383     ClearImageMap();
384 
385     while ( rIStm.ReadLine( aStr ) )
386         ImpReadCERNLine( aStr, rBaseURL );
387 
388     return IMAP_ERR_OK;
389 }
390 
391 
392 /******************************************************************************
393 |*
394 |*
395 |*
396 \******************************************************************************/
397 
398 void ImageMap::ImpReadCERNLine( const ByteString& rLine, const String& rBaseURL  )
399 {
400     ByteString  aStr( rLine );
401     ByteString  aToken;
402 
403     aStr.EraseLeadingChars( ' ' );
404     aStr.EraseLeadingChars( '\t' );
405     aStr.EraseAllChars( ';' );
406     aStr.ToLowerAscii();
407 
408     const char* pStr = aStr.GetBuffer();
409     char        cChar = *pStr++;
410 
411         // Anweisung finden
412     while( ( cChar >= 'a' ) && ( cChar <= 'z' ) && NOTEOL( cChar ) )
413     {
414         aToken += cChar;
415         cChar = *pStr++;
416     }
417 
418     if ( NOTEOL( cChar ) )
419     {
420         if ( ( aToken == "rectangle" ) || ( aToken == "rect" ) )
421         {
422             const Point     aTopLeft( ImpReadCERNCoords( &pStr ) );
423             const Point     aBottomRight( ImpReadCERNCoords( &pStr ) );
424             const String    aURL( ImpReadCERNURL( &pStr, rBaseURL ) );
425             const Rectangle aRect( aTopLeft, aBottomRight );
426 
427             IMapRectangleObject* pObj = new IMapRectangleObject( aRect, aURL, String(), String(), String(), String() );
428             maList.Insert( pObj, LIST_APPEND );
429         }
430         else if ( ( aToken == "circle" ) || ( aToken == "circ" ) )
431         {
432             const Point     aCenter( ImpReadCERNCoords( &pStr ) );
433             const long      nRadius = ImpReadCERNRadius( &pStr );
434             const String    aURL( ImpReadCERNURL( &pStr, rBaseURL ) );
435 
436             IMapCircleObject* pObj = new IMapCircleObject( aCenter, nRadius, aURL, String(), String(), String(), String() );
437             maList.Insert( pObj, LIST_APPEND );
438         }
439         else if ( ( aToken == "polygon" ) || ( aToken == "poly" ) )
440         {
441             const sal_uInt16    nCount = aStr.GetTokenCount( '(' ) - 1;
442             Polygon         aPoly( nCount );
443             String          aURL;
444 
445             for ( sal_uInt16 i = 0; i < nCount; i++ )
446                 aPoly[ i ] = ImpReadCERNCoords( &pStr );
447 
448             aURL = ImpReadCERNURL( &pStr, rBaseURL );
449 
450             IMapPolygonObject* pObj = new IMapPolygonObject( aPoly, aURL, String(), String(), String(), String() );
451             maList.Insert( pObj, LIST_APPEND );
452         }
453     }
454 }
455 
456 
457 /******************************************************************************
458 |*
459 |*
460 |*
461 \******************************************************************************/
462 
463 Point ImageMap::ImpReadCERNCoords( const char** ppStr )
464 {
465     String  aStrX;
466     String  aStrY;
467     Point   aPt;
468     char    cChar = *(*ppStr)++;
469 
470     while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
471         cChar = *(*ppStr)++;
472 
473     if ( NOTEOL( cChar ) )
474     {
475         while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
476         {
477             aStrX += cChar;
478             cChar = *(*ppStr)++;
479         }
480 
481         if ( NOTEOL( cChar ) )
482         {
483             while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
484                 cChar = *(*ppStr)++;
485 
486             while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
487             {
488                 aStrY += cChar;
489                 cChar = *(*ppStr)++;
490             }
491 
492             if ( NOTEOL( cChar ) )
493                 while( NOTEOL( cChar ) && ( cChar != ')' ) )
494                     cChar = *(*ppStr)++;
495 
496             aPt = Point( aStrX.ToInt32(), aStrY.ToInt32() );
497         }
498     }
499 
500     return aPt;
501 }
502 
503 
504 /******************************************************************************
505 |*
506 |*
507 |*
508 \******************************************************************************/
509 
510 long ImageMap::ImpReadCERNRadius( const char** ppStr )
511 {
512     String  aStr;
513     char    cChar = *(*ppStr)++;
514 
515     while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
516         cChar = *(*ppStr)++;
517 
518     if ( NOTEOL( cChar ) )
519     {
520         while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
521         {
522             aStr += cChar;
523             cChar = *(*ppStr)++;
524         }
525     }
526 
527     return aStr.ToInt32();
528 }
529 
530 
531 /******************************************************************************
532 |*
533 |*
534 |*
535 \******************************************************************************/
536 
537 String ImageMap::ImpReadCERNURL( const char** ppStr, const String& rBaseURL )
538 {
539     String  aStr( String::CreateFromAscii( *ppStr ) );
540 
541     aStr.EraseLeadingChars( ' ' );
542     aStr.EraseLeadingChars( '\t' );
543     aStr.EraseTrailingChars( ' ' );
544     aStr.EraseTrailingChars( '\t' );
545 
546     return INetURLObject::GetAbsURL( rBaseURL, aStr );
547 }
548 
549 
550 /******************************************************************************
551 |*
552 |*
553 |*
554 \******************************************************************************/
555 
556 sal_uLong ImageMap::ImpReadNCSA( SvStream& rIStm, const String& rBaseURL )
557 {
558     ByteString aStr;
559 
560     // alten Inhalt loeschen
561     ClearImageMap();
562 
563     while ( rIStm.ReadLine( aStr ) )
564         ImpReadNCSALine( aStr, rBaseURL );
565 
566     return IMAP_ERR_OK;
567 }
568 
569 
570 /******************************************************************************
571 |*
572 |*
573 |*
574 \******************************************************************************/
575 
576 void ImageMap::ImpReadNCSALine( const ByteString& rLine, const String& rBaseURL )
577 {
578     ByteString  aStr( rLine );
579     ByteString  aToken;
580 
581     aStr.EraseLeadingChars( ' ' );
582     aStr.EraseLeadingChars( '\t' );
583     aStr.EraseAllChars( ';' );
584     aStr.ToLowerAscii();
585 
586     const char* pStr = aStr.GetBuffer();
587     char        cChar = *pStr++;
588 
589         // Anweisung finden
590     while( ( cChar >= 'a' ) && ( cChar <= 'z' ) && NOTEOL( cChar ) )
591     {
592         aToken += cChar;
593         cChar = *pStr++;
594     }
595 
596     if ( NOTEOL( cChar ) )
597     {
598         if ( aToken == "rect" )
599         {
600             const String    aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
601             const Point     aTopLeft( ImpReadNCSACoords( &pStr ) );
602             const Point     aBottomRight( ImpReadNCSACoords( &pStr ) );
603             const Rectangle aRect( aTopLeft, aBottomRight );
604 
605             IMapRectangleObject* pObj = new IMapRectangleObject( aRect, aURL, String(), String(), String(), String() );
606             maList.Insert( pObj, LIST_APPEND );
607         }
608         else if ( aToken == "circle" )
609         {
610             const String    aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
611             const Point     aCenter( ImpReadNCSACoords( &pStr ) );
612             const Point     aDX( aCenter - ImpReadNCSACoords( &pStr ) );
613             long            nRadius = (long) sqrt( (double) aDX.X() * aDX.X() +
614                                                    (double) aDX.Y() * aDX.Y() );
615 
616             IMapCircleObject* pObj = new IMapCircleObject( aCenter, nRadius, aURL, String(), String(), String(), String() );
617             maList.Insert( pObj, LIST_APPEND );
618         }
619         else if ( aToken == "poly" )
620         {
621             const sal_uInt16    nCount = aStr.GetTokenCount( ',' ) - 1;
622             const String    aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
623             Polygon         aPoly( nCount );
624 
625             for ( sal_uInt16 i = 0; i < nCount; i++ )
626                 aPoly[ i ] = ImpReadNCSACoords( &pStr );
627 
628             IMapPolygonObject* pObj = new IMapPolygonObject( aPoly, aURL, String(), String(), String(), String() );
629             maList.Insert( pObj, LIST_APPEND );
630         }
631     }
632 }
633 
634 
635 /******************************************************************************
636 |*
637 |*
638 |*
639 \******************************************************************************/
640 
641 String ImageMap::ImpReadNCSAURL( const char** ppStr, const String& rBaseURL )
642 {
643     String  aStr;
644     char    cChar = *(*ppStr)++;
645 
646     while( NOTEOL( cChar ) && ( ( cChar == ' ' ) || ( cChar == '\t' ) ) )
647         cChar = *(*ppStr)++;
648 
649     if ( NOTEOL( cChar ) )
650     {
651         while( NOTEOL( cChar ) && ( cChar != ' ' ) && ( cChar != '\t' ) )
652         {
653             aStr += cChar;
654             cChar = *(*ppStr)++;
655         }
656     }
657 
658     return INetURLObject::GetAbsURL( rBaseURL, aStr );
659 }
660 
661 
662 /******************************************************************************
663 |*
664 |*
665 |*
666 \******************************************************************************/
667 
668 Point ImageMap::ImpReadNCSACoords( const char** ppStr )
669 {
670     String  aStrX;
671     String  aStrY;
672     Point   aPt;
673     char    cChar = *(*ppStr)++;
674 
675     while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
676         cChar = *(*ppStr)++;
677 
678     if ( NOTEOL( cChar ) )
679     {
680         while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
681         {
682             aStrX += cChar;
683             cChar = *(*ppStr)++;
684         }
685 
686         if ( NOTEOL( cChar ) )
687         {
688             while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
689                 cChar = *(*ppStr)++;
690 
691             while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
692             {
693                 aStrY += cChar;
694                 cChar = *(*ppStr)++;
695             }
696 
697             aPt = Point( aStrX.ToInt32(), aStrY.ToInt32() );
698         }
699     }
700 
701     return aPt;
702 }
703 
704 
705 /******************************************************************************
706 |*
707 |*
708 |*
709 \******************************************************************************/
710 
711 sal_uLong ImageMap::ImpDetectFormat( SvStream& rIStm )
712 {
713     sal_uLong   nPos = rIStm.Tell();
714     sal_uLong   nRet = IMAP_FORMAT_BIN;
715     char    cMagic[6];
716 
717     rIStm.Read( cMagic, sizeof( cMagic ) );
718 
719     // Falls wir kein internes Format haben,
720     // untersuchen wir das Format
721     if ( memcmp( cMagic, IMAPMAGIC, sizeof( cMagic ) ) )
722     {
723         ByteString  aStr;
724         long        nCount = 128;
725 
726         rIStm.Seek( nPos );
727         while ( rIStm.ReadLine( aStr ) && nCount-- )
728         {
729             aStr.ToLowerAscii();
730 
731             if ( ( aStr.Search( "rect" ) != STRING_NOTFOUND ) ||
732                  ( aStr.Search( "circ" ) != STRING_NOTFOUND ) ||
733                  ( aStr.Search( "poly" ) != STRING_NOTFOUND ) )
734             {
735                 if ( ( aStr.Search( '(' ) != STRING_NOTFOUND ) &&
736                      ( aStr.Search( ')' ) != STRING_NOTFOUND ) )
737                 {
738                     nRet = IMAP_FORMAT_CERN;
739                 }
740                 else
741                     nRet = IMAP_FORMAT_NCSA;
742 
743                 break;
744             }
745         }
746     }
747 
748     rIStm.Seek( nPos );
749 
750     return nRet;
751 }
752