Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "svgfilter.hxx"
21 : #include "svgfontexport.hxx"
22 : #include "svgwriter.hxx"
23 :
24 : #include <rtl/crc.h>
25 : #include <vcl/unohelp.hxx>
26 : #include <vcl/outdev.hxx>
27 : #include <vcl/settings.hxx>
28 : #include <tools/helpers.hxx>
29 : #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
30 : #include <sax/tools/converter.hxx>
31 :
32 : #include <boost/scoped_ptr.hpp>
33 : #include <boost/shared_array.hpp>
34 :
35 :
36 : static const char aXMLElemG[] = "g";
37 : static const char aXMLElemA[] = "a";
38 : static const char aXMLElemDefs[] = "defs";
39 : static const char aXMLElemLine[] = "line";
40 : static const char aXMLElemRect[] = "rect";
41 : static const char aXMLElemEllipse[] = "ellipse";
42 : static const char aXMLElemPath[] = "path";
43 : static const char aXMLElemText[] = "text";
44 : static const char aXMLElemTspan[] = "tspan";
45 : static const char aXMLElemImage[] = "image";
46 : static const char aXMLElemMask[] = "mask";
47 : static const char aXMLElemPattern[] = "pattern";
48 : static const char aXMLElemLinearGradient[] = "linearGradient";
49 : static const char aXMLElemRadialGradient[] = "radialGradient";
50 : static const char aXMLElemStop[] = "stop";
51 :
52 : static const char aXMLAttrTransform[] = "transform";
53 : static const char aXMLAttrStyle[] = "style";
54 : static const char aXMLAttrId[] = "id";
55 : static const char aXMLAttrD[] = "d";
56 : static const char aXMLAttrX[] = "x";
57 : static const char aXMLAttrY[] = "y";
58 : static const char aXMLAttrX1[] = "x1";
59 : static const char aXMLAttrY1[] = "y1";
60 : static const char aXMLAttrX2[] = "x2";
61 : static const char aXMLAttrY2[] = "y2";
62 : static const char aXMLAttrCX[] = "cx";
63 : static const char aXMLAttrCY[] = "cy";
64 : static const char aXMLAttrR[] = "r";
65 : static const char aXMLAttrRX[] = "rx";
66 : static const char aXMLAttrRY[] = "ry";
67 : static const char aXMLAttrWidth[] = "width";
68 : static const char aXMLAttrHeight[] = "height";
69 : static const char aXMLAttrStroke[] = "stroke";
70 : static const char aXMLAttrStrokeOpacity[] = "stroke-opacity";
71 : static const char aXMLAttrStrokeWidth[] = "stroke-width";
72 : static const char aXMLAttrStrokeDashArray[] = "stroke-dasharray";
73 : static const char aXMLAttrFill[] = "fill";
74 : static const char aXMLAttrFillOpacity[] = "fill-opacity";
75 : static const char aXMLAttrFontFamily[] = "font-family";
76 : static const char aXMLAttrFontSize[] = "font-size";
77 : static const char aXMLAttrFontStyle[] = "font-style";
78 : static const char aXMLAttrFontWeight[] = "font-weight";
79 : static const char aXMLAttrTextDecoration[] = "text-decoration";
80 : static const char aXMLAttrXLinkHRef[] = "xlink:href";
81 : static const char aXMLAttrGradientUnits[] = "gradientUnits";
82 : static const char aXMLAttrPatternUnits[] = "patternUnits";
83 : static const char aXMLAttrOffset[] = "offset";
84 : static const char aXMLAttrStopColor[] = "stop-color";
85 : static const char aXMLAttrStrokeLinejoin[] = "stroke-linejoin";
86 : static const char aXMLAttrStrokeLinecap[] = "stroke-linecap";
87 :
88 :
89 : #define NSPREFIX "ooo:"
90 :
91 : static const char aOOOAttrNumberingType[] = NSPREFIX "numbering-type";
92 :
93 :
94 : static sal_Char const XML_UNO_NAME_NRULE_NUMBERINGTYPE[] = "NumberingType";
95 : static sal_Char const XML_UNO_NAME_NRULE_BULLET_CHAR[] = "BulletChar";
96 :
97 0 : SVGAttributeWriter::SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport )
98 : : mrExport( rExport )
99 : , mrFontExport( rFontExport )
100 : , mpElemFont( NULL )
101 : , mpElemPaint( NULL )
102 : , maLineJoin(basegfx::B2DLINEJOIN_NONE)
103 0 : , maLineCap(css::drawing::LineCap_BUTT)
104 : {
105 0 : }
106 :
107 0 : SVGAttributeWriter::~SVGAttributeWriter()
108 : {
109 0 : if( mpElemPaint )
110 0 : delete mpElemPaint;
111 0 : if( mpElemFont )
112 0 : delete mpElemFont;
113 0 : }
114 :
115 0 : double SVGAttributeWriter::ImplRound( double fValue, sal_Int32 nDecs )
116 : {
117 0 : return( floor( fValue * pow( 10.0, (int)nDecs ) + 0.5 ) / pow( 10.0, (int)nDecs ) );
118 : }
119 :
120 0 : void SVGAttributeWriter::ImplGetColorStr( const Color& rColor, OUString& rColorStr )
121 : {
122 0 : if( rColor.GetTransparency() == 255 )
123 0 : rColorStr = "none";
124 : else
125 : {
126 0 : rColorStr = "rgb(" + OUString::number(rColor.GetRed()) + "," + OUString::number(rColor.GetGreen()) +
127 0 : "," + OUString::number(rColor.GetBlue()) + ")";
128 : }
129 0 : }
130 :
131 0 : void SVGAttributeWriter::AddColorAttr( const char* pColorAttrName,
132 : const char* pColorOpacityAttrName,
133 : const Color& rColor )
134 : {
135 0 : OUString aColor, aColorOpacity;
136 :
137 0 : ImplGetColorStr( rColor, aColor );
138 :
139 0 : if( rColor.GetTransparency() > 0 && rColor.GetTransparency() < 255 )
140 0 : aColorOpacity = OUString::number( ImplRound( ( 255.0 - rColor.GetTransparency() ) / 255.0 ) );
141 :
142 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, pColorAttrName, aColor );
143 :
144 0 : if( !aColorOpacity.isEmpty() && mrExport.IsUseOpacity() )
145 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, pColorOpacityAttrName, aColorOpacity );
146 0 : }
147 :
148 0 : void SVGAttributeWriter::AddPaintAttr( const Color& rLineColor, const Color& rFillColor,
149 : const Rectangle* pObjBoundRect, const Gradient* pFillGradient )
150 : {
151 : // Fill
152 0 : if( pObjBoundRect && pFillGradient )
153 : {
154 0 : OUString aGradientId;
155 :
156 0 : AddGradientDef( *pObjBoundRect, *pFillGradient, aGradientId );
157 :
158 0 : if( !aGradientId.isEmpty() )
159 : {
160 0 : OUString aGradientURL = "url(#" + aGradientId + ")";
161 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFill, aGradientURL );
162 0 : }
163 : }
164 : else
165 0 : AddColorAttr( aXMLAttrFill, aXMLAttrFillOpacity, rFillColor );
166 :
167 : // Stroke
168 0 : AddColorAttr( aXMLAttrStroke, aXMLAttrStrokeOpacity, rLineColor );
169 0 : }
170 :
171 0 : void SVGAttributeWriter::AddGradientDef( const Rectangle& rObjRect, const Gradient& rGradient, OUString& rGradientId )
172 : {
173 0 : if( rObjRect.GetWidth() && rObjRect.GetHeight() &&
174 0 : ( rGradient.GetStyle() == GradientStyle_LINEAR || rGradient.GetStyle() == GradientStyle_AXIAL ||
175 0 : rGradient.GetStyle() == GradientStyle_RADIAL || rGradient.GetStyle() == GradientStyle_ELLIPTICAL ) )
176 : {
177 0 : SvXMLElementExport aDesc( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
178 0 : Color aStartColor( rGradient.GetStartColor() ), aEndColor( rGradient.GetEndColor() );
179 0 : sal_uInt16 nAngle = rGradient.GetAngle() % 3600;
180 0 : Point aObjRectCenter( rObjRect.Center() );
181 0 : Polygon aPoly( rObjRect );
182 : static sal_Int32 nCurGradientId = 1;
183 :
184 0 : aPoly.Rotate( aObjRectCenter, nAngle );
185 0 : Rectangle aRect( aPoly.GetBoundRect() );
186 :
187 : // adjust start/end colors with intensities
188 0 : aStartColor.SetRed( (sal_uInt8)( (long) aStartColor.GetRed() * rGradient.GetStartIntensity() ) / 100 );
189 0 : aStartColor.SetGreen( (sal_uInt8)( (long) aStartColor.GetGreen() * rGradient.GetStartIntensity() ) / 100 );
190 0 : aStartColor.SetBlue( (sal_uInt8)( (long) aStartColor.GetBlue() * rGradient.GetStartIntensity() ) / 100 );
191 :
192 0 : aEndColor.SetRed( (sal_uInt8)( (long) aEndColor.GetRed() * rGradient.GetEndIntensity() ) / 100 );
193 0 : aEndColor.SetGreen( (sal_uInt8)( (long) aEndColor.GetGreen() * rGradient.GetEndIntensity() ) / 100 );
194 0 : aEndColor.SetBlue( (sal_uInt8)( (long) aEndColor.GetBlue() * rGradient.GetEndIntensity() ) / 100 );
195 :
196 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId,
197 0 : ( rGradientId = "Gradient_" ) += OUString::number( nCurGradientId++ ) );
198 :
199 : {
200 0 : boost::scoped_ptr< SvXMLElementExport > apGradient;
201 0 : OUString aColorStr;
202 :
203 0 : if( rGradient.GetStyle() == GradientStyle_LINEAR || rGradient.GetStyle() == GradientStyle_AXIAL )
204 : {
205 0 : Polygon aLinePoly( 2 );
206 :
207 0 : aLinePoly[ 0 ] = Point( aObjRectCenter.X(), aRect.Top() );
208 0 : aLinePoly[ 1 ] = Point( aObjRectCenter.X(), aRect.Bottom() );
209 :
210 0 : aLinePoly.Rotate( aObjRectCenter, nAngle );
211 :
212 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrGradientUnits, "userSpaceOnUse" );
213 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, OUString::number( aLinePoly[ 0 ].X() ) );
214 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, OUString::number( aLinePoly[ 0 ].Y() ) );
215 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, OUString::number( aLinePoly[ 1 ].X() ) );
216 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, OUString::number( aLinePoly[ 1 ].Y() ) );
217 :
218 0 : apGradient.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemLinearGradient, true, true ) );
219 :
220 : // write stop values
221 0 : double fBorder = static_cast< double >( rGradient.GetBorder() ) *
222 0 : ( ( rGradient.GetStyle() == GradientStyle_AXIAL ) ? 0.005 : 0.01 );
223 :
224 0 : ImplGetColorStr( ( rGradient.GetStyle() == GradientStyle_AXIAL ) ? aEndColor : aStartColor, aColorStr );
225 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( fBorder ) );
226 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
227 :
228 : {
229 0 : SvXMLElementExport aDesc2( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
230 : }
231 :
232 0 : if( rGradient.GetStyle() == GradientStyle_AXIAL )
233 : {
234 0 : ImplGetColorStr( aStartColor, aColorStr );
235 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( 0.5 ) );
236 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
237 :
238 : {
239 0 : SvXMLElementExport aDesc3( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
240 : }
241 : }
242 :
243 0 : if( rGradient.GetStyle() != GradientStyle_AXIAL )
244 0 : fBorder = 0.0;
245 :
246 0 : ImplGetColorStr( aEndColor, aColorStr );
247 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( ImplRound( 1.0 - fBorder ) ) );
248 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
249 :
250 : {
251 0 : SvXMLElementExport aDesc4( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
252 0 : }
253 : }
254 : else
255 : {
256 0 : const double fCenterX = rObjRect.Left() + rObjRect.GetWidth() * rGradient.GetOfsX() * 0.01;
257 0 : const double fCenterY = rObjRect.Top() + rObjRect.GetHeight() * rGradient.GetOfsY() * 0.01;
258 0 : const double fRadius = sqrt( static_cast< double >( rObjRect.GetWidth() ) * rObjRect.GetWidth() +
259 0 : rObjRect.GetHeight() * rObjRect.GetHeight() ) * 0.5;
260 :
261 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrGradientUnits, "userSpaceOnUse" );
262 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, OUString::number( ImplRound( fCenterX ) ) );
263 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCY, OUString::number( ImplRound( fCenterY ) ) );
264 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrR, OUString::number( ImplRound( fRadius ) ) );
265 :
266 0 : apGradient.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemRadialGradient, true, true ) );
267 :
268 : // write stop values
269 0 : ImplGetColorStr( aEndColor, aColorStr );
270 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( 0.0 ) );
271 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
272 :
273 : {
274 0 : SvXMLElementExport aDesc5( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
275 : }
276 :
277 0 : ImplGetColorStr( aStartColor, aColorStr );
278 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset,
279 0 : OUString::number( ImplRound( 1.0 - rGradient.GetBorder() * 0.01 ) ) );
280 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
281 :
282 : {
283 0 : SvXMLElementExport aDesc6( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
284 : }
285 0 : }
286 0 : }
287 : }
288 : else
289 0 : rGradientId = "";
290 0 : }
291 :
292 0 : void SVGAttributeWriter::SetFontAttr( const Font& rFont )
293 : {
294 0 : if( rFont != maCurFont )
295 : {
296 0 : OUString aFontStyle, aTextDecoration;
297 : sal_Int32 nFontWeight;
298 :
299 0 : maCurFont = rFont;
300 :
301 : // Font Family
302 0 : setFontFamily();
303 :
304 : // Font Size
305 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontSize,
306 0 : OUString::number( rFont.GetHeight() ) + "px" );
307 :
308 : // Font Style
309 0 : if( rFont.GetItalic() != ITALIC_NONE )
310 : {
311 0 : if( rFont.GetItalic() == ITALIC_OBLIQUE )
312 0 : aFontStyle = "oblique";
313 : else
314 0 : aFontStyle = "italic";
315 : }
316 : else
317 0 : aFontStyle = "normal";
318 :
319 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontStyle, aFontStyle );
320 :
321 : // Font Weight
322 0 : switch( rFont.GetWeight() )
323 : {
324 0 : case WEIGHT_THIN: nFontWeight = 100; break;
325 0 : case WEIGHT_ULTRALIGHT: nFontWeight = 200; break;
326 0 : case WEIGHT_LIGHT: nFontWeight = 300; break;
327 0 : case WEIGHT_SEMILIGHT: nFontWeight = 400; break;
328 0 : case WEIGHT_NORMAL: nFontWeight = 400; break;
329 0 : case WEIGHT_MEDIUM: nFontWeight = 500; break;
330 0 : case WEIGHT_SEMIBOLD: nFontWeight = 600; break;
331 0 : case WEIGHT_BOLD: nFontWeight = 700; break;
332 0 : case WEIGHT_ULTRABOLD: nFontWeight = 800; break;
333 0 : case WEIGHT_BLACK: nFontWeight = 900; break;
334 0 : default: nFontWeight = 400; break;
335 : }
336 :
337 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontWeight, OUString::number( nFontWeight ) );
338 :
339 0 : if( mrExport.IsUseNativeTextDecoration() )
340 : {
341 0 : if( rFont.GetUnderline() != UNDERLINE_NONE || rFont.GetStrikeout() != STRIKEOUT_NONE )
342 : {
343 0 : if( rFont.GetUnderline() != UNDERLINE_NONE )
344 0 : aTextDecoration = "underline ";
345 :
346 0 : if( rFont.GetStrikeout() != STRIKEOUT_NONE )
347 0 : aTextDecoration += "line-through ";
348 : }
349 : else
350 0 : aTextDecoration = "none";
351 :
352 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTextDecoration, aTextDecoration );
353 : }
354 :
355 0 : startFontSettings();
356 : }
357 0 : }
358 :
359 0 : void SVGAttributeWriter::startFontSettings()
360 : {
361 0 : endFontSettings();
362 0 : if( mrExport.IsUsePositionedCharacters() )
363 : {
364 0 : mpElemFont = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
365 : }
366 : else
367 : {
368 0 : mpElemFont = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, true, true );
369 : }
370 0 : }
371 :
372 0 : void SVGAttributeWriter::endFontSettings()
373 : {
374 0 : if( mpElemFont )
375 : {
376 0 : delete mpElemFont;
377 0 : mpElemFont = NULL;
378 : }
379 0 : }
380 :
381 0 : void SVGAttributeWriter::setFontFamily()
382 : {
383 0 : if( mrExport.IsUsePositionedCharacters() )
384 : {
385 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontFamily, mrFontExport.GetMappedFontName( maCurFont.GetName() ) );
386 : }
387 : else
388 : {
389 0 : sal_Int32 nNextTokenPos( 0 );
390 0 : const OUString& rsFontName = maCurFont.GetName();
391 0 : OUString sFontFamily( rsFontName.getToken( 0, ';', nNextTokenPos ) );
392 0 : FontPitch ePitch = maCurFont.GetPitch();
393 0 : if( ePitch == PITCH_FIXED )
394 : {
395 0 : sFontFamily += ", monospace";
396 : }
397 : else
398 : {
399 0 : FontFamily eFamily = maCurFont.GetFamily();
400 0 : if( eFamily == FAMILY_ROMAN )
401 0 : sFontFamily += ", serif";
402 0 : else if( eFamily == FAMILY_SWISS )
403 0 : sFontFamily += ", sans-serif";
404 : }
405 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontFamily, sFontFamily );
406 : }
407 0 : }
408 :
409 0 : SVGTextWriter::SVGTextWriter( SVGExport& rExport )
410 : : mrExport( rExport ),
411 : mpContext( NULL ),
412 : mpVDev( NULL ),
413 : mbIsTextShapeStarted( sal_False ),
414 : mrTextShape(),
415 : msShapeId(),
416 : mrParagraphEnumeration(),
417 : mrCurrentTextParagraph(),
418 : mrTextPortionEnumeration(),
419 : mrCurrentTextPortion(),
420 : mpTextEmbeddedBitmapMtf( NULL ),
421 : mpTargetMapMode( NULL ),
422 : mpTextShapeElem( NULL ),
423 : mpTextParagraphElem( NULL ),
424 : mpTextPositionElem( NULL ),
425 : mnLeftTextPortionLength( 0 ),
426 : maTextPos(0,0),
427 : mnTextWidth(0),
428 : mbPositioningNeeded( sal_False ),
429 : mbIsNewListItem( sal_False ),
430 : meNumberingType(0),
431 : mcBulletChar(0),
432 : maBulletListItemMap(),
433 : mbIsListLevelStyleImage( sal_False ),
434 : mbLineBreak( sal_False ),
435 : mbIsURLField( sal_False ),
436 : msUrl(),
437 : mbIsPlacehlolderShape( sal_False ),
438 : mbIWS( sal_False ),
439 : maCurrentFont(),
440 0 : maParentFont()
441 : {
442 0 : }
443 :
444 0 : SVGTextWriter::~SVGTextWriter()
445 : {
446 0 : endTextParagraph();
447 0 : }
448 :
449 0 : void SVGTextWriter::implRegisterInterface( const Reference< XInterface >& rxIf )
450 : {
451 0 : if( rxIf.is() )
452 0 : (mrExport.getInterfaceToIdentifierMapper()).registerReference( rxIf );
453 0 : }
454 :
455 0 : const OUString & SVGTextWriter::implGetValidIDFromInterface( const Reference< XInterface >& rxIf )
456 : {
457 0 : return (mrExport.getInterfaceToIdentifierMapper()).getIdentifier( rxIf );
458 : }
459 :
460 0 : void SVGTextWriter::implMap( const Size& rSz, Size& rDstSz ) const
461 : {
462 0 : if( mpVDev && mpTargetMapMode )
463 0 : rDstSz = mpVDev->LogicToLogic( rSz, mpVDev->GetMapMode(), *mpTargetMapMode );
464 : else
465 : OSL_FAIL( "SVGTextWriter::implMap: invalid virtual device or map mode." );
466 0 : }
467 :
468 0 : void SVGTextWriter::implMap( const Point& rPt, Point& rDstPt ) const
469 : {
470 0 : if( mpVDev && mpTargetMapMode )
471 0 : rDstPt = mpVDev->LogicToLogic( rPt, mpVDev->GetMapMode(), *mpTargetMapMode );
472 : else
473 : OSL_FAIL( "SVGTextWriter::implMap: invalid virtual device or map mode." );
474 0 : }
475 :
476 0 : void SVGTextWriter::implSetCurrentFont()
477 : {
478 0 : if( mpVDev )
479 : {
480 0 : maCurrentFont = mpVDev->GetFont();
481 0 : Size aSz;
482 :
483 0 : implMap( Size( 0, maCurrentFont.GetHeight() ), aSz );
484 :
485 0 : maCurrentFont.SetHeight( aSz.Height() );
486 : }
487 : else
488 : {
489 : OSL_FAIL( "SVGTextWriter::implSetCorrectFontHeight: invalid virtual device." );
490 : }
491 0 : }
492 :
493 : template< typename SubType >
494 0 : sal_Bool SVGTextWriter::implGetTextPosition( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty )
495 : {
496 0 : const SubType* pA = (const SubType*) pAction;
497 0 : sal_uInt16 nLength = pA->GetLen();
498 0 : rbEmpty = ( nLength == 0 );
499 0 : if( !rbEmpty )
500 : {
501 0 : raPos = pA->GetPoint();
502 0 : return sal_True;
503 : }
504 0 : return sal_False;
505 : }
506 :
507 : template<>
508 0 : sal_Bool SVGTextWriter::implGetTextPosition<MetaTextRectAction>( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty )
509 : {
510 0 : const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
511 0 : sal_uInt16 nLength = pA->GetText().getLength();
512 0 : rbEmpty = ( nLength == 0 );
513 0 : if( !rbEmpty )
514 : {
515 0 : raPos = pA->GetRect().TopLeft();
516 0 : return sal_True;
517 : }
518 0 : return sal_False;
519 : }
520 :
521 : template< typename SubType >
522 0 : sal_Bool SVGTextWriter::implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, sal_Bool& rbEmpty )
523 : {
524 0 : const SubType* pA = (const SubType*) pAction;
525 0 : raPos = pA->GetPoint();
526 0 : rbEmpty = sal_False;
527 0 : return sal_True;
528 : }
529 :
530 : /** setTextPosition
531 : * Set the start position of the next line of text. In case no text is found
532 : * the current action index is updated to the index value we reached while
533 : * searching for text.
534 : *
535 : * @returns {sal_Int32}
536 : * -2 if no text found and end of line is reached
537 : * -1 if no text found and end of paragraph is reached
538 : * 0 if no text found and end of text shape is reached
539 : * 1 if text found!
540 : */
541 0 : sal_Int32 SVGTextWriter::setTextPosition( const GDIMetaFile& rMtf, sal_uLong& nCurAction )
542 : {
543 0 : Point aPos;
544 0 : sal_uLong nCount = rMtf.GetActionSize();
545 0 : sal_Bool bEOL = sal_False;
546 0 : sal_Bool bEOP = sal_False;
547 0 : sal_Bool bETS = sal_False;
548 0 : sal_Bool bConfigured = sal_False;
549 0 : sal_Bool bEmpty = sal_True;
550 :
551 0 : sal_uLong nActionIndex = nCurAction + 1;
552 0 : for( ; nActionIndex < nCount; ++nActionIndex )
553 : {
554 0 : const MetaAction* pAction = rMtf.GetAction( nActionIndex );
555 0 : const sal_uInt16 nType = pAction->GetType();
556 :
557 0 : switch( nType )
558 : {
559 : case( META_TEXT_ACTION ):
560 : {
561 0 : bConfigured = implGetTextPosition<MetaTextAction>( pAction, aPos, bEmpty );
562 : }
563 0 : break;
564 :
565 : case( META_TEXTRECT_ACTION ):
566 : {
567 0 : bConfigured = implGetTextPosition<MetaTextRectAction>( pAction, aPos, bEmpty );
568 : }
569 0 : break;
570 :
571 : case( META_TEXTARRAY_ACTION ):
572 : {
573 0 : bConfigured = implGetTextPosition<MetaTextArrayAction>( pAction, aPos, bEmpty );
574 : }
575 0 : break;
576 :
577 : case( META_STRETCHTEXT_ACTION ):
578 : {
579 0 : bConfigured = implGetTextPosition<MetaStretchTextAction>( pAction, aPos, bEmpty );
580 : }
581 0 : break;
582 :
583 : case( META_BMPSCALE_ACTION ):
584 : {
585 0 : bConfigured = implGetTextPositionFromBitmap<MetaBmpScaleAction>( pAction, aPos, bEmpty );
586 : }
587 0 : break;
588 :
589 : case( META_BMPEXSCALE_ACTION ):
590 : {
591 0 : bConfigured = implGetTextPositionFromBitmap<MetaBmpExScaleAction>( pAction, aPos, bEmpty );
592 : }
593 0 : break;
594 :
595 : // If we reach the end of the current line, paragraph or text shape
596 : // without finding any text we stop searching
597 : case( META_COMMENT_ACTION ):
598 : {
599 0 : const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
600 0 : const OString& rsComment = pA->GetComment();
601 0 : if( rsComment.equalsIgnoreAsciiCase( "XTEXT_EOL" ) )
602 : {
603 0 : bEOL = true;
604 : }
605 0 : else if( rsComment.equalsIgnoreAsciiCase( "XTEXT_EOP" ) )
606 : {
607 0 : bEOP = true;
608 :
609 0 : OUString sContent;
610 0 : while( nextTextPortion() )
611 : {
612 0 : sContent = mrCurrentTextPortion->getString();
613 0 : if( sContent.isEmpty() )
614 : {
615 0 : continue;
616 : }
617 : else
618 : {
619 0 : if( sContent.equalsAscii( "\n" ) )
620 0 : mbLineBreak = sal_True;
621 : }
622 : }
623 0 : if( nextParagraph() )
624 : {
625 0 : while( nextTextPortion() )
626 : {
627 0 : sContent = mrCurrentTextPortion->getString();
628 0 : if( sContent.isEmpty() )
629 : {
630 0 : continue;
631 : }
632 : else
633 : {
634 0 : if( sContent.equalsAscii( "\n" ) )
635 0 : mbLineBreak = sal_True;
636 : }
637 : }
638 0 : }
639 : }
640 0 : else if( rsComment.equalsIgnoreAsciiCase( "XTEXT_PAINTSHAPE_END" ) )
641 : {
642 0 : bETS = true;
643 : }
644 : }
645 0 : break;
646 : }
647 0 : if( bConfigured || bEOL || bEOP || bETS ) break;
648 : }
649 0 : implMap( aPos, maTextPos );
650 :
651 0 : if( bEmpty )
652 : {
653 0 : nCurAction = nActionIndex;
654 0 : return ( (bEOL) ? -2 : ( (bEOP) ? -1 : 0 ) );
655 : }
656 : else
657 : {
658 0 : return 1;
659 : }
660 : }
661 :
662 0 : void SVGTextWriter::setTextProperties( const GDIMetaFile& rMtf, sal_uLong nCurAction )
663 : {
664 0 : sal_uLong nCount = rMtf.GetActionSize();
665 0 : sal_Bool bEOP = sal_False;
666 0 : sal_Bool bConfigured = sal_False;
667 0 : for( sal_uLong nActionIndex = nCurAction + 1; nActionIndex < nCount; ++nActionIndex )
668 : {
669 0 : const MetaAction* pAction = rMtf.GetAction( nActionIndex );
670 0 : const sal_uInt16 nType = pAction->GetType();
671 0 : switch( nType )
672 : {
673 : case( META_TEXTLINECOLOR_ACTION ):
674 : case( META_TEXTFILLCOLOR_ACTION ):
675 : case( META_TEXTCOLOR_ACTION ):
676 : case( META_TEXTALIGN_ACTION ):
677 : case( META_FONT_ACTION ):
678 : case( META_LAYOUTMODE_ACTION ):
679 : {
680 0 : ( (MetaAction*) pAction )->Execute( mpVDev );
681 : }
682 0 : break;
683 :
684 : case( META_TEXT_ACTION ):
685 : {
686 0 : const MetaTextAction* pA = (const MetaTextAction*) pAction;
687 0 : if( pA->GetLen() > 2 )
688 0 : bConfigured = true;
689 : }
690 0 : break;
691 : case( META_TEXTRECT_ACTION ):
692 : {
693 0 : const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
694 0 : if( pA->GetText().getLength() > 2 )
695 0 : bConfigured = true;
696 : }
697 0 : break;
698 : case( META_TEXTARRAY_ACTION ):
699 : {
700 0 : const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
701 0 : if( pA->GetLen() > 2 )
702 0 : bConfigured = true;
703 : }
704 0 : break;
705 : case( META_STRETCHTEXT_ACTION ):
706 : {
707 0 : const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
708 0 : if( pA->GetLen() > 2 )
709 0 : bConfigured = true;
710 : }
711 0 : break;
712 : // If we reach the end of the paragraph without finding any text
713 : // we stop searching
714 : case( META_COMMENT_ACTION ):
715 : {
716 0 : const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
717 0 : const OString& rsComment = pA->GetComment();
718 0 : if( rsComment.equalsIgnoreAsciiCase( "XTEXT_EOP" ) )
719 : {
720 0 : bEOP = true;
721 : }
722 : }
723 0 : break;
724 : }
725 0 : if( bConfigured || bEOP ) break;
726 : }
727 0 : }
728 :
729 0 : void SVGTextWriter::addFontAttributes( sal_Bool bIsTextContainer )
730 : {
731 0 : implSetCurrentFont();
732 :
733 0 : if( maCurrentFont != maParentFont )
734 : {
735 0 : const OUString& rsCurFontName = maCurrentFont.GetName();
736 0 : long int nCurFontSize = maCurrentFont.GetHeight();
737 0 : FontItalic eCurFontItalic = maCurrentFont.GetItalic();
738 0 : FontWeight eCurFontWeight = maCurrentFont.GetWeight();
739 :
740 0 : const OUString& rsParFontName = maParentFont.GetName();
741 0 : long int nParFontSize = maParentFont.GetHeight();
742 0 : FontItalic eParFontItalic = maParentFont.GetItalic();
743 0 : FontWeight eParFontWeight = maParentFont.GetWeight();
744 :
745 :
746 : // Font Family
747 0 : if( rsCurFontName != rsParFontName )
748 : {
749 0 : implSetFontFamily();
750 : }
751 :
752 : // Font Size
753 0 : if( nCurFontSize != nParFontSize )
754 : {
755 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontSize,
756 0 : OUString::number( nCurFontSize ) + "px" );
757 : }
758 :
759 : // Font Style
760 0 : if( eCurFontItalic != eParFontItalic )
761 : {
762 0 : OUString sFontStyle;
763 0 : if( eCurFontItalic != ITALIC_NONE )
764 : {
765 0 : if( eCurFontItalic == ITALIC_OBLIQUE )
766 0 : sFontStyle = "oblique";
767 : else
768 0 : sFontStyle = "italic";
769 : }
770 : else
771 : {
772 0 : sFontStyle = "normal";
773 : }
774 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontStyle, sFontStyle );
775 : }
776 :
777 : // Font Weight
778 0 : if( eCurFontWeight != eParFontWeight )
779 : {
780 : sal_Int32 nFontWeight;
781 0 : switch( eCurFontWeight )
782 : {
783 0 : case WEIGHT_THIN: nFontWeight = 100; break;
784 0 : case WEIGHT_ULTRALIGHT: nFontWeight = 200; break;
785 0 : case WEIGHT_LIGHT: nFontWeight = 300; break;
786 0 : case WEIGHT_SEMILIGHT: nFontWeight = 400; break;
787 0 : case WEIGHT_NORMAL: nFontWeight = 400; break;
788 0 : case WEIGHT_MEDIUM: nFontWeight = 500; break;
789 0 : case WEIGHT_SEMIBOLD: nFontWeight = 600; break;
790 0 : case WEIGHT_BOLD: nFontWeight = 700; break;
791 0 : case WEIGHT_ULTRABOLD: nFontWeight = 800; break;
792 0 : case WEIGHT_BLACK: nFontWeight = 900; break;
793 0 : default: nFontWeight = 400; break;
794 : }
795 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontWeight, OUString::number( nFontWeight ) );
796 : }
797 :
798 0 : if( bIsTextContainer )
799 0 : maParentFont = maCurrentFont;
800 : }
801 :
802 0 : if( mrExport.IsUseNativeTextDecoration() )
803 : {
804 0 : FontUnderline eCurFontUnderline = maCurrentFont.GetUnderline();
805 0 : FontStrikeout eCurFontStrikeout = maCurrentFont.GetStrikeout();
806 :
807 0 : FontUnderline eParFontUnderline = maParentFont.GetUnderline();
808 0 : FontStrikeout eParFontStrikeout = maParentFont.GetStrikeout();
809 :
810 0 : OUString sTextDecoration;
811 :
812 0 : if( eCurFontUnderline != eParFontUnderline )
813 : {
814 0 : if( eCurFontUnderline != UNDERLINE_NONE )
815 0 : sTextDecoration = "underline ";
816 : }
817 0 : if( eCurFontStrikeout != eParFontStrikeout )
818 : {
819 0 : if( eCurFontStrikeout != STRIKEOUT_NONE )
820 0 : sTextDecoration += "line-through ";
821 : }
822 0 : if( !sTextDecoration.isEmpty() )
823 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTextDecoration, sTextDecoration );
824 : }
825 0 : }
826 :
827 0 : void SVGTextWriter::implSetFontFamily()
828 : {
829 0 : sal_Int32 nNextTokenPos( 0 );
830 0 : const OUString& rsFontName = maCurrentFont.GetName();
831 0 : OUString sFontFamily( rsFontName.getToken( 0, ';', nNextTokenPos ) );
832 0 : FontPitch ePitch = maCurrentFont.GetPitch();
833 0 : if( ePitch == PITCH_FIXED )
834 : {
835 0 : sFontFamily += ", monospace";
836 : }
837 : else
838 : {
839 0 : FontFamily eFamily = maCurrentFont.GetFamily();
840 0 : if( eFamily == FAMILY_ROMAN )
841 0 : sFontFamily += ", serif";
842 0 : else if( eFamily == FAMILY_SWISS )
843 0 : sFontFamily += ", sans-serif";
844 : }
845 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontFamily, sFontFamily );
846 0 : }
847 :
848 0 : sal_Bool SVGTextWriter::createParagraphEnumeration()
849 : {
850 0 : if( mrTextShape.is() )
851 : {
852 0 : msShapeId = implGetValidIDFromInterface( mrTextShape );
853 :
854 0 : Reference< XEnumerationAccess > xEnumerationAccess( mrTextShape, UNO_QUERY_THROW );
855 0 : Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
856 0 : if( xEnumeration.is() )
857 : {
858 0 : mrParagraphEnumeration.set( xEnumeration );
859 0 : return sal_True;
860 : }
861 : else
862 : {
863 : OSL_FAIL( "SVGTextWriter::createParagraphEnumeration: no valid xEnumeration interface found." );
864 0 : }
865 : }
866 : else
867 : {
868 : OSL_FAIL( "SVGTextWriter::createParagraphEnumeration: no valid XText interface found." );
869 : }
870 0 : return sal_False;
871 : }
872 :
873 0 : sal_Bool SVGTextWriter::nextParagraph()
874 : {
875 0 : mrTextPortionEnumeration.clear();
876 0 : mrCurrentTextParagraph.clear();
877 0 : mbIsNewListItem = sal_False;
878 0 : mbIsListLevelStyleImage = sal_False;
879 :
880 0 : if( mrParagraphEnumeration.is() && mrParagraphEnumeration->hasMoreElements() )
881 : {
882 0 : Reference < XTextContent > xTextContent( mrParagraphEnumeration->nextElement(), UNO_QUERY_THROW );
883 0 : if( xTextContent.is() )
884 : {
885 0 : Reference< XServiceInfo > xServiceInfo( xTextContent, UNO_QUERY_THROW );
886 0 : if( xServiceInfo.is() )
887 : {
888 : #if OSL_DEBUG_LEVEL > 0
889 : OUString sInfo;
890 : #endif
891 0 : if( xServiceInfo->supportsService( "com.sun.star.text.Paragraph" ) )
892 : {
893 0 : mrCurrentTextParagraph.set( xTextContent );
894 0 : Reference< XPropertySet > xPropSet( xTextContent, UNO_QUERY_THROW );
895 0 : Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
896 0 : if( xPropSetInfo->hasPropertyByName( "NumberingLevel" ) )
897 : {
898 0 : sal_Int16 nListLevel = 0;
899 0 : if( xPropSet->getPropertyValue( "NumberingLevel" ) >>= nListLevel )
900 : {
901 0 : mbIsNewListItem = sal_True;
902 : #if OSL_DEBUG_LEVEL > 0
903 : sInfo = "NumberingLevel: " + OUString::number( nListLevel );
904 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "style", sInfo );
905 : #endif
906 0 : Reference< XIndexReplace > xNumRules;
907 0 : if( xPropSetInfo->hasPropertyByName( "NumberingRules" ) )
908 : {
909 0 : xPropSet->getPropertyValue( "NumberingRules" ) >>= xNumRules;
910 : }
911 0 : if( xNumRules.is() && ( nListLevel < xNumRules->getCount() ) )
912 : {
913 0 : sal_Bool bIsNumbered = sal_True;
914 0 : OUString msNumberingIsNumber("NumberingIsNumber");
915 0 : if( xPropSetInfo->hasPropertyByName( msNumberingIsNumber ) )
916 : {
917 0 : if( !(xPropSet->getPropertyValue( msNumberingIsNumber ) >>= bIsNumbered ) )
918 : {
919 : OSL_FAIL( "numbered paragraph without number info" );
920 0 : bIsNumbered = sal_False;
921 : }
922 : #if OSL_DEBUG_LEVEL > 0
923 : if( bIsNumbered )
924 : {
925 : sInfo = "true";
926 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "is-numbered", sInfo );
927 : }
928 : #endif
929 : }
930 0 : mbIsNewListItem = bIsNumbered;
931 :
932 0 : if( bIsNumbered )
933 : {
934 0 : Sequence<PropertyValue> aProps;
935 0 : if( xNumRules->getByIndex( nListLevel ) >>= aProps )
936 : {
937 0 : sal_Int16 eType = NumberingType::CHAR_SPECIAL;
938 0 : sal_Unicode cBullet = 0xf095;
939 0 : const sal_Int32 nCount = aProps.getLength();
940 0 : const PropertyValue* pPropArray = aProps.getConstArray();
941 0 : for( sal_Int32 i = 0; i < nCount; ++i )
942 : {
943 0 : const PropertyValue& rProp = pPropArray[i];
944 0 : if( rProp.Name.equalsAsciiL( XML_UNO_NAME_NRULE_NUMBERINGTYPE, sizeof(XML_UNO_NAME_NRULE_NUMBERINGTYPE)-1 ) )
945 : {
946 0 : rProp.Value >>= eType;
947 : }
948 0 : else if( rProp.Name.equalsAsciiL( XML_UNO_NAME_NRULE_BULLET_CHAR, sizeof(XML_UNO_NAME_NRULE_BULLET_CHAR)-1 ) )
949 : {
950 0 : OUString sValue;
951 0 : rProp.Value >>= sValue;
952 0 : if( !sValue.isEmpty() )
953 : {
954 0 : cBullet = (sal_Unicode)sValue[0];
955 0 : }
956 : }
957 : }
958 0 : meNumberingType = eType;
959 0 : mbIsListLevelStyleImage = ( NumberingType::BITMAP == meNumberingType );
960 0 : if( NumberingType::CHAR_SPECIAL == meNumberingType )
961 : {
962 0 : if( cBullet )
963 : {
964 0 : if( cBullet < ' ' )
965 : {
966 0 : cBullet = 0xF000 + 149;
967 : }
968 0 : mcBulletChar = cBullet;
969 : #if OSL_DEBUG_LEVEL > 0
970 : sInfo = OUString::number( (sal_Int32) cBullet );
971 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "bullet-char", sInfo );
972 : #endif
973 : }
974 :
975 : }
976 0 : }
977 0 : }
978 0 : }
979 :
980 : }
981 : }
982 :
983 0 : Reference< XEnumerationAccess > xEnumerationAccess( xTextContent, UNO_QUERY_THROW );
984 0 : Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW );
985 0 : if( xEnumeration.is() && xEnumeration->hasMoreElements() )
986 : {
987 0 : mrTextPortionEnumeration.set( xEnumeration );
988 0 : }
989 : #if OSL_DEBUG_LEVEL > 0
990 : sInfo = "Paragraph";
991 : #endif
992 : }
993 0 : else if( xServiceInfo->supportsService( "com.sun.star.text.Table" ) )
994 : {
995 : OSL_FAIL( "SVGTextWriter::nextParagraph: text tables are not handled." );
996 : #if OSL_DEBUG_LEVEL > 0
997 : sInfo = "Table";
998 : #endif
999 : }
1000 : else
1001 : {
1002 : OSL_FAIL( "SVGTextWriter::nextParagraph: Unknown text content." );
1003 0 : return sal_False;
1004 : }
1005 : #if OSL_DEBUG_LEVEL > 0
1006 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", sInfo );
1007 : SvXMLElementExport aParaElem( mrExport, XML_NAMESPACE_NONE, "desc", mbIWS, mbIWS );
1008 : #endif
1009 : }
1010 : else
1011 : {
1012 : OSL_FAIL( "SVGTextWriter::nextParagraph: no XServiceInfo interface available for text content." );
1013 0 : return sal_False;
1014 : }
1015 :
1016 0 : const OUString& rParagraphId = implGetValidIDFromInterface( xTextContent );
1017 0 : if( !rParagraphId.isEmpty() )
1018 : {
1019 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId );
1020 : }
1021 0 : return sal_True;
1022 0 : }
1023 : }
1024 :
1025 0 : return sal_False;
1026 : }
1027 :
1028 0 : sal_Bool SVGTextWriter::nextTextPortion()
1029 : {
1030 0 : mrCurrentTextPortion.clear();
1031 0 : mbIsURLField = sal_False;
1032 0 : mbIsPlacehlolderShape = sal_False;
1033 0 : if( mrTextPortionEnumeration.is() && mrTextPortionEnumeration->hasMoreElements() )
1034 : {
1035 : #if OSL_DEBUG_LEVEL > 0
1036 : OUString sInfo;
1037 : #endif
1038 0 : Reference< XPropertySet > xPortionPropSet( mrTextPortionEnumeration->nextElement(), UNO_QUERY );
1039 0 : Reference< XPropertySetInfo > xPortionPropInfo( xPortionPropSet->getPropertySetInfo() );
1040 0 : Reference < XTextRange > xPortionTextRange( xPortionPropSet, UNO_QUERY);
1041 0 : if( xPortionPropSet.is() && xPortionPropInfo.is()
1042 0 : && xPortionPropInfo->hasPropertyByName( "TextPortionType" ) )
1043 : {
1044 : #if OSL_DEBUG_LEVEL > 0
1045 : OUString sPortionType;
1046 : if( xPortionPropSet->getPropertyValue( "TextPortionType" ) >>= sPortionType )
1047 : {
1048 : sInfo = "type: " + sPortionType + "; ";
1049 : }
1050 : #endif
1051 0 : if( xPortionTextRange.is() )
1052 : {
1053 : #if OSL_DEBUG_LEVEL > 0
1054 : sInfo += "content: " + xPortionTextRange->getString() + "; ";
1055 : #endif
1056 0 : mrCurrentTextPortion.set( xPortionTextRange );
1057 :
1058 0 : Reference < XPropertySet > xRangePropSet( xPortionTextRange, UNO_QUERY );
1059 0 : if( xRangePropSet.is() && xRangePropSet->getPropertySetInfo()->hasPropertyByName( "TextField" ) )
1060 : {
1061 0 : Reference < XTextField > xTextField( xRangePropSet->getPropertyValue( "TextField" ), UNO_QUERY );
1062 0 : if( xTextField.is() )
1063 : {
1064 0 : const OUString sServicePrefix("com.sun.star.text.textfield.");
1065 0 : const OUString sPresentationServicePrefix("com.sun.star.presentation.TextField.");
1066 :
1067 0 : Reference< XServiceInfo > xService( xTextField, UNO_QUERY );
1068 0 : const Sequence< OUString > aServices = xService->getSupportedServiceNames();
1069 :
1070 0 : const OUString* pNames = aServices.getConstArray();
1071 0 : sal_Int32 nCount = aServices.getLength();
1072 :
1073 0 : OUString sFieldName; // service name postfix of current field
1074 :
1075 : // search for TextField service name
1076 0 : while( nCount-- )
1077 : {
1078 0 : if ( pNames->matchIgnoreAsciiCase( sServicePrefix ) )
1079 : {
1080 : // TextField found => postfix is field type!
1081 0 : sFieldName = pNames->copy( sServicePrefix.getLength() );
1082 0 : break;
1083 : }
1084 0 : else if( 0 == pNames->compareTo( sPresentationServicePrefix, sPresentationServicePrefix.getLength() ) )
1085 : {
1086 : // TextField found => postfix is field type!
1087 0 : sFieldName = pNames->copy( sPresentationServicePrefix.getLength() );
1088 0 : break;
1089 : }
1090 :
1091 0 : ++pNames;
1092 : }
1093 :
1094 : #if OSL_DEBUG_LEVEL > 0
1095 : sInfo += "text field type: " + sFieldName + "; " +
1096 : "content: " + xTextField->getPresentation( /* show command: */ sal_False ) + "; ";
1097 : #endif
1098 0 : if( sFieldName.equalsAscii( "DateTime" ) || sFieldName.equalsAscii( "Header" )
1099 0 : || sFieldName.equalsAscii( "Footer" ) || sFieldName.equalsAscii( "PageNumber" ) )
1100 : {
1101 0 : mbIsPlacehlolderShape = sal_True;
1102 : }
1103 : else
1104 : {
1105 0 : mbIsURLField = sFieldName.equalsAscii( "URL" );
1106 :
1107 0 : if( mbIsURLField )
1108 : {
1109 0 : Reference<XPropertySet> xTextFieldPropSet(xTextField, UNO_QUERY);
1110 0 : if( xTextFieldPropSet.is() )
1111 : {
1112 0 : OUString sURL;
1113 0 : if( ( xTextFieldPropSet->getPropertyValue( sFieldName ) ) >>= sURL )
1114 : {
1115 : #if OSL_DEBUG_LEVEL > 0
1116 : sInfo += "url: ";
1117 : sInfo += mrExport.GetRelativeReference( sURL );
1118 : #endif
1119 0 : msUrl = mrExport.GetRelativeReference( sURL );
1120 0 : if( !msUrl.isEmpty() )
1121 : {
1122 0 : implRegisterInterface( xPortionTextRange );
1123 :
1124 0 : const OUString& rTextPortionId = implGetValidIDFromInterface( xPortionTextRange );
1125 0 : if( !rTextPortionId.isEmpty() )
1126 : {
1127 0 : msHyperlinkIdList += rTextPortionId;
1128 0 : msHyperlinkIdList += " ";
1129 : }
1130 : }
1131 0 : }
1132 0 : }
1133 : }
1134 0 : }
1135 0 : }
1136 0 : }
1137 : }
1138 : #if OSL_DEBUG_LEVEL > 0
1139 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextPortion" );
1140 : SvXMLElementExport aPortionElem( mrExport, XML_NAMESPACE_NONE, "desc", mbIWS, mbIWS );
1141 : mrExport.GetDocHandler()->characters( sInfo );
1142 : #endif
1143 0 : return sal_True;
1144 0 : }
1145 : }
1146 :
1147 0 : return sal_False;
1148 : }
1149 :
1150 0 : void SVGTextWriter::startTextShape()
1151 : {
1152 0 : if( mpTextShapeElem )
1153 : {
1154 : OSL_FAIL( "SVGTextWriter::startTextShape: text shape already defined." );
1155 : }
1156 :
1157 : {
1158 0 : mbIsTextShapeStarted = sal_True;
1159 0 : maParentFont = Font();
1160 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextShape" );
1161 0 : mpTextShapeElem = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemText, true, mbIWS );
1162 0 : startTextParagraph();
1163 : }
1164 0 : }
1165 :
1166 0 : void SVGTextWriter::endTextShape()
1167 : {
1168 0 : endTextParagraph();
1169 0 : if( mrTextShape.is() )
1170 0 : mrTextShape.clear();
1171 0 : if( mrParagraphEnumeration.is() )
1172 0 : mrParagraphEnumeration.clear();
1173 0 : if( mrCurrentTextParagraph.is() )
1174 0 : mrCurrentTextParagraph.clear();
1175 0 : if( mpTextShapeElem )
1176 : {
1177 0 : delete mpTextShapeElem;
1178 0 : mpTextShapeElem = NULL;
1179 : }
1180 0 : mbIsTextShapeStarted = sal_False;
1181 : // these need to be invoked after the <text> element has been closed
1182 0 : implExportHyperlinkIds();
1183 0 : implWriteBulletChars();
1184 0 : implWriteEmbeddedBitmaps();
1185 :
1186 0 : }
1187 :
1188 0 : void SVGTextWriter::startTextParagraph()
1189 : {
1190 0 : endTextParagraph();
1191 0 : nextParagraph();
1192 0 : if( mbIsNewListItem )
1193 : {
1194 0 : OUString sNumberingType;
1195 0 : switch( meNumberingType )
1196 : {
1197 : case( NumberingType::CHAR_SPECIAL ):
1198 0 : sNumberingType = "bullet-style";
1199 0 : break;
1200 : case( NumberingType::BITMAP ):
1201 0 : sNumberingType = "image-style";
1202 0 : break;
1203 : default:
1204 0 : sNumberingType = "number-style";
1205 0 : break;
1206 : }
1207 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aOOOAttrNumberingType, sNumberingType );
1208 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "ListItem" );
1209 : }
1210 : else
1211 : {
1212 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextParagraph" );
1213 : }
1214 0 : maParentFont = Font();
1215 0 : addFontAttributes( /* isTexTContainer: */ true );
1216 0 : mpTextParagraphElem = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
1217 0 : if( !mbIsListLevelStyleImage )
1218 : {
1219 0 : startTextPosition();
1220 : }
1221 0 : }
1222 :
1223 0 : void SVGTextWriter::endTextParagraph()
1224 : {
1225 0 : mrCurrentTextPortion.clear();
1226 0 : endTextPosition();
1227 0 : mbIsNewListItem = sal_False;
1228 0 : mbIsListLevelStyleImage = sal_False;
1229 0 : mbPositioningNeeded = sal_False;
1230 :
1231 0 : if( mpTextParagraphElem )
1232 : {
1233 0 : delete mpTextParagraphElem;
1234 0 : mpTextParagraphElem = NULL;
1235 : }
1236 :
1237 0 : }
1238 :
1239 0 : void SVGTextWriter::startTextPosition( sal_Bool bExportX, sal_Bool bExportY )
1240 : {
1241 0 : endTextPosition();
1242 0 : mnTextWidth = 0;
1243 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextPosition" );
1244 0 : if( bExportX )
1245 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( maTextPos.X() ) );
1246 0 : if( bExportY )
1247 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( maTextPos.Y() ) );
1248 :
1249 : // if text is rotated, set transform matrix at new tspan element
1250 0 : const Font& rFont = mpVDev->GetFont();
1251 0 : if( rFont.GetOrientation() )
1252 : {
1253 0 : Point aRot( maTextPos );
1254 : OUString aTransform =
1255 0 : OUString("translate(") + OUString::number( aRot.X() ) +
1256 0 : "," + OUString::number( aRot.Y() ) + ")" +
1257 0 : " rotate(" + OUString::number( rFont.GetOrientation() * -0.1 ) +
1258 0 : ")" + " translate(" + OUString::number( -aRot.X() ) +
1259 0 : "," + OUString::number( -aRot.Y() ) + ")";
1260 :
1261 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
1262 : }
1263 :
1264 0 : mpTextPositionElem = new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
1265 0 : }
1266 :
1267 0 : void SVGTextWriter::endTextPosition()
1268 : {
1269 0 : if( mpTextPositionElem )
1270 : {
1271 0 : delete mpTextPositionElem;
1272 0 : mpTextPositionElem = NULL;
1273 : }
1274 0 : }
1275 :
1276 0 : void SVGTextWriter::implExportHyperlinkIds()
1277 : {
1278 0 : if( !msHyperlinkIdList.isEmpty() )
1279 : {
1280 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "HyperlinkIdList" );
1281 0 : SvXMLElementExport aDescElem( mrExport, XML_NAMESPACE_NONE, "desc", true, false );
1282 0 : mrExport.GetDocHandler()->characters( msHyperlinkIdList.trim() );
1283 0 : msHyperlinkIdList = "";
1284 : }
1285 0 : }
1286 :
1287 0 : void SVGTextWriter::implWriteBulletChars()
1288 : {
1289 0 : if( maBulletListItemMap.empty() )
1290 0 : return;
1291 :
1292 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "BulletChars" );
1293 0 : SvXMLElementExport aGroupElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
1294 :
1295 0 : BulletListItemInfoMap::const_iterator it = maBulletListItemMap.begin();
1296 0 : BulletListItemInfoMap::const_iterator end = maBulletListItemMap.end();
1297 0 : OUString sId, sPosition, sScaling, sRefId;
1298 0 : for( ; it != end; ++it )
1299 : {
1300 : // <g id="?" > (used by animations)
1301 : {
1302 : // As id we use the id of the text portion placeholder wrapped
1303 : // by bullet-char(*)
1304 0 : sId = "bullet-char(" + it->first+ ")";
1305 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
1306 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "BulletChar" );
1307 0 : SvXMLElementExport aBulletCharElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
1308 :
1309 : // <g transform="translate(x,y)" >
1310 : {
1311 0 : const BulletListItemInfo& rInfo = it->second;
1312 :
1313 : // Add positioning attribute through a translation
1314 0 : sPosition = "translate(" +
1315 0 : OUString::number( rInfo.aPos.X() ) +
1316 0 : "," + OUString::number( rInfo.aPos.Y() ) + ")";
1317 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "transform", sPosition );
1318 :
1319 0 : mpContext->AddPaintAttr( COL_TRANSPARENT, rInfo.aColor );
1320 :
1321 0 : SvXMLElementExport aPositioningElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
1322 :
1323 : // <use transform="scale(font-size)" xlink:ref="/" >
1324 : {
1325 : // Add size attribute through a scaling
1326 0 : sScaling = "scale(" + OUString::number( rInfo.nFontSize ) +
1327 0 : "," + OUString::number( rInfo.nFontSize )+ ")";
1328 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "transform", sScaling );
1329 :
1330 : // Add ref attribute
1331 0 : sRefId = "#bullet-char-template(" +
1332 0 : OUString::number( ( rInfo.cBulletChar ) ) +
1333 0 : ")";
1334 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
1335 :
1336 0 : SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", true, true );
1337 0 : }
1338 0 : } // close aPositioningElem
1339 : } // close aBulletCharElem
1340 : }
1341 :
1342 :
1343 : // clear the map
1344 0 : maBulletListItemMap.clear();
1345 : }
1346 :
1347 : template< typename MetaBitmapActionType >
1348 0 : void SVGTextWriter::writeBitmapPlaceholder( const MetaBitmapActionType* pAction )
1349 : {
1350 : // text position element
1351 0 : const Point& rPos = pAction->GetPoint();
1352 0 : implMap( rPos, maTextPos );
1353 0 : startTextPosition();
1354 0 : mbPositioningNeeded = sal_True;
1355 0 : if( mbIsNewListItem )
1356 : {
1357 0 : mbIsNewListItem = sal_False;
1358 0 : mbIsListLevelStyleImage = sal_False;
1359 : }
1360 :
1361 : // bitmap placeholder element
1362 0 : sal_uLong nId = SVGActionWriter::GetChecksum( pAction );
1363 0 : OUString sId = "bitmap-placeholder(" + msShapeId + "." +
1364 0 : OUString::number( nId ) + ")";
1365 :
1366 : {
1367 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
1368 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "BitmapPlaceholder" );
1369 0 : SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
1370 : }
1371 0 : endTextPosition();
1372 0 : }
1373 :
1374 0 : void SVGTextWriter::implWriteEmbeddedBitmaps()
1375 : {
1376 0 : if( mpTextEmbeddedBitmapMtf && mpTextEmbeddedBitmapMtf->GetActionSize() )
1377 : {
1378 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "EmbeddedBitmaps" );
1379 0 : SvXMLElementExport aEmbBitmapGroupElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
1380 :
1381 0 : const GDIMetaFile& rMtf = *mpTextEmbeddedBitmapMtf;
1382 :
1383 0 : OUString sId, sRefId;
1384 0 : sal_uLong nId, nChecksum = 0;
1385 0 : Point aPt;
1386 0 : Size aSz;
1387 0 : sal_uLong nCount = rMtf.GetActionSize();
1388 0 : for( sal_uLong nCurAction = 0; nCurAction < nCount; nCurAction++ )
1389 : {
1390 :
1391 0 : const MetaAction* pAction = rMtf.GetAction( nCurAction );
1392 0 : const sal_uInt16 nType = pAction->GetType();
1393 :
1394 0 : switch( nType )
1395 : {
1396 : case( META_BMPSCALE_ACTION ):
1397 : {
1398 0 : const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
1399 0 : nChecksum = pA->GetBitmap().GetChecksum();
1400 0 : aPt = pA->GetPoint();
1401 0 : aSz = pA->GetSize();
1402 : }
1403 0 : break;
1404 : case( META_BMPEXSCALE_ACTION ):
1405 : {
1406 0 : const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
1407 0 : nChecksum = pA->GetBitmapEx().GetChecksum();
1408 0 : aPt = pA->GetPoint();
1409 0 : aSz = pA->GetSize();
1410 : }
1411 0 : break;
1412 : }
1413 :
1414 : // <g id="?" > (used by animations)
1415 : {
1416 : // embedded bitmap id
1417 0 : nId = SVGActionWriter::GetChecksum( pAction );
1418 0 : sId = "embedded-bitmap(";
1419 0 : sId += msShapeId;
1420 0 : sId += ".";
1421 0 : sId += OUString::number( nId );
1422 0 : sId += ")";
1423 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
1424 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "EmbeddedBitmap" );
1425 :
1426 0 : SvXMLElementExport aEmbBitmapElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
1427 :
1428 : // <use x="?" y="?" xlink:ref="?" >
1429 : {
1430 : // referenced bitmap template
1431 0 : sRefId = "#bitmap(";
1432 0 : sRefId += OUString::number( nChecksum );
1433 0 : sRefId += ")";
1434 :
1435 0 : Point aPoint;
1436 0 : Size aSize;
1437 0 : implMap( aPt, aPoint );
1438 0 : implMap( aSz, aSize );
1439 :
1440 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aPoint.X() ) );
1441 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPoint.Y() ) );
1442 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
1443 :
1444 0 : SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", true, true );
1445 0 : }
1446 : } // close aEmbBitmapElem
1447 0 : }
1448 : }
1449 0 : }
1450 :
1451 0 : void SVGTextWriter::writeTextPortion( const Point& rPos,
1452 : const OUString& rText,
1453 : sal_Bool bApplyMapping )
1454 : {
1455 0 : if( rText.isEmpty() )
1456 0 : return;
1457 :
1458 0 : mbLineBreak = sal_False;
1459 :
1460 0 : if( !mbIsNewListItem || mbIsListLevelStyleImage )
1461 : {
1462 0 : bool bNotSync = true;
1463 0 : OUString sContent;
1464 : sal_Int32 nStartPos;
1465 0 : while( bNotSync )
1466 : {
1467 0 : if( mnLeftTextPortionLength <= 0 || !mrCurrentTextPortion.is() )
1468 : {
1469 0 : if( !nextTextPortion() )
1470 0 : break;
1471 : else
1472 : {
1473 0 : sContent = mrCurrentTextPortion->getString();
1474 0 : if( mbIsURLField && sContent.isEmpty() )
1475 : {
1476 0 : Reference < XPropertySet > xPropSet( mrCurrentTextPortion, UNO_QUERY );
1477 0 : Reference < XTextField > xTextField( xPropSet->getPropertyValue( "TextField" ), UNO_QUERY );
1478 0 : sContent = xTextField->getPresentation( /* show command: */ sal_False );
1479 0 : if( sContent.isEmpty() )
1480 0 : OSL_FAIL( "SVGTextWriter::writeTextPortion: content of URL TextField is empty." );
1481 : }
1482 0 : mnLeftTextPortionLength = sContent.getLength();
1483 : }
1484 : }
1485 : else
1486 : {
1487 0 : sContent = mrCurrentTextPortion->getString();
1488 : }
1489 :
1490 0 : nStartPos = sContent.getLength() - mnLeftTextPortionLength;
1491 0 : if( nStartPos < 0 ) nStartPos = 0;
1492 0 : mnLeftTextPortionLength -= rText.getLength();
1493 :
1494 0 : if( sContent.isEmpty() )
1495 0 : continue;
1496 0 : if( sContent.equalsAscii( "\n" ) )
1497 0 : mbLineBreak = sal_True;
1498 0 : if( sContent.match( rText, nStartPos ) )
1499 0 : bNotSync = false;
1500 0 : }
1501 : }
1502 :
1503 : assert(mpVDev); //invalid virtual device
1504 :
1505 0 : const FontMetric aMetric( mpVDev->GetFontMetric() );
1506 :
1507 0 : bool bTextSpecial = aMetric.IsShadow() || aMetric.IsOutline() || (aMetric.GetRelief() != RELIEF_NONE);
1508 :
1509 : if( true || !bTextSpecial )
1510 : {
1511 0 : implWriteTextPortion( rPos, rText, mpVDev->GetTextColor(), bApplyMapping );
1512 : }
1513 : else
1514 : {
1515 : // to be implemented
1516 0 : }
1517 :
1518 : }
1519 :
1520 0 : void SVGTextWriter::implWriteTextPortion( const Point& rPos,
1521 : const OUString& rText,
1522 : Color aTextColor,
1523 : sal_Bool bApplyMapping )
1524 : {
1525 0 : Point aPos;
1526 0 : Point aBaseLinePos( rPos );
1527 0 : const FontMetric aMetric( mpVDev->GetFontMetric() );
1528 0 : const Font& rFont = mpVDev->GetFont();
1529 :
1530 0 : if( rFont.GetAlign() == ALIGN_TOP )
1531 0 : aBaseLinePos.Y() += aMetric.GetAscent();
1532 0 : else if( rFont.GetAlign() == ALIGN_BOTTOM )
1533 0 : aBaseLinePos.Y() -= aMetric.GetDescent();
1534 :
1535 0 : if( bApplyMapping )
1536 0 : implMap( rPos, aPos );
1537 : else
1538 0 : aPos = rPos;
1539 :
1540 0 : if( mbPositioningNeeded )
1541 : {
1542 0 : mbPositioningNeeded = sal_False;
1543 0 : maTextPos.setX( aPos.X() );
1544 0 : maTextPos.setY( aPos.Y() );
1545 0 : startTextPosition();
1546 : }
1547 0 : else if( maTextPos.Y() != aPos.Y() )
1548 : {
1549 : // In case the text position moved backward we could have a line break
1550 : // so we end the current line and start a new one.
1551 0 : if( mbLineBreak || ( ( maTextPos.X() + mnTextWidth ) > aPos.X() ) )
1552 : {
1553 0 : mbLineBreak = sal_False;
1554 0 : maTextPos.setX( aPos.X() );
1555 0 : maTextPos.setY( aPos.Y() );
1556 0 : startTextPosition();
1557 : }
1558 : else // superscript, subscript, list item numbering
1559 : {
1560 0 : maTextPos.setY( aPos.Y() );
1561 0 : startTextPosition( sal_False /* do not export x attribute */ );
1562 : }
1563 : }
1564 : // we are dealing with a bullet, so set up this for the next text portion
1565 0 : if( mbIsNewListItem )
1566 : {
1567 0 : mbIsNewListItem = sal_False;
1568 0 : mbPositioningNeeded = sal_True;
1569 :
1570 0 : if( meNumberingType == NumberingType::CHAR_SPECIAL )
1571 : {
1572 : // Create an id for the current text portion
1573 0 : implRegisterInterface( mrCurrentTextParagraph );
1574 :
1575 : // Add the needed info to the BulletListItemMap
1576 0 : OUString sId = implGetValidIDFromInterface( mrCurrentTextParagraph );
1577 0 : if( !sId.isEmpty() )
1578 : {
1579 0 : sId += ".bp";
1580 0 : BulletListItemInfo& aBulletListItemInfo = maBulletListItemMap[ sId ];
1581 0 : aBulletListItemInfo.nFontSize = rFont.GetHeight();
1582 0 : aBulletListItemInfo.aColor = aTextColor;
1583 0 : aBulletListItemInfo.aPos = maTextPos;
1584 0 : aBulletListItemInfo.cBulletChar = mcBulletChar;
1585 :
1586 : // Make this text portion a bullet placeholder
1587 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
1588 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "BulletPlaceholder" );
1589 0 : SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
1590 0 : return;
1591 0 : }
1592 : }
1593 : }
1594 :
1595 0 : const OUString& rTextPortionId = implGetValidIDFromInterface( mrCurrentTextPortion );
1596 0 : if( !rTextPortionId.isEmpty() )
1597 : {
1598 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rTextPortionId );
1599 : }
1600 :
1601 0 : if( mbIsPlacehlolderShape )
1602 : {
1603 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "PlaceholderText" );
1604 0 : mbIsPlacehlolderShape = sal_False;
1605 : }
1606 :
1607 0 : addFontAttributes( /* isTexTContainer: */ false );
1608 : assert(mpContext); //invalid context object
1609 :
1610 0 : mpContext->AddPaintAttr( COL_TRANSPARENT, aTextColor );
1611 :
1612 0 : OUString sTextContent = rText;
1613 :
1614 : // <a> tag for link should be the innermost tag, inside <tspan>
1615 0 : if( !mbIsPlacehlolderShape && mbIsURLField && !msUrl.isEmpty() )
1616 : {
1617 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "UrlField" );
1618 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, msUrl );
1619 :
1620 0 : SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
1621 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, msUrl );
1622 : {
1623 0 : SvXMLElementExport aSVGAElem( mrExport, XML_NAMESPACE_NONE, aXMLElemA, mbIWS, mbIWS );
1624 0 : mrExport.GetDocHandler()->characters( sTextContent );
1625 0 : }
1626 : }
1627 : else
1628 : {
1629 0 : SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
1630 0 : mrExport.GetDocHandler()->characters( sTextContent );
1631 : }
1632 :
1633 0 : mnTextWidth += mpVDev->GetTextWidth( sTextContent );
1634 : }
1635 :
1636 0 : SVGActionWriter::SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport ) :
1637 : mnCurGradientId( 1 ),
1638 : mnCurMaskId( 1 ),
1639 : mnCurPatternId( 1 ),
1640 : mrExport( rExport ),
1641 : mrFontExport( rFontExport ),
1642 : mpContext( NULL ),
1643 : maTextWriter( rExport ),
1644 : mnInnerMtfCount( 0 ),
1645 0 : mbClipAttrChanged( sal_False )
1646 : {
1647 0 : mpVDev = new VirtualDevice;
1648 0 : mpVDev->EnableOutput( false );
1649 0 : maTargetMapMode = MAP_100TH_MM;
1650 0 : maTextWriter.setVirtualDevice( mpVDev, maTargetMapMode );
1651 0 : }
1652 :
1653 0 : SVGActionWriter::~SVGActionWriter()
1654 : {
1655 : DBG_ASSERT( !mpContext, "Not all contexts are closed" );
1656 0 : delete mpVDev;
1657 0 : }
1658 :
1659 0 : long SVGActionWriter::ImplMap( sal_Int32 nVal ) const
1660 : {
1661 0 : Size aSz( nVal, nVal );
1662 :
1663 0 : return( ImplMap( aSz, aSz ).Width() );
1664 : }
1665 :
1666 0 : Point& SVGActionWriter::ImplMap( const Point& rPt, Point& rDstPt ) const
1667 : {
1668 0 : return( rDstPt = mpVDev->LogicToLogic( rPt, mpVDev->GetMapMode(), maTargetMapMode ) );
1669 : }
1670 :
1671 0 : Size& SVGActionWriter::ImplMap( const Size& rSz, Size& rDstSz ) const
1672 : {
1673 0 : return( rDstSz = mpVDev->LogicToLogic( rSz, mpVDev->GetMapMode(), maTargetMapMode ) );
1674 : }
1675 :
1676 0 : Rectangle& SVGActionWriter::ImplMap( const Rectangle& rRect, Rectangle& rDstRect ) const
1677 : {
1678 0 : Point aTL( rRect.TopLeft() );
1679 0 : Size aSz( rRect.GetSize() );
1680 :
1681 0 : return( rDstRect = Rectangle( ImplMap( aTL, aTL ), ImplMap( aSz, aSz ) ) );
1682 : }
1683 :
1684 0 : Polygon& SVGActionWriter::ImplMap( const Polygon& rPoly, Polygon& rDstPoly ) const
1685 : {
1686 0 : rDstPoly = Polygon( rPoly.GetSize() );
1687 :
1688 0 : for( sal_uInt16 i = 0, nSize = rPoly.GetSize(); i < nSize; ++i )
1689 : {
1690 0 : ImplMap( rPoly[ i ], rDstPoly[ i ] );
1691 0 : rDstPoly.SetFlags( i, rPoly.GetFlags( i ) );
1692 : }
1693 :
1694 0 : return( rDstPoly );
1695 : }
1696 :
1697 0 : PolyPolygon& SVGActionWriter::ImplMap( const PolyPolygon& rPolyPoly, PolyPolygon& rDstPolyPoly ) const
1698 : {
1699 0 : Polygon aPoly;
1700 :
1701 0 : rDstPolyPoly = PolyPolygon();
1702 :
1703 0 : for( sal_uInt16 i = 0, nCount = rPolyPoly.Count(); i < nCount; ++i )
1704 : {
1705 0 : rDstPolyPoly.Insert( ImplMap( rPolyPoly[ i ], aPoly ) );
1706 : }
1707 :
1708 0 : return( rDstPolyPoly );
1709 : }
1710 :
1711 0 : OUString SVGActionWriter::GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine )
1712 : {
1713 0 : OUString aPathData;
1714 0 : const OUString aBlank( " " );
1715 0 : const OUString aComma( "," );
1716 0 : Point aPolyPoint;
1717 :
1718 0 : for( long i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
1719 : {
1720 0 : const Polygon& rPoly = rPolyPoly[ (sal_uInt16) i ];
1721 0 : sal_uInt16 n = 1, nSize = rPoly.GetSize();
1722 :
1723 0 : if( nSize > 1 )
1724 : {
1725 0 : aPathData += "M ";
1726 0 : aPathData += OUString::number( ( aPolyPoint = rPoly[ 0 ] ).X() );
1727 0 : aPathData += aComma;
1728 0 : aPathData += OUString::number( aPolyPoint.Y() );
1729 :
1730 0 : sal_Char nCurrentMode = 0;
1731 0 : const bool bClose(!bLine || rPoly[0] == rPoly[nSize - 1]);
1732 0 : while( n < nSize )
1733 : {
1734 0 : aPathData += aBlank;
1735 :
1736 0 : if ( ( rPoly.GetFlags( n ) == POLY_CONTROL ) && ( ( n + 2 ) < nSize ) )
1737 : {
1738 0 : if ( nCurrentMode != 'C' )
1739 : {
1740 0 : nCurrentMode = 'C';
1741 0 : aPathData += "C ";
1742 : }
1743 0 : for ( int j = 0; j < 3; j++ )
1744 : {
1745 0 : if ( j )
1746 0 : aPathData += aBlank;
1747 0 : aPathData += OUString::number( ( aPolyPoint = rPoly[ n++ ] ).X() );
1748 0 : aPathData += aComma;
1749 0 : aPathData += OUString::number( aPolyPoint.Y() );
1750 : }
1751 : }
1752 : else
1753 : {
1754 0 : if ( nCurrentMode != 'L' )
1755 : {
1756 0 : nCurrentMode = 'L';
1757 0 : aPathData += "L ";
1758 : }
1759 0 : aPathData += OUString::number( ( aPolyPoint = rPoly[ n++ ] ).X() );
1760 0 : aPathData += aComma;
1761 0 : aPathData += OUString::number( aPolyPoint.Y() );
1762 : }
1763 : }
1764 :
1765 0 : if(bClose)
1766 0 : aPathData += " Z";
1767 :
1768 0 : if( i < ( nCount - 1 ) )
1769 0 : aPathData += aBlank;
1770 : }
1771 : }
1772 :
1773 0 : return aPathData;
1774 : }
1775 :
1776 0 : sal_uLong SVGActionWriter::GetChecksum( const MetaAction* pAction )
1777 : {
1778 0 : GDIMetaFile aMtf;
1779 0 : MetaAction* pA = (MetaAction*)pAction;
1780 0 : pA->Duplicate();
1781 0 : aMtf.AddAction( pA );
1782 0 : return aMtf.GetChecksum();
1783 : }
1784 :
1785 0 : void SVGActionWriter::ImplWriteLine( const Point& rPt1, const Point& rPt2,
1786 : const Color* pLineColor, sal_Bool bApplyMapping )
1787 : {
1788 0 : Point aPt1, aPt2;
1789 :
1790 0 : if( bApplyMapping )
1791 : {
1792 0 : ImplMap( rPt1, aPt1 );
1793 0 : ImplMap( rPt2, aPt2 );
1794 : }
1795 : else
1796 : {
1797 0 : aPt1 = rPt1;
1798 0 : aPt2 = rPt2;
1799 : }
1800 :
1801 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, OUString::number( aPt1.X() ) );
1802 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, OUString::number( aPt1.Y() ) );
1803 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, OUString::number( aPt2.X() ) );
1804 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, OUString::number( aPt2.Y() ) );
1805 :
1806 : if( pLineColor )
1807 : {
1808 : // !!! mrExport.AddAttribute( XML_NAMESPACE_NONE, ... )
1809 : OSL_FAIL( "SVGActionWriter::ImplWriteLine: Line color not implemented" );
1810 : }
1811 :
1812 : {
1813 0 : SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemLine, true, true );
1814 : }
1815 0 : }
1816 :
1817 0 : void SVGActionWriter::ImplWriteRect( const Rectangle& rRect, long nRadX, long nRadY,
1818 : sal_Bool bApplyMapping )
1819 : {
1820 0 : Rectangle aRect;
1821 :
1822 0 : if( bApplyMapping )
1823 0 : ImplMap( rRect, aRect );
1824 : else
1825 0 : aRect = rRect;
1826 :
1827 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aRect.Left() ) );
1828 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aRect.Top() ) );
1829 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, OUString::number( aRect.GetWidth() ) );
1830 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, OUString::number( aRect.GetHeight() ) );
1831 :
1832 0 : if( nRadX )
1833 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, OUString::number( bApplyMapping ? ImplMap( nRadX ) : nRadX ) );
1834 :
1835 0 : if( nRadY )
1836 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, OUString::number( bApplyMapping ? ImplMap( nRadY ) : nRadY ) );
1837 :
1838 : {
1839 0 : SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemRect, true, true );
1840 : }
1841 0 : }
1842 :
1843 0 : void SVGActionWriter::ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY,
1844 : sal_Bool bApplyMapping )
1845 : {
1846 0 : Point aCenter;
1847 :
1848 0 : if( bApplyMapping )
1849 0 : ImplMap( rCenter, aCenter );
1850 : else
1851 0 : aCenter = rCenter;
1852 :
1853 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, OUString::number( aCenter.X() ) );
1854 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCY, OUString::number( aCenter.Y() ) );
1855 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, OUString::number( bApplyMapping ? ImplMap( nRadX ) : nRadX ) );
1856 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, OUString::number( bApplyMapping ? ImplMap( nRadY ) : nRadY ) );
1857 :
1858 : {
1859 0 : SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemEllipse, true, true );
1860 : }
1861 0 : }
1862 :
1863 0 : void SVGActionWriter::ImplAddLineAttr( const LineInfo &rAttrs,
1864 : sal_Bool bApplyMapping )
1865 : {
1866 0 : if ( !rAttrs.IsDefault() )
1867 : {
1868 0 : sal_Int32 nStrokeWidth = bApplyMapping ? ImplMap( rAttrs.GetWidth() ) : rAttrs.GetWidth();
1869 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStrokeWidth,
1870 0 : OUString::number( nStrokeWidth ) );
1871 : // support for LineJoint
1872 0 : switch(rAttrs.GetLineJoin())
1873 : {
1874 : default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
1875 : case basegfx::B2DLINEJOIN_MITER:
1876 : {
1877 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "miter");
1878 0 : break;
1879 : }
1880 : case basegfx::B2DLINEJOIN_BEVEL:
1881 : {
1882 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "bevel");
1883 0 : break;
1884 : }
1885 : case basegfx::B2DLINEJOIN_ROUND:
1886 : {
1887 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "round");
1888 0 : break;
1889 : }
1890 : }
1891 :
1892 : // support for LineCap
1893 0 : switch(rAttrs.GetLineCap())
1894 : {
1895 : default: /* com::sun::star::drawing::LineCap_BUTT */
1896 : {
1897 : // butt is Svg default, so no need to write until the exporter might write styles.
1898 : // If this happens, activate here
1899 : // mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "butt");
1900 0 : break;
1901 : }
1902 : case com::sun::star::drawing::LineCap_ROUND:
1903 : {
1904 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "round");
1905 0 : break;
1906 : }
1907 : case com::sun::star::drawing::LineCap_SQUARE:
1908 : {
1909 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "square");
1910 0 : break;
1911 : }
1912 : }
1913 :
1914 : }
1915 :
1916 0 : }
1917 :
1918 0 : void SVGActionWriter::ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly,
1919 : sal_Bool bApplyMapping )
1920 : {
1921 0 : PolyPolygon aPolyPoly;
1922 :
1923 0 : if( bApplyMapping )
1924 0 : ImplMap( rPolyPoly, aPolyPoly );
1925 : else
1926 0 : aPolyPoly = rPolyPoly;
1927 :
1928 : // add path data attribute
1929 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrD, GetPathString( aPolyPoly, bLineOnly ) );
1930 :
1931 : {
1932 : // write polyline/polygon element
1933 0 : SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemPath, true, true );
1934 0 : }
1935 0 : }
1936 :
1937 0 : void SVGActionWriter::ImplWriteShape( const SVGShapeDescriptor& rShape, sal_Bool bApplyMapping )
1938 : {
1939 0 : PolyPolygon aPolyPoly;
1940 :
1941 0 : if( bApplyMapping )
1942 0 : ImplMap( rShape.maShapePolyPoly, aPolyPoly );
1943 : else
1944 0 : aPolyPoly = rShape.maShapePolyPoly;
1945 :
1946 0 : const sal_Bool bLineOnly = ( rShape.maShapeFillColor == Color( COL_TRANSPARENT ) ) && ( !rShape.mapShapeGradient.get() );
1947 0 : Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
1948 :
1949 0 : mpContext->AddPaintAttr( rShape.maShapeLineColor, rShape.maShapeFillColor, &aBoundRect, rShape.mapShapeGradient.get() );
1950 :
1951 0 : if( !rShape.maId.isEmpty() )
1952 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, rShape.maId );
1953 :
1954 0 : if( rShape.mnStrokeWidth )
1955 : {
1956 0 : sal_Int32 nStrokeWidth = ( bApplyMapping ? ImplMap( rShape.mnStrokeWidth ) : rShape.mnStrokeWidth );
1957 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStrokeWidth, OUString::number( nStrokeWidth ) );
1958 : }
1959 :
1960 : // support for LineJoin
1961 0 : switch(rShape.maLineJoin)
1962 : {
1963 : default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
1964 : case basegfx::B2DLINEJOIN_MITER:
1965 : {
1966 : // miter is Svg default, so no need to write until the exporter might write styles.
1967 : // If this happens, activate here
1968 : // mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "miter");
1969 0 : break;
1970 : }
1971 : case basegfx::B2DLINEJOIN_BEVEL:
1972 : {
1973 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "bevel");
1974 0 : break;
1975 : }
1976 : case basegfx::B2DLINEJOIN_ROUND:
1977 : {
1978 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "round");
1979 0 : break;
1980 : }
1981 : }
1982 :
1983 : // support for LineCap
1984 0 : switch(rShape.maLineCap)
1985 : {
1986 : default: /* com::sun::star::drawing::LineCap_BUTT */
1987 : {
1988 : // butt is Svg default, so no need to write until the exporter might write styles.
1989 : // If this happens, activate here
1990 : // mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "butt");
1991 0 : break;
1992 : }
1993 : case com::sun::star::drawing::LineCap_ROUND:
1994 : {
1995 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "round");
1996 0 : break;
1997 : }
1998 : case com::sun::star::drawing::LineCap_SQUARE:
1999 : {
2000 0 : mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "square");
2001 0 : break;
2002 : }
2003 : }
2004 :
2005 0 : if( rShape.maDashArray.size() )
2006 : {
2007 0 : const OUString aComma( "," );
2008 0 : OUString aDashArrayStr;
2009 :
2010 0 : for( unsigned int k = 0; k < rShape.maDashArray.size(); ++k )
2011 : {
2012 : const sal_Int32 nDash = ( bApplyMapping ?
2013 0 : ImplMap( FRound( rShape.maDashArray[ k ] ) ) :
2014 0 : FRound( rShape.maDashArray[ k ] ) );
2015 :
2016 0 : if( k )
2017 0 : aDashArrayStr += aComma;
2018 :
2019 0 : aDashArrayStr += OUString::number( nDash );
2020 : }
2021 :
2022 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStrokeDashArray, aDashArrayStr );
2023 : }
2024 :
2025 0 : ImplWritePolyPolygon( aPolyPoly, bLineOnly, sal_False );
2026 0 : }
2027 :
2028 0 : void SVGActionWriter::ImplWritePattern( const PolyPolygon& rPolyPoly,
2029 : const Hatch* pHatch,
2030 : const Gradient* pGradient,
2031 : sal_uInt32 nWriteFlags )
2032 : {
2033 0 : if( rPolyPoly.Count() )
2034 : {
2035 0 : SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
2036 :
2037 0 : OUString aPatternId = "pattern" + OUString::number( mnCurPatternId++ );
2038 :
2039 : {
2040 0 : SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
2041 :
2042 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aPatternId );
2043 :
2044 0 : Rectangle aRect;
2045 0 : ImplMap( rPolyPoly.GetBoundRect(), aRect );
2046 :
2047 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aRect.Left() ) );
2048 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aRect.Top() ) );
2049 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, OUString::number( aRect.GetWidth() ) );
2050 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, OUString::number( aRect.GetHeight() ) );
2051 :
2052 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrPatternUnits, OUString( "userSpaceOnUse") );
2053 :
2054 : {
2055 0 : SvXMLElementExport aElemPattern( mrExport, XML_NAMESPACE_NONE, aXMLElemPattern, true, true );
2056 :
2057 : // The origin of a pattern is positioned at (aRect.Left(), aRect.Top()).
2058 : // So we need to adjust the pattern coordinate.
2059 0 : OUString aTransform = "translate(" +
2060 0 : OUString::number( -aRect.Left() ) +
2061 0 : "," + OUString::number( -aRect.Top() ) +
2062 0 : ")";
2063 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
2064 :
2065 : {
2066 0 : SvXMLElementExport aElemG2( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
2067 :
2068 0 : GDIMetaFile aTmpMtf;
2069 0 : if( pHatch )
2070 0 : mpVDev->AddHatchActions( rPolyPoly, *pHatch, aTmpMtf );
2071 0 : else if ( pGradient )
2072 0 : mpVDev->AddGradientActions( rPolyPoly.GetBoundRect(), *pGradient, aTmpMtf );
2073 0 : ImplWriteActions( aTmpMtf, nWriteFlags, NULL );
2074 0 : }
2075 0 : }
2076 : }
2077 :
2078 0 : OUString aPatternStyle = "fill:url(#" + aPatternId + ")";
2079 :
2080 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aPatternStyle );
2081 0 : ImplWritePolyPolygon( rPolyPoly, sal_False );
2082 : }
2083 0 : }
2084 :
2085 0 : void SVGActionWriter::ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
2086 : sal_uInt32 nWriteFlags)
2087 : {
2088 0 : if ( rGradient.GetStyle() == GradientStyle_LINEAR ||
2089 0 : rGradient.GetStyle() == GradientStyle_AXIAL )
2090 : {
2091 0 : ImplWriteGradientLinear( rPolyPoly, rGradient );
2092 : }
2093 : else
2094 : {
2095 0 : ImplWritePattern( rPolyPoly, NULL, &rGradient, nWriteFlags );
2096 : }
2097 0 : }
2098 :
2099 0 : void SVGActionWriter::ImplWriteGradientLinear( const PolyPolygon& rPolyPoly,
2100 : const Gradient& rGradient )
2101 : {
2102 0 : if( rPolyPoly.Count() )
2103 : {
2104 0 : SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
2105 :
2106 0 : OUString aGradientId = "gradient" + OUString::number( mnCurGradientId++ );
2107 :
2108 : {
2109 0 : SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
2110 :
2111 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aGradientId );
2112 : {
2113 0 : Rectangle aTmpRect, aRect;
2114 0 : Point aTmpCenter, aCenter;
2115 :
2116 0 : rGradient.GetBoundRect( rPolyPoly.GetBoundRect(), aTmpRect, aTmpCenter );
2117 0 : ImplMap( aTmpRect, aRect );
2118 0 : ImplMap( aTmpCenter, aCenter );
2119 0 : const sal_uInt16 nAngle = rGradient.GetAngle() % 3600;
2120 :
2121 0 : Polygon aPoly( 2 );
2122 : // Setting x value of a gradient vector to rotation center to
2123 : // place a gradient vector in a target polygon.
2124 : // This would help editing it in SVG editors like inkscape.
2125 0 : aPoly[ 0 ].X() = aPoly[ 1 ].X() = aCenter.X();
2126 0 : aPoly[ 0 ].Y() = aRect.Top();
2127 0 : aPoly[ 1 ].Y() = aRect.Bottom();
2128 0 : aPoly.Rotate( aCenter, nAngle );
2129 :
2130 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, OUString::number( aPoly[ 0 ].X() ) );
2131 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, OUString::number( aPoly[ 0 ].Y() ) );
2132 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, OUString::number( aPoly[ 1 ].X() ) );
2133 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, OUString::number( aPoly[ 1 ].Y() ) );
2134 :
2135 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrGradientUnits,
2136 0 : OUString( "userSpaceOnUse" ) );
2137 : }
2138 :
2139 : {
2140 0 : SvXMLElementExport aElemLinearGradient( mrExport, XML_NAMESPACE_NONE, aXMLElemLinearGradient, true, true );
2141 :
2142 0 : const Color aStartColor = ImplGetColorWithIntensity( rGradient.GetStartColor(), rGradient.GetStartIntensity() );
2143 0 : const Color aEndColor = ImplGetColorWithIntensity( rGradient.GetEndColor(), rGradient.GetEndIntensity() );
2144 0 : double fBorderOffset = rGradient.GetBorder() / 100.0;
2145 0 : const sal_uInt16 nSteps = rGradient.GetSteps();
2146 0 : if( rGradient.GetStyle() == GradientStyle_LINEAR )
2147 : {
2148 : // Emulate non-smooth gradient
2149 0 : if( 0 < nSteps && nSteps < 100 )
2150 : {
2151 0 : double fOffsetStep = ( 1.0 - fBorderOffset ) / (double)nSteps;
2152 0 : for( sal_uInt16 i = 0; i < nSteps; i++ ) {
2153 0 : Color aColor = ImplGetGradientColor( aStartColor, aEndColor, i / (double) nSteps );
2154 0 : ImplWriteGradientStop( aColor, fBorderOffset + ( i + 1 ) * fOffsetStep );
2155 0 : aColor = ImplGetGradientColor( aStartColor, aEndColor, ( i + 1 ) / (double) nSteps );
2156 0 : ImplWriteGradientStop( aColor, fBorderOffset + ( i + 1 ) * fOffsetStep );
2157 0 : }
2158 : }
2159 : else
2160 : {
2161 0 : ImplWriteGradientStop( aStartColor, fBorderOffset );
2162 0 : ImplWriteGradientStop( aEndColor, 1.0 );
2163 : }
2164 : }
2165 : else
2166 : {
2167 0 : fBorderOffset /= 2;
2168 : // Emulate non-smooth gradient
2169 0 : if( 0 < nSteps && nSteps < 100 )
2170 : {
2171 0 : double fOffsetStep = ( 0.5 - fBorderOffset ) / (double)nSteps;
2172 : // Upper half
2173 0 : for( sal_uInt16 i = 0; i < nSteps; i++ )
2174 : {
2175 0 : Color aColor = ImplGetGradientColor( aEndColor, aStartColor, i / (double) nSteps );
2176 0 : ImplWriteGradientStop( aColor, fBorderOffset + i * fOffsetStep );
2177 0 : aColor = ImplGetGradientColor( aEndColor, aStartColor, (i + 1 ) / (double) nSteps );
2178 0 : ImplWriteGradientStop( aColor, fBorderOffset + i * fOffsetStep );
2179 : }
2180 : // Lower half
2181 0 : for( sal_uInt16 i = 0; i < nSteps; i++ )
2182 : {
2183 0 : Color aColor = ImplGetGradientColor( aStartColor, aEndColor, i / (double) nSteps );
2184 0 : ImplWriteGradientStop( aColor, 0.5 + (i + 1) * fOffsetStep );
2185 0 : aColor = ImplGetGradientColor( aStartColor, aEndColor, (i + 1 ) / (double) nSteps );
2186 0 : ImplWriteGradientStop( aColor, 0.5 + (i + 1) * fOffsetStep );
2187 0 : }
2188 : }
2189 : else
2190 : {
2191 0 : ImplWriteGradientStop( aEndColor, fBorderOffset );
2192 0 : ImplWriteGradientStop( aStartColor, 0.5 );
2193 0 : ImplWriteGradientStop( aEndColor, 1.0 - fBorderOffset );
2194 : }
2195 0 : }
2196 0 : }
2197 : }
2198 :
2199 0 : OUString aGradientStyle = "fill:url(#" + aGradientId + ")";
2200 :
2201 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aGradientStyle );
2202 0 : ImplWritePolyPolygon( rPolyPoly, sal_False );
2203 : }
2204 0 : }
2205 :
2206 0 : void SVGActionWriter::ImplWriteGradientStop( const Color& rColor, double fOffset )
2207 : {
2208 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( fOffset ) );
2209 :
2210 0 : OUString aStyle, aColor;
2211 0 : aStyle += "stop-color:";
2212 0 : SVGAttributeWriter::ImplGetColorStr ( rColor, aColor );
2213 0 : aStyle += aColor;
2214 :
2215 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle );
2216 : {
2217 0 : SvXMLElementExport aElemStartStop( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
2218 0 : }
2219 0 : }
2220 :
2221 0 : Color SVGActionWriter::ImplGetColorWithIntensity( const Color& rColor,
2222 : sal_uInt16 nIntensity )
2223 : {
2224 0 : sal_uInt8 nNewRed = (sal_uInt8)( (long)rColor.GetRed() * nIntensity / 100L );
2225 0 : sal_uInt8 nNewGreen = (sal_uInt8)( (long)rColor.GetGreen() * nIntensity / 100L );
2226 0 : sal_uInt8 nNewBlue = (sal_uInt8)( (long)rColor.GetBlue() * nIntensity / 100L );
2227 0 : return Color( nNewRed, nNewGreen, nNewBlue);
2228 : }
2229 :
2230 0 : Color SVGActionWriter::ImplGetGradientColor( const Color& rStartColor,
2231 : const Color& rEndColor,
2232 : double fOffset )
2233 : {
2234 0 : long nRedStep = rEndColor.GetRed() - rStartColor.GetRed();
2235 0 : long nNewRed = rStartColor.GetRed() + (long)( nRedStep * fOffset );
2236 0 : nNewRed = ( nNewRed < 0 ) ? 0 : ( nNewRed > 0xFF) ? 0xFF : nNewRed;
2237 :
2238 0 : long nGreenStep = rEndColor.GetGreen() - rStartColor.GetGreen();
2239 0 : long nNewGreen = rStartColor.GetGreen() + (long)( nGreenStep * fOffset );
2240 0 : nNewGreen = ( nNewGreen < 0 ) ? 0 : ( nNewGreen > 0xFF) ? 0xFF : nNewGreen;
2241 :
2242 0 : long nBlueStep = rEndColor.GetBlue() - rStartColor.GetBlue();
2243 0 : long nNewBlue = rStartColor.GetBlue() + (long)( nBlueStep * fOffset );
2244 0 : nNewBlue = ( nNewBlue < 0 ) ? 0 : ( nNewBlue > 0xFF) ? 0xFF : nNewBlue;
2245 :
2246 0 : return Color( (sal_uInt8)nNewRed, (sal_uInt8)nNewGreen, (sal_uInt8)nNewBlue );
2247 : }
2248 :
2249 0 : void SVGActionWriter::ImplWriteMask( GDIMetaFile& rMtf,
2250 : const Point& rDestPt,
2251 : const Size& rDestSize,
2252 : const Gradient& rGradient,
2253 : sal_uInt32 nWriteFlags )
2254 : {
2255 0 : Point aSrcPt( rMtf.GetPrefMapMode().GetOrigin() );
2256 0 : const Size aSrcSize( rMtf.GetPrefSize() );
2257 0 : const double fScaleX = aSrcSize.Width() ? (double) rDestSize.Width() / aSrcSize.Width() : 1.0;
2258 0 : const double fScaleY = aSrcSize.Height() ? (double) rDestSize.Height() / aSrcSize.Height() : 1.0;
2259 : long nMoveX, nMoveY;
2260 :
2261 0 : if( fScaleX != 1.0 || fScaleY != 1.0 )
2262 : {
2263 0 : rMtf.Scale( fScaleX, fScaleY );
2264 0 : aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
2265 : }
2266 :
2267 0 : nMoveX = rDestPt.X() - aSrcPt.X(), nMoveY = rDestPt.Y() - aSrcPt.Y();
2268 :
2269 0 : if( nMoveX || nMoveY )
2270 0 : rMtf.Move( nMoveX, nMoveY );
2271 :
2272 0 : OUString aMaskId = "mask" + OUString::number( mnCurMaskId++ );
2273 :
2274 : {
2275 0 : SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
2276 :
2277 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aMaskId );
2278 : {
2279 0 : SvXMLElementExport aElemMask( mrExport, XML_NAMESPACE_NONE, aXMLElemMask, true, true );
2280 :
2281 0 : const PolyPolygon aPolyPolygon( PolyPolygon( Rectangle( rDestPt, rDestSize ) ) );
2282 0 : Gradient aGradient( rGradient );
2283 :
2284 : // swap gradient stops to adopt SVG mask
2285 0 : Color aTmpColor( aGradient.GetStartColor() );
2286 0 : sal_uInt16 nTmpIntensity( aGradient.GetStartIntensity() );
2287 0 : aGradient.SetStartColor( aGradient.GetEndColor() );
2288 0 : aGradient.SetStartIntensity( aGradient.GetEndIntensity() ) ;
2289 0 : aGradient.SetEndColor( aTmpColor );
2290 0 : aGradient.SetEndIntensity( nTmpIntensity );
2291 :
2292 0 : ImplWriteGradientEx( aPolyPolygon, aGradient, nWriteFlags );
2293 0 : }
2294 : }
2295 :
2296 0 : OUString aMaskStyle = "mask:url(#" + aMaskId + ")";
2297 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aMaskStyle );
2298 :
2299 : {
2300 0 : SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
2301 :
2302 0 : mpVDev->Push();
2303 0 : ImplWriteActions( rMtf, nWriteFlags, NULL );
2304 0 : mpVDev->Pop();
2305 0 : }
2306 0 : }
2307 :
2308 0 : void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
2309 : const sal_Int32* pDXArray, long nWidth,
2310 : sal_Bool bApplyMapping )
2311 : {
2312 0 : const FontMetric aMetric( mpVDev->GetFontMetric() );
2313 :
2314 0 : bool bTextSpecial = aMetric.IsShadow() || aMetric.IsOutline() || (aMetric.GetRelief() != RELIEF_NONE);
2315 :
2316 0 : if( !bTextSpecial )
2317 : {
2318 0 : ImplWriteText( rPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2319 : }
2320 : else
2321 : {
2322 0 : if( aMetric.GetRelief() != RELIEF_NONE )
2323 : {
2324 0 : Color aReliefColor( COL_LIGHTGRAY );
2325 0 : Color aTextColor( mpVDev->GetTextColor() );
2326 :
2327 0 : if ( aTextColor.GetColor() == COL_BLACK )
2328 0 : aTextColor = Color( COL_WHITE );
2329 :
2330 0 : if ( aTextColor.GetColor() == COL_WHITE )
2331 0 : aReliefColor = Color( COL_BLACK );
2332 :
2333 :
2334 0 : Point aPos( rPos );
2335 0 : Point aOffset( 6, 6 );
2336 :
2337 0 : if ( aMetric.GetRelief() == RELIEF_ENGRAVED )
2338 : {
2339 0 : aPos -= aOffset;
2340 : }
2341 : else
2342 : {
2343 0 : aPos += aOffset;
2344 : }
2345 :
2346 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, aReliefColor, bApplyMapping );
2347 0 : ImplWriteText( rPos, rText, pDXArray, nWidth, aTextColor, bApplyMapping );
2348 : }
2349 : else
2350 : {
2351 0 : if( aMetric.IsShadow() )
2352 : {
2353 0 : long nOff = 1 + ((aMetric.GetLineHeight()-24)/24);
2354 0 : if ( aMetric.IsOutline() )
2355 0 : nOff += 6;
2356 :
2357 0 : Color aTextColor( mpVDev->GetTextColor() );
2358 0 : Color aShadowColor = Color( COL_BLACK );
2359 :
2360 0 : if ( (aTextColor.GetColor() == COL_BLACK) || (aTextColor.GetLuminance() < 8) )
2361 0 : aShadowColor = Color( COL_LIGHTGRAY );
2362 :
2363 0 : Point aPos( rPos );
2364 0 : aPos += Point( nOff, nOff );
2365 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, aShadowColor, bApplyMapping );
2366 :
2367 0 : if( !aMetric.IsOutline() )
2368 : {
2369 0 : ImplWriteText( rPos, rText, pDXArray, nWidth, aTextColor, bApplyMapping );
2370 : }
2371 : }
2372 :
2373 0 : if( aMetric.IsOutline() )
2374 : {
2375 0 : Point aPos = rPos + Point( -6, -6 );
2376 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2377 0 : aPos = rPos + Point( +6, +6);
2378 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2379 0 : aPos = rPos + Point( -6, +0);
2380 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2381 0 : aPos = rPos + Point( -6, +6);
2382 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2383 0 : aPos = rPos + Point( +0, +6);
2384 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2385 0 : aPos = rPos + Point( +0, -6);
2386 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2387 0 : aPos = rPos + Point( +6, -1);
2388 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2389 0 : aPos = rPos + Point( +6, +0);
2390 0 : ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor(), bApplyMapping );
2391 :
2392 0 : ImplWriteText( rPos, rText, pDXArray, nWidth, Color( COL_WHITE ), bApplyMapping );
2393 : }
2394 : }
2395 0 : }
2396 0 : }
2397 :
2398 0 : void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
2399 : const sal_Int32* pDXArray, long nWidth,
2400 : Color aTextColor, sal_Bool bApplyMapping )
2401 : {
2402 0 : sal_Int32 nLen = rText.getLength();
2403 0 : Size aNormSize;
2404 0 : Point aPos;
2405 0 : Point aBaseLinePos( rPos );
2406 0 : const FontMetric aMetric( mpVDev->GetFontMetric() );
2407 0 : const Font& rFont = mpVDev->GetFont();
2408 :
2409 0 : if( rFont.GetAlign() == ALIGN_TOP )
2410 0 : aBaseLinePos.Y() += aMetric.GetAscent();
2411 0 : else if( rFont.GetAlign() == ALIGN_BOTTOM )
2412 0 : aBaseLinePos.Y() -= aMetric.GetDescent();
2413 :
2414 0 : if( bApplyMapping )
2415 0 : ImplMap( rPos, aPos );
2416 : else
2417 0 : aPos = rPos;
2418 :
2419 0 : boost::shared_array<sal_Int32> xTmpArray(new sal_Int32[nLen]);
2420 : // get text sizes
2421 0 : if( pDXArray )
2422 : {
2423 0 : aNormSize = Size( mpVDev->GetTextWidth( rText ), 0 );
2424 0 : memcpy(xTmpArray.get(), pDXArray, nLen * sizeof(sal_Int32));
2425 : }
2426 : else
2427 : {
2428 0 : aNormSize = Size( mpVDev->GetTextArray( rText, xTmpArray.get() ), 0 );
2429 : }
2430 0 : sal_Int32* pDX = xTmpArray.get();
2431 :
2432 : // if text is rotated, set transform matrix at new g element
2433 0 : if( rFont.GetOrientation() )
2434 : {
2435 0 : Point aRot( aPos );
2436 : OUString aTransform =
2437 0 : OUString("translate") +
2438 0 : "(" + OUString::number( aRot.X() ) +
2439 0 : "," + OUString::number( aRot.Y() ) + ")" +
2440 0 : " rotate" +
2441 0 : "(" + OUString::number( rFont.GetOrientation() * -0.1 ) + ")" +
2442 0 : " translate" +
2443 0 : "(" + OUString::number( -aRot.X() ) +
2444 0 : "," + OUString::number( -aRot.Y() ) + ")";
2445 :
2446 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
2447 : }
2448 :
2449 :
2450 0 : mpContext->AddPaintAttr( COL_TRANSPARENT, aTextColor );
2451 :
2452 : // for each line of text there should be at least one group element
2453 0 : SvXMLElementExport aSVGGElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, false );
2454 :
2455 0 : sal_Bool bIsPlaceholderField = sal_False;
2456 :
2457 0 : if( mbIsPlacehlolderShape )
2458 : {
2459 0 : OUString sTextContent = rText;
2460 0 : bIsPlaceholderField = sTextContent.match( sPlaceholderTag );
2461 : // for a placeholder text field we export only one <text> svg element
2462 0 : if( bIsPlaceholderField )
2463 : {
2464 0 : OUString sCleanTextContent;
2465 0 : static const sal_Int32 nFrom = sPlaceholderTag.getLength();
2466 0 : if( sTextContent.getLength() > nFrom )
2467 : {
2468 0 : sCleanTextContent = sTextContent.copy( nFrom );
2469 : }
2470 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "PlaceholderText" );
2471 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aPos.X() ) );
2472 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPos.Y() ) );
2473 : {
2474 0 : SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, true, false );
2475 : // At least for the single slide case we need really to export placeholder text
2476 0 : mrExport.GetDocHandler()->characters( sCleanTextContent );
2477 0 : }
2478 0 : }
2479 : }
2480 :
2481 0 : if( !bIsPlaceholderField )
2482 : {
2483 0 : if( nLen > 1 )
2484 : {
2485 0 : aNormSize.Width() = pDX[ nLen - 2 ] + mpVDev->GetTextWidth( OUString(rText[nLen - 1]) );
2486 :
2487 0 : if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) )
2488 : {
2489 : long i;
2490 0 : const double fFactor = (double) nWidth / aNormSize.Width();
2491 :
2492 0 : for( i = 0; i < ( nLen - 1 ); i++ )
2493 0 : pDX[ i ] = FRound( pDX[ i ] * fFactor );
2494 : }
2495 : else
2496 : {
2497 0 : ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator > xBI( ::vcl::unohelper::CreateBreakIterator() );
2498 0 : const ::com::sun::star::lang::Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
2499 0 : sal_Int32 nCurPos = 0, nLastPos = 0, nX = aPos.X();
2500 :
2501 : // write single glyphs at absolute text positions
2502 0 : for( sal_Bool bCont = sal_True; bCont; )
2503 : {
2504 0 : sal_Int32 nCount = 1;
2505 :
2506 0 : nLastPos = nCurPos;
2507 0 : nCurPos = xBI->nextCharacters( rText, nCurPos, rLocale,
2508 : ::com::sun::star::i18n::CharacterIteratorMode::SKIPCELL,
2509 0 : nCount, nCount );
2510 :
2511 0 : nCount = nCurPos - nLastPos;
2512 0 : bCont = ( nCurPos < rText.getLength() ) && nCount;
2513 :
2514 0 : if( nCount )
2515 : {
2516 0 : const OUString aGlyph( rText.copy( nLastPos, nCount ) );
2517 :
2518 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( nX ) );
2519 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPos.Y() ) );
2520 :
2521 : {
2522 0 : SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, true, false );
2523 0 : mrExport.GetDocHandler()->characters( aGlyph );
2524 : }
2525 :
2526 0 : if( bCont )
2527 : {
2528 : // #118796# do NOT access pDXArray, it may be zero (!)
2529 0 : sal_Int32 nDXWidth = pDX[ nCurPos - 1 ];
2530 0 : if ( bApplyMapping )
2531 0 : nDXWidth = ImplMap( nDXWidth );
2532 0 : nX = aPos.X() + nDXWidth;
2533 0 : }
2534 : }
2535 0 : }
2536 : }
2537 : }
2538 : else
2539 : {
2540 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aPos.X() ) );
2541 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPos.Y() ) );
2542 :
2543 : {
2544 0 : SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, true, false );
2545 0 : mrExport.GetDocHandler()->characters( rText );
2546 : }
2547 : }
2548 : }
2549 :
2550 :
2551 0 : if( !mrExport.IsUseNativeTextDecoration() )
2552 : {
2553 0 : if( rFont.GetStrikeout() != STRIKEOUT_NONE || rFont.GetUnderline() != UNDERLINE_NONE )
2554 : {
2555 0 : Polygon aPoly( 4 );
2556 0 : const long nLineHeight = std::max( (long) FRound( aMetric.GetLineHeight() * 0.05 ), (long) 1 );
2557 :
2558 0 : if( rFont.GetStrikeout() )
2559 : {
2560 0 : const long nYLinePos = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 );
2561 :
2562 0 : aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 );
2563 0 : aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
2564 0 : aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1;
2565 0 : aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
2566 :
2567 0 : ImplWritePolyPolygon( aPoly, sal_False );
2568 : }
2569 :
2570 0 : if( rFont.GetUnderline() )
2571 : {
2572 0 : const long nYLinePos = aBaseLinePos.Y() + ( nLineHeight << 1 );
2573 :
2574 0 : aPoly[ 0 ].X() = aBaseLinePos.X(); aPoly[ 0 ].Y() = nYLinePos - ( nLineHeight >> 1 );
2575 0 : aPoly[ 1 ].X() = aBaseLinePos.X() + aNormSize.Width() - 1; aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
2576 0 : aPoly[ 2 ].X() = aPoly[ 1 ].X(); aPoly[ 2 ].Y() = aPoly[ 0 ].Y() + nLineHeight - 1;
2577 0 : aPoly[ 3 ].X() = aPoly[ 0 ].X(); aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
2578 :
2579 0 : ImplWritePolyPolygon( aPoly, sal_False );
2580 0 : }
2581 : }
2582 0 : }
2583 0 : }
2584 :
2585 0 : void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
2586 : const Point& rPt, const Size& rSz,
2587 : const Point& rSrcPt, const Size& rSrcSz,
2588 : sal_Bool bApplyMapping )
2589 : {
2590 0 : if( !!rBmpEx )
2591 : {
2592 0 : BitmapEx aBmpEx( rBmpEx );
2593 0 : Point aPoint = Point();
2594 0 : const Rectangle aBmpRect( aPoint, rBmpEx.GetSizePixel() );
2595 0 : const Rectangle aSrcRect( rSrcPt, rSrcSz );
2596 :
2597 0 : if( aSrcRect != aBmpRect )
2598 0 : aBmpEx.Crop( aSrcRect );
2599 :
2600 0 : if( !!aBmpEx )
2601 : {
2602 0 : SvMemoryStream aOStm( 65535, 65535 );
2603 :
2604 0 : if( GraphicConverter::Export( aOStm, rBmpEx, CVT_PNG ) == ERRCODE_NONE )
2605 : {
2606 0 : Point aPt;
2607 0 : Size aSz;
2608 0 : Sequence< sal_Int8 > aSeq( (sal_Int8*) aOStm.GetData(), aOStm.Tell() );
2609 0 : OUStringBuffer aBuffer( "data:image/png;base64," );
2610 0 : ::sax::Converter::encodeBase64( aBuffer, aSeq );
2611 :
2612 0 : if( bApplyMapping )
2613 : {
2614 0 : ImplMap( rPt, aPt );
2615 0 : ImplMap( rSz, aSz );
2616 : }
2617 : else
2618 : {
2619 0 : aPt = rPt;
2620 0 : aSz = rSz;
2621 : }
2622 :
2623 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aPt.X() ) );
2624 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPt.Y() ) );
2625 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, OUString::number( aSz.Width() ) );
2626 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, OUString::number( aSz.Height() ) );
2627 0 : mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, aBuffer.makeStringAndClear() );
2628 : {
2629 0 : SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemImage, true, true );
2630 0 : }
2631 0 : }
2632 0 : }
2633 : }
2634 0 : }
2635 :
2636 0 : void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
2637 : sal_uInt32 nWriteFlags,
2638 : const OUString* pElementId,
2639 : const Reference< XShape >* pxShape,
2640 : const GDIMetaFile* pTextEmbeddedBitmapMtf )
2641 : {
2642 : // need a counter fo rthe actions written per shape to avoid double ID
2643 : // generation
2644 0 : sal_Int32 nEntryCount(0);
2645 :
2646 0 : if( mnInnerMtfCount )
2647 0 : nWriteFlags |= SVGWRITER_NO_SHAPE_COMMENTS;
2648 :
2649 :
2650 : #if OSL_DEBUG_LEVEL > 0
2651 : bool bIsTextShape = false;
2652 : if( !mrExport.IsUsePositionedCharacters() && pxShape
2653 : && Reference< XText >( *pxShape, UNO_QUERY ).is() )
2654 : {
2655 : bIsTextShape = true;
2656 : }
2657 : #endif
2658 0 : mbIsPlacehlolderShape = false;
2659 0 : if( ( pElementId != NULL ) && ( *pElementId == sPlaceholderTag ) )
2660 : {
2661 0 : mbIsPlacehlolderShape = true;
2662 : // since we utilize pElementId in an improper way we reset it to NULL before to go on
2663 0 : pElementId = NULL;
2664 : }
2665 :
2666 0 : for( sal_uLong nCurAction = 0, nCount = rMtf.GetActionSize(); nCurAction < nCount; nCurAction++ )
2667 : {
2668 0 : const MetaAction* pAction = rMtf.GetAction( nCurAction );
2669 0 : const sal_uInt16 nType = pAction->GetType();
2670 :
2671 : #if OSL_DEBUG_LEVEL > 0
2672 : if( bIsTextShape )
2673 : {
2674 : try
2675 : {
2676 : SvXMLElementExport aElem( mrExport,
2677 : XML_NAMESPACE_NONE, "desc", false, false );
2678 : OUStringBuffer sType(OUString::number(nType));
2679 : if (pAction && (nType == META_COMMENT_ACTION))
2680 : {
2681 : sType.append(": ");
2682 : const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
2683 : OString sComment = pA->GetComment();
2684 : if (!sComment.isEmpty())
2685 : {
2686 : sType.append(OStringToOUString(
2687 : sComment, RTL_TEXTENCODING_UTF8));
2688 : }
2689 : if (sComment.equalsIgnoreAsciiCase("FIELD_SEQ_BEGIN"))
2690 : {
2691 : sal_uInt8 const*const pData = pA->GetData();
2692 : if (pData && (pA->GetDataSize()))
2693 : {
2694 : sal_uInt16 sz = (sal_uInt16)((pA->GetDataSize()) / 2);
2695 : if (sz)
2696 : {
2697 : sType.append("; ");
2698 : sType.append(
2699 : reinterpret_cast<sal_Unicode const*>(pData),
2700 : sz);
2701 : }
2702 : }
2703 : }
2704 : }
2705 : if (sType.getLength())
2706 : {
2707 : mrExport.GetDocHandler()->characters(
2708 : sType.makeStringAndClear());
2709 : }
2710 : }
2711 : catch( ... )
2712 : {
2713 : const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
2714 : OSL_FAIL( pA->GetComment().getStr() );
2715 : }
2716 :
2717 : }
2718 : #endif
2719 0 : switch( nType )
2720 : {
2721 : case( META_PIXEL_ACTION ):
2722 : {
2723 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2724 : {
2725 0 : const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
2726 :
2727 0 : mpContext->AddPaintAttr( pA->GetColor(), pA->GetColor() );
2728 0 : ImplWriteLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor() );
2729 : }
2730 : }
2731 0 : break;
2732 :
2733 : case( META_POINT_ACTION ):
2734 : {
2735 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2736 : {
2737 0 : const MetaPointAction* pA = (const MetaPointAction*) pAction;
2738 :
2739 0 : mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
2740 0 : ImplWriteLine( pA->GetPoint(), pA->GetPoint(), NULL );
2741 : }
2742 : }
2743 0 : break;
2744 :
2745 : case( META_LINE_ACTION ):
2746 : {
2747 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2748 : {
2749 0 : const MetaLineAction* pA = (const MetaLineAction*) pAction;
2750 :
2751 0 : mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
2752 0 : ImplWriteLine( pA->GetStartPoint(), pA->GetEndPoint(), NULL );
2753 : }
2754 : }
2755 0 : break;
2756 :
2757 : case( META_RECT_ACTION ):
2758 : {
2759 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2760 : {
2761 0 : mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
2762 0 : ImplWriteRect( ( (const MetaRectAction*) pAction )->GetRect(), 0, 0 );
2763 : }
2764 : }
2765 0 : break;
2766 :
2767 : case( META_ROUNDRECT_ACTION ):
2768 : {
2769 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2770 : {
2771 0 : const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
2772 :
2773 0 : mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
2774 0 : ImplWriteRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
2775 : }
2776 : }
2777 0 : break;
2778 :
2779 : case( META_ELLIPSE_ACTION ):
2780 : {
2781 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2782 : {
2783 0 : const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
2784 0 : const Rectangle& rRect = pA->GetRect();
2785 :
2786 0 : mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
2787 0 : ImplWriteEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1 );
2788 : }
2789 : }
2790 0 : break;
2791 :
2792 : case( META_ARC_ACTION ):
2793 : case( META_PIE_ACTION ):
2794 : case( META_CHORD_ACTION ):
2795 : case( META_POLYGON_ACTION ):
2796 : {
2797 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2798 : {
2799 0 : Polygon aPoly;
2800 :
2801 0 : switch( nType )
2802 : {
2803 : case( META_ARC_ACTION ):
2804 : {
2805 0 : const MetaArcAction* pA = (const MetaArcAction*) pAction;
2806 0 : aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
2807 : }
2808 0 : break;
2809 :
2810 : case( META_PIE_ACTION ):
2811 : {
2812 0 : const MetaPieAction* pA = (const MetaPieAction*) pAction;
2813 0 : aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
2814 : }
2815 0 : break;
2816 :
2817 : case( META_CHORD_ACTION ):
2818 : {
2819 0 : const MetaChordAction* pA = (const MetaChordAction*) pAction;
2820 0 : aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
2821 : }
2822 0 : break;
2823 :
2824 : case( META_POLYGON_ACTION ):
2825 0 : aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon();
2826 0 : break;
2827 : }
2828 :
2829 0 : if( aPoly.GetSize() )
2830 : {
2831 0 : mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
2832 0 : ImplWritePolyPolygon( aPoly, sal_False );
2833 0 : }
2834 : }
2835 : }
2836 0 : break;
2837 :
2838 : case( META_POLYLINE_ACTION ):
2839 : {
2840 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2841 : {
2842 0 : const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
2843 0 : const Polygon& rPoly = pA->GetPolygon();
2844 :
2845 0 : if( rPoly.GetSize() )
2846 : {
2847 0 : mpContext->AddPaintAttr( mpVDev->GetLineColor(), Color( COL_TRANSPARENT ) );
2848 0 : ImplAddLineAttr( pA->GetLineInfo() );
2849 0 : ImplWritePolyPolygon( rPoly, sal_True );
2850 : }
2851 : }
2852 : }
2853 0 : break;
2854 :
2855 : case( META_POLYPOLYGON_ACTION ):
2856 : {
2857 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2858 : {
2859 0 : const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
2860 0 : const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
2861 :
2862 0 : if( rPolyPoly.Count() )
2863 : {
2864 0 : mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
2865 0 : ImplWritePolyPolygon( rPolyPoly, sal_False );
2866 : }
2867 : }
2868 : }
2869 0 : break;
2870 :
2871 : case( META_GRADIENT_ACTION ):
2872 : {
2873 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2874 : {
2875 0 : const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
2876 0 : const Polygon aRectPoly( pA->GetRect() );
2877 0 : const PolyPolygon aRectPolyPoly( aRectPoly );
2878 :
2879 0 : ImplWriteGradientEx( aRectPolyPoly, pA->GetGradient(), nWriteFlags );
2880 : }
2881 : }
2882 0 : break;
2883 :
2884 : case( META_GRADIENTEX_ACTION ):
2885 : {
2886 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2887 : {
2888 0 : const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
2889 0 : ImplWriteGradientEx( pA->GetPolyPolygon(), pA->GetGradient(), nWriteFlags );
2890 : }
2891 : }
2892 0 : break;
2893 :
2894 : case META_HATCH_ACTION:
2895 : {
2896 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2897 : {
2898 0 : const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
2899 0 : ImplWritePattern( pA->GetPolyPolygon(), &pA->GetHatch(), NULL, nWriteFlags );
2900 : }
2901 : }
2902 0 : break;
2903 :
2904 : case( META_TRANSPARENT_ACTION ):
2905 : {
2906 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2907 : {
2908 0 : const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
2909 0 : const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
2910 :
2911 0 : if( rPolyPoly.Count() )
2912 : {
2913 0 : Color aNewLineColor( mpVDev->GetLineColor() ), aNewFillColor( mpVDev->GetFillColor() );
2914 :
2915 0 : aNewLineColor.SetTransparency( sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
2916 0 : aNewFillColor.SetTransparency( sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
2917 :
2918 0 : mpContext->AddPaintAttr( aNewLineColor, aNewFillColor );
2919 0 : ImplWritePolyPolygon( rPolyPoly, sal_False );
2920 : }
2921 : }
2922 : }
2923 0 : break;
2924 :
2925 : case( META_FLOATTRANSPARENT_ACTION ):
2926 : {
2927 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2928 : {
2929 0 : const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
2930 0 : GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
2931 0 : ImplWriteMask( aTmpMtf, pA->GetPoint(), pA->GetSize(),
2932 0 : pA->GetGradient(), nWriteFlags );
2933 : }
2934 : }
2935 0 : break;
2936 :
2937 : case( META_EPS_ACTION ):
2938 : {
2939 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
2940 : {
2941 0 : const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
2942 0 : const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
2943 0 : sal_Bool bFound = sal_False;
2944 :
2945 0 : for( sal_uInt32 k = 0, nCount2 = aGDIMetaFile.GetActionSize(); ( k < nCount2 ) && !bFound; ++k )
2946 : {
2947 0 : const MetaAction* pSubstAct = aGDIMetaFile.GetAction( k );
2948 :
2949 0 : if( pSubstAct->GetType() == META_BMPSCALE_ACTION )
2950 : {
2951 0 : bFound = sal_True;
2952 0 : const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*) pSubstAct;
2953 0 : ImplWriteBmp( pBmpScaleAction->GetBitmap(),
2954 0 : pA->GetPoint(), pA->GetSize(),
2955 0 : Point(), pBmpScaleAction->GetBitmap().GetSizePixel() );
2956 : }
2957 0 : }
2958 : }
2959 : }
2960 0 : break;
2961 :
2962 : case( META_COMMENT_ACTION ):
2963 : {
2964 0 : const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
2965 :
2966 0 : if( ( pA->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN") ) &&
2967 0 : ( nWriteFlags & SVGWRITER_WRITE_FILL ) )
2968 : {
2969 0 : const MetaGradientExAction* pGradAction = NULL;
2970 0 : sal_Bool bDone = sal_False;
2971 :
2972 0 : while( !bDone && ( ++nCurAction < nCount ) )
2973 : {
2974 0 : pAction = rMtf.GetAction( nCurAction );
2975 :
2976 0 : if( pAction->GetType() == META_GRADIENTEX_ACTION )
2977 0 : pGradAction = (const MetaGradientExAction*) pAction;
2978 0 : else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
2979 0 : ( ( (const MetaCommentAction*) pAction )->GetComment().
2980 0 : equalsIgnoreAsciiCase("XGRAD_SEQ_END") ) )
2981 : {
2982 0 : bDone = sal_True;
2983 : }
2984 : }
2985 :
2986 0 : if( pGradAction )
2987 0 : ImplWriteGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), nWriteFlags );
2988 : }
2989 0 : else if( ( pA->GetComment().equalsIgnoreAsciiCase("XPATHFILL_SEQ_BEGIN") ) &&
2990 0 : ( nWriteFlags & SVGWRITER_WRITE_FILL ) && !( nWriteFlags & SVGWRITER_NO_SHAPE_COMMENTS ) &&
2991 0 : pA->GetDataSize() )
2992 : {
2993 : // write open shape in every case
2994 0 : if( mapCurShape.get() )
2995 : {
2996 0 : ImplWriteShape( *mapCurShape );
2997 0 : mapCurShape.reset();
2998 : }
2999 :
3000 0 : SvMemoryStream aMemStm( (void*) pA->GetData(), pA->GetDataSize(), STREAM_READ );
3001 0 : SvtGraphicFill aFill;
3002 :
3003 0 : ReadSvtGraphicFill( aMemStm, aFill );
3004 :
3005 0 : sal_Bool bGradient = SvtGraphicFill::fillGradient == aFill.getFillType() &&
3006 0 : ( SvtGraphicFill::gradientLinear == aFill.getGradientType() ||
3007 0 : SvtGraphicFill::gradientRadial == aFill.getGradientType() );
3008 0 : sal_Bool bSkip = ( SvtGraphicFill::fillSolid == aFill.getFillType() || bGradient );
3009 :
3010 0 : if( bSkip )
3011 : {
3012 0 : PolyPolygon aShapePolyPoly;
3013 :
3014 0 : aFill.getPath( aShapePolyPoly );
3015 :
3016 0 : if( aShapePolyPoly.Count() )
3017 : {
3018 0 : mapCurShape.reset( new SVGShapeDescriptor );
3019 :
3020 0 : if( pElementId )
3021 : {
3022 0 : mapCurShape->maId = *pElementId + "_" + OUString::number(nEntryCount++);
3023 : }
3024 :
3025 0 : mapCurShape->maShapePolyPoly = aShapePolyPoly;
3026 0 : mapCurShape->maShapeFillColor = aFill.getFillColor();
3027 0 : mapCurShape->maShapeFillColor.SetTransparency( (sal_uInt8) FRound( 255.0 * aFill.getTransparency() ) );
3028 :
3029 0 : if( bGradient )
3030 : {
3031 : // step through following actions until the first Gradient/GradientEx action is found
3032 0 : while( !mapCurShape->mapShapeGradient.get() && bSkip && ( ++nCurAction < nCount ) )
3033 : {
3034 0 : pAction = rMtf.GetAction( nCurAction );
3035 :
3036 0 : if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
3037 0 : ( ( (const MetaCommentAction*) pAction )->GetComment().
3038 0 : equalsIgnoreAsciiCase("XPATHFILL_SEQ_END") ) )
3039 : {
3040 0 : bSkip = sal_False;
3041 : }
3042 0 : else if( pAction->GetType() == META_GRADIENTEX_ACTION )
3043 : {
3044 0 : mapCurShape->mapShapeGradient.reset( new Gradient(
3045 0 : static_cast< const MetaGradientExAction* >( pAction )->GetGradient() ) );
3046 : }
3047 0 : else if( pAction->GetType() == META_GRADIENT_ACTION )
3048 : {
3049 0 : mapCurShape->mapShapeGradient.reset( new Gradient(
3050 0 : static_cast< const MetaGradientAction* >( pAction )->GetGradient() ) );
3051 : }
3052 : }
3053 : }
3054 : }
3055 : else
3056 0 : bSkip = sal_False;
3057 : }
3058 :
3059 : // skip rest of comment
3060 0 : while( bSkip && ( ++nCurAction < nCount ) )
3061 : {
3062 0 : pAction = rMtf.GetAction( nCurAction );
3063 :
3064 0 : if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
3065 0 : ( ( (const MetaCommentAction*) pAction )->GetComment().
3066 0 : equalsIgnoreAsciiCase("XPATHFILL_SEQ_END") ) )
3067 : {
3068 0 : bSkip = sal_False;
3069 : }
3070 0 : }
3071 : }
3072 0 : else if( ( pA->GetComment().equalsIgnoreAsciiCase("XPATHSTROKE_SEQ_BEGIN") ) &&
3073 0 : ( nWriteFlags & SVGWRITER_WRITE_FILL ) && !( nWriteFlags & SVGWRITER_NO_SHAPE_COMMENTS ) &&
3074 0 : pA->GetDataSize() )
3075 : {
3076 0 : SvMemoryStream aMemStm( (void*) pA->GetData(), pA->GetDataSize(), STREAM_READ );
3077 0 : SvtGraphicStroke aStroke;
3078 0 : PolyPolygon aStartArrow, aEndArrow;
3079 :
3080 0 : ReadSvtGraphicStroke( aMemStm, aStroke );
3081 0 : aStroke.getStartArrow( aStartArrow );
3082 0 : aStroke.getEndArrow( aEndArrow );
3083 :
3084 : // Currently no support for strokes with start/end arrow(s)
3085 : // added that support
3086 0 : Polygon aPoly;
3087 :
3088 0 : aStroke.getPath(aPoly);
3089 :
3090 0 : if(mapCurShape.get())
3091 : {
3092 0 : if(1 != mapCurShape->maShapePolyPoly.Count()
3093 0 : || !mapCurShape->maShapePolyPoly[0].IsEqual(aPoly))
3094 : {
3095 : // this path action is not covering the same path than the already existing
3096 : // fill polypolygon, so write out the fill polygon
3097 0 : ImplWriteShape( *mapCurShape );
3098 0 : mapCurShape.reset();
3099 : }
3100 : }
3101 :
3102 0 : if( !mapCurShape.get() )
3103 : {
3104 :
3105 0 : mapCurShape.reset( new SVGShapeDescriptor );
3106 :
3107 0 : if( pElementId )
3108 : {
3109 0 : mapCurShape->maId = *pElementId + "_" + OUString::number(nEntryCount++);
3110 : }
3111 :
3112 0 : mapCurShape->maShapePolyPoly = aPoly;
3113 : }
3114 :
3115 0 : mapCurShape->maShapeLineColor = mpVDev->GetLineColor();
3116 0 : mapCurShape->maShapeLineColor.SetTransparency( (sal_uInt8) FRound( aStroke.getTransparency() * 255.0 ) );
3117 0 : mapCurShape->mnStrokeWidth = FRound( aStroke.getStrokeWidth() );
3118 0 : aStroke.getDashArray( mapCurShape->maDashArray );
3119 :
3120 : // added support for LineJoin
3121 0 : switch(aStroke.getJoinType())
3122 : {
3123 : default: /* SvtGraphicStroke::joinMiter, SvtGraphicStroke::joinNone */
3124 : {
3125 0 : mapCurShape->maLineJoin = basegfx::B2DLINEJOIN_MITER;
3126 0 : break;
3127 : }
3128 : case SvtGraphicStroke::joinRound:
3129 : {
3130 0 : mapCurShape->maLineJoin = basegfx::B2DLINEJOIN_ROUND;
3131 0 : break;
3132 : }
3133 : case SvtGraphicStroke::joinBevel:
3134 : {
3135 0 : mapCurShape->maLineJoin = basegfx::B2DLINEJOIN_BEVEL;
3136 0 : break;
3137 : }
3138 : }
3139 :
3140 : // added support for LineCap
3141 0 : switch(aStroke.getCapType())
3142 : {
3143 : default: /* SvtGraphicStroke::capButt */
3144 : {
3145 0 : mapCurShape->maLineCap = com::sun::star::drawing::LineCap_BUTT;
3146 0 : break;
3147 : }
3148 : case SvtGraphicStroke::capRound:
3149 : {
3150 0 : mapCurShape->maLineCap = com::sun::star::drawing::LineCap_ROUND;
3151 0 : break;
3152 : }
3153 : case SvtGraphicStroke::capSquare:
3154 : {
3155 0 : mapCurShape->maLineCap = com::sun::star::drawing::LineCap_SQUARE;
3156 0 : break;
3157 : }
3158 : }
3159 :
3160 0 : if(mapCurShape.get() &&(aStartArrow.Count() || aEndArrow.Count()))
3161 : {
3162 0 : ImplWriteShape( *mapCurShape );
3163 :
3164 0 : mapCurShape->maShapeFillColor = mapCurShape->maShapeLineColor;
3165 0 : mapCurShape->maShapeLineColor = Color(COL_TRANSPARENT);
3166 0 : mapCurShape->mnStrokeWidth = 0;
3167 0 : mapCurShape->maDashArray.clear();
3168 0 : mapCurShape->maLineJoin = basegfx::B2DLINEJOIN_MITER;
3169 0 : mapCurShape->maLineCap = com::sun::star::drawing::LineCap_BUTT;
3170 :
3171 0 : if(aStartArrow.Count())
3172 : {
3173 0 : mapCurShape->maShapePolyPoly = aStartArrow;
3174 0 : mapCurShape->maId = *pElementId + "_" + OUString::number(nEntryCount++);
3175 :
3176 0 : ImplWriteShape( *mapCurShape );
3177 : }
3178 :
3179 0 : if(aEndArrow.Count())
3180 : {
3181 0 : mapCurShape->maShapePolyPoly = aEndArrow;
3182 0 : mapCurShape->maId = *pElementId + "_" + OUString::number(nEntryCount++);
3183 :
3184 0 : ImplWriteShape( *mapCurShape );
3185 : }
3186 :
3187 0 : mapCurShape.reset();
3188 : }
3189 :
3190 : // write open shape in every case
3191 0 : if( mapCurShape.get() )
3192 : {
3193 0 : ImplWriteShape( *mapCurShape );
3194 0 : mapCurShape.reset();
3195 : }
3196 :
3197 : // skip rest of comment
3198 0 : sal_Bool bSkip = true;
3199 :
3200 0 : while( bSkip && ( ++nCurAction < nCount ) )
3201 : {
3202 0 : pAction = rMtf.GetAction( nCurAction );
3203 :
3204 0 : if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
3205 0 : ( ( (const MetaCommentAction*) pAction )->GetComment().
3206 0 : equalsIgnoreAsciiCase("XPATHSTROKE_SEQ_END") ) )
3207 : {
3208 0 : bSkip = sal_False;
3209 : }
3210 0 : }
3211 : }
3212 0 : else if( !mrExport.IsUsePositionedCharacters() && ( nWriteFlags & SVGWRITER_WRITE_TEXT ) )
3213 : {
3214 0 : if( ( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_PAINTSHAPE_BEGIN" ) ) )
3215 : {
3216 0 : if( pxShape )
3217 : {
3218 0 : Reference< XText > xText( *pxShape, UNO_QUERY );
3219 0 : if( xText.is() )
3220 0 : maTextWriter.setTextShape( xText, pTextEmbeddedBitmapMtf );
3221 : }
3222 0 : maTextWriter.createParagraphEnumeration();
3223 : {
3224 : // nTextFound == -1 => no text found
3225 : // nTextFound == 0 => no text found and end of text shape reached
3226 : // nTextFound == 1 => text found!
3227 0 : sal_Int32 nTextFound = -1;
3228 0 : while( ( nTextFound < 0 ) && ( nCurAction < nCount ) )
3229 : {
3230 0 : nTextFound = maTextWriter.setTextPosition( rMtf, nCurAction );
3231 : }
3232 : // We found some text in the current text shape.
3233 0 : if( nTextFound > 0 )
3234 : {
3235 0 : maTextWriter.setTextProperties( rMtf, nCurAction );
3236 0 : maTextWriter.startTextShape();
3237 : }
3238 : // We reached the end of the current text shape
3239 : // without finding any text. So we need to go back
3240 : // by one action in order to handle the
3241 : // XTEXT_PAINTSHAPE_END action because on the next
3242 : // loop the nCurAction is incremented by one.
3243 : else
3244 : {
3245 0 : --nCurAction;
3246 : }
3247 : }
3248 : }
3249 0 : else if( ( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_PAINTSHAPE_END" ) ) )
3250 : {
3251 0 : maTextWriter.endTextShape();
3252 : }
3253 0 : else if( ( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_EOP" ) ) )
3254 : {
3255 0 : const MetaAction* pNextAction = rMtf.GetAction( nCurAction + 1 );
3256 0 : if( !( ( pNextAction->GetType() == META_COMMENT_ACTION ) &&
3257 0 : ( ( (const MetaCommentAction*) pNextAction )->GetComment().equalsIgnoreAsciiCase("XTEXT_PAINTSHAPE_END") ) ))
3258 : {
3259 : // nTextFound == -1 => no text found and end of paragraph reached
3260 : // nTextFound == 0 => no text found and end of text shape reached
3261 : // nTextFound == 1 => text found!
3262 0 : sal_Int32 nTextFound = -1;
3263 0 : while( ( nTextFound < 0 ) && ( nCurAction < nCount ) )
3264 : {
3265 0 : nTextFound = maTextWriter.setTextPosition( rMtf, nCurAction );
3266 : }
3267 : // We found a paragraph with some text in the
3268 : // current text shape.
3269 0 : if( nTextFound > 0 )
3270 : {
3271 0 : maTextWriter.setTextProperties( rMtf, nCurAction );
3272 0 : maTextWriter.startTextParagraph();
3273 : }
3274 : // We reached the end of the current text shape
3275 : // without finding any text. So we need to go back
3276 : // by one action in order to handle the
3277 : // XTEXT_PAINTSHAPE_END action because on the next
3278 : // loop the nCurAction is incremented by one.
3279 : else
3280 : {
3281 0 : --nCurAction;
3282 : }
3283 :
3284 : }
3285 : }
3286 0 : else if( ( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_EOL" ) ) )
3287 : {
3288 0 : const MetaAction* pNextAction = rMtf.GetAction( nCurAction + 1 );
3289 0 : if( !( ( pNextAction->GetType() == META_COMMENT_ACTION ) &&
3290 0 : ( ( (const MetaCommentAction*) pNextAction )->GetComment().equalsIgnoreAsciiCase("XTEXT_EOP") ) ) )
3291 : {
3292 : // nTextFound == -2 => no text found and end of line reached
3293 : // nTextFound == -1 => no text found and end of paragraph reached
3294 : // nTextFound == 1 => text found!
3295 0 : sal_Int32 nTextFound = -2;
3296 0 : while( ( nTextFound < -1 ) && ( nCurAction < nCount ) )
3297 : {
3298 0 : nTextFound = maTextWriter.setTextPosition( rMtf, nCurAction );
3299 : }
3300 : // We found a line with some text in the current
3301 : // paragraph.
3302 0 : if( nTextFound > 0 )
3303 : {
3304 0 : maTextWriter.startTextPosition();
3305 : }
3306 : // We reached the end of the current paragraph
3307 : // without finding any text. So we need to go back
3308 : // by one action in order to handle the XTEXT_EOP
3309 : // action because on the next loop the nCurAction is
3310 : // incremented by one.
3311 : else
3312 : {
3313 0 : --nCurAction;
3314 : }
3315 : }
3316 : }
3317 : }
3318 : }
3319 0 : break;
3320 :
3321 : case( META_BMP_ACTION ):
3322 : {
3323 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
3324 : {
3325 0 : const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
3326 :
3327 0 : ImplWriteBmp( pA->GetBitmap(),
3328 0 : pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ),
3329 0 : Point(), pA->GetBitmap().GetSizePixel() );
3330 : }
3331 : }
3332 0 : break;
3333 :
3334 : case( META_BMPSCALE_ACTION ):
3335 : {
3336 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
3337 : {
3338 0 : const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
3339 :
3340 : // Bitmaps embedded into text shapes are collected and exported elsewhere.
3341 0 : if( maTextWriter.isTextShapeStarted() )
3342 : {
3343 0 : maTextWriter.writeBitmapPlaceholder( pA );
3344 : }
3345 : else
3346 : {
3347 0 : ImplWriteBmp( pA->GetBitmap(),
3348 0 : pA->GetPoint(), pA->GetSize(),
3349 0 : Point(), pA->GetBitmap().GetSizePixel() );
3350 : }
3351 : }
3352 : }
3353 0 : break;
3354 :
3355 : case( META_BMPSCALEPART_ACTION ):
3356 : {
3357 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
3358 : {
3359 0 : const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
3360 :
3361 0 : ImplWriteBmp( pA->GetBitmap(),
3362 0 : pA->GetDestPoint(), pA->GetDestSize(),
3363 0 : pA->GetSrcPoint(), pA->GetSrcSize() );
3364 : }
3365 : }
3366 0 : break;
3367 :
3368 : case( META_BMPEX_ACTION ):
3369 : {
3370 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
3371 : {
3372 0 : const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction;
3373 :
3374 0 : ImplWriteBmp( pA->GetBitmapEx(),
3375 0 : pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ),
3376 0 : Point(), pA->GetBitmapEx().GetSizePixel() );
3377 : }
3378 : }
3379 0 : break;
3380 :
3381 : case( META_BMPEXSCALE_ACTION ):
3382 : {
3383 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
3384 : {
3385 0 : const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
3386 :
3387 : // Bitmaps embedded into text shapes are collected and exported elsewhere.
3388 0 : if( maTextWriter.isTextShapeStarted() )
3389 : {
3390 0 : maTextWriter.writeBitmapPlaceholder( pA );
3391 : }
3392 : else
3393 : {
3394 0 : ImplWriteBmp( pA->GetBitmapEx(),
3395 0 : pA->GetPoint(), pA->GetSize(),
3396 0 : Point(), pA->GetBitmapEx().GetSizePixel() );
3397 : }
3398 : }
3399 : }
3400 0 : break;
3401 :
3402 : case( META_BMPEXSCALEPART_ACTION ):
3403 : {
3404 0 : if( nWriteFlags & SVGWRITER_WRITE_FILL )
3405 : {
3406 0 : const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
3407 :
3408 0 : ImplWriteBmp( pA->GetBitmapEx(),
3409 0 : pA->GetDestPoint(), pA->GetDestSize(),
3410 0 : pA->GetSrcPoint(), pA->GetSrcSize() );
3411 : }
3412 : }
3413 0 : break;
3414 :
3415 : case( META_TEXT_ACTION ):
3416 : {
3417 0 : if( nWriteFlags & SVGWRITER_WRITE_TEXT )
3418 : {
3419 0 : const MetaTextAction* pA = (const MetaTextAction*) pAction;
3420 0 : const OUString aText = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
3421 :
3422 0 : if( !aText.isEmpty() )
3423 : {
3424 0 : if( mrExport.IsUsePositionedCharacters() )
3425 : {
3426 0 : Font aFont = ImplSetCorrectFontHeight();
3427 0 : mpContext->SetFontAttr( aFont );
3428 0 : ImplWriteText( pA->GetPoint(), aText, NULL, 0 );
3429 : }
3430 : else
3431 : {
3432 0 : maTextWriter.writeTextPortion( pA->GetPoint(), aText );
3433 : }
3434 :
3435 0 : }
3436 : }
3437 : }
3438 0 : break;
3439 :
3440 : case( META_TEXTRECT_ACTION ):
3441 : {
3442 0 : if( nWriteFlags & SVGWRITER_WRITE_TEXT )
3443 : {
3444 0 : const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
3445 :
3446 0 : if (!pA->GetText().isEmpty())
3447 : {
3448 0 : if( mrExport.IsUsePositionedCharacters() )
3449 : {
3450 0 : Font aFont = ImplSetCorrectFontHeight();
3451 0 : mpContext->SetFontAttr( aFont );
3452 0 : ImplWriteText( pA->GetRect().TopLeft(), pA->GetText(), NULL, 0 );
3453 : }
3454 : {
3455 0 : maTextWriter.writeTextPortion( pA->GetRect().TopLeft(), pA->GetText() );
3456 : }
3457 : }
3458 : }
3459 : }
3460 0 : break;
3461 :
3462 : case( META_TEXTARRAY_ACTION ):
3463 : {
3464 0 : if( nWriteFlags & SVGWRITER_WRITE_TEXT )
3465 : {
3466 0 : const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
3467 0 : const OUString aText = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
3468 :
3469 0 : if( !aText.isEmpty() )
3470 : {
3471 0 : if( mrExport.IsUsePositionedCharacters() )
3472 : {
3473 0 : Font aFont = ImplSetCorrectFontHeight();
3474 0 : mpContext->SetFontAttr( aFont );
3475 0 : ImplWriteText( pA->GetPoint(), aText, pA->GetDXArray(), 0 );
3476 : }
3477 : else
3478 : {
3479 0 : maTextWriter.writeTextPortion( pA->GetPoint(), aText );
3480 : }
3481 0 : }
3482 : }
3483 : }
3484 0 : break;
3485 :
3486 : case( META_STRETCHTEXT_ACTION ):
3487 : {
3488 0 : if( nWriteFlags & SVGWRITER_WRITE_TEXT )
3489 : {
3490 0 : const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
3491 0 : const OUString aText = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
3492 :
3493 0 : if( !aText.isEmpty() )
3494 : {
3495 0 : if( mrExport.IsUsePositionedCharacters() )
3496 : {
3497 0 : Font aFont = ImplSetCorrectFontHeight();
3498 0 : mpContext->SetFontAttr( aFont );
3499 0 : ImplWriteText( pA->GetPoint(), aText, NULL, pA->GetWidth() );
3500 : }
3501 : else
3502 : {
3503 0 : maTextWriter.writeTextPortion( pA->GetPoint(), aText );
3504 : }
3505 0 : }
3506 : }
3507 : }
3508 0 : break;
3509 :
3510 : case( META_CLIPREGION_ACTION ):
3511 : case( META_ISECTRECTCLIPREGION_ACTION ):
3512 : case( META_ISECTREGIONCLIPREGION_ACTION ):
3513 : case( META_MOVECLIPREGION_ACTION ):
3514 : {
3515 0 : ( (MetaAction*) pAction )->Execute( mpVDev );
3516 0 : mbClipAttrChanged = sal_True;
3517 : }
3518 0 : break;
3519 :
3520 : case( META_REFPOINT_ACTION ):
3521 : case( META_MAPMODE_ACTION ):
3522 : case( META_LINECOLOR_ACTION ):
3523 : case( META_FILLCOLOR_ACTION ):
3524 : case( META_TEXTLINECOLOR_ACTION ):
3525 : case( META_TEXTFILLCOLOR_ACTION ):
3526 : case( META_TEXTCOLOR_ACTION ):
3527 : case( META_TEXTALIGN_ACTION ):
3528 : case( META_FONT_ACTION ):
3529 : case( META_PUSH_ACTION ):
3530 : case( META_POP_ACTION ):
3531 : case( META_LAYOUTMODE_ACTION ):
3532 : {
3533 0 : ( (MetaAction*) pAction )->Execute( mpVDev );
3534 : }
3535 0 : break;
3536 :
3537 : case( META_RASTEROP_ACTION ):
3538 : case( META_MASK_ACTION ):
3539 : case( META_MASKSCALE_ACTION ):
3540 : case( META_MASKSCALEPART_ACTION ):
3541 : case( META_WALLPAPER_ACTION ):
3542 : case( META_TEXTLINE_ACTION ):
3543 : {
3544 : // !!! >>> we don't want to support these actions
3545 : }
3546 0 : break;
3547 :
3548 : default:
3549 : OSL_FAIL( "SVGActionWriter::ImplWriteActions: unsupported MetaAction #" );
3550 0 : break;
3551 : }
3552 : }
3553 0 : }
3554 :
3555 0 : Font SVGActionWriter::ImplSetCorrectFontHeight() const
3556 : {
3557 0 : Font aFont( mpVDev->GetFont() );
3558 0 : Size aSz;
3559 :
3560 0 : ImplMap( Size( 0, aFont.GetHeight() ), aSz );
3561 :
3562 0 : aFont.SetHeight( aSz.Height() );
3563 :
3564 0 : return aFont;
3565 : }
3566 :
3567 0 : void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm,
3568 : const Size& rSize100thmm,
3569 : const GDIMetaFile& rMtf,
3570 : sal_uInt32 nWriteFlags,
3571 : const OUString* pElementId,
3572 : const Reference< XShape >* pXShape,
3573 : const GDIMetaFile* pTextEmbeddedBitmapMtf )
3574 : {
3575 0 : MapMode aMapMode( rMtf.GetPrefMapMode() );
3576 0 : Size aPrefSize( rMtf.GetPrefSize() );
3577 0 : Fraction aFractionX( aMapMode.GetScaleX() );
3578 0 : Fraction aFractionY( aMapMode.GetScaleY() );
3579 :
3580 0 : mpVDev->Push();
3581 :
3582 0 : Size aSize( OutputDevice::LogicToLogic( rSize100thmm, MAP_100TH_MM, aMapMode ) );
3583 0 : aMapMode.SetScaleX( aFractionX *= Fraction( aSize.Width(), aPrefSize.Width() ) );
3584 0 : aMapMode.SetScaleY( aFractionY *= Fraction( aSize.Height(), aPrefSize.Height() ) );
3585 :
3586 0 : Point aOffset( OutputDevice::LogicToLogic( rPos100thmm, MAP_100TH_MM, aMapMode ) );
3587 0 : aMapMode.SetOrigin( aOffset += aMapMode.GetOrigin() );
3588 :
3589 0 : mpVDev->SetMapMode( aMapMode );
3590 0 : ImplAcquireContext();
3591 :
3592 0 : mapCurShape.reset();
3593 :
3594 0 : ImplWriteActions( rMtf, nWriteFlags, pElementId, pXShape, pTextEmbeddedBitmapMtf );
3595 0 : maTextWriter.endTextParagraph();
3596 :
3597 : // draw open shape that doesn't have a border
3598 0 : if( mapCurShape.get() )
3599 : {
3600 0 : ImplWriteShape( *mapCurShape );
3601 0 : mapCurShape.reset();
3602 : }
3603 :
3604 0 : ImplReleaseContext();
3605 0 : mpVDev->Pop();
3606 0 : }
3607 :
3608 :
3609 : // - SVGWriter -
3610 :
3611 :
3612 0 : SVGWriter::SVGWriter( const Sequence<Any>& args, const Reference< XComponentContext >& rxCtx )
3613 0 : : mxContext(rxCtx)
3614 : {
3615 0 : if(args.getLength()==1)
3616 0 : args[0]>>=maFilterData;
3617 0 : }
3618 :
3619 :
3620 :
3621 0 : SVGWriter::~SVGWriter()
3622 : {
3623 0 : }
3624 :
3625 :
3626 :
3627 0 : void SAL_CALL SVGWriter::write( const Reference<XDocumentHandler>& rxDocHandler,
3628 : const Sequence<sal_Int8>& rMtfSeq ) throw( RuntimeException, std::exception )
3629 : {
3630 0 : SvMemoryStream aMemStm( (char*) rMtfSeq.getConstArray(), rMtfSeq.getLength(), STREAM_READ );
3631 0 : GDIMetaFile aMtf;
3632 :
3633 0 : ReadGDIMetaFile( aMemStm, aMtf );
3634 :
3635 0 : const Reference< XDocumentHandler > xDocumentHandler( rxDocHandler );
3636 0 : SVGExport* pWriter = new SVGExport( mxContext, xDocumentHandler, maFilterData );
3637 0 : pWriter->writeMtf( aMtf );
3638 0 : delete pWriter;
3639 0 : }
3640 :
3641 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|