1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <comphelper/string.hxx>
23 #include <rtl/strbuf.hxx>
24 #include <vcl/svapp.hxx>
25 #include <tools/urlobj.hxx>
26 #include <vcl/wrkwin.hxx>
27 #include <sot/formats.hxx>
29 #include "svl/urihelper.hxx"
30 #include <svtools/imap.hxx>
31 #include <svtools/imapobj.hxx>
32 #include <svtools/imaprect.hxx>
33 #include <svtools/imapcirc.hxx>
34 #include <svtools/imappoly.hxx>
38 #define NOTEOL(c) ((c)!='\0')
40 TYPEINIT0_AUTOFACTORY( ImageMap
);
42 void IMapObject::AppendCERNCoords(OStringBuffer
& rBuf
, const Point
& rPoint100
) const
44 const Point
aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100
, MapMode( MAP_100TH_MM
) ) );
47 rBuf
.append(static_cast<sal_Int32
>(aPixPt
.X()));
49 rBuf
.append(static_cast<sal_Int32
>(aPixPt
.Y()));
50 rBuf
.append(RTL_CONSTASCII_STRINGPARAM(") "));
53 void IMapObject::AppendNCSACoords(OStringBuffer
& rBuf
, const Point
& rPoint100
) const
55 const Point
aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100
, MapMode( MAP_100TH_MM
) ) );
57 rBuf
.append(static_cast<sal_Int32
>(aPixPt
.X()));
59 rBuf
.append(static_cast<sal_Int32
>(aPixPt
.Y()));
63 void IMapObject::AppendCERNURL(OStringBuffer
& rBuf
, const String
& rBaseURL
) const
65 rBuf
.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative(rBaseURL
, aURL
), osl_getThreadTextEncoding()));
68 void IMapObject::AppendNCSAURL(OStringBuffer
& rBuf
, const String
& rBaseURL
) const
70 rBuf
.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative(rBaseURL
, aURL
), osl_getThreadTextEncoding()));
74 void IMapRectangleObject::WriteCERN( SvStream
& rOStm
, const String
& rBaseURL
) const
76 OStringBuffer
aStrBuf(RTL_CONSTASCII_STRINGPARAM("rectangle "));
78 AppendCERNCoords(aStrBuf
, aRect
.TopLeft());
79 AppendCERNCoords(aStrBuf
, aRect
.BottomRight());
80 AppendCERNURL(aStrBuf
, rBaseURL
);
82 rOStm
.WriteLine(aStrBuf
.makeStringAndClear());
85 void IMapRectangleObject::WriteNCSA( SvStream
& rOStm
, const String
& rBaseURL
) const
87 OStringBuffer
aStrBuf(RTL_CONSTASCII_STRINGPARAM("rect "));
89 AppendNCSAURL(aStrBuf
, rBaseURL
);
90 AppendNCSACoords(aStrBuf
, aRect
.TopLeft());
91 AppendNCSACoords(aStrBuf
, aRect
.BottomRight());
93 rOStm
.WriteLine(aStrBuf
.makeStringAndClear());
96 void IMapCircleObject::WriteCERN( SvStream
& rOStm
, const String
& rBaseURL
) const
98 OStringBuffer
aStrBuf(RTL_CONSTASCII_STRINGPARAM("circle "));
100 AppendCERNCoords(aStrBuf
, aCenter
);
101 aStrBuf
.append(nRadius
);
103 AppendCERNURL(aStrBuf
, rBaseURL
);
105 rOStm
.WriteLine(aStrBuf
.makeStringAndClear());
108 void IMapCircleObject::WriteNCSA( SvStream
& rOStm
, const String
& rBaseURL
) const
110 OStringBuffer
aStrBuf(RTL_CONSTASCII_STRINGPARAM("circle "));
112 AppendNCSAURL(aStrBuf
, rBaseURL
);
113 AppendNCSACoords(aStrBuf
, aCenter
);
114 AppendNCSACoords(aStrBuf
, aCenter
+ Point(nRadius
, 0));
116 rOStm
.WriteLine(aStrBuf
.makeStringAndClear());
119 void IMapPolygonObject::WriteCERN( SvStream
& rOStm
, const String
& rBaseURL
) const
121 OStringBuffer
aStrBuf(RTL_CONSTASCII_STRINGPARAM("polygon "));
122 const sal_uInt16 nCount
= aPoly
.GetSize();
124 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
125 AppendCERNCoords(aStrBuf
, aPoly
[i
]);
127 AppendCERNURL(aStrBuf
, rBaseURL
);
129 rOStm
.WriteLine(aStrBuf
.makeStringAndClear());
132 void IMapPolygonObject::WriteNCSA( SvStream
& rOStm
, const String
& rBaseURL
) const
134 OStringBuffer
aStrBuf(RTL_CONSTASCII_STRINGPARAM("poly "));
135 const sal_uInt16 nCount
= std::min( aPoly
.GetSize(), (sal_uInt16
) 100 );
137 AppendNCSAURL(aStrBuf
, rBaseURL
);
139 for (sal_uInt16 i
= 0; i
< nCount
; ++i
)
140 AppendNCSACoords(aStrBuf
, aPoly
[i
]);
142 rOStm
.WriteLine(aStrBuf
.makeStringAndClear());
145 void ImageMap::Write( SvStream
& rOStm
, sal_uLong nFormat
, const String
& rBaseURL
) const
149 case( IMAP_FORMAT_BIN
) : Write( rOStm
, rBaseURL
);
150 case( IMAP_FORMAT_CERN
) : ImpWriteCERN( rOStm
, rBaseURL
); break;
151 case( IMAP_FORMAT_NCSA
) : ImpWriteNCSA( rOStm
, rBaseURL
); break;
158 void ImageMap::ImpWriteCERN( SvStream
& rOStm
, const String
& rBaseURL
) const
161 size_t nCount
= maList
.size();
163 for ( size_t i
= 0; i
< nCount
; i
++ )
167 switch( pObj
->GetType() )
169 case( IMAP_OBJ_RECTANGLE
):
170 ( (IMapRectangleObject
*) pObj
)->WriteCERN( rOStm
, rBaseURL
);
173 case( IMAP_OBJ_CIRCLE
):
174 ( (IMapCircleObject
*) pObj
)->WriteCERN( rOStm
, rBaseURL
);
177 case( IMAP_OBJ_POLYGON
):
178 ( (IMapPolygonObject
*) pObj
)->WriteCERN( rOStm
, rBaseURL
);
187 void ImageMap::ImpWriteNCSA( SvStream
& rOStm
, const String
& rBaseURL
) const
190 size_t nCount
= maList
.size();
192 for ( size_t i
= 0; i
< nCount
; i
++ )
196 switch( pObj
->GetType() )
198 case( IMAP_OBJ_RECTANGLE
):
199 ( (IMapRectangleObject
*) pObj
)->WriteNCSA( rOStm
, rBaseURL
);
202 case( IMAP_OBJ_CIRCLE
):
203 ( (IMapCircleObject
*) pObj
)->WriteNCSA( rOStm
, rBaseURL
);
206 case( IMAP_OBJ_POLYGON
):
207 ( (IMapPolygonObject
*) pObj
)->WriteNCSA( rOStm
, rBaseURL
);
216 sal_uLong
ImageMap::Read( SvStream
& rIStm
, sal_uLong nFormat
, const String
& rBaseURL
)
218 sal_uLong nRet
= IMAP_ERR_FORMAT
;
220 if ( nFormat
== IMAP_FORMAT_DETECT
)
221 nFormat
= ImpDetectFormat( rIStm
);
225 case ( IMAP_FORMAT_BIN
) : Read( rIStm
, rBaseURL
); break;
226 case ( IMAP_FORMAT_CERN
) : nRet
= ImpReadCERN( rIStm
, rBaseURL
); break;
227 case ( IMAP_FORMAT_NCSA
) : nRet
= ImpReadNCSA( rIStm
, rBaseURL
); break;
233 if ( !rIStm
.GetError() )
239 sal_uLong
ImageMap::ImpReadCERN( SvStream
& rIStm
, const String
& rBaseURL
)
241 // alten Inhalt loeschen
245 while ( rIStm
.ReadLine( aStr
) )
246 ImpReadCERNLine( aStr
, rBaseURL
);
251 void ImageMap::ImpReadCERNLine( const OString
& rLine
, const String
& rBaseURL
)
253 OString aStr
= comphelper::string::stripStart(rLine
, ' ');
254 aStr
= comphelper::string::stripStart(aStr
, '\t');
255 aStr
= comphelper::string::remove(aStr
, ';');
256 aStr
= aStr
.toAsciiLowerCase();
258 const char* pStr
= aStr
.getStr();
259 char cChar
= *pStr
++;
263 while( ( cChar
>= 'a' ) && ( cChar
<= 'z' ) && NOTEOL( cChar
) )
268 OString aToken
= aBuf
.makeStringAndClear();
270 if ( NOTEOL( cChar
) )
272 if ( ( aToken
== "rectangle" ) || ( aToken
== "rect" ) )
274 const Point
aTopLeft( ImpReadCERNCoords( &pStr
) );
275 const Point
aBottomRight( ImpReadCERNCoords( &pStr
) );
276 const String
aURL( ImpReadCERNURL( &pStr
, rBaseURL
) );
277 const Rectangle
aRect( aTopLeft
, aBottomRight
);
279 IMapRectangleObject
* pObj
= new IMapRectangleObject( aRect
, aURL
, String(), String(), String(), String() );
280 maList
.push_back( pObj
);
282 else if ( ( aToken
== "circle" ) || ( aToken
== "circ" ) )
284 const Point
aCenter( ImpReadCERNCoords( &pStr
) );
285 const long nRadius
= ImpReadCERNRadius( &pStr
);
286 const String
aURL( ImpReadCERNURL( &pStr
, rBaseURL
) );
288 IMapCircleObject
* pObj
= new IMapCircleObject( aCenter
, nRadius
, aURL
, String(), String(), String(), String() );
289 maList
.push_back( pObj
);
291 else if ( ( aToken
== "polygon" ) || ( aToken
== "poly" ) )
293 const sal_uInt16 nCount
= comphelper::string::getTokenCount(aStr
,
295 Polygon
aPoly( nCount
);
298 for ( sal_uInt16 i
= 0; i
< nCount
; i
++ )
299 aPoly
[ i
] = ImpReadCERNCoords( &pStr
);
301 aURL
= ImpReadCERNURL( &pStr
, rBaseURL
);
303 IMapPolygonObject
* pObj
= new IMapPolygonObject( aPoly
, aURL
, String(), String(), String(), String() );
304 maList
.push_back( pObj
);
309 Point
ImageMap::ImpReadCERNCoords( const char** ppStr
)
314 char cChar
= *(*ppStr
)++;
316 while( NOTEOL( cChar
) && ( ( cChar
< '0' ) || ( cChar
> '9' ) ) )
319 if ( NOTEOL( cChar
) )
321 while( NOTEOL( cChar
) && ( cChar
>= '0' ) && ( cChar
<= '9' ) )
327 if ( NOTEOL( cChar
) )
329 while( NOTEOL( cChar
) && ( ( cChar
< '0' ) || ( cChar
> '9' ) ) )
332 while( NOTEOL( cChar
) && ( cChar
>= '0' ) && ( cChar
<= '9' ) )
338 if ( NOTEOL( cChar
) )
339 while( NOTEOL( cChar
) && ( cChar
!= ')' ) )
342 aPt
= Point( aStrX
.ToInt32(), aStrY
.ToInt32() );
349 long ImageMap::ImpReadCERNRadius( const char** ppStr
)
352 char cChar
= *(*ppStr
)++;
354 while( NOTEOL( cChar
) && ( ( cChar
< '0' ) || ( cChar
> '9' ) ) )
357 if ( NOTEOL( cChar
) )
359 while( NOTEOL( cChar
) && ( cChar
>= '0' ) && ( cChar
<= '9' ) )
366 return aStr
.ToInt32();
369 String
ImageMap::ImpReadCERNURL( const char** ppStr
, const String
& rBaseURL
)
371 OUString
aStr(OUString::createFromAscii(*ppStr
));
373 aStr
= comphelper::string::stripStart(aStr
, ' ');
374 aStr
= comphelper::string::stripStart(aStr
, '\t');
375 aStr
= comphelper::string::stripEnd(aStr
, ' ');
376 aStr
= comphelper::string::stripEnd(aStr
, '\t');
378 return INetURLObject::GetAbsURL( rBaseURL
, aStr
);
381 sal_uLong
ImageMap::ImpReadNCSA( SvStream
& rIStm
, const String
& rBaseURL
)
383 // alten Inhalt loeschen
387 while ( rIStm
.ReadLine( aStr
) )
388 ImpReadNCSALine( aStr
, rBaseURL
);
393 void ImageMap::ImpReadNCSALine( const OString
& rLine
, const String
& rBaseURL
)
395 OString aStr
= comphelper::string::stripStart(rLine
, ' ');
396 aStr
= comphelper::string::stripStart(aStr
, '\t');
397 aStr
= comphelper::string::remove(aStr
, ';');
398 aStr
= aStr
.toAsciiLowerCase();
400 const char* pStr
= aStr
.getStr();
401 char cChar
= *pStr
++;
405 while( ( cChar
>= 'a' ) && ( cChar
<= 'z' ) && NOTEOL( cChar
) )
410 OString aToken
= aBuf
.makeStringAndClear();
412 if ( NOTEOL( cChar
) )
414 if ( aToken
== "rect" )
416 const String
aURL( ImpReadNCSAURL( &pStr
, rBaseURL
) );
417 const Point
aTopLeft( ImpReadNCSACoords( &pStr
) );
418 const Point
aBottomRight( ImpReadNCSACoords( &pStr
) );
419 const Rectangle
aRect( aTopLeft
, aBottomRight
);
421 IMapRectangleObject
* pObj
= new IMapRectangleObject( aRect
, aURL
, String(), String(), String(), String() );
422 maList
.push_back( pObj
);
424 else if ( aToken
== "circle" )
426 const String
aURL( ImpReadNCSAURL( &pStr
, rBaseURL
) );
427 const Point
aCenter( ImpReadNCSACoords( &pStr
) );
428 const Point
aDX( aCenter
- ImpReadNCSACoords( &pStr
) );
429 long nRadius
= (long) sqrt( (double) aDX
.X() * aDX
.X() +
430 (double) aDX
.Y() * aDX
.Y() );
432 IMapCircleObject
* pObj
= new IMapCircleObject( aCenter
, nRadius
, aURL
, String(), String(), String(), String() );
433 maList
.push_back( pObj
);
435 else if ( aToken
== "poly" )
437 const sal_uInt16 nCount
= comphelper::string::getTokenCount(aStr
,
439 const String
aURL( ImpReadNCSAURL( &pStr
, rBaseURL
) );
440 Polygon
aPoly( nCount
);
442 for ( sal_uInt16 i
= 0; i
< nCount
; i
++ )
443 aPoly
[ i
] = ImpReadNCSACoords( &pStr
);
445 IMapPolygonObject
* pObj
= new IMapPolygonObject( aPoly
, aURL
, String(), String(), String(), String() );
446 maList
.push_back( pObj
);
451 String
ImageMap::ImpReadNCSAURL( const char** ppStr
, const String
& rBaseURL
)
454 char cChar
= *(*ppStr
)++;
456 while( NOTEOL( cChar
) && ( ( cChar
== ' ' ) || ( cChar
== '\t' ) ) )
459 if ( NOTEOL( cChar
) )
461 while( NOTEOL( cChar
) && ( cChar
!= ' ' ) && ( cChar
!= '\t' ) )
468 return INetURLObject::GetAbsURL( rBaseURL
, aStr
);
471 Point
ImageMap::ImpReadNCSACoords( const char** ppStr
)
476 char cChar
= *(*ppStr
)++;
478 while( NOTEOL( cChar
) && ( ( cChar
< '0' ) || ( cChar
> '9' ) ) )
481 if ( NOTEOL( cChar
) )
483 while( NOTEOL( cChar
) && ( cChar
>= '0' ) && ( cChar
<= '9' ) )
489 if ( NOTEOL( cChar
) )
491 while( NOTEOL( cChar
) && ( ( cChar
< '0' ) || ( cChar
> '9' ) ) )
494 while( NOTEOL( cChar
) && ( cChar
>= '0' ) && ( cChar
<= '9' ) )
500 aPt
= Point( aStrX
.ToInt32(), aStrY
.ToInt32() );
507 sal_uLong
ImageMap::ImpDetectFormat( SvStream
& rIStm
)
509 sal_uLong nPos
= rIStm
.Tell();
510 sal_uLong nRet
= IMAP_FORMAT_BIN
;
513 rIStm
.Read( cMagic
, sizeof( cMagic
) );
515 // Falls wir kein internes Format haben,
516 // untersuchen wir das Format
517 if ( memcmp( cMagic
, IMAPMAGIC
, sizeof( cMagic
) ) )
523 while ( rIStm
.ReadLine( aStr
) && nCount
-- )
525 aStr
= aStr
.toAsciiLowerCase();
527 if ( (aStr
.indexOfL(RTL_CONSTASCII_STRINGPARAM("rect")) != -1) ||
528 (aStr
.indexOfL(RTL_CONSTASCII_STRINGPARAM("circ")) != -1) ||
529 (aStr
.indexOfL(RTL_CONSTASCII_STRINGPARAM("poly")) != -1) )
531 if ( ( aStr
.indexOf('(') != -1 ) &&
532 ( aStr
.indexOf(')') != -1 ) )
534 nRet
= IMAP_FORMAT_CERN
;
537 nRet
= IMAP_FORMAT_NCSA
;
549 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */