build fix
[LibreOffice.git] / filter / source / svg / svgfontexport.cxx
blob39b7276f3f7ff7078f854edf33dfd47925eed60b
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"
25 #include <vcl/unohelp.hxx>
26 #include <vcl/font.hxx>
27 #include <vcl/outdev.hxx>
28 #include <vcl/settings.hxx>
30 static const sal_Int32 nFontEM = 2048;
33 SVGFontExport::SVGFontExport( SVGExport& rExport, const ::std::vector< ObjectRepresentation >& rObjects ) :
34 mrExport( rExport ),
35 maObjects( rObjects ),
36 mnCurFontId( 0 )
41 SVGFontExport::~SVGFontExport()
46 SVGFontExport::GlyphSet& SVGFontExport::implGetGlyphSet( const vcl::Font& rFont )
48 FontWeight eWeight( WEIGHT_NORMAL );
49 FontItalic eItalic( ITALIC_NONE );
50 const OUString& aFontName( rFont.GetFamilyName() );
51 sal_Int32 nNextTokenPos( 0 );
53 switch( rFont.GetWeight() )
55 case WEIGHT_BOLD:
56 case WEIGHT_ULTRABOLD:
57 case WEIGHT_BLACK:
58 eWeight = WEIGHT_BOLD;
59 break;
61 default:
62 break;
65 if( rFont.GetItalic() != ITALIC_NONE )
66 eItalic = ITALIC_NORMAL;
68 return( maGlyphTree[ aFontName.getToken( 0, ';', nNextTokenPos ) ][ eWeight ][ eItalic ] );
72 void SVGFontExport::implCollectGlyphs()
74 ScopedVclPtrInstance< VirtualDevice > pVDev;
75 ObjectVector::const_iterator aIter( maObjects.begin() );
77 pVDev->EnableOutput( false );
79 while( aIter != maObjects.end() )
81 if( (*aIter).HasRepresentation() )
83 const GDIMetaFile& rMtf = (*aIter).GetRepresentation();
85 pVDev->Push();
87 for( size_t i = 0, nCount = rMtf.GetActionSize(); i < nCount; ++i )
89 OUString aText;
90 MetaAction* pAction = rMtf.GetAction( i );
91 const MetaActionType nType = pAction->GetType();
93 switch( nType )
95 case( MetaActionType::TEXT ):
97 const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
98 sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
99 aText = pA->GetText().copy( pA->GetIndex(), aLength );
101 break;
103 case( MetaActionType::TEXTRECT ):
105 const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
106 aText = pA->GetText();
108 break;
110 case( MetaActionType::TEXTARRAY ):
112 const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
113 sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
114 aText = pA->GetText().copy( pA->GetIndex(), aLength );
116 break;
118 case( MetaActionType::STRETCHTEXT ):
120 const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
121 sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
122 aText = pA->GetText().copy( pA->GetIndex(), aLength );
124 break;
126 default:
127 pAction->Execute( pVDev );
128 break;
131 if( !aText.isEmpty() )
133 GlyphSet& rGlyphSet = implGetGlyphSet( pVDev->GetFont() );
134 css::uno::Reference< css::i18n::XBreakIterator > xBI(
135 vcl::unohelper::CreateBreakIterator() );
137 if( xBI.is() )
139 const css::lang::Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
140 sal_Int32 nCurPos = 0, nLastPos = -1;
142 while( ( nCurPos < aText.getLength() ) && ( nCurPos > nLastPos ) )
144 sal_Int32 nCount2 = 1;
146 nLastPos = nCurPos;
147 nCurPos = xBI->nextCharacters( aText, nCurPos, rLocale,
148 css::i18n::CharacterIteratorMode::SKIPCELL,
149 nCount2, nCount2 );
151 rGlyphSet.insert( aText.copy( nLastPos, nCurPos - nLastPos ) );
154 else
156 const sal_Unicode* pStr = aText.getStr();
158 for( sal_uInt32 k = 0, nLen = aText.getLength(); k < nLen; ++k )
159 rGlyphSet.insert( OUString( pStr[ k ] ) );
164 pVDev->Pop();
167 ++aIter;
172 void SVGFontExport::implEmbedFont( const vcl::Font& rFont )
174 if( mrExport.IsEmbedFonts() )
176 GlyphSet& rGlyphSet = implGetGlyphSet( rFont );
178 if( !rGlyphSet.empty() )
180 GlyphSet::const_iterator aIter( rGlyphSet.begin() );
181 const OUString aEmbeddedFontStr( "EmbeddedFont_" );
184 SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "defs", true, true );
185 OUString aCurIdStr( aEmbeddedFontStr );
186 OUString aUnitsPerEM( OUString::number( nFontEM ) );
187 ScopedVclPtrInstance< VirtualDevice > pVDev;
188 vcl::Font aFont( rFont );
190 aFont.SetFontSize( Size( 0, nFontEM ) );
191 aFont.SetAlignment( ALIGN_BASELINE );
193 pVDev->SetMapMode( MapUnit::Map100thMM );
194 pVDev->SetFont( aFont );
196 mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", aCurIdStr += OUString::number( ++mnCurFontId ) );
197 mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", aUnitsPerEM );
200 SvXMLElementExport aExp2( mrExport, XML_NAMESPACE_NONE, "font", true, true );
201 OUString aFontWeight;
202 OUString aFontStyle;
203 const Size aSize( nFontEM, nFontEM );
205 // Font Weight
206 if( aFont.GetWeight() != WEIGHT_NORMAL )
207 aFontWeight = "bold";
208 else
209 aFontWeight = "normal";
211 // Font Italic
212 if( aFont.GetItalic() != ITALIC_NONE )
213 aFontStyle = "italic";
214 else
215 aFontStyle = "normal";
217 mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-family", GetMappedFontName( rFont.GetFamilyName() ) );
218 mrExport.AddAttribute( XML_NAMESPACE_NONE, "units-per-em", aUnitsPerEM );
219 mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-weight", aFontWeight );
220 mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-style", aFontStyle );
221 mrExport.AddAttribute( XML_NAMESPACE_NONE, "ascent", OUString::number( pVDev->GetFontMetric().GetAscent() ) );
222 mrExport.AddAttribute( XML_NAMESPACE_NONE, "descent", OUString::number( pVDev->GetFontMetric().GetDescent() ) );
225 SvXMLElementExport aExp3( mrExport, XML_NAMESPACE_NONE, "font-face", true, true );
228 mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", OUString::number( aSize.Width() ) );
231 const Point aPos;
232 const tools::PolyPolygon aMissingGlyphPolyPoly( Rectangle( aPos, aSize ) );
234 mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", SVGActionWriter::GetPathString( aMissingGlyphPolyPoly, false ) );
237 SvXMLElementExport aExp4( mrExport, XML_NAMESPACE_NONE, "missing-glyph", true, true );
241 while( aIter != rGlyphSet.end() )
243 implEmbedGlyph( *pVDev.get(), *aIter );
244 ++aIter;
253 void SVGFontExport::implEmbedGlyph( OutputDevice& rOut, const OUString& rCellStr )
255 tools::PolyPolygon aPolyPoly;
256 const sal_Unicode nSpace = ' ';
258 if( rOut.GetTextOutline( aPolyPoly, rCellStr ) )
260 Rectangle aBoundRect;
262 aPolyPoly.Scale( 1.0, -1.0 );
264 if( !rOut.GetTextBoundRect( aBoundRect, rCellStr ) )
265 aBoundRect = Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( rCellStr ), 0 ) );
267 mrExport.AddAttribute( XML_NAMESPACE_NONE, "unicode", rCellStr );
269 if( rCellStr[ 0 ] == nSpace && rCellStr.getLength() == 1 )
270 aBoundRect = Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( OUString(' ') ), 0 ) );
272 mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", OUString::number( aBoundRect.GetWidth() ) );
274 const OUString aPathString( SVGActionWriter::GetPathString( aPolyPoly, false ) );
275 if( !aPathString.isEmpty() )
277 mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", aPathString );
281 SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "glyph", true, true );
287 void SVGFontExport::EmbedFonts()
289 implCollectGlyphs();
291 GlyphTree::const_iterator aGlyphTreeIter( maGlyphTree.begin() );
293 while( aGlyphTreeIter != maGlyphTree.end() )
295 const FontWeightMap& rFontWeightMap = (*aGlyphTreeIter).second;
296 FontWeightMap::const_iterator aFontWeightIter( rFontWeightMap.begin() );
298 while( aFontWeightIter != rFontWeightMap.end() )
300 const FontItalicMap& rFontItalicMap = (*aFontWeightIter).second;
301 FontItalicMap::const_iterator aFontItalicIter( rFontItalicMap.begin() );
303 while( aFontItalicIter != rFontItalicMap.end() )
305 vcl::Font aFont;
307 aFont.SetFamilyName( (*aGlyphTreeIter).first );
308 aFont.SetWeight( (*aFontWeightIter).first );
309 aFont.SetItalic( (*aFontItalicIter).first );
311 implEmbedFont( aFont );
313 ++aFontItalicIter;
316 ++aFontWeightIter;
319 ++aGlyphTreeIter;
324 OUString SVGFontExport::GetMappedFontName( const OUString& rFontName ) const
326 sal_Int32 nNextTokenPos( 0 );
327 OUString aRet( rFontName.getToken( 0, ';', nNextTokenPos ) );
329 if( mnCurFontId )
330 aRet += " embedded";
332 return aRet;
335 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */