Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2008 by Sun Microsystems, Inc.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "svgfontexport.hxx"
31 : : #include "svgfilter.hxx"
32 : : #include "svgwriter.hxx"
33 : :
34 : :
35 : : #include <vcl/unohelp.hxx>
36 : : #include <vcl/font.hxx>
37 : : #include <vcl/outdev.hxx>
38 : :
39 : : static const sal_Int32 nFontEM = 2048;
40 : :
41 : : // -----------------
42 : : // - SVGFontExport -
43 : : // -----------------
44 : :
45 : 0 : SVGFontExport::SVGFontExport( SVGExport& rExport, const ::std::vector< ObjectRepresentation >& rObjects ) :
46 : : mrExport( rExport ),
47 : : maObjects( rObjects ),
48 [ # # ]: 0 : mnCurFontId( 0 )
49 : : {
50 : 0 : }
51 : :
52 : : // -----------------------------------------------------------------------------
53 : :
54 : 0 : SVGFontExport::~SVGFontExport()
55 : : {
56 : 0 : }
57 : :
58 : : // -----------------------------------------------------------------------------
59 : :
60 : 0 : SVGFontExport::GlyphSet& SVGFontExport::implGetGlyphSet( const Font& rFont )
61 : : {
62 : 0 : FontWeight eWeight( WEIGHT_NORMAL );
63 : 0 : FontItalic eItalic( ITALIC_NONE );
64 [ # # ][ # # ]: 0 : ::rtl::OUString aFontName( rFont.GetName() );
65 : 0 : sal_Int32 nNextTokenPos( 0 );
66 : :
67 [ # # ][ # # ]: 0 : switch( rFont.GetWeight() )
68 : : {
69 : : case WEIGHT_BOLD:
70 : : case WEIGHT_ULTRABOLD:
71 : : case WEIGHT_BLACK:
72 : 0 : eWeight = WEIGHT_BOLD;
73 : 0 : break;
74 : :
75 : : default:
76 : 0 : break;
77 : : }
78 : :
79 [ # # ][ # # ]: 0 : if( rFont.GetItalic() != ITALIC_NONE )
80 : 0 : eItalic = ITALIC_NORMAL;
81 : :
82 [ # # ][ # # ]: 0 : return( maGlyphTree[ aFontName.getToken( 0, ';', nNextTokenPos ) ][ eWeight ][ eItalic ] );
[ # # ]
83 : : }
84 : :
85 : : // -----------------------------------------------------------------------------
86 : :
87 : 0 : void SVGFontExport::implCollectGlyphs()
88 : : {
89 [ # # ]: 0 : VirtualDevice aVDev;
90 [ # # ]: 0 : ObjectVector::const_iterator aIter( maObjects.begin() );
91 : :
92 [ # # ]: 0 : aVDev.EnableOutput( sal_False );
93 : :
94 [ # # ][ # # ]: 0 : while( aIter != maObjects.end() )
95 : : {
96 [ # # ]: 0 : if( (*aIter).HasRepresentation() )
97 : : {
98 : 0 : const GDIMetaFile& rMtf = (*aIter).GetRepresentation();
99 : :
100 [ # # ]: 0 : aVDev.Push();
101 : :
102 [ # # ][ # # ]: 0 : for( size_t i = 0, nCount = rMtf.GetActionSize(); i < nCount; ++i )
103 : : {
104 : 0 : ::rtl::OUString aText;
105 [ # # ]: 0 : MetaAction* pAction = rMtf.GetAction( i );
106 : 0 : const sal_uInt16 nType = pAction->GetType();
107 : :
108 [ # # # # : 0 : switch( nType )
# ]
109 : : {
110 : : case( META_TEXT_ACTION ):
111 : : {
112 : 0 : const MetaTextAction* pA = (const MetaTextAction*) pAction;
113 [ # # ][ # # ]: 0 : aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() );
[ # # ][ # # ]
[ # # ]
114 : : }
115 : 0 : break;
116 : :
117 : : case( META_TEXTRECT_ACTION ):
118 : : {
119 : 0 : const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
120 : 0 : aText = pA->GetText();
121 : : }
122 : 0 : break;
123 : :
124 : : case( META_TEXTARRAY_ACTION ):
125 : : {
126 : 0 : const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
127 [ # # ][ # # ]: 0 : aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() );
[ # # ][ # # ]
[ # # ]
128 : : }
129 : 0 : break;
130 : :
131 : : case( META_STRETCHTEXT_ACTION ):
132 : : {
133 : 0 : const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
134 [ # # ][ # # ]: 0 : aText = String( pA->GetText(), pA->GetIndex(), pA->GetLen() );
[ # # ][ # # ]
[ # # ]
135 : : }
136 : 0 : break;
137 : :
138 : : default:
139 [ # # ]: 0 : pAction->Execute( &aVDev );
140 : 0 : break;
141 : : }
142 : :
143 [ # # ]: 0 : if( !aText.isEmpty() )
144 : : {
145 [ # # ]: 0 : GlyphSet& rGlyphSet = implGetGlyphSet( aVDev.GetFont() );
146 : : ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xBI(
147 [ # # ]: 0 : ::vcl::unohelper::CreateBreakIterator() );
148 : :
149 [ # # ]: 0 : if( xBI.is() )
150 : : {
151 [ # # ][ # # ]: 0 : const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLocale();
152 : 0 : sal_Int32 nCurPos = 0, nLastPos = -1;
153 : :
154 [ # # ][ # # ]: 0 : while( ( nCurPos < aText.getLength() ) && ( nCurPos > nLastPos ) )
[ # # ]
155 : : {
156 : 0 : sal_Int32 nCount2 = 1;
157 : :
158 : 0 : nLastPos = nCurPos;
159 [ # # ]: 0 : nCurPos = xBI->nextCharacters( aText, nCurPos, rLocale,
160 : : ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL,
161 [ # # ]: 0 : nCount2, nCount2 );
162 : :
163 [ # # ]: 0 : rGlyphSet.insert( aText.copy( nLastPos, nCurPos - nLastPos ) );
164 : : }
165 : : }
166 : : else
167 : : {
168 : 0 : const sal_Unicode* pStr = aText.getStr();
169 : :
170 [ # # ]: 0 : for( sal_uInt32 k = 0, nLen = aText.getLength(); k < nLen; ++k )
171 [ # # ]: 0 : rGlyphSet.insert( rtl::OUString( pStr[ k ] ) );
172 : 0 : }
173 : : }
174 : 0 : }
175 : :
176 [ # # ]: 0 : aVDev.Pop();
177 : : }
178 : :
179 : 0 : ++aIter;
180 [ # # ]: 0 : }
181 : 0 : }
182 : :
183 : : // -----------------------------------------------------------------------------
184 : :
185 : 0 : void SVGFontExport::implEmbedFont( const Font& rFont )
186 : : {
187 [ # # ]: 0 : if( mrExport.IsEmbedFonts() )
188 : : {
189 : 0 : GlyphSet& rGlyphSet = implGetGlyphSet( rFont );
190 : :
191 [ # # ]: 0 : if( !rGlyphSet.empty() )
192 : : {
193 : 0 : GlyphSet::const_iterator aIter( rGlyphSet.begin() );
194 [ # # ]: 0 : const ::rtl::OUString aEmbeddedFontStr( B2UCONST( "EmbeddedFont_" ) );
195 : :
196 : : {
197 [ # # ]: 0 : SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "defs", sal_True, sal_True );
198 : 0 : ::rtl::OUString aCurIdStr( aEmbeddedFontStr );
199 : 0 : ::rtl::OUString aUnitsPerEM( ::rtl::OUString::valueOf( nFontEM ) );
200 [ # # ]: 0 : VirtualDevice aVDev;
201 [ # # ]: 0 : Font aFont( rFont );
202 : :
203 [ # # ]: 0 : aFont.SetSize( Size( 0, nFontEM ) );
204 [ # # ]: 0 : aFont.SetAlign( ALIGN_BASELINE );
205 : :
206 [ # # ][ # # ]: 0 : aVDev.SetMapMode( MAP_100TH_MM );
[ # # ]
207 [ # # ]: 0 : aVDev.SetFont( aFont );
208 : :
209 [ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", aCurIdStr += ::rtl::OUString::valueOf( ++mnCurFontId ) );
210 [ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", aUnitsPerEM );
211 : :
212 : : {
213 [ # # ]: 0 : SvXMLElementExport aExp2( mrExport, XML_NAMESPACE_NONE, "font", sal_True, sal_True );
214 : 0 : ::rtl::OUString aFontWeight;
215 : 0 : ::rtl::OUString aFontStyle;
216 : 0 : const Size aSize( nFontEM, nFontEM );
217 : :
218 : : // Font Weight
219 [ # # ][ # # ]: 0 : if( aFont.GetWeight() != WEIGHT_NORMAL )
220 [ # # ]: 0 : aFontWeight = B2UCONST( "bold" );
221 : : else
222 [ # # ]: 0 : aFontWeight = B2UCONST( "normal" );
223 : :
224 : : // Font Italic
225 [ # # ][ # # ]: 0 : if( aFont.GetItalic() != ITALIC_NONE )
226 [ # # ]: 0 : aFontStyle = B2UCONST( "italic" );
227 : : else
228 [ # # ]: 0 : aFontStyle = B2UCONST( "normal" );
229 : :
230 [ # # ][ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-family", GetMappedFontName( rFont.GetName() ) );
[ # # ][ # # ]
231 [ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "units-per-em", aUnitsPerEM );
232 [ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-weight", aFontWeight );
233 [ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-style", aFontStyle );
234 [ # # ][ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "ascent", ::rtl::OUString::valueOf( aVDev.GetFontMetric().GetAscent() ) );
[ # # ][ # # ]
235 [ # # ][ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "descent", ::rtl::OUString::valueOf( aVDev.GetFontMetric().GetDescent() ) );
[ # # ][ # # ]
236 : :
237 : : {
238 [ # # ][ # # ]: 0 : SvXMLElementExport aExp3( mrExport, XML_NAMESPACE_NONE, "font-face", sal_True, sal_True );
239 : : }
240 : :
241 [ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", ::rtl::OUString::valueOf( aSize.Width() ) );
242 : :
243 : : {
244 : 0 : const Point aPos;
245 [ # # ][ # # ]: 0 : const PolyPolygon aMissingGlyphPolyPoly( Rectangle( aPos, aSize ) );
[ # # ][ # # ]
246 : :
247 [ # # ][ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", SVGActionWriter::GetPathString( aMissingGlyphPolyPoly, sal_False ) );
248 : :
249 : : {
250 [ # # ][ # # ]: 0 : SvXMLElementExport aExp4( mrExport, XML_NAMESPACE_NONE, "missing-glyph", sal_True, sal_True );
251 [ # # ]: 0 : }
252 : : }
253 : :
254 [ # # ]: 0 : while( aIter != rGlyphSet.end() )
255 : : {
256 [ # # ]: 0 : implEmbedGlyph( aVDev, *aIter );
257 : 0 : ++aIter;
258 [ # # ]: 0 : }
259 [ # # ][ # # ]: 0 : }
[ # # ]
260 : 0 : }
261 : : }
262 : : }
263 : 0 : }
264 : :
265 : : // -----------------------------------------------------------------------------
266 : :
267 : 0 : void SVGFontExport::implEmbedGlyph( OutputDevice& rOut, const ::rtl::OUString& rCellStr )
268 : : {
269 [ # # ]: 0 : PolyPolygon aPolyPoly;
270 : 0 : const sal_Unicode nSpace = ' ';
271 : :
272 [ # # ][ # # ]: 0 : if( rOut.GetTextOutline( aPolyPoly, rCellStr ) )
[ # # ][ # # ]
273 : : {
274 [ # # ]: 0 : Rectangle aBoundRect;
275 : :
276 [ # # ]: 0 : aPolyPoly.Scale( 1.0, -1.0 );
277 : :
278 [ # # ][ # # ]: 0 : if( !rOut.GetTextBoundRect( aBoundRect, rCellStr ) )
[ # # ][ # # ]
279 [ # # ][ # # ]: 0 : aBoundRect = Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( rCellStr ), 0 ) );
[ # # ][ # # ]
280 : :
281 [ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "unicode", rCellStr );
282 : :
283 [ # # ][ # # ]: 0 : if( rCellStr[ 0 ] == nSpace && rCellStr.getLength() == 1 )
[ # # ]
284 [ # # ][ # # ]: 0 : aBoundRect = Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( rtl::OUString(' ') ), 0 ) );
[ # # ][ # # ]
285 : :
286 [ # # ][ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", ::rtl::OUString::valueOf( aBoundRect.GetWidth() ) );
287 : :
288 [ # # ]: 0 : const ::rtl::OUString aPathString( SVGActionWriter::GetPathString( aPolyPoly, sal_False ) );
289 [ # # ]: 0 : if( !aPathString.isEmpty() )
290 : : {
291 [ # # ]: 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", aPathString );
292 : : }
293 : :
294 : : {
295 [ # # ][ # # ]: 0 : SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "glyph", sal_True, sal_True );
296 : 0 : }
297 [ # # ]: 0 : }
298 : 0 : }
299 : :
300 : : // -----------------------------------------------------------------------------
301 : :
302 : 0 : void SVGFontExport::EmbedFonts()
303 : : {
304 [ # # ]: 0 : implCollectGlyphs();
305 : :
306 : 0 : GlyphTree::const_iterator aGlyphTreeIter( maGlyphTree.begin() );
307 : :
308 [ # # ]: 0 : while( aGlyphTreeIter != maGlyphTree.end() )
309 : : {
310 : 0 : const FontWeightMap& rFontWeightMap = (*aGlyphTreeIter).second;
311 : 0 : FontWeightMap::const_iterator aFontWeightIter( rFontWeightMap.begin() );
312 : :
313 [ # # ]: 0 : while( aFontWeightIter != rFontWeightMap.end() )
314 : : {
315 : 0 : const FontItalicMap& rFontItalicMap = (*aFontWeightIter).second;
316 : 0 : FontItalicMap::const_iterator aFontItalicIter( rFontItalicMap.begin() );
317 : :
318 [ # # ]: 0 : while( aFontItalicIter != rFontItalicMap.end() )
319 : : {
320 [ # # ]: 0 : Font aFont;
321 : :
322 [ # # ]: 0 : aFont.SetName( (*aGlyphTreeIter).first );
323 [ # # ]: 0 : aFont.SetWeight( (*aFontWeightIter).first );
324 [ # # ]: 0 : aFont.SetItalic( (*aFontItalicIter).first );
325 : :
326 [ # # ]: 0 : implEmbedFont( aFont );
327 : :
328 : 0 : ++aFontItalicIter;
329 [ # # ]: 0 : }
330 : :
331 : 0 : ++aFontWeightIter;
332 : : }
333 : :
334 : 0 : ++aGlyphTreeIter;
335 : : }
336 : 0 : }
337 : :
338 : : // -----------------------------------------------------------------------------
339 : :
340 : 0 : ::rtl::OUString SVGFontExport::GetMappedFontName( const ::rtl::OUString& rFontName ) const
341 : : {
342 : 0 : sal_Int32 nNextTokenPos( 0 );
343 : 0 : ::rtl::OUString aRet( rFontName.getToken( 0, ';', nNextTokenPos ) );
344 : :
345 [ # # ]: 0 : if( mnCurFontId )
346 [ # # ]: 0 : aRet += B2UCONST( " embedded" );
347 : :
348 : 0 : return aRet;
349 [ + - ][ + - ]: 18 : }
350 : :
351 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|