1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <xmloff/XMLFontStylesContext.hxx>
21 #include "XMLFontStylesContext_impl.hxx"
22
23 #include <com/sun/star/awt/FontFamily.hpp>
24 #include <com/sun/star/awt/FontPitch.hpp>
25 #include <com/sun/star/embed/ElementModes.hpp>
26 #include <com/sun/star/embed/XStorage.hpp>
27
28 #include <comphelper/seqstream.hxx>
29
30 #include <sal/log.hxx>
31 #include <vcl/embeddedfontshelper.hxx>
32
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>
39
40
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;
49
50
51 #define XML_STYLE_FAMILY_FONT 1
52
53 enum XMLFontStyleAttrTokens
54 {
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,
60 };
61
lcl_getFontStyleAttrTokenMap()62 static const SvXMLTokenMapEntry* lcl_getFontStyleAttrTokenMap()
63 {
64 static const SvXMLTokenMapEntry aFontStyleAttrTokenMap[] =
65 {
66 { XML_NAMESPACE_SVG, XML_FONT_FAMILY,
67 XML_TOK_FONT_STYLE_ATTR_FAMILY },
68 { XML_NAMESPACE_STYLE, XML_FONT_FAMILY_GENERIC,
69 XML_TOK_FONT_STYLE_ATTR_FAMILY_GENERIC },
70 { XML_NAMESPACE_STYLE, XML_FONT_ADORNMENTS,
71 XML_TOK_FONT_STYLE_ATTR_STYLENAME },
72 { XML_NAMESPACE_STYLE, XML_FONT_PITCH,
73 XML_TOK_FONT_STYLE_ATTR_PITCH },
74 { XML_NAMESPACE_STYLE, XML_FONT_CHARSET,
75 XML_TOK_FONT_STYLE_ATTR_CHARSET },
76
77 XML_TOKEN_MAP_END
78 };
79 return aFontStyleAttrTokenMap;
80 }
81
82
XMLFontStyleContextFontFace(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<XAttributeList> & xAttrList,XMLFontStylesContext & rStyles)83 XMLFontStyleContextFontFace::XMLFontStyleContextFontFace( SvXMLImport& rImport,
84 sal_uInt16 nPrfx, const OUString& rLName,
85 const Reference< XAttributeList > & xAttrList,
86 XMLFontStylesContext& rStyles ) :
87 SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, XML_STYLE_FAMILY_FONT ),
88 xStyles( &rStyles )
89 {
90 aFamilyName <<= OUString();
91 aStyleName <<= OUString();
92 aFamily <<= sal_Int16(awt::FontFamily::DONTKNOW);
93 aPitch <<= sal_Int16(awt::FontPitch::DONTKNOW);
94 aEnc <<= static_cast<sal_Int16>(rStyles.GetDfltCharset());
95 }
96
SetAttribute(sal_uInt16 nPrefixKey,const OUString & rLocalName,const OUString & rValue)97 void XMLFontStyleContextFontFace::SetAttribute( sal_uInt16 nPrefixKey,
98 const OUString& rLocalName,
99 const OUString& rValue )
100 {
101 SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
102 const SvXMLTokenMap& rTokenMap = GetStyles()->GetFontStyleAttrTokenMap();
103 Any aAny;
104
105 switch( rTokenMap.Get( nPrefixKey, rLocalName ) )
106 {
107 case XML_TOK_FONT_STYLE_ATTR_FAMILY:
108 if( GetStyles()->GetFamilyNameHdl().importXML( rValue, aAny,
109 rUnitConv ) )
110 aFamilyName = aAny;
111 break;
112 case XML_TOK_FONT_STYLE_ATTR_STYLENAME:
113 aStyleName <<= rValue;
114 break;
115 case XML_TOK_FONT_STYLE_ATTR_FAMILY_GENERIC:
116 if( GetStyles()->GetFamilyHdl().importXML( rValue, aAny,
117 rUnitConv ) )
118 aFamily = aAny;
119 break;
120 case XML_TOK_FONT_STYLE_ATTR_PITCH:
121 if( GetStyles()->GetPitchHdl().importXML( rValue, aAny,
122 rUnitConv ) )
123 aPitch = aAny;
124 break;
125 case XML_TOK_FONT_STYLE_ATTR_CHARSET:
126 if( GetStyles()->GetEncodingHdl().importXML( rValue, aAny,
127 rUnitConv ) )
128 aEnc = aAny;
129 break;
130 default:
131 SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
132 break;
133 }
134 }
135
~XMLFontStyleContextFontFace()136 XMLFontStyleContextFontFace::~XMLFontStyleContextFontFace()
137 {
138 }
139
FillProperties(::std::vector<XMLPropertyState> & rProps,sal_Int32 nFamilyNameIdx,sal_Int32 nStyleNameIdx,sal_Int32 nFamilyIdx,sal_Int32 nPitchIdx,sal_Int32 nCharsetIdx) const140 void XMLFontStyleContextFontFace::FillProperties(
141 ::std::vector< XMLPropertyState > &rProps,
142 sal_Int32 nFamilyNameIdx,
143 sal_Int32 nStyleNameIdx,
144 sal_Int32 nFamilyIdx,
145 sal_Int32 nPitchIdx,
146 sal_Int32 nCharsetIdx ) const
147 {
148 if( nFamilyNameIdx != -1 )
149 {
150 XMLPropertyState aPropState( nFamilyNameIdx, aFamilyName );
151 rProps.push_back( aPropState );
152 }
153 if( nStyleNameIdx != -1 )
154 {
155 XMLPropertyState aPropState( nStyleNameIdx, aStyleName );
156 rProps.push_back( aPropState );
157 }
158 if( nFamilyIdx != -1 )
159 {
160 XMLPropertyState aPropState( nFamilyIdx, aFamily );
161 rProps.push_back( aPropState );
162 }
163 if( nPitchIdx != -1 )
164 {
165 XMLPropertyState aPropState( nPitchIdx, aPitch );
166 rProps.push_back( aPropState );
167 }
168 if( nCharsetIdx != -1 )
169 {
170 XMLPropertyState aPropState( nCharsetIdx, aEnc );
171 rProps.push_back( aPropState );
172 }
173 }
174
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttrList)175 SvXMLImportContextRef XMLFontStyleContextFontFace::CreateChildContext(
176 sal_uInt16 nPrefix,
177 const OUString& rLocalName,
178 const css::uno::Reference< css::xml::sax::XAttributeList > & xAttrList )
179 {
180 if( nPrefix == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_FONT_FACE_SRC ))
181 return new XMLFontStyleContextFontFaceSrc( GetImport(), nPrefix, rLocalName, *this );
182 return SvXMLStyleContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
183 }
184
familyName() const185 OUString XMLFontStyleContextFontFace::familyName() const
186 {
187 OUString ret;
188 aFamilyName >>= ret;
189 return ret;
190 }
191
192
XMLFontStyleContextFontFaceFormat(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttrList,XMLFontStyleContextFontFaceUri & _uri)193 XMLFontStyleContextFontFaceFormat::XMLFontStyleContextFontFaceFormat( SvXMLImport& rImport,
194 sal_uInt16 nPrfx, const OUString& rLName,
195 const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList,
196 XMLFontStyleContextFontFaceUri& _uri )
197 : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList)
198 , uri(_uri)
199 {
200 }
201
SetAttribute(sal_uInt16 nPrefixKey,const OUString & rLocalName,const OUString & rValue)202 void XMLFontStyleContextFontFaceFormat::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName,
203 const OUString& rValue )
204 {
205 if( nPrefixKey == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_STRING ))
206 uri.SetFormat(rValue);
207 else
208 SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
209 }
210
211
XMLFontStyleContextFontFaceSrc(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const XMLFontStyleContextFontFace & _font)212 XMLFontStyleContextFontFaceSrc::XMLFontStyleContextFontFaceSrc( SvXMLImport& rImport,
213 sal_uInt16 nPrfx, const OUString& rLName,
214 const XMLFontStyleContextFontFace& _font )
215 : SvXMLImportContext( rImport, nPrfx, rLName )
216 , font( _font )
217 {
218 }
219
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttrList)220 SvXMLImportContextRef XMLFontStyleContextFontFaceSrc::CreateChildContext(
221 sal_uInt16 nPrefix,
222 const OUString& rLocalName,
223 const css::uno::Reference< css::xml::sax::XAttributeList > & xAttrList )
224 {
225 if( nPrefix == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_FONT_FACE_URI ))
226 return new XMLFontStyleContextFontFaceUri( GetImport(), nPrefix, rLocalName, xAttrList, font );
227 return SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
228 }
229
230
XMLFontStyleContextFontFaceUri(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttrList,const XMLFontStyleContextFontFace & _font)231 XMLFontStyleContextFontFaceUri::XMLFontStyleContextFontFaceUri( SvXMLImport& rImport,
232 sal_uInt16 nPrfx, const OUString& rLName,
233 const css::uno::Reference< css::xml::sax::XAttributeList > & xAttrList,
234 const XMLFontStyleContextFontFace& _font )
235 : SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList )
236 , font( _font )
237 {
238 }
239
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttrList)240 SvXMLImportContextRef XMLFontStyleContextFontFaceUri::CreateChildContext(
241 sal_uInt16 nPrefix,
242 const OUString& rLocalName,
243 const css::uno::Reference< css::xml::sax::XAttributeList > & xAttrList )
244 {
245 if( nPrefix == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_FONT_FACE_FORMAT ))
246 return new XMLFontStyleContextFontFaceFormat( GetImport(), nPrefix, rLocalName, xAttrList, *this );
247 if( linkPath.isEmpty() && ( nPrefix == XML_NAMESPACE_OFFICE ) && IsXMLToken( rLocalName, XML_BINARY_DATA ) )
248 {
249 mxBase64Stream.set( new comphelper::OSequenceOutputStream( maFontData ) );
250 if( mxBase64Stream.is() )
251 return new XMLBase64ImportContext( GetImport(), nPrefix, rLocalName, xAttrList, mxBase64Stream );
252 }
253 return SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
254 }
255
SetAttribute(sal_uInt16 nPrefixKey,const OUString & rLocalName,const OUString & rValue)256 void XMLFontStyleContextFontFaceUri::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName,
257 const OUString& rValue )
258 {
259 if( nPrefixKey == XML_NAMESPACE_XLINK && IsXMLToken( rLocalName, XML_HREF ))
260 linkPath = rValue;
261 else
262 SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
263 }
264
SetFormat(const OUString & rFormat)265 void XMLFontStyleContextFontFaceUri::SetFormat( const OUString& rFormat )
266 {
267 format = rFormat;
268 }
269
270 // the CSS2 standard ( http://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#referencing )
271 // defines these format strings.
272 const char OPENTYPE_FORMAT[] = "opentype";
273 const char TRUETYPE_FORMAT[] = "truetype";
274 const char EOT_FORMAT[] = "embedded-opentype";
275
EndElement()276 void XMLFontStyleContextFontFaceUri::EndElement()
277 {
278 if( ( linkPath.getLength() == 0 ) && ( !maFontData.hasElements() ) )
279 {
280 SAL_WARN( "xmloff", "svg:font-face-uri tag with no link or base64 data; ignoring." );
281 return;
282 }
283 bool eot;
284 // Assume by default that the font is not compressed.
285 if( format.getLength() == 0
286 || format == OPENTYPE_FORMAT
287 || format == TRUETYPE_FORMAT )
288 {
289 eot = false;
290 }
291 else if( format == EOT_FORMAT )
292 {
293 eot = true;
294 }
295 else
296 {
297 SAL_WARN( "xmloff", "Unknown format of embedded font; assuming TTF." );
298 eot = false;
299 }
300 if ( !maFontData.hasElements() )
301 handleEmbeddedFont( linkPath, eot );
302 else
303 handleEmbeddedFont( maFontData, eot );
304 }
305
handleEmbeddedFont(const OUString & url,bool eot)306 void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url, bool eot )
307 {
308 if( GetImport().embeddedFontAlreadyProcessed( url ))
309 {
310 GetImport().NotifyEmbeddedFontRead();
311 return;
312 }
313 OUString fontName = font.familyName();
314 // If there's any giveMeStreamForThisURL(), then it's well-hidden for me to find it.
315 if( GetImport().IsPackageURL( url ))
316 {
317 uno::Reference< embed::XStorage > storage;
318 storage.set( GetImport().GetSourceStorage(), UNO_SET_THROW );
319 if( url.indexOf( '/' ) > -1 ) // TODO what if more levels?
320 storage.set( storage->openStorageElement( url.copy( 0, url.indexOf( '/' )),
321 ::embed::ElementModes::READ ), uno::UNO_SET_THROW );
322 uno::Reference< io::XInputStream > inputStream;
323 inputStream.set( storage->openStreamElement( url.copy( url.indexOf( '/' ) + 1 ), ::embed::ElementModes::READ ),
324 UNO_QUERY_THROW );
325 if( EmbeddedFontsHelper::addEmbeddedFont( inputStream, fontName, "?", std::vector< unsigned char >(), eot ))
326 GetImport().NotifyEmbeddedFontRead();
327 inputStream->closeInput();
328 }
329 else
330 SAL_WARN( "xmloff", "External URL for font file not handled." );
331 }
332
handleEmbeddedFont(const::css::uno::Sequence<sal_Int8> & rData,const bool eot)333 void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const ::css::uno::Sequence< sal_Int8 >& rData, const bool eot )
334 {
335 const uno::Reference< io::XInputStream > xInput( new comphelper::SequenceInputStream( rData ) );
336 const OUString fontName = font.familyName();
337 if( EmbeddedFontsHelper::addEmbeddedFont( xInput, fontName, "?", std::vector< unsigned char >(), eot ) )
338 GetImport().NotifyEmbeddedFontRead();
339 xInput->closeInput();
340 }
341
CreateStyleChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttrList)342 SvXMLStyleContext *XMLFontStylesContext::CreateStyleChildContext(
343 sal_uInt16 nPrefix,
344 const OUString& rLocalName,
345 const css::uno::Reference< css::xml::sax::XAttributeList > & xAttrList )
346 {
347 SvXMLStyleContext *pStyle;
348 if( XML_NAMESPACE_STYLE == nPrefix &&
349 IsXMLToken( rLocalName, XML_FONT_FACE ) )
350 {
351 pStyle = new XMLFontStyleContextFontFace( GetImport(), nPrefix,
352 rLocalName, xAttrList, *this );
353 }
354 else
355 {
356 pStyle = SvXMLStylesContext::CreateStyleChildContext( nPrefix,
357 rLocalName, xAttrList );
358 }
359
360 return pStyle;
361 }
362
363
XMLFontStylesContext(SvXMLImport & rImport,sal_uInt16 nPrfx,const OUString & rLName,const Reference<XAttributeList> & xAttrList,rtl_TextEncoding eDfltEnc)364 XMLFontStylesContext::XMLFontStylesContext( SvXMLImport& rImport,
365 sal_uInt16 nPrfx, const OUString& rLName,
366 const Reference< XAttributeList > & xAttrList,
367 rtl_TextEncoding eDfltEnc ) :
368 SvXMLStylesContext( rImport, nPrfx, rLName, xAttrList ),
369 pFamilyNameHdl( new XMLFontFamilyNamePropHdl ),
370 pFamilyHdl( new XMLFontFamilyPropHdl ),
371 pPitchHdl( new XMLFontPitchPropHdl ),
372 pEncHdl( new XMLFontEncodingPropHdl ),
373 pFontStyleAttrTokenMap( new SvXMLTokenMap(lcl_getFontStyleAttrTokenMap()) ),
374 eDfltEncoding( eDfltEnc )
375 {
376 }
377
~XMLFontStylesContext()378 XMLFontStylesContext::~XMLFontStylesContext() {}
379
FillProperties(const OUString & rName,::std::vector<XMLPropertyState> & rProps,sal_Int32 nFamilyNameIdx,sal_Int32 nStyleNameIdx,sal_Int32 nFamilyIdx,sal_Int32 nPitchIdx,sal_Int32 nCharsetIdx) const380 bool XMLFontStylesContext::FillProperties( const OUString& rName,
381 ::std::vector< XMLPropertyState > &rProps,
382 sal_Int32 nFamilyNameIdx,
383 sal_Int32 nStyleNameIdx,
384 sal_Int32 nFamilyIdx,
385 sal_Int32 nPitchIdx,
386 sal_Int32 nCharsetIdx ) const
387 {
388 const SvXMLStyleContext* pStyle = FindStyleChildContext( XML_STYLE_FAMILY_FONT, rName, true );
389 const XMLFontStyleContextFontFace *pFontStyle = dynamic_cast<const XMLFontStyleContextFontFace*>(pStyle);// use temp var, PTR_CAST is a bad macro, FindStyleChildContext will be called twice
390 if( pFontStyle )
391 pFontStyle->FillProperties( rProps, nFamilyNameIdx, nStyleNameIdx,
392 nFamilyIdx, nPitchIdx, nCharsetIdx );
393 return nullptr != pFontStyle;
394 }
395
396 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
397