1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svgfontexport.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_filter.hxx"
35 #include "svgfontexport.hxx"
37 static const sal_Int32 nFontEM
= 2048;
43 SVGFontExport::SVGFontExport( SvXMLExport
& rExport
, const ::std::vector
< ObjectRepresentation
>& rObjects
) :
45 maObjects( rObjects
),
50 // -----------------------------------------------------------------------------
52 SVGFontExport::~SVGFontExport()
56 // -----------------------------------------------------------------------------
58 void SVGFontExport::implCollectGlyphs()
61 ObjectVector::const_iterator
aIter( maObjects
.begin() );
63 aVDev
.EnableOutput( sal_False
);
65 while( aIter
!= maObjects
.end() )
67 if( (*aIter
).HasRepresentation() )
69 const GDIMetaFile
& rMtf
= (*aIter
).GetRepresentation();
73 for( sal_uInt32 i
= 0, nCount
= rMtf
.GetActionCount(); i
< nCount
; ++i
)
75 ::rtl::OUString aText
;
76 MetaAction
* pAction
= rMtf
.GetAction( i
);
77 const USHORT nType
= pAction
->GetType();
81 case( META_TEXT_ACTION
):
83 const MetaTextAction
* pA
= (const MetaTextAction
*) pAction
;
84 aText
= String( pA
->GetText(), pA
->GetIndex(), pA
->GetLen() );
88 case( META_TEXTRECT_ACTION
):
90 const MetaTextRectAction
* pA
= (const MetaTextRectAction
*) pAction
;
91 aText
= pA
->GetText();
95 case( META_TEXTARRAY_ACTION
):
97 const MetaTextArrayAction
* pA
= (const MetaTextArrayAction
*) pAction
;
98 aText
= String( pA
->GetText(), pA
->GetIndex(), pA
->GetLen() );
102 case( META_STRETCHTEXT_ACTION
):
104 const MetaStretchTextAction
* pA
= (const MetaStretchTextAction
*) pAction
;
105 aText
= String( pA
->GetText(), pA
->GetIndex(), pA
->GetLen() );
110 pAction
->Execute( &aVDev
);
114 if( aText
.getLength() )
116 const String
& rFontName
= aVDev
.GetFont().GetName();
117 const sal_Unicode
* pStr
= aText
.getStr();
119 for( sal_uInt32 j
= 0, nLen
= aText
.getLength(); j
< nLen
; ++j
)
120 maGlyphs
[ rFontName
].insert( pStr
[ j
] );
131 // -----------------------------------------------------------------------------
133 void SVGFontExport::implEmbedFont( const ::rtl::OUString
& rFontName
, const ::std::set
< sal_Unicode
>& rGlyphs
)
135 #ifdef _SVG_EMBED_FONTS
136 ::std::set
< sal_Unicode
>::const_iterator
aIter( rGlyphs
.begin() );
137 const ::rtl::OUString
aEmbeddedFontStr( B2UCONST( "EmbeddedFont_" ) );
140 SvXMLElementExport
aExp( mrExport
, XML_NAMESPACE_NONE
, "defs", TRUE
, TRUE
);
141 ::rtl::OUString
aCurIdStr( aEmbeddedFontStr
);
142 ::rtl::OUString
aUnitsPerEM( SVGActionWriter::GetValueString( nFontEM
) );
144 Font
aFont( rFontName
, Size( 0, nFontEM
) );
146 aVDev
.SetMapMode( MAP_100TH_MM
);
147 aFont
.SetAlign( ALIGN_BASELINE
);
148 aVDev
.SetFont( aFont
);
150 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "id", aCurIdStr
+= SVGActionWriter::GetValueString( ++mnCurFontId
) );
151 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "horiz-adv-x", aUnitsPerEM
);
154 SvXMLElementExport
aExp2( mrExport
, XML_NAMESPACE_NONE
, "font", TRUE
, TRUE
);
156 Size
aSize( nFontEM
, nFontEM
);
157 PolyPolygon
aMissingGlyphPolyPoly( Rectangle( aPos
, aSize
) );
159 aMissingGlyphPolyPoly
.Move( 0, -nFontEM
);
160 aMissingGlyphPolyPoly
.Scale( 1.0, -1.0 );
162 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "font-family", GetMappedFontName( rFontName
) );
163 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "units-per-em", aUnitsPerEM
);
164 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "ascent", SVGActionWriter::GetValueString( aVDev
.GetFontMetric().GetAscent() ) );
165 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "descent", SVGActionWriter::GetValueString( aVDev
.GetFontMetric().GetDescent() ) );
168 SvXMLElementExport
aExp3( mrExport
, XML_NAMESPACE_NONE
, "font-face", TRUE
, TRUE
);
171 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "horiz-adv-x", SVGActionWriter::GetValueString( aSize
.Width() ) );
174 SvXMLElementExport
aExp3( mrExport
, XML_NAMESPACE_NONE
, "missing-glyph", TRUE
, TRUE
);
176 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "style", B2UCONST( "fill:none;stroke:black;stroke-width:33" ) );
177 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "d", SVGActionWriter::GetPathString( aMissingGlyphPolyPoly
, sal_False
) );
180 SvXMLElementExport
aExp4( mrExport
, XML_NAMESPACE_NONE
, "path", TRUE
, TRUE
);
184 while( aIter
!= rGlyphs
.end() )
186 implEmbedGlyph( aVDev
, ::rtl::OUString( *aIter
) );
194 // -----------------------------------------------------------------------------
196 void SVGFontExport::implEmbedGlyph( OutputDevice
& rOut
, const ::rtl::OUString
& rGlyphs
)
198 PolyPolygon aPolyPoly
;
199 ::rtl::OUString
aStr( rGlyphs
);
200 const sal_Unicode nSpace
= ' ';
202 if( rOut
.GetTextOutline( aPolyPoly
, aStr
) )
204 Rectangle aBoundRect
;
206 aPolyPoly
.Scale( 1.0, -1.0 );
208 if( !rOut
.GetTextBoundRect( aBoundRect
, aStr
) )
209 aBoundRect
= Rectangle( Point( 0, 0 ), Size( rOut
.GetTextWidth( aStr
), 0 ) );
211 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "unicode", aStr
);
213 if( rGlyphs
[ 0 ] == nSpace
)
214 aBoundRect
= Rectangle( Point( 0, 0 ), Size( rOut
.GetTextWidth( sal_Unicode( 'x' ) ), 0 ) );
216 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "horiz-adv-x", SVGActionWriter::GetValueString( aBoundRect
.GetWidth() ) );
219 SvXMLElementExport
aExp( mrExport
, XML_NAMESPACE_NONE
, "glyph", TRUE
, TRUE
);
220 const ::rtl::OUString
aPathString( SVGActionWriter::GetPathString( aPolyPoly
, sal_False
) );
222 if( aPathString
.getLength() )
224 mrExport
.AddAttribute( XML_NAMESPACE_NONE
, "d", aPathString
);
227 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_NONE
, B2UCONST( "path" ), TRUE
, TRUE
);
234 // -----------------------------------------------------------------------------
236 void SVGFontExport::EmbedFonts()
240 GlyphMap::const_iterator
aIter( maGlyphs
.begin() );
242 while( aIter
!= maGlyphs
.end() )
244 implEmbedFont( (*aIter
).first
, (*aIter
).second
);
249 // -----------------------------------------------------------------------------
251 ::rtl::OUString
SVGFontExport::GetMappedFontName( const ::rtl::OUString
& rFontName
) const
253 ::rtl::OUString
aRet( String( rFontName
).GetToken( 0, ';' ) );
255 #ifdef _SVG_EMBED_FONTS
257 aRet
+= B2UCONST( " embedded" );