1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef INCLUDED_PDFI_STYLE_HXX
29 #define INCLUDED_PDFI_STYLE_HXX
30 
31 #include "pdfihelper.hxx"
32 #include <hash_map>
33 #include <vector>
34 #include <rtl/ustring.hxx>
35 #include <rtl/string.hxx>
36 #include "treevisiting.hxx"
37 
38 namespace pdfi
39 {
40     struct Element;
41     struct EmitContext;
42     struct ElementTreeVisitable;
43 
44     class StyleContainer
45     {
46     public:
47         struct Style
48         {
49             rtl::OString             Name;
50             PropertyMap              Properties;
51             rtl::OUString            Contents;
52             Element*                 ContainedElement;
53             std::vector< Style* >    SubStyles;
54 
55             Style() : ContainedElement( NULL )  {}
56             Style( const rtl::OString& rName, const PropertyMap& rProps ) :
57                 Name( rName ),
58                 Properties( rProps ),
59                 ContainedElement( NULL )
60             {}
61         };
62 
63     private:
64         struct HashedStyle
65         {
66             rtl::OString            Name;
67             PropertyMap             Properties;
68             rtl::OUString           Contents;
69             Element*                ContainedElement;
70             std::vector<sal_Int32>  SubStyles;
71 
72             bool                    IsSubStyle;
73             sal_Int32               RefCount;
74 
75             HashedStyle() : ContainedElement( NULL ), IsSubStyle( true ), RefCount( 0 ) {}
76 
77             HashedStyle( const HashedStyle& rRight ) :
78                 Name( rRight.Name ),
79                 Properties( rRight.Properties ),
80                 Contents( rRight.Contents ),
81                 ContainedElement( rRight.ContainedElement ),
82                 SubStyles( rRight.SubStyles ),
83                 IsSubStyle( rRight.IsSubStyle ),
84                 RefCount( 0 )
85             {}
86 
87             size_t hashCode() const
88             {
89                 size_t nRet = size_t(Name.hashCode());
90                 for( PropertyMap::const_iterator it = Properties.begin();
91                      it != Properties.end(); ++it )
92                 {
93                      nRet ^= size_t(it->first.hashCode());
94                      nRet ^= size_t(it->second.hashCode());
95                 }
96                 nRet = size_t(Contents.hashCode());
97                 nRet ^= size_t(ContainedElement);
98                 for( unsigned int n = 0; n < SubStyles.size(); ++n )
99                      nRet ^= size_t(SubStyles[n]);
100                 return nRet;
101             }
102 
103             bool operator==(const HashedStyle& rRight) const
104             {
105                 if( Name != rRight.Name                 ||
106                     Properties != rRight.Properties     ||
107                     Contents != rRight.Contents         ||
108                     ContainedElement != rRight.ContainedElement ||
109                     SubStyles.size() != rRight.SubStyles.size()
110                     )
111                     return false;
112                 for( unsigned int n = 0; n < SubStyles.size(); ++n )
113                 {
114                     if( SubStyles[n] != rRight.SubStyles[n] )
115                         return false;
116                 }
117                 return true;
118             }
119         };
120 
121         struct StyleHash;
122         friend struct StyleHash;
123         struct StyleHash
124         {
125             size_t operator()( const StyleContainer::HashedStyle& rStyle ) const
126             {
127                 return rStyle.hashCode();
128             }
129         };
130 
131         struct StyleIdNameSort;
132         friend struct StyleIdNameSort;
133         struct StyleIdNameSort
134         {
135             const std::hash_map< sal_Int32, HashedStyle >* m_pMap;
136 
137             StyleIdNameSort( const std::hash_map< sal_Int32, HashedStyle >* pMap ) :
138                 m_pMap(pMap)
139             {}
140             bool operator()( sal_Int32 nLeft, sal_Int32 nRight )
141             {
142                 const std::hash_map< sal_Int32, HashedStyle >::const_iterator left_it =
143                     m_pMap->find( nLeft );
144                 const std::hash_map< sal_Int32, HashedStyle >::const_iterator right_it =
145                     m_pMap->find( nRight );
146                 if( left_it == m_pMap->end() )
147                     return false;
148                 else if( right_it == m_pMap->end() )
149                     return true;
150                 else
151                     return left_it->second.Name < right_it->second.Name;
152             }
153         };
154 
155         sal_Int32                                               m_nNextId;
156         std::hash_map< sal_Int32, HashedStyle >                 m_aIdToStyle;
157         std::hash_map< HashedStyle, sal_Int32, StyleHash >      m_aStyleToId;
158 
159         void impl_emitStyle( sal_Int32           nStyleId,
160                              EmitContext&        rContext,
161                              ElementTreeVisitor& rContainedElemVisitor );
162 
163     public:
164         StyleContainer();
165 
166         void emit( EmitContext&        rContext,
167                    ElementTreeVisitor& rContainedElemVisitor );
168 
169         sal_Int32 impl_getStyleId( const Style& rStyle, bool bSubStyle );
170         sal_Int32 getStyleId( const Style& rStyle )
171         { return impl_getStyleId( rStyle, false ); }
172         sal_Int32 getStandardStyleId( const rtl::OString& rFamily );
173 
174         // returns NULL for an invalid style id
175         const PropertyMap* getProperties( sal_Int32 nStyleId ) const;
176         sal_Int32 setProperties( sal_Int32 nStyleId, const PropertyMap &rNewProps );
177         rtl::OUString getStyleName( sal_Int32 nStyle ) const;
178     };
179 }
180 
181 #endif
182