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