xref: /AOO41X/main/svx/source/svdraw/svdfmtf.cxx (revision 54628ca40d27d15cc98fe861da7fff7e60c2f7d6)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include "svdfmtf.hxx"
28 #include <editeng/editdata.hxx>
29 #include <math.h>
30 #include <svx/xpoly.hxx>
31 #include <vcl/svapp.hxx>
32 #include <editeng/eeitem.hxx>
33 #include <editeng/fhgtitem.hxx>
34 #include <editeng/wghtitem.hxx>
35 #include <editeng/postitem.hxx>
36 #include <editeng/udlnitem.hxx>
37 #include <editeng/crsditem.hxx>
38 #include <editeng/shdditem.hxx>
39 #include <svx/xlnclit.hxx>
40 #include <svx/xlncapit.hxx>
41 #include <svx/xlnwtit.hxx>
42 #include <svx/xflclit.hxx>
43 #include <svx/xgrad.hxx>
44 #include <svx/xflgrit.hxx>
45 #include <editeng/fontitem.hxx>
46 #include <editeng/akrnitem.hxx>
47 #include <editeng/wrlmitem.hxx>
48 #include <editeng/cntritem.hxx>
49 #include <editeng/colritem.hxx>
50 #include <vcl/metric.hxx>
51 #include <editeng/charscaleitem.hxx>
52 #include <svx/xflhtit.hxx>
53 #include <svx/svdattr.hxx>
54 #include <svx/svdmodel.hxx>
55 #include <svx/svdpage.hxx>
56 #include <svx/svdobj.hxx>
57 #include "svx/svditext.hxx"
58 #include <svx/svdotext.hxx>
59 #include <svx/svdorect.hxx>
60 #include <svx/svdocirc.hxx>
61 #include <svx/svdograf.hxx>
62 #include <svx/svdopath.hxx>
63 #include <svx/svdetc.hxx>
64 #include <svl/itemset.hxx>
65 #include <basegfx/polygon/b2dpolygon.hxx>
66 #include <vcl/salbtype.hxx>     // FRound
67 #include <basegfx/matrix/b2dhommatrix.hxx>
68 #include <basegfx/matrix/b2dhommatrixtools.hxx>
69 #include <svx/xlinjoit.hxx>
70 #include <svx/xlndsit.hxx>
71 #include <basegfx/polygon/b2dpolygonclipper.hxx>
72 #include <svx/xbtmpit.hxx>
73 #include <svx/xfltrit.hxx>
74 #include <vcl/bmpacc.hxx>
75 #include <svx/xflbmtit.hxx>
76 #include <svx/xflbstit.hxx>
77 #include <svx/svdpntv.hxx>
78 
79 ////////////////////////////////////////////////////////////////////////////////////////////////////
80 
81 ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
82     SdrModel& rModel,
83     SdrLayerID nLay,
84     const Rectangle& rRect)
85 :   maTmpList(),
86     maVD(),
87     maScaleRect(rRect),
88     mnMapScalingOfs(0),
89     mpLineAttr(0),
90     mpFillAttr(0),
91     mpTextAttr(0),
92     mpModel(&rModel),
93     mnLayer(nLay),
94     maOldLineColor(),
95     mnLineWidth(0),
96     maLineJoin(basegfx::B2DLINEJOIN_NONE),
97     maLineCap(com::sun::star::drawing::LineCap_BUTT),
98     maDash(XDASH_RECT, 0, 0, 0, 0, 0),
99     mbMov(false),
100     mbSize(false),
101     maOfs(0, 0),
102     mfScaleX(1.0),
103     mfScaleY(1.0),
104     maScaleX(1.0),
105     maScaleY(1.0),
106     mbFntDirty(true),
107     mbLastObjWasPolyWithoutLine(false),
108     mbNoLine(false),
109     mbNoFill(false),
110     mbLastObjWasLine(false),
111     maClip()
112 {
113     maVD.EnableOutput(false);
114     maVD.SetLineColor();
115     maVD.SetFillColor();
116     maOldLineColor.SetRed( maVD.GetLineColor().GetRed() + 1 );
117     mpLineAttr = new SfxItemSet(rModel.GetItemPool(), XATTR_LINE_FIRST, XATTR_LINE_LAST, 0, 0);
118     mpFillAttr = new SfxItemSet(rModel.GetItemPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST, 0, 0);
119     mpTextAttr = new SfxItemSet(rModel.GetItemPool(), EE_ITEMS_START, EE_ITEMS_END, 0, 0);
120     checkClip();
121 }
122 
123 ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport()
124 {
125     delete mpLineAttr;
126     delete mpFillAttr;
127     delete mpTextAttr;
128 }
129 
130 void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile& rMtf, SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
131 {
132     for( MetaAction* pAct = rMtf.FirstAction(); pAct; pAct = rMtf.NextAction() )
133     {
134         switch (pAct->GetType())
135         {
136             case META_PIXEL_ACTION          : DoAction((MetaPixelAction          &)*pAct); break;
137             case META_POINT_ACTION          : DoAction((MetaPointAction          &)*pAct); break;
138             case META_LINE_ACTION           : DoAction((MetaLineAction           &)*pAct); break;
139             case META_RECT_ACTION           : DoAction((MetaRectAction           &)*pAct); break;
140             case META_ROUNDRECT_ACTION      : DoAction((MetaRoundRectAction      &)*pAct); break;
141             case META_ELLIPSE_ACTION        : DoAction((MetaEllipseAction        &)*pAct); break;
142             case META_ARC_ACTION            : DoAction((MetaArcAction            &)*pAct); break;
143             case META_PIE_ACTION            : DoAction((MetaPieAction            &)*pAct); break;
144             case META_CHORD_ACTION          : DoAction((MetaChordAction          &)*pAct); break;
145             case META_POLYLINE_ACTION       : DoAction((MetaPolyLineAction       &)*pAct); break;
146             case META_POLYGON_ACTION        : DoAction((MetaPolygonAction        &)*pAct); break;
147             case META_POLYPOLYGON_ACTION    : DoAction((MetaPolyPolygonAction    &)*pAct); break;
148             case META_TEXT_ACTION           : DoAction((MetaTextAction           &)*pAct); break;
149             case META_TEXTARRAY_ACTION      : DoAction((MetaTextArrayAction      &)*pAct); break;
150             case META_STRETCHTEXT_ACTION    : DoAction((MetaStretchTextAction    &)*pAct); break;
151             case META_BMP_ACTION            : DoAction((MetaBmpAction            &)*pAct); break;
152             case META_BMPSCALE_ACTION       : DoAction((MetaBmpScaleAction       &)*pAct); break;
153             case META_BMPEX_ACTION          : DoAction((MetaBmpExAction          &)*pAct); break;
154             case META_BMPEXSCALE_ACTION     : DoAction((MetaBmpExScaleAction     &)*pAct); break;
155             case META_LINECOLOR_ACTION      : DoAction((MetaLineColorAction      &)*pAct); break;
156             case META_FILLCOLOR_ACTION      : DoAction((MetaFillColorAction      &)*pAct); break;
157             case META_TEXTCOLOR_ACTION      : DoAction((MetaTextColorAction      &)*pAct); break;
158             case META_TEXTFILLCOLOR_ACTION  : DoAction((MetaTextFillColorAction  &)*pAct); break;
159             case META_FONT_ACTION           : DoAction((MetaFontAction           &)*pAct); break;
160             case META_TEXTALIGN_ACTION      : DoAction((MetaTextAlignAction      &)*pAct); break;
161             case META_MAPMODE_ACTION        : DoAction((MetaMapModeAction        &)*pAct); break;
162             case META_CLIPREGION_ACTION     : DoAction((MetaClipRegionAction     &)*pAct); break;
163             case META_MOVECLIPREGION_ACTION : DoAction((MetaMoveClipRegionAction &)*pAct); break;
164             case META_ISECTRECTCLIPREGION_ACTION: DoAction((MetaISectRectClipRegionAction&)*pAct); break;
165             case META_ISECTREGIONCLIPREGION_ACTION: DoAction((MetaISectRegionClipRegionAction&)*pAct); break;
166             case META_RASTEROP_ACTION       : DoAction((MetaRasterOpAction       &)*pAct); break;
167             case META_PUSH_ACTION           : DoAction((MetaPushAction           &)*pAct); break;
168             case META_POP_ACTION            : DoAction((MetaPopAction            &)*pAct); break;
169             case META_HATCH_ACTION          : DoAction((MetaHatchAction          &)*pAct); break;
170             case META_COMMENT_ACTION        : DoAction((MetaCommentAction        &)*pAct, &rMtf); break;
171 
172             // missing actions added
173             case META_TEXTRECT_ACTION       : DoAction((MetaTextRectAction&)*pAct); break;
174             case META_BMPSCALEPART_ACTION   : DoAction((MetaBmpScalePartAction&)*pAct); break;
175             case META_BMPEXSCALEPART_ACTION : DoAction((MetaBmpExScalePartAction&)*pAct); break;
176             case META_MASK_ACTION           : DoAction((MetaMaskAction&)*pAct); break;
177             case META_MASKSCALE_ACTION      : DoAction((MetaMaskScaleAction&)*pAct); break;
178             case META_MASKSCALEPART_ACTION  : DoAction((MetaMaskScalePartAction&)*pAct); break;
179             case META_GRADIENT_ACTION       : DoAction((MetaGradientAction&)*pAct); break;
180             case META_WALLPAPER_ACTION      : DoAction((MetaWallpaperAction&)*pAct); break;
181             case META_TRANSPARENT_ACTION    : DoAction((MetaTransparentAction&)*pAct); break;
182             case META_EPS_ACTION            : DoAction((MetaEPSAction&)*pAct); break;
183             case META_REFPOINT_ACTION       : DoAction((MetaRefPointAction&)*pAct); break;
184             case META_TEXTLINECOLOR_ACTION  : DoAction((MetaTextLineColorAction&)*pAct); break;
185             case META_TEXTLINE_ACTION       : DoAction((MetaTextLineAction&)*pAct); break;
186             case META_FLOATTRANSPARENT_ACTION : DoAction((MetaFloatTransparentAction&)*pAct); break;
187             case META_GRADIENTEX_ACTION     : DoAction((MetaGradientExAction&)*pAct); break;
188             case META_LAYOUTMODE_ACTION     : DoAction((MetaLayoutModeAction&)*pAct); break;
189             case META_TEXTLANGUAGE_ACTION   : DoAction((MetaTextLanguageAction&)*pAct); break;
190             case META_OVERLINECOLOR_ACTION  : DoAction((MetaOverlineColorAction&)*pAct); break;
191         }
192 
193         if(pProgrInfo && pActionsToReport)
194         {
195             (*pActionsToReport)++;
196 
197             if(*pActionsToReport >= 16) // Alle 16 Action updaten
198             {
199                 if(!pProgrInfo->ReportActions(*pActionsToReport))
200                     break;
201 
202                 *pActionsToReport = 0;
203             }
204         }
205     }
206 }
207 
208 sal_uInt32 ImpSdrGDIMetaFileImport::DoImport(
209     const GDIMetaFile& rMtf,
210     SdrObjList& rOL,
211     sal_uInt32 nInsPos,
212     SvdProgressInfo* pProgrInfo)
213 {
214     // setup some global scale parameter
215     // mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
216     mfScaleX = mfScaleY = 1.0;
217     const Size aMtfSize(rMtf.GetPrefSize());
218 
219     if(aMtfSize.Width() & aMtfSize.Height() && (!maScaleRect.IsEmpty()))
220     {
221         maOfs = maScaleRect.TopLeft();
222 
223         if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
224         {
225             mfScaleX = (double)( maScaleRect.GetWidth() - 1 ) / (double)aMtfSize.Width();
226         }
227 
228         if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
229         {
230             mfScaleY = (double)( maScaleRect.GetHeight() - 1 ) / (double)aMtfSize.Height();
231         }
232     }
233 
234     mbMov = maOfs.X()!=0 || maOfs.Y()!=0;
235     mbSize = false;
236     maScaleX = Fraction( 1, 1 );
237     maScaleY = Fraction( 1, 1 );
238 
239     if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
240     {
241         maScaleX = Fraction(maScaleRect.GetWidth() - 1, aMtfSize.Width());
242         mbSize = true;
243     }
244 
245     if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
246     {
247         maScaleY = Fraction(maScaleRect.GetHeight() - 1, aMtfSize.Height());
248         mbSize = true;
249     }
250 
251     if(pProgrInfo)
252     {
253         pProgrInfo->SetActionCount(rMtf.GetActionCount());
254     }
255 
256     sal_uInt32 nActionsToReport(0);
257 
258     // execute
259     DoLoopActions(const_cast< GDIMetaFile& >(rMtf), pProgrInfo, &nActionsToReport);
260 
261     if(pProgrInfo)
262     {
263         pProgrInfo->ReportActions(nActionsToReport);
264         nActionsToReport = 0;
265     }
266 
267     // MapMode-Scaling  vornehmen
268     MapScaling();
269 
270     // Beim berechnen der Fortschrittsanzeige wird GetActionCount()*3 benutzt.
271     // Da in maTmpList allerdings weniger eintraege als GetActionCount()
272     // existieren koennen, muessen hier die zuviel vermuteten Actionen wieder
273     // hinzugefuegt werden.
274     nActionsToReport = (rMtf.GetActionCount() - maTmpList.size()) * 2;
275 
276     // Alle noch nicht gemeldeten Rescales melden
277     if(pProgrInfo)
278     {
279         pProgrInfo->ReportRescales(nActionsToReport);
280         pProgrInfo->SetInsertCount(maTmpList.size());
281     }
282 
283     nActionsToReport = 0;
284 
285     // alle in maTmpList zwischengespeicherten Objekte nun in rOL ab der Position nInsPos einfuegen
286     if(nInsPos > rOL.GetObjCount())
287     {
288         nInsPos = rOL.GetObjCount();
289     }
290 
291     SdrInsertReason aReason(SDRREASON_VIEWCALL);
292 
293     for(sal_uInt32 i(0); i < maTmpList.size(); i++)
294     {
295         SdrObject* pObj = maTmpList[i];
296         rOL.NbcInsertObject(pObj, nInsPos, &aReason);
297         nInsPos++;
298 
299         if(pProgrInfo)
300         {
301             nActionsToReport++;
302 
303             if(nActionsToReport >= 32) // Alle 32 Action updaten
304             {
305                 pProgrInfo->ReportInserts(nActionsToReport);
306                 nActionsToReport = 0;
307             }
308         }
309     }
310 
311     // ein letztesmal alle verbliebennen Inserts reporten
312     if(pProgrInfo)
313     {
314         pProgrInfo->ReportInserts(nActionsToReport);
315     }
316 
317     return maTmpList.size();
318 }
319 
320 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr)
321 {
322     mbNoLine = false;
323     mbNoFill = false;
324     bool bLine(!bForceTextAttr);
325     bool bFill(!pObj || (pObj->IsClosedObj() && !bForceTextAttr));
326     bool bText(bForceTextAttr || (pObj && pObj->GetOutlinerParaObject()));
327 
328     if(bLine)
329     {
330         if(mnLineWidth)
331         {
332             mpLineAttr->Put(XLineWidthItem(mnLineWidth));
333         }
334         else
335         {
336             mpLineAttr->Put(XLineWidthItem(0));
337         }
338 
339         maOldLineColor = maVD.GetLineColor();
340 
341         if(maVD.IsLineColor())
342         {
343             mpLineAttr->Put(XLineStyleItem(XLINE_SOLID));
344             mpLineAttr->Put(XLineColorItem(String(), maVD.GetLineColor()));
345         }
346         else
347         {
348             mpLineAttr->Put(XLineStyleItem(XLINE_NONE));
349         }
350 
351         switch(maLineJoin)
352         {
353             default : // basegfx::B2DLINEJOIN_NONE
354                 mpLineAttr->Put(XLineJointItem(XLINEJOINT_NONE));
355                 break;
356             case basegfx::B2DLINEJOIN_MIDDLE:
357                 mpLineAttr->Put(XLineJointItem(XLINEJOINT_MIDDLE));
358                 break;
359             case basegfx::B2DLINEJOIN_BEVEL:
360                 mpLineAttr->Put(XLineJointItem(XLINEJOINT_BEVEL));
361                 break;
362             case basegfx::B2DLINEJOIN_MITER:
363                 mpLineAttr->Put(XLineJointItem(XLINEJOINT_MITER));
364                 break;
365             case basegfx::B2DLINEJOIN_ROUND:
366                 mpLineAttr->Put(XLineJointItem(XLINEJOINT_ROUND));
367                 break;
368         }
369 
370         // Add LineCap support
371         mpLineAttr->Put(XLineCapItem(maLineCap));
372 
373         if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance())
374         {
375             mpLineAttr->Put(XLineDashItem(String(), maDash));
376         }
377         else
378         {
379             mpLineAttr->Put(XLineDashItem(String(), XDash(XDASH_RECT)));
380         }
381     }
382     else
383     {
384         mbNoLine = true;
385     }
386 
387     if(bFill)
388     {
389         if(maVD.IsFillColor())
390         {
391             mpFillAttr->Put(XFillStyleItem(XFILL_SOLID));
392             mpFillAttr->Put(XFillColorItem(String(), maVD.GetFillColor()));
393         }
394         else
395         {
396             mpFillAttr->Put(XFillStyleItem(XFILL_NONE));
397         }
398     }
399     else
400     {
401         mbNoFill = true;
402     }
403 
404     if(bText && mbFntDirty)
405     {
406         Font aFnt(maVD.GetFont());
407         const sal_uInt32 nHeight(FRound(aFnt.GetSize().Height() * mfScaleY));
408 
409         mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
410         mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
411         mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) );
412         mpTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC));
413         mpTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT));
414         mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
415         mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
416         mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
417         mpTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
418         mpTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
419         mpTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
420         mpTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
421         mpTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
422 
423         // #i118485# Setting this item leads to problems (written #i118498# for this)
424         // mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
425 
426         mpTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
427         mpTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
428         mpTextAttr->Put(SvxColorItem(maVD.GetTextColor(), EE_CHAR_COLOR));
429         //... svxfont textitem svditext
430         mbFntDirty = false;
431     }
432 
433     if(pObj)
434     {
435         pObj->SetLayer(mnLayer);
436 
437         if(bLine)
438         {
439             pObj->SetMergedItemSet(*mpLineAttr);
440         }
441 
442         if(bFill)
443         {
444             pObj->SetMergedItemSet(*mpFillAttr);
445         }
446 
447         if(bText)
448         {
449             pObj->SetMergedItemSet(*mpTextAttr);
450             pObj->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
451         }
452     }
453 }
454 
455 void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj, bool bScale)
456 {
457     if(bScale && !maScaleRect.IsEmpty())
458     {
459         if(mbSize)
460         {
461             pObj->NbcResize(Point(), maScaleX, maScaleY);
462         }
463 
464         if(mbMov)
465         {
466             pObj->NbcMove(Size(maOfs.X(), maOfs.Y()));
467         }
468     }
469 
470     if(isClip())
471     {
472         const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
473         const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
474         const SdrLayerID aOldLayer(pObj->GetLayer());
475         const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
476         const SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
477         BitmapEx aBitmapEx;
478 
479         if(pSdrGrafObj)
480         {
481             aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
482         }
483 
484         SdrObject::Free(pObj);
485 
486         if(!aOldRange.isEmpty())
487         {
488             // clip against ClipRegion
489             const basegfx::B2DPolyPolygon aNewPoly(
490                 basegfx::tools::clipPolyPolygonOnPolyPolygon(
491                     aPoly,
492                     maClip,
493                     true,
494                     aPoly.isClosed() ? false : true));
495             const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
496 
497             if(!aNewRange.isEmpty())
498             {
499                 pObj = new SdrPathObj(
500                     aNewPoly.isClosed() ? OBJ_POLY : OBJ_PLIN,
501                     aNewPoly);
502 
503                 pObj->SetLayer(aOldLayer);
504                 pObj->SetMergedItemSet(aOldItemSet);
505 
506                 if(!!aBitmapEx)
507                 {
508                     // aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
509                     const double fScaleX(aBitmapEx.GetSizePixel().Width() / (aOldRange.getWidth() ? aOldRange.getWidth() : 1.0));
510                     const double fScaleY(aBitmapEx.GetSizePixel().Height() / (aOldRange.getHeight() ? aOldRange.getHeight() : 1.0));
511                     basegfx::B2DRange aPixel(aNewRange);
512                     basegfx::B2DHomMatrix aTrans;
513 
514                     aTrans.translate(-aOldRange.getMinX(), -aOldRange.getMinY());
515                     aTrans.scale(fScaleX, fScaleY);
516                     aPixel.transform(aTrans);
517 
518                     const BitmapEx aClippedBitmap(
519                         aBitmapEx,
520                         Point(floor(std::max(0.0, aPixel.getMinX())), floor(std::max(0.0, aPixel.getMinY()))),
521                         Size(ceil(aPixel.getWidth()), ceil(aPixel.getHeight())));
522 
523                     pObj->SetMergedItem(XFillStyleItem(XFILL_BITMAP));
524                     pObj->SetMergedItem(XFillBitmapItem(String(), Graphic(aClippedBitmap)));
525                     pObj->SetMergedItem(XFillBmpTileItem(false));
526                     pObj->SetMergedItem(XFillBmpStretchItem(true));
527                 }
528             }
529         }
530     }
531 
532     if(pObj)
533     {
534         // #i111954# check object for visibility
535         // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
536         bool bVisible(false);
537 
538         if(pObj->HasLineStyle())
539         {
540             bVisible = true;
541         }
542 
543         if(!bVisible && pObj->HasFillStyle())
544         {
545             bVisible = true;
546         }
547 
548         if(!bVisible)
549         {
550             SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >(pObj);
551 
552             if(pTextObj && pTextObj->HasText())
553             {
554                 bVisible = true;
555             }
556         }
557 
558         if(!bVisible)
559         {
560             SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
561 
562             if(pGrafObj)
563             {
564                 // this may be refined to check if the graphic really is visible. It
565                 // is here to ensure that graphic objects without fill, line and text
566                 // get created
567                 bVisible = true;
568             }
569         }
570 
571         if(!bVisible)
572         {
573             SdrObject::Free(pObj);
574         }
575         else
576         {
577             maTmpList.push_back(pObj);
578 
579             if(dynamic_cast< SdrPathObj* >(pObj))
580             {
581                 const bool bClosed(pObj->IsClosedObj());
582 
583                 mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
584                 mbLastObjWasLine = !bClosed;
585             }
586             else
587             {
588                 mbLastObjWasPolyWithoutLine = false;
589                 mbLastObjWasLine = false;
590             }
591         }
592     }
593 }
594 
595 /**************************************************************************************************/
596 
597 void ImpSdrGDIMetaFileImport::DoAction(MetaPixelAction& /*rAct*/)
598 {
599 }
600 
601 void ImpSdrGDIMetaFileImport::DoAction(MetaPointAction& /*rAct*/)
602 {
603 }
604 
605 void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction& rAct)
606 {
607     // #i73407# reformulation to use new B2DPolygon classes
608     const basegfx::B2DPoint aStart(rAct.GetStartPoint().X(), rAct.GetStartPoint().Y());
609     const basegfx::B2DPoint aEnd(rAct.GetEndPoint().X(), rAct.GetEndPoint().Y());
610 
611     if(!aStart.equal(aEnd))
612     {
613         basegfx::B2DPolygon aLine;
614         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
615 
616         aLine.append(aStart);
617         aLine.append(aEnd);
618         aLine.transform(aTransform);
619 
620         const LineInfo& rLineInfo = rAct.GetLineInfo();
621         const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
622         bool bCreateLineObject(true);
623 
624         if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aLine))
625         {
626             bCreateLineObject = false;
627         }
628 
629         if(bCreateLineObject)
630         {
631             SdrPathObj* pPath = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aLine));
632             mnLineWidth = nNewLineWidth;
633             maLineJoin = rLineInfo.GetLineJoin();
634             maLineCap = rLineInfo.GetLineCap();
635             maDash = XDash(XDASH_RECT,
636                 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
637                 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
638                 rLineInfo.GetDistance());
639             SetAttributes(pPath);
640             mnLineWidth = 0;
641             maLineJoin = basegfx::B2DLINEJOIN_NONE;
642             maDash = XDash();
643             InsertObj(pPath, false);
644         }
645     }
646 }
647 
648 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction& rAct)
649 {
650     SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
651     SetAttributes(pRect);
652     InsertObj(pRect);
653 }
654 
655 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction& rAct)
656 {
657     SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
658     SetAttributes(pRect);
659     long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
660     if (nRad!=0) {
661         SfxItemSet aSet(*mpLineAttr->GetPool(), SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS, 0, 0);
662         aSet.Put(SdrEckenradiusItem(nRad));
663         pRect->SetMergedItemSet(aSet);
664     }
665     InsertObj(pRect);
666 }
667 
668 /**************************************************************************************************/
669 
670 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction& rAct)
671 {
672     SdrCircObj* pCirc=new SdrCircObj(OBJ_CIRC,rAct.GetRect());
673     SetAttributes(pCirc);
674     InsertObj(pCirc);
675 }
676 
677 void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction& rAct)
678 {
679     Point aCenter(rAct.GetRect().Center());
680     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
681     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
682     SdrCircObj* pCirc=new SdrCircObj(OBJ_CARC,rAct.GetRect(),nStart,nEnd);
683     SetAttributes(pCirc);
684     InsertObj(pCirc);
685 }
686 
687 void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction& rAct)
688 {
689     Point aCenter(rAct.GetRect().Center());
690     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
691     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
692     SdrCircObj* pCirc=new SdrCircObj(OBJ_SECT,rAct.GetRect(),nStart,nEnd);
693     SetAttributes(pCirc);
694     InsertObj(pCirc);
695 }
696 
697 void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction& rAct)
698 {
699     Point aCenter(rAct.GetRect().Center());
700     long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
701     long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
702     SdrCircObj* pCirc=new SdrCircObj(OBJ_CCUT,rAct.GetRect(),nStart,nEnd);
703     SetAttributes(pCirc);
704     InsertObj(pCirc);
705 }
706 
707 /**************************************************************************************************/
708 
709 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
710 {
711     // #i102706# Do not merge closed polygons
712     if(rSrcPoly.isClosed())
713     {
714         return false;
715     }
716 
717     // #i73407# reformulation to use new B2DPolygon classes
718     if(mbLastObjWasLine && (maOldLineColor == maVD.GetLineColor()) && rSrcPoly.count())
719     {
720         SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : 0;
721         SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
722 
723         if(pLastPoly)
724         {
725             if(1L == pLastPoly->GetPathPoly().count())
726             {
727                 bool bOk(false);
728                 basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0L));
729 
730                 // #i102706# Do not merge closed polygons
731                 if(aDstPoly.isClosed())
732                 {
733                     return false;
734                 }
735 
736                 if(aDstPoly.count())
737                 {
738                     const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1L);
739                     const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1L);
740 
741                     if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0L))
742                     {
743                         aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
744                         bOk = true;
745                     }
746                     else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
747                     {
748                         basegfx::B2DPolygon aNew(rSrcPoly);
749                         aNew.append(aDstPoly, 1L, aDstPoly.count() - 1L);
750                         aDstPoly = aNew;
751                         bOk = true;
752                     }
753                     else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(0L))
754                     {
755                         aDstPoly.flip();
756                         aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
757                         bOk = true;
758                     }
759                     else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
760                     {
761                         basegfx::B2DPolygon aNew(rSrcPoly);
762                         aNew.flip();
763                         aDstPoly.append(aNew, 1L, aNew.count() - 1L);
764                         bOk = true;
765                     }
766                 }
767 
768                 if(bOk)
769                 {
770                     pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
771                 }
772 
773                 return bOk;
774             }
775         }
776     }
777 
778     return false;
779 }
780 
781 bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
782 {
783     // #i73407# reformulation to use new B2DPolygon classes
784     if(mbLastObjWasPolyWithoutLine)
785     {
786         SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : 0;
787         SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
788 
789         if(pLastPoly)
790         {
791             if(pLastPoly->GetPathPoly() == rPolyPolygon)
792             {
793                 SetAttributes(NULL);
794 
795                 if(!mbNoLine && mbNoFill)
796                 {
797                     pLastPoly->SetMergedItemSet(*mpLineAttr);
798 
799                     return true;
800                 }
801             }
802         }
803     }
804 
805     return false;
806 }
807 
808 void ImpSdrGDIMetaFileImport::checkClip()
809 {
810     if(maVD.IsClipRegion())
811     {
812         maClip = maVD.GetClipRegion().GetAsB2DPolyPolygon();
813 
814         if(isClip())
815         {
816             const basegfx::B2DHomMatrix aTransform(
817                 basegfx::tools::createScaleTranslateB2DHomMatrix(
818                     mfScaleX,
819                     mfScaleY,
820                     maOfs.X(),
821                     maOfs.Y()));
822 
823             maClip.transform(aTransform);
824         }
825     }
826 }
827 
828 bool ImpSdrGDIMetaFileImport::isClip() const
829 {
830     return !maClip.getB2DRange().isEmpty();
831 }
832 
833 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct )
834 {
835     // #i73407# reformulation to use new B2DPolygon classes
836     basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
837 
838     if(aSource.count())
839     {
840         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
841         aSource.transform(aTransform);
842     }
843 
844     const LineInfo& rLineInfo = rAct.GetLineInfo();
845     const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
846     bool bCreateLineObject(true);
847 
848     if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aSource))
849     {
850         bCreateLineObject = false;
851     }
852     else if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
853     {
854         bCreateLineObject = false;
855     }
856 
857     if(bCreateLineObject)
858     {
859         SdrPathObj* pPath = new SdrPathObj(
860             aSource.isClosed() ? OBJ_POLY : OBJ_PLIN,
861             basegfx::B2DPolyPolygon(aSource));
862         mnLineWidth = nNewLineWidth;
863         maLineJoin = rLineInfo.GetLineJoin();
864         maLineCap = rLineInfo.GetLineCap();
865         maDash = XDash(XDASH_RECT,
866             rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
867             rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
868             rLineInfo.GetDistance());
869         SetAttributes(pPath);
870         mnLineWidth = 0;
871         maLineJoin = basegfx::B2DLINEJOIN_NONE;
872         maDash = XDash();
873         InsertObj(pPath, false);
874     }
875 }
876 
877 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct )
878 {
879     // #i73407# reformulation to use new B2DPolygon classes
880     basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
881 
882     if(aSource.count())
883     {
884         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
885         aSource.transform(aTransform);
886 
887         if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
888         {
889             // #i73407# make sure polygon is closed, it's a filled primitive
890             aSource.setClosed(true);
891             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource));
892             SetAttributes(pPath);
893             InsertObj(pPath, false);
894         }
895     }
896 }
897 
898 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct)
899 {
900     // #i73407# reformulation to use new B2DPolygon classes
901     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
902 
903     if(aSource.count())
904     {
905         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
906         aSource.transform(aTransform);
907 
908         if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
909         {
910             // #i73407# make sure polygon is closed, it's a filled primitive
911             aSource.setClosed(true);
912             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
913             SetAttributes(pPath);
914             InsertObj(pPath, false);
915         }
916     }
917 }
918 
919 /**************************************************************************************************/
920 
921 void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct )
922 {
923     // calc text box size, add 5% to make it fit safely
924 
925     FontMetric aFontMetric( maVD.GetFontMetric() );
926     Font aFnt( maVD.GetFont() );
927     FontAlign eAlg( aFnt.GetAlign() );
928 
929     sal_Int32 nTextWidth = (sal_Int32)( maVD.GetTextWidth( rStr ) * mfScaleX );
930     sal_Int32 nTextHeight = (sal_Int32)( maVD.GetTextHeight() * mfScaleY );
931     //sal_Int32 nDxWidth = 0;
932     //sal_Int32 nLen = rStr.Len();
933 
934     Point aPos( FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()) );
935     Size aSize( nTextWidth, nTextHeight );
936 
937     if ( eAlg == ALIGN_BASELINE )
938         aPos.Y() -= FRound(aFontMetric.GetAscent() * mfScaleY);
939     else if ( eAlg == ALIGN_BOTTOM )
940         aPos.Y() -= nTextHeight;
941 
942     Rectangle aTextRect( aPos, aSize );
943     SdrRectObj* pText =new SdrRectObj( OBJ_TEXT, aTextRect );
944 
945     if ( aFnt.GetWidth() || ( rAct.GetType() == META_STRETCHTEXT_ACTION ) )
946     {
947         pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
948         pText->SetMergedItem( SdrTextAutoGrowHeightItem( false ) );
949         // don't let the margins eat the space needed for the text
950         pText->SetMergedItem ( SdrTextUpperDistItem (0));
951         pText->SetMergedItem ( SdrTextLowerDistItem (0));
952         pText->SetMergedItem ( SdrTextRightDistItem (0));
953         pText->SetMergedItem ( SdrTextLeftDistItem (0));
954         pText->SetMergedItem( SdrTextFitToSizeTypeItem( SDRTEXTFIT_ALLLINES ) );
955     }
956     else
957         pText->SetMergedItem( SdrTextAutoGrowWidthItem( true ) );
958 
959     pText->SetModel(mpModel);
960     pText->SetLayer(mnLayer);
961     pText->NbcSetText( rStr );
962     SetAttributes( pText, true );
963     pText->SetSnapRect( aTextRect );
964 
965     if (!aFnt.IsTransparent())
966     {
967         SfxItemSet aAttr(*mpFillAttr->GetPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST, 0, 0);
968         aAttr.Put(XFillStyleItem(XFILL_SOLID));
969         aAttr.Put(XFillColorItem(String(), aFnt.GetFillColor()));
970         pText->SetMergedItemSet(aAttr);
971     }
972     sal_uInt32 nWink = aFnt.GetOrientation();
973     if ( nWink )
974     {
975         nWink*=10;
976         double a=nWink*nPi180;
977         double nSin=sin(a);
978         double nCos=cos(a);
979         pText->NbcRotate(aPos,nWink,nSin,nCos);
980     }
981     InsertObj( pText, false );
982 }
983 
984 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction& rAct)
985 {
986     XubString aStr(rAct.GetText());
987     aStr.Erase(0,rAct.GetIndex());
988     aStr.Erase(rAct.GetLen());
989     ImportText( rAct.GetPoint(), aStr, rAct );
990 }
991 
992 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction& rAct)
993 {
994     XubString aStr(rAct.GetText());
995     aStr.Erase(0,rAct.GetIndex());
996     aStr.Erase(rAct.GetLen());
997     ImportText( rAct.GetPoint(), aStr, rAct );
998 }
999 
1000 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction& rAct)
1001 {
1002     XubString aStr(rAct.GetText());
1003     aStr.Erase(0,rAct.GetIndex());
1004     aStr.Erase(rAct.GetLen());
1005     ImportText( rAct.GetPoint(), aStr, rAct );
1006 }
1007 
1008 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction& rAct)
1009 {
1010     Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
1011     aRect.Right()++; aRect.Bottom()++;
1012     SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
1013     InsertObj(pGraf);
1014 }
1015 
1016 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction& rAct)
1017 {
1018     Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1019     aRect.Right()++; aRect.Bottom()++;
1020     SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
1021     InsertObj(pGraf);
1022 }
1023 
1024 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction& rAct)
1025 {
1026     Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
1027     aRect.Right()++; aRect.Bottom()++;
1028     SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
1029     InsertObj(pGraf);
1030 }
1031 
1032 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction& rAct)
1033 {
1034     Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1035     aRect.Right()++; aRect.Bottom()++;
1036     SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
1037     InsertObj(pGraf);
1038 }
1039 
1040 ////////////////////////////////////////////////////////////////////////////////////////////////////
1041 
1042 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction& rAct )
1043 {
1044     // #i73407# reformulation to use new B2DPolygon classes
1045     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1046 
1047     if(aSource.count())
1048     {
1049         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1050         aSource.transform(aTransform);
1051 
1052         if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1053         {
1054             const Hatch& rHatch = rAct.GetHatch();
1055             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1056             SfxItemSet aHatchAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLHATCH, XATTR_FILLHATCH, 0, 0);
1057             XHatchStyle eStyle;
1058 
1059             switch(rHatch.GetStyle())
1060             {
1061                 case(HATCH_TRIPLE) :
1062                 {
1063                     eStyle = XHATCH_TRIPLE;
1064                     break;
1065                 }
1066 
1067                 case(HATCH_DOUBLE) :
1068                 {
1069                     eStyle = XHATCH_DOUBLE;
1070                     break;
1071                 }
1072 
1073                 default:
1074                 {
1075                     eStyle = XHATCH_SINGLE;
1076                     break;
1077                 }
1078             }
1079 
1080             SetAttributes(pPath);
1081             aHatchAttr.Put(XFillStyleItem(XFILL_HATCH));
1082             aHatchAttr.Put(XFillHatchItem(&mpModel->GetItemPool(), XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
1083             pPath->SetMergedItemSet(aHatchAttr);
1084 
1085             InsertObj(pPath, false);
1086         }
1087     }
1088 }
1089 
1090 ////////////////////////////////////////////////////////////////////////////////////////////////////
1091 
1092 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
1093 {
1094     rAct.Execute(&maVD);
1095 }
1096 
1097 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
1098 {
1099     MapScaling();
1100     rAct.Execute(&maVD);
1101     mbLastObjWasPolyWithoutLine = false;
1102     mbLastObjWasLine = false;
1103 }
1104 
1105 void ImpSdrGDIMetaFileImport::MapScaling()
1106 {
1107     const sal_uInt32 nAnz(maTmpList.size());
1108     sal_uInt32 i(0);
1109     const MapMode& rMap = maVD.GetMapMode();
1110     Point aMapOrg( rMap.GetOrigin() );
1111     bool bMov2(aMapOrg.X() != 0 || aMapOrg.Y() != 0);
1112 
1113     if(bMov2)
1114     {
1115         for(i = mnMapScalingOfs; i < nAnz; i++)
1116         {
1117             SdrObject* pObj = maTmpList[i];
1118 
1119             pObj->NbcMove(Size(aMapOrg.X(), aMapOrg.Y()));
1120         }
1121     }
1122 
1123     mnMapScalingOfs = nAnz;
1124 }
1125 
1126 ////////////////////////////////////////////////////////////////////////////////////////////////////
1127 
1128 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction& rAct, GDIMetaFile* pMtf )
1129 {
1130     ByteString aSkipComment;
1131 
1132     if( rAct.GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1133     {
1134         MetaGradientExAction* pAct = (MetaGradientExAction*) pMtf->NextAction();
1135 
1136         if( pAct && pAct->GetType() == META_GRADIENTEX_ACTION )
1137         {
1138             // #i73407# reformulation to use new B2DPolygon classes
1139             basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
1140 
1141             if(aSource.count())
1142             {
1143                 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1144                 {
1145                     const Gradient& rGrad = pAct->GetGradient();
1146                     SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1147                     SfxItemSet aGradAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
1148                     XGradient aXGradient;
1149 
1150                     aXGradient.SetGradientStyle((XGradientStyle)rGrad.GetStyle());
1151                     aXGradient.SetStartColor(rGrad.GetStartColor());
1152                     aXGradient.SetEndColor(rGrad.GetEndColor());
1153                     aXGradient.SetAngle((sal_uInt16)rGrad.GetAngle());
1154                     aXGradient.SetBorder(rGrad.GetBorder());
1155                     aXGradient.SetXOffset(rGrad.GetOfsX());
1156                     aXGradient.SetYOffset(rGrad.GetOfsY());
1157                     aXGradient.SetStartIntens(rGrad.GetStartIntensity());
1158                     aXGradient.SetEndIntens(rGrad.GetEndIntensity());
1159                     aXGradient.SetSteps(rGrad.GetSteps());
1160 
1161                     if(maVD.IsLineColor())
1162                     {
1163                         // switch line off; when there was one there will be a
1164                         // META_POLYLINE_ACTION following creating another object
1165                         const Color aLineColor(maVD.GetLineColor());
1166                         maVD.SetLineColor();
1167                         SetAttributes(pPath);
1168                         maVD.SetLineColor(aLineColor);
1169                     }
1170                     else
1171                     {
1172                         SetAttributes(pPath);
1173                     }
1174 
1175                     aGradAttr.Put(XFillStyleItem(XFILL_GRADIENT));
1176                     aGradAttr.Put(XFillGradientItem(&mpModel->GetItemPool(), aXGradient));
1177                     pPath->SetMergedItemSet(aGradAttr);
1178 
1179                     InsertObj(pPath);
1180                 }
1181             }
1182 
1183             aSkipComment = "XGRAD_SEQ_END";
1184         }
1185     }
1186 
1187     if(aSkipComment.Len())
1188     {
1189         MetaAction* pSkipAct = pMtf->NextAction();
1190 
1191         while( pSkipAct
1192             && ((pSkipAct->GetType() != META_COMMENT_ACTION )
1193                 || (((MetaCommentAction*)pSkipAct)->GetComment().CompareIgnoreCaseToAscii(aSkipComment.GetBuffer()) != COMPARE_EQUAL)))
1194         {
1195             pSkipAct = pMtf->NextAction();
1196         }
1197     }
1198 }
1199 
1200 ////////////////////////////////////////////////////////////////////////////////////////////////////
1201 
1202 void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction& rAct)
1203 {
1204     GDIMetaFile aTemp;
1205 
1206     maVD.AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
1207     DoLoopActions(aTemp, 0, 0);
1208 }
1209 
1210 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction& rAct)
1211 {
1212     Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1213     Bitmap aBitmap(rAct.GetBitmap());
1214 
1215     aRect.Right()++;
1216     aRect.Bottom()++;
1217     aBitmap.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1218 
1219     SdrGrafObj* pGraf = new SdrGrafObj(aBitmap, aRect);
1220 
1221     InsertObj(pGraf);
1222 }
1223 
1224 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction& rAct)
1225 {
1226     Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
1227     BitmapEx aBitmapEx(rAct.GetBitmapEx());
1228 
1229     aRect.Right()++;
1230     aRect.Bottom()++;
1231     aBitmapEx.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1232 
1233     SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1234 
1235     InsertObj(pGraf);
1236 }
1237 
1238 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction& rAct)
1239 {
1240     Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
1241     BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1242 
1243     aRect.Right()++;
1244     aRect.Bottom()++;
1245 
1246     SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1247 
1248     InsertObj(pGraf);
1249 }
1250 
1251 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction& rAct)
1252 {
1253     Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
1254     BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1255 
1256     aRect.Right()++;
1257     aRect.Bottom()++;
1258 
1259     SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1260 
1261     InsertObj(pGraf);
1262 }
1263 
1264 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction& rAct)
1265 {
1266     Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1267     BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1268 
1269     aRect.Right()++;
1270     aRect.Bottom()++;
1271     aBitmapEx.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1272 
1273     SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1274 
1275     InsertObj(pGraf);
1276 }
1277 
1278 XGradientStyle getXGradientStyleFromGradientStyle(const GradientStyle& rGradientStyle)
1279 {
1280     XGradientStyle aXGradientStyle(XGRAD_LINEAR);
1281 
1282     switch(rGradientStyle)
1283     {
1284         case GRADIENT_LINEAR: aXGradientStyle = XGRAD_LINEAR; break;
1285         case GRADIENT_AXIAL: aXGradientStyle = XGRAD_AXIAL; break;
1286         case GRADIENT_RADIAL: aXGradientStyle = XGRAD_RADIAL; break;
1287         case GRADIENT_ELLIPTICAL: aXGradientStyle = XGRAD_ELLIPTICAL; break;
1288         case GRADIENT_SQUARE: aXGradientStyle = XGRAD_SQUARE; break;
1289         case GRADIENT_RECT: aXGradientStyle = XGRAD_RECT; break;
1290 
1291         // Needed due to GRADIENT_FORCE_EQUAL_SIZE; this again is needed
1292         // to force the enum defines in VCL to a defined size for the compilers,
1293         // so despite it is never used it cannot be removed (would break the
1294         // API implementation probably).
1295         default: break;
1296     }
1297 
1298     return aXGradientStyle;
1299 }
1300 
1301 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction& rAct)
1302 {
1303     basegfx::B2DRange aRange(rAct.GetRect().Left(), rAct.GetRect().Top(), rAct.GetRect().Right(), rAct.GetRect().Bottom());
1304 
1305     if(!aRange.isEmpty())
1306     {
1307         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1308         aRange.transform(aTransform);
1309         const Gradient& rGradient = rAct.GetGradient();
1310         SdrRectObj* pRect = new SdrRectObj(
1311             Rectangle(
1312                 floor(aRange.getMinX()),
1313                 floor(aRange.getMinY()),
1314                 ceil(aRange.getMaxX()),
1315                 ceil(aRange.getMaxY())));
1316         SfxItemSet aGradientAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
1317         const XGradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1318         const XFillGradientItem aXFillGradientItem(
1319             &mpModel->GetItemPool(),
1320             XGradient(
1321                 rGradient.GetStartColor(),
1322                 rGradient.GetEndColor(),
1323                 aXGradientStyle,
1324                 rGradient.GetAngle(),
1325                 rGradient.GetOfsX(),
1326                 rGradient.GetOfsY(),
1327                 rGradient.GetBorder(),
1328                 rGradient.GetStartIntensity(),
1329                 rGradient.GetEndIntensity(),
1330                 rGradient.GetSteps()));
1331 
1332         SetAttributes(pRect);
1333         aGradientAttr.Put(XFillStyleItem(XFILL_HATCH));
1334         aGradientAttr.Put(aXFillGradientItem);
1335         pRect->SetMergedItemSet(aGradientAttr);
1336 
1337         InsertObj(pRect, false);
1338     }
1339 }
1340 
1341 void ImpSdrGDIMetaFileImport::DoAction(MetaWallpaperAction& /*rAct*/)
1342 {
1343     OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)");
1344 }
1345 
1346 void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction& rAct)
1347 {
1348     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1349 
1350     if(aSource.count())
1351     {
1352         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1353         aSource.transform(aTransform);
1354         aSource.setClosed(true);
1355 
1356         SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1357         SetAttributes(pPath);
1358         pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
1359         InsertObj(pPath, false);
1360     }
1361 }
1362 
1363 void ImpSdrGDIMetaFileImport::DoAction(MetaEPSAction& /*rAct*/)
1364 {
1365     OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)");
1366 }
1367 
1368 void ImpSdrGDIMetaFileImport::DoAction(MetaTextLineAction& /*rAct*/)
1369 {
1370     OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)");
1371 }
1372 
1373 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction& rAct)
1374 {
1375     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1376 
1377     if(aSource.count())
1378     {
1379         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1380         aSource.transform(aTransform);
1381 
1382         if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1383         {
1384             const Gradient& rGradient = rAct.GetGradient();
1385             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1386             SfxItemSet aGradientAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
1387             const XGradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1388             const XFillGradientItem aXFillGradientItem(
1389                 &mpModel->GetItemPool(),
1390                 XGradient(
1391                     rGradient.GetStartColor(),
1392                     rGradient.GetEndColor(),
1393                     aXGradientStyle,
1394                     rGradient.GetAngle(),
1395                     rGradient.GetOfsX(),
1396                     rGradient.GetOfsY(),
1397                     rGradient.GetBorder(),
1398                     rGradient.GetStartIntensity(),
1399                     rGradient.GetEndIntensity(),
1400                     rGradient.GetSteps()));
1401 
1402             SetAttributes(pPath);
1403             aGradientAttr.Put(XFillStyleItem(XFILL_HATCH));
1404             aGradientAttr.Put(aXFillGradientItem);
1405             pPath->SetMergedItemSet(aGradientAttr);
1406 
1407             InsertObj(pPath, false);
1408         }
1409     }
1410 }
1411 
1412 void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction& rAct)
1413 {
1414     const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
1415 
1416     if(rMtf.GetActionCount())
1417     {
1418         const Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1419 
1420         // convert metafile sub-content to BitmapEx
1421         BitmapEx aBitmapEx(
1422             convertMetafileToBitmapEx(
1423                 rMtf,
1424                 basegfx::B2DRange(
1425                     aRect.Left(), aRect.Top(),
1426                     aRect.Right(), aRect.Bottom()),
1427                 125000));
1428 
1429         // handle colors
1430         const Gradient& rGradient = rAct.GetGradient();
1431         basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
1432         basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
1433 
1434         if(100 != rGradient.GetStartIntensity())
1435         {
1436             aStart *= (double)rGradient.GetStartIntensity() / 100.0;
1437         }
1438 
1439         if(100 != rGradient.GetEndIntensity())
1440         {
1441             aEnd *= (double)rGradient.GetEndIntensity() / 100.0;
1442         }
1443 
1444         const bool bEqualColors(aStart == aEnd);
1445         const bool bNoSteps(1 == rGradient.GetSteps());
1446         bool bCreateObject(true);
1447         bool bHasNewMask(false);
1448         AlphaMask aNewMask;
1449         double fTransparence(0.0);
1450         bool bFixedTransparence(false);
1451 
1452         if(bEqualColors || bNoSteps)
1453         {
1454             // single transparence
1455             const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
1456             fTransparence = aMedium.luminance();
1457 
1458             if(basegfx::fTools::lessOrEqual(fTransparence, 0.0))
1459             {
1460                 // no transparence needed, all done
1461             }
1462             else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
1463             {
1464                 // all transparent, no object
1465                 bCreateObject = false;
1466             }
1467             else
1468             {
1469                 // 0.0 < transparence < 1.0, apply fixed transparence
1470                 bFixedTransparence = true;
1471             }
1472         }
1473         else
1474         {
1475             // gradient transparence
1476             VirtualDevice aVDev;
1477 
1478             aVDev.SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
1479             aVDev.DrawGradient(Rectangle(Point(0, 0), aVDev.GetOutputSizePixel()), rGradient);
1480 
1481             aNewMask = AlphaMask(aVDev.GetBitmap(Point(0, 0), aVDev.GetOutputSizePixel()));
1482             bHasNewMask = true;
1483         }
1484 
1485         if(bCreateObject)
1486         {
1487             if(bHasNewMask || bFixedTransparence)
1488             {
1489                 if(!aBitmapEx.IsAlpha() && !aBitmapEx.IsTransparent())
1490                 {
1491                     // no transparence yet, apply new one
1492                     if(bFixedTransparence)
1493                     {
1494                         sal_uInt8 aAlpha(basegfx::fround(fTransparence * 255.0));
1495 
1496                         aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), &aAlpha);
1497                     }
1498 
1499                     aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
1500                 }
1501                 else
1502                 {
1503                     // mix existing and new alpha mask
1504                     AlphaMask aOldMask;
1505 
1506                     if(aBitmapEx.IsAlpha())
1507                     {
1508                         aOldMask = aBitmapEx.GetAlpha();
1509                     }
1510                     else if(TRANSPARENT_BITMAP == aBitmapEx.GetTransparentType())
1511                     {
1512                         aOldMask = aBitmapEx.GetMask();
1513                     }
1514                     else if(TRANSPARENT_COLOR == aBitmapEx.GetTransparentType())
1515                     {
1516                         aOldMask = aBitmapEx.GetBitmap().CreateMask(aBitmapEx.GetTransparentColor());
1517                     }
1518 
1519                     BitmapWriteAccess* pOld = aOldMask.AcquireWriteAccess();
1520 
1521                     if(pOld)
1522                     {
1523                         const double fFactor(1.0 / 255.0);
1524 
1525                         if(bFixedTransparence)
1526                         {
1527                             const double fOpNew(1.0 - fTransparence);
1528 
1529                             for(sal_uInt32 y(0); y < static_cast< sal_uInt32 >(pOld->Height()); y++)
1530                             {
1531                                 for(sal_uInt32 x(0); x < static_cast< sal_uInt32 >(pOld->Width()); x++)
1532                                 {
1533                                     const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1534                                     const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1535 
1536                                     pOld->SetPixel(y, x, BitmapColor(aCol));
1537                                 }
1538                             }
1539                         }
1540                         else
1541                         {
1542                             BitmapReadAccess* pNew = aNewMask.AcquireReadAccess();
1543 
1544                             if(pNew)
1545                             {
1546                                 if(pOld->Width() == pNew->Width() && pOld->Height() == pNew->Height())
1547                                 {
1548                                     for(sal_uInt32 y(0); y < static_cast< sal_uInt32 >(pOld->Height()); y++)
1549                                     {
1550                                         for(sal_uInt32 x(0); x < static_cast< sal_uInt32 >(pOld->Width()); x++)
1551                                         {
1552                                             const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1553                                             const double fOpNew(1.0 - (pNew->GetPixel(y, x).GetIndex() * fFactor));
1554                                             const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1555 
1556                                             pOld->SetPixel(y, x, BitmapColor(aCol));
1557                                         }
1558                                     }
1559                                 }
1560                                 else
1561                                 {
1562                                     OSL_ENSURE(false, "Alpha masks have different sizes (!)");
1563                                 }
1564 
1565                                 aNewMask.ReleaseAccess(pNew);
1566                             }
1567                             else
1568                             {
1569                                 OSL_ENSURE(false, "Got no access to new alpha mask (!)");
1570                             }
1571                         }
1572 
1573                         aOldMask.ReleaseAccess(pOld);
1574                     }
1575                     else
1576                     {
1577                         OSL_ENSURE(false, "Got no access to old alpha mask (!)");
1578                     }
1579 
1580                     // apply combined bitmap as mask
1581                     aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aOldMask);
1582                 }
1583             }
1584 
1585             // create and add object
1586             SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1587 
1588             InsertObj(pGraf);
1589         }
1590     }
1591 }
1592 
1593 ////////////////////////////////////////////////////////////////////////////////////////////////////
1594 // eof
1595