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