xref: /trunk/main/svx/source/svdraw/svdfmtf.cxx (revision e2f0c31b42bde6066c6021ce2619669c0060ee12)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include "svdfmtf.hxx"
28 #include <editeng/editdata.hxx>
29 #include <math.h>
30 #include <svx/xpoly.hxx>
31 #include <vcl/svapp.hxx>
32 #include <editeng/eeitem.hxx>
33 #include <editeng/fhgtitem.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <editeng/postitem.hxx>
36 #include <editeng/udlnitem.hxx>
37 #include <editeng/crsditem.hxx>
38 #include <editeng/shdditem.hxx>
39 #include <svx/xlnclit.hxx>
40 #include <svx/xlncapit.hxx>
41 #include <svx/xlnwtit.hxx>
42 #include <svx/xflclit.hxx>
43 #include <svx/xgrad.hxx>
44 #include <svx/xflgrit.hxx>
45 #include <editeng/fontitem.hxx>
46 #include <editeng/akrnitem.hxx>
47 #include <editeng/wrlmitem.hxx>
48 #include <editeng/cntritem.hxx>
49 #include <editeng/colritem.hxx>
50 #include <vcl/metric.hxx>
51 #include <editeng/charscaleitem.hxx>
52 #include <svx/xflhtit.hxx>
53 #include <svx/svdattr.hxx>
54 #include <svx/svdmodel.hxx>
55 #include <svx/svdpage.hxx>
56 #include <svx/svdobj.hxx>
57 #include "svx/svditext.hxx"
58 #include <svx/svdotext.hxx>
59 #include <svx/svdorect.hxx>
60 #include <svx/svdocirc.hxx>
61 #include <svx/svdograf.hxx>
62 #include <svx/svdopath.hxx>
63 #include <svx/svdetc.hxx>
64 #include <svl/itemset.hxx>
65 #include <basegfx/polygon/b2dpolygon.hxx>
66 #include <vcl/salbtype.hxx>     // FRound
67 #include <basegfx/matrix/b2dhommatrix.hxx>
68 #include <basegfx/matrix/b2dhommatrixtools.hxx>
69 #include <svx/xlinjoit.hxx>
70 #include <svx/xlndsit.hxx>
71 #include <basegfx/polygon/b2dpolygonclipper.hxx>
72 #include <svx/xbtmpit.hxx>
73 
74 ////////////////////////////////////////////////////////////////////////////////////////////////////
75 
76 ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel):
77     nMapScalingOfs(0),
78     pLineAttr(NULL),pFillAttr(NULL),pTextAttr(NULL),
79     pPage(NULL),pModel(NULL),nLayer(0),
80     nLineWidth(0),
81     maLineJoin(basegfx::B2DLINEJOIN_NONE),
82     maLineCap(com::sun::star::drawing::LineCap_BUTT),
83     maDash(XDASH_RECT, 0, 0, 0, 0, 0),
84     bFntDirty(sal_True),
85     bLastObjWasPolyWithoutLine(sal_False),
86     bNoLine(sal_False),
87     bNoFill(sal_False),
88     bLastObjWasLine(sal_False),
89     maClip()
90 {
91     aVD.EnableOutput(sal_False);
92 
93     // #i111954# init to no fill and no line initially
94     aVD.SetLineColor();
95     aVD.SetFillColor();
96 
97     aOldLineColor.SetRed( aVD.GetLineColor().GetRed() + 1 ); // invalidate old line color
98     pLineAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_LINE_FIRST,XATTR_LINE_LAST);
99     pFillAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST);
100     pTextAttr=new SfxItemSet(rModel.GetItemPool(),EE_ITEMS_START,EE_ITEMS_END);
101     pModel=&rModel;
102     checkClip();
103 }
104 
105 ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport()
106 {
107     delete pLineAttr;
108     delete pFillAttr;
109     delete pTextAttr;
110 }
111 
112 sal_uIntPtr ImpSdrGDIMetaFileImport::DoImport(const GDIMetaFile& rMtf,
113     SdrObjList& rOL,
114     sal_uIntPtr nInsPos,
115     SvdProgressInfo *pProgrInfo)
116 {
117     pPage = rOL.GetPage();
118     GDIMetaFile* pTmpMtf=NULL;
119     GDIMetaFile* pMtf = (GDIMetaFile*) &rMtf;
120     sal_uIntPtr nActionAnz=pMtf->GetActionCount();
121     sal_Bool bError = sal_False;
122 
123 
124     // setup some global scale parameter
125     // fScaleX, fScaleY, aScaleX, aScaleY, bMov, bSize
126     fScaleX = fScaleY = 1.0;
127     Size  aMtfSize( pMtf->GetPrefSize() );
128     if ( aMtfSize.Width() & aMtfSize.Height() && ( aScaleRect.IsEmpty() == sal_False ) )
129     {
130         aOfs = aScaleRect.TopLeft();
131         if ( aMtfSize.Width() != ( aScaleRect.GetWidth() - 1 ) )
132             fScaleX = (double)( aScaleRect.GetWidth() - 1 ) / (double)aMtfSize.Width();
133         if ( aMtfSize.Height() != ( aScaleRect.GetHeight() - 1 ) )
134             fScaleY = (double)( aScaleRect.GetHeight() - 1 ) / (double)aMtfSize.Height();
135     }
136 
137     bMov = aOfs.X()!=0 || aOfs.Y()!=0;
138     bSize = sal_False;
139 
140     aScaleX = Fraction( 1, 1 );
141     aScaleY = Fraction( 1, 1 );
142     if ( aMtfSize.Width() != ( aScaleRect.GetWidth() - 1 ) )
143     {
144         aScaleX = Fraction( aScaleRect.GetWidth() - 1, aMtfSize.Width() );
145         bSize = sal_True;
146     }
147     if ( aMtfSize.Height() != ( aScaleRect.GetHeight() - 1 ) )
148     {
149         aScaleY = Fraction( aScaleRect.GetHeight() - 1, aMtfSize.Height() );
150         bSize = sal_True;
151     }
152 
153     if(65000 < nActionAnz)
154     {
155         nActionAnz = 65000;
156         bError = sal_True;
157     }
158 
159     if(pProgrInfo)
160         pProgrInfo->SetActionCount(nActionAnz);
161 
162     sal_uIntPtr nActionsToReport = 0;
163 
164     for( MetaAction* pAct = pMtf->FirstAction(); pAct; pAct = pMtf->NextAction() )
165     {
166         switch (pAct->GetType())
167         {
168             case META_PIXEL_ACTION          : DoAction((MetaPixelAction          &)*pAct); break;
169             case META_POINT_ACTION          : DoAction((MetaPointAction          &)*pAct); break;
170             case META_LINE_ACTION           : DoAction((MetaLineAction           &)*pAct); break;
171             case META_RECT_ACTION           : DoAction((MetaRectAction           &)*pAct); break;
172             case META_ROUNDRECT_ACTION      : DoAction((MetaRoundRectAction      &)*pAct); break;
173             case META_ELLIPSE_ACTION        : DoAction((MetaEllipseAction        &)*pAct); break;
174             case META_ARC_ACTION            : DoAction((MetaArcAction            &)*pAct); break;
175             case META_PIE_ACTION            : DoAction((MetaPieAction            &)*pAct); break;
176             case META_CHORD_ACTION          : DoAction((MetaChordAction          &)*pAct); break;
177             case META_POLYLINE_ACTION       : DoAction((MetaPolyLineAction       &)*pAct); break;
178             case META_POLYGON_ACTION        : DoAction((MetaPolygonAction        &)*pAct); break;
179             case META_POLYPOLYGON_ACTION    : DoAction((MetaPolyPolygonAction    &)*pAct); break;
180             case META_TEXT_ACTION           : DoAction((MetaTextAction           &)*pAct); break;
181             case META_TEXTARRAY_ACTION      : DoAction((MetaTextArrayAction      &)*pAct); break;
182             case META_STRETCHTEXT_ACTION    : DoAction((MetaStretchTextAction    &)*pAct); break;
183             case META_BMP_ACTION            : DoAction((MetaBmpAction            &)*pAct); break;
184             case META_BMPSCALE_ACTION       : DoAction((MetaBmpScaleAction       &)*pAct); break;
185             case META_BMPEX_ACTION          : DoAction((MetaBmpExAction          &)*pAct); break;
186             case META_BMPEXSCALE_ACTION     : DoAction((MetaBmpExScaleAction     &)*pAct); break;
187             case META_LINECOLOR_ACTION      : DoAction((MetaLineColorAction      &)*pAct); break;
188             case META_FILLCOLOR_ACTION      : DoAction((MetaFillColorAction      &)*pAct); break;
189             case META_TEXTCOLOR_ACTION      : DoAction((MetaTextColorAction      &)*pAct); break;
190             case META_TEXTFILLCOLOR_ACTION  : DoAction((MetaTextFillColorAction  &)*pAct); break;
191             case META_FONT_ACTION           : DoAction((MetaFontAction           &)*pAct); break;
192             case META_TEXTALIGN_ACTION      : DoAction((MetaTextAlignAction      &)*pAct); break;
193             case META_MAPMODE_ACTION        : DoAction((MetaMapModeAction        &)*pAct); break;
194             case META_CLIPREGION_ACTION     : DoAction((MetaClipRegionAction     &)*pAct); break;
195             case META_MOVECLIPREGION_ACTION : DoAction((MetaMoveClipRegionAction &)*pAct); break;
196             case META_ISECTRECTCLIPREGION_ACTION: DoAction((MetaISectRectClipRegionAction&)*pAct); break;
197             case META_ISECTREGIONCLIPREGION_ACTION: DoAction((MetaISectRegionClipRegionAction&)*pAct); break;
198             case META_RASTEROP_ACTION       : DoAction((MetaRasterOpAction       &)*pAct); break;
199             case META_PUSH_ACTION           : DoAction((MetaPushAction           &)*pAct); break;
200             case META_POP_ACTION            : DoAction((MetaPopAction            &)*pAct); break;
201             case META_HATCH_ACTION          : DoAction((MetaHatchAction          &)*pAct); break;
202             case META_COMMENT_ACTION        : DoAction((MetaCommentAction        &)*pAct, pMtf); break;
203         }
204 
205         if(pProgrInfo != NULL)
206         {
207           nActionsToReport++;
208           if(nActionsToReport >= 16) // Alle 16 Action updaten
209           {
210             if(!pProgrInfo->ReportActions(nActionsToReport))
211               break;
212             nActionsToReport = 0;
213           }
214         }
215     }
216 
217     if(pProgrInfo != NULL)
218     {
219         pProgrInfo->ReportActions(nActionsToReport);
220         nActionsToReport = 0;
221     }
222 
223     // MapMode-Scaling  vornehmen
224     MapScaling();
225     // Objekte in vorgegebenes Rechteck hineinskalieren
226     sal_uIntPtr nAnz=aTmpList.GetObjCount();
227 
228     // Beim berechnen der Fortschrittsanzeige wird GetActionCount()*3 benutzt.
229     // Da in aTmpList allerdings weniger eintraege als GetActionCount()
230     // existieren koennen, muessen hier die zuviel vermuteten Actionen wieder
231     // hinzugefuegt werden.
232     nActionsToReport = (pMtf->GetActionCount() - nAnz)*2;
233 
234 
235     // Alle noch nicht gemeldeten Rescales melden
236     if(pProgrInfo)
237     {
238         pProgrInfo->ReportRescales(nActionsToReport);
239         pProgrInfo->SetInsertCount(nAnz);
240     }
241     nActionsToReport = 0;
242 
243     // alle in aTmpList zwischengespeicherten Objekte nun in rOL ab der Position nInsPos einfuegen
244     if (nInsPos>rOL.GetObjCount()) nInsPos=rOL.GetObjCount();
245     SdrInsertReason aReason(SDRREASON_VIEWCALL);
246     for (sal_uIntPtr i=0; i<nAnz; i++)
247     {
248          SdrObject* pObj=aTmpList.GetObj(i);
249          rOL.NbcInsertObject(pObj,nInsPos,&aReason);
250          nInsPos++;
251 
252         if(pProgrInfo != NULL)
253         {
254             nActionsToReport++;
255             if(nActionsToReport >= 32) // Alle 32 Action updaten
256             {
257                 pProgrInfo->ReportInserts(nActionsToReport);
258                 nActionsToReport = 0;
259             }
260         }
261     }
262     if (pTmpMtf!=NULL) delete pTmpMtf;
263 
264     // ein letztesmal alle verbliebennen Inserts reporten
265     if(pProgrInfo != NULL)
266     {
267         pProgrInfo->ReportInserts(nActionsToReport);
268         if(bError)
269             pProgrInfo->ReportError();
270     }
271 
272     return aTmpList.GetObjCount();
273 }
274 
275 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, FASTBOOL bForceTextAttr)
276 {
277     bNoLine = sal_False; bNoFill = sal_False;
278     FASTBOOL bLine=sal_True && !bForceTextAttr;
279     FASTBOOL bFill=pObj==NULL || ( pObj->IsClosedObj() && !bForceTextAttr );
280     FASTBOOL bText=bForceTextAttr || (pObj!=NULL && pObj->GetOutlinerParaObject()!=NULL);
281 
282     if ( bLine )
283     {
284         if ( nLineWidth )
285             pLineAttr->Put( XLineWidthItem( nLineWidth ) );
286         else
287             pLineAttr->Put( XLineWidthItem( 0 ) );
288 
289         aOldLineColor = aVD.GetLineColor();
290         if( aVD.IsLineColor() )
291         {
292             pLineAttr->Put(XLineStyleItem(XLINE_SOLID));
293             pLineAttr->Put(XLineColorItem(String(), aVD.GetLineColor()));
294         }
295         else
296             pLineAttr->Put(XLineStyleItem(XLINE_NONE));
297 
298         switch(maLineJoin)
299         {
300             default : // basegfx::B2DLINEJOIN_NONE
301                 pLineAttr->Put(XLineJointItem(XLINEJOINT_NONE));
302                 break;
303             case basegfx::B2DLINEJOIN_MIDDLE:
304                 pLineAttr->Put(XLineJointItem(XLINEJOINT_MIDDLE));
305                 break;
306             case basegfx::B2DLINEJOIN_BEVEL:
307                 pLineAttr->Put(XLineJointItem(XLINEJOINT_BEVEL));
308                 break;
309             case basegfx::B2DLINEJOIN_MITER:
310                 pLineAttr->Put(XLineJointItem(XLINEJOINT_MITER));
311                 break;
312             case basegfx::B2DLINEJOIN_ROUND:
313                 pLineAttr->Put(XLineJointItem(XLINEJOINT_ROUND));
314                 break;
315         }
316 
317         // Add LineCap support
318         pLineAttr->Put(XLineCapItem(maLineCap));
319 
320         if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance())
321         {
322             pLineAttr->Put(XLineDashItem(String(), maDash));
323         }
324         else
325         {
326             pLineAttr->Put(XLineDashItem(String(), XDash(XDASH_RECT)));
327         }
328     }
329     else
330         bNoLine = sal_True;
331 
332     if ( bFill )
333     {
334         if( aVD.IsFillColor() )
335         {
336             pFillAttr->Put(XFillStyleItem(XFILL_SOLID));
337             pFillAttr->Put(XFillColorItem(String(), aVD.GetFillColor()));
338         }
339         else
340             pFillAttr->Put(XFillStyleItem(XFILL_NONE));
341     }
342     else
343         bNoFill = sal_True;
344 
345     if ( bText && bFntDirty )
346     {
347         Font aFnt(aVD.GetFont());
348         pTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(),
349                             aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
350         pTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(),
351                             aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
352         pTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(),
353                             aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) );
354         pTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC));
355         pTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT));
356         sal_uInt32 nHeight = FRound(aFnt.GetSize().Height() * fScaleY);
357         pTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
358         pTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
359         pTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
360         pTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
361         pTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
362         pTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
363         pTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
364         pTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
365 
366         // #i118485# Setting this item leads to problems (written #i118498# for this)
367         // pTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
368 
369         pTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
370         pTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
371         pTextAttr->Put(SvxColorItem(aVD.GetTextColor(), EE_CHAR_COLOR));
372         //... svxfont textitem svditext
373         bFntDirty=sal_False;
374     }
375     if (pObj!=NULL)
376     {
377         pObj->SetLayer(nLayer);
378         if (bLine) pObj->SetMergedItemSet(*pLineAttr);
379         if (bFill) pObj->SetMergedItemSet(*pFillAttr);
380         if (bText)
381         {
382             pObj->SetMergedItemSet(*pTextAttr);
383             pObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_LEFT ) );
384         }
385     }
386 }
387 
388 void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj, sal_Bool bScale)
389 {
390     if ( bScale && !aScaleRect.IsEmpty() )
391     {
392         if ( bSize )
393             pObj->NbcResize( Point(), aScaleX, aScaleY );
394         if ( bMov )
395             pObj->NbcMove( Size( aOfs.X(), aOfs.Y() ) );
396     }
397 
398     if(isClip())
399     {
400         const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
401         const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
402         const SdrLayerID aOldLayer(pObj->GetLayer());
403         const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
404         const SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
405         BitmapEx aBitmapEx;
406 
407         if(pSdrGrafObj)
408         {
409             aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
410         }
411 
412         SdrObject::Free(pObj);
413 
414         if(!aOldRange.isEmpty())
415         {
416             // clip against ClipRegion
417             const basegfx::B2DPolyPolygon aNewPoly(
418                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
419                     aPoly,
420                     maClip,
421                     true,
422                     aPoly.isClosed() ? false : true));
423             const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
424 
425             if(!aNewRange.isEmpty())
426             {
427                 pObj = new SdrPathObj(
428                     aNewPoly.isClosed() ? OBJ_POLY : OBJ_PLIN,
429                     aNewPoly);
430 
431                 pObj->SetLayer(aOldLayer);
432                 pObj->SetMergedItemSet(aOldItemSet);
433 
434                 if(!!aBitmapEx)
435                 {
436                     // aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
437                     const double fScaleX(aBitmapEx.GetSizePixel().Width() / (aOldRange.getWidth() ? aOldRange.getWidth() : 1.0));
438                     const double fScaleY(aBitmapEx.GetSizePixel().Height() / (aOldRange.getHeight() ? aOldRange.getHeight() : 1.0));
439                     basegfx::B2DRange aPixel(aNewRange);
440                     basegfx::B2DHomMatrix aTrans;
441 
442                     aTrans.translate(-aOldRange.getMinX(), -aOldRange.getMinY());
443                     aTrans.scale(fScaleX, fScaleY);
444                     aPixel.transform(aTrans);
445 
446                     const BitmapEx aClippedBitmap(
447                         aBitmapEx,
448                         Point(floor(std::max(0.0, aPixel.getMinX())), floor(std::max(0.0, aPixel.getMinY()))),
449                         Size(ceil(aPixel.getWidth()), ceil(aPixel.getHeight())));
450 
451                     pObj->SetMergedItem(XFillStyleItem(XFILL_BITMAP));
452                     pObj->SetMergedItem(XFillBitmapItem(String(), aClippedBitmap.GetBitmap()));
453                 }
454             }
455         }
456     }
457 
458     if(pObj)
459     {
460         // #i111954# check object for visibility
461         // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
462         bool bVisible(false);
463 
464         if(pObj->HasLineStyle())
465         {
466             bVisible = true;
467         }
468 
469         if(!bVisible && pObj->HasFillStyle())
470         {
471             bVisible = true;
472         }
473 
474         if(!bVisible)
475         {
476             SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >(pObj);
477 
478             if(pTextObj && pTextObj->HasText())
479             {
480                 bVisible = true;
481             }
482         }
483 
484         if(!bVisible)
485         {
486             SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
487 
488             if(pGrafObj)
489             {
490                 // this may be refined to check if the graphic really is visible. It
491                 // is here to ensure that graphic objects without fill, line and text
492                 // get created
493                 bVisible = true;
494             }
495         }
496 
497         if(!bVisible)
498         {
499             SdrObject::Free(pObj);
500         }
501         else
502         {
503             aTmpList.InsertObject( pObj );
504             if ( HAS_BASE( SdrPathObj, pObj ) )
505             {
506                 FASTBOOL bClosed=pObj->IsClosedObj();
507                 bLastObjWasPolyWithoutLine=bNoLine && bClosed;
508                 bLastObjWasLine=!bClosed;
509             }
510             else
511             {
512                 bLastObjWasPolyWithoutLine = sal_False;
513                 bLastObjWasLine = sal_False;
514             }
515         }
516     }
517 }
518 
519 /**************************************************************************************************/
520 
521 void ImpSdrGDIMetaFileImport::DoAction(MetaPixelAction& /*rAct*/)
522 {
523 }
524 
525 void ImpSdrGDIMetaFileImport::DoAction(MetaPointAction& /*rAct*/)
526 {
527 }
528 
529 void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction& rAct)
530 {
531     // #i73407# reformulation to use new B2DPolygon classes
532     const basegfx::B2DPoint aStart(rAct.GetStartPoint().X(), rAct.GetStartPoint().Y());
533     const basegfx::B2DPoint aEnd(rAct.GetEndPoint().X(), rAct.GetEndPoint().Y());
534 
535     if(!aStart.equal(aEnd))
536     {
537         basegfx::B2DPolygon aLine;
538         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
539 
540         aLine.append(aStart);
541         aLine.append(aEnd);
542         aLine.transform(aTransform);
543 
544         const LineInfo& rLineInfo = rAct.GetLineInfo();
545         const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
546         bool bCreateLineObject(true);
547 
548         if(bLastObjWasLine && (nNewLineWidth == nLineWidth) && CheckLastLineMerge(aLine))
549         {
550             bCreateLineObject = false;
551         }
552 
553         if(bCreateLineObject)
554         {
555             SdrPathObj* pPath = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aLine));
556             nLineWidth = nNewLineWidth;
557             maLineJoin = rLineInfo.GetLineJoin();
558             maLineCap = rLineInfo.GetLineCap();
559             maDash = XDash(XDASH_RECT,
560                 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
561                 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
562                 rLineInfo.GetDistance());
563             SetAttributes(pPath);
564             nLineWidth = 0;
565             maLineJoin = basegfx::B2DLINEJOIN_NONE;
566             maDash = XDash();
567             InsertObj(pPath, false);
568         }
569     }
570 }
571 
572 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction& rAct)
573 {
574     SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
575     SetAttributes(pRect);
576     InsertObj(pRect);
577 }
578 
579 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction& rAct)
580 {
581     SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
582     SetAttributes(pRect);
583     long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
584     if (nRad!=0) {
585         SfxItemSet aSet(*pLineAttr->GetPool(),SDRATTR_ECKENRADIUS,SDRATTR_ECKENRADIUS);
586         aSet.Put(SdrEckenradiusItem(nRad));
587         pRect->SetMergedItemSet(aSet);
588     }
589     InsertObj(pRect);
590 }
591 
592 /**************************************************************************************************/
593 
594 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction& rAct)
595 {
596     SdrCircObj* pCirc=new SdrCircObj(OBJ_CIRC,rAct.GetRect());
597     SetAttributes(pCirc);
598     InsertObj(pCirc);
599 }
600 
601 void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction& rAct)
602 {
603     Point aCenter(rAct.GetRect().Center());
604     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
605     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
606     SdrCircObj* pCirc=new SdrCircObj(OBJ_CARC,rAct.GetRect(),nStart,nEnd);
607     SetAttributes(pCirc);
608     InsertObj(pCirc);
609 }
610 
611 void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction& rAct)
612 {
613     Point aCenter(rAct.GetRect().Center());
614     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
615     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
616     SdrCircObj* pCirc=new SdrCircObj(OBJ_SECT,rAct.GetRect(),nStart,nEnd);
617     SetAttributes(pCirc);
618     InsertObj(pCirc);
619 }
620 
621 void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction& rAct)
622 {
623     Point aCenter(rAct.GetRect().Center());
624     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
625     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
626     SdrCircObj* pCirc=new SdrCircObj(OBJ_CCUT,rAct.GetRect(),nStart,nEnd);
627     SetAttributes(pCirc);
628     InsertObj(pCirc);
629 }
630 
631 /**************************************************************************************************/
632 
633 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
634 {
635     // #i102706# Do not merge closed polygons
636     if(rSrcPoly.isClosed())
637     {
638         return false;
639     }
640 
641     // #i73407# reformulation to use new B2DPolygon classes
642     if(bLastObjWasLine && (aOldLineColor == aVD.GetLineColor()) && rSrcPoly.count())
643     {
644         SdrObject* pTmpObj = aTmpList.GetObj(aTmpList.GetObjCount() - 1);
645         SdrPathObj* pLastPoly = PTR_CAST(SdrPathObj, pTmpObj);
646 
647         if(pLastPoly)
648         {
649             if(1L == pLastPoly->GetPathPoly().count())
650             {
651                 bool bOk(false);
652                 basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0L));
653 
654                 // #i102706# Do not merge closed polygons
655                 if(aDstPoly.isClosed())
656                 {
657                     return false;
658                 }
659 
660                 if(aDstPoly.count())
661                 {
662                     const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1L);
663                     const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1L);
664 
665                     if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0L))
666                     {
667                         aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
668                         bOk = true;
669                     }
670                     else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
671                     {
672                         basegfx::B2DPolygon aNew(rSrcPoly);
673                         aNew.append(aDstPoly, 1L, aDstPoly.count() - 1L);
674                         aDstPoly = aNew;
675                         bOk = true;
676                     }
677                     else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(0L))
678                     {
679                         aDstPoly.flip();
680                         aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
681                         bOk = true;
682                     }
683                     else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
684                     {
685                         basegfx::B2DPolygon aNew(rSrcPoly);
686                         aNew.flip();
687                         aDstPoly.append(aNew, 1L, aNew.count() - 1L);
688                         bOk = true;
689                     }
690                 }
691 
692                 if(bOk)
693                 {
694                     pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
695                 }
696 
697                 return bOk;
698             }
699         }
700     }
701 
702     return false;
703 }
704 
705 bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
706 {
707     // #i73407# reformulation to use new B2DPolygon classes
708     if(bLastObjWasPolyWithoutLine)
709     {
710         SdrObject* pTmpObj = aTmpList.GetObj(aTmpList.GetObjCount() - 1);
711         SdrPathObj* pLastPoly = PTR_CAST(SdrPathObj, pTmpObj);
712 
713         if(pLastPoly)
714         {
715             if(pLastPoly->GetPathPoly() == rPolyPolygon)
716             {
717                 SetAttributes(NULL);
718 
719                 if(!bNoLine && bNoFill)
720                 {
721                     pLastPoly->SetMergedItemSet(*pLineAttr);
722 
723                     return true;
724                 }
725             }
726         }
727     }
728 
729     return false;
730 }
731 
732 void ImpSdrGDIMetaFileImport::checkClip()
733 {
734     if(aVD.IsClipRegion())
735     {
736         Region aRegion(aVD.GetClipRegion());
737 
738         maClip = aRegion.ConvertToB2DPolyPolygon();
739 
740         if(isClip())
741         {
742             const basegfx::B2DHomMatrix aTransform(
743                 basegfx::tools::createScaleTranslateB2DHomMatrix(
744                     fScaleX,
745                     fScaleY,
746                     aOfs.X(),
747                     aOfs.Y()));
748 
749             maClip.transform(aTransform);
750         }
751     }
752 }
753 
754 bool ImpSdrGDIMetaFileImport::isClip() const
755 {
756     return !maClip.getB2DRange().isEmpty();
757 }
758 
759 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct )
760 {
761     // #i73407# reformulation to use new B2DPolygon classes
762     basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
763 
764     if(aSource.count())
765     {
766         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
767         aSource.transform(aTransform);
768     }
769 
770     const LineInfo& rLineInfo = rAct.GetLineInfo();
771     const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
772     bool bCreateLineObject(true);
773 
774     if(bLastObjWasLine && (nNewLineWidth == nLineWidth) && CheckLastLineMerge(aSource))
775     {
776         bCreateLineObject = false;
777     }
778     else if(bLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
779     {
780         bCreateLineObject = false;
781     }
782 
783     if(bCreateLineObject)
784     {
785         SdrPathObj* pPath = new SdrPathObj(
786             aSource.isClosed() ? OBJ_POLY : OBJ_PLIN,
787             basegfx::B2DPolyPolygon(aSource));
788         nLineWidth = nNewLineWidth;
789         maLineJoin = rLineInfo.GetLineJoin();
790         maLineCap = rLineInfo.GetLineCap();
791         maDash = XDash(XDASH_RECT,
792             rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
793             rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
794             rLineInfo.GetDistance());
795         SetAttributes(pPath);
796         nLineWidth = 0;
797         maLineJoin = basegfx::B2DLINEJOIN_NONE;
798         maDash = XDash();
799         InsertObj(pPath, false);
800     }
801 }
802 
803 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct )
804 {
805     // #i73407# reformulation to use new B2DPolygon classes
806     basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
807 
808     if(aSource.count())
809     {
810         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
811         aSource.transform(aTransform);
812 
813         if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
814         {
815             // #i73407# make sure polygon is closed, it's a filled primitive
816             aSource.setClosed(true);
817             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource));
818             SetAttributes(pPath);
819             InsertObj(pPath, false);
820         }
821     }
822 }
823 
824 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct)
825 {
826     // #i73407# reformulation to use new B2DPolygon classes
827     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
828 
829     if(aSource.count())
830     {
831         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
832         aSource.transform(aTransform);
833 
834         if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
835         {
836             // #i73407# make sure polygon is closed, it's a filled primitive
837             aSource.setClosed(true);
838             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
839             SetAttributes(pPath);
840             InsertObj(pPath, false);
841         }
842     }
843 }
844 
845 /**************************************************************************************************/
846 
847 void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct )
848 {
849     // calc text box size, add 5% to make it fit safely
850 
851     FontMetric aFontMetric( aVD.GetFontMetric() );
852     Font aFnt( aVD.GetFont() );
853     FontAlign eAlg( aFnt.GetAlign() );
854 
855     sal_Int32 nTextWidth = (sal_Int32)( aVD.GetTextWidth( rStr ) * fScaleX );
856     sal_Int32 nTextHeight = (sal_Int32)( aVD.GetTextHeight() * fScaleY );
857     //sal_Int32 nDxWidth = 0;
858     //sal_Int32 nLen = rStr.Len();
859 
860     Point aPos( FRound(rPos.X() * fScaleX + aOfs.X()), FRound(rPos.Y() * fScaleY + aOfs.Y()) );
861     Size aSize( nTextWidth, nTextHeight );
862 
863     if ( eAlg == ALIGN_BASELINE )
864         aPos.Y() -= FRound(aFontMetric.GetAscent() * fScaleY);
865     else if ( eAlg == ALIGN_BOTTOM )
866         aPos.Y() -= nTextHeight;
867 
868     Rectangle aTextRect( aPos, aSize );
869     SdrRectObj* pText =new SdrRectObj( OBJ_TEXT, aTextRect );
870 
871     if ( aFnt.GetWidth() || ( rAct.GetType() == META_STRETCHTEXT_ACTION ) )
872     {
873         pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
874         pText->SetMergedItem( SdrTextAutoGrowHeightItem( sal_False ) );
875         // don't let the margins eat the space needed for the text
876         pText->SetMergedItem ( SdrTextUpperDistItem (0));
877         pText->SetMergedItem ( SdrTextLowerDistItem (0));
878         pText->SetMergedItem ( SdrTextRightDistItem (0));
879         pText->SetMergedItem ( SdrTextLeftDistItem (0));
880         pText->SetMergedItem( SdrTextFitToSizeTypeItem( SDRTEXTFIT_ALLLINES ) );
881     }
882     else
883         pText->SetMergedItem( SdrTextAutoGrowWidthItem( sal_True ) );
884 
885     pText->SetModel( pModel );
886     pText->SetLayer( nLayer );
887     pText->NbcSetText( rStr );
888     SetAttributes( pText, sal_True );
889     pText->SetSnapRect( aTextRect );
890 
891     if (!aFnt.IsTransparent())
892     {
893         SfxItemSet aAttr(*pFillAttr->GetPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST);
894         aAttr.Put(XFillStyleItem(XFILL_SOLID));
895         aAttr.Put(XFillColorItem(String(), aFnt.GetFillColor()));
896         pText->SetMergedItemSet(aAttr);
897     }
898     sal_uInt32 nWink = aFnt.GetOrientation();
899     if ( nWink )
900     {
901         nWink*=10;
902         double a=nWink*nPi180;
903         double nSin=sin(a);
904         double nCos=cos(a);
905         pText->NbcRotate(aPos,nWink,nSin,nCos);
906     }
907     InsertObj( pText, sal_False );
908 }
909 
910 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction& rAct)
911 {
912     XubString aStr(rAct.GetText());
913     aStr.Erase(0,rAct.GetIndex());
914     aStr.Erase(rAct.GetLen());
915     ImportText( rAct.GetPoint(), aStr, rAct );
916 }
917 
918 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction& rAct)
919 {
920     XubString aStr(rAct.GetText());
921     aStr.Erase(0,rAct.GetIndex());
922     aStr.Erase(rAct.GetLen());
923     ImportText( rAct.GetPoint(), aStr, rAct );
924 }
925 
926 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction& rAct)
927 {
928     XubString aStr(rAct.GetText());
929     aStr.Erase(0,rAct.GetIndex());
930     aStr.Erase(rAct.GetLen());
931     ImportText( rAct.GetPoint(), aStr, rAct );
932 }
933 
934 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction& rAct)
935 {
936     Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
937     aRect.Right()++; aRect.Bottom()++;
938     SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
939     InsertObj(pGraf);
940 }
941 
942 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction& rAct)
943 {
944     Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
945     aRect.Right()++; aRect.Bottom()++;
946     SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
947     InsertObj(pGraf);
948 }
949 
950 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction& rAct)
951 {
952     Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
953     aRect.Right()++; aRect.Bottom()++;
954     SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
955     InsertObj(pGraf);
956 }
957 
958 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction& rAct)
959 {
960     Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
961     aRect.Right()++; aRect.Bottom()++;
962     SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
963     InsertObj(pGraf);
964 }
965 
966 ////////////////////////////////////////////////////////////////////////////////////////////////////
967 
968 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction& rAct )
969 {
970     // #i73407# reformulation to use new B2DPolygon classes
971     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
972 
973     if(aSource.count())
974     {
975         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
976         aSource.transform(aTransform);
977 
978         if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
979         {
980             const Hatch& rHatch = rAct.GetHatch();
981             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
982             SfxItemSet aHatchAttr(pModel->GetItemPool(),
983                 XATTR_FILLSTYLE, XATTR_FILLSTYLE,
984                 XATTR_FILLHATCH, XATTR_FILLHATCH, 0, 0 );
985             XHatchStyle eStyle;
986 
987             switch(rHatch.GetStyle())
988             {
989                 case(HATCH_TRIPLE) :
990                 {
991                     eStyle = XHATCH_TRIPLE;
992                     break;
993                 }
994 
995                 case(HATCH_DOUBLE) :
996                 {
997                     eStyle = XHATCH_DOUBLE;
998                     break;
999                 }
1000 
1001                 default:
1002                 {
1003                     eStyle = XHATCH_SINGLE;
1004                     break;
1005                 }
1006             }
1007 
1008             SetAttributes(pPath);
1009             aHatchAttr.Put(XFillStyleItem(XFILL_HATCH));
1010             aHatchAttr.Put(XFillHatchItem(&pModel->GetItemPool(), XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
1011             pPath->SetMergedItemSet(aHatchAttr);
1012 
1013             InsertObj(pPath, false);
1014         }
1015     }
1016 }
1017 
1018 ////////////////////////////////////////////////////////////////////////////////////////////////////
1019 
1020 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
1021 {
1022     rAct.Execute(&aVD);
1023 }
1024 
1025 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
1026 {
1027     MapScaling();
1028     rAct.Execute(&aVD);
1029     bLastObjWasPolyWithoutLine=sal_False;
1030     bLastObjWasLine=sal_False;
1031 }
1032 
1033 void ImpSdrGDIMetaFileImport::MapScaling()
1034 {
1035     sal_uInt32 i, nAnz = aTmpList.GetObjCount();
1036     const MapMode& rMap = aVD.GetMapMode();
1037     Point aMapOrg( rMap.GetOrigin() );
1038     sal_Bool bMov2 = aMapOrg.X() != 0 || aMapOrg.Y() != 0;
1039     if ( bMov2 )
1040     {
1041         for ( i = nMapScalingOfs; i < nAnz; i++ )
1042         {
1043             SdrObject* pObj = aTmpList.GetObj(i);
1044             if ( bMov2 )
1045                 pObj->NbcMove( Size( aMapOrg.X(), aMapOrg.Y() ) );
1046         }
1047     }
1048     nMapScalingOfs = nAnz;
1049 }
1050 
1051 ////////////////////////////////////////////////////////////////////////////////////////////////////
1052 
1053 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction& rAct, GDIMetaFile* pMtf )
1054 {
1055     ByteString aSkipComment;
1056 
1057     if( rAct.GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1058     {
1059         MetaGradientExAction* pAct = (MetaGradientExAction*) pMtf->NextAction();
1060 
1061         if( pAct && pAct->GetType() == META_GRADIENTEX_ACTION )
1062         {
1063             // #i73407# reformulation to use new B2DPolygon classes
1064             basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
1065 
1066             if(aSource.count())
1067             {
1068                 if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1069                 {
1070                     const Gradient& rGrad = pAct->GetGradient();
1071                     SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1072                     SfxItemSet aGradAttr(pModel->GetItemPool(),
1073                        XATTR_FILLSTYLE, XATTR_FILLSTYLE,
1074                        XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0 );
1075                     XGradient aXGradient;
1076 
1077                     aXGradient.SetGradientStyle((XGradientStyle)rGrad.GetStyle());
1078                     aXGradient.SetStartColor(rGrad.GetStartColor());
1079                     aXGradient.SetEndColor(rGrad.GetEndColor());
1080                     aXGradient.SetAngle((sal_uInt16)rGrad.GetAngle());
1081                     aXGradient.SetBorder(rGrad.GetBorder());
1082                     aXGradient.SetXOffset(rGrad.GetOfsX());
1083                     aXGradient.SetYOffset(rGrad.GetOfsY());
1084                     aXGradient.SetStartIntens(rGrad.GetStartIntensity());
1085                     aXGradient.SetEndIntens(rGrad.GetEndIntensity());
1086                     aXGradient.SetSteps(rGrad.GetSteps());
1087 
1088                     if(aVD.IsLineColor())
1089                     {
1090                         // switch line off; when there was one there will be a
1091                         // META_POLYLINE_ACTION following creating another object
1092                         const Color aLineColor(aVD.GetLineColor());
1093                         aVD.SetLineColor();
1094                         SetAttributes(pPath);
1095                         aVD.SetLineColor(aLineColor);
1096                     }
1097                     else
1098                     {
1099                         SetAttributes(pPath);
1100                     }
1101 
1102                     aGradAttr.Put(XFillStyleItem(XFILL_GRADIENT));
1103                     aGradAttr.Put(XFillGradientItem(&pModel->GetItemPool(), aXGradient));
1104                     pPath->SetMergedItemSet(aGradAttr);
1105 
1106                     InsertObj(pPath);
1107                 }
1108             }
1109 
1110             aSkipComment = "XGRAD_SEQ_END";
1111         }
1112     }
1113 
1114     if(aSkipComment.Len())
1115     {
1116         MetaAction* pSkipAct = pMtf->NextAction();
1117 
1118         while( pSkipAct
1119             && ((pSkipAct->GetType() != META_COMMENT_ACTION )
1120                 || (((MetaCommentAction*)pSkipAct)->GetComment().CompareIgnoreCaseToAscii(aSkipComment.GetBuffer()) != COMPARE_EQUAL)))
1121         {
1122             pSkipAct = pMtf->NextAction();
1123         }
1124     }
1125 }
1126 
1127 ////////////////////////////////////////////////////////////////////////////////////////////////////
1128 // eof
1129