1*c142477cSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*c142477cSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*c142477cSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*c142477cSAndrew Rist * distributed with this work for additional information 6*c142477cSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*c142477cSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*c142477cSAndrew Rist * "License"); you may not use this file except in compliance 9*c142477cSAndrew Rist * with the License. You may obtain a copy of the License at 10*c142477cSAndrew Rist * 11*c142477cSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*c142477cSAndrew Rist * 13*c142477cSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*c142477cSAndrew Rist * software distributed under the License is distributed on an 15*c142477cSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*c142477cSAndrew Rist * KIND, either express or implied. See the License for the 17*c142477cSAndrew Rist * specific language governing permissions and limitations 18*c142477cSAndrew Rist * under the License. 19*c142477cSAndrew Rist * 20*c142477cSAndrew Rist *************************************************************/ 21*c142477cSAndrew Rist 22*c142477cSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_sdext.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include "style.hxx" 28cdf0e10cSrcweir #include "genericelements.hxx" 29cdf0e10cSrcweir #include "xmlemitter.hxx" 30cdf0e10cSrcweir #include "pdfiprocessor.hxx" 31cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 32cdf0e10cSrcweir 33cdf0e10cSrcweir #include <algorithm> 34cdf0e10cSrcweir 35cdf0e10cSrcweir using namespace rtl; 36cdf0e10cSrcweir using namespace pdfi; 37cdf0e10cSrcweir 38cdf0e10cSrcweir #define USTR(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) ) 39cdf0e10cSrcweir 40cdf0e10cSrcweir StyleContainer::StyleContainer() : 41cdf0e10cSrcweir m_nNextId( 1 ) 42cdf0e10cSrcweir { 43cdf0e10cSrcweir } 44cdf0e10cSrcweir 45cdf0e10cSrcweir sal_Int32 StyleContainer::impl_getStyleId( const Style& rStyle, bool bSubStyle ) 46cdf0e10cSrcweir { 47cdf0e10cSrcweir sal_Int32 nRet = -1; 48cdf0e10cSrcweir 49cdf0e10cSrcweir // construct HashedStyle to find or insert 50cdf0e10cSrcweir HashedStyle aSearchStyle; 51cdf0e10cSrcweir aSearchStyle.Name = rStyle.Name; 52cdf0e10cSrcweir aSearchStyle.Properties = rStyle.Properties; 53cdf0e10cSrcweir aSearchStyle.Contents = rStyle.Contents; 54cdf0e10cSrcweir aSearchStyle.ContainedElement = rStyle.ContainedElement; 55cdf0e10cSrcweir for( unsigned int n = 0; n < rStyle.SubStyles.size(); ++n ) 56cdf0e10cSrcweir aSearchStyle.SubStyles.push_back( impl_getStyleId( *rStyle.SubStyles[n], true ) ); 57cdf0e10cSrcweir 58cdf0e10cSrcweir std::hash_map< HashedStyle, sal_Int32, StyleHash >::iterator it = 59cdf0e10cSrcweir m_aStyleToId.find( aSearchStyle ); 60cdf0e10cSrcweir 61cdf0e10cSrcweir if( it != m_aStyleToId.end() ) 62cdf0e10cSrcweir { 63cdf0e10cSrcweir nRet = it->second; 64cdf0e10cSrcweir HashedStyle& rFound = m_aIdToStyle[ nRet ]; 65cdf0e10cSrcweir // increase refcount on this style 66cdf0e10cSrcweir rFound.RefCount++; 67cdf0e10cSrcweir if( ! bSubStyle ) 68cdf0e10cSrcweir rFound.IsSubStyle = false; 69cdf0e10cSrcweir } 70cdf0e10cSrcweir else 71cdf0e10cSrcweir { 72cdf0e10cSrcweir nRet = m_nNextId++; 73cdf0e10cSrcweir // create new style 74cdf0e10cSrcweir HashedStyle& rNew = m_aIdToStyle[ nRet ]; 75cdf0e10cSrcweir rNew = aSearchStyle; 76cdf0e10cSrcweir rNew.RefCount = 1; 77cdf0e10cSrcweir rNew.IsSubStyle = bSubStyle; 78cdf0e10cSrcweir // fill the style hash to find the id 79cdf0e10cSrcweir m_aStyleToId[ rNew ] = nRet; 80cdf0e10cSrcweir } 81cdf0e10cSrcweir return nRet; 82cdf0e10cSrcweir } 83cdf0e10cSrcweir 84cdf0e10cSrcweir sal_Int32 StyleContainer::getStandardStyleId( const rtl::OString& rName ) 85cdf0e10cSrcweir { 86cdf0e10cSrcweir PropertyMap aProps; 87cdf0e10cSrcweir aProps[ USTR( "style:family" ) ] = rtl::OStringToOUString( rName, RTL_TEXTENCODING_UTF8 ); 88cdf0e10cSrcweir aProps[ USTR( "style:name" ) ] = USTR( "standard" ); 89cdf0e10cSrcweir 90cdf0e10cSrcweir Style aStyle( "style:style", aProps ); 91cdf0e10cSrcweir return getStyleId( aStyle ); 92cdf0e10cSrcweir } 93cdf0e10cSrcweir 94cdf0e10cSrcweir const PropertyMap* StyleContainer::getProperties( sal_Int32 nStyleId ) const 95cdf0e10cSrcweir { 96cdf0e10cSrcweir std::hash_map< sal_Int32, HashedStyle >::const_iterator it = 97cdf0e10cSrcweir m_aIdToStyle.find( nStyleId ); 98cdf0e10cSrcweir return it != m_aIdToStyle.end() ? &(it->second.Properties) : NULL; 99cdf0e10cSrcweir } 100cdf0e10cSrcweir 101cdf0e10cSrcweir sal_Int32 StyleContainer::setProperties( sal_Int32 nStyleId, const PropertyMap& rNewProps ) 102cdf0e10cSrcweir { 103cdf0e10cSrcweir sal_Int32 nRet = -1; 104cdf0e10cSrcweir std::hash_map< sal_Int32, HashedStyle >::iterator it = 105cdf0e10cSrcweir m_aIdToStyle.find( nStyleId ); 106cdf0e10cSrcweir if( it != m_aIdToStyle.end() ) 107cdf0e10cSrcweir { 108cdf0e10cSrcweir if( it->second.RefCount == 1 ) 109cdf0e10cSrcweir { 110cdf0e10cSrcweir nRet = it->first; 111cdf0e10cSrcweir // erase old hash to id mapping 112cdf0e10cSrcweir m_aStyleToId.erase( it->second ); 113cdf0e10cSrcweir // change properties 114cdf0e10cSrcweir it->second.Properties = rNewProps; 115cdf0e10cSrcweir // fill in new hash to id mapping 116cdf0e10cSrcweir m_aStyleToId[ it->second ] = nRet; 117cdf0e10cSrcweir } 118cdf0e10cSrcweir else 119cdf0e10cSrcweir { 120cdf0e10cSrcweir // decrease refcound on old instance 121cdf0e10cSrcweir it->second.RefCount--; 122cdf0e10cSrcweir // acquire new HashedStyle 123cdf0e10cSrcweir HashedStyle aSearchStyle; 124cdf0e10cSrcweir aSearchStyle.Name = it->second.Name; 125cdf0e10cSrcweir aSearchStyle.Properties = rNewProps; 126cdf0e10cSrcweir aSearchStyle.Contents = it->second.Contents; 127cdf0e10cSrcweir aSearchStyle.ContainedElement = it->second.ContainedElement; 128cdf0e10cSrcweir aSearchStyle.SubStyles = it->second.SubStyles; 129cdf0e10cSrcweir aSearchStyle.IsSubStyle = it->second.IsSubStyle; 130cdf0e10cSrcweir 131cdf0e10cSrcweir // find out whether this new style already exists 132cdf0e10cSrcweir std::hash_map< HashedStyle, sal_Int32, StyleHash >::iterator new_it = 133cdf0e10cSrcweir m_aStyleToId.find( aSearchStyle ); 134cdf0e10cSrcweir if( new_it != m_aStyleToId.end() ) 135cdf0e10cSrcweir { 136cdf0e10cSrcweir nRet = new_it->second; 137cdf0e10cSrcweir m_aIdToStyle[ nRet ].RefCount++; 138cdf0e10cSrcweir } 139cdf0e10cSrcweir else 140cdf0e10cSrcweir { 141cdf0e10cSrcweir nRet = m_nNextId++; 142cdf0e10cSrcweir // create new style with new id 143cdf0e10cSrcweir HashedStyle& rNew = m_aIdToStyle[ nRet ]; 144cdf0e10cSrcweir rNew = aSearchStyle; 145cdf0e10cSrcweir rNew.RefCount = 1; 146cdf0e10cSrcweir // fill style to id hash 147cdf0e10cSrcweir m_aStyleToId[ aSearchStyle ] = nRet; 148cdf0e10cSrcweir } 149cdf0e10cSrcweir } 150cdf0e10cSrcweir } 151cdf0e10cSrcweir return nRet; 152cdf0e10cSrcweir } 153cdf0e10cSrcweir 154cdf0e10cSrcweir OUString StyleContainer::getStyleName( sal_Int32 nStyle ) const 155cdf0e10cSrcweir { 156cdf0e10cSrcweir OUStringBuffer aRet( 64 ); 157cdf0e10cSrcweir 158cdf0e10cSrcweir std::hash_map< sal_Int32, HashedStyle >::const_iterator style_it = 159cdf0e10cSrcweir m_aIdToStyle.find( nStyle ); 160cdf0e10cSrcweir if( style_it != m_aIdToStyle.end() ) 161cdf0e10cSrcweir { 162cdf0e10cSrcweir const HashedStyle& rStyle = style_it->second; 163cdf0e10cSrcweir 164cdf0e10cSrcweir PropertyMap::const_iterator name_it = rStyle.Properties.find( USTR("style:name") ); 165cdf0e10cSrcweir if( name_it != rStyle.Properties.end() ) 166cdf0e10cSrcweir aRet.append( name_it->second ); 167cdf0e10cSrcweir else 168cdf0e10cSrcweir { 169cdf0e10cSrcweir PropertyMap::const_iterator fam_it = rStyle.Properties.find( USTR("style:family" ) ); 170cdf0e10cSrcweir OUString aStyleName; 171cdf0e10cSrcweir if( fam_it != rStyle.Properties.end() ) 172cdf0e10cSrcweir { 173cdf0e10cSrcweir aStyleName = fam_it->second; 174cdf0e10cSrcweir } 175cdf0e10cSrcweir else 176cdf0e10cSrcweir aStyleName = OStringToOUString( rStyle.Name, RTL_TEXTENCODING_ASCII_US ); 177cdf0e10cSrcweir sal_Int32 nIndex = aStyleName.lastIndexOf( ':' ); 178cdf0e10cSrcweir aRet.append( aStyleName.copy( nIndex+1 ) ); 179cdf0e10cSrcweir aRet.append( nStyle ); 180cdf0e10cSrcweir } 181cdf0e10cSrcweir } 182cdf0e10cSrcweir else 183cdf0e10cSrcweir { 184cdf0e10cSrcweir aRet.appendAscii( "invalid style id " ); 185cdf0e10cSrcweir aRet.append( nStyle ); 186cdf0e10cSrcweir } 187cdf0e10cSrcweir 188cdf0e10cSrcweir return aRet.makeStringAndClear(); 189cdf0e10cSrcweir } 190cdf0e10cSrcweir 191cdf0e10cSrcweir void StyleContainer::impl_emitStyle( sal_Int32 nStyleId, 192cdf0e10cSrcweir EmitContext& rContext, 193cdf0e10cSrcweir ElementTreeVisitor& rContainedElemVisitor ) 194cdf0e10cSrcweir { 195cdf0e10cSrcweir std::hash_map< sal_Int32, HashedStyle >::const_iterator it = m_aIdToStyle.find( nStyleId ); 196cdf0e10cSrcweir if( it != m_aIdToStyle.end() ) 197cdf0e10cSrcweir { 198cdf0e10cSrcweir const HashedStyle& rStyle = it->second; 199cdf0e10cSrcweir PropertyMap aProps( rStyle.Properties ); 200cdf0e10cSrcweir if( !rStyle.IsSubStyle ) 201cdf0e10cSrcweir aProps[ USTR( "style:name" ) ] = getStyleName( nStyleId ); 202cdf0e10cSrcweir rContext.rEmitter.beginTag( rStyle.Name.getStr(), aProps ); 203cdf0e10cSrcweir 204cdf0e10cSrcweir for( unsigned int n = 0; n < rStyle.SubStyles.size(); ++n ) 205cdf0e10cSrcweir impl_emitStyle( rStyle.SubStyles[n], rContext, rContainedElemVisitor ); 206cdf0e10cSrcweir if( rStyle.Contents ) 207cdf0e10cSrcweir rContext.rEmitter.write( rStyle.Contents ); 208cdf0e10cSrcweir if( rStyle.ContainedElement ) 209cdf0e10cSrcweir rStyle.ContainedElement->visitedBy( rContainedElemVisitor, 210cdf0e10cSrcweir std::list<Element*>::iterator() ); 211cdf0e10cSrcweir rContext.rEmitter.endTag( rStyle.Name.getStr() ); 212cdf0e10cSrcweir } 213cdf0e10cSrcweir } 214cdf0e10cSrcweir 215cdf0e10cSrcweir void StyleContainer::emit( EmitContext& rContext, 216cdf0e10cSrcweir ElementTreeVisitor& rContainedElemVisitor ) 217cdf0e10cSrcweir { 218cdf0e10cSrcweir std::vector< sal_Int32 > aMasterPageSection, aAutomaticStyleSection, aOfficeStyleSection; 219cdf0e10cSrcweir for( std::hash_map< sal_Int32, HashedStyle >::iterator it = m_aIdToStyle.begin(); 220cdf0e10cSrcweir it != m_aIdToStyle.end(); ++it ) 221cdf0e10cSrcweir { 222cdf0e10cSrcweir if( ! it->second.IsSubStyle ) 223cdf0e10cSrcweir { 224cdf0e10cSrcweir if( it->second.Name.equals( "style:master-page" ) ) 225cdf0e10cSrcweir aMasterPageSection.push_back( it->first ); 226cdf0e10cSrcweir else if( getStyleName( it->first ).equalsAscii( "standard" ) ) 227cdf0e10cSrcweir aOfficeStyleSection.push_back( it->first ); 228cdf0e10cSrcweir else 229cdf0e10cSrcweir aAutomaticStyleSection.push_back( it->first ); 230cdf0e10cSrcweir } 231cdf0e10cSrcweir } 232cdf0e10cSrcweir 233cdf0e10cSrcweir if( ! aMasterPageSection.empty() ) 234cdf0e10cSrcweir std::stable_sort( aMasterPageSection.begin(), aMasterPageSection.end(), StyleIdNameSort(&m_aIdToStyle) ); 235cdf0e10cSrcweir if( ! aAutomaticStyleSection.empty() ) 236cdf0e10cSrcweir std::stable_sort( aAutomaticStyleSection.begin(), aAutomaticStyleSection.end(), StyleIdNameSort(&m_aIdToStyle) ); 237cdf0e10cSrcweir if( ! aOfficeStyleSection.empty() ) 238cdf0e10cSrcweir std::stable_sort( aOfficeStyleSection.begin(), aOfficeStyleSection.end(), StyleIdNameSort(&m_aIdToStyle) ); 239cdf0e10cSrcweir 240cdf0e10cSrcweir int n = 0, nElements = 0; 241cdf0e10cSrcweir rContext.rEmitter.beginTag( "office:styles", PropertyMap() ); 242cdf0e10cSrcweir for( n = 0, nElements = aOfficeStyleSection.size(); n < nElements; n++ ) 243cdf0e10cSrcweir impl_emitStyle( aOfficeStyleSection[n], rContext, rContainedElemVisitor ); 244cdf0e10cSrcweir rContext.rEmitter.endTag( "office:styles" ); 245cdf0e10cSrcweir rContext.rEmitter.beginTag( "office:automatic-styles", PropertyMap() ); 246cdf0e10cSrcweir for( n = 0, nElements = aAutomaticStyleSection.size(); n < nElements; n++ ) 247cdf0e10cSrcweir impl_emitStyle( aAutomaticStyleSection[n], rContext, rContainedElemVisitor ); 248cdf0e10cSrcweir rContext.rEmitter.endTag( "office:automatic-styles" ); 249cdf0e10cSrcweir rContext.rEmitter.beginTag( "office:master-styles", PropertyMap() ); 250cdf0e10cSrcweir for( n = 0, nElements = aMasterPageSection.size(); n < nElements; n++ ) 251cdf0e10cSrcweir impl_emitStyle( aMasterPageSection[n], rContext, rContainedElemVisitor ); 252cdf0e10cSrcweir rContext.rEmitter.endTag( "office:master-styles" ); 253cdf0e10cSrcweir } 254