1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <xmloff/XMLFontStylesContext.hxx>
21 #include "XMLFontStylesContext_impl.hxx"
23 #include <com/sun/star/awt/FontFamily.hpp>
24 #include <com/sun/star/awt/FontPitch.hpp>
25 #include <com/sun/star/embed/ElementModes.hpp>
27 #include <comphelper/seqstream.hxx>
29 #include <osl/file.hxx>
30 #include <vcl/embeddedfontshelper.hxx>
32 #include <xmloff/nmspmap.hxx>
33 #include <xmloff/xmlnmspe.hxx>
34 #include <xmloff/xmltoken.hxx>
35 #include "fonthdl.hxx"
36 #include <xmloff/xmlimp.hxx>
37 #include <xmloff/maptype.hxx>
38 #include <xmloff/XMLBase64ImportContext.hxx>
41 using namespace ::com::sun::star
;
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::xml::sax
;
44 using namespace ::com::sun::star::container
;
45 using namespace ::com::sun::star::beans
;
46 using namespace ::com::sun::star::lang
;
47 using namespace ::com::sun::star::awt
;
48 using namespace ::xmloff::token
;
51 #define XML_STYLE_FAMILY_FONT 1
53 enum XMLFontStyleAttrTokens
55 XML_TOK_FONT_STYLE_ATTR_FAMILY
,
56 XML_TOK_FONT_STYLE_ATTR_FAMILY_GENERIC
,
57 XML_TOK_FONT_STYLE_ATTR_STYLENAME
,
58 XML_TOK_FONT_STYLE_ATTR_PITCH
,
59 XML_TOK_FONT_STYLE_ATTR_CHARSET
,
61 XML_TOK_FONT_STYLE_ATTR_END
=XML_TOK_UNKNOWN
64 static const SvXMLTokenMapEntry
* lcl_getFontStyleAttrTokenMap()
66 static const SvXMLTokenMapEntry aFontStyleAttrTokenMap
[] =
68 { XML_NAMESPACE_SVG
, XML_FONT_FAMILY
,
69 XML_TOK_FONT_STYLE_ATTR_FAMILY
},
70 { XML_NAMESPACE_STYLE
, XML_FONT_FAMILY_GENERIC
,
71 XML_TOK_FONT_STYLE_ATTR_FAMILY_GENERIC
},
72 { XML_NAMESPACE_STYLE
, XML_FONT_ADORNMENTS
,
73 XML_TOK_FONT_STYLE_ATTR_STYLENAME
},
74 { XML_NAMESPACE_STYLE
, XML_FONT_PITCH
,
75 XML_TOK_FONT_STYLE_ATTR_PITCH
},
76 { XML_NAMESPACE_STYLE
, XML_FONT_CHARSET
,
77 XML_TOK_FONT_STYLE_ATTR_CHARSET
},
81 return aFontStyleAttrTokenMap
;
84 TYPEINIT1( XMLFontStyleContextFontFace
, SvXMLStyleContext
);
86 XMLFontStyleContextFontFace::XMLFontStyleContextFontFace( SvXMLImport
& rImport
,
87 sal_uInt16 nPrfx
, const OUString
& rLName
,
88 const Reference
< XAttributeList
> & xAttrList
,
89 XMLFontStylesContext
& rStyles
) :
90 SvXMLStyleContext( rImport
, nPrfx
, rLName
, xAttrList
, XML_STYLE_FAMILY_FONT
),
94 aFamilyName
<<= sEmpty
;
95 aStyleName
<<= sEmpty
;
96 aFamily
<<= (sal_Int16
)awt::FontFamily::DONTKNOW
;
97 aPitch
<<= (sal_Int16
)awt::FontPitch::DONTKNOW
;
98 aEnc
<<= (sal_Int16
)rStyles
.GetDfltCharset();
101 void XMLFontStyleContextFontFace::SetAttribute( sal_uInt16 nPrefixKey
,
102 const OUString
& rLocalName
,
103 const OUString
& rValue
)
105 SvXMLUnitConverter
& rUnitConv
= GetImport().GetMM100UnitConverter();
106 const SvXMLTokenMap
& rTokenMap
= GetStyles()->GetFontStyleAttrTokenMap();
109 switch( rTokenMap
.Get( nPrefixKey
, rLocalName
) )
111 case XML_TOK_FONT_STYLE_ATTR_FAMILY
:
112 if( GetStyles()->GetFamilyNameHdl().importXML( rValue
, aAny
,
116 case XML_TOK_FONT_STYLE_ATTR_STYLENAME
:
117 aStyleName
<<= rValue
;
119 case XML_TOK_FONT_STYLE_ATTR_FAMILY_GENERIC
:
120 if( GetStyles()->GetFamilyHdl().importXML( rValue
, aAny
,
124 case XML_TOK_FONT_STYLE_ATTR_PITCH
:
125 if( GetStyles()->GetPitchHdl().importXML( rValue
, aAny
,
129 case XML_TOK_FONT_STYLE_ATTR_CHARSET
:
130 if( GetStyles()->GetEncodingHdl().importXML( rValue
, aAny
,
135 SvXMLStyleContext::SetAttribute( nPrefixKey
, rLocalName
, rValue
);
140 XMLFontStyleContextFontFace::~XMLFontStyleContextFontFace()
144 void XMLFontStyleContextFontFace::FillProperties(
145 ::std::vector
< XMLPropertyState
> &rProps
,
146 sal_Int32 nFamilyNameIdx
,
147 sal_Int32 nStyleNameIdx
,
148 sal_Int32 nFamilyIdx
,
150 sal_Int32 nCharsetIdx
) const
152 if( nFamilyNameIdx
!= -1 )
154 XMLPropertyState
aPropState( nFamilyNameIdx
, aFamilyName
);
155 rProps
.push_back( aPropState
);
157 if( nStyleNameIdx
!= -1 )
159 XMLPropertyState
aPropState( nStyleNameIdx
, aStyleName
);
160 rProps
.push_back( aPropState
);
162 if( nFamilyIdx
!= -1 )
164 XMLPropertyState
aPropState( nFamilyIdx
, aFamily
);
165 rProps
.push_back( aPropState
);
167 if( nPitchIdx
!= -1 )
169 XMLPropertyState
aPropState( nPitchIdx
, aPitch
);
170 rProps
.push_back( aPropState
);
172 if( nCharsetIdx
!= -1 )
174 XMLPropertyState
aPropState( nCharsetIdx
, aEnc
);
175 rProps
.push_back( aPropState
);
179 SvXMLImportContext
* XMLFontStyleContextFontFace::CreateChildContext(
181 const OUString
& rLocalName
,
182 const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XAttributeList
> & xAttrList
)
184 if( nPrefix
== XML_NAMESPACE_SVG
&& IsXMLToken( rLocalName
, XML_FONT_FACE_SRC
))
185 return new XMLFontStyleContextFontFaceSrc( GetImport(), nPrefix
, rLocalName
, *this );
186 return SvXMLStyleContext::CreateChildContext( nPrefix
, rLocalName
, xAttrList
);
189 OUString
XMLFontStyleContextFontFace::familyName() const
196 TYPEINIT1( XMLFontStyleContextFontFaceFormat
, SvXMLStyleContext
);
198 XMLFontStyleContextFontFaceFormat::XMLFontStyleContextFontFaceFormat( SvXMLImport
& rImport
,
199 sal_uInt16 nPrfx
, const OUString
& rLName
,
200 const ::com::sun::star::uno::Reference
<
201 ::com::sun::star::xml::sax::XAttributeList
> &xAttrList
,
202 XMLFontStyleContextFontFaceUri
& _uri
)
203 : SvXMLStyleContext( rImport
, nPrfx
, rLName
, xAttrList
)
208 void XMLFontStyleContextFontFaceFormat::SetAttribute( sal_uInt16 nPrefixKey
, const OUString
& rLocalName
,
209 const OUString
& rValue
)
211 if( nPrefixKey
== XML_NAMESPACE_SVG
&& IsXMLToken( rLocalName
, XML_STRING
))
212 uri
.SetFormat(rValue
);
214 SvXMLStyleContext::SetAttribute( nPrefixKey
, rLocalName
, rValue
);
217 TYPEINIT1( XMLFontStyleContextFontFaceSrc
, SvXMLImportContext
);
219 XMLFontStyleContextFontFaceSrc::XMLFontStyleContextFontFaceSrc( SvXMLImport
& rImport
,
220 sal_uInt16 nPrfx
, const OUString
& rLName
,
221 const XMLFontStyleContextFontFace
& _font
)
222 : SvXMLImportContext( rImport
, nPrfx
, rLName
)
227 SvXMLImportContext
* XMLFontStyleContextFontFaceSrc::CreateChildContext(
229 const OUString
& rLocalName
,
230 const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XAttributeList
> & xAttrList
)
232 if( nPrefix
== XML_NAMESPACE_SVG
&& IsXMLToken( rLocalName
, XML_FONT_FACE_URI
))
233 return new XMLFontStyleContextFontFaceUri( GetImport(), nPrefix
, rLocalName
, xAttrList
, font
);
234 return SvXMLImportContext::CreateChildContext( nPrefix
, rLocalName
, xAttrList
);
238 TYPEINIT1( XMLFontStyleContextFontFaceUri
, SvXMLImportContext
);
240 XMLFontStyleContextFontFaceUri::XMLFontStyleContextFontFaceUri( SvXMLImport
& rImport
,
241 sal_uInt16 nPrfx
, const OUString
& rLName
,
242 const ::com::sun::star::uno::Reference
<
243 ::com::sun::star::xml::sax::XAttributeList
> & xAttrList
,
244 const XMLFontStyleContextFontFace
& _font
)
245 : SvXMLStyleContext( rImport
, nPrfx
, rLName
, xAttrList
)
250 SvXMLImportContext
* XMLFontStyleContextFontFaceUri::CreateChildContext(
252 const OUString
& rLocalName
,
253 const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XAttributeList
> & xAttrList
)
255 if( nPrefix
== XML_NAMESPACE_SVG
&& IsXMLToken( rLocalName
, XML_FONT_FACE_FORMAT
))
256 return new XMLFontStyleContextFontFaceFormat( GetImport(), nPrefix
, rLocalName
, xAttrList
, *this );
257 if( linkPath
.isEmpty() && ( nPrefix
== XML_NAMESPACE_OFFICE
) && IsXMLToken( rLocalName
, XML_BINARY_DATA
) )
259 mxBase64Stream
.set( new comphelper::OSequenceOutputStream( maFontData
) );
260 if( mxBase64Stream
.is() )
261 return new XMLBase64ImportContext( GetImport(), nPrefix
, rLocalName
, xAttrList
, mxBase64Stream
);
263 return SvXMLImportContext::CreateChildContext( nPrefix
, rLocalName
, xAttrList
);
266 void XMLFontStyleContextFontFaceUri::SetAttribute( sal_uInt16 nPrefixKey
, const OUString
& rLocalName
,
267 const OUString
& rValue
)
269 if( nPrefixKey
== XML_NAMESPACE_XLINK
&& IsXMLToken( rLocalName
, XML_HREF
))
272 SvXMLStyleContext::SetAttribute( nPrefixKey
, rLocalName
, rValue
);
275 void XMLFontStyleContextFontFaceUri::SetFormat( const OUString
& rFormat
)
280 // the CSS2 standard ( http://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#referencing )
281 // defines these format strings.
282 const char* OPENTYPE_FORMAT
= "opentype";
283 const char* TRUETYPE_FORMAT
= "truetype";
284 const char* EOT_FORMAT
= "embedded-opentype";
286 void XMLFontStyleContextFontFaceUri::EndElement()
288 if( ( linkPath
.getLength() == 0 ) && ( maFontData
.getLength() == 0 ) )
290 SAL_WARN( "xmloff", "svg:font-face-uri tag with no link or base64 data; ignoring." );
294 // Assume by default that the font is not compressed.
295 if( format
.getLength() == 0
296 || format
.equalsAscii( OPENTYPE_FORMAT
)
297 || format
.equalsAscii( TRUETYPE_FORMAT
))
301 else if( format
.equalsAscii( EOT_FORMAT
))
307 SAL_WARN( "xmloff", "Unknown format of embedded font; assuming TTF." );
310 if ( maFontData
.getLength() == 0 )
311 handleEmbeddedFont( linkPath
, eot
);
313 handleEmbeddedFont( maFontData
, eot
);
316 void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString
& url
, bool eot
)
318 if( GetImport().embeddedFontAlreadyProcessed( url
))
320 GetImport().NotifyEmbeddedFontRead();
323 OUString fontName
= font
.familyName();
324 // If there's any giveMeStreamForThisURL(), then it's well-hidden for me to find it.
325 if( GetImport().IsPackageURL( url
))
327 uno::Reference
< embed::XStorage
> storage
;
328 storage
.set( GetImport().GetSourceStorage(), UNO_QUERY_THROW
);
329 if( url
.indexOf( '/' ) > -1 ) // TODO what if more levels?
330 storage
.set( storage
->openStorageElement( url
.copy( 0, url
.indexOf( '/' )),
331 ::embed::ElementModes::READ
), uno::UNO_QUERY_THROW
);
332 uno::Reference
< io::XInputStream
> inputStream
;
333 inputStream
.set( storage
->openStreamElement( url
.copy( url
.indexOf( '/' ) + 1 ), ::embed::ElementModes::READ
),
335 if( EmbeddedFontsHelper::addEmbeddedFont( inputStream
, fontName
, "?", std::vector
< unsigned char >(), eot
))
336 GetImport().NotifyEmbeddedFontRead();
337 inputStream
->closeInput();
340 SAL_WARN( "xmloff", "External URL for font file not handled." );
343 void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const ::css::uno::Sequence
< sal_Int8
>& rData
, const bool eot
)
345 const uno::Reference
< io::XInputStream
> xInput( new comphelper::SequenceInputStream( rData
) );
346 const OUString fontName
= font
.familyName();
347 if( EmbeddedFontsHelper::addEmbeddedFont( xInput
, fontName
, "?", std::vector
< unsigned char >(), eot
) )
348 GetImport().NotifyEmbeddedFontRead();
349 xInput
->closeInput();
352 SvXMLStyleContext
*XMLFontStylesContext::CreateStyleChildContext(
354 const OUString
& rLocalName
,
355 const ::com::sun::star::uno::Reference
<
356 ::com::sun::star::xml::sax::XAttributeList
> & xAttrList
)
358 SvXMLStyleContext
*pStyle
;
359 if( XML_NAMESPACE_STYLE
== nPrefix
&&
360 IsXMLToken( rLocalName
, XML_FONT_FACE
) )
362 pStyle
= new XMLFontStyleContextFontFace( GetImport(), nPrefix
,
363 rLocalName
, xAttrList
, *this );
367 pStyle
= SvXMLStylesContext::CreateStyleChildContext( nPrefix
,
368 rLocalName
, xAttrList
);
374 TYPEINIT1( XMLFontStylesContext
, SvXMLStylesContext
);
376 XMLFontStylesContext::XMLFontStylesContext( SvXMLImport
& rImport
,
377 sal_uInt16 nPrfx
, const OUString
& rLName
,
378 const Reference
< XAttributeList
> & xAttrList
,
379 rtl_TextEncoding eDfltEnc
) :
380 SvXMLStylesContext( rImport
, nPrfx
, rLName
, xAttrList
),
381 pFamilyNameHdl( new XMLFontFamilyNamePropHdl
),
382 pFamilyHdl( new XMLFontFamilyPropHdl
),
383 pPitchHdl( new XMLFontPitchPropHdl
),
384 pEncHdl( new XMLFontEncodingPropHdl
),
385 pFontStyleAttrTokenMap( new SvXMLTokenMap(lcl_getFontStyleAttrTokenMap()) ),
386 eDfltEncoding( eDfltEnc
)
390 XMLFontStylesContext::~XMLFontStylesContext()
392 delete pFamilyNameHdl
;
396 delete pFontStyleAttrTokenMap
;
399 bool XMLFontStylesContext::FillProperties( const OUString
& rName
,
400 ::std::vector
< XMLPropertyState
> &rProps
,
401 sal_Int32 nFamilyNameIdx
,
402 sal_Int32 nStyleNameIdx
,
403 sal_Int32 nFamilyIdx
,
405 sal_Int32 nCharsetIdx
) const
407 const SvXMLStyleContext
* pStyle
= FindStyleChildContext( XML_STYLE_FAMILY_FONT
, rName
, true );
408 const XMLFontStyleContextFontFace
*pFontStyle
= PTR_CAST( XMLFontStyleContextFontFace
,pStyle
);// use temp var, PTR_CAST is a bad macro, FindStyleChildContext will be called twice
410 pFontStyle
->FillProperties( rProps
, nFamilyNameIdx
, nStyleNameIdx
,
411 nFamilyIdx
, nPitchIdx
, nCharsetIdx
);
412 return 0 != pFontStyle
;
415 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */