xref: /AOO41X/main/sdext/source/pdfimport/tree/genericelements.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_sdext.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include "xmlemitter.hxx"
32*cdf0e10cSrcweir #include "genericelements.hxx"
33*cdf0e10cSrcweir #include "pdfiprocessor.hxx"
34*cdf0e10cSrcweir #include "pdfihelper.hxx"
35*cdf0e10cSrcweir #include "style.hxx"
36*cdf0e10cSrcweir 
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
39*cdf0e10cSrcweir #include <basegfx/range/b2drange.hxx>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir namespace pdfi
42*cdf0e10cSrcweir {
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir ElementFactory::~ElementFactory()
45*cdf0e10cSrcweir {
46*cdf0e10cSrcweir }
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir Element::~Element()
49*cdf0e10cSrcweir {
50*cdf0e10cSrcweir     while( !Children.empty() )
51*cdf0e10cSrcweir     {
52*cdf0e10cSrcweir         Element* pCurr( Children.front() );
53*cdf0e10cSrcweir         delete pCurr;
54*cdf0e10cSrcweir         Children.pop_front();
55*cdf0e10cSrcweir     }
56*cdf0e10cSrcweir }
57*cdf0e10cSrcweir 
58*cdf0e10cSrcweir void Element::applyToChildren( ElementTreeVisitor& rVisitor )
59*cdf0e10cSrcweir {
60*cdf0e10cSrcweir     for( std::list< Element* >::iterator it = Children.begin(); it != Children.end(); ++it )
61*cdf0e10cSrcweir         (*it)->visitedBy( rVisitor, it );
62*cdf0e10cSrcweir }
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir void Element::setParent( std::list<Element*>::iterator& el, Element* pNewParent )
65*cdf0e10cSrcweir {
66*cdf0e10cSrcweir     if( pNewParent )
67*cdf0e10cSrcweir     {
68*cdf0e10cSrcweir         pNewParent->Children.splice( pNewParent->Children.end(), (*el)->Parent->Children, el );
69*cdf0e10cSrcweir         (*el)->Parent = pNewParent;
70*cdf0e10cSrcweir     }
71*cdf0e10cSrcweir }
72*cdf0e10cSrcweir 
73*cdf0e10cSrcweir void Element::updateGeometryWith( const Element* pMergeFrom )
74*cdf0e10cSrcweir {
75*cdf0e10cSrcweir     if( w == 0 && h == 0 )
76*cdf0e10cSrcweir     {
77*cdf0e10cSrcweir         x = pMergeFrom->x;
78*cdf0e10cSrcweir         y = pMergeFrom->y;
79*cdf0e10cSrcweir         w = pMergeFrom->w;
80*cdf0e10cSrcweir         h = pMergeFrom->h;
81*cdf0e10cSrcweir     }
82*cdf0e10cSrcweir     else
83*cdf0e10cSrcweir     {
84*cdf0e10cSrcweir         if( pMergeFrom->x < x )
85*cdf0e10cSrcweir         {
86*cdf0e10cSrcweir             w += x - pMergeFrom->x;
87*cdf0e10cSrcweir             x = pMergeFrom->x;
88*cdf0e10cSrcweir         }
89*cdf0e10cSrcweir         if( pMergeFrom->x+pMergeFrom->w > x+w )
90*cdf0e10cSrcweir             w = pMergeFrom->w+pMergeFrom->x - x;
91*cdf0e10cSrcweir         if( pMergeFrom->y < y )
92*cdf0e10cSrcweir         {
93*cdf0e10cSrcweir             h += y - pMergeFrom->y;
94*cdf0e10cSrcweir             y = pMergeFrom->y;
95*cdf0e10cSrcweir         }
96*cdf0e10cSrcweir         if( pMergeFrom->y+pMergeFrom->h > y+h )
97*cdf0e10cSrcweir             h = pMergeFrom->h+pMergeFrom->y - y;
98*cdf0e10cSrcweir     }
99*cdf0e10cSrcweir }
100*cdf0e10cSrcweir 
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
103*cdf0e10cSrcweir #include <typeinfo>
104*cdf0e10cSrcweir void Element::emitStructure( int nLevel)
105*cdf0e10cSrcweir {
106*cdf0e10cSrcweir     OSL_TRACE( "%*s<%s %p> (%.1f,%.1f)+(%.1fx%.1f)\n",
107*cdf0e10cSrcweir                nLevel, "", typeid( *this ).name(), this,
108*cdf0e10cSrcweir                x, y, w, h );
109*cdf0e10cSrcweir     for( std::list< Element* >::iterator it = Children.begin(); it != Children.end(); ++it )
110*cdf0e10cSrcweir         (*it)->emitStructure(nLevel+1 );
111*cdf0e10cSrcweir     OSL_TRACE( "%*s</%s>\n", nLevel, "", typeid( *this ).name() );
112*cdf0e10cSrcweir }
113*cdf0e10cSrcweir #endif
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir void ListElement::visitedBy( ElementTreeVisitor& visitor, const std::list< Element* >::const_iterator& )
116*cdf0e10cSrcweir {
117*cdf0e10cSrcweir     // this is only an inner node
118*cdf0e10cSrcweir     applyToChildren(visitor);
119*cdf0e10cSrcweir }
120*cdf0e10cSrcweir 
121*cdf0e10cSrcweir void HyperlinkElement::visitedBy( ElementTreeVisitor&                          rVisitor,
122*cdf0e10cSrcweir                                   const std::list< Element* >::const_iterator& rParentIt )
123*cdf0e10cSrcweir {
124*cdf0e10cSrcweir     rVisitor.visit(*this,rParentIt);
125*cdf0e10cSrcweir }
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir void TextElement::visitedBy( ElementTreeVisitor&                          rVisitor,
128*cdf0e10cSrcweir                              const std::list< Element* >::const_iterator& rParentIt )
129*cdf0e10cSrcweir {
130*cdf0e10cSrcweir     rVisitor.visit(*this,rParentIt);
131*cdf0e10cSrcweir }
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir void FrameElement::visitedBy( ElementTreeVisitor&                          rVisitor,
134*cdf0e10cSrcweir                               const std::list< Element* >::const_iterator& rParentIt )
135*cdf0e10cSrcweir {
136*cdf0e10cSrcweir     rVisitor.visit(*this,rParentIt);
137*cdf0e10cSrcweir }
138*cdf0e10cSrcweir 
139*cdf0e10cSrcweir void ImageElement::visitedBy( ElementTreeVisitor&                          rVisitor,
140*cdf0e10cSrcweir                               const std::list< Element* >::const_iterator& rParentIt)
141*cdf0e10cSrcweir {
142*cdf0e10cSrcweir     rVisitor.visit( *this, rParentIt);
143*cdf0e10cSrcweir }
144*cdf0e10cSrcweir 
145*cdf0e10cSrcweir PolyPolyElement::PolyPolyElement( Element*                       pParent,
146*cdf0e10cSrcweir                                   sal_Int32                      nGCId,
147*cdf0e10cSrcweir                                   const basegfx::B2DPolyPolygon& rPolyPoly,
148*cdf0e10cSrcweir                                   sal_Int8                       nAction )
149*cdf0e10cSrcweir     : DrawElement( pParent, nGCId ),
150*cdf0e10cSrcweir       PolyPoly( rPolyPoly ),
151*cdf0e10cSrcweir       Action( nAction )
152*cdf0e10cSrcweir {
153*cdf0e10cSrcweir }
154*cdf0e10cSrcweir 
155*cdf0e10cSrcweir void PolyPolyElement::updateGeometry()
156*cdf0e10cSrcweir {
157*cdf0e10cSrcweir     basegfx::B2DRange aRange;
158*cdf0e10cSrcweir     if( PolyPoly.areControlPointsUsed() )
159*cdf0e10cSrcweir         aRange = basegfx::tools::getRange( basegfx::tools::adaptiveSubdivideByAngle( PolyPoly ) );
160*cdf0e10cSrcweir     else
161*cdf0e10cSrcweir         aRange = basegfx::tools::getRange( PolyPoly );
162*cdf0e10cSrcweir     x = aRange.getMinX();
163*cdf0e10cSrcweir     y = aRange.getMinY();
164*cdf0e10cSrcweir     w = aRange.getWidth();
165*cdf0e10cSrcweir     h = aRange.getHeight();
166*cdf0e10cSrcweir }
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir void PolyPolyElement::visitedBy( ElementTreeVisitor&                          rVisitor,
169*cdf0e10cSrcweir                                  const std::list< Element* >::const_iterator& rParentIt)
170*cdf0e10cSrcweir {
171*cdf0e10cSrcweir     rVisitor.visit( *this, rParentIt);
172*cdf0e10cSrcweir }
173*cdf0e10cSrcweir 
174*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
175*cdf0e10cSrcweir void PolyPolyElement::emitStructure( int nLevel)
176*cdf0e10cSrcweir {
177*cdf0e10cSrcweir     OSL_TRACE( "%*s<%s %p>\n", nLevel, "", typeid( *this ).name(), this  );
178*cdf0e10cSrcweir     OSL_TRACE( "path=" );
179*cdf0e10cSrcweir     int nPoly = PolyPoly.count();
180*cdf0e10cSrcweir     for( int i = 0; i < nPoly; i++ )
181*cdf0e10cSrcweir     {
182*cdf0e10cSrcweir         basegfx::B2DPolygon aPoly = PolyPoly.getB2DPolygon( i );
183*cdf0e10cSrcweir         int nPoints = aPoly.count();
184*cdf0e10cSrcweir         for( int n = 0; n < nPoints; n++ )
185*cdf0e10cSrcweir         {
186*cdf0e10cSrcweir             basegfx::B2DPoint aPoint = aPoly.getB2DPoint( n );
187*cdf0e10cSrcweir             OSL_TRACE( " (%g,%g)", aPoint.getX(), aPoint.getY() );
188*cdf0e10cSrcweir         }
189*cdf0e10cSrcweir         OSL_TRACE( "\n" );
190*cdf0e10cSrcweir     }
191*cdf0e10cSrcweir     for( std::list< Element* >::iterator it = Children.begin(); it != Children.end(); ++it )
192*cdf0e10cSrcweir         (*it)->emitStructure( nLevel+1 );
193*cdf0e10cSrcweir     OSL_TRACE( "%*s</%s>\n", nLevel, "", typeid( *this ).name() );
194*cdf0e10cSrcweir }
195*cdf0e10cSrcweir #endif
196*cdf0e10cSrcweir 
197*cdf0e10cSrcweir void ParagraphElement::visitedBy( ElementTreeVisitor&                          rVisitor,
198*cdf0e10cSrcweir                                   const std::list< Element* >::const_iterator& rParentIt )
199*cdf0e10cSrcweir {
200*cdf0e10cSrcweir     rVisitor.visit(*this,rParentIt);
201*cdf0e10cSrcweir }
202*cdf0e10cSrcweir 
203*cdf0e10cSrcweir bool ParagraphElement::isSingleLined( PDFIProcessor& rProc ) const
204*cdf0e10cSrcweir {
205*cdf0e10cSrcweir     std::list< Element* >::const_iterator it = Children.begin();
206*cdf0e10cSrcweir     TextElement* pText = NULL, *pLastText = NULL;
207*cdf0e10cSrcweir     while( it != Children.end() )
208*cdf0e10cSrcweir     {
209*cdf0e10cSrcweir         // a paragraph containing subparagraphs cannot be single lined
210*cdf0e10cSrcweir         if( dynamic_cast< ParagraphElement* >(*it) != NULL )
211*cdf0e10cSrcweir             return false;
212*cdf0e10cSrcweir 
213*cdf0e10cSrcweir         pText = dynamic_cast< TextElement* >(*it);
214*cdf0e10cSrcweir         if( pText )
215*cdf0e10cSrcweir         {
216*cdf0e10cSrcweir             const FontAttributes& rFont = rProc.getFont( pText->FontId );
217*cdf0e10cSrcweir             if( pText->h > rFont.size*1.5 )
218*cdf0e10cSrcweir                 return  false;
219*cdf0e10cSrcweir             if( pLastText )
220*cdf0e10cSrcweir             {
221*cdf0e10cSrcweir                 if( pText->y > pLastText->y+pLastText->h ||
222*cdf0e10cSrcweir                     pLastText->y > pText->y+pText->h )
223*cdf0e10cSrcweir                     return false;
224*cdf0e10cSrcweir             }
225*cdf0e10cSrcweir             else
226*cdf0e10cSrcweir                 pLastText = pText;
227*cdf0e10cSrcweir         }
228*cdf0e10cSrcweir         ++it;
229*cdf0e10cSrcweir     }
230*cdf0e10cSrcweir 
231*cdf0e10cSrcweir     // a paragraph without a single text is not considered single lined
232*cdf0e10cSrcweir     return pLastText != NULL;
233*cdf0e10cSrcweir }
234*cdf0e10cSrcweir 
235*cdf0e10cSrcweir double ParagraphElement::getLineHeight( PDFIProcessor& rProc ) const
236*cdf0e10cSrcweir {
237*cdf0e10cSrcweir     double line_h = 0;
238*cdf0e10cSrcweir     for( std::list< Element* >::const_iterator it = Children.begin(); it != Children.end(); ++it )
239*cdf0e10cSrcweir     {
240*cdf0e10cSrcweir         ParagraphElement* pPara = dynamic_cast< ParagraphElement* >(*it);
241*cdf0e10cSrcweir         TextElement* pText = NULL;
242*cdf0e10cSrcweir         if( pPara )
243*cdf0e10cSrcweir         {
244*cdf0e10cSrcweir             double lh = pPara->getLineHeight( rProc );
245*cdf0e10cSrcweir             if( lh > line_h )
246*cdf0e10cSrcweir                 line_h = lh;
247*cdf0e10cSrcweir         }
248*cdf0e10cSrcweir         else if( (pText = dynamic_cast< TextElement* >( *it )) != NULL )
249*cdf0e10cSrcweir         {
250*cdf0e10cSrcweir             const FontAttributes& rFont = rProc.getFont( pText->FontId );
251*cdf0e10cSrcweir             double lh = pText->h;
252*cdf0e10cSrcweir             if( pText->h > rFont.size*1.5 )
253*cdf0e10cSrcweir                 lh = rFont.size;
254*cdf0e10cSrcweir             if( lh > line_h )
255*cdf0e10cSrcweir                 line_h = lh;
256*cdf0e10cSrcweir         }
257*cdf0e10cSrcweir     }
258*cdf0e10cSrcweir     return line_h;
259*cdf0e10cSrcweir }
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir TextElement* ParagraphElement::getFirstTextChild() const
262*cdf0e10cSrcweir {
263*cdf0e10cSrcweir     TextElement* pText = NULL;
264*cdf0e10cSrcweir     for( std::list< Element* >::const_iterator it = Children.begin();
265*cdf0e10cSrcweir          it != Children.end() && ! pText; ++it )
266*cdf0e10cSrcweir     {
267*cdf0e10cSrcweir         pText = dynamic_cast<TextElement*>(*it);
268*cdf0e10cSrcweir     }
269*cdf0e10cSrcweir     return pText;
270*cdf0e10cSrcweir }
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir PageElement::~PageElement()
273*cdf0e10cSrcweir {
274*cdf0e10cSrcweir     if( HeaderElement )
275*cdf0e10cSrcweir         delete HeaderElement;
276*cdf0e10cSrcweir     if( FooterElement )
277*cdf0e10cSrcweir         delete FooterElement;
278*cdf0e10cSrcweir }
279*cdf0e10cSrcweir 
280*cdf0e10cSrcweir void PageElement::visitedBy( ElementTreeVisitor&                          rVisitor,
281*cdf0e10cSrcweir                              const std::list< Element* >::const_iterator& rParentIt )
282*cdf0e10cSrcweir {
283*cdf0e10cSrcweir      rVisitor.visit(*this, rParentIt);
284*cdf0e10cSrcweir }
285*cdf0e10cSrcweir 
286*cdf0e10cSrcweir void PageElement::updateParagraphGeometry( Element* pEle )
287*cdf0e10cSrcweir {
288*cdf0e10cSrcweir     // update geometry of children
289*cdf0e10cSrcweir     for( std::list< Element* >::iterator it = pEle->Children.begin();
290*cdf0e10cSrcweir          it != pEle->Children.end(); ++it )
291*cdf0e10cSrcweir     {
292*cdf0e10cSrcweir         updateParagraphGeometry( *it );
293*cdf0e10cSrcweir     }
294*cdf0e10cSrcweir     // if this is a paragraph itself, then update according to children geometry
295*cdf0e10cSrcweir     if( dynamic_cast<ParagraphElement*>(pEle) )
296*cdf0e10cSrcweir     {
297*cdf0e10cSrcweir         for( std::list< Element* >::iterator it = pEle->Children.begin();
298*cdf0e10cSrcweir              it != pEle->Children.end(); ++it )
299*cdf0e10cSrcweir         {
300*cdf0e10cSrcweir             Element* pChild = NULL;
301*cdf0e10cSrcweir             TextElement* pText = dynamic_cast<TextElement*>(*it);
302*cdf0e10cSrcweir             if( pText )
303*cdf0e10cSrcweir                 pChild = pText;
304*cdf0e10cSrcweir             else
305*cdf0e10cSrcweir             {
306*cdf0e10cSrcweir                 ParagraphElement* pPara = dynamic_cast<ParagraphElement*>(*it);
307*cdf0e10cSrcweir                 if( pPara )
308*cdf0e10cSrcweir                     pChild = pPara;
309*cdf0e10cSrcweir             }
310*cdf0e10cSrcweir             if( pChild )
311*cdf0e10cSrcweir                 pEle->updateGeometryWith( pChild );
312*cdf0e10cSrcweir         }
313*cdf0e10cSrcweir     }
314*cdf0e10cSrcweir }
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir bool PageElement::resolveHyperlink( std::list<Element*>::iterator link_it, std::list<Element*>& rElements )
317*cdf0e10cSrcweir {
318*cdf0e10cSrcweir     HyperlinkElement* pLink = dynamic_cast<HyperlinkElement*>(*link_it);
319*cdf0e10cSrcweir     if( ! pLink ) // sanity check
320*cdf0e10cSrcweir         return false;
321*cdf0e10cSrcweir 
322*cdf0e10cSrcweir     for( std::list<Element*>::iterator it = rElements.begin(); it != rElements.end(); ++it )
323*cdf0e10cSrcweir     {
324*cdf0e10cSrcweir         if( (*it)->x >= pLink->x && (*it)->x + (*it)->w <= pLink->x + pLink->w &&
325*cdf0e10cSrcweir             (*it)->y >= pLink->y && (*it)->y + (*it)->h <= pLink->y + pLink->h )
326*cdf0e10cSrcweir         {
327*cdf0e10cSrcweir             TextElement* pText = dynamic_cast<TextElement*>(*it);
328*cdf0e10cSrcweir             if( pText )
329*cdf0e10cSrcweir             {
330*cdf0e10cSrcweir                 if( pLink->Children.empty() )
331*cdf0e10cSrcweir                 {
332*cdf0e10cSrcweir                     // insert the hyperlink before the frame
333*cdf0e10cSrcweir                     rElements.splice( it, Hyperlinks.Children, link_it );
334*cdf0e10cSrcweir                     pLink->Parent = (*it)->Parent;
335*cdf0e10cSrcweir                 }
336*cdf0e10cSrcweir                 // move text element into hyperlink
337*cdf0e10cSrcweir                 std::list<Element*>::iterator next = it;
338*cdf0e10cSrcweir                 ++next;
339*cdf0e10cSrcweir                 Element::setParent( it, pLink );
340*cdf0e10cSrcweir                 it = next;
341*cdf0e10cSrcweir                 --it;
342*cdf0e10cSrcweir                 continue;
343*cdf0e10cSrcweir             }
344*cdf0e10cSrcweir             // a link can contain multiple text elements or a single frame
345*cdf0e10cSrcweir             if( ! pLink->Children.empty() )
346*cdf0e10cSrcweir                 continue;
347*cdf0e10cSrcweir             if( dynamic_cast<ParagraphElement*>(*it)  )
348*cdf0e10cSrcweir             {
349*cdf0e10cSrcweir                 if( resolveHyperlink( link_it, (*it)->Children ) )
350*cdf0e10cSrcweir                     break;
351*cdf0e10cSrcweir                 continue;
352*cdf0e10cSrcweir             }
353*cdf0e10cSrcweir             FrameElement* pFrame = dynamic_cast<FrameElement*>(*it);
354*cdf0e10cSrcweir             if( pFrame )
355*cdf0e10cSrcweir             {
356*cdf0e10cSrcweir                 // insert the hyperlink before the frame
357*cdf0e10cSrcweir                 rElements.splice( it, Hyperlinks.Children, link_it );
358*cdf0e10cSrcweir                 pLink->Parent = (*it)->Parent;
359*cdf0e10cSrcweir                 // move frame into hyperlink
360*cdf0e10cSrcweir                 Element::setParent( it, pLink );
361*cdf0e10cSrcweir                 break;
362*cdf0e10cSrcweir             }
363*cdf0e10cSrcweir         }
364*cdf0e10cSrcweir     }
365*cdf0e10cSrcweir     return ! pLink->Children.empty();
366*cdf0e10cSrcweir }
367*cdf0e10cSrcweir 
368*cdf0e10cSrcweir void PageElement::resolveHyperlinks()
369*cdf0e10cSrcweir {
370*cdf0e10cSrcweir     while( ! Hyperlinks.Children.empty() )
371*cdf0e10cSrcweir     {
372*cdf0e10cSrcweir         if( ! resolveHyperlink( Hyperlinks.Children.begin(), Children ) )
373*cdf0e10cSrcweir         {
374*cdf0e10cSrcweir             delete Hyperlinks.Children.front();
375*cdf0e10cSrcweir             Hyperlinks.Children.pop_front();
376*cdf0e10cSrcweir         }
377*cdf0e10cSrcweir     }
378*cdf0e10cSrcweir }
379*cdf0e10cSrcweir 
380*cdf0e10cSrcweir void PageElement::resolveFontStyles( PDFIProcessor& rProc )
381*cdf0e10cSrcweir {
382*cdf0e10cSrcweir     resolveUnderlines(rProc);
383*cdf0e10cSrcweir }
384*cdf0e10cSrcweir 
385*cdf0e10cSrcweir void PageElement::resolveUnderlines( PDFIProcessor& rProc )
386*cdf0e10cSrcweir {
387*cdf0e10cSrcweir     // FIXME: currently the algorithm used is quadratic
388*cdf0e10cSrcweir     // this could be solved by some sorting beforehand
389*cdf0e10cSrcweir 
390*cdf0e10cSrcweir     std::list< Element* >::iterator poly_it = Children.begin();
391*cdf0e10cSrcweir     while( poly_it != Children.end() )
392*cdf0e10cSrcweir     {
393*cdf0e10cSrcweir         PolyPolyElement* pPoly = dynamic_cast< PolyPolyElement* >(*poly_it);
394*cdf0e10cSrcweir         if( ! pPoly || ! pPoly->Children.empty() )
395*cdf0e10cSrcweir         {
396*cdf0e10cSrcweir             ++poly_it;
397*cdf0e10cSrcweir             continue;
398*cdf0e10cSrcweir         }
399*cdf0e10cSrcweir         /* check for: no filling
400*cdf0e10cSrcweir         *             only two points (FIXME: handle small rectangles, too)
401*cdf0e10cSrcweir         *             y coordinates of points are equal
402*cdf0e10cSrcweir         */
403*cdf0e10cSrcweir         if( pPoly->Action != PATH_STROKE )
404*cdf0e10cSrcweir         {
405*cdf0e10cSrcweir             ++poly_it;
406*cdf0e10cSrcweir             continue;
407*cdf0e10cSrcweir         }
408*cdf0e10cSrcweir         if( pPoly->PolyPoly.count() != 1 )
409*cdf0e10cSrcweir         {
410*cdf0e10cSrcweir             ++poly_it;
411*cdf0e10cSrcweir             continue;
412*cdf0e10cSrcweir         }
413*cdf0e10cSrcweir 
414*cdf0e10cSrcweir         bool bRemovePoly = false;
415*cdf0e10cSrcweir         basegfx::B2DPolygon aPoly = pPoly->PolyPoly.getB2DPolygon(0);
416*cdf0e10cSrcweir         if( aPoly.count() != 2 ||
417*cdf0e10cSrcweir             aPoly.getB2DPoint(0).getY() != aPoly.getB2DPoint(1).getY() )
418*cdf0e10cSrcweir         {
419*cdf0e10cSrcweir             ++poly_it;
420*cdf0e10cSrcweir             continue;
421*cdf0e10cSrcweir         }
422*cdf0e10cSrcweir         double l_x = aPoly.getB2DPoint(0).getX();
423*cdf0e10cSrcweir         double r_x = aPoly.getB2DPoint(1).getX();
424*cdf0e10cSrcweir         double u_y;
425*cdf0e10cSrcweir         if( r_x < l_x )
426*cdf0e10cSrcweir         {
427*cdf0e10cSrcweir             u_y = r_x; r_x = l_x; l_x = u_y;
428*cdf0e10cSrcweir         }
429*cdf0e10cSrcweir         u_y = aPoly.getB2DPoint(0).getY();
430*cdf0e10cSrcweir         for( std::list< Element*>::iterator it = Children.begin();
431*cdf0e10cSrcweir              it != Children.end(); ++it )
432*cdf0e10cSrcweir         {
433*cdf0e10cSrcweir             Element* pEle = *it;
434*cdf0e10cSrcweir             if( pEle->y <= u_y && pEle->y + pEle->h*1.1 >= u_y )
435*cdf0e10cSrcweir             {
436*cdf0e10cSrcweir                 // first: is the element underlined completely ?
437*cdf0e10cSrcweir                 if( pEle->x + pEle->w*0.1 >= l_x &&
438*cdf0e10cSrcweir                     pEle->x + pEle->w*0.9 <= r_x )
439*cdf0e10cSrcweir                 {
440*cdf0e10cSrcweir                     TextElement* pText = dynamic_cast< TextElement* >(pEle);
441*cdf0e10cSrcweir                     if( pText )
442*cdf0e10cSrcweir                     {
443*cdf0e10cSrcweir                         const GraphicsContext& rTextGC = rProc.getGraphicsContext( pText->GCId );
444*cdf0e10cSrcweir                         if( ! rTextGC.isRotatedOrSkewed() )
445*cdf0e10cSrcweir                         {
446*cdf0e10cSrcweir                             bRemovePoly = true;
447*cdf0e10cSrcweir                             // retrieve ID for modified font
448*cdf0e10cSrcweir                             FontAttributes aAttr = rProc.getFont( pText->FontId );
449*cdf0e10cSrcweir                             aAttr.isUnderline = true;
450*cdf0e10cSrcweir                             pText->FontId = rProc.getFontId( aAttr );
451*cdf0e10cSrcweir                         }
452*cdf0e10cSrcweir                     }
453*cdf0e10cSrcweir                     else if( dynamic_cast< HyperlinkElement* >(pEle) )
454*cdf0e10cSrcweir                         bRemovePoly = true;
455*cdf0e10cSrcweir                 }
456*cdf0e10cSrcweir                 // second: hyperlinks may be larger than their underline
457*cdf0e10cSrcweir                 // since they are just arbitrary rectangles in the action definition
458*cdf0e10cSrcweir                 else if( dynamic_cast< HyperlinkElement* >(pEle) != NULL &&
459*cdf0e10cSrcweir                          l_x >= pEle->x && r_x <= pEle->x+pEle->w )
460*cdf0e10cSrcweir                 {
461*cdf0e10cSrcweir                     bRemovePoly = true;
462*cdf0e10cSrcweir                 }
463*cdf0e10cSrcweir             }
464*cdf0e10cSrcweir         }
465*cdf0e10cSrcweir         if( bRemovePoly )
466*cdf0e10cSrcweir         {
467*cdf0e10cSrcweir             std::list< Element* >::iterator next_it = poly_it;
468*cdf0e10cSrcweir             ++next_it;
469*cdf0e10cSrcweir             Children.erase( poly_it );
470*cdf0e10cSrcweir             delete pPoly;
471*cdf0e10cSrcweir             poly_it = next_it;
472*cdf0e10cSrcweir         }
473*cdf0e10cSrcweir         else
474*cdf0e10cSrcweir             ++poly_it;
475*cdf0e10cSrcweir     }
476*cdf0e10cSrcweir }
477*cdf0e10cSrcweir 
478*cdf0e10cSrcweir DocumentElement::~DocumentElement()
479*cdf0e10cSrcweir {
480*cdf0e10cSrcweir }
481*cdf0e10cSrcweir 
482*cdf0e10cSrcweir void DocumentElement::visitedBy( ElementTreeVisitor&                          rVisitor,
483*cdf0e10cSrcweir                                  const std::list< Element* >::const_iterator& rParentIt)
484*cdf0e10cSrcweir {
485*cdf0e10cSrcweir     rVisitor.visit(*this, rParentIt);
486*cdf0e10cSrcweir }
487*cdf0e10cSrcweir 
488*cdf0e10cSrcweir 
489*cdf0e10cSrcweir }
490