Line data Source code
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 :
27 : #include <comphelper/seqstream.hxx>
28 :
29 : #include <osl/file.hxx>
30 : #include <vcl/embeddedfontshelper.hxx>
31 :
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>
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 : XML_TOK_FONT_STYLE_ATTR_END=XML_TOK_UNKNOWN
62 : };
63 :
64 1120 : static const SvXMLTokenMapEntry* lcl_getFontStyleAttrTokenMap()
65 : {
66 : static const SvXMLTokenMapEntry aFontStyleAttrTokenMap[] =
67 : {
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 },
78 :
79 : XML_TOKEN_MAP_END
80 : };
81 1120 : return aFontStyleAttrTokenMap;
82 : }
83 :
84 41753 : TYPEINIT1( XMLFontStyleContextFontFace, SvXMLStyleContext );
85 :
86 5710 : 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 ),
91 5710 : xStyles( &rStyles )
92 : {
93 5710 : OUString sEmpty;
94 5710 : aFamilyName <<= sEmpty;
95 5710 : aStyleName <<= sEmpty;
96 5710 : aFamily <<= (sal_Int16)awt::FontFamily::DONTKNOW;
97 5710 : aPitch <<= (sal_Int16)awt::FontPitch::DONTKNOW;
98 5710 : aEnc <<= (sal_Int16)rStyles.GetDfltCharset();
99 5710 : }
100 :
101 21307 : void XMLFontStyleContextFontFace::SetAttribute( sal_uInt16 nPrefixKey,
102 : const OUString& rLocalName,
103 : const OUString& rValue )
104 : {
105 21307 : SvXMLUnitConverter& rUnitConv = GetImport().GetMM100UnitConverter();
106 21307 : const SvXMLTokenMap& rTokenMap = GetStyles()->GetFontStyleAttrTokenMap();
107 21307 : Any aAny;
108 :
109 21307 : switch( rTokenMap.Get( nPrefixKey, rLocalName ) )
110 : {
111 : case XML_TOK_FONT_STYLE_ATTR_FAMILY:
112 11420 : if( GetStyles()->GetFamilyNameHdl().importXML( rValue, aAny,
113 5710 : rUnitConv ) )
114 5680 : aFamilyName = aAny;
115 5710 : break;
116 : case XML_TOK_FONT_STYLE_ATTR_STYLENAME:
117 162 : aStyleName <<= rValue;
118 162 : break;
119 : case XML_TOK_FONT_STYLE_ATTR_FAMILY_GENERIC:
120 9708 : if( GetStyles()->GetFamilyHdl().importXML( rValue, aAny,
121 4854 : rUnitConv ) )
122 4854 : aFamily = aAny;
123 4854 : break;
124 : case XML_TOK_FONT_STYLE_ATTR_PITCH:
125 9348 : if( GetStyles()->GetPitchHdl().importXML( rValue, aAny,
126 4674 : rUnitConv ) )
127 4674 : aPitch = aAny;
128 4674 : break;
129 : case XML_TOK_FONT_STYLE_ATTR_CHARSET:
130 394 : if( GetStyles()->GetEncodingHdl().importXML( rValue, aAny,
131 197 : rUnitConv ) )
132 197 : aEnc = aAny;
133 197 : break;
134 : default:
135 5710 : SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
136 5710 : break;
137 21307 : }
138 21307 : }
139 :
140 11420 : XMLFontStyleContextFontFace::~XMLFontStyleContextFontFace()
141 : {
142 11420 : }
143 :
144 10428 : void XMLFontStyleContextFontFace::FillProperties(
145 : ::std::vector< XMLPropertyState > &rProps,
146 : sal_Int32 nFamilyNameIdx,
147 : sal_Int32 nStyleNameIdx,
148 : sal_Int32 nFamilyIdx,
149 : sal_Int32 nPitchIdx,
150 : sal_Int32 nCharsetIdx ) const
151 : {
152 10428 : if( nFamilyNameIdx != -1 )
153 : {
154 10428 : XMLPropertyState aPropState( nFamilyNameIdx, aFamilyName );
155 10428 : rProps.push_back( aPropState );
156 : }
157 10428 : if( nStyleNameIdx != -1 )
158 : {
159 10428 : XMLPropertyState aPropState( nStyleNameIdx, aStyleName );
160 10428 : rProps.push_back( aPropState );
161 : }
162 10428 : if( nFamilyIdx != -1 )
163 : {
164 10428 : XMLPropertyState aPropState( nFamilyIdx, aFamily );
165 10428 : rProps.push_back( aPropState );
166 : }
167 10428 : if( nPitchIdx != -1 )
168 : {
169 10428 : XMLPropertyState aPropState( nPitchIdx, aPitch );
170 10428 : rProps.push_back( aPropState );
171 : }
172 10428 : if( nCharsetIdx != -1 )
173 : {
174 10428 : XMLPropertyState aPropState( nCharsetIdx, aEnc );
175 10428 : rProps.push_back( aPropState );
176 : }
177 10428 : }
178 :
179 5 : SvXMLImportContext * XMLFontStyleContextFontFace::CreateChildContext(
180 : sal_uInt16 nPrefix,
181 : const OUString& rLocalName,
182 : const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList )
183 : {
184 5 : if( nPrefix == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_FONT_FACE_SRC ))
185 5 : return new XMLFontStyleContextFontFaceSrc( GetImport(), nPrefix, rLocalName, *this );
186 0 : return SvXMLStyleContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
187 : }
188 :
189 13 : OUString XMLFontStyleContextFontFace::familyName() const
190 : {
191 13 : OUString ret;
192 13 : aFamilyName >>= ret;
193 13 : return ret;
194 : }
195 :
196 0 : TYPEINIT1( XMLFontStyleContextFontFaceFormat, SvXMLStyleContext );
197 :
198 0 : 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)
204 0 : , uri(_uri)
205 : {
206 0 : }
207 :
208 0 : void XMLFontStyleContextFontFaceFormat::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName,
209 : const OUString& rValue )
210 : {
211 0 : if( nPrefixKey == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_STRING ))
212 0 : uri.SetFormat(rValue);
213 : else
214 0 : SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
215 0 : }
216 :
217 0 : TYPEINIT1( XMLFontStyleContextFontFaceSrc, SvXMLImportContext );
218 :
219 5 : XMLFontStyleContextFontFaceSrc::XMLFontStyleContextFontFaceSrc( SvXMLImport& rImport,
220 : sal_uInt16 nPrfx, const OUString& rLName,
221 : const XMLFontStyleContextFontFace& _font )
222 : : SvXMLImportContext( rImport, nPrfx, rLName )
223 5 : , font( _font )
224 : {
225 5 : }
226 :
227 13 : SvXMLImportContext * XMLFontStyleContextFontFaceSrc::CreateChildContext(
228 : sal_uInt16 nPrefix,
229 : const OUString& rLocalName,
230 : const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList )
231 : {
232 13 : if( nPrefix == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_FONT_FACE_URI ))
233 13 : return new XMLFontStyleContextFontFaceUri( GetImport(), nPrefix, rLocalName, xAttrList, font );
234 0 : return SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
235 : }
236 :
237 :
238 0 : TYPEINIT1( XMLFontStyleContextFontFaceUri, SvXMLImportContext );
239 :
240 13 : 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 )
246 13 : , font( _font )
247 : {
248 13 : }
249 :
250 0 : SvXMLImportContext * XMLFontStyleContextFontFaceUri::CreateChildContext(
251 : sal_uInt16 nPrefix,
252 : const OUString& rLocalName,
253 : const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList )
254 : {
255 0 : if( nPrefix == XML_NAMESPACE_SVG && IsXMLToken( rLocalName, XML_FONT_FACE_FORMAT ))
256 0 : return new XMLFontStyleContextFontFaceFormat( GetImport(), nPrefix, rLocalName, xAttrList, *this );
257 0 : if( linkPath.isEmpty() && ( nPrefix == XML_NAMESPACE_OFFICE ) && IsXMLToken( rLocalName, XML_BINARY_DATA ) )
258 : {
259 0 : mxBase64Stream.set( new comphelper::OSequenceOutputStream( maFontData ) );
260 0 : if( mxBase64Stream.is() )
261 0 : return new XMLBase64ImportContext( GetImport(), nPrefix, rLocalName, xAttrList, mxBase64Stream );
262 : }
263 0 : return SvXMLImportContext::CreateChildContext( nPrefix, rLocalName, xAttrList );
264 : }
265 :
266 26 : void XMLFontStyleContextFontFaceUri::SetAttribute( sal_uInt16 nPrefixKey, const OUString& rLocalName,
267 : const OUString& rValue )
268 : {
269 26 : if( nPrefixKey == XML_NAMESPACE_XLINK && IsXMLToken( rLocalName, XML_HREF ))
270 13 : linkPath = rValue;
271 : else
272 13 : SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
273 26 : }
274 :
275 0 : void XMLFontStyleContextFontFaceUri::SetFormat( const OUString& rFormat )
276 : {
277 0 : format = rFormat;
278 0 : }
279 :
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";
285 :
286 13 : void XMLFontStyleContextFontFaceUri::EndElement()
287 : {
288 13 : if( ( linkPath.getLength() == 0 ) && ( maFontData.getLength() == 0 ) )
289 : {
290 : SAL_WARN( "xmloff", "svg:font-face-uri tag with no link or base64 data; ignoring." );
291 13 : return;
292 : }
293 : bool eot;
294 : // Assume by default that the font is not compressed.
295 26 : if( format.getLength() == 0
296 0 : || format.equalsAscii( OPENTYPE_FORMAT )
297 13 : || format.equalsAscii( TRUETYPE_FORMAT ))
298 : {
299 13 : eot = false;
300 : }
301 0 : else if( format.equalsAscii( EOT_FORMAT ))
302 : {
303 0 : eot = true;
304 : }
305 : else
306 : {
307 : SAL_WARN( "xmloff", "Unknown format of embedded font; assuming TTF." );
308 0 : eot = false;
309 : }
310 13 : if ( maFontData.getLength() == 0 )
311 13 : handleEmbeddedFont( linkPath, eot );
312 : else
313 0 : handleEmbeddedFont( maFontData, eot );
314 : }
315 :
316 13 : void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const OUString& url, bool eot )
317 : {
318 13 : if( GetImport().embeddedFontAlreadyProcessed( url ))
319 : {
320 0 : GetImport().NotifyEmbeddedFontRead();
321 13 : return;
322 : }
323 13 : OUString fontName = font.familyName();
324 : // If there's any giveMeStreamForThisURL(), then it's well-hidden for me to find it.
325 13 : if( GetImport().IsPackageURL( url ))
326 : {
327 13 : uno::Reference< embed::XStorage > storage;
328 13 : storage.set( GetImport().GetSourceStorage(), UNO_QUERY_THROW );
329 13 : if( url.indexOf( '/' ) > -1 ) // TODO what if more levels?
330 13 : storage.set( storage->openStorageElement( url.copy( 0, url.indexOf( '/' )),
331 13 : ::embed::ElementModes::READ ), uno::UNO_QUERY_THROW );
332 26 : uno::Reference< io::XInputStream > inputStream;
333 13 : inputStream.set( storage->openStreamElement( url.copy( url.indexOf( '/' ) + 1 ), ::embed::ElementModes::READ ),
334 13 : UNO_QUERY_THROW );
335 13 : if( EmbeddedFontsHelper::addEmbeddedFont( inputStream, fontName, "?", std::vector< unsigned char >(), eot ))
336 13 : GetImport().NotifyEmbeddedFontRead();
337 26 : inputStream->closeInput();
338 : }
339 : else
340 13 : SAL_WARN( "xmloff", "External URL for font file not handled." );
341 : }
342 :
343 0 : void XMLFontStyleContextFontFaceUri::handleEmbeddedFont( const ::css::uno::Sequence< sal_Int8 >& rData, const bool eot )
344 : {
345 0 : const uno::Reference< io::XInputStream > xInput( new comphelper::SequenceInputStream( rData ) );
346 0 : const OUString fontName = font.familyName();
347 0 : if( EmbeddedFontsHelper::addEmbeddedFont( xInput, fontName, "?", std::vector< unsigned char >(), eot ) )
348 0 : GetImport().NotifyEmbeddedFontRead();
349 0 : xInput->closeInput();
350 0 : }
351 :
352 5710 : SvXMLStyleContext *XMLFontStylesContext::CreateStyleChildContext(
353 : sal_uInt16 nPrefix,
354 : const OUString& rLocalName,
355 : const ::com::sun::star::uno::Reference<
356 : ::com::sun::star::xml::sax::XAttributeList > & xAttrList )
357 : {
358 : SvXMLStyleContext *pStyle;
359 11420 : if( XML_NAMESPACE_STYLE == nPrefix &&
360 5710 : IsXMLToken( rLocalName, XML_FONT_FACE ) )
361 : {
362 5710 : pStyle = new XMLFontStyleContextFontFace( GetImport(), nPrefix,
363 5710 : rLocalName, xAttrList, *this );
364 : }
365 : else
366 : {
367 : pStyle = SvXMLStylesContext::CreateStyleChildContext( nPrefix,
368 0 : rLocalName, xAttrList );
369 : }
370 :
371 5710 : return pStyle;
372 : }
373 :
374 0 : TYPEINIT1( XMLFontStylesContext, SvXMLStylesContext );
375 :
376 1120 : 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 1120 : pFamilyNameHdl( new XMLFontFamilyNamePropHdl ),
382 1120 : pFamilyHdl( new XMLFontFamilyPropHdl ),
383 1120 : pPitchHdl( new XMLFontPitchPropHdl ),
384 1120 : pEncHdl( new XMLFontEncodingPropHdl ),
385 1120 : pFontStyleAttrTokenMap( new SvXMLTokenMap(lcl_getFontStyleAttrTokenMap()) ),
386 6720 : eDfltEncoding( eDfltEnc )
387 : {
388 1120 : }
389 :
390 3360 : XMLFontStylesContext::~XMLFontStylesContext()
391 : {
392 1120 : delete pFamilyNameHdl;
393 1120 : delete pFamilyHdl;
394 1120 : delete pPitchHdl;
395 1120 : delete pEncHdl;
396 1120 : delete pFontStyleAttrTokenMap;
397 2240 : }
398 :
399 10469 : bool XMLFontStylesContext::FillProperties( const OUString& rName,
400 : ::std::vector< XMLPropertyState > &rProps,
401 : sal_Int32 nFamilyNameIdx,
402 : sal_Int32 nStyleNameIdx,
403 : sal_Int32 nFamilyIdx,
404 : sal_Int32 nPitchIdx,
405 : sal_Int32 nCharsetIdx ) const
406 : {
407 10469 : const SvXMLStyleContext* pStyle = FindStyleChildContext( XML_STYLE_FAMILY_FONT, rName, true );
408 10469 : const XMLFontStyleContextFontFace *pFontStyle = PTR_CAST( XMLFontStyleContextFontFace,pStyle);// use temp var, PTR_CAST is a bad macro, FindStyleChildContext will be called twice
409 10469 : if( pFontStyle )
410 : pFontStyle->FillProperties( rProps, nFamilyNameIdx, nStyleNameIdx,
411 10428 : nFamilyIdx, nPitchIdx, nCharsetIdx );
412 10469 : return 0 != pFontStyle;
413 : }
414 :
415 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|