xref: /AOO41X/main/svx/source/svdraw/svdfmtf.cxx (revision 4bfbcde8d64cc5d114df10dce4a9ed79eff32278)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include "svdfmtf.hxx"
28 #include <editeng/editdata.hxx>
29 #include <math.h>
30 #include <svx/xpoly.hxx>
31 #include <vcl/svapp.hxx>
32 #include <editeng/eeitem.hxx>
33 #include <editeng/fhgtitem.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <editeng/postitem.hxx>
36 #include <editeng/udlnitem.hxx>
37 #include <editeng/crsditem.hxx>
38 #include <editeng/shdditem.hxx>
39 #include <svx/xlnclit.hxx>
40 #include <svx/xlncapit.hxx>
41 #include <svx/xlnwtit.hxx>
42 #include <svx/xflclit.hxx>
43 #include <svx/xgrad.hxx>
44 #include <svx/xflgrit.hxx>
45 #include <editeng/fontitem.hxx>
46 #include <editeng/akrnitem.hxx>
47 #include <editeng/wrlmitem.hxx>
48 #include <editeng/cntritem.hxx>
49 #include <editeng/colritem.hxx>
50 #include <vcl/metric.hxx>
51 #include <editeng/charscaleitem.hxx>
52 #include <svx/xflhtit.hxx>
53 #include <svx/svdattr.hxx>
54 #include <svx/svdmodel.hxx>
55 #include <svx/svdpage.hxx>
56 #include <svx/svdobj.hxx>
57 #include "svx/svditext.hxx"
58 #include <svx/svdotext.hxx>
59 #include <svx/svdorect.hxx>
60 #include <svx/svdocirc.hxx>
61 #include <svx/svdograf.hxx>
62 #include <svx/svdopath.hxx>
63 #include <svx/svdetc.hxx>
64 #include <svl/itemset.hxx>
65 #include <basegfx/polygon/b2dpolygon.hxx>
66 #include <vcl/salbtype.hxx>     // FRound
67 #include <basegfx/matrix/b2dhommatrix.hxx>
68 #include <basegfx/matrix/b2dhommatrixtools.hxx>
69 #include <svx/xlinjoit.hxx>
70 #include <svx/xlndsit.hxx>
71 
72 ////////////////////////////////////////////////////////////////////////////////////////////////////
73 
74 ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel):
75     nMapScalingOfs(0),
76     pLineAttr(NULL),pFillAttr(NULL),pTextAttr(NULL),
77     pPage(NULL),pModel(NULL),nLayer(0),
78     nLineWidth(0),
79     maLineJoin(basegfx::B2DLINEJOIN_NONE),
80     maLineCap(com::sun::star::drawing::LineCap_BUTT),
81     maDash(XDASH_RECT, 0, 0, 0, 0, 0),
82     bFntDirty(sal_True),
83     bLastObjWasPolyWithoutLine(sal_False),bNoLine(sal_False),bNoFill(sal_False),bLastObjWasLine(sal_False)
84 {
85     aVD.EnableOutput(sal_False);
86 
87     // #i111954# init to no fill and no line initially
88     aVD.SetLineColor();
89     aVD.SetFillColor();
90 
91     aOldLineColor.SetRed( aVD.GetLineColor().GetRed() + 1 ); // invalidate old line color
92     pLineAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_LINE_FIRST,XATTR_LINE_LAST);
93     pFillAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST);
94     pTextAttr=new SfxItemSet(rModel.GetItemPool(),EE_ITEMS_START,EE_ITEMS_END);
95     pModel=&rModel;
96 }
97 
98 ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport()
99 {
100     delete pLineAttr;
101     delete pFillAttr;
102     delete pTextAttr;
103 }
104 
105 sal_uIntPtr ImpSdrGDIMetaFileImport::DoImport(const GDIMetaFile& rMtf,
106     SdrObjList& rOL,
107     sal_uIntPtr nInsPos,
108     SvdProgressInfo *pProgrInfo)
109 {
110     pPage = rOL.GetPage();
111     GDIMetaFile* pTmpMtf=NULL;
112     GDIMetaFile* pMtf = (GDIMetaFile*) &rMtf;
113     sal_uIntPtr nActionAnz=pMtf->GetActionCount();
114     sal_Bool bError = sal_False;
115 
116 
117     // setup some global scale parameter
118     // fScaleX, fScaleY, aScaleX, aScaleY, bMov, bSize
119     fScaleX = fScaleY = 1.0;
120     Size  aMtfSize( pMtf->GetPrefSize() );
121     if ( aMtfSize.Width() & aMtfSize.Height() && ( aScaleRect.IsEmpty() == sal_False ) )
122     {
123         aOfs = aScaleRect.TopLeft();
124         if ( aMtfSize.Width() != ( aScaleRect.GetWidth() - 1 ) )
125             fScaleX = (double)( aScaleRect.GetWidth() - 1 ) / (double)aMtfSize.Width();
126         if ( aMtfSize.Height() != ( aScaleRect.GetHeight() - 1 ) )
127             fScaleY = (double)( aScaleRect.GetHeight() - 1 ) / (double)aMtfSize.Height();
128     }
129 
130     bMov = aOfs.X()!=0 || aOfs.Y()!=0;
131     bSize = sal_False;
132 
133     aScaleX = Fraction( 1, 1 );
134     aScaleY = Fraction( 1, 1 );
135     if ( aMtfSize.Width() != ( aScaleRect.GetWidth() - 1 ) )
136     {
137         aScaleX = Fraction( aScaleRect.GetWidth() - 1, aMtfSize.Width() );
138         bSize = sal_True;
139     }
140     if ( aMtfSize.Height() != ( aScaleRect.GetHeight() - 1 ) )
141     {
142         aScaleY = Fraction( aScaleRect.GetHeight() - 1, aMtfSize.Height() );
143         bSize = sal_True;
144     }
145 
146     if(65000 < nActionAnz)
147     {
148         nActionAnz = 65000;
149         bError = sal_True;
150     }
151 
152     if(pProgrInfo)
153         pProgrInfo->SetActionCount(nActionAnz);
154 
155     sal_uIntPtr nActionsToReport = 0;
156 
157     for( MetaAction* pAct = pMtf->FirstAction(); pAct; pAct = pMtf->NextAction() )
158     {
159         switch (pAct->GetType())
160         {
161             case META_PIXEL_ACTION          : DoAction((MetaPixelAction          &)*pAct); break;
162             case META_POINT_ACTION          : DoAction((MetaPointAction          &)*pAct); break;
163             case META_LINE_ACTION           : DoAction((MetaLineAction           &)*pAct); break;
164             case META_RECT_ACTION           : DoAction((MetaRectAction           &)*pAct); break;
165             case META_ROUNDRECT_ACTION      : DoAction((MetaRoundRectAction      &)*pAct); break;
166             case META_ELLIPSE_ACTION        : DoAction((MetaEllipseAction        &)*pAct); break;
167             case META_ARC_ACTION            : DoAction((MetaArcAction            &)*pAct); break;
168             case META_PIE_ACTION            : DoAction((MetaPieAction            &)*pAct); break;
169             case META_CHORD_ACTION          : DoAction((MetaChordAction          &)*pAct); break;
170             case META_POLYLINE_ACTION       : DoAction((MetaPolyLineAction       &)*pAct); break;
171             case META_POLYGON_ACTION        : DoAction((MetaPolygonAction        &)*pAct); break;
172             case META_POLYPOLYGON_ACTION    : DoAction((MetaPolyPolygonAction    &)*pAct); break;
173             case META_TEXT_ACTION           : DoAction((MetaTextAction           &)*pAct); break;
174             case META_TEXTARRAY_ACTION      : DoAction((MetaTextArrayAction      &)*pAct); break;
175             case META_STRETCHTEXT_ACTION    : DoAction((MetaStretchTextAction    &)*pAct); break;
176             case META_BMP_ACTION            : DoAction((MetaBmpAction            &)*pAct); break;
177             case META_BMPSCALE_ACTION       : DoAction((MetaBmpScaleAction       &)*pAct); break;
178             case META_BMPEX_ACTION          : DoAction((MetaBmpExAction          &)*pAct); break;
179             case META_BMPEXSCALE_ACTION     : DoAction((MetaBmpExScaleAction     &)*pAct); break;
180             case META_LINECOLOR_ACTION      : DoAction((MetaLineColorAction      &)*pAct); break;
181             case META_FILLCOLOR_ACTION      : DoAction((MetaFillColorAction      &)*pAct); break;
182             case META_TEXTCOLOR_ACTION      : DoAction((MetaTextColorAction      &)*pAct); break;
183             case META_TEXTFILLCOLOR_ACTION  : DoAction((MetaTextFillColorAction  &)*pAct); break;
184             case META_FONT_ACTION           : DoAction((MetaFontAction           &)*pAct); break;
185             case META_TEXTALIGN_ACTION      : DoAction((MetaTextAlignAction      &)*pAct); break;
186             case META_MAPMODE_ACTION        : DoAction((MetaMapModeAction        &)*pAct); break;
187             case META_CLIPREGION_ACTION     : DoAction((MetaClipRegionAction     &)*pAct); break;
188             case META_MOVECLIPREGION_ACTION : DoAction((MetaMoveClipRegionAction &)*pAct); break;
189             case META_ISECTRECTCLIPREGION_ACTION: DoAction((MetaISectRectClipRegionAction&)*pAct); break;
190             case META_ISECTREGIONCLIPREGION_ACTION: DoAction((MetaISectRegionClipRegionAction&)*pAct); break;
191             case META_RASTEROP_ACTION       : DoAction((MetaRasterOpAction       &)*pAct); break;
192             case META_PUSH_ACTION           : DoAction((MetaPushAction           &)*pAct); break;
193             case META_POP_ACTION            : DoAction((MetaPopAction            &)*pAct); break;
194             case META_HATCH_ACTION          : DoAction((MetaHatchAction          &)*pAct); break;
195             case META_COMMENT_ACTION        : DoAction((MetaCommentAction        &)*pAct, pMtf); break;
196         }
197 
198         if(pProgrInfo != NULL)
199         {
200           nActionsToReport++;
201           if(nActionsToReport >= 16) // Alle 16 Action updaten
202           {
203             if(!pProgrInfo->ReportActions(nActionsToReport))
204               break;
205             nActionsToReport = 0;
206           }
207         }
208     }
209 
210     if(pProgrInfo != NULL)
211     {
212         pProgrInfo->ReportActions(nActionsToReport);
213         nActionsToReport = 0;
214     }
215 
216     // MapMode-Scaling  vornehmen
217     MapScaling();
218     // Objekte in vorgegebenes Rechteck hineinskalieren
219     sal_uIntPtr nAnz=aTmpList.GetObjCount();
220 
221     // Beim berechnen der Fortschrittsanzeige wird GetActionCount()*3 benutzt.
222     // Da in aTmpList allerdings weniger eintraege als GetActionCount()
223     // existieren koennen, muessen hier die zuviel vermuteten Actionen wieder
224     // hinzugefuegt werden.
225     nActionsToReport = (pMtf->GetActionCount() - nAnz)*2;
226 
227 
228     // Alle noch nicht gemeldeten Rescales melden
229     if(pProgrInfo)
230     {
231         pProgrInfo->ReportRescales(nActionsToReport);
232         pProgrInfo->SetInsertCount(nAnz);
233     }
234     nActionsToReport = 0;
235 
236     // alle in aTmpList zwischengespeicherten Objekte nun in rOL ab der Position nInsPos einfuegen
237     if (nInsPos>rOL.GetObjCount()) nInsPos=rOL.GetObjCount();
238     SdrInsertReason aReason(SDRREASON_VIEWCALL);
239     for (sal_uIntPtr i=0; i<nAnz; i++)
240     {
241          SdrObject* pObj=aTmpList.GetObj(i);
242          rOL.NbcInsertObject(pObj,nInsPos,&aReason);
243          nInsPos++;
244 
245         if(pProgrInfo != NULL)
246         {
247             nActionsToReport++;
248             if(nActionsToReport >= 32) // Alle 32 Action updaten
249             {
250                 pProgrInfo->ReportInserts(nActionsToReport);
251                 nActionsToReport = 0;
252             }
253         }
254     }
255     if (pTmpMtf!=NULL) delete pTmpMtf;
256 
257     // ein letztesmal alle verbliebennen Inserts reporten
258     if(pProgrInfo != NULL)
259     {
260         pProgrInfo->ReportInserts(nActionsToReport);
261         if(bError)
262             pProgrInfo->ReportError();
263     }
264 
265     return aTmpList.GetObjCount();
266 }
267 
268 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, FASTBOOL bForceTextAttr)
269 {
270     bNoLine = sal_False; bNoFill = sal_False;
271     FASTBOOL bLine=sal_True && !bForceTextAttr;
272     FASTBOOL bFill=pObj==NULL || ( pObj->IsClosedObj() && !bForceTextAttr );
273     FASTBOOL bText=bForceTextAttr || (pObj!=NULL && pObj->GetOutlinerParaObject()!=NULL);
274 
275     if ( bLine )
276     {
277         if ( nLineWidth )
278             pLineAttr->Put( XLineWidthItem( nLineWidth ) );
279         else
280             pLineAttr->Put( XLineWidthItem( 0 ) );
281 
282         aOldLineColor = aVD.GetLineColor();
283         if( aVD.IsLineColor() )
284         {
285             pLineAttr->Put(XLineStyleItem(XLINE_SOLID));
286             pLineAttr->Put(XLineColorItem(String(), aVD.GetLineColor()));
287         }
288         else
289             pLineAttr->Put(XLineStyleItem(XLINE_NONE));
290 
291         switch(maLineJoin)
292         {
293             default : // basegfx::B2DLINEJOIN_NONE
294                 pLineAttr->Put(XLineJointItem(XLINEJOINT_NONE));
295                 break;
296             case basegfx::B2DLINEJOIN_MIDDLE:
297                 pLineAttr->Put(XLineJointItem(XLINEJOINT_MIDDLE));
298                 break;
299             case basegfx::B2DLINEJOIN_BEVEL:
300                 pLineAttr->Put(XLineJointItem(XLINEJOINT_BEVEL));
301                 break;
302             case basegfx::B2DLINEJOIN_MITER:
303                 pLineAttr->Put(XLineJointItem(XLINEJOINT_MITER));
304                 break;
305             case basegfx::B2DLINEJOIN_ROUND:
306                 pLineAttr->Put(XLineJointItem(XLINEJOINT_ROUND));
307                 break;
308         }
309 
310         // Add LineCap support
311         pLineAttr->Put(XLineCapItem(maLineCap));
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(aVD.GetTextColor(), 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             maLineCap = rLineInfo.GetLineCap();
489             maDash = XDash(XDASH_RECT,
490                 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
491                 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
492                 rLineInfo.GetDistance());
493             SetAttributes(pPath);
494             nLineWidth = 0;
495             maLineJoin = basegfx::B2DLINEJOIN_NONE;
496             maDash = XDash();
497             InsertObj(pPath, false);
498         }
499     }
500 }
501 
502 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction& rAct)
503 {
504     SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
505     SetAttributes(pRect);
506     InsertObj(pRect);
507 }
508 
509 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction& rAct)
510 {
511     SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
512     SetAttributes(pRect);
513     long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
514     if (nRad!=0) {
515         SfxItemSet aSet(*pLineAttr->GetPool(),SDRATTR_ECKENRADIUS,SDRATTR_ECKENRADIUS);
516         aSet.Put(SdrEckenradiusItem(nRad));
517         pRect->SetMergedItemSet(aSet);
518     }
519     InsertObj(pRect);
520 }
521 
522 /**************************************************************************************************/
523 
524 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction& rAct)
525 {
526     SdrCircObj* pCirc=new SdrCircObj(OBJ_CIRC,rAct.GetRect());
527     SetAttributes(pCirc);
528     InsertObj(pCirc);
529 }
530 
531 void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction& rAct)
532 {
533     Point aCenter(rAct.GetRect().Center());
534     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
535     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
536     SdrCircObj* pCirc=new SdrCircObj(OBJ_CARC,rAct.GetRect(),nStart,nEnd);
537     SetAttributes(pCirc);
538     InsertObj(pCirc);
539 }
540 
541 void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction& rAct)
542 {
543     Point aCenter(rAct.GetRect().Center());
544     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
545     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
546     SdrCircObj* pCirc=new SdrCircObj(OBJ_SECT,rAct.GetRect(),nStart,nEnd);
547     SetAttributes(pCirc);
548     InsertObj(pCirc);
549 }
550 
551 void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction& rAct)
552 {
553     Point aCenter(rAct.GetRect().Center());
554     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
555     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
556     SdrCircObj* pCirc=new SdrCircObj(OBJ_CCUT,rAct.GetRect(),nStart,nEnd);
557     SetAttributes(pCirc);
558     InsertObj(pCirc);
559 }
560 
561 /**************************************************************************************************/
562 
563 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
564 {
565     // #i102706# Do not merge closed polygons
566     if(rSrcPoly.isClosed())
567     {
568         return false;
569     }
570 
571     // #i73407# reformulation to use new B2DPolygon classes
572     if(bLastObjWasLine && (aOldLineColor == aVD.GetLineColor()) && rSrcPoly.count())
573     {
574         SdrObject* pTmpObj = aTmpList.GetObj(aTmpList.GetObjCount() - 1);
575         SdrPathObj* pLastPoly = PTR_CAST(SdrPathObj, pTmpObj);
576 
577         if(pLastPoly)
578         {
579             if(1L == pLastPoly->GetPathPoly().count())
580             {
581                 bool bOk(false);
582                 basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0L));
583 
584                 // #i102706# Do not merge closed polygons
585                 if(aDstPoly.isClosed())
586                 {
587                     return false;
588                 }
589 
590                 if(aDstPoly.count())
591                 {
592                     const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1L);
593                     const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1L);
594 
595                     if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0L))
596                     {
597                         aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
598                         bOk = true;
599                     }
600                     else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
601                     {
602                         basegfx::B2DPolygon aNew(rSrcPoly);
603                         aNew.append(aDstPoly, 1L, aDstPoly.count() - 1L);
604                         aDstPoly = aNew;
605                         bOk = true;
606                     }
607                     else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(0L))
608                     {
609                         aDstPoly.flip();
610                         aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
611                         bOk = true;
612                     }
613                     else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
614                     {
615                         basegfx::B2DPolygon aNew(rSrcPoly);
616                         aNew.flip();
617                         aDstPoly.append(aNew, 1L, aNew.count() - 1L);
618                         bOk = true;
619                     }
620                 }
621 
622                 if(bOk)
623                 {
624                     pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
625                 }
626 
627                 return bOk;
628             }
629         }
630     }
631 
632     return false;
633 }
634 
635 bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
636 {
637     // #i73407# reformulation to use new B2DPolygon classes
638     if(bLastObjWasPolyWithoutLine)
639     {
640         SdrObject* pTmpObj = aTmpList.GetObj(aTmpList.GetObjCount() - 1);
641         SdrPathObj* pLastPoly = PTR_CAST(SdrPathObj, pTmpObj);
642 
643         if(pLastPoly)
644         {
645             if(pLastPoly->GetPathPoly() == rPolyPolygon)
646             {
647                 SetAttributes(NULL);
648 
649                 if(!bNoLine && bNoFill)
650                 {
651                     pLastPoly->SetMergedItemSet(*pLineAttr);
652 
653                     return true;
654                 }
655             }
656         }
657     }
658 
659     return false;
660 }
661 
662 
663 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct )
664 {
665     // #i73407# reformulation to use new B2DPolygon classes
666     basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
667 
668     if(aSource.count())
669     {
670         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
671         aSource.transform(aTransform);
672     }
673 
674     const LineInfo& rLineInfo = rAct.GetLineInfo();
675     const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
676     bool bCreateLineObject(true);
677 
678     if(bLastObjWasLine && (nNewLineWidth == nLineWidth) && CheckLastLineMerge(aSource))
679     {
680         bCreateLineObject = false;
681     }
682     else if(bLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
683     {
684         bCreateLineObject = false;
685     }
686 
687     if(bCreateLineObject)
688     {
689         SdrPathObj* pPath = new SdrPathObj(
690             aSource.isClosed() ? OBJ_POLY : OBJ_PLIN,
691             basegfx::B2DPolyPolygon(aSource));
692         nLineWidth = nNewLineWidth;
693         maLineJoin = rLineInfo.GetLineJoin();
694         maLineCap = rLineInfo.GetLineCap();
695         maDash = XDash(XDASH_RECT,
696             rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
697             rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
698             rLineInfo.GetDistance());
699         SetAttributes(pPath);
700         nLineWidth = 0;
701         maLineJoin = basegfx::B2DLINEJOIN_NONE;
702         maDash = XDash();
703         InsertObj(pPath, false);
704     }
705 }
706 
707 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct )
708 {
709     // #i73407# reformulation to use new B2DPolygon classes
710     basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
711 
712     if(aSource.count())
713     {
714         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
715         aSource.transform(aTransform);
716 
717         if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
718         {
719             // #i73407# make sure polygon is closed, it's a filled primitive
720             aSource.setClosed(true);
721 
722             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource));
723             SetAttributes(pPath);
724             InsertObj(pPath, false);
725         }
726     }
727 }
728 
729 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct)
730 {
731     // #i73407# reformulation to use new B2DPolygon classes
732     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
733 
734     if(aSource.count())
735     {
736         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
737         aSource.transform(aTransform);
738 
739         if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
740         {
741             // #i73407# make sure polygon is closed, it's a filled primitive
742             aSource.setClosed(true);
743 
744             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
745             SetAttributes(pPath);
746             InsertObj(pPath, false);
747         }
748     }
749 }
750 
751 /**************************************************************************************************/
752 
753 void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct )
754 {
755     // calc text box size, add 5% to make it fit safely
756 
757     FontMetric aFontMetric( aVD.GetFontMetric() );
758     Font aFnt( aVD.GetFont() );
759     FontAlign eAlg( aFnt.GetAlign() );
760 
761     sal_Int32 nTextWidth = (sal_Int32)( aVD.GetTextWidth( rStr ) * fScaleX );
762     sal_Int32 nTextHeight = (sal_Int32)( aVD.GetTextHeight() * fScaleY );
763     //sal_Int32 nDxWidth = 0;
764     //sal_Int32 nLen = rStr.Len();
765 
766     Point aPos( FRound(rPos.X() * fScaleX + aOfs.X()), FRound(rPos.Y() * fScaleY + aOfs.Y()) );
767     Size aSize( nTextWidth, nTextHeight );
768 
769     if ( eAlg == ALIGN_BASELINE )
770         aPos.Y() -= FRound(aFontMetric.GetAscent() * fScaleY);
771     else if ( eAlg == ALIGN_BOTTOM )
772         aPos.Y() -= nTextHeight;
773 
774     Rectangle aTextRect( aPos, aSize );
775     SdrRectObj* pText =new SdrRectObj( OBJ_TEXT, aTextRect );
776 
777     if ( aFnt.GetWidth() || ( rAct.GetType() == META_STRETCHTEXT_ACTION ) )
778     {
779         pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
780         pText->SetMergedItem( SdrTextAutoGrowHeightItem( sal_False ) );
781         // don't let the margins eat the space needed for the text
782         pText->SetMergedItem ( SdrTextUpperDistItem (0));
783         pText->SetMergedItem ( SdrTextLowerDistItem (0));
784         pText->SetMergedItem ( SdrTextRightDistItem (0));
785         pText->SetMergedItem ( SdrTextLeftDistItem (0));
786         pText->SetMergedItem( SdrTextFitToSizeTypeItem( SDRTEXTFIT_ALLLINES ) );
787     }
788     else
789         pText->SetMergedItem( SdrTextAutoGrowWidthItem( sal_True ) );
790 
791     pText->SetModel( pModel );
792     pText->SetLayer( nLayer );
793     pText->NbcSetText( rStr );
794     SetAttributes( pText, sal_True );
795     pText->SetSnapRect( aTextRect );
796 
797     if (!aFnt.IsTransparent())
798     {
799         SfxItemSet aAttr(*pFillAttr->GetPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST);
800         aAttr.Put(XFillStyleItem(XFILL_SOLID));
801         aAttr.Put(XFillColorItem(String(), aFnt.GetFillColor()));
802         pText->SetMergedItemSet(aAttr);
803     }
804     sal_uInt32 nWink = aFnt.GetOrientation();
805     if ( nWink )
806     {
807         nWink*=10;
808         double a=nWink*nPi180;
809         double nSin=sin(a);
810         double nCos=cos(a);
811         pText->NbcRotate(aPos,nWink,nSin,nCos);
812     }
813     InsertObj( pText, sal_False );
814 }
815 
816 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction& rAct)
817 {
818     XubString aStr(rAct.GetText());
819     aStr.Erase(0,rAct.GetIndex());
820     aStr.Erase(rAct.GetLen());
821     ImportText( rAct.GetPoint(), aStr, rAct );
822 }
823 
824 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction& rAct)
825 {
826     XubString aStr(rAct.GetText());
827     aStr.Erase(0,rAct.GetIndex());
828     aStr.Erase(rAct.GetLen());
829     ImportText( rAct.GetPoint(), aStr, rAct );
830 }
831 
832 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction& rAct)
833 {
834     XubString aStr(rAct.GetText());
835     aStr.Erase(0,rAct.GetIndex());
836     aStr.Erase(rAct.GetLen());
837     ImportText( rAct.GetPoint(), aStr, rAct );
838 }
839 
840 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction& rAct)
841 {
842     Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
843     aRect.Right()++; aRect.Bottom()++;
844     SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
845     InsertObj(pGraf);
846 }
847 
848 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction& rAct)
849 {
850     Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
851     aRect.Right()++; aRect.Bottom()++;
852     SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
853     InsertObj(pGraf);
854 }
855 
856 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction& rAct)
857 {
858     Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
859     aRect.Right()++; aRect.Bottom()++;
860     SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
861     InsertObj(pGraf);
862 }
863 
864 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction& rAct)
865 {
866     Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
867     aRect.Right()++; aRect.Bottom()++;
868     SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
869     InsertObj(pGraf);
870 }
871 
872 ////////////////////////////////////////////////////////////////////////////////////////////////////
873 
874 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction& rAct )
875 {
876     // #i73407# reformulation to use new B2DPolygon classes
877     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
878 
879     if(aSource.count())
880     {
881         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(fScaleX, fScaleY, aOfs.X(), aOfs.Y()));
882         aSource.transform(aTransform);
883 
884         if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
885         {
886             const Hatch& rHatch = rAct.GetHatch();
887             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
888             SfxItemSet aHatchAttr(pModel->GetItemPool(),
889                 XATTR_FILLSTYLE, XATTR_FILLSTYLE,
890                 XATTR_FILLHATCH, XATTR_FILLHATCH, 0, 0 );
891             XHatchStyle eStyle;
892 
893             switch(rHatch.GetStyle())
894             {
895                 case(HATCH_TRIPLE) :
896                 {
897                     eStyle = XHATCH_TRIPLE;
898                     break;
899                 }
900 
901                 case(HATCH_DOUBLE) :
902                 {
903                     eStyle = XHATCH_DOUBLE;
904                     break;
905                 }
906 
907                 default:
908                 {
909                     eStyle = XHATCH_SINGLE;
910                     break;
911                 }
912             }
913 
914             SetAttributes(pPath);
915             aHatchAttr.Put(XFillStyleItem(XFILL_HATCH));
916             aHatchAttr.Put(XFillHatchItem(&pModel->GetItemPool(), XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
917             pPath->SetMergedItemSet(aHatchAttr);
918 
919             InsertObj(pPath, false);
920         }
921     }
922 }
923 
924 ////////////////////////////////////////////////////////////////////////////////////////////////////
925 
926 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
927 {
928     rAct.Execute(&aVD);
929 }
930 
931 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
932 {
933     MapScaling();
934     rAct.Execute(&aVD);
935     bLastObjWasPolyWithoutLine=sal_False;
936     bLastObjWasLine=sal_False;
937 }
938 
939 void ImpSdrGDIMetaFileImport::MapScaling()
940 {
941     sal_uInt32 i, nAnz = aTmpList.GetObjCount();
942     const MapMode& rMap = aVD.GetMapMode();
943     Point aMapOrg( rMap.GetOrigin() );
944     sal_Bool bMov2 = aMapOrg.X() != 0 || aMapOrg.Y() != 0;
945     if ( bMov2 )
946     {
947         for ( i = nMapScalingOfs; i < nAnz; i++ )
948         {
949             SdrObject* pObj = aTmpList.GetObj(i);
950             if ( bMov2 )
951                 pObj->NbcMove( Size( aMapOrg.X(), aMapOrg.Y() ) );
952         }
953     }
954     nMapScalingOfs = nAnz;
955 }
956 
957 ////////////////////////////////////////////////////////////////////////////////////////////////////
958 
959 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction& rAct, GDIMetaFile* pMtf )
960 {
961     ByteString aSkipComment;
962 
963     if( rAct.GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
964     {
965         MetaGradientExAction* pAct = (MetaGradientExAction*) pMtf->NextAction();
966 
967         if( pAct && pAct->GetType() == META_GRADIENTEX_ACTION )
968         {
969             // #i73407# reformulation to use new B2DPolygon classes
970             basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
971 
972             if(aSource.count())
973             {
974                 if(!bLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
975                 {
976                     const Gradient& rGrad = pAct->GetGradient();
977                     SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
978                     SfxItemSet aGradAttr(pModel->GetItemPool(),
979                        XATTR_FILLSTYLE, XATTR_FILLSTYLE,
980                        XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0 );
981                     XGradient aXGradient;
982 
983                     aXGradient.SetGradientStyle((XGradientStyle)rGrad.GetStyle());
984                     aXGradient.SetStartColor(rGrad.GetStartColor());
985                     aXGradient.SetEndColor(rGrad.GetEndColor());
986                     aXGradient.SetAngle((sal_uInt16)rGrad.GetAngle());
987                     aXGradient.SetBorder(rGrad.GetBorder());
988                     aXGradient.SetXOffset(rGrad.GetOfsX());
989                     aXGradient.SetYOffset(rGrad.GetOfsY());
990                     aXGradient.SetStartIntens(rGrad.GetStartIntensity());
991                     aXGradient.SetEndIntens(rGrad.GetEndIntensity());
992                     aXGradient.SetSteps(rGrad.GetSteps());
993 
994                     if(aVD.IsLineColor())
995                     {
996                         // switch line off; when there was one there will be a
997                         // META_POLYLINE_ACTION following creating another object
998                         const Color aLineColor(aVD.GetLineColor());
999                         aVD.SetLineColor();
1000                         SetAttributes(pPath);
1001                         aVD.SetLineColor(aLineColor);
1002                     }
1003                     else
1004                     {
1005                         SetAttributes(pPath);
1006                     }
1007 
1008                     aGradAttr.Put(XFillStyleItem(XFILL_GRADIENT));
1009                     aGradAttr.Put(XFillGradientItem(&pModel->GetItemPool(), aXGradient));
1010                     pPath->SetMergedItemSet(aGradAttr);
1011 
1012                     InsertObj(pPath);
1013                 }
1014             }
1015 
1016             aSkipComment = "XGRAD_SEQ_END";
1017         }
1018     }
1019 
1020     if(aSkipComment.Len())
1021     {
1022         MetaAction* pSkipAct = pMtf->NextAction();
1023 
1024         while( pSkipAct
1025             && ((pSkipAct->GetType() != META_COMMENT_ACTION )
1026                 || (((MetaCommentAction*)pSkipAct)->GetComment().CompareIgnoreCaseToAscii(aSkipComment.GetBuffer()) != COMPARE_EQUAL)))
1027         {
1028             pSkipAct = pMtf->NextAction();
1029         }
1030     }
1031 }
1032 
1033 ////////////////////////////////////////////////////////////////////////////////////////////////////
1034 // eof
1035