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