Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / svdraw / svdfmtf.cxx
blob839fff3bdb152f7b78b9360d5a65bbbacd019815
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/xflgrit.hxx>
36 #include <editeng/fontitem.hxx>
37 #include <editeng/wrlmitem.hxx>
38 #include <editeng/contouritem.hxx>
39 #include <editeng/colritem.hxx>
40 #include <vcl/canvastools.hxx>
41 #include <vcl/metric.hxx>
42 #include <editeng/charscaleitem.hxx>
43 #include <svx/xflhtit.hxx>
44 #include <svx/sdmetitm.hxx>
45 #include <svx/sdtagitm.hxx>
46 #include <svx/sdtaitm.hxx>
47 #include <svx/sdtditm.hxx>
48 #include <svx/sdtfsitm.hxx>
49 #include <svx/svdmodel.hxx>
50 #include <svx/svdpage.hxx>
51 #include <svx/svdobj.hxx>
52 #include <svx/svdotext.hxx>
53 #include <svx/svdorect.hxx>
54 #include <svx/svdocirc.hxx>
55 #include <svx/svdograf.hxx>
56 #include <svx/svdopath.hxx>
57 #include <svx/svdetc.hxx>
58 #include <svl/itemset.hxx>
59 #include <basegfx/polygon/b2dpolygon.hxx>
60 #include <tools/helpers.hxx>
61 #include <basegfx/matrix/b2dhommatrix.hxx>
62 #include <basegfx/matrix/b2dhommatrixtools.hxx>
63 #include <svx/xlinjoit.hxx>
64 #include <svx/xlndsit.hxx>
65 #include <basegfx/polygon/b2dpolygonclipper.hxx>
66 #include <svx/xbtmpit.hxx>
67 #include <svx/xfltrit.hxx>
68 #include <svx/xflbmtit.hxx>
69 #include <svx/xflbstit.hxx>
70 #include <svx/svdpntv.hxx>
71 #include <basegfx/polygon/b2dpolypolygontools.hxx>
72 #include <svx/svditer.hxx>
73 #include <svx/svdogrp.hxx>
74 #include <vcl/BitmapTools.hxx>
75 #include <osl/diagnose.h>
77 using namespace com::sun::star;
79 ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
80 SdrModel& rModel,
81 SdrLayerID nLay,
82 const tools::Rectangle& rRect)
83 : mpVD(VclPtr<VirtualDevice>::Create()),
84 maScaleRect(rRect),
85 mnMapScalingOfs(0),
86 mpModel(&rModel),
87 mnLayer(nLay),
88 mnLineWidth(0),
89 maLineJoin(basegfx::B2DLineJoin::NONE),
90 maLineCap(css::drawing::LineCap_BUTT),
91 maDash(css::drawing::DashStyle_RECT, 0, 0, 0, 0, 0),
92 mbMov(false),
93 mbSize(false),
94 maOfs(0, 0),
95 mfScaleX(1.0),
96 mfScaleY(1.0),
97 maScaleX(1.0),
98 maScaleY(1.0),
99 mbFntDirty(true),
100 mbLastObjWasPolyWithoutLine(false),
101 mbNoLine(false),
102 mbNoFill(false),
103 mbLastObjWasLine(false)
105 mpVD->EnableOutput(false);
106 mpVD->SetLineColor();
107 mpVD->SetFillColor();
108 maOldLineColor.SetRed( mpVD->GetLineColor().GetRed() + 1 );
109 mpLineAttr = std::make_unique<SfxItemSetFixed<XATTR_LINE_FIRST, XATTR_LINE_LAST>>(rModel.GetItemPool());
110 mpFillAttr = std::make_unique<SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST>>(rModel.GetItemPool());
111 mpTextAttr = std::make_unique<SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END>>(rModel.GetItemPool());
112 checkClip();
115 void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile const & rMtf, SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
117 const sal_uLong nCount(rMtf.GetActionSize());
119 for(sal_uLong a(0); a < nCount; a++)
121 MetaAction* pAct = rMtf.GetAction(a);
123 if(!pAct)
125 OSL_ENSURE(false, "OOps, no action at valid position (!)");
126 pAct = rMtf.GetAction(0);
129 switch (pAct->GetType())
131 case MetaActionType::PIXEL : break;
132 case MetaActionType::POINT : break;
133 case MetaActionType::LINE : DoAction(static_cast<MetaLineAction &>(*pAct)); break;
134 case MetaActionType::RECT : DoAction(static_cast<MetaRectAction &>(*pAct)); break;
135 case MetaActionType::ROUNDRECT : DoAction(static_cast<MetaRoundRectAction &>(*pAct)); break;
136 case MetaActionType::ELLIPSE : DoAction(static_cast<MetaEllipseAction &>(*pAct)); break;
137 case MetaActionType::ARC : DoAction(static_cast<MetaArcAction &>(*pAct)); break;
138 case MetaActionType::PIE : DoAction(static_cast<MetaPieAction &>(*pAct)); break;
139 case MetaActionType::CHORD : DoAction(static_cast<MetaChordAction &>(*pAct)); break;
140 case MetaActionType::POLYLINE : DoAction(static_cast<MetaPolyLineAction &>(*pAct)); break;
141 case MetaActionType::POLYGON : DoAction(static_cast<MetaPolygonAction &>(*pAct)); break;
142 case MetaActionType::POLYPOLYGON : DoAction(static_cast<MetaPolyPolygonAction &>(*pAct)); break;
143 case MetaActionType::TEXT : DoAction(static_cast<MetaTextAction &>(*pAct)); break;
144 case MetaActionType::TEXTARRAY : DoAction(static_cast<MetaTextArrayAction &>(*pAct)); break;
145 case MetaActionType::STRETCHTEXT : DoAction(static_cast<MetaStretchTextAction &>(*pAct)); break;
146 case MetaActionType::BMP : DoAction(static_cast<MetaBmpAction &>(*pAct)); break;
147 case MetaActionType::BMPSCALE : DoAction(static_cast<MetaBmpScaleAction &>(*pAct)); break;
148 case MetaActionType::BMPEX : DoAction(static_cast<MetaBmpExAction &>(*pAct)); break;
149 case MetaActionType::BMPEXSCALE : DoAction(static_cast<MetaBmpExScaleAction &>(*pAct)); break;
150 case MetaActionType::LINECOLOR : DoAction(static_cast<MetaLineColorAction &>(*pAct)); break;
151 case MetaActionType::FILLCOLOR : DoAction(static_cast<MetaFillColorAction &>(*pAct)); break;
152 case MetaActionType::TEXTCOLOR : DoAction(static_cast<MetaTextColorAction &>(*pAct)); break;
153 case MetaActionType::TEXTFILLCOLOR : DoAction(static_cast<MetaTextFillColorAction &>(*pAct)); break;
154 case MetaActionType::FONT : DoAction(static_cast<MetaFontAction &>(*pAct)); break;
155 case MetaActionType::TEXTALIGN : DoAction(static_cast<MetaTextAlignAction &>(*pAct)); break;
156 case MetaActionType::MAPMODE : DoAction(static_cast<MetaMapModeAction &>(*pAct)); break;
157 case MetaActionType::CLIPREGION : DoAction(static_cast<MetaClipRegionAction &>(*pAct)); break;
158 case MetaActionType::MOVECLIPREGION : DoAction(static_cast<MetaMoveClipRegionAction &>(*pAct)); break;
159 case MetaActionType::ISECTRECTCLIPREGION: DoAction(static_cast<MetaISectRectClipRegionAction&>(*pAct)); break;
160 case MetaActionType::ISECTREGIONCLIPREGION: DoAction(static_cast<MetaISectRegionClipRegionAction&>(*pAct)); break;
161 case MetaActionType::RASTEROP : DoAction(static_cast<MetaRasterOpAction &>(*pAct)); break;
162 case MetaActionType::PUSH : DoAction(static_cast<MetaPushAction &>(*pAct)); break;
163 case MetaActionType::POP : DoAction(static_cast<MetaPopAction &>(*pAct)); break;
164 case MetaActionType::HATCH : DoAction(static_cast<MetaHatchAction &>(*pAct)); break;
166 // #i125211# MetaCommentAction may change index, thus hand it over
167 case MetaActionType::COMMENT : DoAction(static_cast<MetaCommentAction&>(*pAct), rMtf, a);
168 break;
170 // missing actions added
171 case MetaActionType::TEXTRECT : DoAction(static_cast<MetaTextRectAction&>(*pAct)); break;
172 case MetaActionType::BMPSCALEPART : DoAction(static_cast<MetaBmpScalePartAction&>(*pAct)); break;
173 case MetaActionType::BMPEXSCALEPART : DoAction(static_cast<MetaBmpExScalePartAction&>(*pAct)); break;
174 case MetaActionType::MASK : DoAction(static_cast<MetaMaskAction&>(*pAct)); break;
175 case MetaActionType::MASKSCALE : DoAction(static_cast<MetaMaskScaleAction&>(*pAct)); break;
176 case MetaActionType::MASKSCALEPART : DoAction(static_cast<MetaMaskScalePartAction&>(*pAct)); break;
177 case MetaActionType::GRADIENT : DoAction(static_cast<MetaGradientAction&>(*pAct)); break;
178 case MetaActionType::WALLPAPER : OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)"); break;
179 case MetaActionType::Transparent : DoAction(static_cast<MetaTransparentAction&>(*pAct)); break;
180 case MetaActionType::EPS : OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)"); break;
181 case MetaActionType::REFPOINT : DoAction(static_cast<MetaRefPointAction&>(*pAct)); break;
182 case MetaActionType::TEXTLINECOLOR : DoAction(static_cast<MetaTextLineColorAction&>(*pAct)); break;
183 case MetaActionType::TEXTLINE : OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)"); break;
184 case MetaActionType::FLOATTRANSPARENT : DoAction(static_cast<MetaFloatTransparentAction&>(*pAct)); break;
185 case MetaActionType::GRADIENTEX : DoAction(static_cast<MetaGradientExAction&>(*pAct)); break;
186 case MetaActionType::LAYOUTMODE : DoAction(static_cast<MetaLayoutModeAction&>(*pAct)); break;
187 case MetaActionType::TEXTLANGUAGE : DoAction(static_cast<MetaTextLanguageAction&>(*pAct)); break;
188 case MetaActionType::OVERLINECOLOR : DoAction(static_cast<MetaOverlineColorAction&>(*pAct)); break;
189 default: break;
192 if(pProgrInfo && pActionsToReport)
194 (*pActionsToReport)++;
196 if(*pActionsToReport >= 16) // update all 16 actions
198 if(!pProgrInfo->ReportActions(*pActionsToReport))
199 break;
201 *pActionsToReport = 0;
207 size_t ImpSdrGDIMetaFileImport::DoImport(
208 const GDIMetaFile& rMtf,
209 SdrObjList& rOL,
210 size_t nInsPos,
211 SvdProgressInfo* pProgrInfo)
213 // setup some global scale parameter
214 // mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
215 mfScaleX = mfScaleY = 1.0;
216 const Size aMtfSize(rMtf.GetPrefSize());
218 if(aMtfSize.Width() & aMtfSize.Height() && (!maScaleRect.IsEmpty()))
220 maOfs = maScaleRect.TopLeft();
222 if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
224 mfScaleX = static_cast<double>( maScaleRect.GetWidth() - 1 ) / static_cast<double>(aMtfSize.Width());
227 if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
229 mfScaleY = static_cast<double>( maScaleRect.GetHeight() - 1 ) / static_cast<double>(aMtfSize.Height());
233 mbMov = maOfs.X()!=0 || maOfs.Y()!=0;
234 mbSize = false;
235 maScaleX = Fraction( 1, 1 );
236 maScaleY = Fraction( 1, 1 );
238 if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
240 maScaleX = Fraction(maScaleRect.GetWidth() - 1, aMtfSize.Width());
241 mbSize = true;
244 if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
246 maScaleY = Fraction(maScaleRect.GetHeight() - 1, aMtfSize.Height());
247 mbSize = true;
250 if(pProgrInfo)
252 pProgrInfo->SetActionCount(rMtf.GetActionSize());
255 sal_uInt32 nActionsToReport(0);
257 // execute
258 DoLoopActions(rMtf, pProgrInfo, &nActionsToReport);
260 if(pProgrInfo)
262 pProgrInfo->ReportActions(nActionsToReport);
263 nActionsToReport = 0;
266 // MapMode scaling
267 MapScaling();
269 // To calculate the progress meter, we use GetActionSize()*3.
270 // However, maTmpList has a lower entry count limit than GetActionSize(),
271 // so the actions that were assumed were too much have to be re-added.
272 nActionsToReport = (rMtf.GetActionSize() - maTmpList.size()) * 2;
274 // announce all currently unannounced rescales
275 if(pProgrInfo)
277 pProgrInfo->ReportRescales(nActionsToReport);
278 pProgrInfo->SetInsertCount(maTmpList.size());
281 nActionsToReport = 0;
283 // insert all objects cached in aTmpList now into rOL from nInsPos
284 nInsPos = std::min(nInsPos, rOL.GetObjCount());
286 for(rtl::Reference<SdrObject>& pObj : maTmpList)
288 rOL.NbcInsertObject(pObj.get(), nInsPos);
289 nInsPos++;
291 if(pProgrInfo)
293 nActionsToReport++;
295 if(nActionsToReport >= 32) // update all 32 actions
297 pProgrInfo->ReportInserts(nActionsToReport);
298 nActionsToReport = 0;
303 // report all remaining inserts for the last time
304 if(pProgrInfo)
306 pProgrInfo->ReportInserts(nActionsToReport);
309 return maTmpList.size();
312 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr)
314 mbNoLine = false;
315 mbNoFill = false;
316 bool bLine(!bForceTextAttr);
317 bool bFill(!pObj || (pObj->IsClosedObj() && !bForceTextAttr));
318 bool bText(bForceTextAttr || (pObj && pObj->GetOutlinerParaObject()));
320 if(bLine)
322 if(mnLineWidth)
324 mpLineAttr->Put(XLineWidthItem(mnLineWidth));
326 else
328 mpLineAttr->Put(XLineWidthItem(0));
331 maOldLineColor = mpVD->GetLineColor();
333 if(mpVD->IsLineColor())
335 mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_SOLID));
336 mpLineAttr->Put(XLineColorItem(OUString(), mpVD->GetLineColor()));
338 else
340 mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_NONE));
343 switch(maLineJoin)
345 case basegfx::B2DLineJoin::NONE:
346 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_NONE));
347 break;
348 case basegfx::B2DLineJoin::Bevel:
349 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_BEVEL));
350 break;
351 case basegfx::B2DLineJoin::Miter:
352 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_MITER));
353 break;
354 case basegfx::B2DLineJoin::Round:
355 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_ROUND));
356 break;
359 // Add LineCap support
360 mpLineAttr->Put(XLineCapItem(maLineCap));
362 if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance())
364 mpLineAttr->Put(XLineDashItem(OUString(), maDash));
366 else
368 mpLineAttr->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT)));
371 else
373 mbNoLine = true;
376 if(bFill)
378 if(mpVD->IsFillColor())
380 mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_SOLID));
381 mpFillAttr->Put(XFillColorItem(OUString(), mpVD->GetFillColor()));
383 else
385 mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_NONE));
388 else
390 mbNoFill = true;
393 if(bText && mbFntDirty)
395 vcl::Font aFnt(mpVD->GetFont());
396 const sal_uInt32 nHeight(FRound(aFnt.GetFontSize().Height() * mfScaleY));
398 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
399 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
400 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) );
401 mpTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC));
402 mpTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT));
403 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
404 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
405 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
406 mpTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
407 mpTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
408 mpTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
409 mpTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
410 mpTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
412 // #i118485# Setting this item leads to problems (written #i118498# for this)
413 // mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
415 mpTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
416 mpTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
417 mpTextAttr->Put(SvxColorItem(mpVD->GetTextColor(), EE_CHAR_COLOR));
418 //... svxfont textitem svditext
419 mbFntDirty = false;
422 if(!pObj)
423 return;
425 pObj->SetLayer(mnLayer);
427 if(bLine)
429 pObj->SetMergedItemSet(*mpLineAttr);
432 if(bFill)
434 pObj->SetMergedItemSet(*mpFillAttr);
437 if(bText)
439 pObj->SetMergedItemSet(*mpTextAttr);
440 pObj->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
444 void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj1, bool bScale)
446 rtl::Reference<SdrObject> pObj = pObj1;
447 if(bScale && !maScaleRect.IsEmpty())
449 if(mbSize)
451 pObj->NbcResize(Point(), maScaleX, maScaleY);
454 if(mbMov)
456 pObj->NbcMove(Size(maOfs.X(), maOfs.Y()));
460 if(isClip())
462 const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
463 const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
464 const SdrLayerID aOldLayer(pObj->GetLayer());
465 const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
466 const SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj.get());
467 const SdrTextObj* pSdrTextObj = DynCastSdrTextObj(pObj.get());
469 if(pSdrTextObj && pSdrTextObj->HasText())
471 // all text objects are created from ImportText and have no line or fill attributes, so
472 // it is okay to concentrate on the text itself
473 while(true)
475 const basegfx::B2DPolyPolygon aTextContour(pSdrTextObj->TakeContour());
476 const basegfx::B2DRange aTextRange(aTextContour.getB2DRange());
477 const basegfx::B2DRange aClipRange(maClip.getB2DRange());
479 // no overlap -> completely outside
480 if(!aClipRange.overlaps(aTextRange))
482 pObj.clear();
483 break;
486 // when the clip is a rectangle fast check for inside is possible
487 if(basegfx::utils::isRectangle(maClip) && aClipRange.isInside(aTextRange))
489 // completely inside ClipRect
490 break;
493 // here text needs to be clipped; to do so, convert to SdrObjects with polygons
494 // and add these recursively. Delete original object, do not add in this run
495 rtl::Reference<SdrObject> pConverted = pSdrTextObj->ConvertToPolyObj(true, true);
496 pObj.clear();
498 if(pConverted)
500 // recursively add created conversion; per definition this shall not
501 // contain further SdrTextObjs. Visit only non-group objects
502 SdrObjListIter aIter(*pConverted, SdrIterMode::DeepNoGroups);
504 // work with clones; the created conversion may contain group objects
505 // and when working with the original objects the loop itself could
506 // break and the cleanup later would be pretty complicated (only delete group
507 // objects, are these empty, ...?)
508 while(aIter.IsMore())
510 SdrObject* pCandidate = aIter.Next();
511 OSL_ENSURE(pCandidate && dynamic_cast< SdrObjGroup* >(pCandidate) == nullptr, "SdrObjListIter with SdrIterMode::DeepNoGroups error (!)");
512 rtl::Reference<SdrObject> pNewClone(pCandidate->CloneSdrObject(pCandidate->getSdrModelFromSdrObject()));
514 if(pNewClone)
516 InsertObj(pNewClone.get(), false);
518 else
520 OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
525 break;
528 else
530 BitmapEx aBitmapEx;
532 if(pSdrGrafObj)
534 aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
537 pObj.clear();
539 if(!aOldRange.isEmpty())
541 // clip against ClipRegion
542 const basegfx::B2DPolyPolygon aNewPoly(
543 basegfx::utils::clipPolyPolygonOnPolyPolygon(
544 aPoly,
545 maClip,
546 true,
547 !aPoly.isClosed()));
548 const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
550 if(!aNewRange.isEmpty())
552 pObj = new SdrPathObj(
553 *mpModel,
554 aNewPoly.isClosed() ? SdrObjKind::Polygon : SdrObjKind::PolyLine,
555 aNewPoly);
557 pObj->SetLayer(aOldLayer);
558 pObj->SetMergedItemSet(aOldItemSet);
560 if(!aBitmapEx.IsEmpty())
562 // aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
563 const double fScaleX(aBitmapEx.GetSizePixel().Width() / (aOldRange.getWidth() ? aOldRange.getWidth() : 1.0));
564 const double fScaleY(aBitmapEx.GetSizePixel().Height() / (aOldRange.getHeight() ? aOldRange.getHeight() : 1.0));
565 basegfx::B2DRange aPixel(aNewRange);
566 basegfx::B2DHomMatrix aTrans;
568 aTrans.translate(-aOldRange.getMinX(), -aOldRange.getMinY());
569 aTrans.scale(fScaleX, fScaleY);
570 aPixel.transform(aTrans);
572 const Size aOrigSizePixel(aBitmapEx.GetSizePixel());
573 const Point aClipTopLeft(
574 basegfx::fround(floor(std::max(0.0, aPixel.getMinX()))),
575 basegfx::fround(floor(std::max(0.0, aPixel.getMinY()))));
576 const Size aClipSize(
577 basegfx::fround(ceil(std::min(static_cast<double>(aOrigSizePixel.Width()), aPixel.getWidth()))),
578 basegfx::fround(ceil(std::min(static_cast<double>(aOrigSizePixel.Height()), aPixel.getHeight()))));
579 const BitmapEx aClippedBitmap(
580 aBitmapEx,
581 aClipTopLeft,
582 aClipSize);
584 pObj->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
585 pObj->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap)));
586 pObj->SetMergedItem(XFillBmpTileItem(false));
587 pObj->SetMergedItem(XFillBmpStretchItem(true));
594 if(!pObj)
595 return;
597 // #i111954# check object for visibility
598 // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
599 bool bVisible(false);
601 if(pObj->HasLineStyle())
603 bVisible = true;
606 if(!bVisible && pObj->HasFillStyle())
608 bVisible = true;
611 if(!bVisible)
613 SdrTextObj* pTextObj = DynCastSdrTextObj(pObj.get());
615 if(pTextObj && pTextObj->HasText())
617 bVisible = true;
621 if(!bVisible)
623 SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj.get());
625 if(pGrafObj)
627 // this may be refined to check if the graphic really is visible. It
628 // is here to ensure that graphic objects without fill, line and text
629 // get created
630 bVisible = true;
634 if(bVisible)
636 maTmpList.push_back(pObj);
638 if(dynamic_cast< SdrPathObj* >(pObj.get()))
640 const bool bClosed(pObj->IsClosedObj());
642 mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
643 mbLastObjWasLine = !bClosed;
645 else
647 mbLastObjWasPolyWithoutLine = false;
648 mbLastObjWasLine = false;
653 void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction const & rAct)
655 // #i73407# reformulation to use new B2DPolygon classes
656 const basegfx::B2DPoint aStart(rAct.GetStartPoint().X(), rAct.GetStartPoint().Y());
657 const basegfx::B2DPoint aEnd(rAct.GetEndPoint().X(), rAct.GetEndPoint().Y());
659 if(aStart.equal(aEnd))
660 return;
662 basegfx::B2DPolygon aLine;
663 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
665 aLine.append(aStart);
666 aLine.append(aEnd);
667 aLine.transform(aTransform);
669 const LineInfo& rLineInfo = rAct.GetLineInfo();
670 const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
671 bool bCreateLineObject(true);
673 if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aLine))
675 bCreateLineObject = false;
678 if(!bCreateLineObject)
679 return;
681 rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
682 *mpModel,
683 SdrObjKind::Line,
684 basegfx::B2DPolyPolygon(aLine));
685 mnLineWidth = nNewLineWidth;
686 maLineJoin = rLineInfo.GetLineJoin();
687 maLineCap = rLineInfo.GetLineCap();
688 maDash = XDash(css::drawing::DashStyle_RECT,
689 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
690 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
691 rLineInfo.GetDistance());
692 SetAttributes(pPath.get());
693 mnLineWidth = 0;
694 maLineJoin = basegfx::B2DLineJoin::NONE;
695 maDash = XDash();
696 InsertObj(pPath.get(), false);
699 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction const & rAct)
701 rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
702 *mpModel,
703 rAct.GetRect());
704 SetAttributes(pRect.get());
705 InsertObj(pRect.get());
708 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction const & rAct)
710 rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
711 *mpModel,
712 rAct.GetRect());
713 SetAttributes(pRect.get());
714 tools::Long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
715 if (nRad!=0) {
716 SfxItemSetFixed<SDRATTR_CORNER_RADIUS, SDRATTR_CORNER_RADIUS> aSet(*mpLineAttr->GetPool());
717 aSet.Put(SdrMetricItem(SDRATTR_CORNER_RADIUS, nRad));
718 pRect->SetMergedItemSet(aSet);
720 InsertObj(pRect.get());
723 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction const & rAct)
725 rtl::Reference<SdrCircObj> pCirc=new SdrCircObj(
726 *mpModel,
727 SdrCircKind::Full,
728 rAct.GetRect());
729 SetAttributes(pCirc.get());
730 InsertObj(pCirc.get());
733 void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction const & rAct)
735 Point aCenter(rAct.GetRect().Center());
736 Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
737 Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
738 rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
739 *mpModel,
740 SdrCircKind::Arc,
741 rAct.GetRect(),nStart,nEnd);
742 SetAttributes(pCirc.get());
743 InsertObj(pCirc.get());
746 void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction const & rAct)
748 Point aCenter(rAct.GetRect().Center());
749 Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
750 Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
751 rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
752 *mpModel,
753 SdrCircKind::Section,
754 rAct.GetRect(),
755 nStart,
756 nEnd);
757 SetAttributes(pCirc.get());
758 InsertObj(pCirc.get());
761 void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction const & rAct)
763 Point aCenter(rAct.GetRect().Center());
764 Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
765 Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
766 rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
767 *mpModel,
768 SdrCircKind::Cut,
769 rAct.GetRect(),
770 nStart,
771 nEnd);
772 SetAttributes(pCirc.get());
773 InsertObj(pCirc.get());
776 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
778 // #i102706# Do not merge closed polygons
779 if(rSrcPoly.isClosed())
781 return false;
784 // #i73407# reformulation to use new B2DPolygon classes
785 if(mbLastObjWasLine && (maOldLineColor == mpVD->GetLineColor()) && rSrcPoly.count())
787 SdrObject* pTmpObj = !maTmpList.empty() ? maTmpList[maTmpList.size() - 1].get() : nullptr;
788 SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
790 if(pLastPoly)
792 if(1 == pLastPoly->GetPathPoly().count())
794 bool bOk(false);
795 basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0));
797 // #i102706# Do not merge closed polygons
798 if(aDstPoly.isClosed())
800 return false;
803 if(aDstPoly.count())
805 const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1);
806 const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1);
808 if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0))
810 aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
811 bOk = true;
813 else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
815 basegfx::B2DPolygon aNew(rSrcPoly);
816 aNew.append(aDstPoly, 1, aDstPoly.count() - 1);
817 aDstPoly = aNew;
818 bOk = true;
820 else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(0))
822 aDstPoly.flip();
823 aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
824 bOk = true;
826 else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
828 basegfx::B2DPolygon aNew(rSrcPoly);
829 aNew.flip();
830 aDstPoly.append(aNew, 1, aNew.count() - 1);
831 bOk = true;
835 if(bOk)
837 pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
840 return bOk;
845 return false;
848 bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
850 // #i73407# reformulation to use new B2DPolygon classes
851 if(mbLastObjWasPolyWithoutLine)
853 SdrObject* pTmpObj = !maTmpList.empty() ? maTmpList[maTmpList.size() - 1].get() : nullptr;
854 SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
856 if(pLastPoly)
858 if(pLastPoly->GetPathPoly() == rPolyPolygon)
860 SetAttributes(nullptr);
862 if(!mbNoLine && mbNoFill)
864 pLastPoly->SetMergedItemSet(*mpLineAttr);
866 return true;
872 return false;
875 void ImpSdrGDIMetaFileImport::checkClip()
877 if(!mpVD->IsClipRegion())
878 return;
880 maClip = mpVD->GetClipRegion().GetAsB2DPolyPolygon();
882 if(isClip())
884 const basegfx::B2DHomMatrix aTransform(
885 basegfx::utils::createScaleTranslateB2DHomMatrix(
886 mfScaleX,
887 mfScaleY,
888 maOfs.X(),
889 maOfs.Y()));
891 maClip.transform(aTransform);
895 bool ImpSdrGDIMetaFileImport::isClip() const
897 return !maClip.getB2DRange().isEmpty();
900 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction const & rAct )
902 // #i73407# reformulation to use new B2DPolygon classes
903 basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
905 if(aSource.count())
907 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
908 aSource.transform(aTransform);
911 const LineInfo& rLineInfo = rAct.GetLineInfo();
912 const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
913 bool bCreateLineObject(true);
915 if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aSource))
917 bCreateLineObject = false;
919 else if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
921 bCreateLineObject = false;
924 if(!bCreateLineObject)
925 return;
927 rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
928 *mpModel,
929 aSource.isClosed() ? SdrObjKind::Polygon : SdrObjKind::PolyLine,
930 basegfx::B2DPolyPolygon(aSource));
931 mnLineWidth = nNewLineWidth;
932 maLineJoin = rLineInfo.GetLineJoin();
933 maLineCap = rLineInfo.GetLineCap();
934 maDash = XDash(css::drawing::DashStyle_RECT,
935 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
936 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
937 rLineInfo.GetDistance());
938 SetAttributes(pPath.get());
939 mnLineWidth = 0;
940 maLineJoin = basegfx::B2DLineJoin::NONE;
941 maDash = XDash();
942 InsertObj(pPath.get(), false);
945 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction const & rAct )
947 // #i73407# reformulation to use new B2DPolygon classes
948 basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
950 if(!aSource.count())
951 return;
953 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
954 aSource.transform(aTransform);
956 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
958 // #i73407# make sure polygon is closed, it's a filled primitive
959 aSource.setClosed(true);
960 rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
961 *mpModel,
962 SdrObjKind::Polygon,
963 basegfx::B2DPolyPolygon(aSource));
964 SetAttributes(pPath.get());
965 InsertObj(pPath.get(), false);
969 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction const & rAct)
971 // #i73407# reformulation to use new B2DPolygon classes
972 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
974 if(!aSource.count())
975 return;
977 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
978 aSource.transform(aTransform);
980 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
982 // #i73407# make sure polygon is closed, it's a filled primitive
983 aSource.setClosed(true);
984 rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
985 *mpModel,
986 SdrObjKind::Polygon,
987 std::move(aSource));
988 SetAttributes(pPath.get());
989 InsertObj(pPath.get(), false);
993 void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const OUString& rStr, const MetaAction& rAct )
995 // calc text box size, add 5% to make it fit safely
997 FontMetric aFontMetric( mpVD->GetFontMetric() );
998 vcl::Font aFnt( mpVD->GetFont() );
999 TextAlign eAlg( aFnt.GetAlignment() );
1001 sal_Int32 nTextWidth = static_cast<sal_Int32>( mpVD->GetTextWidth( rStr ) * mfScaleX );
1002 sal_Int32 nTextHeight = static_cast<sal_Int32>( mpVD->GetTextHeight() * mfScaleY );
1004 Point aPos( FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()) );
1005 Size aSize( nTextWidth, nTextHeight );
1007 if ( eAlg == ALIGN_BASELINE )
1008 aPos.AdjustY( -(FRound(aFontMetric.GetAscent() * mfScaleY)) );
1009 else if ( eAlg == ALIGN_BOTTOM )
1010 aPos.AdjustY( -nTextHeight );
1012 tools::Rectangle aTextRect( aPos, aSize );
1013 rtl::Reference<SdrRectObj> pText = new SdrRectObj(
1014 *mpModel,
1015 SdrObjKind::Text,
1016 aTextRect);
1018 pText->SetMergedItem ( makeSdrTextUpperDistItem (0));
1019 pText->SetMergedItem ( makeSdrTextLowerDistItem (0));
1020 pText->SetMergedItem ( makeSdrTextRightDistItem (0));
1021 pText->SetMergedItem ( makeSdrTextLeftDistItem (0));
1023 if ( aFnt.GetAverageFontWidth() || ( rAct.GetType() == MetaActionType::STRETCHTEXT ) )
1025 pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
1026 pText->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
1027 // don't let the margins eat the space needed for the text
1028 pText->SetMergedItem( SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_ALLLINES) );
1030 else
1032 pText->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
1035 pText->SetLayer(mnLayer);
1036 pText->NbcSetText( rStr );
1037 SetAttributes( pText.get(), true );
1038 pText->SetSnapRect( aTextRect );
1040 if (!aFnt.IsTransparent())
1042 SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aAttr(*mpFillAttr->GetPool());
1043 aAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID));
1044 aAttr.Put(XFillColorItem(OUString(), aFnt.GetFillColor()));
1045 pText->SetMergedItemSet(aAttr);
1047 Degree100 nAngle = to<Degree100>(aFnt.GetOrientation());
1048 if ( nAngle )
1049 pText->SdrAttrObj::NbcRotate(aPos,nAngle);
1050 InsertObj( pText.get(), false );
1053 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction const & rAct)
1055 OUString aStr(rAct.GetText());
1056 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1057 ImportText( rAct.GetPoint(), aStr, rAct );
1060 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction const & rAct)
1062 OUString aStr(rAct.GetText());
1063 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1064 ImportText( rAct.GetPoint(), aStr, rAct );
1067 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction const & rAct)
1069 OUString aStr(rAct.GetText());
1070 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1071 ImportText( rAct.GetPoint(), aStr, rAct );
1074 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction const & rAct)
1076 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
1077 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1078 rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1079 *mpModel,
1080 Graphic(BitmapEx(rAct.GetBitmap())),
1081 aRect);
1083 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1084 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1085 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1086 InsertObj(pGraf.get());
1089 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction const & rAct)
1091 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1092 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1093 rtl::Reference<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.get());
1104 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction const & rAct)
1106 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
1107 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1108 rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1109 *mpModel,
1110 rAct.GetBitmapEx(),
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.get());
1119 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction const & rAct)
1121 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1122 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1123 rtl::Reference<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.get());
1135 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction const & rAct )
1137 // #i73407# reformulation to use new B2DPolygon classes
1138 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1140 if(!aSource.count())
1141 return;
1143 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1144 aSource.transform(aTransform);
1146 if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(aSource))
1147 return;
1149 const Hatch& rHatch = rAct.GetHatch();
1150 rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
1151 *mpModel,
1152 SdrObjKind::Polygon,
1153 std::move(aSource));
1154 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1155 SfxItemSet aHatchAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1156 css::drawing::HatchStyle eStyle;
1158 switch(rHatch.GetStyle())
1160 case HatchStyle::Triple :
1162 eStyle = css::drawing::HatchStyle_TRIPLE;
1163 break;
1166 case HatchStyle::Double :
1168 eStyle = css::drawing::HatchStyle_DOUBLE;
1169 break;
1172 default:
1174 eStyle = css::drawing::HatchStyle_SINGLE;
1175 break;
1179 SetAttributes(pPath.get());
1180 aHatchAttr.Put(XFillStyleItem(drawing::FillStyle_HATCH));
1181 aHatchAttr.Put(XFillHatchItem(XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
1182 pPath->SetMergedItemSet(aHatchAttr);
1184 InsertObj(pPath.get(), false);
1188 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
1190 rAct.Execute(mpVD);
1193 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
1195 MapScaling();
1196 rAct.Execute(mpVD);
1197 mbLastObjWasPolyWithoutLine = false;
1198 mbLastObjWasLine = false;
1201 void ImpSdrGDIMetaFileImport::MapScaling()
1203 const size_t nCount(maTmpList.size());
1204 const MapMode& rMap = mpVD->GetMapMode();
1205 Point aMapOrg( rMap.GetOrigin() );
1206 bool bMov2(aMapOrg.X() != 0 || aMapOrg.Y() != 0);
1208 if(bMov2)
1210 for(size_t i = mnMapScalingOfs; i < nCount; i++)
1212 SdrObject* pObj = maTmpList[i].get();
1214 pObj->NbcMove(Size(aMapOrg.X(), aMapOrg.Y()));
1218 mnMapScalingOfs = nCount;
1222 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction const & rAct, GDIMetaFile const & rMtf, sal_uLong& a) // GDIMetaFile* pMtf )
1224 bool aSkipComment = false;
1226 if (a < rMtf.GetActionSize() && rAct.GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
1228 // #i125211# Check if next action is a MetaGradientExAction
1229 MetaGradientExAction* pAct = dynamic_cast< MetaGradientExAction* >(rMtf.GetAction(a + 1));
1231 if( pAct && pAct->GetType() == MetaActionType::GRADIENTEX )
1233 // #i73407# reformulation to use new B2DPolygon classes
1234 basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
1236 if(aSource.count())
1238 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1240 const Gradient& rGrad = pAct->GetGradient();
1241 rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
1242 *mpModel,
1243 SdrObjKind::Polygon,
1244 std::move(aSource));
1245 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1246 SfxItemSet aGradAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1247 basegfx::BGradient aBGradient(
1248 basegfx::BColorStops(
1249 rGrad.GetStartColor().getBColor(),
1250 rGrad.GetEndColor().getBColor()));
1252 aBGradient.SetGradientStyle(rGrad.GetStyle());
1253 aBGradient.SetAngle(rGrad.GetAngle());
1254 aBGradient.SetBorder(rGrad.GetBorder());
1255 aBGradient.SetXOffset(rGrad.GetOfsX());
1256 aBGradient.SetYOffset(rGrad.GetOfsY());
1257 aBGradient.SetStartIntens(rGrad.GetStartIntensity());
1258 aBGradient.SetEndIntens(rGrad.GetEndIntensity());
1259 aBGradient.SetSteps(rGrad.GetSteps());
1261 // no need to use SetAttributes(..) here since line and fill style
1262 // need to be set individually
1263 // SetAttributes(pPath);
1265 // switch line off; if there was one there will be a
1266 // MetaActionType::POLYLINE following creating another object
1267 aGradAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
1269 // add detected gradient fillstyle
1270 aGradAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT));
1271 aGradAttr.Put(XFillGradientItem(aBGradient));
1273 pPath->SetMergedItemSet(aGradAttr);
1275 InsertObj(pPath.get());
1279 aSkipComment = true;
1283 if(aSkipComment)
1285 // #i125211# forward until closing MetaCommentAction
1286 MetaAction* pSkipAct = rMtf.GetAction(++a);
1288 while( pSkipAct
1289 && ((pSkipAct->GetType() != MetaActionType::COMMENT )
1290 || !(static_cast<MetaCommentAction*>(pSkipAct)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END"))))
1292 pSkipAct = rMtf.GetAction(++a);
1297 void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction const & rAct)
1299 GDIMetaFile aTemp;
1301 mpVD->AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
1302 DoLoopActions(aTemp, nullptr, nullptr);
1305 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction const & rAct)
1307 tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1308 BitmapEx aBitmapEx(rAct.GetBitmap());
1310 aRect.AdjustRight( 1 );
1311 aRect.AdjustBottom( 1 );
1312 aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1313 rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1314 *mpModel,
1315 aBitmapEx,
1316 aRect);
1318 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1319 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1320 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1321 InsertObj(pGraf.get());
1324 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction const & rAct)
1326 tools::Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
1327 BitmapEx aBitmapEx(rAct.GetBitmapEx());
1329 aRect.AdjustRight( 1 );
1330 aRect.AdjustBottom( 1 );
1331 aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1332 rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1333 *mpModel,
1334 aBitmapEx,
1335 aRect);
1337 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1338 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1339 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1340 InsertObj(pGraf.get());
1343 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction const & rAct)
1345 tools::Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
1346 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1348 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1349 rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1350 *mpModel,
1351 aBitmapEx,
1352 aRect);
1354 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1355 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1356 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1357 InsertObj(pGraf.get());
1360 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction const & rAct)
1362 tools::Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
1363 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1365 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1366 rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1367 *mpModel,
1368 aBitmapEx,
1369 aRect);
1371 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1372 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1373 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1374 InsertObj(pGraf.get());
1377 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction const & rAct)
1379 tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1380 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1382 aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1383 aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1384 rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1385 *mpModel,
1386 aBitmapEx,
1387 aRect);
1389 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1390 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1391 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1392 InsertObj(pGraf.get());
1395 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction const & rAct)
1397 basegfx::B2DRange aRange = vcl::unotools::b2DRectangleFromRectangle(rAct.GetRect());
1399 if(aRange.isEmpty())
1400 return;
1402 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1403 aRange.transform(aTransform);
1404 const Gradient& rGradient = rAct.GetGradient();
1405 rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
1406 *mpModel,
1407 tools::Rectangle(
1408 floor(aRange.getMinX()),
1409 floor(aRange.getMinY()),
1410 ceil(aRange.getMaxX()),
1411 ceil(aRange.getMaxY())));
1412 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1413 SfxItemSet aGradientAttr(mpModel->GetItemPool(), pRect->GetMergedItemSet().GetRanges());
1414 const XFillGradientItem aXFillGradientItem(
1415 basegfx::BGradient(
1416 basegfx::BColorStops(
1417 rGradient.GetStartColor().getBColor(),
1418 rGradient.GetEndColor().getBColor()),
1419 rGradient.GetStyle(),
1420 rGradient.GetAngle(),
1421 rGradient.GetOfsX(),
1422 rGradient.GetOfsY(),
1423 rGradient.GetBorder(),
1424 rGradient.GetStartIntensity(),
1425 rGradient.GetEndIntensity(),
1426 rGradient.GetSteps()));
1428 SetAttributes(pRect.get());
1429 aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1430 aGradientAttr.Put(aXFillGradientItem);
1431 pRect->SetMergedItemSet(aGradientAttr);
1433 InsertObj(pRect.get(), false);
1436 void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction const & rAct)
1438 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1440 if(!aSource.count())
1441 return;
1443 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1444 aSource.transform(aTransform);
1445 aSource.setClosed(true);
1447 rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
1448 *mpModel,
1449 SdrObjKind::Polygon,
1450 std::move(aSource));
1451 SetAttributes(pPath.get());
1452 pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
1453 InsertObj(pPath.get(), false);
1456 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction const & rAct)
1458 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1460 if(!aSource.count())
1461 return;
1463 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1464 aSource.transform(aTransform);
1466 if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(aSource))
1467 return;
1469 const Gradient& rGradient = rAct.GetGradient();
1470 rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
1471 *mpModel,
1472 SdrObjKind::Polygon,
1473 std::move(aSource));
1474 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1475 SfxItemSet aGradientAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1476 const XFillGradientItem aXFillGradientItem(
1477 basegfx::BGradient(
1478 basegfx::BColorStops(
1479 rGradient.GetStartColor().getBColor(),
1480 rGradient.GetEndColor().getBColor()),
1481 rGradient.GetStyle(),
1482 rGradient.GetAngle(),
1483 rGradient.GetOfsX(),
1484 rGradient.GetOfsY(),
1485 rGradient.GetBorder(),
1486 rGradient.GetStartIntensity(),
1487 rGradient.GetEndIntensity(),
1488 rGradient.GetSteps()));
1490 SetAttributes(pPath.get());
1491 aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1492 aGradientAttr.Put(aXFillGradientItem);
1493 pPath->SetMergedItemSet(aGradientAttr);
1495 InsertObj(pPath.get(), false);
1498 void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction const & rAct)
1500 const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
1502 if(!rMtf.GetActionSize())
1503 return;
1505 const tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1507 // convert metafile sub-content to BitmapEx
1508 BitmapEx aBitmapEx(
1509 convertMetafileToBitmapEx(
1510 rMtf,
1511 vcl::unotools::b2DRectangleFromRectangle(aRect),
1512 125000));
1514 // handle colors
1515 const Gradient& rGradient = rAct.GetGradient();
1516 basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
1517 basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
1519 if(100 != rGradient.GetStartIntensity())
1521 aStart *= static_cast<double>(rGradient.GetStartIntensity()) / 100.0;
1524 if(100 != rGradient.GetEndIntensity())
1526 aEnd *= static_cast<double>(rGradient.GetEndIntensity()) / 100.0;
1529 const bool bEqualColors(aStart == aEnd);
1530 const bool bNoSteps(1 == rGradient.GetSteps());
1531 bool bCreateObject(true);
1532 bool bHasNewMask(false);
1533 AlphaMask aNewMask;
1534 double fTransparence(0.0);
1535 bool bFixedTransparence(false);
1537 if(bEqualColors || bNoSteps)
1539 // single transparence
1540 const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
1541 fTransparence = aMedium.luminance();
1543 if(basegfx::fTools::lessOrEqual(fTransparence, 0.0))
1545 // no transparence needed, all done
1547 else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
1549 // all transparent, no object
1550 bCreateObject = false;
1552 else
1554 // 0.0 < transparence < 1.0, apply fixed transparence
1555 bFixedTransparence = true;
1558 else
1560 // gradient transparence
1561 ScopedVclPtrInstance< VirtualDevice > pVDev;
1563 pVDev->SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
1564 pVDev->DrawGradient(tools::Rectangle(Point(0, 0), pVDev->GetOutputSizePixel()), rGradient);
1566 aNewMask = AlphaMask(pVDev->GetBitmap(Point(0, 0), pVDev->GetOutputSizePixel()));
1567 bHasNewMask = true;
1570 if(!bCreateObject)
1571 return;
1573 if(bHasNewMask || bFixedTransparence)
1575 if(!aBitmapEx.IsAlpha())
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 vcl::bitmap::DrawAlphaBitmapAndAlphaGradient(aBitmapEx, bFixedTransparence, fTransparence, aNewMask);
1593 // create and add object
1594 rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1595 *mpModel,
1596 aBitmapEx,
1597 aRect);
1599 // for MetaFloatTransparentAction, do not use SetAttributes(...)
1600 // since these metafile content is not used to draw line/fill
1601 // dependent of these setting at the device content
1602 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1603 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1604 InsertObj(pGraf.get());
1607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */