1c142477cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3c142477cSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4c142477cSAndrew Rist * or more contributor license agreements. See the NOTICE file
5c142477cSAndrew Rist * distributed with this work for additional information
6c142477cSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7c142477cSAndrew Rist * to you under the Apache License, Version 2.0 (the
8c142477cSAndrew Rist * "License"); you may not use this file except in compliance
9c142477cSAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11c142477cSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13c142477cSAndrew Rist * Unless required by applicable law or agreed to in writing,
14c142477cSAndrew Rist * software distributed under the License is distributed on an
15c142477cSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16c142477cSAndrew Rist * KIND, either express or implied. See the License for the
17c142477cSAndrew Rist * specific language governing permissions and limitations
18c142477cSAndrew Rist * under the License.
19cdf0e10cSrcweir *
20c142477cSAndrew Rist *************************************************************/
21c142477cSAndrew Rist
22c142477cSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sdext.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include "pdfiprocessor.hxx"
28cdf0e10cSrcweir #include "xmlemitter.hxx"
29cdf0e10cSrcweir #include "pdfihelper.hxx"
30cdf0e10cSrcweir #include "imagecontainer.hxx"
31cdf0e10cSrcweir #include "style.hxx"
32cdf0e10cSrcweir #include "drawtreevisiting.hxx"
33cdf0e10cSrcweir #include "genericelements.hxx"
34cdf0e10cSrcweir
35cdf0e10cSrcweir #include "basegfx/polygon/b2dpolypolygontools.hxx"
36cdf0e10cSrcweir #include "basegfx/range/b2drange.hxx"
37cdf0e10cSrcweir
38cdf0e10cSrcweir #include "com/sun/star/i18n/XBreakIterator.hpp"
39cdf0e10cSrcweir #include "com/sun/star/lang/XMultiServiceFactory.hpp"
40cdf0e10cSrcweir #include "comphelper/processfactory.hxx"
41cdf0e10cSrcweir #include "com/sun/star/i18n/ScriptType.hpp"
42cdf0e10cSrcweir #include "com/sun/star/i18n/DirectionProperty.hpp"
43cdf0e10cSrcweir
44cdf0e10cSrcweir #include <string.h>
45cdf0e10cSrcweir
46cdf0e10cSrcweir using namespace ::com::sun::star;
47cdf0e10cSrcweir using namespace ::com::sun::star;
48cdf0e10cSrcweir using namespace ::com::sun::star::lang;
49cdf0e10cSrcweir using namespace ::com::sun::star::i18n;
50cdf0e10cSrcweir using namespace ::com::sun::star::uno;
51cdf0e10cSrcweir
52cdf0e10cSrcweir namespace pdfi
53cdf0e10cSrcweir {
54cdf0e10cSrcweir
GetBreakIterator()55cdf0e10cSrcweir const ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator >& DrawXmlOptimizer::GetBreakIterator()
56cdf0e10cSrcweir {
57cdf0e10cSrcweir if ( !mxBreakIter.is() )
58cdf0e10cSrcweir {
59cdf0e10cSrcweir Reference< XComponentContext > xContext( this->m_rProcessor.m_xContext, uno::UNO_SET_THROW );
60cdf0e10cSrcweir Reference< XMultiComponentFactory > xMSF( xContext->getServiceManager(), uno::UNO_SET_THROW );
61cdf0e10cSrcweir Reference < XInterface > xInterface = xMSF->createInstanceWithContext(::rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator"), xContext);
62cdf0e10cSrcweir
63cdf0e10cSrcweir mxBreakIter = uno::Reference< i18n::XBreakIterator >( xInterface, uno::UNO_QUERY );
64cdf0e10cSrcweir }
65cdf0e10cSrcweir return mxBreakIter;
66cdf0e10cSrcweir }
67cdf0e10cSrcweir
GetBreakIterator()68cdf0e10cSrcweir const ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XBreakIterator >& DrawXmlEmitter::GetBreakIterator()
69cdf0e10cSrcweir {
70cdf0e10cSrcweir if ( !mxBreakIter.is() )
71cdf0e10cSrcweir {
72cdf0e10cSrcweir Reference< XComponentContext > xContext( m_rEmitContext.m_xContext, uno::UNO_SET_THROW );
73cdf0e10cSrcweir Reference< XMultiComponentFactory > xMSF( xContext->getServiceManager(), uno::UNO_SET_THROW );
74cdf0e10cSrcweir Reference < XInterface > xInterface = xMSF->createInstanceWithContext(::rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator"), xContext);
75cdf0e10cSrcweir mxBreakIter = uno::Reference< i18n::XBreakIterator >( xInterface, uno::UNO_QUERY );
76cdf0e10cSrcweir }
77cdf0e10cSrcweir return mxBreakIter;
78cdf0e10cSrcweir }
79cdf0e10cSrcweir
GetCharacterClassification()80cdf0e10cSrcweir const ::com::sun::star::uno::Reference< ::com::sun::star::i18n::XCharacterClassification >& DrawXmlEmitter::GetCharacterClassification()
81cdf0e10cSrcweir {
82cdf0e10cSrcweir if ( !mxCharClass.is() )
83cdf0e10cSrcweir {
84cdf0e10cSrcweir Reference< XComponentContext > xContext( m_rEmitContext.m_xContext, uno::UNO_SET_THROW );
85cdf0e10cSrcweir Reference< XMultiComponentFactory > xMSF( xContext->getServiceManager(), uno::UNO_SET_THROW );
86cdf0e10cSrcweir Reference < XInterface > xInterface = xMSF->createInstanceWithContext(::rtl::OUString::createFromAscii("com.sun.star.i18n.CharacterClassification"), xContext);
87cdf0e10cSrcweir mxCharClass = uno::Reference< i18n::XCharacterClassification >( xInterface, uno::UNO_QUERY );
88cdf0e10cSrcweir }
89cdf0e10cSrcweir return mxCharClass;
90cdf0e10cSrcweir }
91cdf0e10cSrcweir
visit(HyperlinkElement & elem,const std::list<Element * >::const_iterator &)92cdf0e10cSrcweir void DrawXmlEmitter::visit( HyperlinkElement& elem, const std::list< Element* >::const_iterator& )
93cdf0e10cSrcweir {
94cdf0e10cSrcweir if( elem.Children.empty() )
95cdf0e10cSrcweir return;
96cdf0e10cSrcweir
97cdf0e10cSrcweir const char* pType = dynamic_cast<DrawElement*>(elem.Children.front()) ? "draw:a" : "text:a";
98cdf0e10cSrcweir
99cdf0e10cSrcweir PropertyMap aProps;
100cdf0e10cSrcweir aProps[ USTR( "xlink:type" ) ] = USTR( "simple" );
101cdf0e10cSrcweir aProps[ USTR( "xlink:href" ) ] = elem.URI;
102cdf0e10cSrcweir aProps[ USTR( "office:target-frame-name" ) ] = USTR( "_blank" );
103cdf0e10cSrcweir aProps[ USTR( "xlink:show" ) ] = USTR( "new" );
104cdf0e10cSrcweir
105cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( pType, aProps );
106cdf0e10cSrcweir std::list< Element* >::iterator this_it = elem.Children.begin();
107cdf0e10cSrcweir while( this_it !=elem.Children.end() && *this_it != &elem )
108cdf0e10cSrcweir {
109cdf0e10cSrcweir (*this_it)->visitedBy( *this, this_it );
110cdf0e10cSrcweir this_it++;
111cdf0e10cSrcweir }
112cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( pType );
113cdf0e10cSrcweir }
114cdf0e10cSrcweir
visit(TextElement & elem,const std::list<Element * >::const_iterator &)115cdf0e10cSrcweir void DrawXmlEmitter::visit( TextElement& elem, const std::list< Element* >::const_iterator& )
116cdf0e10cSrcweir {
117cdf0e10cSrcweir if( ! elem.Text.getLength() )
118cdf0e10cSrcweir return;
119cdf0e10cSrcweir
120cdf0e10cSrcweir rtl::OUString strSpace(32);
121cdf0e10cSrcweir rtl::OUString strNbSpace(160);
122cdf0e10cSrcweir rtl::OUString tabSpace(0x09);
123cdf0e10cSrcweir PropertyMap aProps;
124cdf0e10cSrcweir if( elem.StyleId != -1 )
125cdf0e10cSrcweir {
126cdf0e10cSrcweir aProps[ rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "text:style-name" ) ) ] =
127cdf0e10cSrcweir m_rEmitContext.rStyles.getStyleName( elem.StyleId );
128cdf0e10cSrcweir }
129cdf0e10cSrcweir
130cdf0e10cSrcweir rtl::OUString str(elem.Text.getStr());
131cdf0e10cSrcweir
132cdf0e10cSrcweir // Check for RTL
133cdf0e10cSrcweir bool isRTL = false;
134cdf0e10cSrcweir Reference< i18n::XCharacterClassification > xCC( GetCharacterClassification() );
135cdf0e10cSrcweir if( xCC.is() )
136cdf0e10cSrcweir {
137cdf0e10cSrcweir for(int i=1; i< elem.Text.getLength(); i++)
138cdf0e10cSrcweir {
139cdf0e10cSrcweir sal_Int16 nType = xCC->getCharacterDirection( str, i );
140cdf0e10cSrcweir if ( nType == ::com::sun::star::i18n::DirectionProperty_RIGHT_TO_LEFT ||
141cdf0e10cSrcweir nType == ::com::sun::star::i18n::DirectionProperty_RIGHT_TO_LEFT_ARABIC ||
142cdf0e10cSrcweir nType == ::com::sun::star::i18n::DirectionProperty_RIGHT_TO_LEFT_EMBEDDING ||
143cdf0e10cSrcweir nType == ::com::sun::star::i18n::DirectionProperty_RIGHT_TO_LEFT_OVERRIDE
144cdf0e10cSrcweir )
145cdf0e10cSrcweir isRTL = true;
146cdf0e10cSrcweir }
147cdf0e10cSrcweir }
148cdf0e10cSrcweir
149cdf0e10cSrcweir if (isRTL) // If so, reverse string
150cdf0e10cSrcweir str = m_rProcessor.mirrorString( str );
151cdf0e10cSrcweir
152cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "text:span", aProps );
153cdf0e10cSrcweir
154cdf0e10cSrcweir for(int i=0; i< elem.Text.getLength(); i++)
155cdf0e10cSrcweir {
156cdf0e10cSrcweir rtl::OUString strToken= str.copy(i,1) ;
157cdf0e10cSrcweir if( strSpace.equals(strToken) || strNbSpace.equals(strToken))
158cdf0e10cSrcweir {
159cdf0e10cSrcweir aProps[ USTR( "text:c" ) ] = USTR( "1" );
160cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "text:s", aProps );
161cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "text:s");
162cdf0e10cSrcweir }
163cdf0e10cSrcweir else
164cdf0e10cSrcweir {
165cdf0e10cSrcweir if( tabSpace.equals(strToken) )
166cdf0e10cSrcweir {
167cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "text:tab", aProps );
168cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "text:tab");
169cdf0e10cSrcweir }
170cdf0e10cSrcweir else
171cdf0e10cSrcweir {
172cdf0e10cSrcweir m_rEmitContext.rEmitter.write( strToken );
173cdf0e10cSrcweir }
174cdf0e10cSrcweir }
175cdf0e10cSrcweir }
176cdf0e10cSrcweir
177cdf0e10cSrcweir std::list< Element* >::iterator this_it = elem.Children.begin();
178cdf0e10cSrcweir while( this_it !=elem.Children.end() && *this_it != &elem )
179cdf0e10cSrcweir {
180cdf0e10cSrcweir (*this_it)->visitedBy( *this, this_it );
181cdf0e10cSrcweir this_it++;
182cdf0e10cSrcweir }
183cdf0e10cSrcweir
184cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "text:span" );
185cdf0e10cSrcweir }
186cdf0e10cSrcweir
visit(ParagraphElement & elem,const std::list<Element * >::const_iterator &)187cdf0e10cSrcweir void DrawXmlEmitter::visit( ParagraphElement& elem, const std::list< Element* >::const_iterator& )
188cdf0e10cSrcweir {
189cdf0e10cSrcweir PropertyMap aProps;
190cdf0e10cSrcweir if( elem.StyleId != -1 )
191cdf0e10cSrcweir {
192cdf0e10cSrcweir aProps[ USTR( "text:style-name" ) ] = m_rEmitContext.rStyles.getStyleName( elem.StyleId );
193cdf0e10cSrcweir }
194cdf0e10cSrcweir const char* pTagType = "text:p";
195cdf0e10cSrcweir if( elem.Type == elem.Headline )
196cdf0e10cSrcweir pTagType = "text:h";
197cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( pTagType, aProps );
198cdf0e10cSrcweir
199cdf0e10cSrcweir std::list< Element* >::iterator this_it = elem.Children.begin();
200cdf0e10cSrcweir while( this_it !=elem.Children.end() && *this_it != &elem )
201cdf0e10cSrcweir {
202cdf0e10cSrcweir (*this_it)->visitedBy( *this, this_it );
203cdf0e10cSrcweir this_it++;
204cdf0e10cSrcweir }
205cdf0e10cSrcweir
206cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( pTagType );
207cdf0e10cSrcweir }
208cdf0e10cSrcweir
fillFrameProps(DrawElement & rElem,PropertyMap & rProps,const EmitContext & rEmitContext,bool bWasTransformed)209cdf0e10cSrcweir void DrawXmlEmitter::fillFrameProps( DrawElement& rElem,
210cdf0e10cSrcweir PropertyMap& rProps,
211cdf0e10cSrcweir const EmitContext& rEmitContext,
212cdf0e10cSrcweir bool bWasTransformed
213cdf0e10cSrcweir )
214cdf0e10cSrcweir {
215cdf0e10cSrcweir double rel_x = rElem.x, rel_y = rElem.y;
216cdf0e10cSrcweir
217cdf0e10cSrcweir rProps[ USTR( "draw:z-index" ) ] = rtl::OUString::valueOf( rElem.ZOrder );
218cdf0e10cSrcweir rProps[ USTR( "draw:style-name" )] = rEmitContext.rStyles.getStyleName( rElem.StyleId );
219cdf0e10cSrcweir rProps[ USTR( "svg:width" ) ] = convertPixelToUnitString( rElem.w );
220cdf0e10cSrcweir rProps[ USTR( "svg:height" ) ] = convertPixelToUnitString( rElem.h );
221cdf0e10cSrcweir
222cdf0e10cSrcweir const GraphicsContext& rGC =
223cdf0e10cSrcweir rEmitContext.rProcessor.getGraphicsContext( rElem.GCId );
224cdf0e10cSrcweir if( rGC.Transformation.isIdentity() || bWasTransformed )
225cdf0e10cSrcweir {
226cdf0e10cSrcweir rProps[ USTR( "svg:x" ) ] = convertPixelToUnitString( rel_x );
227cdf0e10cSrcweir rProps[ USTR( "svg:y" ) ] = convertPixelToUnitString( rel_y );
228cdf0e10cSrcweir }
229cdf0e10cSrcweir else
230cdf0e10cSrcweir {
231cdf0e10cSrcweir basegfx::B2DTuple aScale, aTranslation;
232cdf0e10cSrcweir double fRotate, fShearX;
233cdf0e10cSrcweir
234cdf0e10cSrcweir rGC.Transformation.decompose( aScale, aTranslation, fRotate, fShearX );
235cdf0e10cSrcweir
236cdf0e10cSrcweir rtl::OUStringBuffer aBuf( 256 );
237cdf0e10cSrcweir
238cdf0e10cSrcweir // TODO(F2): general transformation case missing; if implemented, note
239cdf0e10cSrcweir // that ODF rotation is oriented the other way
240cdf0e10cSrcweir
241cdf0e10cSrcweir // vertical mirroring is done by horizontally mirroring and rotaing 180 degree
242cdf0e10cSrcweir // quaint !
243cdf0e10cSrcweir if( rElem.MirrorVertical )
244cdf0e10cSrcweir fRotate += M_PI;
245cdf0e10cSrcweir
246cdf0e10cSrcweir // build transformation string
247cdf0e10cSrcweir if( fShearX != 0.0 )
248cdf0e10cSrcweir {
249cdf0e10cSrcweir aBuf.appendAscii( "skewX( " );
250cdf0e10cSrcweir aBuf.append( fShearX );
251cdf0e10cSrcweir aBuf.appendAscii( " )" );
252cdf0e10cSrcweir }
253cdf0e10cSrcweir if( fRotate != 0.0 )
254cdf0e10cSrcweir {
255cdf0e10cSrcweir if( aBuf.getLength() > 0 )
256cdf0e10cSrcweir aBuf.append( sal_Unicode(' ') );
257cdf0e10cSrcweir aBuf.appendAscii( "rotate( " );
258cdf0e10cSrcweir aBuf.append( -fRotate );
259cdf0e10cSrcweir aBuf.appendAscii( " )" );
260cdf0e10cSrcweir
261cdf0e10cSrcweir }
262cdf0e10cSrcweir if( aBuf.getLength() > 0 )
263cdf0e10cSrcweir aBuf.append( sal_Unicode(' ') );
264cdf0e10cSrcweir aBuf.appendAscii( "translate( " );
265cdf0e10cSrcweir aBuf.append( convertPixelToUnitString( rel_x ) );
266cdf0e10cSrcweir aBuf.append( sal_Unicode(' ') );
267cdf0e10cSrcweir aBuf.append( convertPixelToUnitString( rel_y ) );
268cdf0e10cSrcweir aBuf.appendAscii( " )" );
269cdf0e10cSrcweir
270cdf0e10cSrcweir rProps[ USTR( "draw:transform" ) ] = aBuf.makeStringAndClear();
271cdf0e10cSrcweir }
272cdf0e10cSrcweir }
273cdf0e10cSrcweir
visit(FrameElement & elem,const std::list<Element * >::const_iterator &)274cdf0e10cSrcweir void DrawXmlEmitter::visit( FrameElement& elem, const std::list< Element* >::const_iterator& )
275cdf0e10cSrcweir {
276cdf0e10cSrcweir if( elem.Children.empty() )
277cdf0e10cSrcweir return;
278cdf0e10cSrcweir
279cdf0e10cSrcweir bool bTextBox = (dynamic_cast<ParagraphElement*>(elem.Children.front()) != NULL);
280cdf0e10cSrcweir PropertyMap aFrameProps;
281cdf0e10cSrcweir fillFrameProps( elem, aFrameProps, m_rEmitContext );
282cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "draw:frame", aFrameProps );
283cdf0e10cSrcweir if( bTextBox )
284cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "draw:text-box", PropertyMap() );
285cdf0e10cSrcweir
286cdf0e10cSrcweir std::list< Element* >::iterator this_it = elem.Children.begin();
287cdf0e10cSrcweir while( this_it !=elem.Children.end() && *this_it != &elem )
288cdf0e10cSrcweir {
289cdf0e10cSrcweir (*this_it)->visitedBy( *this, this_it );
290cdf0e10cSrcweir this_it++;
291cdf0e10cSrcweir }
292cdf0e10cSrcweir
293cdf0e10cSrcweir if( bTextBox )
294cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "draw:text-box" );
295cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "draw:frame" );
296cdf0e10cSrcweir }
297cdf0e10cSrcweir
visit(PolyPolyElement & elem,const std::list<Element * >::const_iterator &)298cdf0e10cSrcweir void DrawXmlEmitter::visit( PolyPolyElement& elem, const std::list< Element* >::const_iterator& )
299cdf0e10cSrcweir {
300cdf0e10cSrcweir elem.updateGeometry();
301cdf0e10cSrcweir /* note:
302cdf0e10cSrcweir * aw recommends using 100dth of mm in all respects since the xml import
303cdf0e10cSrcweir * (a) is buggy (see issue 37213)
304cdf0e10cSrcweir * (b) is optimized for 100dth of mm and does not scale itself then,
305cdf0e10cSrcweir * this does not gain us speed but makes for smaller rounding errors since
306cdf0e10cSrcweir * the xml importer coordinates are integer based
307cdf0e10cSrcweir */
308cdf0e10cSrcweir for (sal_uInt32 i = 0; i< elem.PolyPoly.count(); i++)
309cdf0e10cSrcweir {
310cdf0e10cSrcweir basegfx::B2DPolygon b2dPolygon;
311cdf0e10cSrcweir b2dPolygon = elem.PolyPoly.getB2DPolygon( i );
312cdf0e10cSrcweir
313cdf0e10cSrcweir for ( sal_uInt32 j = 0; j< b2dPolygon.count(); j++ )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir basegfx::B2DPoint point;
316cdf0e10cSrcweir basegfx::B2DPoint nextPoint;
317cdf0e10cSrcweir point = b2dPolygon.getB2DPoint( j );
318cdf0e10cSrcweir
319cdf0e10cSrcweir basegfx::B2DPoint prevPoint;
320cdf0e10cSrcweir prevPoint = b2dPolygon.getPrevControlPoint( j ) ;
321cdf0e10cSrcweir
322cdf0e10cSrcweir point.setX( convPx2mmPrec2( point.getX() )*100.0 );
323cdf0e10cSrcweir point.setY( convPx2mmPrec2( point.getY() )*100.0 );
324cdf0e10cSrcweir
325cdf0e10cSrcweir if ( b2dPolygon.isPrevControlPointUsed( j ) )
326cdf0e10cSrcweir {
327cdf0e10cSrcweir prevPoint.setX( convPx2mmPrec2( prevPoint.getX() )*100.0 );
328cdf0e10cSrcweir prevPoint.setY( convPx2mmPrec2( prevPoint.getY() )*100.0 );
329cdf0e10cSrcweir }
330cdf0e10cSrcweir
331cdf0e10cSrcweir if ( b2dPolygon.isNextControlPointUsed( j ) )
332cdf0e10cSrcweir {
333cdf0e10cSrcweir nextPoint = b2dPolygon.getNextControlPoint( j ) ;
334cdf0e10cSrcweir nextPoint.setX( convPx2mmPrec2( nextPoint.getX() )*100.0 );
335cdf0e10cSrcweir nextPoint.setY( convPx2mmPrec2( nextPoint.getY() )*100.0 );
336cdf0e10cSrcweir }
337cdf0e10cSrcweir
338cdf0e10cSrcweir b2dPolygon.setB2DPoint( j, point );
339cdf0e10cSrcweir
340cdf0e10cSrcweir if ( b2dPolygon.isPrevControlPointUsed( j ) )
341cdf0e10cSrcweir b2dPolygon.setPrevControlPoint( j , prevPoint ) ;
342cdf0e10cSrcweir
343cdf0e10cSrcweir if ( b2dPolygon.isNextControlPointUsed( j ) )
344cdf0e10cSrcweir b2dPolygon.setNextControlPoint( j , nextPoint ) ;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir
347cdf0e10cSrcweir elem.PolyPoly.setB2DPolygon( i, b2dPolygon );
348cdf0e10cSrcweir }
349cdf0e10cSrcweir
350cdf0e10cSrcweir PropertyMap aProps;
351cdf0e10cSrcweir // PDFIProcessor transforms geometrical objects, not images and text
352cdf0e10cSrcweir // so we need to tell fillFrameProps here that the transformation for
353cdf0e10cSrcweir // a PolyPolyElement was already applied (aside form translation)
354cdf0e10cSrcweir fillFrameProps( elem, aProps, m_rEmitContext, true );
355cdf0e10cSrcweir rtl::OUStringBuffer aBuf( 64 );
356cdf0e10cSrcweir aBuf.appendAscii( "0 0 " );
357cdf0e10cSrcweir aBuf.append( convPx2mmPrec2(elem.w)*100.0 );
358cdf0e10cSrcweir aBuf.append( sal_Unicode(' ') );
359cdf0e10cSrcweir aBuf.append( convPx2mmPrec2(elem.h)*100.0 );
360cdf0e10cSrcweir aProps[ USTR( "svg:viewBox" ) ] = aBuf.makeStringAndClear();
361*1f882ec4SArmin Le Grand aProps[ USTR( "svg:d" ) ] = basegfx::tools::exportToSvgD( elem.PolyPoly, true, true, false );
362cdf0e10cSrcweir
363cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "draw:path", aProps );
364cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "draw:path" );
365cdf0e10cSrcweir }
366cdf0e10cSrcweir
visit(ImageElement & elem,const std::list<Element * >::const_iterator &)367cdf0e10cSrcweir void DrawXmlEmitter::visit( ImageElement& elem, const std::list< Element* >::const_iterator& )
368cdf0e10cSrcweir {
369cdf0e10cSrcweir PropertyMap aImageProps;
370cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "draw:image", aImageProps );
371cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "office:binary-data", PropertyMap() );
372cdf0e10cSrcweir m_rEmitContext.rImages.writeBase64EncodedStream( elem.Image, m_rEmitContext);
373cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "office:binary-data" );
374cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "draw:image" );
375cdf0e10cSrcweir }
376cdf0e10cSrcweir
visit(PageElement & elem,const std::list<Element * >::const_iterator &)377cdf0e10cSrcweir void DrawXmlEmitter::visit( PageElement& elem, const std::list< Element* >::const_iterator& )
378cdf0e10cSrcweir {
379cdf0e10cSrcweir PropertyMap aPageProps;
380cdf0e10cSrcweir aPageProps[ USTR( "draw:master-page-name" ) ] = m_rEmitContext.rStyles.getStyleName( elem.StyleId );
381cdf0e10cSrcweir
382cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag("draw:page", aPageProps);
383cdf0e10cSrcweir
384cdf0e10cSrcweir if( m_rEmitContext.xStatusIndicator.is() )
385cdf0e10cSrcweir m_rEmitContext.xStatusIndicator->setValue( elem.PageNumber );
386cdf0e10cSrcweir
387cdf0e10cSrcweir std::list< Element* >::iterator this_it = elem.Children.begin();
388cdf0e10cSrcweir while( this_it !=elem.Children.end() && *this_it != &elem )
389cdf0e10cSrcweir {
390cdf0e10cSrcweir (*this_it)->visitedBy( *this, this_it );
391cdf0e10cSrcweir this_it++;
392cdf0e10cSrcweir }
393cdf0e10cSrcweir
394cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag("draw:page");
395cdf0e10cSrcweir }
396cdf0e10cSrcweir
visit(DocumentElement & elem,const std::list<Element * >::const_iterator &)397cdf0e10cSrcweir void DrawXmlEmitter::visit( DocumentElement& elem, const std::list< Element* >::const_iterator&)
398cdf0e10cSrcweir {
399cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( "office:body", PropertyMap() );
400cdf0e10cSrcweir m_rEmitContext.rEmitter.beginTag( m_bWriteDrawDocument ? "office:drawing" : "office:presentation",
401cdf0e10cSrcweir PropertyMap() );
402cdf0e10cSrcweir
403cdf0e10cSrcweir std::list< Element* >::iterator this_it = elem.Children.begin();
404cdf0e10cSrcweir while( this_it !=elem.Children.end() && *this_it != &elem )
405cdf0e10cSrcweir {
406cdf0e10cSrcweir (*this_it)->visitedBy( *this, this_it );
407cdf0e10cSrcweir this_it++;
408cdf0e10cSrcweir }
409cdf0e10cSrcweir
410cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( m_bWriteDrawDocument ? "office:drawing" : "office:presentation" );
411cdf0e10cSrcweir m_rEmitContext.rEmitter.endTag( "office:body" );
412cdf0e10cSrcweir }
413cdf0e10cSrcweir
414cdf0e10cSrcweir /////////////////////////////////////////////////////////////////
415cdf0e10cSrcweir
visit(HyperlinkElement &,const std::list<Element * >::const_iterator &)416cdf0e10cSrcweir void DrawXmlOptimizer::visit( HyperlinkElement&, const std::list< Element* >::const_iterator& )
417cdf0e10cSrcweir {
418cdf0e10cSrcweir }
419cdf0e10cSrcweir
visit(TextElement &,const std::list<Element * >::const_iterator &)420cdf0e10cSrcweir void DrawXmlOptimizer::visit( TextElement&, const std::list< Element* >::const_iterator&)
421cdf0e10cSrcweir {
422cdf0e10cSrcweir }
423cdf0e10cSrcweir
visit(FrameElement & elem,const std::list<Element * >::const_iterator &)424cdf0e10cSrcweir void DrawXmlOptimizer::visit( FrameElement& elem, const std::list< Element* >::const_iterator& )
425cdf0e10cSrcweir {
426cdf0e10cSrcweir elem.applyToChildren(*this);
427cdf0e10cSrcweir }
428cdf0e10cSrcweir
visit(ImageElement &,const std::list<Element * >::const_iterator &)429cdf0e10cSrcweir void DrawXmlOptimizer::visit( ImageElement&, const std::list< Element* >::const_iterator& )
430cdf0e10cSrcweir {
431cdf0e10cSrcweir }
432cdf0e10cSrcweir
visit(PolyPolyElement & elem,const std::list<Element * >::const_iterator &)433cdf0e10cSrcweir void DrawXmlOptimizer::visit( PolyPolyElement& elem, const std::list< Element* >::const_iterator& )
434cdf0e10cSrcweir {
435cdf0e10cSrcweir /* note: optimize two consecutive PolyPolyElements that
436cdf0e10cSrcweir * have the same path but one of which is a stroke while
437cdf0e10cSrcweir * the other is a fill
438cdf0e10cSrcweir */
439cdf0e10cSrcweir if( elem.Parent )
440cdf0e10cSrcweir {
441cdf0e10cSrcweir // find following PolyPolyElement in parent's children list
442cdf0e10cSrcweir std::list< Element* >::iterator this_it = elem.Parent->Children.begin();
443cdf0e10cSrcweir while( this_it != elem.Parent->Children.end() && *this_it != &elem )
444cdf0e10cSrcweir ++this_it;
445cdf0e10cSrcweir
446cdf0e10cSrcweir if( this_it != elem.Parent->Children.end() )
447cdf0e10cSrcweir {
448cdf0e10cSrcweir std::list< Element* >::iterator next_it = this_it;
449cdf0e10cSrcweir if( ++next_it != elem.Parent->Children.end() )
450cdf0e10cSrcweir {
451cdf0e10cSrcweir PolyPolyElement* pNext = dynamic_cast<PolyPolyElement*>(*next_it);
452cdf0e10cSrcweir
453cdf0e10cSrcweir // TODO(F2): this comparison fails for OOo-generated polygons with beziers.
454cdf0e10cSrcweir if( pNext && pNext->PolyPoly == elem.PolyPoly )
455cdf0e10cSrcweir {
456cdf0e10cSrcweir const GraphicsContext& rNextGC =
457cdf0e10cSrcweir m_rProcessor.getGraphicsContext( pNext->GCId );
458cdf0e10cSrcweir const GraphicsContext& rThisGC =
459cdf0e10cSrcweir m_rProcessor.getGraphicsContext( elem.GCId );
460cdf0e10cSrcweir
461cdf0e10cSrcweir if( rThisGC.BlendMode == rNextGC.BlendMode &&
462cdf0e10cSrcweir rThisGC.Flatness == rNextGC.Flatness &&
463cdf0e10cSrcweir rThisGC.Transformation == rNextGC.Transformation &&
464cdf0e10cSrcweir rThisGC.Clip == rNextGC.Clip &&
465cdf0e10cSrcweir rThisGC.FillColor.Red == rNextGC.FillColor.Red &&
466cdf0e10cSrcweir rThisGC.FillColor.Green== rNextGC.FillColor.Green &&
467cdf0e10cSrcweir rThisGC.FillColor.Blue == rNextGC.FillColor.Blue &&
468cdf0e10cSrcweir rThisGC.FillColor.Alpha== rNextGC.FillColor.Alpha &&
469cdf0e10cSrcweir pNext->Action == PATH_STROKE &&
470cdf0e10cSrcweir (elem.Action == PATH_FILL || elem.Action == PATH_EOFILL) )
471cdf0e10cSrcweir {
472cdf0e10cSrcweir GraphicsContext aGC = rThisGC;
473cdf0e10cSrcweir aGC.LineJoin = rNextGC.LineJoin;
474cdf0e10cSrcweir aGC.LineCap = rNextGC.LineCap;
475cdf0e10cSrcweir aGC.LineWidth = rNextGC.LineWidth;
476cdf0e10cSrcweir aGC.MiterLimit= rNextGC.MiterLimit;
477cdf0e10cSrcweir aGC.DashArray = rNextGC.DashArray;
478cdf0e10cSrcweir aGC.LineColor = rNextGC.LineColor;
479cdf0e10cSrcweir elem.GCId = m_rProcessor.getGCId( aGC );
480cdf0e10cSrcweir
481cdf0e10cSrcweir elem.Action |= pNext->Action;
482cdf0e10cSrcweir
483cdf0e10cSrcweir elem.Children.splice( elem.Children.end(), pNext->Children );
484cdf0e10cSrcweir elem.Parent->Children.erase( next_it );
485cdf0e10cSrcweir delete pNext;
486cdf0e10cSrcweir }
487cdf0e10cSrcweir }
488cdf0e10cSrcweir }
489cdf0e10cSrcweir }
490cdf0e10cSrcweir }
491cdf0e10cSrcweir }
492cdf0e10cSrcweir
visit(ParagraphElement & elem,const std::list<Element * >::const_iterator &)493cdf0e10cSrcweir void DrawXmlOptimizer::visit( ParagraphElement& elem, const std::list< Element* >::const_iterator& )
494cdf0e10cSrcweir {
495cdf0e10cSrcweir optimizeTextElements( elem );
496cdf0e10cSrcweir
497cdf0e10cSrcweir elem.applyToChildren(*this);
498cdf0e10cSrcweir }
499cdf0e10cSrcweir
visit(PageElement & elem,const std::list<Element * >::const_iterator &)500cdf0e10cSrcweir void DrawXmlOptimizer::visit( PageElement& elem, const std::list< Element* >::const_iterator& )
501cdf0e10cSrcweir {
502cdf0e10cSrcweir if( m_rProcessor.getStatusIndicator().is() )
503cdf0e10cSrcweir m_rProcessor.getStatusIndicator()->setValue( elem.PageNumber );
504cdf0e10cSrcweir
505cdf0e10cSrcweir // resolve hyperlinks
506cdf0e10cSrcweir elem.resolveHyperlinks();
507cdf0e10cSrcweir
508cdf0e10cSrcweir elem.resolveFontStyles( m_rProcessor ); // underlines and such
509cdf0e10cSrcweir
510cdf0e10cSrcweir // FIXME: until hyperlinks and font effects are adjusted for
511cdf0e10cSrcweir // geometrical search handle them before sorting
512cdf0e10cSrcweir m_rProcessor.sortElements( &elem );
513cdf0e10cSrcweir
514cdf0e10cSrcweir // find paragraphs in text
515cdf0e10cSrcweir ParagraphElement* pCurPara = NULL;
516cdf0e10cSrcweir std::list< Element* >::iterator page_element, next_page_element;
517cdf0e10cSrcweir next_page_element = elem.Children.begin();
518cdf0e10cSrcweir double fCurLineHeight = 0.0; // average height of text items in current para
519cdf0e10cSrcweir int nCurLineElements = 0; // number of line contributing elements in current para
520cdf0e10cSrcweir double line_left = elem.w, line_right = 0.0;
521cdf0e10cSrcweir double column_width = elem.w*0.75; // estimate text width
522cdf0e10cSrcweir // TODO: guess columns
523cdf0e10cSrcweir while( next_page_element != elem.Children.end() )
524cdf0e10cSrcweir {
525cdf0e10cSrcweir page_element = next_page_element++;
526cdf0e10cSrcweir ParagraphElement* pPagePara = dynamic_cast<ParagraphElement*>(*page_element);
527cdf0e10cSrcweir if( pPagePara )
528cdf0e10cSrcweir {
529cdf0e10cSrcweir pCurPara = pPagePara;
530cdf0e10cSrcweir // adjust line height and text items
531cdf0e10cSrcweir fCurLineHeight = 0.0;
532cdf0e10cSrcweir nCurLineElements = 0;
533cdf0e10cSrcweir for( std::list< Element* >::iterator it = pCurPara->Children.begin();
534cdf0e10cSrcweir it != pCurPara->Children.end(); ++it )
535cdf0e10cSrcweir {
536cdf0e10cSrcweir TextElement* pTestText = dynamic_cast<TextElement*>(*it);
537cdf0e10cSrcweir if( pTestText )
538cdf0e10cSrcweir {
539cdf0e10cSrcweir fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pTestText->h)/double(nCurLineElements+1);
540cdf0e10cSrcweir nCurLineElements++;
541cdf0e10cSrcweir }
542cdf0e10cSrcweir }
543cdf0e10cSrcweir continue;
544cdf0e10cSrcweir }
545cdf0e10cSrcweir
546cdf0e10cSrcweir HyperlinkElement* pLink = dynamic_cast<HyperlinkElement*>(*page_element);
547cdf0e10cSrcweir DrawElement* pDraw = dynamic_cast<DrawElement*>(*page_element);
548cdf0e10cSrcweir if( ! pDraw && pLink && ! pLink->Children.empty() )
549cdf0e10cSrcweir pDraw = dynamic_cast<DrawElement*>(pLink->Children.front() );
550cdf0e10cSrcweir if( pDraw )
551cdf0e10cSrcweir {
552cdf0e10cSrcweir // insert small drawing objects as character, else leave them page bound
553cdf0e10cSrcweir
554cdf0e10cSrcweir bool bInsertToParagraph = false;
555cdf0e10cSrcweir // first check if this is either inside the paragraph
556cdf0e10cSrcweir if( pCurPara && pDraw->y < pCurPara->y + pCurPara->h )
557cdf0e10cSrcweir {
558cdf0e10cSrcweir if( pDraw->h < fCurLineHeight * 1.5 )
559cdf0e10cSrcweir {
560cdf0e10cSrcweir bInsertToParagraph = true;
561cdf0e10cSrcweir fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pDraw->h)/double(nCurLineElements+1);
562cdf0e10cSrcweir nCurLineElements++;
563cdf0e10cSrcweir // mark draw element as character
564cdf0e10cSrcweir pDraw->isCharacter = true;
565cdf0e10cSrcweir }
566cdf0e10cSrcweir }
567cdf0e10cSrcweir // or perhaps the draw element begins a new paragraph
568cdf0e10cSrcweir else if( next_page_element != elem.Children.end() )
569cdf0e10cSrcweir {
570cdf0e10cSrcweir TextElement* pText = dynamic_cast<TextElement*>(*next_page_element);
571cdf0e10cSrcweir if( ! pText )
572cdf0e10cSrcweir {
573cdf0e10cSrcweir ParagraphElement* pPara = dynamic_cast<ParagraphElement*>(*next_page_element);
574cdf0e10cSrcweir if( pPara && ! pPara->Children.empty() )
575cdf0e10cSrcweir pText = dynamic_cast<TextElement*>(pPara->Children.front());
576cdf0e10cSrcweir }
577cdf0e10cSrcweir if( pText && // check there is a text
578cdf0e10cSrcweir pDraw->h < pText->h*1.5 && // and it is approx the same height
579cdf0e10cSrcweir // and either upper or lower edge of pDraw is inside text's vertical range
580cdf0e10cSrcweir ( ( pDraw->y >= pText->y && pDraw->y <= pText->y+pText->h ) ||
581cdf0e10cSrcweir ( pDraw->y+pDraw->h >= pText->y && pDraw->y+pDraw->h <= pText->y+pText->h )
582cdf0e10cSrcweir )
583cdf0e10cSrcweir )
584cdf0e10cSrcweir {
585cdf0e10cSrcweir bInsertToParagraph = true;
586cdf0e10cSrcweir fCurLineHeight = pDraw->h;
587cdf0e10cSrcweir nCurLineElements = 1;
588cdf0e10cSrcweir line_left = pDraw->x;
589cdf0e10cSrcweir line_right = pDraw->x + pDraw->w;
590cdf0e10cSrcweir // begin a new paragraph
591cdf0e10cSrcweir pCurPara = NULL;
592cdf0e10cSrcweir // mark draw element as character
593cdf0e10cSrcweir pDraw->isCharacter = true;
594cdf0e10cSrcweir }
595cdf0e10cSrcweir }
596cdf0e10cSrcweir
597cdf0e10cSrcweir if( ! bInsertToParagraph )
598cdf0e10cSrcweir {
599cdf0e10cSrcweir pCurPara = NULL;
600cdf0e10cSrcweir continue;
601cdf0e10cSrcweir }
602cdf0e10cSrcweir }
603cdf0e10cSrcweir
604cdf0e10cSrcweir TextElement* pText = dynamic_cast<TextElement*>(*page_element);
605cdf0e10cSrcweir if( ! pText && pLink && ! pLink->Children.empty() )
606cdf0e10cSrcweir pText = dynamic_cast<TextElement*>(pLink->Children.front());
607cdf0e10cSrcweir if( pText )
608cdf0e10cSrcweir {
609cdf0e10cSrcweir Element* pGeo = pLink ? static_cast<Element*>(pLink) :
610cdf0e10cSrcweir static_cast<Element*>(pText);
611cdf0e10cSrcweir if( pCurPara )
612cdf0e10cSrcweir {
613cdf0e10cSrcweir // there was already a text element, check for a new paragraph
614cdf0e10cSrcweir if( nCurLineElements > 0 )
615cdf0e10cSrcweir {
616cdf0e10cSrcweir // if the new text is significantly distant from the paragraph
617cdf0e10cSrcweir // begin a new paragraph
618cdf0e10cSrcweir if( pGeo->y > pCurPara->y + pCurPara->h + fCurLineHeight*0.5 )
619cdf0e10cSrcweir pCurPara = NULL; // insert new paragraph
620cdf0e10cSrcweir else if( pGeo->y > (pCurPara->y+pCurPara->h - fCurLineHeight*0.05) )
621cdf0e10cSrcweir {
622cdf0e10cSrcweir // new paragraph if either the last line of the paragraph
623cdf0e10cSrcweir // was significantly shorter than the paragraph as a whole
624cdf0e10cSrcweir if( (line_right - line_left) < pCurPara->w*0.75 )
625cdf0e10cSrcweir pCurPara = NULL;
626cdf0e10cSrcweir // or the last line was significantly smaller than the column width
627cdf0e10cSrcweir else if( (line_right - line_left) < column_width*0.75 )
628cdf0e10cSrcweir pCurPara = NULL;
629cdf0e10cSrcweir }
630cdf0e10cSrcweir }
631cdf0e10cSrcweir
632cdf0e10cSrcweir
633cdf0e10cSrcweir }
634cdf0e10cSrcweir
635cdf0e10cSrcweir
636cdf0e10cSrcweir // update line height/width
637cdf0e10cSrcweir if( pCurPara )
638cdf0e10cSrcweir {
639cdf0e10cSrcweir fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pGeo->h)/double(nCurLineElements+1);
640cdf0e10cSrcweir nCurLineElements++;
641cdf0e10cSrcweir if( pGeo->x < line_left )
642cdf0e10cSrcweir line_left = pGeo->x;
643cdf0e10cSrcweir if( pGeo->x+pGeo->w > line_right )
644cdf0e10cSrcweir line_right = pGeo->x+pGeo->w;
645cdf0e10cSrcweir }
646cdf0e10cSrcweir else
647cdf0e10cSrcweir {
648cdf0e10cSrcweir fCurLineHeight = pGeo->h;
649cdf0e10cSrcweir nCurLineElements = 1;
650cdf0e10cSrcweir line_left = pGeo->x;
651cdf0e10cSrcweir line_right = pGeo->x + pGeo->w;
652cdf0e10cSrcweir }
653cdf0e10cSrcweir }
654cdf0e10cSrcweir
655cdf0e10cSrcweir
656cdf0e10cSrcweir // move element to current paragraph
657cdf0e10cSrcweir if (! pCurPara ) // new paragraph, insert one
658cdf0e10cSrcweir {
659cdf0e10cSrcweir pCurPara = m_rProcessor.getElementFactory()->createParagraphElement( NULL );
660cdf0e10cSrcweir // set parent
661cdf0e10cSrcweir pCurPara->Parent = &elem;
662cdf0e10cSrcweir //insert new paragraph before current element
663cdf0e10cSrcweir page_element = elem.Children.insert( page_element, pCurPara );
664cdf0e10cSrcweir // forward iterator to current element again
665cdf0e10cSrcweir ++ page_element;
666cdf0e10cSrcweir // update next_element which is now invalid
667cdf0e10cSrcweir next_page_element = page_element;
668cdf0e10cSrcweir ++ next_page_element;
669cdf0e10cSrcweir }
670cdf0e10cSrcweir Element* pCurEle = *page_element;
671cdf0e10cSrcweir pCurEle->setParent( page_element, pCurPara );
672cdf0e10cSrcweir OSL_ENSURE( !pText || pCurEle == pText || pCurEle == pLink, "paragraph child list in disorder" );
673cdf0e10cSrcweir if( pText || pDraw )
674cdf0e10cSrcweir pCurPara->updateGeometryWith( pCurEle );
675cdf0e10cSrcweir }
676cdf0e10cSrcweir
677cdf0e10cSrcweir // process children
678cdf0e10cSrcweir elem.applyToChildren(*this);
679cdf0e10cSrcweir }
680cdf0e10cSrcweir
isSpaces(TextElement * pTextElem)681cdf0e10cSrcweir bool isSpaces(TextElement* pTextElem)
682cdf0e10cSrcweir {
683cdf0e10cSrcweir rtl::OUString strSpace(32);
684cdf0e10cSrcweir ::rtl::OUString ouTxt2(pTextElem->Text);
685cdf0e10cSrcweir for(int i=0; i< pTextElem->Text.getLength(); i++)
686cdf0e10cSrcweir {
687cdf0e10cSrcweir rtl::OUString strToken = ouTxt2.copy(i,1) ;
688cdf0e10cSrcweir if( !strSpace.equals(strToken) )
689cdf0e10cSrcweir return false;
690cdf0e10cSrcweir }
691cdf0e10cSrcweir return true;
692cdf0e10cSrcweir }
693cdf0e10cSrcweir
notTransformed(GraphicsContext GC)694cdf0e10cSrcweir bool notTransformed(GraphicsContext GC)
695cdf0e10cSrcweir {
696cdf0e10cSrcweir return (
697cdf0e10cSrcweir GC.Transformation.get(0,0) == 100.00 &&
698cdf0e10cSrcweir GC.Transformation.get(1,0) == 0.00 &&
699cdf0e10cSrcweir GC.Transformation.get(0,1) == 0.00 &&
700cdf0e10cSrcweir GC.Transformation.get(1,1) == -100.00
701cdf0e10cSrcweir );
702cdf0e10cSrcweir }
703cdf0e10cSrcweir
optimizeTextElements(Element & rParent)704cdf0e10cSrcweir void DrawXmlOptimizer::optimizeTextElements(Element& rParent)
705cdf0e10cSrcweir {
706cdf0e10cSrcweir if( rParent.Children.empty() ) // this should not happen
707cdf0e10cSrcweir {
708cdf0e10cSrcweir OSL_ENSURE( 0, "empty paragraph optimized" );
709cdf0e10cSrcweir return;
710cdf0e10cSrcweir }
711cdf0e10cSrcweir
712cdf0e10cSrcweir // concatenate child elements with same font id
713cdf0e10cSrcweir std::list< Element* >::iterator next = rParent.Children.begin();
714cdf0e10cSrcweir std::list< Element* >::iterator it = next++;
715cdf0e10cSrcweir FrameElement* pFrame = dynamic_cast<FrameElement*>(rParent.Parent);
716cdf0e10cSrcweir bool bRotatedFrame = false;
717cdf0e10cSrcweir if( pFrame )
718cdf0e10cSrcweir {
719cdf0e10cSrcweir const GraphicsContext& rFrameGC = m_rProcessor.getGraphicsContext( pFrame->GCId );
720cdf0e10cSrcweir if( rFrameGC.isRotatedOrSkewed() )
721cdf0e10cSrcweir bRotatedFrame = true;
722cdf0e10cSrcweir }
723cdf0e10cSrcweir while( next != rParent.Children.end() )
724cdf0e10cSrcweir {
725cdf0e10cSrcweir bool bConcat = false;
726cdf0e10cSrcweir TextElement* pCur = dynamic_cast<TextElement*>(*it);
727cdf0e10cSrcweir
728cdf0e10cSrcweir if( pCur )
729cdf0e10cSrcweir {
730cdf0e10cSrcweir TextElement* pNext = dynamic_cast<TextElement*>(*next);
731cdf0e10cSrcweir bool isComplex = false;
732cdf0e10cSrcweir rtl::OUString str(pCur->Text.getStr());
733cdf0e10cSrcweir for(int i=0; i< str.getLength(); i++)
734cdf0e10cSrcweir {
735cdf0e10cSrcweir sal_Int16 nType = GetBreakIterator()->getScriptType( str, i );
736cdf0e10cSrcweir if (nType == ::com::sun::star::i18n::ScriptType::COMPLEX)
737cdf0e10cSrcweir isComplex = true;
738cdf0e10cSrcweir }
739cdf0e10cSrcweir bool bPara = strspn("ParagraphElement", typeid(rParent).name());
740cdf0e10cSrcweir ParagraphElement* pPara = dynamic_cast<ParagraphElement*>(&rParent);
741cdf0e10cSrcweir if (bPara && isComplex)
742cdf0e10cSrcweir pPara->bRtl = true;
743cdf0e10cSrcweir if( pNext )
744cdf0e10cSrcweir {
745cdf0e10cSrcweir const GraphicsContext& rCurGC = m_rProcessor.getGraphicsContext( pCur->GCId );
746cdf0e10cSrcweir const GraphicsContext& rNextGC = m_rProcessor.getGraphicsContext( pNext->GCId );
747cdf0e10cSrcweir
748cdf0e10cSrcweir // line and space optimization; works only in strictly horizontal mode
749cdf0e10cSrcweir
750cdf0e10cSrcweir // concatenate consecutive text elements unless there is a
751cdf0e10cSrcweir // font or text color or matrix change, leave a new span in that case
752cdf0e10cSrcweir if( (pCur->FontId == pNext->FontId || isSpaces(pNext)) &&
753cdf0e10cSrcweir rCurGC.FillColor.Red == rNextGC.FillColor.Red &&
754cdf0e10cSrcweir rCurGC.FillColor.Green == rNextGC.FillColor.Green &&
755cdf0e10cSrcweir rCurGC.FillColor.Blue == rNextGC.FillColor.Blue &&
756cdf0e10cSrcweir rCurGC.FillColor.Alpha == rNextGC.FillColor.Alpha &&
757cdf0e10cSrcweir (rCurGC.Transformation == rNextGC.Transformation || notTransformed(rNextGC))
758cdf0e10cSrcweir )
759cdf0e10cSrcweir {
760cdf0e10cSrcweir pCur->updateGeometryWith( pNext );
761cdf0e10cSrcweir // append text to current element
762cdf0e10cSrcweir pCur->Text.append( pNext->Text.getStr(), pNext->Text.getLength() );
763cdf0e10cSrcweir
764cdf0e10cSrcweir str = pCur->Text.getStr();
765cdf0e10cSrcweir for(int i=0; i< str.getLength(); i++)
766cdf0e10cSrcweir {
767cdf0e10cSrcweir sal_Int16 nType = GetBreakIterator()->getScriptType( str, i );
768cdf0e10cSrcweir if (nType == ::com::sun::star::i18n::ScriptType::COMPLEX)
769cdf0e10cSrcweir isComplex = true;
770cdf0e10cSrcweir }
771cdf0e10cSrcweir if (bPara && isComplex)
772cdf0e10cSrcweir pPara->bRtl = true;
773cdf0e10cSrcweir // append eventual children to current element
774cdf0e10cSrcweir // and clear children (else the children just
775cdf0e10cSrcweir // appended to pCur would be destroyed)
776cdf0e10cSrcweir pCur->Children.splice( pCur->Children.end(), pNext->Children );
777cdf0e10cSrcweir // get rid of the now useless element
778cdf0e10cSrcweir rParent.Children.erase( next );
779cdf0e10cSrcweir delete pNext;
780cdf0e10cSrcweir bConcat = true;
781cdf0e10cSrcweir }
782cdf0e10cSrcweir }
783cdf0e10cSrcweir }
784cdf0e10cSrcweir else if( dynamic_cast<HyperlinkElement*>(*it) )
785cdf0e10cSrcweir optimizeTextElements( **it );
786cdf0e10cSrcweir if ( bConcat )
787cdf0e10cSrcweir next = it;
788cdf0e10cSrcweir else
789cdf0e10cSrcweir ++it;
790cdf0e10cSrcweir ++next;
791cdf0e10cSrcweir }
792cdf0e10cSrcweir }
793cdf0e10cSrcweir
visit(DocumentElement & elem,const std::list<Element * >::const_iterator &)794cdf0e10cSrcweir void DrawXmlOptimizer::visit( DocumentElement& elem, const std::list< Element* >::const_iterator&)
795cdf0e10cSrcweir {
796cdf0e10cSrcweir elem.applyToChildren(*this);
797cdf0e10cSrcweir }
798cdf0e10cSrcweir
799cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////////
800cdf0e10cSrcweir
801cdf0e10cSrcweir
visit(PolyPolyElement & elem,const std::list<Element * >::const_iterator &)802cdf0e10cSrcweir void DrawXmlFinalizer::visit( PolyPolyElement& elem, const std::list< Element* >::const_iterator& )
803cdf0e10cSrcweir {
804cdf0e10cSrcweir // xxx TODO copied from DrawElement
805cdf0e10cSrcweir const GraphicsContext& rGC = m_rProcessor.getGraphicsContext(elem.GCId );
806cdf0e10cSrcweir PropertyMap aProps;
807cdf0e10cSrcweir aProps[ USTR( "style:family" ) ] = USTR( "graphic" );
808cdf0e10cSrcweir aProps[ USTR( "style:parent-style-name") ] = USTR( "standard" );
809cdf0e10cSrcweir // generate standard graphic style if necessary
810cdf0e10cSrcweir m_rStyleContainer.getStandardStyleId( "graphic" );
811cdf0e10cSrcweir
812cdf0e10cSrcweir PropertyMap aGCProps;
813cdf0e10cSrcweir
814cdf0e10cSrcweir // TODO(F3): proper dash emulation
815cdf0e10cSrcweir if( elem.Action & PATH_STROKE )
816cdf0e10cSrcweir {
817cdf0e10cSrcweir aGCProps[ USTR("draw:stroke") ] = rGC.DashArray.empty() ? USTR("solid") : USTR("dash");
818cdf0e10cSrcweir aGCProps[ USTR("svg:stroke-color") ] = getColorString( rGC.LineColor );
819cdf0e10cSrcweir if( rGC.LineWidth != 0.0 )
820cdf0e10cSrcweir {
821cdf0e10cSrcweir ::basegfx::B2DVector aVec(rGC.LineWidth,0);
822cdf0e10cSrcweir aVec *= rGC.Transformation;
823cdf0e10cSrcweir
824cdf0e10cSrcweir aVec.setX ( convPx2mmPrec2( aVec.getX() )*100.0 );
825cdf0e10cSrcweir aVec.setY ( convPx2mmPrec2( aVec.getY() )*100.0 );
826cdf0e10cSrcweir
827cdf0e10cSrcweir aGCProps[ USTR("svg:stroke-width") ] = rtl::OUString::valueOf( aVec.getLength() );
828cdf0e10cSrcweir }
829cdf0e10cSrcweir }
830cdf0e10cSrcweir else
831cdf0e10cSrcweir {
832cdf0e10cSrcweir aGCProps[ USTR("draw:stroke") ] = USTR("none");
833cdf0e10cSrcweir }
834cdf0e10cSrcweir
835cdf0e10cSrcweir // TODO(F1): check whether stuff could be emulated by gradient/bitmap/hatch
836cdf0e10cSrcweir if( elem.Action & (PATH_FILL | PATH_EOFILL) )
837cdf0e10cSrcweir {
838cdf0e10cSrcweir aGCProps[ USTR("draw:fill") ] = USTR("solid");
839cdf0e10cSrcweir aGCProps[ USTR("draw:fill-color") ] = getColorString( rGC.FillColor );
840cdf0e10cSrcweir }
841cdf0e10cSrcweir else
842cdf0e10cSrcweir {
843cdf0e10cSrcweir aGCProps[ USTR("draw:fill") ] = USTR("none");
844cdf0e10cSrcweir }
845cdf0e10cSrcweir
846cdf0e10cSrcweir StyleContainer::Style aStyle( "style:style", aProps );
847cdf0e10cSrcweir StyleContainer::Style aSubStyle( "style:graphic-properties", aGCProps );
848cdf0e10cSrcweir aStyle.SubStyles.push_back( &aSubStyle );
849cdf0e10cSrcweir
850cdf0e10cSrcweir elem.StyleId = m_rStyleContainer.getStyleId( aStyle );
851cdf0e10cSrcweir }
852cdf0e10cSrcweir
visit(HyperlinkElement &,const std::list<Element * >::const_iterator &)853cdf0e10cSrcweir void DrawXmlFinalizer::visit( HyperlinkElement&, const std::list< Element* >::const_iterator& )
854cdf0e10cSrcweir {
855cdf0e10cSrcweir }
856cdf0e10cSrcweir
visit(TextElement & elem,const std::list<Element * >::const_iterator &)857cdf0e10cSrcweir void DrawXmlFinalizer::visit( TextElement& elem, const std::list< Element* >::const_iterator& )
858cdf0e10cSrcweir {
859cdf0e10cSrcweir const FontAttributes& rFont = m_rProcessor.getFont( elem.FontId );
860cdf0e10cSrcweir PropertyMap aProps;
861cdf0e10cSrcweir aProps[ USTR( "style:family" ) ] = USTR( "text" );
862cdf0e10cSrcweir
863cdf0e10cSrcweir PropertyMap aFontProps;
864cdf0e10cSrcweir
865cdf0e10cSrcweir // family name
866cdf0e10cSrcweir aFontProps[ USTR( "fo:font-family" ) ] = rFont.familyName;
867cdf0e10cSrcweir aFontProps[ USTR( "style:font-family-complex" ) ] = rFont.familyName;
868cdf0e10cSrcweir
869cdf0e10cSrcweir // bold
870cdf0e10cSrcweir if( rFont.isBold )
871cdf0e10cSrcweir {
872cdf0e10cSrcweir aFontProps[ USTR( "fo:font-weight" ) ] = USTR( "bold" );
873cdf0e10cSrcweir aFontProps[ USTR( "fo:font-weight-asian" ) ] = USTR( "bold" );
874cdf0e10cSrcweir aFontProps[ USTR( "style:font-weight-complex" ) ] = USTR( "bold" );
875cdf0e10cSrcweir }
876cdf0e10cSrcweir // italic
877cdf0e10cSrcweir if( rFont.isItalic )
878cdf0e10cSrcweir {
879cdf0e10cSrcweir aFontProps[ USTR( "fo:font-style" ) ] = USTR( "italic" );
880cdf0e10cSrcweir aFontProps[ USTR( "fo:font-style-asian" ) ] = USTR( "italic" );
881cdf0e10cSrcweir aFontProps[ USTR( "style:font-style-complex" ) ] = USTR( "italic" );
882cdf0e10cSrcweir }
883cdf0e10cSrcweir // underline
884cdf0e10cSrcweir if( rFont.isUnderline )
885cdf0e10cSrcweir {
886cdf0e10cSrcweir aFontProps[ USTR( "style:text-underline-style" ) ] = USTR( "solid" );
887cdf0e10cSrcweir aFontProps[ USTR( "style:text-underline-width" ) ] = USTR( "auto" );
888cdf0e10cSrcweir aFontProps[ USTR( "style:text-underline-color" ) ] = USTR( "font-color" );
889cdf0e10cSrcweir }
890cdf0e10cSrcweir // outline
891cdf0e10cSrcweir if( rFont.isOutline )
892cdf0e10cSrcweir {
893cdf0e10cSrcweir aFontProps[ USTR( "style:text-outline" ) ] = USTR( "true" );
894cdf0e10cSrcweir }
895cdf0e10cSrcweir // size
896cdf0e10cSrcweir rtl::OUStringBuffer aBuf( 32 );
897cdf0e10cSrcweir aBuf.append( rFont.size*72/PDFI_OUTDEV_RESOLUTION );
898cdf0e10cSrcweir aBuf.appendAscii( "pt" );
899cdf0e10cSrcweir rtl::OUString aFSize = aBuf.makeStringAndClear();
900cdf0e10cSrcweir aFontProps[ USTR( "fo:font-size" ) ] = aFSize;
901cdf0e10cSrcweir aFontProps[ USTR( "style:font-size-asian" ) ] = aFSize;
902cdf0e10cSrcweir aFontProps[ USTR( "style:font-size-complex" ) ] = aFSize;
903cdf0e10cSrcweir // color
904cdf0e10cSrcweir const GraphicsContext& rGC = m_rProcessor.getGraphicsContext( elem.GCId );
905cdf0e10cSrcweir aFontProps[ USTR( "fo:color" ) ] = getColorString( rFont.isOutline ? rGC.LineColor : rGC.FillColor );
906cdf0e10cSrcweir
907cdf0e10cSrcweir StyleContainer::Style aStyle( "style:style", aProps );
908cdf0e10cSrcweir StyleContainer::Style aSubStyle( "style:text-properties", aFontProps );
909cdf0e10cSrcweir aStyle.SubStyles.push_back( &aSubStyle );
910cdf0e10cSrcweir elem.StyleId = m_rStyleContainer.getStyleId( aStyle );
911cdf0e10cSrcweir }
912cdf0e10cSrcweir
visit(ParagraphElement & elem,const std::list<Element * >::const_iterator &)913cdf0e10cSrcweir void DrawXmlFinalizer::visit( ParagraphElement& elem, const std::list< Element* >::const_iterator& )
914cdf0e10cSrcweir {
915cdf0e10cSrcweir
916cdf0e10cSrcweir PropertyMap aProps;
917cdf0e10cSrcweir aProps[ USTR( "style:family" ) ] = USTR( "paragraph" );
918cdf0e10cSrcweir // generate standard paragraph style if necessary
919cdf0e10cSrcweir m_rStyleContainer.getStandardStyleId( "paragraph" );
920cdf0e10cSrcweir
921cdf0e10cSrcweir PropertyMap aParProps;
922cdf0e10cSrcweir
923cdf0e10cSrcweir aParProps[ USTR("fo:text-align")] = USTR("start");
924cdf0e10cSrcweir if (elem.bRtl)
925cdf0e10cSrcweir aParProps[ USTR("style:writing-mode")] = USTR("rl-tb");
926cdf0e10cSrcweir else
927cdf0e10cSrcweir aParProps[ USTR("style:writing-mode")] = USTR("lr-tb");
928cdf0e10cSrcweir
929cdf0e10cSrcweir StyleContainer::Style aStyle( "style:style", aProps );
930cdf0e10cSrcweir StyleContainer::Style aSubStyle( "style:paragraph-properties", aParProps );
931cdf0e10cSrcweir aStyle.SubStyles.push_back( &aSubStyle );
932cdf0e10cSrcweir
933cdf0e10cSrcweir elem.StyleId = m_rStyleContainer.getStyleId( aStyle );
934cdf0e10cSrcweir
935cdf0e10cSrcweir // update page boundaries
936cdf0e10cSrcweir if( elem.Parent )
937cdf0e10cSrcweir {
938cdf0e10cSrcweir // check for center alignement
939cdf0e10cSrcweir // criterion: paragraph is small relative to parent and distributed around its center
940cdf0e10cSrcweir double p_x = elem.Parent->x;
941cdf0e10cSrcweir double p_y = elem.Parent->y;
942cdf0e10cSrcweir double p_w = elem.Parent->w;
943cdf0e10cSrcweir double p_h = elem.Parent->h;
944cdf0e10cSrcweir
945cdf0e10cSrcweir PageElement* pPage = dynamic_cast<PageElement*>(elem.Parent);
946cdf0e10cSrcweir if( pPage )
947cdf0e10cSrcweir {
948cdf0e10cSrcweir p_x += pPage->LeftMargin;
949cdf0e10cSrcweir p_y += pPage->TopMargin;
950cdf0e10cSrcweir p_w -= pPage->LeftMargin+pPage->RightMargin;
951cdf0e10cSrcweir p_h -= pPage->TopMargin+pPage->BottomMargin;
952cdf0e10cSrcweir }
953cdf0e10cSrcweir }
954cdf0e10cSrcweir
955cdf0e10cSrcweir elem.applyToChildren(*this);
956cdf0e10cSrcweir }
957cdf0e10cSrcweir
visit(FrameElement & elem,const std::list<Element * >::const_iterator &)958cdf0e10cSrcweir void DrawXmlFinalizer::visit( FrameElement& elem, const std::list< Element* >::const_iterator&)
959cdf0e10cSrcweir {
960cdf0e10cSrcweir PropertyMap aProps;
961cdf0e10cSrcweir aProps[ USTR( "style:family" ) ] = USTR( "graphic" );
962cdf0e10cSrcweir aProps[ USTR( "style:parent-style-name") ] = USTR( "standard" );
963cdf0e10cSrcweir // generate standard graphic style if necessary
964cdf0e10cSrcweir m_rStyleContainer.getStandardStyleId( "graphic" );
965cdf0e10cSrcweir
966cdf0e10cSrcweir PropertyMap aGCProps;
967cdf0e10cSrcweir
968cdf0e10cSrcweir aGCProps[ USTR("draw:stroke") ] = USTR("none");
969cdf0e10cSrcweir aGCProps[ USTR("draw:fill") ] = USTR("none");
970cdf0e10cSrcweir aGCProps[ USTR("draw:auto-grow-height") ] = USTR("true");
971cdf0e10cSrcweir aGCProps[ USTR("draw:auto-grow-width") ] = USTR("true");
972cdf0e10cSrcweir aGCProps[ USTR("draw:textarea-horizontal-align") ] = USTR("left");
973cdf0e10cSrcweir aGCProps[ USTR("draw:textarea-vertical-align") ] = USTR("top");
974cdf0e10cSrcweir aGCProps[ USTR("fo:min-height")] = USTR("0cm");
975cdf0e10cSrcweir aGCProps[ USTR("fo:min-width")] = USTR("0cm");
976cdf0e10cSrcweir aGCProps[ USTR("fo:padding-top") ] = USTR("0cm");
977cdf0e10cSrcweir aGCProps[ USTR("fo:padding-left") ] = USTR("0cm");
978cdf0e10cSrcweir aGCProps[ USTR("fo:padding-right") ] = USTR("0cm");
979cdf0e10cSrcweir aGCProps[ USTR("fo:padding-bottom") ] = USTR("0cm");
980cdf0e10cSrcweir
981cdf0e10cSrcweir // remark: vertical mirroring is done in current OOO by
982cdf0e10cSrcweir // mirroring horzontally and rotating 180 degrees
983cdf0e10cSrcweir // this is quaint, but unfortunately it seems
984cdf0e10cSrcweir // mirror=vertical is defined but not implemented in current code
985cdf0e10cSrcweir if( elem.MirrorVertical )
986cdf0e10cSrcweir aGCProps[ USTR("style:mirror") ] = USTR("horizontal");
987cdf0e10cSrcweir
988cdf0e10cSrcweir StyleContainer::Style aStyle( "style:style", aProps );
989cdf0e10cSrcweir StyleContainer::Style aSubStyle( "style:graphic-properties", aGCProps );
990cdf0e10cSrcweir aStyle.SubStyles.push_back( &aSubStyle );
991cdf0e10cSrcweir
992cdf0e10cSrcweir elem.StyleId = m_rStyleContainer.getStyleId( aStyle );
993cdf0e10cSrcweir elem.applyToChildren(*this);
994cdf0e10cSrcweir }
995cdf0e10cSrcweir
visit(ImageElement &,const std::list<Element * >::const_iterator &)996cdf0e10cSrcweir void DrawXmlFinalizer::visit( ImageElement&, const std::list< Element* >::const_iterator& )
997cdf0e10cSrcweir {
998cdf0e10cSrcweir }
999cdf0e10cSrcweir
visit(PageElement & elem,const std::list<Element * >::const_iterator &)1000cdf0e10cSrcweir void DrawXmlFinalizer::visit( PageElement& elem, const std::list< Element* >::const_iterator& )
1001cdf0e10cSrcweir {
1002cdf0e10cSrcweir if( m_rProcessor.getStatusIndicator().is() )
1003cdf0e10cSrcweir m_rProcessor.getStatusIndicator()->setValue( elem.PageNumber );
1004cdf0e10cSrcweir
1005cdf0e10cSrcweir // transform from pixel to mm
1006cdf0e10cSrcweir double page_width = convPx2mm( elem.w ), page_height = convPx2mm( elem.h );
1007cdf0e10cSrcweir
1008cdf0e10cSrcweir // calculate page margins out of the relevant children (paragraphs)
1009cdf0e10cSrcweir elem.TopMargin = elem.h, elem.BottomMargin = 0, elem.LeftMargin = elem.w, elem.RightMargin = 0;
1010cdf0e10cSrcweir
1011cdf0e10cSrcweir for( std::list< Element* >::const_iterator it = elem.Children.begin(); it != elem.Children.end(); ++it )
1012cdf0e10cSrcweir {
1013cdf0e10cSrcweir if( (*it)->x < elem.LeftMargin )
1014cdf0e10cSrcweir elem.LeftMargin = (*it)->x;
1015cdf0e10cSrcweir if( (*it)->y < elem.TopMargin )
1016cdf0e10cSrcweir elem.TopMargin = (*it)->y;
1017cdf0e10cSrcweir if( (*it)->x + (*it)->w > elem.RightMargin )
1018cdf0e10cSrcweir elem.RightMargin = ((*it)->x + (*it)->w);
1019cdf0e10cSrcweir if( (*it)->y + (*it)->h > elem.BottomMargin )
1020cdf0e10cSrcweir elem.BottomMargin = ((*it)->y + (*it)->h);
1021cdf0e10cSrcweir }
1022cdf0e10cSrcweir
1023cdf0e10cSrcweir // transform margins to mm
1024cdf0e10cSrcweir double left_margin = convPx2mm( elem.LeftMargin );
1025cdf0e10cSrcweir double right_margin = convPx2mm( elem.RightMargin );
1026cdf0e10cSrcweir double top_margin = convPx2mm( elem.TopMargin );
1027cdf0e10cSrcweir double bottom_margin = convPx2mm( elem.BottomMargin );
1028cdf0e10cSrcweir
1029cdf0e10cSrcweir // round left/top margin to nearest mm
1030cdf0e10cSrcweir left_margin = rtl_math_round( left_margin, 0, rtl_math_RoundingMode_Floor );
1031cdf0e10cSrcweir top_margin = rtl_math_round( top_margin, 0, rtl_math_RoundingMode_Floor );
1032cdf0e10cSrcweir // round (fuzzy) right/bottom margin to nearest cm
1033cdf0e10cSrcweir right_margin = rtl_math_round( right_margin, right_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1034cdf0e10cSrcweir bottom_margin = rtl_math_round( bottom_margin, bottom_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1035cdf0e10cSrcweir
1036cdf0e10cSrcweir // set reasonable default in case of way too large margins
1037cdf0e10cSrcweir // e.g. no paragraph case
1038cdf0e10cSrcweir if( left_margin > page_width/2.0 - 10 )
1039cdf0e10cSrcweir left_margin = 10;
1040cdf0e10cSrcweir if( right_margin > page_width/2.0 - 10 )
1041cdf0e10cSrcweir right_margin = 10;
1042cdf0e10cSrcweir if( top_margin > page_height/2.0 - 10 )
1043cdf0e10cSrcweir top_margin = 10;
1044cdf0e10cSrcweir if( bottom_margin > page_height/2.0 - 10 )
1045cdf0e10cSrcweir bottom_margin = 10;
1046cdf0e10cSrcweir
1047cdf0e10cSrcweir // catch the weird cases
1048cdf0e10cSrcweir if( left_margin < 0 )
1049cdf0e10cSrcweir left_margin = 0;
1050cdf0e10cSrcweir if( right_margin < 0 )
1051cdf0e10cSrcweir right_margin = 0;
1052cdf0e10cSrcweir if( top_margin < 0 )
1053cdf0e10cSrcweir top_margin = 0;
1054cdf0e10cSrcweir if( bottom_margin < 0 )
1055cdf0e10cSrcweir bottom_margin = 0;
1056cdf0e10cSrcweir
1057cdf0e10cSrcweir // widely differing margins are unlikely to be correct
1058cdf0e10cSrcweir if( right_margin > left_margin*1.5 )
1059cdf0e10cSrcweir right_margin = left_margin;
1060cdf0e10cSrcweir
1061cdf0e10cSrcweir elem.LeftMargin = convmm2Px( left_margin );
1062cdf0e10cSrcweir elem.RightMargin = convmm2Px( right_margin );
1063cdf0e10cSrcweir elem.TopMargin = convmm2Px( top_margin );
1064cdf0e10cSrcweir elem.BottomMargin = convmm2Px( bottom_margin );
1065cdf0e10cSrcweir
1066cdf0e10cSrcweir // get styles for paragraphs
1067cdf0e10cSrcweir PropertyMap aPageProps;
1068cdf0e10cSrcweir PropertyMap aPageLayoutProps;
1069cdf0e10cSrcweir rtl::OUStringBuffer aBuf( 64 );
1070cdf0e10cSrcweir aPageLayoutProps[ USTR( "fo:margin-top" ) ] = unitMMString( top_margin );
1071cdf0e10cSrcweir aPageLayoutProps[ USTR( "fo:margin-bottom" ) ] = unitMMString( bottom_margin );
1072cdf0e10cSrcweir aPageLayoutProps[ USTR( "fo:margin-left" ) ] = unitMMString( left_margin );
1073cdf0e10cSrcweir aPageLayoutProps[ USTR( "fo:margin-right" ) ] = unitMMString( right_margin );
1074cdf0e10cSrcweir aPageLayoutProps[ USTR( "fo:page-width" ) ] = unitMMString( page_width );
1075cdf0e10cSrcweir aPageLayoutProps[ USTR( "fo:page-height" ) ] = unitMMString( page_height );
1076cdf0e10cSrcweir aPageLayoutProps[ USTR( "style:print-orientation" ) ]= elem.w < elem.h ? USTR( "portrait" ) : USTR( "landscape" );
1077cdf0e10cSrcweir aPageLayoutProps[ USTR( "style:writing-mode" ) ]= USTR( "lr-tb" );
1078cdf0e10cSrcweir
1079cdf0e10cSrcweir StyleContainer::Style aStyle( "style:page-layout", aPageProps);
1080cdf0e10cSrcweir StyleContainer::Style aSubStyle( "style:page-layout-properties", aPageLayoutProps);
1081cdf0e10cSrcweir aStyle.SubStyles.push_back(&aSubStyle);
1082cdf0e10cSrcweir sal_Int32 nPageStyle = m_rStyleContainer.impl_getStyleId( aStyle, false );
1083cdf0e10cSrcweir
1084cdf0e10cSrcweir // create master page
1085cdf0e10cSrcweir rtl::OUString aMasterPageLayoutName = m_rStyleContainer.getStyleName( nPageStyle );
1086cdf0e10cSrcweir aPageProps[ USTR( "style:page-layout-name" ) ] = aMasterPageLayoutName;
1087cdf0e10cSrcweir
1088cdf0e10cSrcweir StyleContainer::Style aMPStyle( "style:master-page", aPageProps);
1089cdf0e10cSrcweir
1090cdf0e10cSrcweir StyleContainer::Style aHeaderStyle( "style:header", PropertyMap() );
1091cdf0e10cSrcweir StyleContainer::Style aFooterStyle( "style:footer", PropertyMap() );
1092cdf0e10cSrcweir
1093cdf0e10cSrcweir elem.StyleId = m_rStyleContainer.impl_getStyleId( aMPStyle,false );
1094cdf0e10cSrcweir
1095cdf0e10cSrcweir
1096cdf0e10cSrcweir rtl::OUString aMasterPageName = m_rStyleContainer.getStyleName( elem.StyleId );
1097cdf0e10cSrcweir
1098cdf0e10cSrcweir // create styles for children
1099cdf0e10cSrcweir elem.applyToChildren(*this);
1100cdf0e10cSrcweir }
1101cdf0e10cSrcweir
visit(DocumentElement & elem,const std::list<Element * >::const_iterator &)1102cdf0e10cSrcweir void DrawXmlFinalizer::visit( DocumentElement& elem, const std::list< Element* >::const_iterator& )
1103cdf0e10cSrcweir {
1104cdf0e10cSrcweir elem.applyToChildren(*this);
1105cdf0e10cSrcweir }
1106cdf0e10cSrcweir
1107cdf0e10cSrcweir }
1108