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