1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: style.cxx,v $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_sdext.hxx"
36 #include "genericelements.hxx"
37 #include "xmlemitter.hxx"
38 #include "pdfiprocessor.hxx"
39 #include <rtl/ustrbuf.hxx>
46 #define USTR(x) rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
48 StyleContainer::StyleContainer() :
53 sal_Int32
StyleContainer::impl_getStyleId( const Style
& rStyle
, bool bSubStyle
)
57 // construct HashedStyle to find or insert
58 HashedStyle aSearchStyle
;
59 aSearchStyle
.Name
= rStyle
.Name
;
60 aSearchStyle
.Properties
= rStyle
.Properties
;
61 aSearchStyle
.Contents
= rStyle
.Contents
;
62 aSearchStyle
.ContainedElement
= rStyle
.ContainedElement
;
63 for( unsigned int n
= 0; n
< rStyle
.SubStyles
.size(); ++n
)
64 aSearchStyle
.SubStyles
.push_back( impl_getStyleId( *rStyle
.SubStyles
[n
], true ) );
66 std::hash_map
< HashedStyle
, sal_Int32
, StyleHash
>::iterator it
=
67 m_aStyleToId
.find( aSearchStyle
);
69 if( it
!= m_aStyleToId
.end() )
72 HashedStyle
& rFound
= m_aIdToStyle
[ nRet
];
73 // increase refcount on this style
76 rFound
.IsSubStyle
= false;
82 HashedStyle
& rNew
= m_aIdToStyle
[ nRet
];
85 rNew
.IsSubStyle
= bSubStyle
;
86 // fill the style hash to find the id
87 m_aStyleToId
[ rNew
] = nRet
;
92 sal_Int32
StyleContainer::getStandardStyleId( const rtl::OString
& rName
)
95 aProps
[ USTR( "style:family" ) ] = rtl::OStringToOUString( rName
, RTL_TEXTENCODING_UTF8
);
96 aProps
[ USTR( "style:name" ) ] = USTR( "standard" );
98 Style
aStyle( "style:style", aProps
);
99 return getStyleId( aStyle
);
102 const PropertyMap
* StyleContainer::getProperties( sal_Int32 nStyleId
) const
104 std::hash_map
< sal_Int32
, HashedStyle
>::const_iterator it
=
105 m_aIdToStyle
.find( nStyleId
);
106 return it
!= m_aIdToStyle
.end() ? &(it
->second
.Properties
) : NULL
;
109 sal_Int32
StyleContainer::setProperties( sal_Int32 nStyleId
, const PropertyMap
& rNewProps
)
112 std::hash_map
< sal_Int32
, HashedStyle
>::iterator it
=
113 m_aIdToStyle
.find( nStyleId
);
114 if( it
!= m_aIdToStyle
.end() )
116 if( it
->second
.RefCount
== 1 )
119 // erase old hash to id mapping
120 m_aStyleToId
.erase( it
->second
);
122 it
->second
.Properties
= rNewProps
;
123 // fill in new hash to id mapping
124 m_aStyleToId
[ it
->second
] = nRet
;
128 // decrease refcound on old instance
129 it
->second
.RefCount
--;
130 // acquire new HashedStyle
131 HashedStyle aSearchStyle
;
132 aSearchStyle
.Name
= it
->second
.Name
;
133 aSearchStyle
.Properties
= rNewProps
;
134 aSearchStyle
.Contents
= it
->second
.Contents
;
135 aSearchStyle
.ContainedElement
= it
->second
.ContainedElement
;
136 aSearchStyle
.SubStyles
= it
->second
.SubStyles
;
137 aSearchStyle
.IsSubStyle
= it
->second
.IsSubStyle
;
139 // find out whether this new style already exists
140 std::hash_map
< HashedStyle
, sal_Int32
, StyleHash
>::iterator new_it
=
141 m_aStyleToId
.find( aSearchStyle
);
142 if( new_it
!= m_aStyleToId
.end() )
144 nRet
= new_it
->second
;
145 m_aIdToStyle
[ nRet
].RefCount
++;
150 // create new style with new id
151 HashedStyle
& rNew
= m_aIdToStyle
[ nRet
];
154 // fill style to id hash
155 m_aStyleToId
[ aSearchStyle
] = nRet
;
162 OUString
StyleContainer::getStyleName( sal_Int32 nStyle
) const
164 OUStringBuffer
aRet( 64 );
166 std::hash_map
< sal_Int32
, HashedStyle
>::const_iterator style_it
=
167 m_aIdToStyle
.find( nStyle
);
168 if( style_it
!= m_aIdToStyle
.end() )
170 const HashedStyle
& rStyle
= style_it
->second
;
172 PropertyMap::const_iterator name_it
= rStyle
.Properties
.find( USTR("style:name") );
173 if( name_it
!= rStyle
.Properties
.end() )
174 aRet
.append( name_it
->second
);
177 PropertyMap::const_iterator fam_it
= rStyle
.Properties
.find( USTR("style:family" ) );
179 if( fam_it
!= rStyle
.Properties
.end() )
181 aStyleName
= fam_it
->second
;
184 aStyleName
= OStringToOUString( rStyle
.Name
, RTL_TEXTENCODING_ASCII_US
);
185 sal_Int32 nIndex
= aStyleName
.lastIndexOf( ':' );
186 aRet
.append( aStyleName
.copy( nIndex
+1 ) );
187 aRet
.append( nStyle
);
192 aRet
.appendAscii( "invalid style id " );
193 aRet
.append( nStyle
);
196 return aRet
.makeStringAndClear();
199 void StyleContainer::impl_emitStyle( sal_Int32 nStyleId
,
200 EmitContext
& rContext
,
201 ElementTreeVisitor
& rContainedElemVisitor
)
203 std::hash_map
< sal_Int32
, HashedStyle
>::const_iterator it
= m_aIdToStyle
.find( nStyleId
);
204 if( it
!= m_aIdToStyle
.end() )
206 const HashedStyle
& rStyle
= it
->second
;
207 PropertyMap
aProps( rStyle
.Properties
);
208 if( !rStyle
.IsSubStyle
)
209 aProps
[ USTR( "style:name" ) ] = getStyleName( nStyleId
);
210 rContext
.rEmitter
.beginTag( rStyle
.Name
.getStr(), aProps
);
212 for( unsigned int n
= 0; n
< rStyle
.SubStyles
.size(); ++n
)
213 impl_emitStyle( rStyle
.SubStyles
[n
], rContext
, rContainedElemVisitor
);
214 if( rStyle
.Contents
)
215 rContext
.rEmitter
.write( rStyle
.Contents
);
216 if( rStyle
.ContainedElement
)
217 rStyle
.ContainedElement
->visitedBy( rContainedElemVisitor
,
218 std::list
<Element
*>::iterator() );
219 rContext
.rEmitter
.endTag( rStyle
.Name
.getStr() );
223 void StyleContainer::emit( EmitContext
& rContext
,
224 ElementTreeVisitor
& rContainedElemVisitor
)
226 std::vector
< sal_Int32
> aMasterPageSection
, aAutomaticStyleSection
, aOfficeStyleSection
;
227 for( std::hash_map
< sal_Int32
, HashedStyle
>::iterator it
= m_aIdToStyle
.begin();
228 it
!= m_aIdToStyle
.end(); ++it
)
230 if( ! it
->second
.IsSubStyle
)
232 if( it
->second
.Name
.equals( "style:master-page" ) )
233 aMasterPageSection
.push_back( it
->first
);
234 else if( getStyleName( it
->first
).equalsAscii( "standard" ) )
235 aOfficeStyleSection
.push_back( it
->first
);
237 aAutomaticStyleSection
.push_back( it
->first
);
241 if( ! aMasterPageSection
.empty() )
242 std::stable_sort( aMasterPageSection
.begin(), aMasterPageSection
.end(), StyleIdNameSort(&m_aIdToStyle
) );
243 if( ! aAutomaticStyleSection
.empty() )
244 std::stable_sort( aAutomaticStyleSection
.begin(), aAutomaticStyleSection
.end(), StyleIdNameSort(&m_aIdToStyle
) );
245 if( ! aOfficeStyleSection
.empty() )
246 std::stable_sort( aOfficeStyleSection
.begin(), aOfficeStyleSection
.end(), StyleIdNameSort(&m_aIdToStyle
) );
248 int n
= 0, nElements
= 0;
249 rContext
.rEmitter
.beginTag( "office:styles", PropertyMap() );
250 for( n
= 0, nElements
= aOfficeStyleSection
.size(); n
< nElements
; n
++ )
251 impl_emitStyle( aOfficeStyleSection
[n
], rContext
, rContainedElemVisitor
);
252 rContext
.rEmitter
.endTag( "office:styles" );
253 rContext
.rEmitter
.beginTag( "office:automatic-styles", PropertyMap() );
254 for( n
= 0, nElements
= aAutomaticStyleSection
.size(); n
< nElements
; n
++ )
255 impl_emitStyle( aAutomaticStyleSection
[n
], rContext
, rContainedElemVisitor
);
256 rContext
.rEmitter
.endTag( "office:automatic-styles" );
257 rContext
.rEmitter
.beginTag( "office:master-styles", PropertyMap() );
258 for( n
= 0, nElements
= aMasterPageSection
.size(); n
< nElements
; n
++ )
259 impl_emitStyle( aMasterPageSection
[n
], rContext
, rContainedElemVisitor
);
260 rContext
.rEmitter
.endTag( "office:master-styles" );