bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / svdfmtf.cxx
blob002559e9cc11611d9ba7cf2c68c3a477a87bc978
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "svdfmtf.hxx"
21 #include <editeng/editdata.hxx>
22 #include <math.h>
23 #include <svx/xpoly.hxx>
24 #include <vcl/svapp.hxx>
25 #include <editeng/eeitem.hxx>
26 #include <editeng/fhgtitem.hxx>
27 #include <editeng/wghtitem.hxx>
28 #include <editeng/postitem.hxx>
29 #include <editeng/udlnitem.hxx>
30 #include <editeng/crossedoutitem.hxx>
31 #include <editeng/shdditem.hxx>
32 #include <svx/xlnclit.hxx>
33 #include <svx/xlncapit.hxx>
34 #include <svx/xlnwtit.hxx>
35 #include <svx/xflclit.hxx>
36 #include <svx/xgrad.hxx>
37 #include <svx/xflgrit.hxx>
38 #include <editeng/fontitem.hxx>
39 #include <editeng/autokernitem.hxx>
40 #include <editeng/wrlmitem.hxx>
41 #include <editeng/contouritem.hxx>
42 #include <editeng/colritem.hxx>
43 #include <vcl/metric.hxx>
44 #include <editeng/charscaleitem.hxx>
45 #include <svx/xflhtit.hxx>
46 #include <svx/svdattr.hxx>
47 #include <svx/svdmodel.hxx>
48 #include <svx/svdpage.hxx>
49 #include <svx/svdobj.hxx>
50 #include <svx/svdotext.hxx>
51 #include <svx/svdorect.hxx>
52 #include <svx/svdocirc.hxx>
53 #include <svx/svdograf.hxx>
54 #include <svx/svdopath.hxx>
55 #include <svx/svdetc.hxx>
56 #include <svl/itemset.hxx>
57 #include <basegfx/polygon/b2dpolygon.hxx>
58 #include <tools/helpers.hxx>
59 #include <basegfx/matrix/b2dhommatrix.hxx>
60 #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 #include <svx/xlinjoit.hxx>
62 #include <svx/xlndsit.hxx>
63 #include <basegfx/polygon/b2dpolygonclipper.hxx>
64 #include <svx/xbtmpit.hxx>
65 #include <svx/xfltrit.hxx>
66 #include <vcl/bmpacc.hxx>
67 #include <svx/xflbmtit.hxx>
68 #include <svx/xflbstit.hxx>
69 #include <svx/svdpntv.hxx>
70 #include <basegfx/polygon/b2dpolypolygontools.hxx>
71 #include <svx/svditer.hxx>
72 #include <svx/svdogrp.hxx>
74 using namespace com::sun::star;
76 ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
77 SdrModel& rModel,
78 SdrLayerID nLay,
79 const Rectangle& rRect)
80 : maTmpList(),
81 mpVD(VclPtr<VirtualDevice>::Create()),
82 maScaleRect(rRect),
83 mnMapScalingOfs(0),
84 mpLineAttr(0),
85 mpFillAttr(0),
86 mpTextAttr(0),
87 mpModel(&rModel),
88 mnLayer(nLay),
89 maOldLineColor(),
90 mnLineWidth(0),
91 maLineJoin(basegfx::B2DLINEJOIN_NONE),
92 maLineCap(com::sun::star::drawing::LineCap_BUTT),
93 maDash(css::drawing::DashStyle_RECT, 0, 0, 0, 0, 0),
94 mbMov(false),
95 mbSize(false),
96 maOfs(0, 0),
97 mfScaleX(1.0),
98 mfScaleY(1.0),
99 maScaleX(1.0),
100 maScaleY(1.0),
101 mbFntDirty(true),
102 mbLastObjWasPolyWithoutLine(false),
103 mbNoLine(false),
104 mbNoFill(false),
105 mbLastObjWasLine(false),
106 maClip()
108 mpVD->EnableOutput(false);
109 mpVD->SetLineColor();
110 mpVD->SetFillColor();
111 maOldLineColor.SetRed( mpVD->GetLineColor().GetRed() + 1 );
112 mpLineAttr = new SfxItemSet(rModel.GetItemPool(), XATTR_LINE_FIRST, XATTR_LINE_LAST, 0, 0);
113 mpFillAttr = new SfxItemSet(rModel.GetItemPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST, 0, 0);
114 mpTextAttr = new SfxItemSet(rModel.GetItemPool(), EE_ITEMS_START, EE_ITEMS_END, 0, 0);
115 checkClip();
118 ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport()
120 delete mpLineAttr;
121 delete mpFillAttr;
122 delete mpTextAttr;
125 void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile& rMtf, SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
127 const sal_uLong nCount(rMtf.GetActionSize());
129 for(sal_uLong a(0); a < nCount; a++)
131 MetaAction* pAct = rMtf.GetAction(a);
133 if(!pAct)
135 OSL_ENSURE(false, "OOps, no action at valid position (!)");
136 pAct = rMtf.GetAction(0);
139 switch (pAct->GetType())
141 case MetaActionType::PIXEL : break;
142 case MetaActionType::POINT : break;
143 case MetaActionType::LINE : DoAction(static_cast<MetaLineAction &>(*pAct)); break;
144 case MetaActionType::RECT : DoAction(static_cast<MetaRectAction &>(*pAct)); break;
145 case MetaActionType::ROUNDRECT : DoAction(static_cast<MetaRoundRectAction &>(*pAct)); break;
146 case MetaActionType::ELLIPSE : DoAction(static_cast<MetaEllipseAction &>(*pAct)); break;
147 case MetaActionType::ARC : DoAction(static_cast<MetaArcAction &>(*pAct)); break;
148 case MetaActionType::PIE : DoAction(static_cast<MetaPieAction &>(*pAct)); break;
149 case MetaActionType::CHORD : DoAction(static_cast<MetaChordAction &>(*pAct)); break;
150 case MetaActionType::POLYLINE : DoAction(static_cast<MetaPolyLineAction &>(*pAct)); break;
151 case MetaActionType::POLYGON : DoAction(static_cast<MetaPolygonAction &>(*pAct)); break;
152 case MetaActionType::POLYPOLYGON : DoAction(static_cast<MetaPolyPolygonAction &>(*pAct)); break;
153 case MetaActionType::TEXT : DoAction(static_cast<MetaTextAction &>(*pAct)); break;
154 case MetaActionType::TEXTARRAY : DoAction(static_cast<MetaTextArrayAction &>(*pAct)); break;
155 case MetaActionType::STRETCHTEXT : DoAction(static_cast<MetaStretchTextAction &>(*pAct)); break;
156 case MetaActionType::BMP : DoAction(static_cast<MetaBmpAction &>(*pAct)); break;
157 case MetaActionType::BMPSCALE : DoAction(static_cast<MetaBmpScaleAction &>(*pAct)); break;
158 case MetaActionType::BMPEX : DoAction(static_cast<MetaBmpExAction &>(*pAct)); break;
159 case MetaActionType::BMPEXSCALE : DoAction(static_cast<MetaBmpExScaleAction &>(*pAct)); break;
160 case MetaActionType::LINECOLOR : DoAction(static_cast<MetaLineColorAction &>(*pAct)); break;
161 case MetaActionType::FILLCOLOR : DoAction(static_cast<MetaFillColorAction &>(*pAct)); break;
162 case MetaActionType::TEXTCOLOR : DoAction(static_cast<MetaTextColorAction &>(*pAct)); break;
163 case MetaActionType::TEXTFILLCOLOR : DoAction(static_cast<MetaTextFillColorAction &>(*pAct)); break;
164 case MetaActionType::FONT : DoAction(static_cast<MetaFontAction &>(*pAct)); break;
165 case MetaActionType::TEXTALIGN : DoAction(static_cast<MetaTextAlignAction &>(*pAct)); break;
166 case MetaActionType::MAPMODE : DoAction(static_cast<MetaMapModeAction &>(*pAct)); break;
167 case MetaActionType::CLIPREGION : DoAction(static_cast<MetaClipRegionAction &>(*pAct)); break;
168 case MetaActionType::MOVECLIPREGION : DoAction(static_cast<MetaMoveClipRegionAction &>(*pAct)); break;
169 case MetaActionType::ISECTRECTCLIPREGION: DoAction(static_cast<MetaISectRectClipRegionAction&>(*pAct)); break;
170 case MetaActionType::ISECTREGIONCLIPREGION: DoAction(static_cast<MetaISectRegionClipRegionAction&>(*pAct)); break;
171 case MetaActionType::RASTEROP : DoAction(static_cast<MetaRasterOpAction &>(*pAct)); break;
172 case MetaActionType::PUSH : DoAction(static_cast<MetaPushAction &>(*pAct)); break;
173 case MetaActionType::POP : DoAction(static_cast<MetaPopAction &>(*pAct)); break;
174 case MetaActionType::HATCH : DoAction(static_cast<MetaHatchAction &>(*pAct)); break;
176 // #i125211# MetaCommentAction may change index, thus hand it over
177 case MetaActionType::COMMENT : DoAction(static_cast<MetaCommentAction&>(*pAct), rMtf, a);
178 break;
180 // missing actions added
181 case MetaActionType::TEXTRECT : DoAction(static_cast<MetaTextRectAction&>(*pAct)); break;
182 case MetaActionType::BMPSCALEPART : DoAction(static_cast<MetaBmpScalePartAction&>(*pAct)); break;
183 case MetaActionType::BMPEXSCALEPART : DoAction(static_cast<MetaBmpExScalePartAction&>(*pAct)); break;
184 case MetaActionType::MASK : DoAction(static_cast<MetaMaskAction&>(*pAct)); break;
185 case MetaActionType::MASKSCALE : DoAction(static_cast<MetaMaskScaleAction&>(*pAct)); break;
186 case MetaActionType::MASKSCALEPART : DoAction(static_cast<MetaMaskScalePartAction&>(*pAct)); break;
187 case MetaActionType::GRADIENT : DoAction(static_cast<MetaGradientAction&>(*pAct)); break;
188 case MetaActionType::WALLPAPER : DoAction(static_cast<MetaWallpaperAction&>(*pAct)); break;
189 case MetaActionType::Transparent : DoAction(static_cast<MetaTransparentAction&>(*pAct)); break;
190 case MetaActionType::EPS : DoAction(static_cast<MetaEPSAction&>(*pAct)); break;
191 case MetaActionType::REFPOINT : DoAction(static_cast<MetaRefPointAction&>(*pAct)); break;
192 case MetaActionType::TEXTLINECOLOR : DoAction(static_cast<MetaTextLineColorAction&>(*pAct)); break;
193 case MetaActionType::TEXTLINE : DoAction(static_cast<MetaTextLineAction&>(*pAct)); break;
194 case MetaActionType::FLOATTRANSPARENT : DoAction(static_cast<MetaFloatTransparentAction&>(*pAct)); break;
195 case MetaActionType::GRADIENTEX : DoAction(static_cast<MetaGradientExAction&>(*pAct)); break;
196 case MetaActionType::LAYOUTMODE : DoAction(static_cast<MetaLayoutModeAction&>(*pAct)); break;
197 case MetaActionType::TEXTLANGUAGE : DoAction(static_cast<MetaTextLanguageAction&>(*pAct)); break;
198 case MetaActionType::OVERLINECOLOR : DoAction(static_cast<MetaOverlineColorAction&>(*pAct)); break;
199 default: break;
202 if(pProgrInfo && pActionsToReport)
204 (*pActionsToReport)++;
206 if(*pActionsToReport >= 16) // update all 16 actions
208 if(!pProgrInfo->ReportActions(*pActionsToReport))
209 break;
211 *pActionsToReport = 0;
217 size_t ImpSdrGDIMetaFileImport::DoImport(
218 const GDIMetaFile& rMtf,
219 SdrObjList& rOL,
220 size_t nInsPos,
221 SvdProgressInfo* pProgrInfo)
223 // setup some global scale parameter
224 // mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
225 mfScaleX = mfScaleY = 1.0;
226 const Size aMtfSize(rMtf.GetPrefSize());
228 if(aMtfSize.Width() & aMtfSize.Height() && (!maScaleRect.IsEmpty()))
230 maOfs = maScaleRect.TopLeft();
232 if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
234 mfScaleX = (double)( maScaleRect.GetWidth() - 1 ) / (double)aMtfSize.Width();
237 if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
239 mfScaleY = (double)( maScaleRect.GetHeight() - 1 ) / (double)aMtfSize.Height();
243 mbMov = maOfs.X()!=0 || maOfs.Y()!=0;
244 mbSize = false;
245 maScaleX = Fraction( 1, 1 );
246 maScaleY = Fraction( 1, 1 );
248 if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
250 maScaleX = Fraction(maScaleRect.GetWidth() - 1, aMtfSize.Width());
251 mbSize = true;
254 if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
256 maScaleY = Fraction(maScaleRect.GetHeight() - 1, aMtfSize.Height());
257 mbSize = true;
260 if(pProgrInfo)
262 pProgrInfo->SetActionCount(rMtf.GetActionSize());
265 sal_uInt32 nActionsToReport(0);
267 // execute
268 DoLoopActions(const_cast< GDIMetaFile& >(rMtf), pProgrInfo, &nActionsToReport);
270 if(pProgrInfo)
272 pProgrInfo->ReportActions(nActionsToReport);
273 nActionsToReport = 0;
276 // MapMode scaling
277 MapScaling();
279 // To calculate the progress meter, we use GetActionSize()*3.
280 // However, maTmpList has a lower entry count limit than GetActionSize(),
281 // so the actions that were assumed were too much have to be re-added.
282 nActionsToReport = (rMtf.GetActionSize() - maTmpList.size()) * 2;
284 // announce all currently unannounced rescales
285 if(pProgrInfo)
287 pProgrInfo->ReportRescales(nActionsToReport);
288 pProgrInfo->SetInsertCount(maTmpList.size());
291 nActionsToReport = 0;
293 // insert all objects cached in aTmpList now into rOL from nInsPos
294 nInsPos = std::min(nInsPos, rOL.GetObjCount());
296 SdrInsertReason aReason(SDRREASON_VIEWCALL);
298 for(size_t i = 0; i < maTmpList.size(); ++i)
300 SdrObject* pObj = maTmpList[i];
301 rOL.NbcInsertObject(pObj, nInsPos, &aReason);
302 nInsPos++;
304 if(pProgrInfo)
306 nActionsToReport++;
308 if(nActionsToReport >= 32) // update all 32 actions
310 pProgrInfo->ReportInserts(nActionsToReport);
311 nActionsToReport = 0;
316 // report all remaining inserts for the last time
317 if(pProgrInfo)
319 pProgrInfo->ReportInserts(nActionsToReport);
322 return maTmpList.size();
325 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr)
327 mbNoLine = false;
328 mbNoFill = false;
329 bool bLine(!bForceTextAttr);
330 bool bFill(!pObj || (pObj->IsClosedObj() && !bForceTextAttr));
331 bool bText(bForceTextAttr || (pObj && pObj->GetOutlinerParaObject()));
333 if(bLine)
335 if(mnLineWidth)
337 mpLineAttr->Put(XLineWidthItem(mnLineWidth));
339 else
341 mpLineAttr->Put(XLineWidthItem(0));
344 maOldLineColor = mpVD->GetLineColor();
346 if(mpVD->IsLineColor())
348 mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_SOLID));
349 mpLineAttr->Put(XLineColorItem(OUString(), mpVD->GetLineColor()));
351 else
353 mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_NONE));
356 switch(maLineJoin)
358 default : // basegfx::B2DLINEJOIN_NONE
359 mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_NONE));
360 break;
361 case basegfx::B2DLINEJOIN_MIDDLE:
362 mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_MIDDLE));
363 break;
364 case basegfx::B2DLINEJOIN_BEVEL:
365 mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_BEVEL));
366 break;
367 case basegfx::B2DLINEJOIN_MITER:
368 mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_MITER));
369 break;
370 case basegfx::B2DLINEJOIN_ROUND:
371 mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_ROUND));
372 break;
375 // Add LineCap support
376 mpLineAttr->Put(XLineCapItem(maLineCap));
378 if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance())
380 mpLineAttr->Put(XLineDashItem(OUString(), maDash));
382 else
384 mpLineAttr->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT)));
387 else
389 mbNoLine = true;
392 if(bFill)
394 if(mpVD->IsFillColor())
396 mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_SOLID));
397 mpFillAttr->Put(XFillColorItem(OUString(), mpVD->GetFillColor()));
399 else
401 mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_NONE));
404 else
406 mbNoFill = true;
409 if(bText && mbFntDirty)
411 vcl::Font aFnt(mpVD->GetFont());
412 const sal_uInt32 nHeight(FRound(aFnt.GetSize().Height() * mfScaleY));
414 mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
415 mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
416 mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) );
417 mpTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC));
418 mpTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT));
419 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
420 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
421 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
422 mpTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
423 mpTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
424 mpTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
425 mpTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
426 mpTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
428 // #i118485# Setting this item leads to problems (written #i118498# for this)
429 // mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
431 mpTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
432 mpTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
433 mpTextAttr->Put(SvxColorItem(mpVD->GetTextColor(), EE_CHAR_COLOR));
434 //... svxfont textitem svditext
435 mbFntDirty = false;
438 if(pObj)
440 pObj->SetLayer(mnLayer);
442 if(bLine)
444 pObj->SetMergedItemSet(*mpLineAttr);
447 if(bFill)
449 pObj->SetMergedItemSet(*mpFillAttr);
452 if(bText)
454 pObj->SetMergedItemSet(*mpTextAttr);
455 pObj->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
460 void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj, bool bScale)
462 if(bScale && !maScaleRect.IsEmpty())
464 if(mbSize)
466 pObj->NbcResize(Point(), maScaleX, maScaleY);
469 if(mbMov)
471 pObj->NbcMove(Size(maOfs.X(), maOfs.Y()));
475 if(isClip())
477 const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
478 const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
479 const SdrLayerID aOldLayer(pObj->GetLayer());
480 const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
481 const SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
482 const SdrTextObj* pSdrTextObj = dynamic_cast< SdrTextObj* >(pObj);
484 if(pSdrTextObj && pSdrTextObj->HasText())
486 // all text objects are created from ImportText and have no line or fill attributes, so
487 // it is okay to concentrate on the text itself
488 while(true)
490 const basegfx::B2DPolyPolygon aTextContour(pSdrTextObj->TakeContour());
491 const basegfx::B2DRange aTextRange(aTextContour.getB2DRange());
492 const basegfx::B2DRange aClipRange(maClip.getB2DRange());
494 // no overlap -> completely outside
495 if(!aClipRange.overlaps(aTextRange))
497 SdrObject::Free(pObj);
498 break;
501 // when the clip is a rectangle fast check for inside is possible
502 if(basegfx::tools::isRectangle(maClip) && aClipRange.isInside(aTextRange))
504 // completely inside ClipRect
505 break;
508 // here text needs to be clipped; to do so, convert to SdrObjects with polygons
509 // and add these recursively. Delete original object, do not add in this run
510 SdrObject* pConverted = pSdrTextObj->ConvertToPolyObj(true, true);
511 SdrObject::Free(pObj);
513 if(pConverted)
515 // recursively add created conversion; per definition this shall not
516 // contain further SdrTextObjs. Visit only non-group objects
517 SdrObjListIter aIter(*pConverted, IM_DEEPNOGROUPS);
519 // work with clones; the created conversion may contain group objects
520 // and when working with the original objects the loop itself could
521 // break and the cleanup later would be pretty complicated (only delete group
522 // objects, are these empty, ...?)
523 while(aIter.IsMore())
525 SdrObject* pCandidate = aIter.Next();
526 OSL_ENSURE(pCandidate && 0 == dynamic_cast< SdrObjGroup* >(pCandidate), "SdrObjListIter with IM_DEEPNOGROUPS error (!)");
527 SdrObject* pNewClone = pCandidate->Clone();
529 if(pNewClone)
531 InsertObj(pNewClone, false);
533 else
535 OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
539 // cleanup temporary conversion objects
540 SdrObject::Free(pConverted);
543 break;
546 else
548 BitmapEx aBitmapEx;
550 if(pSdrGrafObj)
552 aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
555 SdrObject::Free(pObj);
557 if(!aOldRange.isEmpty())
559 // clip against ClipRegion
560 const basegfx::B2DPolyPolygon aNewPoly(
561 basegfx::tools::clipPolyPolygonOnPolyPolygon(
562 aPoly,
563 maClip,
564 true,
565 !aPoly.isClosed()));
566 const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
568 if(!aNewRange.isEmpty())
570 pObj = new SdrPathObj(
571 aNewPoly.isClosed() ? OBJ_POLY : OBJ_PLIN,
572 aNewPoly);
574 pObj->SetLayer(aOldLayer);
575 pObj->SetMergedItemSet(aOldItemSet);
577 if(!!aBitmapEx)
579 // aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
580 const double fScaleX(aBitmapEx.GetSizePixel().Width() / (aOldRange.getWidth() ? aOldRange.getWidth() : 1.0));
581 const double fScaleY(aBitmapEx.GetSizePixel().Height() / (aOldRange.getHeight() ? aOldRange.getHeight() : 1.0));
582 basegfx::B2DRange aPixel(aNewRange);
583 basegfx::B2DHomMatrix aTrans;
585 aTrans.translate(-aOldRange.getMinX(), -aOldRange.getMinY());
586 aTrans.scale(fScaleX, fScaleY);
587 aPixel.transform(aTrans);
589 const Size aOrigSizePixel(aBitmapEx.GetSizePixel());
590 const Point aClipTopLeft(
591 basegfx::fround(floor(std::max(0.0, aPixel.getMinX()))),
592 basegfx::fround(floor(std::max(0.0, aPixel.getMinY()))));
593 const Size aClipSize(
594 basegfx::fround(ceil(std::min((double)aOrigSizePixel.Width(), aPixel.getWidth()))),
595 basegfx::fround(ceil(std::min((double)aOrigSizePixel.Height(), aPixel.getHeight()))));
596 const BitmapEx aClippedBitmap(
597 aBitmapEx,
598 aClipTopLeft,
599 aClipSize);
601 pObj->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
602 pObj->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap)));
603 pObj->SetMergedItem(XFillBmpTileItem(false));
604 pObj->SetMergedItem(XFillBmpStretchItem(true));
611 if(pObj)
613 // #i111954# check object for visibility
614 // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
615 bool bVisible(false);
617 if(pObj->HasLineStyle())
619 bVisible = true;
622 if(!bVisible && pObj->HasFillStyle())
624 bVisible = true;
627 if(!bVisible)
629 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >(pObj);
631 if(pTextObj && pTextObj->HasText())
633 bVisible = true;
637 if(!bVisible)
639 SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
641 if(pGrafObj)
643 // this may be refined to check if the graphic really is visible. It
644 // is here to ensure that graphic objects without fill, line and text
645 // get created
646 bVisible = true;
650 if(!bVisible)
652 SdrObject::Free(pObj);
654 else
656 maTmpList.push_back(pObj);
658 if(dynamic_cast< SdrPathObj* >(pObj))
660 const bool bClosed(pObj->IsClosedObj());
662 mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
663 mbLastObjWasLine = !bClosed;
665 else
667 mbLastObjWasPolyWithoutLine = false;
668 mbLastObjWasLine = false;
674 void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction& rAct)
676 // #i73407# reformulation to use new B2DPolygon classes
677 const basegfx::B2DPoint aStart(rAct.GetStartPoint().X(), rAct.GetStartPoint().Y());
678 const basegfx::B2DPoint aEnd(rAct.GetEndPoint().X(), rAct.GetEndPoint().Y());
680 if(!aStart.equal(aEnd))
682 basegfx::B2DPolygon aLine;
683 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
685 aLine.append(aStart);
686 aLine.append(aEnd);
687 aLine.transform(aTransform);
689 const LineInfo& rLineInfo = rAct.GetLineInfo();
690 const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
691 bool bCreateLineObject(true);
693 if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aLine))
695 bCreateLineObject = false;
698 if(bCreateLineObject)
700 SdrPathObj* pPath = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aLine));
701 mnLineWidth = nNewLineWidth;
702 maLineJoin = rLineInfo.GetLineJoin();
703 maLineCap = rLineInfo.GetLineCap();
704 maDash = XDash(css::drawing::DashStyle_RECT,
705 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
706 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
707 rLineInfo.GetDistance());
708 SetAttributes(pPath);
709 mnLineWidth = 0;
710 maLineJoin = basegfx::B2DLINEJOIN_NONE;
711 maDash = XDash();
712 InsertObj(pPath, false);
717 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction& rAct)
719 SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
720 SetAttributes(pRect);
721 InsertObj(pRect);
724 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction& rAct)
726 SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
727 SetAttributes(pRect);
728 long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
729 if (nRad!=0) {
730 SfxItemSet aSet(*mpLineAttr->GetPool(), SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS, 0, 0);
731 aSet.Put(SdrMetricItem(SDRATTR_ECKENRADIUS, nRad));
732 pRect->SetMergedItemSet(aSet);
734 InsertObj(pRect);
737 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction& rAct)
739 SdrCircObj* pCirc=new SdrCircObj(OBJ_CIRC,rAct.GetRect());
740 SetAttributes(pCirc);
741 InsertObj(pCirc);
744 void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction& rAct)
746 Point aCenter(rAct.GetRect().Center());
747 long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
748 long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
749 SdrCircObj* pCirc=new SdrCircObj(OBJ_CARC,rAct.GetRect(),nStart,nEnd);
750 SetAttributes(pCirc);
751 InsertObj(pCirc);
754 void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction& rAct)
756 Point aCenter(rAct.GetRect().Center());
757 long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
758 long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
759 SdrCircObj* pCirc=new SdrCircObj(OBJ_SECT,rAct.GetRect(),nStart,nEnd);
760 SetAttributes(pCirc);
761 InsertObj(pCirc);
764 void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction& rAct)
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_CCUT,rAct.GetRect(),nStart,nEnd);
770 SetAttributes(pCirc);
771 InsertObj(pCirc);
774 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
776 // #i102706# Do not merge closed polygons
777 if(rSrcPoly.isClosed())
779 return false;
782 // #i73407# reformulation to use new B2DPolygon classes
783 if(mbLastObjWasLine && (maOldLineColor == mpVD->GetLineColor()) && rSrcPoly.count())
785 SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : 0;
786 SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
788 if(pLastPoly)
790 if(1L == pLastPoly->GetPathPoly().count())
792 bool bOk(false);
793 basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0L));
795 // #i102706# Do not merge closed polygons
796 if(aDstPoly.isClosed())
798 return false;
801 if(aDstPoly.count())
803 const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1L);
804 const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1L);
806 if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0L))
808 aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
809 bOk = true;
811 else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
813 basegfx::B2DPolygon aNew(rSrcPoly);
814 aNew.append(aDstPoly, 1L, aDstPoly.count() - 1L);
815 aDstPoly = aNew;
816 bOk = true;
818 else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(0L))
820 aDstPoly.flip();
821 aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
822 bOk = true;
824 else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
826 basegfx::B2DPolygon aNew(rSrcPoly);
827 aNew.flip();
828 aDstPoly.append(aNew, 1L, aNew.count() - 1L);
829 bOk = true;
833 if(bOk)
835 pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
838 return bOk;
843 return false;
846 bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
848 // #i73407# reformulation to use new B2DPolygon classes
849 if(mbLastObjWasPolyWithoutLine)
851 SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : 0;
852 SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
854 if(pLastPoly)
856 if(pLastPoly->GetPathPoly() == rPolyPolygon)
858 SetAttributes(NULL);
860 if(!mbNoLine && mbNoFill)
862 pLastPoly->SetMergedItemSet(*mpLineAttr);
864 return true;
870 return false;
873 void ImpSdrGDIMetaFileImport::checkClip()
875 if(mpVD->IsClipRegion())
877 maClip = mpVD->GetClipRegion().GetAsB2DPolyPolygon();
879 if(isClip())
881 const basegfx::B2DHomMatrix aTransform(
882 basegfx::tools::createScaleTranslateB2DHomMatrix(
883 mfScaleX,
884 mfScaleY,
885 maOfs.X(),
886 maOfs.Y()));
888 maClip.transform(aTransform);
893 bool ImpSdrGDIMetaFileImport::isClip() const
895 return !maClip.getB2DRange().isEmpty();
898 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct )
900 // #i73407# reformulation to use new B2DPolygon classes
901 basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
903 if(aSource.count())
905 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
906 aSource.transform(aTransform);
909 const LineInfo& rLineInfo = rAct.GetLineInfo();
910 const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
911 bool bCreateLineObject(true);
913 if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aSource))
915 bCreateLineObject = false;
917 else if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
919 bCreateLineObject = false;
922 if(bCreateLineObject)
924 SdrPathObj* pPath = new SdrPathObj(
925 aSource.isClosed() ? OBJ_POLY : OBJ_PLIN,
926 basegfx::B2DPolyPolygon(aSource));
927 mnLineWidth = nNewLineWidth;
928 maLineJoin = rLineInfo.GetLineJoin();
929 maLineCap = rLineInfo.GetLineCap();
930 maDash = XDash(css::drawing::DashStyle_RECT,
931 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
932 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
933 rLineInfo.GetDistance());
934 SetAttributes(pPath);
935 mnLineWidth = 0;
936 maLineJoin = basegfx::B2DLINEJOIN_NONE;
937 maDash = XDash();
938 InsertObj(pPath, false);
942 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct )
944 // #i73407# reformulation to use new B2DPolygon classes
945 basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
947 if(aSource.count())
949 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
950 aSource.transform(aTransform);
952 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
954 // #i73407# make sure polygon is closed, it's a filled primitive
955 aSource.setClosed(true);
956 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource));
957 SetAttributes(pPath);
958 InsertObj(pPath, false);
963 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct)
965 // #i73407# reformulation to use new B2DPolygon classes
966 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
968 if(aSource.count())
970 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
971 aSource.transform(aTransform);
973 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
975 // #i73407# make sure polygon is closed, it's a filled primitive
976 aSource.setClosed(true);
977 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
978 SetAttributes(pPath);
979 InsertObj(pPath, false);
984 void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const OUString& rStr, const MetaAction& rAct )
986 // calc text box size, add 5% to make it fit safely
988 FontMetric aFontMetric( mpVD->GetFontMetric() );
989 vcl::Font aFnt( mpVD->GetFont() );
990 FontAlign eAlg( aFnt.GetAlign() );
992 sal_Int32 nTextWidth = (sal_Int32)( mpVD->GetTextWidth( rStr ) * mfScaleX );
993 sal_Int32 nTextHeight = (sal_Int32)( mpVD->GetTextHeight() * mfScaleY );
995 Point aPos( FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()) );
996 Size aSize( nTextWidth, nTextHeight );
998 if ( eAlg == ALIGN_BASELINE )
999 aPos.Y() -= FRound(aFontMetric.GetAscent() * mfScaleY);
1000 else if ( eAlg == ALIGN_BOTTOM )
1001 aPos.Y() -= nTextHeight;
1003 Rectangle aTextRect( aPos, aSize );
1004 SdrRectObj* pText =new SdrRectObj( OBJ_TEXT, aTextRect );
1006 pText->SetMergedItem ( makeSdrTextUpperDistItem (0));
1007 pText->SetMergedItem ( makeSdrTextLowerDistItem (0));
1008 pText->SetMergedItem ( makeSdrTextRightDistItem (0));
1009 pText->SetMergedItem ( makeSdrTextLeftDistItem (0));
1011 if ( aFnt.GetWidth() || ( rAct.GetType() == MetaActionType::STRETCHTEXT ) )
1013 pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
1014 pText->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
1015 // don't let the margins eat the space needed for the text
1016 pText->SetMergedItem( SdrTextFitToSizeTypeItem( SDRTEXTFIT_ALLLINES ) );
1018 else
1020 pText->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
1023 pText->SetModel(mpModel);
1024 pText->SetLayer(mnLayer);
1025 pText->NbcSetText( rStr );
1026 SetAttributes( pText, true );
1027 pText->SetSnapRect( aTextRect );
1029 if (!aFnt.IsTransparent())
1031 SfxItemSet aAttr(*mpFillAttr->GetPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST, 0, 0);
1032 aAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID));
1033 aAttr.Put(XFillColorItem(OUString(), aFnt.GetFillColor()));
1034 pText->SetMergedItemSet(aAttr);
1036 sal_uInt32 nAngle = aFnt.GetOrientation();
1037 if ( nAngle )
1039 nAngle*=10;
1040 double a=nAngle*nPi180;
1041 double nSin=sin(a);
1042 double nCos=cos(a);
1043 pText->NbcRotate(aPos,nAngle,nSin,nCos);
1045 InsertObj( pText, false );
1048 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction& rAct)
1050 OUString aStr(rAct.GetText());
1051 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1052 ImportText( rAct.GetPoint(), aStr, rAct );
1055 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction& rAct)
1057 OUString aStr(rAct.GetText());
1058 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1059 ImportText( rAct.GetPoint(), aStr, rAct );
1062 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction& rAct)
1064 OUString aStr(rAct.GetText());
1065 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1066 ImportText( rAct.GetPoint(), aStr, rAct );
1069 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction& rAct)
1071 Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
1072 aRect.Right()++; aRect.Bottom()++;
1073 SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
1075 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1076 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1077 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1078 InsertObj(pGraf);
1081 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction& rAct)
1083 Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1084 aRect.Right()++; aRect.Bottom()++;
1085 SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
1087 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1088 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1089 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1090 InsertObj(pGraf);
1093 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction& rAct)
1095 Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
1096 aRect.Right()++; aRect.Bottom()++;
1097 SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
1099 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1100 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1101 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1102 InsertObj(pGraf);
1105 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction& rAct)
1107 Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1108 aRect.Right()++; aRect.Bottom()++;
1109 SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
1111 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1112 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1113 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1114 InsertObj(pGraf);
1119 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction& rAct )
1121 // #i73407# reformulation to use new B2DPolygon classes
1122 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1124 if(aSource.count())
1126 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1127 aSource.transform(aTransform);
1129 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1131 const Hatch& rHatch = rAct.GetHatch();
1132 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1133 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1134 SfxItemSet aHatchAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1135 css::drawing::HatchStyle eStyle;
1137 switch(rHatch.GetStyle())
1139 case(HATCH_TRIPLE) :
1141 eStyle = css::drawing::HatchStyle_TRIPLE;
1142 break;
1145 case(HATCH_DOUBLE) :
1147 eStyle = css::drawing::HatchStyle_DOUBLE;
1148 break;
1151 default:
1153 eStyle = css::drawing::HatchStyle_SINGLE;
1154 break;
1158 SetAttributes(pPath);
1159 aHatchAttr.Put(XFillStyleItem(drawing::FillStyle_HATCH));
1160 aHatchAttr.Put(XFillHatchItem(&mpModel->GetItemPool(), XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
1161 pPath->SetMergedItemSet(aHatchAttr);
1163 InsertObj(pPath, false);
1170 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
1172 rAct.Execute(mpVD);
1175 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
1177 MapScaling();
1178 rAct.Execute(mpVD);
1179 mbLastObjWasPolyWithoutLine = false;
1180 mbLastObjWasLine = false;
1183 void ImpSdrGDIMetaFileImport::MapScaling()
1185 const size_t nCount(maTmpList.size());
1186 const MapMode& rMap = mpVD->GetMapMode();
1187 Point aMapOrg( rMap.GetOrigin() );
1188 bool bMov2(aMapOrg.X() != 0 || aMapOrg.Y() != 0);
1190 if(bMov2)
1192 for(size_t i = mnMapScalingOfs; i < nCount; i++)
1194 SdrObject* pObj = maTmpList[i];
1196 pObj->NbcMove(Size(aMapOrg.X(), aMapOrg.Y()));
1200 mnMapScalingOfs = nCount;
1205 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction& rAct, GDIMetaFile& rMtf, sal_uLong& a) // GDIMetaFile* pMtf )
1207 bool aSkipComment = false;
1209 if (a < rMtf.GetActionSize() && rAct.GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
1211 // #i125211# Check if next action is a MetaGradientExAction
1212 MetaGradientExAction* pAct = dynamic_cast< MetaGradientExAction* >(rMtf.GetAction(a + 1));
1214 if( pAct && pAct->GetType() == MetaActionType::GRADIENTEX )
1216 // #i73407# reformulation to use new B2DPolygon classes
1217 basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
1219 if(aSource.count())
1221 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1223 const Gradient& rGrad = pAct->GetGradient();
1224 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1225 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1226 SfxItemSet aGradAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1227 XGradient aXGradient;
1229 aXGradient.SetGradientStyle((css::awt::GradientStyle)rGrad.GetStyle());
1230 aXGradient.SetStartColor(rGrad.GetStartColor());
1231 aXGradient.SetEndColor(rGrad.GetEndColor());
1232 aXGradient.SetAngle((sal_uInt16)rGrad.GetAngle());
1233 aXGradient.SetBorder(rGrad.GetBorder());
1234 aXGradient.SetXOffset(rGrad.GetOfsX());
1235 aXGradient.SetYOffset(rGrad.GetOfsY());
1236 aXGradient.SetStartIntens(rGrad.GetStartIntensity());
1237 aXGradient.SetEndIntens(rGrad.GetEndIntensity());
1238 aXGradient.SetSteps(rGrad.GetSteps());
1240 // no need to use SetAttributes(..) here since line and fill style
1241 // need to be set individually
1242 // SetAttributes(pPath);
1244 // switch line off; if there was one there will be a
1245 // MetaActionType::POLYLINE following creating another object
1246 aGradAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
1248 // add detected gradient fillstyle
1249 aGradAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT));
1250 aGradAttr.Put(XFillGradientItem(aXGradient));
1252 pPath->SetMergedItemSet(aGradAttr);
1254 InsertObj(pPath);
1258 aSkipComment = true;
1262 if(aSkipComment)
1264 // #i125211# forward until closing MetaCommentAction
1265 MetaAction* pSkipAct = rMtf.GetAction(++a);
1267 while( pSkipAct
1268 && ((pSkipAct->GetType() != MetaActionType::COMMENT )
1269 || !(static_cast<MetaCommentAction*>(pSkipAct)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END"))))
1271 pSkipAct = rMtf.GetAction(++a);
1276 void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction& rAct)
1278 GDIMetaFile aTemp;
1280 mpVD->AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
1281 DoLoopActions(aTemp, 0, 0);
1284 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction& rAct)
1286 Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1287 Bitmap aBitmap(rAct.GetBitmap());
1289 aRect.Right()++;
1290 aRect.Bottom()++;
1291 aBitmap.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1292 SdrGrafObj* pGraf = new SdrGrafObj(aBitmap, aRect);
1294 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1295 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1296 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1297 InsertObj(pGraf);
1300 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction& rAct)
1302 Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
1303 BitmapEx aBitmapEx(rAct.GetBitmapEx());
1305 aRect.Right()++;
1306 aRect.Bottom()++;
1307 aBitmapEx.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1308 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1310 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1311 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1312 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1313 InsertObj(pGraf);
1316 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction& rAct)
1318 Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
1319 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1321 aRect.Right()++; aRect.Bottom()++;
1322 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1324 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1325 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1326 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1327 InsertObj(pGraf);
1330 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction& rAct)
1332 Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
1333 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1335 aRect.Right()++; aRect.Bottom()++;
1336 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1338 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1339 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1340 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1341 InsertObj(pGraf);
1344 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction& rAct)
1346 Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1347 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1349 aRect.Right()++; aRect.Bottom()++;
1350 aBitmapEx.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1351 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1353 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1354 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1355 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1356 InsertObj(pGraf);
1359 namespace
1361 css::awt::GradientStyle getXGradientStyleFromGradientStyle(const GradientStyle& rGradientStyle)
1363 css::awt::GradientStyle aXGradientStyle(css::awt::GradientStyle_LINEAR);
1365 switch(rGradientStyle)
1367 case GradientStyle_LINEAR: aXGradientStyle = css::awt::GradientStyle_LINEAR; break;
1368 case GradientStyle_AXIAL: aXGradientStyle = css::awt::GradientStyle_AXIAL; break;
1369 case GradientStyle_RADIAL: aXGradientStyle = css::awt::GradientStyle_RADIAL; break;
1370 case GradientStyle_ELLIPTICAL: aXGradientStyle = css::awt::GradientStyle_ELLIPTICAL; break;
1371 case GradientStyle_SQUARE: aXGradientStyle = css::awt::GradientStyle_SQUARE; break;
1372 case GradientStyle_RECT: aXGradientStyle = css::awt::GradientStyle_RECT; break;
1374 // Needed due to GradientStyle_FORCE_EQUAL_SIZE; this again is needed
1375 // to force the enum defines in VCL to a defined size for the compilers,
1376 // so despite it is never used it cannot be removed (would break the
1377 // API implementation probably).
1378 case GradientStyle_FORCE_EQUAL_SIZE: break;
1379 default:
1380 break;
1383 return aXGradientStyle;
1387 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction& rAct)
1389 basegfx::B2DRange aRange(rAct.GetRect().Left(), rAct.GetRect().Top(), rAct.GetRect().Right(), rAct.GetRect().Bottom());
1391 if(!aRange.isEmpty())
1393 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1394 aRange.transform(aTransform);
1395 const Gradient& rGradient = rAct.GetGradient();
1396 SdrRectObj* pRect = new SdrRectObj(
1397 Rectangle(
1398 floor(aRange.getMinX()),
1399 floor(aRange.getMinY()),
1400 ceil(aRange.getMaxX()),
1401 ceil(aRange.getMaxY())));
1402 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1403 SfxItemSet aGradientAttr(mpModel->GetItemPool(), pRect->GetMergedItemSet().GetRanges());
1404 const css::awt::GradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1405 const XFillGradientItem aXFillGradientItem(
1406 XGradient(
1407 rGradient.GetStartColor(),
1408 rGradient.GetEndColor(),
1409 aXGradientStyle,
1410 rGradient.GetAngle(),
1411 rGradient.GetOfsX(),
1412 rGradient.GetOfsY(),
1413 rGradient.GetBorder(),
1414 rGradient.GetStartIntensity(),
1415 rGradient.GetEndIntensity(),
1416 rGradient.GetSteps()));
1418 SetAttributes(pRect);
1419 aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1420 aGradientAttr.Put(aXFillGradientItem);
1421 pRect->SetMergedItemSet(aGradientAttr);
1423 InsertObj(pRect, false);
1427 void ImpSdrGDIMetaFileImport::DoAction(MetaWallpaperAction&)
1429 OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)");
1432 void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction& rAct)
1434 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1436 if(aSource.count())
1438 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1439 aSource.transform(aTransform);
1440 aSource.setClosed(true);
1442 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1443 SetAttributes(pPath);
1444 pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
1445 InsertObj(pPath, false);
1449 void ImpSdrGDIMetaFileImport::DoAction(MetaEPSAction&)
1451 OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)");
1454 void ImpSdrGDIMetaFileImport::DoAction(MetaTextLineAction&)
1456 OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)");
1459 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction& rAct)
1461 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1463 if(aSource.count())
1465 const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1466 aSource.transform(aTransform);
1468 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1470 const Gradient& rGradient = rAct.GetGradient();
1471 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1472 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1473 SfxItemSet aGradientAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1474 const css::awt::GradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1475 const XFillGradientItem aXFillGradientItem(
1476 XGradient(
1477 rGradient.GetStartColor(),
1478 rGradient.GetEndColor(),
1479 aXGradientStyle,
1480 rGradient.GetAngle(),
1481 rGradient.GetOfsX(),
1482 rGradient.GetOfsY(),
1483 rGradient.GetBorder(),
1484 rGradient.GetStartIntensity(),
1485 rGradient.GetEndIntensity(),
1486 rGradient.GetSteps()));
1488 SetAttributes(pPath);
1489 aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1490 aGradientAttr.Put(aXFillGradientItem);
1491 pPath->SetMergedItemSet(aGradientAttr);
1493 InsertObj(pPath, false);
1498 void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction& rAct)
1500 const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
1502 if(rMtf.GetActionSize())
1504 const Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1506 // convert metafile sub-content to BitmapEx
1507 BitmapEx aBitmapEx(
1508 convertMetafileToBitmapEx(
1509 rMtf,
1510 basegfx::B2DRange(
1511 aRect.Left(), aRect.Top(),
1512 aRect.Right(), aRect.Bottom()),
1513 125000));
1515 // handle colors
1516 const Gradient& rGradient = rAct.GetGradient();
1517 basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
1518 basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
1520 if(100 != rGradient.GetStartIntensity())
1522 aStart *= (double)rGradient.GetStartIntensity() / 100.0;
1525 if(100 != rGradient.GetEndIntensity())
1527 aEnd *= (double)rGradient.GetEndIntensity() / 100.0;
1530 const bool bEqualColors(aStart == aEnd);
1531 const bool bNoSteps(1 == rGradient.GetSteps());
1532 bool bCreateObject(true);
1533 bool bHasNewMask(false);
1534 AlphaMask aNewMask;
1535 double fTransparence(0.0);
1536 bool bFixedTransparence(false);
1538 if(bEqualColors || bNoSteps)
1540 // single transparence
1541 const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
1542 fTransparence = aMedium.luminance();
1544 if(basegfx::fTools::lessOrEqual(fTransparence, 0.0))
1546 // no transparence needed, all done
1548 else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
1550 // all transparent, no object
1551 bCreateObject = false;
1553 else
1555 // 0.0 < transparence < 1.0, apply fixed transparence
1556 bFixedTransparence = true;
1559 else
1561 // gradient transparence
1562 ScopedVclPtrInstance< VirtualDevice > pVDev;
1564 pVDev->SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
1565 pVDev->DrawGradient(Rectangle(Point(0, 0), pVDev->GetOutputSizePixel()), rGradient);
1567 aNewMask = AlphaMask(pVDev->GetBitmap(Point(0, 0), pVDev->GetOutputSizePixel()));
1568 bHasNewMask = true;
1571 if(bCreateObject)
1573 if(bHasNewMask || bFixedTransparence)
1575 if(!aBitmapEx.IsAlpha() && !aBitmapEx.IsTransparent())
1577 // no transparence yet, apply new one
1578 if(bFixedTransparence)
1580 sal_uInt8 aAlpha(basegfx::fround(fTransparence * 255.0));
1582 aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), &aAlpha);
1585 aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
1587 else
1589 // mix existing and new alpha mask
1590 AlphaMask aOldMask;
1592 if(aBitmapEx.IsAlpha())
1594 aOldMask = aBitmapEx.GetAlpha();
1596 else if(TRANSPARENT_BITMAP == aBitmapEx.GetTransparentType())
1598 aOldMask = aBitmapEx.GetMask();
1600 else if(TRANSPARENT_COLOR == aBitmapEx.GetTransparentType())
1602 aOldMask = aBitmapEx.GetBitmap().CreateMask(aBitmapEx.GetTransparentColor());
1605 BitmapWriteAccess* pOld = aOldMask.AcquireWriteAccess();
1607 if(pOld)
1609 const double fFactor(1.0 / 255.0);
1611 if(bFixedTransparence)
1613 const double fOpNew(1.0 - fTransparence);
1615 for(int y(0); y < pOld->Height(); y++)
1617 for(int x(0); x < pOld->Width(); x++)
1619 const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1620 const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1622 pOld->SetPixel(y, x, BitmapColor(aCol));
1626 else
1628 BitmapReadAccess* pNew = aNewMask.AcquireReadAccess();
1630 if(pNew)
1632 if(pOld->Width() == pNew->Width() && pOld->Height() == pNew->Height())
1634 for(int y(0); y < pOld->Height(); y++)
1636 for(int x(0); x < pOld->Width(); x++)
1638 const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1639 const double fOpNew(1.0 - (pNew->GetPixel(y, x).GetIndex() * fFactor));
1640 const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1642 pOld->SetPixel(y, x, BitmapColor(aCol));
1646 else
1648 OSL_ENSURE(false, "Alpha masks have different sizes (!)");
1651 aNewMask.ReleaseAccess(pNew);
1653 else
1655 OSL_ENSURE(false, "Got no access to new alpha mask (!)");
1659 aOldMask.ReleaseAccess(pOld);
1661 else
1663 OSL_ENSURE(false, "Got no access to old alpha mask (!)");
1666 // apply combined bitmap as mask
1667 aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aOldMask);
1671 // create and add object
1672 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1674 // for MetaFloatTransparentAction, do not use SetAttributes(...)
1675 // since these metafile content is not used to draw line/fill
1676 // dependent of these setting at the device content
1677 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1678 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1679 InsertObj(pGraf);
1684 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */