diff options
Diffstat (limited to 'vcl/source/treelist/imap2.cxx')
-rw-r--r-- | vcl/source/treelist/imap2.cxx | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/vcl/source/treelist/imap2.cxx b/vcl/source/treelist/imap2.cxx new file mode 100644 index 0000000000..1543801392 --- /dev/null +++ b/vcl/source/treelist/imap2.cxx @@ -0,0 +1,528 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <comphelper/string.hxx> +#include <string.h> +#include <o3tl/string_view.hxx> +#include <rtl/strbuf.hxx> +#include <vcl/outdev.hxx> +#include <vcl/svapp.hxx> +#include <tools/urlobj.hxx> + +#include <svl/urihelper.hxx> +#include <vcl/imap.hxx> +#include <vcl/imapobj.hxx> +#include <vcl/imaprect.hxx> +#include <vcl/imapcirc.hxx> +#include <vcl/imappoly.hxx> + +#include <math.h> + +#define NOTEOL(c) ((c)!='\0') + +void IMapObject::AppendCERNCoords(OStringBuffer& rBuf, const Point& rPoint100) +{ + const Point aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100, MapMode( MapUnit::Map100thMM ) ) ); + + rBuf.append('('); + rBuf.append(static_cast<sal_Int32>(aPixPt.X())); + rBuf.append(','); + rBuf.append(static_cast<sal_Int32>(aPixPt.Y())); + rBuf.append(") "); +} + +void IMapObject::AppendNCSACoords(OStringBuffer& rBuf, const Point& rPoint100) +{ + const Point aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100, MapMode( MapUnit::Map100thMM ) ) ); + + rBuf.append(static_cast<sal_Int32>(aPixPt.X())); + rBuf.append(','); + rBuf.append(static_cast<sal_Int32>(aPixPt.Y())); + rBuf.append(' '); +} + +void IMapObject::AppendCERNURL(OStringBuffer& rBuf) const +{ + rBuf.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative("", aURL), osl_getThreadTextEncoding())); +} + +void IMapObject::AppendNCSAURL(OStringBuffer& rBuf) const +{ + rBuf.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative("", aURL), osl_getThreadTextEncoding())); + rBuf.append(' '); +} + +void IMapRectangleObject::WriteCERN( SvStream& rOStm ) const +{ + OStringBuffer aStrBuf("rectangle "); + + AppendCERNCoords(aStrBuf, aRect.TopLeft()); + AppendCERNCoords(aStrBuf, aRect.BottomRight()); + AppendCERNURL(aStrBuf); + + rOStm.WriteLine(aStrBuf); +} + +void IMapRectangleObject::WriteNCSA( SvStream& rOStm ) const +{ + OStringBuffer aStrBuf("rect "); + + AppendNCSAURL(aStrBuf); + AppendNCSACoords(aStrBuf, aRect.TopLeft()); + AppendNCSACoords(aStrBuf, aRect.BottomRight()); + + rOStm.WriteLine(aStrBuf); +} + +void IMapCircleObject::WriteCERN( SvStream& rOStm ) const +{ + OStringBuffer aStrBuf("circle "); + + AppendCERNCoords(aStrBuf, aCenter); + aStrBuf.append(OString::number(nRadius) + " "); + AppendCERNURL(aStrBuf); + + rOStm.WriteLine(aStrBuf); +} + +void IMapCircleObject::WriteNCSA( SvStream& rOStm ) const +{ + OStringBuffer aStrBuf("circle "); + + AppendNCSAURL(aStrBuf); + AppendNCSACoords(aStrBuf, aCenter); + AppendNCSACoords(aStrBuf, aCenter + Point(nRadius, 0)); + + rOStm.WriteLine(aStrBuf); +} + +void IMapPolygonObject::WriteCERN( SvStream& rOStm ) const +{ + OStringBuffer aStrBuf("polygon "); + const sal_uInt16 nCount = aPoly.GetSize(); + + for (sal_uInt16 i = 0; i < nCount; ++i) + AppendCERNCoords(aStrBuf, aPoly[i]); + + AppendCERNURL(aStrBuf); + + rOStm.WriteLine(aStrBuf); +} + +void IMapPolygonObject::WriteNCSA( SvStream& rOStm ) const +{ + OStringBuffer aStrBuf("poly "); + const sal_uInt16 nCount = std::min( aPoly.GetSize(), sal_uInt16(100) ); + + AppendNCSAURL(aStrBuf); + + for (sal_uInt16 i = 0; i < nCount; ++i) + AppendNCSACoords(aStrBuf, aPoly[i]); + + rOStm.WriteLine(aStrBuf); +} + +void ImageMap::Write( SvStream& rOStm, IMapFormat nFormat ) const +{ + switch( nFormat ) + { + case IMapFormat::Binary : Write( rOStm ); break; + case IMapFormat::CERN : ImpWriteCERN( rOStm ); break; + case IMapFormat::NCSA : ImpWriteNCSA( rOStm ); break; + + default: + break; + } +} + +void ImageMap::ImpWriteCERN( SvStream& rOStm ) const +{ + size_t nCount = maList.size(); + + for ( size_t i = 0; i < nCount; i++ ) + { + IMapObject* pObj = maList[ i ].get(); + + switch( pObj->GetType() ) + { + case IMapObjectType::Rectangle: + static_cast<IMapRectangleObject*>( pObj )->WriteCERN( rOStm ); + break; + + case IMapObjectType::Circle: + static_cast<IMapCircleObject*>( pObj )->WriteCERN( rOStm ); + break; + + case IMapObjectType::Polygon: + static_cast<IMapPolygonObject*>( pObj )->WriteCERN( rOStm ); + break; + + default: + break; + } + } +} + +void ImageMap::ImpWriteNCSA( SvStream& rOStm ) const +{ + size_t nCount = maList.size(); + + for ( size_t i = 0; i < nCount; i++ ) + { + IMapObject* pObj = maList[ i ].get(); + + switch( pObj->GetType() ) + { + case IMapObjectType::Rectangle: + static_cast<IMapRectangleObject*>( pObj )->WriteNCSA( rOStm ); + break; + + case IMapObjectType::Circle: + static_cast<IMapCircleObject*>( pObj )->WriteNCSA( rOStm ); + break; + + case IMapObjectType::Polygon: + static_cast<IMapPolygonObject*>( pObj )->WriteNCSA( rOStm ); + break; + + default: + break; + } + } +} + +sal_uLong ImageMap::Read( SvStream& rIStm, IMapFormat nFormat ) +{ + sal_uLong nRet = IMAP_ERR_FORMAT; + + if ( nFormat == IMapFormat::Detect ) + nFormat = ImpDetectFormat( rIStm ); + + switch ( nFormat ) + { + case IMapFormat::Binary : Read( rIStm ); break; + case IMapFormat::CERN : ImpReadCERN( rIStm ); break; + case IMapFormat::NCSA : ImpReadNCSA( rIStm ); break; + + default: + break; + } + + if ( !rIStm.GetError() ) + nRet = IMAP_ERR_OK; + + return nRet; +} + +void ImageMap::ImpReadCERN( SvStream& rIStm ) +{ + // delete old content + ClearImageMap(); + + OStringBuffer aStr; + while ( rIStm.ReadLine( aStr ) ) + ImpReadCERNLine( aStr ); +} + +void ImageMap::ImpReadCERNLine( std::string_view rLine ) +{ + OString aStr( comphelper::string::stripStart(rLine, ' ') ); + aStr = comphelper::string::stripStart(aStr, '\t'); + aStr = aStr.replaceAll(";"_ostr, ""_ostr); + aStr = aStr.toAsciiLowerCase(); + + const char* pStr = aStr.getStr(); + char cChar = *pStr++; + + // find instruction + OStringBuffer aBuf; + while ((cChar >= 'a') && (cChar <= 'z')) + { + aBuf.append(cChar); + cChar = *pStr++; + } + OString aToken = aBuf.makeStringAndClear(); + + if ( !(NOTEOL( cChar )) ) + return; + + if ( ( aToken == "rectangle" ) || ( aToken == "rect" ) ) + { + const Point aTopLeft( ImpReadCERNCoords( &pStr ) ); + const Point aBottomRight( ImpReadCERNCoords( &pStr ) ); + const OUString aURL( ImpReadCERNURL( &pStr ) ); + const tools::Rectangle aRect( aTopLeft, aBottomRight ); + + maList.emplace_back( new IMapRectangleObject( aRect, aURL, OUString(), OUString(), OUString(), OUString() ) ); + } + else if ( ( aToken == "circle" ) || ( aToken == "circ" ) ) + { + const Point aCenter( ImpReadCERNCoords( &pStr ) ); + const tools::Long nRadius = ImpReadCERNRadius( &pStr ); + const OUString aURL( ImpReadCERNURL( &pStr ) ); + + maList.emplace_back( new IMapCircleObject( aCenter, nRadius, aURL, OUString(), OUString(), OUString(), OUString() ) ); + } + else if ( ( aToken == "polygon" ) || ( aToken == "poly" ) ) + { + const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr, '(') - 1; + tools::Polygon aPoly( nCount ); + + for ( sal_uInt16 i = 0; i < nCount; i++ ) + aPoly[ i ] = ImpReadCERNCoords( &pStr ); + + const OUString aURL = ImpReadCERNURL( &pStr ); + + maList.emplace_back( new IMapPolygonObject( aPoly, aURL, OUString(), OUString(), OUString(), OUString() ) ); + } +} + +Point ImageMap::ImpReadCERNCoords( const char** ppStr ) +{ + OUStringBuffer aStrX; + OUStringBuffer aStrY; + Point aPt; + char cChar = *(*ppStr)++; + + while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) ) + cChar = *(*ppStr)++; + + if ( NOTEOL( cChar ) ) + { + while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) ) + { + aStrX.append( cChar ); + cChar = *(*ppStr)++; + } + + if ( NOTEOL( cChar ) ) + { + while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) ) + cChar = *(*ppStr)++; + + while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) ) + { + aStrY.append( cChar ); + cChar = *(*ppStr)++; + } + + if ( NOTEOL( cChar ) ) + while( NOTEOL( cChar ) && ( cChar != ')' ) ) + cChar = *(*ppStr)++; + + aPt = Point( o3tl::toInt32(aStrX), o3tl::toInt32(aStrY) ); + } + } + + return aPt; +} + +tools::Long ImageMap::ImpReadCERNRadius( const char** ppStr ) +{ + OUStringBuffer aStr; + char cChar = *(*ppStr)++; + + while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) ) + cChar = *(*ppStr)++; + + if ( NOTEOL( cChar ) ) + { + while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) ) + { + aStr.append( cChar ); + cChar = *(*ppStr)++; + } + } + + return o3tl::toInt32(aStr); +} + +OUString ImageMap::ImpReadCERNURL( const char** ppStr ) +{ + OUString aStr(OUString::createFromAscii(*ppStr)); + + aStr = comphelper::string::strip(aStr, ' '); + aStr = comphelper::string::strip(aStr, '\t'); + + return INetURLObject::GetAbsURL( u"", aStr ); +} + +void ImageMap::ImpReadNCSA( SvStream& rIStm ) +{ + // delete old content + ClearImageMap(); + + OStringBuffer aStr; + while ( rIStm.ReadLine( aStr ) ) + ImpReadNCSALine( aStr ); +} + +void ImageMap::ImpReadNCSALine( std::string_view rLine ) +{ + OString aStr( comphelper::string::stripStart(rLine, ' ') ); + aStr = comphelper::string::stripStart(aStr, '\t'); + aStr = aStr.replaceAll(";"_ostr, ""_ostr); + aStr = aStr.toAsciiLowerCase(); + + const char* pStr = aStr.getStr(); + char cChar = *pStr++; + + // find instruction + OStringBuffer aBuf; + while ((cChar >= 'a') && (cChar <= 'z')) + { + aBuf.append(cChar); + cChar = *pStr++; + } + OString aToken = aBuf.makeStringAndClear(); + + if ( !(NOTEOL( cChar )) ) + return; + + if ( aToken == "rect" ) + { + const OUString aURL( ImpReadNCSAURL( &pStr ) ); + const Point aTopLeft( ImpReadNCSACoords( &pStr ) ); + const Point aBottomRight( ImpReadNCSACoords( &pStr ) ); + const tools::Rectangle aRect( aTopLeft, aBottomRight ); + + maList.emplace_back( new IMapRectangleObject( aRect, aURL, OUString(), OUString(), OUString(), OUString() ) ); + } + else if ( aToken == "circle" ) + { + const OUString aURL( ImpReadNCSAURL( &pStr ) ); + const Point aCenter( ImpReadNCSACoords( &pStr ) ); + const Point aDX( aCenter - ImpReadNCSACoords( &pStr ) ); + tools::Long nRadius = static_cast<tools::Long>(std::hypot( aDX.X(), aDX.Y())); + + maList.emplace_back( new IMapCircleObject( aCenter, nRadius, aURL, OUString(), OUString(), OUString(), OUString() ) ); + } + else if ( aToken == "poly" ) + { + const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr, ',') - 1; + const OUString aURL( ImpReadNCSAURL( &pStr ) ); + tools::Polygon aPoly( nCount ); + + for ( sal_uInt16 i = 0; i < nCount; i++ ) + aPoly[ i ] = ImpReadNCSACoords( &pStr ); + + maList.emplace_back( new IMapPolygonObject( aPoly, aURL, OUString(), OUString(), OUString(), OUString() ) ); + } +} + +OUString ImageMap::ImpReadNCSAURL( const char** ppStr ) +{ + OUStringBuffer aStr; + char cChar = *(*ppStr)++; + + while( NOTEOL( cChar ) && ( ( cChar == ' ' ) || ( cChar == '\t' ) ) ) + cChar = *(*ppStr)++; + + if ( NOTEOL( cChar ) ) + { + while( NOTEOL( cChar ) && ( cChar != ' ' ) && ( cChar != '\t' ) ) + { + aStr.append( cChar ); + cChar = *(*ppStr)++; + } + } + + return INetURLObject::GetAbsURL( u"", aStr.makeStringAndClear() ); +} + +Point ImageMap::ImpReadNCSACoords( const char** ppStr ) +{ + OUStringBuffer aStrX; + OUStringBuffer aStrY; + Point aPt; + char cChar = *(*ppStr)++; + + while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) ) + cChar = *(*ppStr)++; + + if ( NOTEOL( cChar ) ) + { + while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) ) + { + aStrX.append( cChar ); + cChar = *(*ppStr)++; + } + + if ( NOTEOL( cChar ) ) + { + while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) ) + cChar = *(*ppStr)++; + + while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) ) + { + aStrY.append( cChar ); + cChar = *(*ppStr)++; + } + + aPt = Point( o3tl::toInt32(aStrX), o3tl::toInt32(aStrY) ); + } + } + + return aPt; +} + +IMapFormat ImageMap::ImpDetectFormat( SvStream& rIStm ) +{ + sal_uInt64 nPos = rIStm.Tell(); + IMapFormat nRet = IMapFormat::Binary; + char cMagic[6]; + + rIStm.ReadBytes(cMagic, sizeof(cMagic)); + + // if we do not have an internal formats + // we check the format + if ( memcmp( cMagic, IMAPMAGIC, sizeof( cMagic ) ) ) + { + tools::Long nCount = 128; + + rIStm.Seek( nPos ); + OString aStr; + while ( rIStm.ReadLine( aStr ) && nCount-- ) + { + aStr = aStr.toAsciiLowerCase(); + + if ( (aStr.indexOf("rect") != -1) || + (aStr.indexOf("circ") != -1) || + (aStr.indexOf("poly") != -1) ) + { + if ( ( aStr.indexOf('(') != -1 ) && + ( aStr.indexOf(')') != -1 ) ) + { + nRet = IMapFormat::CERN; + } + else + nRet = IMapFormat::NCSA; + + break; + } + } + } + + rIStm.Seek( nPos ); + + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |