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 #ifndef INCLUDED_PDFI_STYLE_HXX
25 #define INCLUDED_PDFI_STYLE_HXX
26 
27 #include "pdfihelper.hxx"
28 #include <hash_map>
29 #include <vector>
30 #include <rtl/ustring.hxx>
31 #include <rtl/string.hxx>
32 #include "treevisiting.hxx"
33 
34 namespace pdfi
35 {
36     struct Element;
37     struct EmitContext;
38     struct ElementTreeVisitable;
39 
40     class StyleContainer
41     {
42     public:
43         struct Style
44         {
45             rtl::OString             Name;
46             PropertyMap              Properties;
47             rtl::OUString            Contents;
48             Element*                 ContainedElement;
49             std::vector< Style* >    SubStyles;
50 
Stylepdfi::StyleContainer::Style51             Style() : ContainedElement( NULL )  {}
Stylepdfi::StyleContainer::Style52             Style( const rtl::OString& rName, const PropertyMap& rProps ) :
53                 Name( rName ),
54                 Properties( rProps ),
55                 ContainedElement( NULL )
56             {}
57         };
58 
59     private:
60         struct HashedStyle
61         {
62             rtl::OString            Name;
63             PropertyMap             Properties;
64             rtl::OUString           Contents;
65             Element*                ContainedElement;
66             std::vector<sal_Int32>  SubStyles;
67 
68             bool                    IsSubStyle;
69             sal_Int32               RefCount;
70 
HashedStylepdfi::StyleContainer::HashedStyle71             HashedStyle() : ContainedElement( NULL ), IsSubStyle( true ), RefCount( 0 ) {}
72 
HashedStylepdfi::StyleContainer::HashedStyle73             HashedStyle( const HashedStyle& rRight ) :
74                 Name( rRight.Name ),
75                 Properties( rRight.Properties ),
76                 Contents( rRight.Contents ),
77                 ContainedElement( rRight.ContainedElement ),
78                 SubStyles( rRight.SubStyles ),
79                 IsSubStyle( rRight.IsSubStyle ),
80                 RefCount( 0 )
81             {}
82 
hashCodepdfi::StyleContainer::HashedStyle83             size_t hashCode() const
84             {
85                 size_t nRet = size_t(Name.hashCode());
86                 for( PropertyMap::const_iterator it = Properties.begin();
87                      it != Properties.end(); ++it )
88                 {
89                      nRet ^= size_t(it->first.hashCode());
90                      nRet ^= size_t(it->second.hashCode());
91                 }
92                 nRet = size_t(Contents.hashCode());
93                 nRet ^= size_t(ContainedElement);
94                 for( unsigned int n = 0; n < SubStyles.size(); ++n )
95                      nRet ^= size_t(SubStyles[n]);
96                 return nRet;
97             }
98 
operator ==pdfi::StyleContainer::HashedStyle99             bool operator==(const HashedStyle& rRight) const
100             {
101                 if( Name != rRight.Name                 ||
102                     Properties != rRight.Properties     ||
103                     Contents != rRight.Contents         ||
104                     ContainedElement != rRight.ContainedElement ||
105                     SubStyles.size() != rRight.SubStyles.size()
106                     )
107                     return false;
108                 for( unsigned int n = 0; n < SubStyles.size(); ++n )
109                 {
110                     if( SubStyles[n] != rRight.SubStyles[n] )
111                         return false;
112                 }
113                 return true;
114             }
115         };
116 
117         struct StyleHash;
118         friend struct StyleHash;
119         struct StyleHash
120         {
operator ()pdfi::StyleContainer::StyleHash121             size_t operator()( const StyleContainer::HashedStyle& rStyle ) const
122             {
123                 return rStyle.hashCode();
124             }
125         };
126 
127         struct StyleIdNameSort;
128         friend struct StyleIdNameSort;
129         struct StyleIdNameSort
130         {
131             const std::hash_map< sal_Int32, HashedStyle >* m_pMap;
132 
StyleIdNameSortpdfi::StyleContainer::StyleIdNameSort133             StyleIdNameSort( const std::hash_map< sal_Int32, HashedStyle >* pMap ) :
134                 m_pMap(pMap)
135             {}
operator ()pdfi::StyleContainer::StyleIdNameSort136             bool operator()( sal_Int32 nLeft, sal_Int32 nRight )
137             {
138                 const std::hash_map< sal_Int32, HashedStyle >::const_iterator left_it =
139                     m_pMap->find( nLeft );
140                 const std::hash_map< sal_Int32, HashedStyle >::const_iterator right_it =
141                     m_pMap->find( nRight );
142                 if( left_it == m_pMap->end() )
143                     return false;
144                 else if( right_it == m_pMap->end() )
145                     return true;
146                 else
147                     return left_it->second.Name < right_it->second.Name;
148             }
149         };
150 
151         sal_Int32                                               m_nNextId;
152         std::hash_map< sal_Int32, HashedStyle >                 m_aIdToStyle;
153         std::hash_map< HashedStyle, sal_Int32, StyleHash >      m_aStyleToId;
154 
155         void impl_emitStyle( sal_Int32           nStyleId,
156                              EmitContext&        rContext,
157                              ElementTreeVisitor& rContainedElemVisitor );
158 
159     public:
160         StyleContainer();
161 
162         void emit( EmitContext&        rContext,
163                    ElementTreeVisitor& rContainedElemVisitor );
164 
165         sal_Int32 impl_getStyleId( const Style& rStyle, bool bSubStyle );
getStyleId(const Style & rStyle)166         sal_Int32 getStyleId( const Style& rStyle )
167         { return impl_getStyleId( rStyle, false ); }
168         sal_Int32 getStandardStyleId( const rtl::OString& rFamily );
169 
170         // returns NULL for an invalid style id
171         const PropertyMap* getProperties( sal_Int32 nStyleId ) const;
172         sal_Int32 setProperties( sal_Int32 nStyleId, const PropertyMap &rNewProps );
173         rtl::OUString getStyleName( sal_Int32 nStyle ) const;
174     };
175 }
176 
177 #endif
178