diff options
Diffstat (limited to 'sdext/source/pdfimport/tree/style.cxx')
-rw-r--r-- | sdext/source/pdfimport/tree/style.cxx | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/sdext/source/pdfimport/tree/style.cxx b/sdext/source/pdfimport/tree/style.cxx new file mode 100644 index 000000000000..c4068def4307 --- /dev/null +++ b/sdext/source/pdfimport/tree/style.cxx @@ -0,0 +1,262 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sdext.hxx" + +#include "style.hxx" +#include "genericelements.hxx" +#include "xmlemitter.hxx" +#include "pdfiprocessor.hxx" +#include <rtl/ustrbuf.hxx> + +#include <algorithm> + +using namespace pdfi; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +#define USTR(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) ) + +StyleContainer::StyleContainer() : + m_nNextId( 1 ) +{ +} + +sal_Int32 StyleContainer::impl_getStyleId( const Style& rStyle, bool bSubStyle ) +{ + sal_Int32 nRet = -1; + + // construct HashedStyle to find or insert + HashedStyle aSearchStyle; + aSearchStyle.Name = rStyle.Name; + aSearchStyle.Properties = rStyle.Properties; + aSearchStyle.Contents = rStyle.Contents; + aSearchStyle.ContainedElement = rStyle.ContainedElement; + for( unsigned int n = 0; n < rStyle.SubStyles.size(); ++n ) + aSearchStyle.SubStyles.push_back( impl_getStyleId( *rStyle.SubStyles[n], true ) ); + + boost::unordered_map< HashedStyle, sal_Int32, StyleHash >::iterator it = + m_aStyleToId.find( aSearchStyle ); + + if( it != m_aStyleToId.end() ) + { + nRet = it->second; + HashedStyle& rFound = m_aIdToStyle[ nRet ]; + // increase refcount on this style + rFound.RefCount++; + if( ! bSubStyle ) + rFound.IsSubStyle = false; + } + else + { + nRet = m_nNextId++; + // create new style + HashedStyle& rNew = m_aIdToStyle[ nRet ]; + rNew = aSearchStyle; + rNew.RefCount = 1; + rNew.IsSubStyle = bSubStyle; + // fill the style hash to find the id + m_aStyleToId[ rNew ] = nRet; + } + return nRet; +} + +sal_Int32 StyleContainer::getStandardStyleId( const rtl::OString& rName ) +{ + PropertyMap aProps; + aProps[ USTR( "style:family" ) ] = rtl::OStringToOUString( rName, RTL_TEXTENCODING_UTF8 ); + aProps[ USTR( "style:name" ) ] = USTR( "standard" ); + + Style aStyle( "style:style", aProps ); + return getStyleId( aStyle ); +} + +const PropertyMap* StyleContainer::getProperties( sal_Int32 nStyleId ) const +{ + boost::unordered_map< sal_Int32, HashedStyle >::const_iterator it = + m_aIdToStyle.find( nStyleId ); + return it != m_aIdToStyle.end() ? &(it->second.Properties) : NULL; +} + +sal_Int32 StyleContainer::setProperties( sal_Int32 nStyleId, const PropertyMap& rNewProps ) +{ + sal_Int32 nRet = -1; + boost::unordered_map< sal_Int32, HashedStyle >::iterator it = + m_aIdToStyle.find( nStyleId ); + if( it != m_aIdToStyle.end() ) + { + if( it->second.RefCount == 1 ) + { + nRet = it->first; + // erase old hash to id mapping + m_aStyleToId.erase( it->second ); + // change properties + it->second.Properties = rNewProps; + // fill in new hash to id mapping + m_aStyleToId[ it->second ] = nRet; + } + else + { + // decrease refcound on old instance + it->second.RefCount--; + // acquire new HashedStyle + HashedStyle aSearchStyle; + aSearchStyle.Name = it->second.Name; + aSearchStyle.Properties = rNewProps; + aSearchStyle.Contents = it->second.Contents; + aSearchStyle.ContainedElement = it->second.ContainedElement; + aSearchStyle.SubStyles = it->second.SubStyles; + aSearchStyle.IsSubStyle = it->second.IsSubStyle; + + // find out whether this new style already exists + boost::unordered_map< HashedStyle, sal_Int32, StyleHash >::iterator new_it = + m_aStyleToId.find( aSearchStyle ); + if( new_it != m_aStyleToId.end() ) + { + nRet = new_it->second; + m_aIdToStyle[ nRet ].RefCount++; + } + else + { + nRet = m_nNextId++; + // create new style with new id + HashedStyle& rNew = m_aIdToStyle[ nRet ]; + rNew = aSearchStyle; + rNew.RefCount = 1; + // fill style to id hash + m_aStyleToId[ aSearchStyle ] = nRet; + } + } + } + return nRet; +} + +OUString StyleContainer::getStyleName( sal_Int32 nStyle ) const +{ + OUStringBuffer aRet( 64 ); + + boost::unordered_map< sal_Int32, HashedStyle >::const_iterator style_it = + m_aIdToStyle.find( nStyle ); + if( style_it != m_aIdToStyle.end() ) + { + const HashedStyle& rStyle = style_it->second; + + PropertyMap::const_iterator name_it = rStyle.Properties.find( USTR("style:name") ); + if( name_it != rStyle.Properties.end() ) + aRet.append( name_it->second ); + else + { + PropertyMap::const_iterator fam_it = rStyle.Properties.find( USTR("style:family" ) ); + OUString aStyleName; + if( fam_it != rStyle.Properties.end() ) + { + aStyleName = fam_it->second; + } + else + aStyleName = OStringToOUString( rStyle.Name, RTL_TEXTENCODING_ASCII_US ); + sal_Int32 nIndex = aStyleName.lastIndexOf( ':' ); + aRet.append( aStyleName.copy( nIndex+1 ) ); + aRet.append( nStyle ); + } + } + else + { + aRet.appendAscii( "invalid style id " ); + aRet.append( nStyle ); + } + + return aRet.makeStringAndClear(); +} + +void StyleContainer::impl_emitStyle( sal_Int32 nStyleId, + EmitContext& rContext, + ElementTreeVisitor& rContainedElemVisitor ) +{ + boost::unordered_map< sal_Int32, HashedStyle >::const_iterator it = m_aIdToStyle.find( nStyleId ); + if( it != m_aIdToStyle.end() ) + { + const HashedStyle& rStyle = it->second; + PropertyMap aProps( rStyle.Properties ); + if( !rStyle.IsSubStyle ) + aProps[ USTR( "style:name" ) ] = getStyleName( nStyleId ); + rContext.rEmitter.beginTag( rStyle.Name.getStr(), aProps ); + + for( unsigned int n = 0; n < rStyle.SubStyles.size(); ++n ) + impl_emitStyle( rStyle.SubStyles[n], rContext, rContainedElemVisitor ); + if( rStyle.Contents.getLength() ) + rContext.rEmitter.write( rStyle.Contents ); + if( rStyle.ContainedElement ) + rStyle.ContainedElement->visitedBy( rContainedElemVisitor, + std::list<Element*>::iterator() ); + rContext.rEmitter.endTag( rStyle.Name.getStr() ); + } +} + +void StyleContainer::emit( EmitContext& rContext, + ElementTreeVisitor& rContainedElemVisitor ) +{ + std::vector< sal_Int32 > aMasterPageSection, aAutomaticStyleSection, aOfficeStyleSection; + for( boost::unordered_map< sal_Int32, HashedStyle >::iterator it = m_aIdToStyle.begin(); + it != m_aIdToStyle.end(); ++it ) + { + if( ! it->second.IsSubStyle ) + { + if( it->second.Name.equals( "style:master-page" ) ) + aMasterPageSection.push_back( it->first ); + else if( getStyleName( it->first ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "standard" ) ) ) + aOfficeStyleSection.push_back( it->first ); + else + aAutomaticStyleSection.push_back( it->first ); + } + } + + if( ! aMasterPageSection.empty() ) + std::stable_sort( aMasterPageSection.begin(), aMasterPageSection.end(), StyleIdNameSort(&m_aIdToStyle) ); + if( ! aAutomaticStyleSection.empty() ) + std::stable_sort( aAutomaticStyleSection.begin(), aAutomaticStyleSection.end(), StyleIdNameSort(&m_aIdToStyle) ); + if( ! aOfficeStyleSection.empty() ) + std::stable_sort( aOfficeStyleSection.begin(), aOfficeStyleSection.end(), StyleIdNameSort(&m_aIdToStyle) ); + + int n = 0, nElements = 0; + rContext.rEmitter.beginTag( "office:styles", PropertyMap() ); + for( n = 0, nElements = aOfficeStyleSection.size(); n < nElements; n++ ) + impl_emitStyle( aOfficeStyleSection[n], rContext, rContainedElemVisitor ); + rContext.rEmitter.endTag( "office:styles" ); + rContext.rEmitter.beginTag( "office:automatic-styles", PropertyMap() ); + for( n = 0, nElements = aAutomaticStyleSection.size(); n < nElements; n++ ) + impl_emitStyle( aAutomaticStyleSection[n], rContext, rContainedElemVisitor ); + rContext.rEmitter.endTag( "office:automatic-styles" ); + rContext.rEmitter.beginTag( "office:master-styles", PropertyMap() ); + for( n = 0, nElements = aMasterPageSection.size(); n < nElements; n++ ) + impl_emitStyle( aMasterPageSection[n], rContext, rContainedElemVisitor ); + rContext.rEmitter.endTag( "office:master-styles" ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |