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_sdext.hxx" 30 31 #include "style.hxx" 32 #include "genericelements.hxx" 33 #include "xmlemitter.hxx" 34 #include "pdfiprocessor.hxx" 35 #include <rtl/ustrbuf.hxx> 36 37 #include <algorithm> 38 39 using namespace rtl; 40 using namespace pdfi; 41 42 #define USTR(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) ) 43 44 StyleContainer::StyleContainer() : 45 m_nNextId( 1 ) 46 { 47 } 48 49 sal_Int32 StyleContainer::impl_getStyleId( const Style& rStyle, bool bSubStyle ) 50 { 51 sal_Int32 nRet = -1; 52 53 // construct HashedStyle to find or insert 54 HashedStyle aSearchStyle; 55 aSearchStyle.Name = rStyle.Name; 56 aSearchStyle.Properties = rStyle.Properties; 57 aSearchStyle.Contents = rStyle.Contents; 58 aSearchStyle.ContainedElement = rStyle.ContainedElement; 59 for( unsigned int n = 0; n < rStyle.SubStyles.size(); ++n ) 60 aSearchStyle.SubStyles.push_back( impl_getStyleId( *rStyle.SubStyles[n], true ) ); 61 62 std::hash_map< HashedStyle, sal_Int32, StyleHash >::iterator it = 63 m_aStyleToId.find( aSearchStyle ); 64 65 if( it != m_aStyleToId.end() ) 66 { 67 nRet = it->second; 68 HashedStyle& rFound = m_aIdToStyle[ nRet ]; 69 // increase refcount on this style 70 rFound.RefCount++; 71 if( ! bSubStyle ) 72 rFound.IsSubStyle = false; 73 } 74 else 75 { 76 nRet = m_nNextId++; 77 // create new style 78 HashedStyle& rNew = m_aIdToStyle[ nRet ]; 79 rNew = aSearchStyle; 80 rNew.RefCount = 1; 81 rNew.IsSubStyle = bSubStyle; 82 // fill the style hash to find the id 83 m_aStyleToId[ rNew ] = nRet; 84 } 85 return nRet; 86 } 87 88 sal_Int32 StyleContainer::getStandardStyleId( const rtl::OString& rName ) 89 { 90 PropertyMap aProps; 91 aProps[ USTR( "style:family" ) ] = rtl::OStringToOUString( rName, RTL_TEXTENCODING_UTF8 ); 92 aProps[ USTR( "style:name" ) ] = USTR( "standard" ); 93 94 Style aStyle( "style:style", aProps ); 95 return getStyleId( aStyle ); 96 } 97 98 const PropertyMap* StyleContainer::getProperties( sal_Int32 nStyleId ) const 99 { 100 std::hash_map< sal_Int32, HashedStyle >::const_iterator it = 101 m_aIdToStyle.find( nStyleId ); 102 return it != m_aIdToStyle.end() ? &(it->second.Properties) : NULL; 103 } 104 105 sal_Int32 StyleContainer::setProperties( sal_Int32 nStyleId, const PropertyMap& rNewProps ) 106 { 107 sal_Int32 nRet = -1; 108 std::hash_map< sal_Int32, HashedStyle >::iterator it = 109 m_aIdToStyle.find( nStyleId ); 110 if( it != m_aIdToStyle.end() ) 111 { 112 if( it->second.RefCount == 1 ) 113 { 114 nRet = it->first; 115 // erase old hash to id mapping 116 m_aStyleToId.erase( it->second ); 117 // change properties 118 it->second.Properties = rNewProps; 119 // fill in new hash to id mapping 120 m_aStyleToId[ it->second ] = nRet; 121 } 122 else 123 { 124 // decrease refcound on old instance 125 it->second.RefCount--; 126 // acquire new HashedStyle 127 HashedStyle aSearchStyle; 128 aSearchStyle.Name = it->second.Name; 129 aSearchStyle.Properties = rNewProps; 130 aSearchStyle.Contents = it->second.Contents; 131 aSearchStyle.ContainedElement = it->second.ContainedElement; 132 aSearchStyle.SubStyles = it->second.SubStyles; 133 aSearchStyle.IsSubStyle = it->second.IsSubStyle; 134 135 // find out whether this new style already exists 136 std::hash_map< HashedStyle, sal_Int32, StyleHash >::iterator new_it = 137 m_aStyleToId.find( aSearchStyle ); 138 if( new_it != m_aStyleToId.end() ) 139 { 140 nRet = new_it->second; 141 m_aIdToStyle[ nRet ].RefCount++; 142 } 143 else 144 { 145 nRet = m_nNextId++; 146 // create new style with new id 147 HashedStyle& rNew = m_aIdToStyle[ nRet ]; 148 rNew = aSearchStyle; 149 rNew.RefCount = 1; 150 // fill style to id hash 151 m_aStyleToId[ aSearchStyle ] = nRet; 152 } 153 } 154 } 155 return nRet; 156 } 157 158 OUString StyleContainer::getStyleName( sal_Int32 nStyle ) const 159 { 160 OUStringBuffer aRet( 64 ); 161 162 std::hash_map< sal_Int32, HashedStyle >::const_iterator style_it = 163 m_aIdToStyle.find( nStyle ); 164 if( style_it != m_aIdToStyle.end() ) 165 { 166 const HashedStyle& rStyle = style_it->second; 167 168 PropertyMap::const_iterator name_it = rStyle.Properties.find( USTR("style:name") ); 169 if( name_it != rStyle.Properties.end() ) 170 aRet.append( name_it->second ); 171 else 172 { 173 PropertyMap::const_iterator fam_it = rStyle.Properties.find( USTR("style:family" ) ); 174 OUString aStyleName; 175 if( fam_it != rStyle.Properties.end() ) 176 { 177 aStyleName = fam_it->second; 178 } 179 else 180 aStyleName = OStringToOUString( rStyle.Name, RTL_TEXTENCODING_ASCII_US ); 181 sal_Int32 nIndex = aStyleName.lastIndexOf( ':' ); 182 aRet.append( aStyleName.copy( nIndex+1 ) ); 183 aRet.append( nStyle ); 184 } 185 } 186 else 187 { 188 aRet.appendAscii( "invalid style id " ); 189 aRet.append( nStyle ); 190 } 191 192 return aRet.makeStringAndClear(); 193 } 194 195 void StyleContainer::impl_emitStyle( sal_Int32 nStyleId, 196 EmitContext& rContext, 197 ElementTreeVisitor& rContainedElemVisitor ) 198 { 199 std::hash_map< sal_Int32, HashedStyle >::const_iterator it = m_aIdToStyle.find( nStyleId ); 200 if( it != m_aIdToStyle.end() ) 201 { 202 const HashedStyle& rStyle = it->second; 203 PropertyMap aProps( rStyle.Properties ); 204 if( !rStyle.IsSubStyle ) 205 aProps[ USTR( "style:name" ) ] = getStyleName( nStyleId ); 206 rContext.rEmitter.beginTag( rStyle.Name.getStr(), aProps ); 207 208 for( unsigned int n = 0; n < rStyle.SubStyles.size(); ++n ) 209 impl_emitStyle( rStyle.SubStyles[n], rContext, rContainedElemVisitor ); 210 if( rStyle.Contents ) 211 rContext.rEmitter.write( rStyle.Contents ); 212 if( rStyle.ContainedElement ) 213 rStyle.ContainedElement->visitedBy( rContainedElemVisitor, 214 std::list<Element*>::iterator() ); 215 rContext.rEmitter.endTag( rStyle.Name.getStr() ); 216 } 217 } 218 219 void StyleContainer::emit( EmitContext& rContext, 220 ElementTreeVisitor& rContainedElemVisitor ) 221 { 222 std::vector< sal_Int32 > aMasterPageSection, aAutomaticStyleSection, aOfficeStyleSection; 223 for( std::hash_map< sal_Int32, HashedStyle >::iterator it = m_aIdToStyle.begin(); 224 it != m_aIdToStyle.end(); ++it ) 225 { 226 if( ! it->second.IsSubStyle ) 227 { 228 if( it->second.Name.equals( "style:master-page" ) ) 229 aMasterPageSection.push_back( it->first ); 230 else if( getStyleName( it->first ).equalsAscii( "standard" ) ) 231 aOfficeStyleSection.push_back( it->first ); 232 else 233 aAutomaticStyleSection.push_back( it->first ); 234 } 235 } 236 237 if( ! aMasterPageSection.empty() ) 238 std::stable_sort( aMasterPageSection.begin(), aMasterPageSection.end(), StyleIdNameSort(&m_aIdToStyle) ); 239 if( ! aAutomaticStyleSection.empty() ) 240 std::stable_sort( aAutomaticStyleSection.begin(), aAutomaticStyleSection.end(), StyleIdNameSort(&m_aIdToStyle) ); 241 if( ! aOfficeStyleSection.empty() ) 242 std::stable_sort( aOfficeStyleSection.begin(), aOfficeStyleSection.end(), StyleIdNameSort(&m_aIdToStyle) ); 243 244 int n = 0, nElements = 0; 245 rContext.rEmitter.beginTag( "office:styles", PropertyMap() ); 246 for( n = 0, nElements = aOfficeStyleSection.size(); n < nElements; n++ ) 247 impl_emitStyle( aOfficeStyleSection[n], rContext, rContainedElemVisitor ); 248 rContext.rEmitter.endTag( "office:styles" ); 249 rContext.rEmitter.beginTag( "office:automatic-styles", PropertyMap() ); 250 for( n = 0, nElements = aAutomaticStyleSection.size(); n < nElements; n++ ) 251 impl_emitStyle( aAutomaticStyleSection[n], rContext, rContainedElemVisitor ); 252 rContext.rEmitter.endTag( "office:automatic-styles" ); 253 rContext.rEmitter.beginTag( "office:master-styles", PropertyMap() ); 254 for( n = 0, nElements = aMasterPageSection.size(); n < nElements; n++ ) 255 impl_emitStyle( aMasterPageSection[n], rContext, rContainedElemVisitor ); 256 rContext.rEmitter.endTag( "office:master-styles" ); 257 } 258