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
StyleContainer()40cdf0e10cSrcweir StyleContainer::StyleContainer() :
41cdf0e10cSrcweir m_nNextId( 1 )
42cdf0e10cSrcweir {
43cdf0e10cSrcweir }
44cdf0e10cSrcweir
impl_getStyleId(const Style & rStyle,bool bSubStyle)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
getStandardStyleId(const rtl::OString & rName)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
getProperties(sal_Int32 nStyleId) const94cdf0e10cSrcweir 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
setProperties(sal_Int32 nStyleId,const PropertyMap & rNewProps)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
getStyleName(sal_Int32 nStyle) const154cdf0e10cSrcweir 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
impl_emitStyle(sal_Int32 nStyleId,EmitContext & rContext,ElementTreeVisitor & rContainedElemVisitor)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
emit(EmitContext & rContext,ElementTreeVisitor & rContainedElemVisitor)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