Revert "Revert "Revert "stronger typing for SwClient::GetRegisteredIn"" and fix SwIte...
[LibreOffice.git] / filter / source / svg / svgfontexport.cxx
blobc31a2f53b467babd6d942442eb1d9432c17039a3
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/metric.hxx>
28 #include <vcl/outdev.hxx>
29 #include <vcl/settings.hxx>
30 #include <i18nlangtag/languagetag.hxx>
31 #include <xmloff/namespacemap.hxx>
32 #include <o3tl/string_view.hxx>
34 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
35 #include <com/sun/star/i18n/XBreakIterator.hpp>
37 const sal_Int32 nFontEM = 2048;
40 SVGFontExport::SVGFontExport( SVGExport& rExport, ::std::vector< ObjectRepresentation >&& rObjects ) :
41 mrExport( rExport ),
42 maObjects( std::move(rObjects) ),
43 mnCurFontId( 0 )
48 SVGFontExport::~SVGFontExport()
53 SVGFontExport::GlyphSet& SVGFontExport::implGetGlyphSet( const vcl::Font& rFont )
55 FontWeight eWeight( WEIGHT_NORMAL );
56 FontItalic eItalic( ITALIC_NONE );
57 const OUString& aFontName( rFont.GetFamilyName() );
59 switch( rFont.GetWeight() )
61 case WEIGHT_BOLD:
62 case WEIGHT_ULTRABOLD:
63 case WEIGHT_BLACK:
64 eWeight = WEIGHT_BOLD;
65 break;
67 default:
68 break;
71 if( rFont.GetItalic() != ITALIC_NONE )
72 eItalic = ITALIC_NORMAL;
74 return( maGlyphTree[ aFontName.getToken( 0, ';' ) ][ eWeight ][ eItalic ] );
78 void SVGFontExport::implCollectGlyphs()
80 ScopedVclPtrInstance< VirtualDevice > pVDev;
82 pVDev->EnableOutput( false );
84 for (auto const& elem : maObjects)
86 if( elem.HasRepresentation() )
88 const GDIMetaFile& rMtf = elem.GetRepresentation();
90 pVDev->Push();
92 for( size_t i = 0, nCount = rMtf.GetActionSize(); i < nCount; ++i )
94 OUString aText;
95 MetaAction* pAction = rMtf.GetAction( i );
96 const MetaActionType nType = pAction->GetType();
98 switch( nType )
100 case MetaActionType::TEXT:
102 const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
103 sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
104 aText = pA->GetText().copy( pA->GetIndex(), aLength );
106 break;
108 case MetaActionType::TEXTRECT:
110 const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
111 aText = pA->GetText();
113 break;
115 case MetaActionType::TEXTARRAY:
117 const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
118 sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
119 aText = pA->GetText().copy( pA->GetIndex(), aLength );
121 break;
123 case MetaActionType::STRETCHTEXT:
125 const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
126 sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
127 aText = pA->GetText().copy( pA->GetIndex(), aLength );
129 break;
131 default:
132 pAction->Execute( pVDev );
133 break;
136 if( !aText.isEmpty() )
138 GlyphSet& rGlyphSet = implGetGlyphSet( pVDev->GetFont() );
139 css::uno::Reference< css::i18n::XBreakIterator > xBI(
140 vcl::unohelper::CreateBreakIterator() );
142 if( xBI.is() )
144 const css::lang::Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
145 sal_Int32 nCurPos = 0, nLastPos = -1;
147 while( ( nCurPos < aText.getLength() ) && ( nCurPos > nLastPos ) )
149 sal_Int32 nCount2 = 1;
151 nLastPos = nCurPos;
152 nCurPos = xBI->nextCharacters( aText, nCurPos, rLocale,
153 css::i18n::CharacterIteratorMode::SKIPCELL,
154 nCount2, nCount2 );
156 rGlyphSet.insert( aText.copy( nLastPos, nCurPos - nLastPos ) );
159 else
161 const sal_Unicode* pStr = aText.getStr();
163 for( sal_uInt32 k = 0, nLen = aText.getLength(); k < nLen; ++k )
164 rGlyphSet.insert( OUString( pStr[ k ] ) );
169 pVDev->Pop();
175 void SVGFontExport::implEmbedFont( const vcl::Font& rFont )
177 if( !mrExport.IsEmbedFonts() )
178 return;
180 GlyphSet& rGlyphSet = implGetGlyphSet( rFont );
182 if( rGlyphSet.empty() )
183 return;
186 SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, u"defs"_ustr, true, true );
187 OUString aCurIdStr( u"EmbeddedFont_"_ustr );
188 OUString aUnitsPerEM( OUString::number( nFontEM ) );
189 ScopedVclPtrInstance< VirtualDevice > pVDev;
190 vcl::Font aFont( rFont );
192 aFont.SetFontSize( Size( 0, nFontEM ) );
193 aFont.SetAlignment( ALIGN_BASELINE );
195 pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));
196 pVDev->SetFont( aFont );
198 aCurIdStr += OUString::number( ++mnCurFontId );
199 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"id"_ustr, aCurIdStr );
200 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"horiz-adv-x"_ustr, aUnitsPerEM );
203 SvXMLElementExport aExp2( mrExport, XML_NAMESPACE_NONE, u"font"_ustr, true, true );
204 OUString aFontWeight;
205 OUString aFontStyle;
206 const Size aSize( nFontEM, nFontEM );
208 // Font Weight
209 if( aFont.GetWeight() != WEIGHT_NORMAL )
210 aFontWeight = "bold";
211 else
212 aFontWeight = "normal";
214 // Font Italic
215 if( aFont.GetItalic() != ITALIC_NONE )
216 aFontStyle = "italic";
217 else
218 aFontStyle = "normal";
220 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"font-family"_ustr, GetMappedFontName( rFont.GetFamilyName() ) );
221 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"units-per-em"_ustr, aUnitsPerEM );
222 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"font-weight"_ustr, aFontWeight );
223 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"font-style"_ustr, aFontStyle );
224 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"ascent"_ustr, OUString::number( pVDev->GetFontMetric().GetAscent() ) );
225 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"descent"_ustr, OUString::number( pVDev->GetFontMetric().GetDescent() ) );
228 SvXMLElementExport aExp3( mrExport, XML_NAMESPACE_NONE, u"font-face"_ustr, true, true );
231 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"horiz-adv-x"_ustr, OUString::number( aSize.Width() ) );
234 const Point aPos;
235 const tools::PolyPolygon aMissingGlyphPolyPoly( tools::Rectangle( aPos, aSize ) );
237 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"d"_ustr, SVGActionWriter::GetPathString( aMissingGlyphPolyPoly, false ) );
240 SvXMLElementExport aExp4( mrExport, XML_NAMESPACE_NONE, u"missing-glyph"_ustr, true, true );
243 for (auto const& glyph : rGlyphSet)
245 implEmbedGlyph( *pVDev, glyph);
252 void SVGFontExport::implEmbedGlyph( OutputDevice const & rOut, const OUString& rCellStr )
254 tools::PolyPolygon aPolyPoly;
256 if( !rOut.GetTextOutline( aPolyPoly, rCellStr ) )
257 return;
259 tools::Rectangle aBoundRect;
261 aPolyPoly.Scale( 1.0, -1.0 );
263 if (rCellStr == " " || !rOut.GetTextBoundRect(aBoundRect, rCellStr))
264 aBoundRect = tools::Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( rCellStr ), 0 ) );
266 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"unicode"_ustr, rCellStr );
267 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"horiz-adv-x"_ustr, OUString::number( aBoundRect.GetWidth() ) );
269 const OUString aPathString( SVGActionWriter::GetPathString( aPolyPoly, false ) );
270 if( !aPathString.isEmpty() )
272 mrExport.AddAttribute( XML_NAMESPACE_NONE, u"d"_ustr, aPathString );
276 SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, u"glyph"_ustr, true, true );
281 void SVGFontExport::EmbedFonts()
283 implCollectGlyphs();
285 for (auto const& glyph : maGlyphTree)
287 const FontWeightMap& rFontWeightMap = glyph.second;
288 for (auto const& fontWeight : rFontWeightMap)
290 const FontItalicMap& rFontItalicMap = fontWeight.second;
291 for (auto const& fontItalic : rFontItalicMap)
293 vcl::Font aFont;
295 aFont.SetFamilyName( glyph.first );
296 aFont.SetWeight( fontWeight.first );
297 aFont.SetItalic( fontItalic.first );
299 implEmbedFont( aFont );
306 OUString SVGFontExport::GetMappedFontName( std::u16string_view rFontName ) const
308 OUString aRet( o3tl::getToken(rFontName, 0, ';' ) );
310 if( mnCurFontId )
311 aRet += " embedded";
313 return aRet;
316 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */