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