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