bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / svg / svgfontexport.cxx
blobd7cb1c2ebc3c1a7a3b0c4d4a845ffc43ee3a9d91
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include "svgfontexport.hxx"
22 #include "svgfilter.hxx"
23 #include "svgwriter.hxx"
26 #include <vcl/unohelp.hxx>
27 #include <vcl/font.hxx>
28 #include <vcl/outdev.hxx>
30 static const sal_Int32 nFontEM = 2048;
32 // -----------------
33 // - SVGFontExport -
34 // -----------------
36 SVGFontExport::SVGFontExport( SVGExport& rExport, const ::std::vector< ObjectRepresentation >& rObjects ) :
37 mrExport( rExport ),
38 maObjects( rObjects ),
39 mnCurFontId( 0 )
43 // -----------------------------------------------------------------------------
45 SVGFontExport::~SVGFontExport()
49 // -----------------------------------------------------------------------------
51 SVGFontExport::GlyphSet& SVGFontExport::implGetGlyphSet( const Font& rFont )
53 FontWeight eWeight( WEIGHT_NORMAL );
54 FontItalic eItalic( ITALIC_NONE );
55 OUString aFontName( rFont.GetName() );
56 sal_Int32 nNextTokenPos( 0 );
58 switch( rFont.GetWeight() )
60 case WEIGHT_BOLD:
61 case WEIGHT_ULTRABOLD:
62 case WEIGHT_BLACK:
63 eWeight = WEIGHT_BOLD;
64 break;
66 default:
67 break;
70 if( rFont.GetItalic() != ITALIC_NONE )
71 eItalic = ITALIC_NORMAL;
73 return( maGlyphTree[ aFontName.getToken( 0, ';', nNextTokenPos ) ][ eWeight ][ eItalic ] );
76 // -----------------------------------------------------------------------------
78 void SVGFontExport::implCollectGlyphs()
80 VirtualDevice aVDev;
81 ObjectVector::const_iterator aIter( maObjects.begin() );
83 aVDev.EnableOutput( sal_False );
85 while( aIter != maObjects.end() )
87 if( (*aIter).HasRepresentation() )
89 const GDIMetaFile& rMtf = (*aIter).GetRepresentation();
91 aVDev.Push();
93 for( size_t i = 0, nCount = rMtf.GetActionSize(); i < nCount; ++i )
95 OUString aText;
96 MetaAction* pAction = rMtf.GetAction( i );
97 const sal_uInt16 nType = pAction->GetType();
99 switch( nType )
101 case( META_TEXT_ACTION ):
103 const MetaTextAction* pA = (const MetaTextAction*) pAction;
104 aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() );
106 break;
108 case( META_TEXTRECT_ACTION ):
110 const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
111 aText = pA->GetText();
113 break;
115 case( META_TEXTARRAY_ACTION ):
117 const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
118 aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() );
120 break;
122 case( META_STRETCHTEXT_ACTION ):
124 const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
125 aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() );
127 break;
129 default:
130 pAction->Execute( &aVDev );
131 break;
134 if( !aText.isEmpty() )
136 GlyphSet& rGlyphSet = implGetGlyphSet( aVDev.GetFont() );
137 ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xBI(
138 ::vcl::unohelper::CreateBreakIterator() );
140 if( xBI.is() )
142 const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
143 sal_Int32 nCurPos = 0, nLastPos = -1;
145 while( ( nCurPos < aText.getLength() ) && ( nCurPos > nLastPos ) )
147 sal_Int32 nCount2 = 1;
149 nLastPos = nCurPos;
150 nCurPos = xBI->nextCharacters( aText, nCurPos, rLocale,
151 ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL,
152 nCount2, nCount2 );
154 rGlyphSet.insert( aText.copy( nLastPos, nCurPos - nLastPos ) );
157 else
159 const sal_Unicode* pStr = aText.getStr();
161 for( sal_uInt32 k = 0, nLen = aText.getLength(); k < nLen; ++k )
162 rGlyphSet.insert( OUString( pStr[ k ] ) );
167 aVDev.Pop();
170 ++aIter;
174 // -----------------------------------------------------------------------------
176 void SVGFontExport::implEmbedFont( const Font& rFont )
178 if( mrExport.IsEmbedFonts() )
180 GlyphSet& rGlyphSet = implGetGlyphSet( rFont );
182 if( !rGlyphSet.empty() )
184 GlyphSet::const_iterator aIter( rGlyphSet.begin() );
185 const OUString aEmbeddedFontStr( "EmbeddedFont_" );
188 SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
189 OUString aCurIdStr( aEmbeddedFontStr );
190 OUString aUnitsPerEM( OUString::valueOf( nFontEM ) );
191 VirtualDevice aVDev;
192 Font aFont( rFont );
194 aFont.SetSize( Size( 0, nFontEM ) );
195 aFont.SetAlign( ALIGN_BASELINE );
197 aVDev.SetMapMode( MAP_100TH_MM );
198 aVDev.SetFont( aFont );
200 mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", aCurIdStr += OUString::valueOf( ++mnCurFontId ) );
201 mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", aUnitsPerEM );
204 SvXMLElementExport aExp2( mrExport, XML_NAMESPACE_NONE, "font", sal_True, sal_True );
205 OUString aFontWeight;
206 OUString aFontStyle;
207 const Size aSize( nFontEM, nFontEM );
209 // Font Weight
210 if( aFont.GetWeight() != WEIGHT_NORMAL )
211 aFontWeight = "bold";
212 else
213 aFontWeight = "normal";
215 // Font Italic
216 if( aFont.GetItalic() != ITALIC_NONE )
217 aFontStyle = "italic";
218 else
219 aFontStyle = "normal";
221 mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-family", GetMappedFontName( rFont.GetName() ) );
222 mrExport.AddAttribute( XML_NAMESPACE_NONE, "units-per-em", aUnitsPerEM );
223 mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-weight", aFontWeight );
224 mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-style", aFontStyle );
225 mrExport.AddAttribute( XML_NAMESPACE_NONE, "ascent", OUString::valueOf( aVDev.GetFontMetric().GetAscent() ) );
226 mrExport.AddAttribute( XML_NAMESPACE_NONE, "descent", OUString::valueOf( aVDev.GetFontMetric().GetDescent() ) );
229 SvXMLElementExport aExp3( mrExport, XML_NAMESPACE_NONE, "font-face", sal_True, sal_True );
232 mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", OUString::valueOf( aSize.Width() ) );
235 const Point aPos;
236 const PolyPolygon aMissingGlyphPolyPoly( Rectangle( aPos, aSize ) );
238 mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", SVGActionWriter::GetPathString( aMissingGlyphPolyPoly, sal_False ) );
241 SvXMLElementExport aExp4( mrExport, XML_NAMESPACE_NONE, "missing-glyph", sal_True, sal_True );
245 while( aIter != rGlyphSet.end() )
247 implEmbedGlyph( aVDev, *aIter );
248 ++aIter;
256 // -----------------------------------------------------------------------------
258 void SVGFontExport::implEmbedGlyph( OutputDevice& rOut, const OUString& rCellStr )
260 PolyPolygon aPolyPoly;
261 const sal_Unicode nSpace = ' ';
263 if( rOut.GetTextOutline( aPolyPoly, rCellStr ) )
265 Rectangle aBoundRect;
267 aPolyPoly.Scale( 1.0, -1.0 );
269 if( !rOut.GetTextBoundRect( aBoundRect, rCellStr ) )
270 aBoundRect = Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( rCellStr ), 0 ) );
272 mrExport.AddAttribute( XML_NAMESPACE_NONE, "unicode", rCellStr );
274 if( rCellStr[ 0 ] == nSpace && rCellStr.getLength() == 1 )
275 aBoundRect = Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( OUString(' ') ), 0 ) );
277 mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", OUString::valueOf( aBoundRect.GetWidth() ) );
279 const OUString aPathString( SVGActionWriter::GetPathString( aPolyPoly, sal_False ) );
280 if( !aPathString.isEmpty() )
282 mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", aPathString );
286 SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "glyph", sal_True, sal_True );
291 // -----------------------------------------------------------------------------
293 void SVGFontExport::EmbedFonts()
295 implCollectGlyphs();
297 GlyphTree::const_iterator aGlyphTreeIter( maGlyphTree.begin() );
299 while( aGlyphTreeIter != maGlyphTree.end() )
301 const FontWeightMap& rFontWeightMap = (*aGlyphTreeIter).second;
302 FontWeightMap::const_iterator aFontWeightIter( rFontWeightMap.begin() );
304 while( aFontWeightIter != rFontWeightMap.end() )
306 const FontItalicMap& rFontItalicMap = (*aFontWeightIter).second;
307 FontItalicMap::const_iterator aFontItalicIter( rFontItalicMap.begin() );
309 while( aFontItalicIter != rFontItalicMap.end() )
311 Font aFont;
313 aFont.SetName( (*aGlyphTreeIter).first );
314 aFont.SetWeight( (*aFontWeightIter).first );
315 aFont.SetItalic( (*aFontItalicIter).first );
317 implEmbedFont( aFont );
319 ++aFontItalicIter;
322 ++aFontWeightIter;
325 ++aGlyphTreeIter;
329 // -----------------------------------------------------------------------------
331 OUString SVGFontExport::GetMappedFontName( const OUString& rFontName ) const
333 sal_Int32 nNextTokenPos( 0 );
334 OUString aRet( rFontName.getToken( 0, ';', nNextTokenPos ) );
336 if( mnCurFontId )
337 aRet += " embedded";
339 return aRet;
342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */