Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / svx / source / svdraw / svdfmtf.cxx
blob278b93c407a1fbbf08975f61a0d73500f778ea53
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 <math.h>
22 #include <editeng/eeitem.hxx>
23 #include <editeng/fhgtitem.hxx>
24 #include <editeng/wghtitem.hxx>
25 #include <editeng/postitem.hxx>
26 #include <editeng/udlnitem.hxx>
27 #include <editeng/crossedoutitem.hxx>
28 #include <editeng/shdditem.hxx>
29 #include <svx/xlineit0.hxx>
30 #include <svx/xlnclit.hxx>
31 #include <svx/xlncapit.hxx>
32 #include <svx/xlnwtit.hxx>
33 #include <svx/xfillit0.hxx>
34 #include <svx/xflclit.hxx>
35 #include <svx/xgrad.hxx>
36 #include <svx/xflgrit.hxx>
37 #include <editeng/fontitem.hxx>
38 #include <editeng/wrlmitem.hxx>
39 #include <editeng/contouritem.hxx>
40 #include <editeng/colritem.hxx>
41 #include <vcl/canvastools.hxx>
42 #include <vcl/metric.hxx>
43 #include <editeng/charscaleitem.hxx>
44 #include <svx/xflhtit.hxx>
45 #include <svx/sdmetitm.hxx>
46 #include <svx/sdtagitm.hxx>
47 #include <svx/sdtaitm.hxx>
48 #include <svx/sdtditm.hxx>
49 #include <svx/sdtfsitm.hxx>
50 #include <svx/svdmodel.hxx>
51 #include <svx/svdpage.hxx>
52 #include <svx/svdobj.hxx>
53 #include <svx/svdotext.hxx>
54 #include <svx/svdorect.hxx>
55 #include <svx/svdocirc.hxx>
56 #include <svx/svdograf.hxx>
57 #include <svx/svdopath.hxx>
58 #include <svx/svdetc.hxx>
59 #include <svl/itemset.hxx>
60 #include <basegfx/polygon/b2dpolygon.hxx>
61 #include <tools/helpers.hxx>
62 #include <basegfx/matrix/b2dhommatrix.hxx>
63 #include <basegfx/matrix/b2dhommatrixtools.hxx>
64 #include <svx/xlinjoit.hxx>
65 #include <svx/xlndsit.hxx>
66 #include <basegfx/polygon/b2dpolygonclipper.hxx>
67 #include <svx/xbtmpit.hxx>
68 #include <svx/xfltrit.hxx>
69 #include <svx/xflbmtit.hxx>
70 #include <svx/xflbstit.hxx>
71 #include <svx/svdpntv.hxx>
72 #include <basegfx/polygon/b2dpolypolygontools.hxx>
73 #include <svx/svditer.hxx>
74 #include <svx/svdogrp.hxx>
75 #include <vcl/BitmapTools.hxx>
77 using namespace com::sun::star;
79 ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
80 SdrModel& rModel,
81 SdrLayerID nLay,
82 const tools::Rectangle& rRect)
83 : maTmpList(),
84 mpVD(VclPtr<VirtualDevice>::Create()),
85 maScaleRect(rRect),
86 mnMapScalingOfs(0),
87 mpModel(&rModel),
88 mnLayer(nLay),
89 maOldLineColor(),
90 mnLineWidth(0),
91 maLineJoin(basegfx::B2DLineJoin::NONE),
92 maLineCap(css::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 = std::make_unique<SfxItemSet>(rModel.GetItemPool(), svl::Items<XATTR_LINE_FIRST, XATTR_LINE_LAST>{});
113 mpFillAttr = std::make_unique<SfxItemSet>(rModel.GetItemPool(), svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{});
114 mpTextAttr = std::make_unique<SfxItemSet>(rModel.GetItemPool(), svl::Items<EE_ITEMS_START, EE_ITEMS_END>{});
115 checkClip();
118 void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile const & rMtf, SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
120 const sal_uLong nCount(rMtf.GetActionSize());
122 for(sal_uLong a(0); a < nCount; a++)
124 MetaAction* pAct = rMtf.GetAction(a);
126 if(!pAct)
128 OSL_ENSURE(false, "OOps, no action at valid position (!)");
129 pAct = rMtf.GetAction(0);
132 switch (pAct->GetType())
134 case MetaActionType::PIXEL : break;
135 case MetaActionType::POINT : break;
136 case MetaActionType::LINE : DoAction(static_cast<MetaLineAction &>(*pAct)); break;
137 case MetaActionType::RECT : DoAction(static_cast<MetaRectAction &>(*pAct)); break;
138 case MetaActionType::ROUNDRECT : DoAction(static_cast<MetaRoundRectAction &>(*pAct)); break;
139 case MetaActionType::ELLIPSE : DoAction(static_cast<MetaEllipseAction &>(*pAct)); break;
140 case MetaActionType::ARC : DoAction(static_cast<MetaArcAction &>(*pAct)); break;
141 case MetaActionType::PIE : DoAction(static_cast<MetaPieAction &>(*pAct)); break;
142 case MetaActionType::CHORD : DoAction(static_cast<MetaChordAction &>(*pAct)); break;
143 case MetaActionType::POLYLINE : DoAction(static_cast<MetaPolyLineAction &>(*pAct)); break;
144 case MetaActionType::POLYGON : DoAction(static_cast<MetaPolygonAction &>(*pAct)); break;
145 case MetaActionType::POLYPOLYGON : DoAction(static_cast<MetaPolyPolygonAction &>(*pAct)); break;
146 case MetaActionType::TEXT : DoAction(static_cast<MetaTextAction &>(*pAct)); break;
147 case MetaActionType::TEXTARRAY : DoAction(static_cast<MetaTextArrayAction &>(*pAct)); break;
148 case MetaActionType::STRETCHTEXT : DoAction(static_cast<MetaStretchTextAction &>(*pAct)); break;
149 case MetaActionType::BMP : DoAction(static_cast<MetaBmpAction &>(*pAct)); break;
150 case MetaActionType::BMPSCALE : DoAction(static_cast<MetaBmpScaleAction &>(*pAct)); break;
151 case MetaActionType::BMPEX : DoAction(static_cast<MetaBmpExAction &>(*pAct)); break;
152 case MetaActionType::BMPEXSCALE : DoAction(static_cast<MetaBmpExScaleAction &>(*pAct)); break;
153 case MetaActionType::LINECOLOR : DoAction(static_cast<MetaLineColorAction &>(*pAct)); break;
154 case MetaActionType::FILLCOLOR : DoAction(static_cast<MetaFillColorAction &>(*pAct)); break;
155 case MetaActionType::TEXTCOLOR : DoAction(static_cast<MetaTextColorAction &>(*pAct)); break;
156 case MetaActionType::TEXTFILLCOLOR : DoAction(static_cast<MetaTextFillColorAction &>(*pAct)); break;
157 case MetaActionType::FONT : DoAction(static_cast<MetaFontAction &>(*pAct)); break;
158 case MetaActionType::TEXTALIGN : DoAction(static_cast<MetaTextAlignAction &>(*pAct)); break;
159 case MetaActionType::MAPMODE : DoAction(static_cast<MetaMapModeAction &>(*pAct)); break;
160 case MetaActionType::CLIPREGION : DoAction(static_cast<MetaClipRegionAction &>(*pAct)); break;
161 case MetaActionType::MOVECLIPREGION : DoAction(static_cast<MetaMoveClipRegionAction &>(*pAct)); break;
162 case MetaActionType::ISECTRECTCLIPREGION: DoAction(static_cast<MetaISectRectClipRegionAction&>(*pAct)); break;
163 case MetaActionType::ISECTREGIONCLIPREGION: DoAction(static_cast<MetaISectRegionClipRegionAction&>(*pAct)); break;
164 case MetaActionType::RASTEROP : DoAction(static_cast<MetaRasterOpAction &>(*pAct)); break;
165 case MetaActionType::PUSH : DoAction(static_cast<MetaPushAction &>(*pAct)); break;
166 case MetaActionType::POP : DoAction(static_cast<MetaPopAction &>(*pAct)); break;
167 case MetaActionType::HATCH : DoAction(static_cast<MetaHatchAction &>(*pAct)); break;
169 // #i125211# MetaCommentAction may change index, thus hand it over
170 case MetaActionType::COMMENT : DoAction(static_cast<MetaCommentAction&>(*pAct), rMtf, a);
171 break;
173 // missing actions added
174 case MetaActionType::TEXTRECT : DoAction(static_cast<MetaTextRectAction&>(*pAct)); break;
175 case MetaActionType::BMPSCALEPART : DoAction(static_cast<MetaBmpScalePartAction&>(*pAct)); break;
176 case MetaActionType::BMPEXSCALEPART : DoAction(static_cast<MetaBmpExScalePartAction&>(*pAct)); break;
177 case MetaActionType::MASK : DoAction(static_cast<MetaMaskAction&>(*pAct)); break;
178 case MetaActionType::MASKSCALE : DoAction(static_cast<MetaMaskScaleAction&>(*pAct)); break;
179 case MetaActionType::MASKSCALEPART : DoAction(static_cast<MetaMaskScalePartAction&>(*pAct)); break;
180 case MetaActionType::GRADIENT : DoAction(static_cast<MetaGradientAction&>(*pAct)); break;
181 case MetaActionType::WALLPAPER : OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)"); break;
182 case MetaActionType::Transparent : DoAction(static_cast<MetaTransparentAction&>(*pAct)); break;
183 case MetaActionType::EPS : OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)"); break;
184 case MetaActionType::REFPOINT : DoAction(static_cast<MetaRefPointAction&>(*pAct)); break;
185 case MetaActionType::TEXTLINECOLOR : DoAction(static_cast<MetaTextLineColorAction&>(*pAct)); break;
186 case MetaActionType::TEXTLINE : OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)"); break;
187 case MetaActionType::FLOATTRANSPARENT : DoAction(static_cast<MetaFloatTransparentAction&>(*pAct)); break;
188 case MetaActionType::GRADIENTEX : DoAction(static_cast<MetaGradientExAction&>(*pAct)); break;
189 case MetaActionType::LAYOUTMODE : DoAction(static_cast<MetaLayoutModeAction&>(*pAct)); break;
190 case MetaActionType::TEXTLANGUAGE : DoAction(static_cast<MetaTextLanguageAction&>(*pAct)); break;
191 case MetaActionType::OVERLINECOLOR : DoAction(static_cast<MetaOverlineColorAction&>(*pAct)); break;
192 default: break;
195 if(pProgrInfo && pActionsToReport)
197 (*pActionsToReport)++;
199 if(*pActionsToReport >= 16) // update all 16 actions
201 if(!pProgrInfo->ReportActions(*pActionsToReport))
202 break;
204 *pActionsToReport = 0;
210 size_t ImpSdrGDIMetaFileImport::DoImport(
211 const GDIMetaFile& rMtf,
212 SdrObjList& rOL,
213 size_t nInsPos,
214 SvdProgressInfo* pProgrInfo)
216 // setup some global scale parameter
217 // mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
218 mfScaleX = mfScaleY = 1.0;
219 const Size aMtfSize(rMtf.GetPrefSize());
221 if(aMtfSize.Width() & aMtfSize.Height() && (!maScaleRect.IsEmpty()))
223 maOfs = maScaleRect.TopLeft();
225 if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
227 mfScaleX = static_cast<double>( maScaleRect.GetWidth() - 1 ) / static_cast<double>(aMtfSize.Width());
230 if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
232 mfScaleY = static_cast<double>( maScaleRect.GetHeight() - 1 ) / static_cast<double>(aMtfSize.Height());
236 mbMov = maOfs.X()!=0 || maOfs.Y()!=0;
237 mbSize = false;
238 maScaleX = Fraction( 1, 1 );
239 maScaleY = Fraction( 1, 1 );
241 if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
243 maScaleX = Fraction(maScaleRect.GetWidth() - 1, aMtfSize.Width());
244 mbSize = true;
247 if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
249 maScaleY = Fraction(maScaleRect.GetHeight() - 1, aMtfSize.Height());
250 mbSize = true;
253 if(pProgrInfo)
255 pProgrInfo->SetActionCount(rMtf.GetActionSize());
258 sal_uInt32 nActionsToReport(0);
260 // execute
261 DoLoopActions(rMtf, pProgrInfo, &nActionsToReport);
263 if(pProgrInfo)
265 pProgrInfo->ReportActions(nActionsToReport);
266 nActionsToReport = 0;
269 // MapMode scaling
270 MapScaling();
272 // To calculate the progress meter, we use GetActionSize()*3.
273 // However, maTmpList has a lower entry count limit than GetActionSize(),
274 // so the actions that were assumed were too much have to be re-added.
275 nActionsToReport = (rMtf.GetActionSize() - maTmpList.size()) * 2;
277 // announce all currently unannounced rescales
278 if(pProgrInfo)
280 pProgrInfo->ReportRescales(nActionsToReport);
281 pProgrInfo->SetInsertCount(maTmpList.size());
284 nActionsToReport = 0;
286 // insert all objects cached in aTmpList now into rOL from nInsPos
287 nInsPos = std::min(nInsPos, rOL.GetObjCount());
289 for(SdrObject* pObj : maTmpList)
291 rOL.NbcInsertObject(pObj, nInsPos);
292 nInsPos++;
294 if(pProgrInfo)
296 nActionsToReport++;
298 if(nActionsToReport >= 32) // update all 32 actions
300 pProgrInfo->ReportInserts(nActionsToReport);
301 nActionsToReport = 0;
306 // report all remaining inserts for the last time
307 if(pProgrInfo)
309 pProgrInfo->ReportInserts(nActionsToReport);
312 return maTmpList.size();
315 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr)
317 mbNoLine = false;
318 mbNoFill = false;
319 bool bLine(!bForceTextAttr);
320 bool bFill(!pObj || (pObj->IsClosedObj() && !bForceTextAttr));
321 bool bText(bForceTextAttr || (pObj && pObj->GetOutlinerParaObject()));
323 if(bLine)
325 if(mnLineWidth)
327 mpLineAttr->Put(XLineWidthItem(mnLineWidth));
329 else
331 mpLineAttr->Put(XLineWidthItem(0));
334 maOldLineColor = mpVD->GetLineColor();
336 if(mpVD->IsLineColor())
338 mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_SOLID));
339 mpLineAttr->Put(XLineColorItem(OUString(), mpVD->GetLineColor()));
341 else
343 mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_NONE));
346 switch(maLineJoin)
348 case basegfx::B2DLineJoin::NONE:
349 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_NONE));
350 break;
351 case basegfx::B2DLineJoin::Bevel:
352 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_BEVEL));
353 break;
354 case basegfx::B2DLineJoin::Miter:
355 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_MITER));
356 break;
357 case basegfx::B2DLineJoin::Round:
358 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_ROUND));
359 break;
362 // Add LineCap support
363 mpLineAttr->Put(XLineCapItem(maLineCap));
365 if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance())
367 mpLineAttr->Put(XLineDashItem(OUString(), maDash));
369 else
371 mpLineAttr->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT)));
374 else
376 mbNoLine = true;
379 if(bFill)
381 if(mpVD->IsFillColor())
383 mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_SOLID));
384 mpFillAttr->Put(XFillColorItem(OUString(), mpVD->GetFillColor()));
386 else
388 mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_NONE));
391 else
393 mbNoFill = true;
396 if(bText && mbFntDirty)
398 vcl::Font aFnt(mpVD->GetFont());
399 const sal_uInt32 nHeight(FRound(aFnt.GetFontSize().Height() * mfScaleY));
401 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
402 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
403 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) );
404 mpTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC));
405 mpTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT));
406 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
407 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
408 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
409 mpTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
410 mpTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
411 mpTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
412 mpTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
413 mpTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
415 // #i118485# Setting this item leads to problems (written #i118498# for this)
416 // mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
418 mpTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
419 mpTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
420 mpTextAttr->Put(SvxColorItem(mpVD->GetTextColor(), EE_CHAR_COLOR));
421 //... svxfont textitem svditext
422 mbFntDirty = false;
425 if(!pObj)
426 return;
428 pObj->SetLayer(mnLayer);
430 if(bLine)
432 pObj->SetMergedItemSet(*mpLineAttr);
435 if(bFill)
437 pObj->SetMergedItemSet(*mpFillAttr);
440 if(bText)
442 pObj->SetMergedItemSet(*mpTextAttr);
443 pObj->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
447 void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj, bool bScale)
449 if(bScale && !maScaleRect.IsEmpty())
451 if(mbSize)
453 pObj->NbcResize(Point(), maScaleX, maScaleY);
456 if(mbMov)
458 pObj->NbcMove(Size(maOfs.X(), maOfs.Y()));
462 if(isClip())
464 const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
465 const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
466 const SdrLayerID aOldLayer(pObj->GetLayer());
467 const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
468 const SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
469 const SdrTextObj* pSdrTextObj = dynamic_cast< SdrTextObj* >(pObj);
471 if(pSdrTextObj && pSdrTextObj->HasText())
473 // all text objects are created from ImportText and have no line or fill attributes, so
474 // it is okay to concentrate on the text itself
475 while(true)
477 const basegfx::B2DPolyPolygon aTextContour(pSdrTextObj->TakeContour());
478 const basegfx::B2DRange aTextRange(aTextContour.getB2DRange());
479 const basegfx::B2DRange aClipRange(maClip.getB2DRange());
481 // no overlap -> completely outside
482 if(!aClipRange.overlaps(aTextRange))
484 SdrObject::Free(pObj);
485 break;
488 // when the clip is a rectangle fast check for inside is possible
489 if(basegfx::utils::isRectangle(maClip) && aClipRange.isInside(aTextRange))
491 // completely inside ClipRect
492 break;
495 // here text needs to be clipped; to do so, convert to SdrObjects with polygons
496 // and add these recursively. Delete original object, do not add in this run
497 SdrObject* pConverted = pSdrTextObj->ConvertToPolyObj(true, true).release();
498 SdrObject::Free(pObj);
500 if(pConverted)
502 // recursively add created conversion; per definition this shall not
503 // contain further SdrTextObjs. Visit only non-group objects
504 SdrObjListIter aIter(*pConverted, SdrIterMode::DeepNoGroups);
506 // work with clones; the created conversion may contain group objects
507 // and when working with the original objects the loop itself could
508 // break and the cleanup later would be pretty complicated (only delete group
509 // objects, are these empty, ...?)
510 while(aIter.IsMore())
512 SdrObject* pCandidate = aIter.Next();
513 OSL_ENSURE(pCandidate && dynamic_cast< SdrObjGroup* >(pCandidate) == nullptr, "SdrObjListIter with SdrIterMode::DeepNoGroups error (!)");
514 SdrObject* pNewClone(pCandidate->CloneSdrObject(pCandidate->getSdrModelFromSdrObject()));
516 if(pNewClone)
518 InsertObj(pNewClone, false);
520 else
522 OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
526 // cleanup temporary conversion objects
527 SdrObject::Free(pConverted);
530 break;
533 else
535 BitmapEx aBitmapEx;
537 if(pSdrGrafObj)
539 aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
542 SdrObject::Free(pObj);
544 if(!aOldRange.isEmpty())
546 // clip against ClipRegion
547 const basegfx::B2DPolyPolygon aNewPoly(
548 basegfx::utils::clipPolyPolygonOnPolyPolygon(
549 aPoly,
550 maClip,
551 true,
552 !aPoly.isClosed()));
553 const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
555 if(!aNewRange.isEmpty())
557 pObj = new SdrPathObj(
558 *mpModel,
559 aNewPoly.isClosed() ? OBJ_POLY : OBJ_PLIN,
560 aNewPoly);
562 pObj->SetLayer(aOldLayer);
563 pObj->SetMergedItemSet(aOldItemSet);
565 if(!!aBitmapEx)
567 // aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
568 const double fScaleX(aBitmapEx.GetSizePixel().Width() / (aOldRange.getWidth() ? aOldRange.getWidth() : 1.0));
569 const double fScaleY(aBitmapEx.GetSizePixel().Height() / (aOldRange.getHeight() ? aOldRange.getHeight() : 1.0));
570 basegfx::B2DRange aPixel(aNewRange);
571 basegfx::B2DHomMatrix aTrans;
573 aTrans.translate(-aOldRange.getMinX(), -aOldRange.getMinY());
574 aTrans.scale(fScaleX, fScaleY);
575 aPixel.transform(aTrans);
577 const Size aOrigSizePixel(aBitmapEx.GetSizePixel());
578 const Point aClipTopLeft(
579 basegfx::fround(floor(std::max(0.0, aPixel.getMinX()))),
580 basegfx::fround(floor(std::max(0.0, aPixel.getMinY()))));
581 const Size aClipSize(
582 basegfx::fround(ceil(std::min(static_cast<double>(aOrigSizePixel.Width()), aPixel.getWidth()))),
583 basegfx::fround(ceil(std::min(static_cast<double>(aOrigSizePixel.Height()), aPixel.getHeight()))));
584 const BitmapEx aClippedBitmap(
585 aBitmapEx,
586 aClipTopLeft,
587 aClipSize);
589 pObj->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
590 pObj->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap)));
591 pObj->SetMergedItem(XFillBmpTileItem(false));
592 pObj->SetMergedItem(XFillBmpStretchItem(true));
599 if(!pObj)
600 return;
602 // #i111954# check object for visibility
603 // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
604 bool bVisible(false);
606 if(pObj->HasLineStyle())
608 bVisible = true;
611 if(!bVisible && pObj->HasFillStyle())
613 bVisible = true;
616 if(!bVisible)
618 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >(pObj);
620 if(pTextObj && pTextObj->HasText())
622 bVisible = true;
626 if(!bVisible)
628 SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
630 if(pGrafObj)
632 // this may be refined to check if the graphic really is visible. It
633 // is here to ensure that graphic objects without fill, line and text
634 // get created
635 bVisible = true;
639 if(!bVisible)
641 SdrObject::Free(pObj);
643 else
645 maTmpList.push_back(pObj);
647 if(dynamic_cast< SdrPathObj* >(pObj))
649 const bool bClosed(pObj->IsClosedObj());
651 mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
652 mbLastObjWasLine = !bClosed;
654 else
656 mbLastObjWasPolyWithoutLine = false;
657 mbLastObjWasLine = false;
662 void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction const & rAct)
664 // #i73407# reformulation to use new B2DPolygon classes
665 const basegfx::B2DPoint aStart(rAct.GetStartPoint().X(), rAct.GetStartPoint().Y());
666 const basegfx::B2DPoint aEnd(rAct.GetEndPoint().X(), rAct.GetEndPoint().Y());
668 if(aStart.equal(aEnd))
669 return;
671 basegfx::B2DPolygon aLine;
672 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
674 aLine.append(aStart);
675 aLine.append(aEnd);
676 aLine.transform(aTransform);
678 const LineInfo& rLineInfo = rAct.GetLineInfo();
679 const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
680 bool bCreateLineObject(true);
682 if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aLine))
684 bCreateLineObject = false;
687 if(!bCreateLineObject)
688 return;
690 SdrPathObj* pPath = new SdrPathObj(
691 *mpModel,
692 OBJ_LINE,
693 basegfx::B2DPolyPolygon(aLine));
694 mnLineWidth = nNewLineWidth;
695 maLineJoin = rLineInfo.GetLineJoin();
696 maLineCap = rLineInfo.GetLineCap();
697 maDash = XDash(css::drawing::DashStyle_RECT,
698 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
699 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
700 rLineInfo.GetDistance());
701 SetAttributes(pPath);
702 mnLineWidth = 0;
703 maLineJoin = basegfx::B2DLineJoin::NONE;
704 maDash = XDash();
705 InsertObj(pPath, false);
708 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction const & rAct)
710 SdrRectObj* pRect = new SdrRectObj(
711 *mpModel,
712 rAct.GetRect());
713 SetAttributes(pRect);
714 InsertObj(pRect);
717 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction const & rAct)
719 SdrRectObj* pRect = new SdrRectObj(
720 *mpModel,
721 rAct.GetRect());
722 SetAttributes(pRect);
723 tools::Long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
724 if (nRad!=0) {
725 SfxItemSet aSet(*mpLineAttr->GetPool(), svl::Items<SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS>{});
726 aSet.Put(SdrMetricItem(SDRATTR_ECKENRADIUS, nRad));
727 pRect->SetMergedItemSet(aSet);
729 InsertObj(pRect);
732 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction const & rAct)
734 SdrCircObj* pCirc=new SdrCircObj(
735 *mpModel,
736 SdrCircKind::Full,
737 rAct.GetRect());
738 SetAttributes(pCirc);
739 InsertObj(pCirc);
742 void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction const & rAct)
744 Point aCenter(rAct.GetRect().Center());
745 tools::Long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
746 tools::Long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
747 SdrCircObj* pCirc = new SdrCircObj(
748 *mpModel,
749 SdrCircKind::Arc,
750 rAct.GetRect(),nStart,nEnd);
751 SetAttributes(pCirc);
752 InsertObj(pCirc);
755 void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction const & rAct)
757 Point aCenter(rAct.GetRect().Center());
758 tools::Long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
759 tools::Long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
760 SdrCircObj* pCirc = new SdrCircObj(
761 *mpModel,
762 SdrCircKind::Section,
763 rAct.GetRect(),
764 nStart,
765 nEnd);
766 SetAttributes(pCirc);
767 InsertObj(pCirc);
770 void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction const & rAct)
772 Point aCenter(rAct.GetRect().Center());
773 tools::Long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
774 tools::Long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
775 SdrCircObj* pCirc = new SdrCircObj(
776 *mpModel,
777 SdrCircKind::Cut,
778 rAct.GetRect(),
779 nStart,
780 nEnd);
781 SetAttributes(pCirc);
782 InsertObj(pCirc);
785 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
787 // #i102706# Do not merge closed polygons
788 if(rSrcPoly.isClosed())
790 return false;
793 // #i73407# reformulation to use new B2DPolygon classes
794 if(mbLastObjWasLine && (maOldLineColor == mpVD->GetLineColor()) && rSrcPoly.count())
796 SdrObject* pTmpObj = !maTmpList.empty() ? maTmpList[maTmpList.size() - 1] : nullptr;
797 SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
799 if(pLastPoly)
801 if(1 == pLastPoly->GetPathPoly().count())
803 bool bOk(false);
804 basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0));
806 // #i102706# Do not merge closed polygons
807 if(aDstPoly.isClosed())
809 return false;
812 if(aDstPoly.count())
814 const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1);
815 const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1);
817 if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0))
819 aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
820 bOk = true;
822 else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
824 basegfx::B2DPolygon aNew(rSrcPoly);
825 aNew.append(aDstPoly, 1, aDstPoly.count() - 1);
826 aDstPoly = aNew;
827 bOk = true;
829 else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(0))
831 aDstPoly.flip();
832 aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
833 bOk = true;
835 else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
837 basegfx::B2DPolygon aNew(rSrcPoly);
838 aNew.flip();
839 aDstPoly.append(aNew, 1, aNew.count() - 1);
840 bOk = true;
844 if(bOk)
846 pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
849 return bOk;
854 return false;
857 bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
859 // #i73407# reformulation to use new B2DPolygon classes
860 if(mbLastObjWasPolyWithoutLine)
862 SdrObject* pTmpObj = !maTmpList.empty() ? maTmpList[maTmpList.size() - 1] : nullptr;
863 SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
865 if(pLastPoly)
867 if(pLastPoly->GetPathPoly() == rPolyPolygon)
869 SetAttributes(nullptr);
871 if(!mbNoLine && mbNoFill)
873 pLastPoly->SetMergedItemSet(*mpLineAttr);
875 return true;
881 return false;
884 void ImpSdrGDIMetaFileImport::checkClip()
886 if(!mpVD->IsClipRegion())
887 return;
889 maClip = mpVD->GetClipRegion().GetAsB2DPolyPolygon();
891 if(isClip())
893 const basegfx::B2DHomMatrix aTransform(
894 basegfx::utils::createScaleTranslateB2DHomMatrix(
895 mfScaleX,
896 mfScaleY,
897 maOfs.X(),
898 maOfs.Y()));
900 maClip.transform(aTransform);
904 bool ImpSdrGDIMetaFileImport::isClip() const
906 return !maClip.getB2DRange().isEmpty();
909 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction const & rAct )
911 // #i73407# reformulation to use new B2DPolygon classes
912 basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
914 if(aSource.count())
916 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
917 aSource.transform(aTransform);
920 const LineInfo& rLineInfo = rAct.GetLineInfo();
921 const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
922 bool bCreateLineObject(true);
924 if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aSource))
926 bCreateLineObject = false;
928 else if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
930 bCreateLineObject = false;
933 if(!bCreateLineObject)
934 return;
936 SdrPathObj* pPath = new SdrPathObj(
937 *mpModel,
938 aSource.isClosed() ? OBJ_POLY : OBJ_PLIN,
939 basegfx::B2DPolyPolygon(aSource));
940 mnLineWidth = nNewLineWidth;
941 maLineJoin = rLineInfo.GetLineJoin();
942 maLineCap = rLineInfo.GetLineCap();
943 maDash = XDash(css::drawing::DashStyle_RECT,
944 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
945 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
946 rLineInfo.GetDistance());
947 SetAttributes(pPath);
948 mnLineWidth = 0;
949 maLineJoin = basegfx::B2DLineJoin::NONE;
950 maDash = XDash();
951 InsertObj(pPath, false);
954 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction const & rAct )
956 // #i73407# reformulation to use new B2DPolygon classes
957 basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
959 if(!aSource.count())
960 return;
962 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
963 aSource.transform(aTransform);
965 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
967 // #i73407# make sure polygon is closed, it's a filled primitive
968 aSource.setClosed(true);
969 SdrPathObj* pPath = new SdrPathObj(
970 *mpModel,
971 OBJ_POLY,
972 basegfx::B2DPolyPolygon(aSource));
973 SetAttributes(pPath);
974 InsertObj(pPath, false);
978 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction const & rAct)
980 // #i73407# reformulation to use new B2DPolygon classes
981 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
983 if(!aSource.count())
984 return;
986 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
987 aSource.transform(aTransform);
989 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
991 // #i73407# make sure polygon is closed, it's a filled primitive
992 aSource.setClosed(true);
993 SdrPathObj* pPath = new SdrPathObj(
994 *mpModel,
995 OBJ_POLY,
996 aSource);
997 SetAttributes(pPath);
998 InsertObj(pPath, false);
1002 void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const OUString& rStr, const MetaAction& rAct )
1004 // calc text box size, add 5% to make it fit safely
1006 FontMetric aFontMetric( mpVD->GetFontMetric() );
1007 vcl::Font aFnt( mpVD->GetFont() );
1008 FontAlign eAlg( aFnt.GetAlignment() );
1010 sal_Int32 nTextWidth = static_cast<sal_Int32>( mpVD->GetTextWidth( rStr ) * mfScaleX );
1011 sal_Int32 nTextHeight = static_cast<sal_Int32>( mpVD->GetTextHeight() * mfScaleY );
1013 Point aPos( FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()) );
1014 Size aSize( nTextWidth, nTextHeight );
1016 if ( eAlg == ALIGN_BASELINE )
1017 aPos.AdjustY( -(FRound(aFontMetric.GetAscent() * mfScaleY)) );
1018 else if ( eAlg == ALIGN_BOTTOM )
1019 aPos.AdjustY( -nTextHeight );
1021 tools::Rectangle aTextRect( aPos, aSize );
1022 SdrRectObj* pText = new SdrRectObj(
1023 *mpModel,
1024 OBJ_TEXT,
1025 aTextRect);
1027 pText->SetMergedItem ( makeSdrTextUpperDistItem (0));
1028 pText->SetMergedItem ( makeSdrTextLowerDistItem (0));
1029 pText->SetMergedItem ( makeSdrTextRightDistItem (0));
1030 pText->SetMergedItem ( makeSdrTextLeftDistItem (0));
1032 if ( aFnt.GetAverageFontWidth() || ( rAct.GetType() == MetaActionType::STRETCHTEXT ) )
1034 pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
1035 pText->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
1036 // don't let the margins eat the space needed for the text
1037 pText->SetMergedItem( SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_ALLLINES) );
1039 else
1041 pText->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
1044 pText->SetLayer(mnLayer);
1045 pText->NbcSetText( rStr );
1046 SetAttributes( pText, true );
1047 pText->SetSnapRect( aTextRect );
1049 if (!aFnt.IsTransparent())
1051 SfxItemSet aAttr(*mpFillAttr->GetPool(), svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{});
1052 aAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID));
1053 aAttr.Put(XFillColorItem(OUString(), aFnt.GetFillColor()));
1054 pText->SetMergedItemSet(aAttr);
1056 sal_Int32 nAngle = aFnt.GetOrientation().get();
1057 if ( nAngle )
1059 nAngle*=10;
1060 double a = nAngle * F_PI18000;
1061 double nSin=sin(a);
1062 double nCos=cos(a);
1063 pText->NbcRotate(aPos,nAngle,nSin,nCos);
1065 InsertObj( pText, false );
1068 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction const & rAct)
1070 OUString aStr(rAct.GetText());
1071 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1072 ImportText( rAct.GetPoint(), aStr, rAct );
1075 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction const & rAct)
1077 OUString aStr(rAct.GetText());
1078 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1079 ImportText( rAct.GetPoint(), aStr, rAct );
1082 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction const & rAct)
1084 OUString aStr(rAct.GetText());
1085 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1086 ImportText( rAct.GetPoint(), aStr, rAct );
1089 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction const & rAct)
1091 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
1092 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1093 SdrGrafObj* pGraf = new SdrGrafObj(
1094 *mpModel,
1095 Graphic(BitmapEx(rAct.GetBitmap())),
1096 aRect);
1098 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1099 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1100 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1101 InsertObj(pGraf);
1104 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction const & rAct)
1106 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1107 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1108 SdrGrafObj* pGraf = new SdrGrafObj(
1109 *mpModel,
1110 Graphic(BitmapEx(rAct.GetBitmap())),
1111 aRect);
1113 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1114 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1115 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1116 InsertObj(pGraf);
1119 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction const & rAct)
1121 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
1122 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1123 SdrGrafObj* pGraf = new SdrGrafObj(
1124 *mpModel,
1125 rAct.GetBitmapEx(),
1126 aRect);
1128 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1129 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1130 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1131 InsertObj(pGraf);
1134 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction const & rAct)
1136 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1137 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1138 SdrGrafObj* pGraf = new SdrGrafObj(
1139 *mpModel,
1140 rAct.GetBitmapEx(),
1141 aRect);
1143 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1144 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1145 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1146 InsertObj(pGraf);
1150 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction const & rAct )
1152 // #i73407# reformulation to use new B2DPolygon classes
1153 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1155 if(!aSource.count())
1156 return;
1158 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1159 aSource.transform(aTransform);
1161 if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(aSource))
1162 return;
1164 const Hatch& rHatch = rAct.GetHatch();
1165 SdrPathObj* pPath = new SdrPathObj(
1166 *mpModel,
1167 OBJ_POLY,
1168 aSource);
1169 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1170 SfxItemSet aHatchAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1171 css::drawing::HatchStyle eStyle;
1173 switch(rHatch.GetStyle())
1175 case HatchStyle::Triple :
1177 eStyle = css::drawing::HatchStyle_TRIPLE;
1178 break;
1181 case HatchStyle::Double :
1183 eStyle = css::drawing::HatchStyle_DOUBLE;
1184 break;
1187 default:
1189 eStyle = css::drawing::HatchStyle_SINGLE;
1190 break;
1194 SetAttributes(pPath);
1195 aHatchAttr.Put(XFillStyleItem(drawing::FillStyle_HATCH));
1196 aHatchAttr.Put(XFillHatchItem(XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
1197 pPath->SetMergedItemSet(aHatchAttr);
1199 InsertObj(pPath, false);
1203 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
1205 rAct.Execute(mpVD);
1208 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
1210 MapScaling();
1211 rAct.Execute(mpVD);
1212 mbLastObjWasPolyWithoutLine = false;
1213 mbLastObjWasLine = false;
1216 void ImpSdrGDIMetaFileImport::MapScaling()
1218 const size_t nCount(maTmpList.size());
1219 const MapMode& rMap = mpVD->GetMapMode();
1220 Point aMapOrg( rMap.GetOrigin() );
1221 bool bMov2(aMapOrg.X() != 0 || aMapOrg.Y() != 0);
1223 if(bMov2)
1225 for(size_t i = mnMapScalingOfs; i < nCount; i++)
1227 SdrObject* pObj = maTmpList[i];
1229 pObj->NbcMove(Size(aMapOrg.X(), aMapOrg.Y()));
1233 mnMapScalingOfs = nCount;
1237 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction const & rAct, GDIMetaFile const & rMtf, sal_uLong& a) // GDIMetaFile* pMtf )
1239 bool aSkipComment = false;
1241 if (a < rMtf.GetActionSize() && rAct.GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
1243 // #i125211# Check if next action is a MetaGradientExAction
1244 MetaGradientExAction* pAct = dynamic_cast< MetaGradientExAction* >(rMtf.GetAction(a + 1));
1246 if( pAct && pAct->GetType() == MetaActionType::GRADIENTEX )
1248 // #i73407# reformulation to use new B2DPolygon classes
1249 basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
1251 if(aSource.count())
1253 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1255 const Gradient& rGrad = pAct->GetGradient();
1256 SdrPathObj* pPath = new SdrPathObj(
1257 *mpModel,
1258 OBJ_POLY,
1259 aSource);
1260 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1261 SfxItemSet aGradAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1262 XGradient aXGradient;
1264 aXGradient.SetGradientStyle(static_cast<css::awt::GradientStyle>(rGrad.GetStyle()));
1265 aXGradient.SetStartColor(rGrad.GetStartColor());
1266 aXGradient.SetEndColor(rGrad.GetEndColor());
1267 aXGradient.SetAngle(rGrad.GetAngle());
1268 aXGradient.SetBorder(rGrad.GetBorder());
1269 aXGradient.SetXOffset(rGrad.GetOfsX());
1270 aXGradient.SetYOffset(rGrad.GetOfsY());
1271 aXGradient.SetStartIntens(rGrad.GetStartIntensity());
1272 aXGradient.SetEndIntens(rGrad.GetEndIntensity());
1273 aXGradient.SetSteps(rGrad.GetSteps());
1275 // no need to use SetAttributes(..) here since line and fill style
1276 // need to be set individually
1277 // SetAttributes(pPath);
1279 // switch line off; if there was one there will be a
1280 // MetaActionType::POLYLINE following creating another object
1281 aGradAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
1283 // add detected gradient fillstyle
1284 aGradAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT));
1285 aGradAttr.Put(XFillGradientItem(aXGradient));
1287 pPath->SetMergedItemSet(aGradAttr);
1289 InsertObj(pPath);
1293 aSkipComment = true;
1297 if(aSkipComment)
1299 // #i125211# forward until closing MetaCommentAction
1300 MetaAction* pSkipAct = rMtf.GetAction(++a);
1302 while( pSkipAct
1303 && ((pSkipAct->GetType() != MetaActionType::COMMENT )
1304 || !(static_cast<MetaCommentAction*>(pSkipAct)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END"))))
1306 pSkipAct = rMtf.GetAction(++a);
1311 void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction const & rAct)
1313 GDIMetaFile aTemp;
1315 mpVD->AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
1316 DoLoopActions(aTemp, nullptr, nullptr);
1319 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction const & rAct)
1321 tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1322 BitmapEx aBitmapEx(rAct.GetBitmap());
1324 aRect.AdjustRight( 1 );
1325 aRect.AdjustBottom( 1 );
1326 aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1327 SdrGrafObj* pGraf = new SdrGrafObj(
1328 *mpModel,
1329 aBitmapEx,
1330 aRect);
1332 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1333 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1334 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1335 InsertObj(pGraf);
1338 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction const & rAct)
1340 tools::Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
1341 BitmapEx aBitmapEx(rAct.GetBitmapEx());
1343 aRect.AdjustRight( 1 );
1344 aRect.AdjustBottom( 1 );
1345 aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1346 SdrGrafObj* pGraf = new SdrGrafObj(
1347 *mpModel,
1348 aBitmapEx,
1349 aRect);
1351 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1352 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1353 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1354 InsertObj(pGraf);
1357 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction const & rAct)
1359 tools::Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
1360 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1362 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1363 SdrGrafObj* pGraf = new SdrGrafObj(
1364 *mpModel,
1365 aBitmapEx,
1366 aRect);
1368 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1369 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1370 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1371 InsertObj(pGraf);
1374 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction const & rAct)
1376 tools::Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
1377 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1379 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1380 SdrGrafObj* pGraf = new SdrGrafObj(
1381 *mpModel,
1382 aBitmapEx,
1383 aRect);
1385 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1386 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1387 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1388 InsertObj(pGraf);
1391 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction const & rAct)
1393 tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1394 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1396 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1397 aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1398 SdrGrafObj* pGraf = new SdrGrafObj(
1399 *mpModel,
1400 aBitmapEx,
1401 aRect);
1403 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1404 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1405 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1406 InsertObj(pGraf);
1409 namespace
1411 css::awt::GradientStyle getXGradientStyleFromGradientStyle(const GradientStyle& rGradientStyle)
1413 css::awt::GradientStyle aXGradientStyle(css::awt::GradientStyle_LINEAR);
1415 switch(rGradientStyle)
1417 case GradientStyle::Linear: aXGradientStyle = css::awt::GradientStyle_LINEAR; break;
1418 case GradientStyle::Axial: aXGradientStyle = css::awt::GradientStyle_AXIAL; break;
1419 case GradientStyle::Radial: aXGradientStyle = css::awt::GradientStyle_RADIAL; break;
1420 case GradientStyle::Elliptical: aXGradientStyle = css::awt::GradientStyle_ELLIPTICAL; break;
1421 case GradientStyle::Square: aXGradientStyle = css::awt::GradientStyle_SQUARE; break;
1422 case GradientStyle::Rect: aXGradientStyle = css::awt::GradientStyle_RECT; break;
1424 // Needed due to GradientStyle::FORCE_EQUAL_SIZE; this again is needed
1425 // to force the enum defines in VCL to a defined size for the compilers,
1426 // so despite it is never used it cannot be removed (would break the
1427 // API implementation probably).
1428 case GradientStyle::FORCE_EQUAL_SIZE: break;
1429 default:
1430 break;
1433 return aXGradientStyle;
1437 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction const & rAct)
1439 basegfx::B2DRange aRange = vcl::unotools::b2DRectangleFromRectangle(rAct.GetRect());
1441 if(aRange.isEmpty())
1442 return;
1444 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1445 aRange.transform(aTransform);
1446 const Gradient& rGradient = rAct.GetGradient();
1447 SdrRectObj* pRect = new SdrRectObj(
1448 *mpModel,
1449 tools::Rectangle(
1450 floor(aRange.getMinX()),
1451 floor(aRange.getMinY()),
1452 ceil(aRange.getMaxX()),
1453 ceil(aRange.getMaxY())));
1454 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1455 SfxItemSet aGradientAttr(mpModel->GetItemPool(), pRect->GetMergedItemSet().GetRanges());
1456 const css::awt::GradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1457 const XFillGradientItem aXFillGradientItem(
1458 XGradient(
1459 rGradient.GetStartColor(),
1460 rGradient.GetEndColor(),
1461 aXGradientStyle,
1462 rGradient.GetAngle(),
1463 rGradient.GetOfsX(),
1464 rGradient.GetOfsY(),
1465 rGradient.GetBorder(),
1466 rGradient.GetStartIntensity(),
1467 rGradient.GetEndIntensity(),
1468 rGradient.GetSteps()));
1470 SetAttributes(pRect);
1471 aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1472 aGradientAttr.Put(aXFillGradientItem);
1473 pRect->SetMergedItemSet(aGradientAttr);
1475 InsertObj(pRect, false);
1478 void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction const & rAct)
1480 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1482 if(!aSource.count())
1483 return;
1485 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1486 aSource.transform(aTransform);
1487 aSource.setClosed(true);
1489 SdrPathObj* pPath = new SdrPathObj(
1490 *mpModel,
1491 OBJ_POLY,
1492 aSource);
1493 SetAttributes(pPath);
1494 pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
1495 InsertObj(pPath, false);
1498 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction const & rAct)
1500 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1502 if(!aSource.count())
1503 return;
1505 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1506 aSource.transform(aTransform);
1508 if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(aSource))
1509 return;
1511 const Gradient& rGradient = rAct.GetGradient();
1512 SdrPathObj* pPath = new SdrPathObj(
1513 *mpModel,
1514 OBJ_POLY,
1515 aSource);
1516 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1517 SfxItemSet aGradientAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1518 const css::awt::GradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1519 const XFillGradientItem aXFillGradientItem(
1520 XGradient(
1521 rGradient.GetStartColor(),
1522 rGradient.GetEndColor(),
1523 aXGradientStyle,
1524 rGradient.GetAngle(),
1525 rGradient.GetOfsX(),
1526 rGradient.GetOfsY(),
1527 rGradient.GetBorder(),
1528 rGradient.GetStartIntensity(),
1529 rGradient.GetEndIntensity(),
1530 rGradient.GetSteps()));
1532 SetAttributes(pPath);
1533 aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1534 aGradientAttr.Put(aXFillGradientItem);
1535 pPath->SetMergedItemSet(aGradientAttr);
1537 InsertObj(pPath, false);
1540 void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction const & rAct)
1542 const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
1544 if(!rMtf.GetActionSize())
1545 return;
1547 const tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1549 // convert metafile sub-content to BitmapEx
1550 BitmapEx aBitmapEx(
1551 convertMetafileToBitmapEx(
1552 rMtf,
1553 vcl::unotools::b2DRectangleFromRectangle(aRect),
1554 125000));
1556 // handle colors
1557 const Gradient& rGradient = rAct.GetGradient();
1558 basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
1559 basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
1561 if(100 != rGradient.GetStartIntensity())
1563 aStart *= static_cast<double>(rGradient.GetStartIntensity()) / 100.0;
1566 if(100 != rGradient.GetEndIntensity())
1568 aEnd *= static_cast<double>(rGradient.GetEndIntensity()) / 100.0;
1571 const bool bEqualColors(aStart == aEnd);
1572 const bool bNoSteps(1 == rGradient.GetSteps());
1573 bool bCreateObject(true);
1574 bool bHasNewMask(false);
1575 AlphaMask aNewMask;
1576 double fTransparence(0.0);
1577 bool bFixedTransparence(false);
1579 if(bEqualColors || bNoSteps)
1581 // single transparence
1582 const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
1583 fTransparence = aMedium.luminance();
1585 if(basegfx::fTools::lessOrEqual(fTransparence, 0.0))
1587 // no transparence needed, all done
1589 else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
1591 // all transparent, no object
1592 bCreateObject = false;
1594 else
1596 // 0.0 < transparence < 1.0, apply fixed transparence
1597 bFixedTransparence = true;
1600 else
1602 // gradient transparence
1603 ScopedVclPtrInstance< VirtualDevice > pVDev;
1605 pVDev->SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
1606 pVDev->DrawGradient(tools::Rectangle(Point(0, 0), pVDev->GetOutputSizePixel()), rGradient);
1608 aNewMask = AlphaMask(pVDev->GetBitmap(Point(0, 0), pVDev->GetOutputSizePixel()));
1609 bHasNewMask = true;
1612 if(!bCreateObject)
1613 return;
1615 if(bHasNewMask || bFixedTransparence)
1617 if(!aBitmapEx.IsAlpha() && !aBitmapEx.IsTransparent())
1619 // no transparence yet, apply new one
1620 if(bFixedTransparence)
1622 sal_uInt8 aAlpha(basegfx::fround(fTransparence * 255.0));
1624 aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), &aAlpha);
1627 aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
1629 else
1631 vcl::bitmap::DrawAlphaBitmapAndAlphaGradient(aBitmapEx, bFixedTransparence, fTransparence, aNewMask);
1635 // create and add object
1636 SdrGrafObj* pGraf = new SdrGrafObj(
1637 *mpModel,
1638 aBitmapEx,
1639 aRect);
1641 // for MetaFloatTransparentAction, do not use SetAttributes(...)
1642 // since these metafile content is not used to draw line/fill
1643 // dependent of these setting at the device content
1644 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1645 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1646 InsertObj(pGraf);
1649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */