xref: /AOO41X/main/svx/source/svdraw/svdfmtf.cxx (revision 7b6b9ddb4b63a97ea0214b9472b5270bbf674949)
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         Region aRegion(maVD.GetClipRegion());
813 
814         maClip = aRegion.ConvertToB2DPolyPolygon();
815 
816         if(isClip())
817         {
818             const basegfx::B2DHomMatrix aTransform(
819                 basegfx::tools::createScaleTranslateB2DHomMatrix(
820                     mfScaleX,
821                     mfScaleY,
822                     maOfs.X(),
823                     maOfs.Y()));
824 
825             maClip.transform(aTransform);
826         }
827     }
828 }
829 
830 bool ImpSdrGDIMetaFileImport::isClip() const
831 {
832     return !maClip.getB2DRange().isEmpty();
833 }
834 
835 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct )
836 {
837     // #i73407# reformulation to use new B2DPolygon classes
838     basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
839 
840     if(aSource.count())
841     {
842         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
843         aSource.transform(aTransform);
844     }
845 
846     const LineInfo& rLineInfo = rAct.GetLineInfo();
847     const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
848     bool bCreateLineObject(true);
849 
850     if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aSource))
851     {
852         bCreateLineObject = false;
853     }
854     else if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
855     {
856         bCreateLineObject = false;
857     }
858 
859     if(bCreateLineObject)
860     {
861         SdrPathObj* pPath = new SdrPathObj(
862             aSource.isClosed() ? OBJ_POLY : OBJ_PLIN,
863             basegfx::B2DPolyPolygon(aSource));
864         mnLineWidth = nNewLineWidth;
865         maLineJoin = rLineInfo.GetLineJoin();
866         maLineCap = rLineInfo.GetLineCap();
867         maDash = XDash(XDASH_RECT,
868             rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
869             rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
870             rLineInfo.GetDistance());
871         SetAttributes(pPath);
872         mnLineWidth = 0;
873         maLineJoin = basegfx::B2DLINEJOIN_NONE;
874         maDash = XDash();
875         InsertObj(pPath, false);
876     }
877 }
878 
879 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct )
880 {
881     // #i73407# reformulation to use new B2DPolygon classes
882     basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
883 
884     if(aSource.count())
885     {
886         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
887         aSource.transform(aTransform);
888 
889         if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
890         {
891             // #i73407# make sure polygon is closed, it's a filled primitive
892             aSource.setClosed(true);
893             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource));
894             SetAttributes(pPath);
895             InsertObj(pPath, false);
896         }
897     }
898 }
899 
900 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct)
901 {
902     // #i73407# reformulation to use new B2DPolygon classes
903     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
904 
905     if(aSource.count())
906     {
907         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
908         aSource.transform(aTransform);
909 
910         if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
911         {
912             // #i73407# make sure polygon is closed, it's a filled primitive
913             aSource.setClosed(true);
914             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
915             SetAttributes(pPath);
916             InsertObj(pPath, false);
917         }
918     }
919 }
920 
921 /**************************************************************************************************/
922 
923 void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct )
924 {
925     // calc text box size, add 5% to make it fit safely
926 
927     FontMetric aFontMetric( maVD.GetFontMetric() );
928     Font aFnt( maVD.GetFont() );
929     FontAlign eAlg( aFnt.GetAlign() );
930 
931     sal_Int32 nTextWidth = (sal_Int32)( maVD.GetTextWidth( rStr ) * mfScaleX );
932     sal_Int32 nTextHeight = (sal_Int32)( maVD.GetTextHeight() * mfScaleY );
933     //sal_Int32 nDxWidth = 0;
934     //sal_Int32 nLen = rStr.Len();
935 
936     Point aPos( FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()) );
937     Size aSize( nTextWidth, nTextHeight );
938 
939     if ( eAlg == ALIGN_BASELINE )
940         aPos.Y() -= FRound(aFontMetric.GetAscent() * mfScaleY);
941     else if ( eAlg == ALIGN_BOTTOM )
942         aPos.Y() -= nTextHeight;
943 
944     Rectangle aTextRect( aPos, aSize );
945     SdrRectObj* pText =new SdrRectObj( OBJ_TEXT, aTextRect );
946 
947     if ( aFnt.GetWidth() || ( rAct.GetType() == META_STRETCHTEXT_ACTION ) )
948     {
949         pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
950         pText->SetMergedItem( SdrTextAutoGrowHeightItem( false ) );
951         // don't let the margins eat the space needed for the text
952         pText->SetMergedItem ( SdrTextUpperDistItem (0));
953         pText->SetMergedItem ( SdrTextLowerDistItem (0));
954         pText->SetMergedItem ( SdrTextRightDistItem (0));
955         pText->SetMergedItem ( SdrTextLeftDistItem (0));
956         pText->SetMergedItem( SdrTextFitToSizeTypeItem( SDRTEXTFIT_ALLLINES ) );
957     }
958     else
959         pText->SetMergedItem( SdrTextAutoGrowWidthItem( true ) );
960 
961     pText->SetModel(mpModel);
962     pText->SetLayer(mnLayer);
963     pText->NbcSetText( rStr );
964     SetAttributes( pText, true );
965     pText->SetSnapRect( aTextRect );
966 
967     if (!aFnt.IsTransparent())
968     {
969         SfxItemSet aAttr(*mpFillAttr->GetPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST, 0, 0);
970         aAttr.Put(XFillStyleItem(XFILL_SOLID));
971         aAttr.Put(XFillColorItem(String(), aFnt.GetFillColor()));
972         pText->SetMergedItemSet(aAttr);
973     }
974     sal_uInt32 nWink = aFnt.GetOrientation();
975     if ( nWink )
976     {
977         nWink*=10;
978         double a=nWink*nPi180;
979         double nSin=sin(a);
980         double nCos=cos(a);
981         pText->NbcRotate(aPos,nWink,nSin,nCos);
982     }
983     InsertObj( pText, false );
984 }
985 
986 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction& rAct)
987 {
988     XubString aStr(rAct.GetText());
989     aStr.Erase(0,rAct.GetIndex());
990     aStr.Erase(rAct.GetLen());
991     ImportText( rAct.GetPoint(), aStr, rAct );
992 }
993 
994 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction& rAct)
995 {
996     XubString aStr(rAct.GetText());
997     aStr.Erase(0,rAct.GetIndex());
998     aStr.Erase(rAct.GetLen());
999     ImportText( rAct.GetPoint(), aStr, rAct );
1000 }
1001 
1002 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction& rAct)
1003 {
1004     XubString aStr(rAct.GetText());
1005     aStr.Erase(0,rAct.GetIndex());
1006     aStr.Erase(rAct.GetLen());
1007     ImportText( rAct.GetPoint(), aStr, rAct );
1008 }
1009 
1010 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction& rAct)
1011 {
1012     Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
1013     aRect.Right()++; aRect.Bottom()++;
1014     SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
1015     InsertObj(pGraf);
1016 }
1017 
1018 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction& rAct)
1019 {
1020     Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1021     aRect.Right()++; aRect.Bottom()++;
1022     SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
1023     InsertObj(pGraf);
1024 }
1025 
1026 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction& rAct)
1027 {
1028     Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
1029     aRect.Right()++; aRect.Bottom()++;
1030     SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
1031     InsertObj(pGraf);
1032 }
1033 
1034 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction& rAct)
1035 {
1036     Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1037     aRect.Right()++; aRect.Bottom()++;
1038     SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
1039     InsertObj(pGraf);
1040 }
1041 
1042 ////////////////////////////////////////////////////////////////////////////////////////////////////
1043 
1044 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction& rAct )
1045 {
1046     // #i73407# reformulation to use new B2DPolygon classes
1047     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1048 
1049     if(aSource.count())
1050     {
1051         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1052         aSource.transform(aTransform);
1053 
1054         if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1055         {
1056             const Hatch& rHatch = rAct.GetHatch();
1057             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1058             SfxItemSet aHatchAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLHATCH, XATTR_FILLHATCH, 0, 0);
1059             XHatchStyle eStyle;
1060 
1061             switch(rHatch.GetStyle())
1062             {
1063                 case(HATCH_TRIPLE) :
1064                 {
1065                     eStyle = XHATCH_TRIPLE;
1066                     break;
1067                 }
1068 
1069                 case(HATCH_DOUBLE) :
1070                 {
1071                     eStyle = XHATCH_DOUBLE;
1072                     break;
1073                 }
1074 
1075                 default:
1076                 {
1077                     eStyle = XHATCH_SINGLE;
1078                     break;
1079                 }
1080             }
1081 
1082             SetAttributes(pPath);
1083             aHatchAttr.Put(XFillStyleItem(XFILL_HATCH));
1084             aHatchAttr.Put(XFillHatchItem(&mpModel->GetItemPool(), XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
1085             pPath->SetMergedItemSet(aHatchAttr);
1086 
1087             InsertObj(pPath, false);
1088         }
1089     }
1090 }
1091 
1092 ////////////////////////////////////////////////////////////////////////////////////////////////////
1093 
1094 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
1095 {
1096     rAct.Execute(&maVD);
1097 }
1098 
1099 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
1100 {
1101     MapScaling();
1102     rAct.Execute(&maVD);
1103     mbLastObjWasPolyWithoutLine = false;
1104     mbLastObjWasLine = false;
1105 }
1106 
1107 void ImpSdrGDIMetaFileImport::MapScaling()
1108 {
1109     const sal_uInt32 nAnz(maTmpList.size());
1110     sal_uInt32 i(0);
1111     const MapMode& rMap = maVD.GetMapMode();
1112     Point aMapOrg( rMap.GetOrigin() );
1113     bool bMov2(aMapOrg.X() != 0 || aMapOrg.Y() != 0);
1114 
1115     if(bMov2)
1116     {
1117         for(i = mnMapScalingOfs; i < nAnz; i++)
1118         {
1119             SdrObject* pObj = maTmpList[i];
1120 
1121             pObj->NbcMove(Size(aMapOrg.X(), aMapOrg.Y()));
1122         }
1123     }
1124 
1125     mnMapScalingOfs = nAnz;
1126 }
1127 
1128 ////////////////////////////////////////////////////////////////////////////////////////////////////
1129 
1130 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction& rAct, GDIMetaFile* pMtf )
1131 {
1132     ByteString aSkipComment;
1133 
1134     if( rAct.GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
1135     {
1136         MetaGradientExAction* pAct = (MetaGradientExAction*) pMtf->NextAction();
1137 
1138         if( pAct && pAct->GetType() == META_GRADIENTEX_ACTION )
1139         {
1140             // #i73407# reformulation to use new B2DPolygon classes
1141             basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
1142 
1143             if(aSource.count())
1144             {
1145                 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1146                 {
1147                     const Gradient& rGrad = pAct->GetGradient();
1148                     SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1149                     SfxItemSet aGradAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
1150                     XGradient aXGradient;
1151 
1152                     aXGradient.SetGradientStyle((XGradientStyle)rGrad.GetStyle());
1153                     aXGradient.SetStartColor(rGrad.GetStartColor());
1154                     aXGradient.SetEndColor(rGrad.GetEndColor());
1155                     aXGradient.SetAngle((sal_uInt16)rGrad.GetAngle());
1156                     aXGradient.SetBorder(rGrad.GetBorder());
1157                     aXGradient.SetXOffset(rGrad.GetOfsX());
1158                     aXGradient.SetYOffset(rGrad.GetOfsY());
1159                     aXGradient.SetStartIntens(rGrad.GetStartIntensity());
1160                     aXGradient.SetEndIntens(rGrad.GetEndIntensity());
1161                     aXGradient.SetSteps(rGrad.GetSteps());
1162 
1163                     if(maVD.IsLineColor())
1164                     {
1165                         // switch line off; when there was one there will be a
1166                         // META_POLYLINE_ACTION following creating another object
1167                         const Color aLineColor(maVD.GetLineColor());
1168                         maVD.SetLineColor();
1169                         SetAttributes(pPath);
1170                         maVD.SetLineColor(aLineColor);
1171                     }
1172                     else
1173                     {
1174                         SetAttributes(pPath);
1175                     }
1176 
1177                     aGradAttr.Put(XFillStyleItem(XFILL_GRADIENT));
1178                     aGradAttr.Put(XFillGradientItem(&mpModel->GetItemPool(), aXGradient));
1179                     pPath->SetMergedItemSet(aGradAttr);
1180 
1181                     InsertObj(pPath);
1182                 }
1183             }
1184 
1185             aSkipComment = "XGRAD_SEQ_END";
1186         }
1187     }
1188 
1189     if(aSkipComment.Len())
1190     {
1191         MetaAction* pSkipAct = pMtf->NextAction();
1192 
1193         while( pSkipAct
1194             && ((pSkipAct->GetType() != META_COMMENT_ACTION )
1195                 || (((MetaCommentAction*)pSkipAct)->GetComment().CompareIgnoreCaseToAscii(aSkipComment.GetBuffer()) != COMPARE_EQUAL)))
1196         {
1197             pSkipAct = pMtf->NextAction();
1198         }
1199     }
1200 }
1201 
1202 ////////////////////////////////////////////////////////////////////////////////////////////////////
1203 
1204 void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction& rAct)
1205 {
1206     GDIMetaFile aTemp;
1207 
1208     maVD.AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
1209     DoLoopActions(aTemp, 0, 0);
1210 }
1211 
1212 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction& rAct)
1213 {
1214     Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1215     Bitmap aBitmap(rAct.GetBitmap());
1216 
1217     aRect.Right()++;
1218     aRect.Bottom()++;
1219     aBitmap.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1220 
1221     SdrGrafObj* pGraf = new SdrGrafObj(aBitmap, aRect);
1222 
1223     InsertObj(pGraf);
1224 }
1225 
1226 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction& rAct)
1227 {
1228     Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
1229     BitmapEx aBitmapEx(rAct.GetBitmapEx());
1230 
1231     aRect.Right()++;
1232     aRect.Bottom()++;
1233     aBitmapEx.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1234 
1235     SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1236 
1237     InsertObj(pGraf);
1238 }
1239 
1240 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction& rAct)
1241 {
1242     Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
1243     BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1244 
1245     aRect.Right()++;
1246     aRect.Bottom()++;
1247 
1248     SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1249 
1250     InsertObj(pGraf);
1251 }
1252 
1253 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction& rAct)
1254 {
1255     Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
1256     BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1257 
1258     aRect.Right()++;
1259     aRect.Bottom()++;
1260 
1261     SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1262 
1263     InsertObj(pGraf);
1264 }
1265 
1266 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction& rAct)
1267 {
1268     Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1269     BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1270 
1271     aRect.Right()++;
1272     aRect.Bottom()++;
1273     aBitmapEx.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1274 
1275     SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1276 
1277     InsertObj(pGraf);
1278 }
1279 
1280 XGradientStyle getXGradientStyleFromGradientStyle(const GradientStyle& rGradientStyle)
1281 {
1282     XGradientStyle aXGradientStyle(XGRAD_LINEAR);
1283 
1284     switch(rGradientStyle)
1285     {
1286         case GRADIENT_LINEAR: aXGradientStyle = XGRAD_LINEAR; break;
1287         case GRADIENT_AXIAL: aXGradientStyle = XGRAD_AXIAL; break;
1288         case GRADIENT_RADIAL: aXGradientStyle = XGRAD_RADIAL; break;
1289         case GRADIENT_ELLIPTICAL: aXGradientStyle = XGRAD_ELLIPTICAL; break;
1290         case GRADIENT_SQUARE: aXGradientStyle = XGRAD_SQUARE; break;
1291         case GRADIENT_RECT: aXGradientStyle = XGRAD_RECT; break;
1292 
1293         // Needed due to GRADIENT_FORCE_EQUAL_SIZE; this again is needed
1294         // to force the enum defines in VCL to a defined size for the compilers,
1295         // so despite it is never used it cannot be removed (would break the
1296         // API implementation probably).
1297         default: break;
1298     }
1299 
1300     return aXGradientStyle;
1301 }
1302 
1303 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction& rAct)
1304 {
1305     basegfx::B2DRange aRange(rAct.GetRect().Left(), rAct.GetRect().Top(), rAct.GetRect().Right(), rAct.GetRect().Bottom());
1306 
1307     if(!aRange.isEmpty())
1308     {
1309         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1310         aRange.transform(aTransform);
1311         const Gradient& rGradient = rAct.GetGradient();
1312         SdrRectObj* pRect = new SdrRectObj(
1313             Rectangle(
1314                 floor(aRange.getMinX()),
1315                 floor(aRange.getMinY()),
1316                 ceil(aRange.getMaxX()),
1317                 ceil(aRange.getMaxY())));
1318         SfxItemSet aGradientAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
1319         const XGradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1320         const XFillGradientItem aXFillGradientItem(
1321             &mpModel->GetItemPool(),
1322             XGradient(
1323                 rGradient.GetStartColor(),
1324                 rGradient.GetEndColor(),
1325                 aXGradientStyle,
1326                 rGradient.GetAngle(),
1327                 rGradient.GetOfsX(),
1328                 rGradient.GetOfsY(),
1329                 rGradient.GetBorder(),
1330                 rGradient.GetStartIntensity(),
1331                 rGradient.GetEndIntensity(),
1332                 rGradient.GetSteps()));
1333 
1334         SetAttributes(pRect);
1335         aGradientAttr.Put(XFillStyleItem(XFILL_HATCH));
1336         aGradientAttr.Put(aXFillGradientItem);
1337         pRect->SetMergedItemSet(aGradientAttr);
1338 
1339         InsertObj(pRect, false);
1340     }
1341 }
1342 
1343 void ImpSdrGDIMetaFileImport::DoAction(MetaWallpaperAction& /*rAct*/)
1344 {
1345     OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)");
1346 }
1347 
1348 void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction& rAct)
1349 {
1350     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1351 
1352     if(aSource.count())
1353     {
1354         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1355         aSource.transform(aTransform);
1356         aSource.setClosed(true);
1357 
1358         SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1359         SetAttributes(pPath);
1360         pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
1361         InsertObj(pPath, false);
1362     }
1363 }
1364 
1365 void ImpSdrGDIMetaFileImport::DoAction(MetaEPSAction& /*rAct*/)
1366 {
1367     OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)");
1368 }
1369 
1370 void ImpSdrGDIMetaFileImport::DoAction(MetaTextLineAction& /*rAct*/)
1371 {
1372     OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)");
1373 }
1374 
1375 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction& rAct)
1376 {
1377     basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1378 
1379     if(aSource.count())
1380     {
1381         const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1382         aSource.transform(aTransform);
1383 
1384         if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1385         {
1386             const Gradient& rGradient = rAct.GetGradient();
1387             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1388             SfxItemSet aGradientAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
1389             const XGradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1390             const XFillGradientItem aXFillGradientItem(
1391                 &mpModel->GetItemPool(),
1392                 XGradient(
1393                     rGradient.GetStartColor(),
1394                     rGradient.GetEndColor(),
1395                     aXGradientStyle,
1396                     rGradient.GetAngle(),
1397                     rGradient.GetOfsX(),
1398                     rGradient.GetOfsY(),
1399                     rGradient.GetBorder(),
1400                     rGradient.GetStartIntensity(),
1401                     rGradient.GetEndIntensity(),
1402                     rGradient.GetSteps()));
1403 
1404             SetAttributes(pPath);
1405             aGradientAttr.Put(XFillStyleItem(XFILL_HATCH));
1406             aGradientAttr.Put(aXFillGradientItem);
1407             pPath->SetMergedItemSet(aGradientAttr);
1408 
1409             InsertObj(pPath, false);
1410         }
1411     }
1412 }
1413 
1414 void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction& rAct)
1415 {
1416     const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
1417 
1418     if(rMtf.GetActionCount())
1419     {
1420         const Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1421 
1422         // convert metafile sub-content to BitmapEx
1423         BitmapEx aBitmapEx(
1424             convertMetafileToBitmapEx(
1425                 rMtf,
1426                 basegfx::B2DRange(
1427                     aRect.Left(), aRect.Top(),
1428                     aRect.Right(), aRect.Bottom()),
1429                 125000));
1430 
1431         // handle colors
1432         const Gradient& rGradient = rAct.GetGradient();
1433         basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
1434         basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
1435 
1436         if(100 != rGradient.GetStartIntensity())
1437         {
1438             aStart *= (double)rGradient.GetStartIntensity() / 100.0;
1439         }
1440 
1441         if(100 != rGradient.GetEndIntensity())
1442         {
1443             aEnd *= (double)rGradient.GetEndIntensity() / 100.0;
1444         }
1445 
1446         const bool bEqualColors(aStart == aEnd);
1447         const bool bNoSteps(1 == rGradient.GetSteps());
1448         bool bCreateObject(true);
1449         bool bHasNewMask(false);
1450         AlphaMask aNewMask;
1451         double fTransparence(0.0);
1452         bool bFixedTransparence(false);
1453 
1454         if(bEqualColors || bNoSteps)
1455         {
1456             // single transparence
1457             const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
1458             fTransparence = aMedium.luminance();
1459 
1460             if(basegfx::fTools::lessOrEqual(fTransparence, 0.0))
1461             {
1462                 // no transparence needed, all done
1463             }
1464             else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
1465             {
1466                 // all transparent, no object
1467                 bCreateObject = false;
1468             }
1469             else
1470             {
1471                 // 0.0 < transparence < 1.0, apply fixed transparence
1472                 bFixedTransparence = true;
1473             }
1474         }
1475         else
1476         {
1477             // gradient transparence
1478             VirtualDevice aVDev;
1479 
1480             aVDev.SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
1481             aVDev.DrawGradient(Rectangle(Point(0, 0), aVDev.GetOutputSizePixel()), rGradient);
1482 
1483             aNewMask = AlphaMask(aVDev.GetBitmap(Point(0, 0), aVDev.GetOutputSizePixel()));
1484             bHasNewMask = true;
1485         }
1486 
1487         if(bCreateObject)
1488         {
1489             if(bHasNewMask || bFixedTransparence)
1490             {
1491                 if(!aBitmapEx.IsAlpha() && !aBitmapEx.IsTransparent())
1492                 {
1493                     // no transparence yet, apply new one
1494                     if(bFixedTransparence)
1495                     {
1496                         sal_uInt8 aAlpha(basegfx::fround(fTransparence * 255.0));
1497 
1498                         aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), &aAlpha);
1499                     }
1500 
1501                     aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
1502                 }
1503                 else
1504                 {
1505                     // mix existing and new alpha mask
1506                     AlphaMask aOldMask;
1507 
1508                     if(aBitmapEx.IsAlpha())
1509                     {
1510                         aOldMask = aBitmapEx.GetAlpha();
1511                     }
1512                     else if(TRANSPARENT_BITMAP == aBitmapEx.GetTransparentType())
1513                     {
1514                         aOldMask = aBitmapEx.GetMask();
1515                     }
1516                     else if(TRANSPARENT_COLOR == aBitmapEx.GetTransparentType())
1517                     {
1518                         aOldMask = aBitmapEx.GetBitmap().CreateMask(aBitmapEx.GetTransparentColor());
1519                     }
1520 
1521                     BitmapWriteAccess* pOld = aOldMask.AcquireWriteAccess();
1522 
1523                     if(pOld)
1524                     {
1525                         const double fFactor(1.0 / 255.0);
1526 
1527                         if(bFixedTransparence)
1528                         {
1529                             const double fOpNew(1.0 - fTransparence);
1530 
1531                             for(sal_uInt32 y(0); y < static_cast< sal_uInt32 >(pOld->Height()); y++)
1532                             {
1533                                 for(sal_uInt32 x(0); x < static_cast< sal_uInt32 >(pOld->Width()); x++)
1534                                 {
1535                                     const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1536                                     const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1537 
1538                                     pOld->SetPixel(y, x, BitmapColor(aCol));
1539                                 }
1540                             }
1541                         }
1542                         else
1543                         {
1544                             BitmapReadAccess* pNew = aNewMask.AcquireReadAccess();
1545 
1546                             if(pNew)
1547                             {
1548                                 if(pOld->Width() == pNew->Width() && pOld->Height() == pNew->Height())
1549                                 {
1550                                     for(sal_uInt32 y(0); y < static_cast< sal_uInt32 >(pOld->Height()); y++)
1551                                     {
1552                                         for(sal_uInt32 x(0); x < static_cast< sal_uInt32 >(pOld->Width()); x++)
1553                                         {
1554                                             const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1555                                             const double fOpNew(1.0 - (pNew->GetPixel(y, x).GetIndex() * fFactor));
1556                                             const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1557 
1558                                             pOld->SetPixel(y, x, BitmapColor(aCol));
1559                                         }
1560                                     }
1561                                 }
1562                                 else
1563                                 {
1564                                     OSL_ENSURE(false, "Alpha masks have different sizes (!)");
1565                                 }
1566 
1567                                 aNewMask.ReleaseAccess(pNew);
1568                             }
1569                             else
1570                             {
1571                                 OSL_ENSURE(false, "Got no access to new alpha mask (!)");
1572                             }
1573                         }
1574 
1575                         aOldMask.ReleaseAccess(pOld);
1576                     }
1577                     else
1578                     {
1579                         OSL_ENSURE(false, "Got no access to old alpha mask (!)");
1580                     }
1581 
1582                     // apply combined bitmap as mask
1583                     aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aOldMask);
1584                 }
1585             }
1586 
1587             // create and add object
1588             SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1589 
1590             InsertObj(pGraf);
1591         }
1592     }
1593 }
1594 
1595 ////////////////////////////////////////////////////////////////////////////////////////////////////
1596 // eof
1597