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