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