xref: /aoo41x/main/svx/source/svdraw/svdfmtf.cxx (revision 9f63b866)
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 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction& rAct)
1281 {
1282     basegfx::B2DRange aRange(rAct.GetRect().Left(), rAct.GetRect().Top(), rAct.GetRect().Right(), rAct.GetRect().Bottom());
1283 
1284 	if(!aRange.isEmpty())
1285 	{
1286 		const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1287 		aRange.transform(aTransform);
1288         const Gradient& rGradient = rAct.GetGradient();
1289         SdrRectObj* pRect = new SdrRectObj(
1290             Rectangle(
1291                 floor(aRange.getMinX()),
1292                 floor(aRange.getMinY()),
1293                 ceil(aRange.getMaxX()),
1294                 ceil(aRange.getMaxY())));
1295 		SfxItemSet aGradientAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
1296         XGradientStyle aXGradientStyle(XGRAD_LINEAR);
1297 
1298         switch(rGradient.GetStyle())
1299         {
1300             case GRADIENT_LINEAR: aXGradientStyle = XGRAD_LINEAR; break;
1301             case GRADIENT_AXIAL: aXGradientStyle = XGRAD_AXIAL; break;
1302             case GRADIENT_RADIAL: aXGradientStyle = XGRAD_RADIAL; break;
1303             case GRADIENT_ELLIPTICAL: aXGradientStyle = XGRAD_ELLIPTICAL; break;
1304             case GRADIENT_SQUARE: aXGradientStyle = XGRAD_SQUARE; break;
1305             case GRADIENT_RECT: aXGradientStyle = XGRAD_RECT; break;
1306         }
1307 
1308         const XFillGradientItem aXFillGradientItem(
1309             &mpModel->GetItemPool(),
1310             XGradient(
1311                 rGradient.GetStartColor(),
1312                 rGradient.GetEndColor(),
1313                 aXGradientStyle,
1314                 rGradient.GetAngle(),
1315                 rGradient.GetOfsX(),
1316                 rGradient.GetOfsY(),
1317                 rGradient.GetBorder(),
1318                 rGradient.GetStartIntensity(),
1319                 rGradient.GetEndIntensity(),
1320                 rGradient.GetSteps()));
1321 
1322 		SetAttributes(pRect);
1323 		aGradientAttr.Put(XFillStyleItem(XFILL_HATCH));
1324 		aGradientAttr.Put(aXFillGradientItem);
1325 		pRect->SetMergedItemSet(aGradientAttr);
1326 
1327 		InsertObj(pRect, false);
1328 	}
1329 }
1330 
1331 void ImpSdrGDIMetaFileImport::DoAction(MetaWallpaperAction& rAct)
1332 {
1333     OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)");
1334 }
1335 
1336 void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction& rAct)
1337 {
1338 	basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1339 
1340 	if(aSource.count())
1341 	{
1342 		const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1343 		aSource.transform(aTransform);
1344     	aSource.setClosed(true);
1345 
1346         SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1347 		SetAttributes(pPath);
1348         pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
1349 		InsertObj(pPath, false);
1350 	}
1351 }
1352 
1353 void ImpSdrGDIMetaFileImport::DoAction(MetaEPSAction& rAct)
1354 {
1355     OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)");
1356 }
1357 
1358 void ImpSdrGDIMetaFileImport::DoAction(MetaTextLineAction& rAct)
1359 {
1360     OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)");
1361 }
1362 
1363 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction& rAct)
1364 {
1365 	basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1366 
1367 	if(aSource.count())
1368 	{
1369 		const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1370 		aSource.transform(aTransform);
1371 
1372 		if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1373 		{
1374         	const Gradient& rGradient = rAct.GetGradient();
1375             SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1376 			SfxItemSet aGradientAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
1377             XGradientStyle aXGradientStyle(XGRAD_LINEAR);
1378 
1379             switch(rGradient.GetStyle())
1380             {
1381                 case GRADIENT_LINEAR: aXGradientStyle = XGRAD_LINEAR; break;
1382                 case GRADIENT_AXIAL: aXGradientStyle = XGRAD_AXIAL; break;
1383                 case GRADIENT_RADIAL: aXGradientStyle = XGRAD_RADIAL; break;
1384                 case GRADIENT_ELLIPTICAL: aXGradientStyle = XGRAD_ELLIPTICAL; break;
1385                 case GRADIENT_SQUARE: aXGradientStyle = XGRAD_SQUARE; break;
1386                 case GRADIENT_RECT: aXGradientStyle = XGRAD_RECT; break;
1387             }
1388 
1389             const XFillGradientItem aXFillGradientItem(
1390                 &mpModel->GetItemPool(),
1391                 XGradient(
1392                     rGradient.GetStartColor(),
1393                     rGradient.GetEndColor(),
1394                     aXGradientStyle,
1395                     rGradient.GetAngle(),
1396                     rGradient.GetOfsX(),
1397                     rGradient.GetOfsY(),
1398                     rGradient.GetBorder(),
1399                     rGradient.GetStartIntensity(),
1400                     rGradient.GetEndIntensity(),
1401                     rGradient.GetSteps()));
1402 
1403 			SetAttributes(pPath);
1404 			aGradientAttr.Put(XFillStyleItem(XFILL_HATCH));
1405 			aGradientAttr.Put(aXFillGradientItem);
1406 			pPath->SetMergedItemSet(aGradientAttr);
1407 
1408 			InsertObj(pPath, false);
1409 		}
1410 	}
1411 }
1412 
1413 void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction& rAct)
1414 {
1415 	const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
1416 
1417     if(rMtf.GetActionCount())
1418     {
1419 	    const Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1420 
1421         // convert metafile sub-content to BitmapEx
1422         BitmapEx aBitmapEx(
1423             convertMetafileToBitmapEx(
1424                 rMtf,
1425                 basegfx::B2DRange(
1426                     aRect.Left(), aRect.Top(),
1427                     aRect.Right(), aRect.Bottom()),
1428                 125000));
1429 
1430         // handle colors
1431         const Gradient& rGradient = rAct.GetGradient();
1432 	    basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
1433 	    basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
1434 
1435         if(100 != rGradient.GetStartIntensity())
1436 	    {
1437             aStart *= (double)rGradient.GetStartIntensity() / 100.0;
1438 	    }
1439 
1440         if(100 != rGradient.GetEndIntensity())
1441 	    {
1442             aEnd *= (double)rGradient.GetEndIntensity() / 100.0;
1443 	    }
1444 
1445         const bool bEqualColors(aStart == aEnd);
1446         const bool bNoSteps(1 == rGradient.GetSteps());
1447         bool bCreateObject(true);
1448         bool bHasNewMask(false);
1449         AlphaMask aNewMask;
1450         double fTransparence(0.0);
1451         bool bFixedTransparence(false);
1452 
1453         if(bEqualColors || bNoSteps)
1454         {
1455             // single transparence
1456             const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
1457             fTransparence = aMedium.luminance();
1458 
1459             if(basegfx::fTools::lessOrEqual(fTransparence, 0.0))
1460             {
1461                 // no transparence needed, all done
1462             }
1463             else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
1464             {
1465                 // all transparent, no object
1466                 bCreateObject = false;
1467             }
1468             else
1469             {
1470                 // 0.0 < transparence < 1.0, apply fixed transparence
1471                 bFixedTransparence = true;
1472             }
1473         }
1474         else
1475         {
1476             // gradient transparence
1477             VirtualDevice aVDev;
1478 
1479             aVDev.SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
1480             aVDev.DrawGradient(Rectangle(Point(0, 0), aVDev.GetOutputSizePixel()), rGradient);
1481 
1482             aNewMask = AlphaMask(aVDev.GetBitmap(Point(0, 0), aVDev.GetOutputSizePixel()));
1483             bHasNewMask = true;
1484         }
1485 
1486         if(bCreateObject)
1487         {
1488             if(bHasNewMask || bFixedTransparence)
1489             {
1490                 if(!aBitmapEx.IsAlpha() && !aBitmapEx.IsTransparent())
1491                 {
1492                     // no transparence yet, apply new one
1493                     if(bFixedTransparence)
1494                     {
1495                         sal_uInt8 aAlpha(basegfx::fround(fTransparence * 255.0));
1496 
1497                         aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), &aAlpha);
1498                     }
1499 
1500                     aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
1501                 }
1502                 else
1503                 {
1504                     // mix existing and new alpha mask
1505                     AlphaMask aOldMask;
1506 
1507                     if(aBitmapEx.IsAlpha())
1508                     {
1509                         aOldMask = aBitmapEx.GetAlpha();
1510                     }
1511                     else if(TRANSPARENT_BITMAP == aBitmapEx.GetTransparentType())
1512                     {
1513                         aOldMask = aBitmapEx.GetMask();
1514                     }
1515                     else if(TRANSPARENT_COLOR == aBitmapEx.GetTransparentType())
1516                     {
1517                         aOldMask = aBitmapEx.GetBitmap().CreateMask(aBitmapEx.GetTransparentColor());
1518                     }
1519 
1520                     BitmapWriteAccess* pOld = aOldMask.AcquireWriteAccess();
1521 
1522                     if(pOld)
1523                     {
1524                         const double fFactor(1.0 / 255.0);
1525 
1526                         if(bFixedTransparence)
1527                         {
1528                             const double fOpNew(1.0 - fTransparence);
1529 
1530                             for(sal_uInt32 y(0); y < pOld->Height(); y++)
1531                             {
1532                                 for(sal_uInt32 x(0); x < pOld->Width(); x++)
1533                                 {
1534                                     const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1535                                     const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1536 
1537                                     pOld->SetPixel(y, x, BitmapColor(aCol));
1538                                 }
1539                             }
1540                         }
1541                         else
1542                         {
1543                             BitmapReadAccess* pNew = aNewMask.AcquireReadAccess();
1544 
1545                             if(pNew)
1546                             {
1547                                 if(pOld->Width() == pNew->Width() && pOld->Height() == pNew->Height())
1548                                 {
1549                                     for(sal_uInt32 y(0); y < pOld->Height(); y++)
1550                                     {
1551                                         for(sal_uInt32 x(0); x < pOld->Width(); x++)
1552                                         {
1553                                             const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1554                                             const double fOpNew(1.0 - (pNew->GetPixel(y, x).GetIndex() * fFactor));
1555                                             const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1556 
1557                                             pOld->SetPixel(y, x, BitmapColor(aCol));
1558                                         }
1559                                     }
1560                                 }
1561                                 else
1562                                 {
1563                                     OSL_ENSURE(false, "Alpha masks have different sizes (!)");
1564                                 }
1565 
1566                                 aNewMask.ReleaseAccess(pNew);
1567                             }
1568                             else
1569                             {
1570                                 OSL_ENSURE(false, "Got no access to new alpha mask (!)");
1571                             }
1572                         }
1573 
1574                         aOldMask.ReleaseAccess(pOld);
1575                     }
1576                     else
1577                     {
1578                         OSL_ENSURE(false, "Got no access to old alpha mask (!)");
1579                     }
1580 
1581                     // apply combined bitmap as mask
1582                     aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aOldMask);
1583                 }
1584             }
1585 
1586             // create and add object
1587             SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1588 
1589             InsertObj(pGraf);
1590         }
1591     }
1592 }
1593 
1594 ////////////////////////////////////////////////////////////////////////////////////////////////////
1595 // eof
1596