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