Adjust includes
[LibreOffice.git] / svx / source / svdraw / svdfmtf.cxx
blob3e47750564142ce88cd2a67daacd16091a87dd28
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "svdfmtf.hxx"
21 #include <editeng/editdata.hxx>
22 #include <o3tl/make_unique.hxx>
23 #include <math.h>
24 #include <svx/xpoly.hxx>
25 #include <vcl/svapp.hxx>
26 #include <editeng/eeitem.hxx>
27 #include <editeng/fhgtitem.hxx>
28 #include <editeng/wghtitem.hxx>
29 #include <editeng/postitem.hxx>
30 #include <editeng/udlnitem.hxx>
31 #include <editeng/crossedoutitem.hxx>
32 #include <editeng/shdditem.hxx>
33 #include <svx/xlnclit.hxx>
34 #include <svx/xlncapit.hxx>
35 #include <svx/xlnwtit.hxx>
36 #include <svx/xflclit.hxx>
37 #include <svx/xgrad.hxx>
38 #include <svx/xflgrit.hxx>
39 #include <editeng/fontitem.hxx>
40 #include <editeng/autokernitem.hxx>
41 #include <editeng/wrlmitem.hxx>
42 #include <editeng/contouritem.hxx>
43 #include <editeng/colritem.hxx>
44 #include <vcl/metric.hxx>
45 #include <editeng/charscaleitem.hxx>
46 #include <svx/xflhtit.hxx>
47 #include <svx/svdattr.hxx>
48 #include <svx/svdmodel.hxx>
49 #include <svx/svdpage.hxx>
50 #include <svx/svdobj.hxx>
51 #include <svx/svdotext.hxx>
52 #include <svx/svdorect.hxx>
53 #include <svx/svdocirc.hxx>
54 #include <svx/svdograf.hxx>
55 #include <svx/svdopath.hxx>
56 #include <svx/svdetc.hxx>
57 #include <svl/itemset.hxx>
58 #include <basegfx/polygon/b2dpolygon.hxx>
59 #include <tools/helpers.hxx>
60 #include <basegfx/matrix/b2dhommatrix.hxx>
61 #include <basegfx/matrix/b2dhommatrixtools.hxx>
62 #include <svx/xlinjoit.hxx>
63 #include <svx/xlndsit.hxx>
64 #include <basegfx/polygon/b2dpolygonclipper.hxx>
65 #include <svx/xbtmpit.hxx>
66 #include <svx/xfltrit.hxx>
67 #include <vcl/bitmapaccess.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>
75 using namespace com::sun::star;
77 ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
78 SdrModel& rModel,
79 SdrLayerID nLay,
80 const tools::Rectangle& rRect)
81 : maTmpList(),
82 mpVD(VclPtr<VirtualDevice>::Create()),
83 maScaleRect(rRect),
84 mnMapScalingOfs(0),
85 mpLineAttr(nullptr),
86 mpFillAttr(nullptr),
87 mpTextAttr(nullptr),
88 mpModel(&rModel),
89 mnLayer(nLay),
90 maOldLineColor(),
91 mnLineWidth(0),
92 maLineJoin(basegfx::B2DLineJoin::NONE),
93 maLineCap(css::drawing::LineCap_BUTT),
94 maDash(css::drawing::DashStyle_RECT, 0, 0, 0, 0, 0),
95 mbMov(false),
96 mbSize(false),
97 maOfs(0, 0),
98 mfScaleX(1.0),
99 mfScaleY(1.0),
100 maScaleX(1.0),
101 maScaleY(1.0),
102 mbFntDirty(true),
103 mbLastObjWasPolyWithoutLine(false),
104 mbNoLine(false),
105 mbNoFill(false),
106 mbLastObjWasLine(false),
107 maClip()
109 mpVD->EnableOutput(false);
110 mpVD->SetLineColor();
111 mpVD->SetFillColor();
112 maOldLineColor.SetRed( mpVD->GetLineColor().GetRed() + 1 );
113 mpLineAttr = o3tl::make_unique<SfxItemSet>(rModel.GetItemPool(), svl::Items<XATTR_LINE_FIRST, XATTR_LINE_LAST>{});
114 mpFillAttr = o3tl::make_unique<SfxItemSet>(rModel.GetItemPool(), svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{});
115 mpTextAttr = o3tl::make_unique<SfxItemSet>(rModel.GetItemPool(), svl::Items<EE_ITEMS_START, EE_ITEMS_END>{});
116 checkClip();
119 void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile const & rMtf, SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
121 const sal_uLong nCount(rMtf.GetActionSize());
123 for(sal_uLong a(0); a < nCount; a++)
125 MetaAction* pAct = rMtf.GetAction(a);
127 if(!pAct)
129 OSL_ENSURE(false, "OOps, no action at valid position (!)");
130 pAct = rMtf.GetAction(0);
133 switch (pAct->GetType())
135 case MetaActionType::PIXEL : break;
136 case MetaActionType::POINT : break;
137 case MetaActionType::LINE : DoAction(static_cast<MetaLineAction &>(*pAct)); break;
138 case MetaActionType::RECT : DoAction(static_cast<MetaRectAction &>(*pAct)); break;
139 case MetaActionType::ROUNDRECT : DoAction(static_cast<MetaRoundRectAction &>(*pAct)); break;
140 case MetaActionType::ELLIPSE : DoAction(static_cast<MetaEllipseAction &>(*pAct)); break;
141 case MetaActionType::ARC : DoAction(static_cast<MetaArcAction &>(*pAct)); break;
142 case MetaActionType::PIE : DoAction(static_cast<MetaPieAction &>(*pAct)); break;
143 case MetaActionType::CHORD : DoAction(static_cast<MetaChordAction &>(*pAct)); break;
144 case MetaActionType::POLYLINE : DoAction(static_cast<MetaPolyLineAction &>(*pAct)); break;
145 case MetaActionType::POLYGON : DoAction(static_cast<MetaPolygonAction &>(*pAct)); break;
146 case MetaActionType::POLYPOLYGON : DoAction(static_cast<MetaPolyPolygonAction &>(*pAct)); break;
147 case MetaActionType::TEXT : DoAction(static_cast<MetaTextAction &>(*pAct)); break;
148 case MetaActionType::TEXTARRAY : DoAction(static_cast<MetaTextArrayAction &>(*pAct)); break;
149 case MetaActionType::STRETCHTEXT : DoAction(static_cast<MetaStretchTextAction &>(*pAct)); break;
150 case MetaActionType::BMP : DoAction(static_cast<MetaBmpAction &>(*pAct)); break;
151 case MetaActionType::BMPSCALE : DoAction(static_cast<MetaBmpScaleAction &>(*pAct)); break;
152 case MetaActionType::BMPEX : DoAction(static_cast<MetaBmpExAction &>(*pAct)); break;
153 case MetaActionType::BMPEXSCALE : DoAction(static_cast<MetaBmpExScaleAction &>(*pAct)); break;
154 case MetaActionType::LINECOLOR : DoAction(static_cast<MetaLineColorAction &>(*pAct)); break;
155 case MetaActionType::FILLCOLOR : DoAction(static_cast<MetaFillColorAction &>(*pAct)); break;
156 case MetaActionType::TEXTCOLOR : DoAction(static_cast<MetaTextColorAction &>(*pAct)); break;
157 case MetaActionType::TEXTFILLCOLOR : DoAction(static_cast<MetaTextFillColorAction &>(*pAct)); break;
158 case MetaActionType::FONT : DoAction(static_cast<MetaFontAction &>(*pAct)); break;
159 case MetaActionType::TEXTALIGN : DoAction(static_cast<MetaTextAlignAction &>(*pAct)); break;
160 case MetaActionType::MAPMODE : DoAction(static_cast<MetaMapModeAction &>(*pAct)); break;
161 case MetaActionType::CLIPREGION : DoAction(static_cast<MetaClipRegionAction &>(*pAct)); break;
162 case MetaActionType::MOVECLIPREGION : DoAction(static_cast<MetaMoveClipRegionAction &>(*pAct)); break;
163 case MetaActionType::ISECTRECTCLIPREGION: DoAction(static_cast<MetaISectRectClipRegionAction&>(*pAct)); break;
164 case MetaActionType::ISECTREGIONCLIPREGION: DoAction(static_cast<MetaISectRegionClipRegionAction&>(*pAct)); break;
165 case MetaActionType::RASTEROP : DoAction(static_cast<MetaRasterOpAction &>(*pAct)); break;
166 case MetaActionType::PUSH : DoAction(static_cast<MetaPushAction &>(*pAct)); break;
167 case MetaActionType::POP : DoAction(static_cast<MetaPopAction &>(*pAct)); break;
168 case MetaActionType::HATCH : DoAction(static_cast<MetaHatchAction &>(*pAct)); break;
170 // #i125211# MetaCommentAction may change index, thus hand it over
171 case MetaActionType::COMMENT : DoAction(static_cast<MetaCommentAction&>(*pAct), rMtf, a);
172 break;
174 // missing actions added
175 case MetaActionType::TEXTRECT : DoAction(static_cast<MetaTextRectAction&>(*pAct)); break;
176 case MetaActionType::BMPSCALEPART : DoAction(static_cast<MetaBmpScalePartAction&>(*pAct)); break;
177 case MetaActionType::BMPEXSCALEPART : DoAction(static_cast<MetaBmpExScalePartAction&>(*pAct)); break;
178 case MetaActionType::MASK : DoAction(static_cast<MetaMaskAction&>(*pAct)); break;
179 case MetaActionType::MASKSCALE : DoAction(static_cast<MetaMaskScaleAction&>(*pAct)); break;
180 case MetaActionType::MASKSCALEPART : DoAction(static_cast<MetaMaskScalePartAction&>(*pAct)); break;
181 case MetaActionType::GRADIENT : DoAction(static_cast<MetaGradientAction&>(*pAct)); break;
182 case MetaActionType::WALLPAPER : OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)"); break;
183 case MetaActionType::Transparent : DoAction(static_cast<MetaTransparentAction&>(*pAct)); break;
184 case MetaActionType::EPS : OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)"); break;
185 case MetaActionType::REFPOINT : DoAction(static_cast<MetaRefPointAction&>(*pAct)); break;
186 case MetaActionType::TEXTLINECOLOR : DoAction(static_cast<MetaTextLineColorAction&>(*pAct)); break;
187 case MetaActionType::TEXTLINE : OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)"); break;
188 case MetaActionType::FLOATTRANSPARENT : DoAction(static_cast<MetaFloatTransparentAction&>(*pAct)); break;
189 case MetaActionType::GRADIENTEX : DoAction(static_cast<MetaGradientExAction&>(*pAct)); break;
190 case MetaActionType::LAYOUTMODE : DoAction(static_cast<MetaLayoutModeAction&>(*pAct)); break;
191 case MetaActionType::TEXTLANGUAGE : DoAction(static_cast<MetaTextLanguageAction&>(*pAct)); break;
192 case MetaActionType::OVERLINECOLOR : DoAction(static_cast<MetaOverlineColorAction&>(*pAct)); break;
193 default: break;
196 if(pProgrInfo && pActionsToReport)
198 (*pActionsToReport)++;
200 if(*pActionsToReport >= 16) // update all 16 actions
202 if(!pProgrInfo->ReportActions(*pActionsToReport))
203 break;
205 *pActionsToReport = 0;
211 size_t ImpSdrGDIMetaFileImport::DoImport(
212 const GDIMetaFile& rMtf,
213 SdrObjList& rOL,
214 size_t nInsPos,
215 SvdProgressInfo* pProgrInfo)
217 // setup some global scale parameter
218 // mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
219 mfScaleX = mfScaleY = 1.0;
220 const Size aMtfSize(rMtf.GetPrefSize());
222 if(aMtfSize.Width() & aMtfSize.Height() && (!maScaleRect.IsEmpty()))
224 maOfs = maScaleRect.TopLeft();
226 if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
228 mfScaleX = (double)( maScaleRect.GetWidth() - 1 ) / (double)aMtfSize.Width();
231 if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
233 mfScaleY = (double)( maScaleRect.GetHeight() - 1 ) / (double)aMtfSize.Height();
237 mbMov = maOfs.X()!=0 || maOfs.Y()!=0;
238 mbSize = false;
239 maScaleX = Fraction( 1, 1 );
240 maScaleY = Fraction( 1, 1 );
242 if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
244 maScaleX = Fraction(maScaleRect.GetWidth() - 1, aMtfSize.Width());
245 mbSize = true;
248 if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
250 maScaleY = Fraction(maScaleRect.GetHeight() - 1, aMtfSize.Height());
251 mbSize = true;
254 if(pProgrInfo)
256 pProgrInfo->SetActionCount(rMtf.GetActionSize());
259 sal_uInt32 nActionsToReport(0);
261 // execute
262 DoLoopActions(rMtf, pProgrInfo, &nActionsToReport);
264 if(pProgrInfo)
266 pProgrInfo->ReportActions(nActionsToReport);
267 nActionsToReport = 0;
270 // MapMode scaling
271 MapScaling();
273 // To calculate the progress meter, we use GetActionSize()*3.
274 // However, maTmpList has a lower entry count limit than GetActionSize(),
275 // so the actions that were assumed were too much have to be re-added.
276 nActionsToReport = (rMtf.GetActionSize() - maTmpList.size()) * 2;
278 // announce all currently unannounced rescales
279 if(pProgrInfo)
281 pProgrInfo->ReportRescales(nActionsToReport);
282 pProgrInfo->SetInsertCount(maTmpList.size());
285 nActionsToReport = 0;
287 // insert all objects cached in aTmpList now into rOL from nInsPos
288 nInsPos = std::min(nInsPos, rOL.GetObjCount());
290 for(SdrObject* pObj : maTmpList)
292 rOL.NbcInsertObject(pObj, nInsPos);
293 nInsPos++;
295 if(pProgrInfo)
297 nActionsToReport++;
299 if(nActionsToReport >= 32) // update all 32 actions
301 pProgrInfo->ReportInserts(nActionsToReport);
302 nActionsToReport = 0;
307 // report all remaining inserts for the last time
308 if(pProgrInfo)
310 pProgrInfo->ReportInserts(nActionsToReport);
313 return maTmpList.size();
316 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr)
318 mbNoLine = false;
319 mbNoFill = false;
320 bool bLine(!bForceTextAttr);
321 bool bFill(!pObj || (pObj->IsClosedObj() && !bForceTextAttr));
322 bool bText(bForceTextAttr || (pObj && pObj->GetOutlinerParaObject()));
324 if(bLine)
326 if(mnLineWidth)
328 mpLineAttr->Put(XLineWidthItem(mnLineWidth));
330 else
332 mpLineAttr->Put(XLineWidthItem(0));
335 maOldLineColor = mpVD->GetLineColor();
337 if(mpVD->IsLineColor())
339 mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_SOLID));
340 mpLineAttr->Put(XLineColorItem(OUString(), mpVD->GetLineColor()));
342 else
344 mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_NONE));
347 switch(maLineJoin)
349 case basegfx::B2DLineJoin::NONE:
350 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_NONE));
351 break;
352 case basegfx::B2DLineJoin::Bevel:
353 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_BEVEL));
354 break;
355 case basegfx::B2DLineJoin::Miter:
356 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_MITER));
357 break;
358 case basegfx::B2DLineJoin::Round:
359 mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_ROUND));
360 break;
363 // Add LineCap support
364 mpLineAttr->Put(XLineCapItem(maLineCap));
366 if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance())
368 mpLineAttr->Put(XLineDashItem(OUString(), maDash));
370 else
372 mpLineAttr->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT)));
375 else
377 mbNoLine = true;
380 if(bFill)
382 if(mpVD->IsFillColor())
384 mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_SOLID));
385 mpFillAttr->Put(XFillColorItem(OUString(), mpVD->GetFillColor()));
387 else
389 mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_NONE));
392 else
394 mbNoFill = true;
397 if(bText && mbFntDirty)
399 vcl::Font aFnt(mpVD->GetFont());
400 const sal_uInt32 nHeight(FRound(aFnt.GetFontSize().Height() * mfScaleY));
402 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
403 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
404 mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) );
405 mpTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC));
406 mpTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT));
407 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
408 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
409 mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
410 mpTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
411 mpTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
412 mpTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
413 mpTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
414 mpTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
416 // #i118485# Setting this item leads to problems (written #i118498# for this)
417 // mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
419 mpTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
420 mpTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
421 mpTextAttr->Put(SvxColorItem(mpVD->GetTextColor(), EE_CHAR_COLOR));
422 //... svxfont textitem svditext
423 mbFntDirty = false;
426 if(pObj)
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));
448 void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj, bool bScale)
450 if(bScale && !maScaleRect.IsEmpty())
452 if(mbSize)
454 pObj->NbcResize(Point(), maScaleX, maScaleY);
457 if(mbMov)
459 pObj->NbcMove(Size(maOfs.X(), maOfs.Y()));
463 if(isClip())
465 const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
466 const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
467 const SdrLayerID aOldLayer(pObj->GetLayer());
468 const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
469 const SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
470 const SdrTextObj* pSdrTextObj = dynamic_cast< SdrTextObj* >(pObj);
472 if(pSdrTextObj && pSdrTextObj->HasText())
474 // all text objects are created from ImportText and have no line or fill attributes, so
475 // it is okay to concentrate on the text itself
476 while(true)
478 const basegfx::B2DPolyPolygon aTextContour(pSdrTextObj->TakeContour());
479 const basegfx::B2DRange aTextRange(aTextContour.getB2DRange());
480 const basegfx::B2DRange aClipRange(maClip.getB2DRange());
482 // no overlap -> completely outside
483 if(!aClipRange.overlaps(aTextRange))
485 SdrObject::Free(pObj);
486 break;
489 // when the clip is a rectangle fast check for inside is possible
490 if(basegfx::utils::isRectangle(maClip) && aClipRange.isInside(aTextRange))
492 // completely inside ClipRect
493 break;
496 // here text needs to be clipped; to do so, convert to SdrObjects with polygons
497 // and add these recursively. Delete original object, do not add in this run
498 SdrObject* pConverted = pSdrTextObj->ConvertToPolyObj(true, true);
499 SdrObject::Free(pObj);
501 if(pConverted)
503 // recursively add created conversion; per definition this shall not
504 // contain further SdrTextObjs. Visit only non-group objects
505 SdrObjListIter aIter(*pConverted, SdrIterMode::DeepNoGroups);
507 // work with clones; the created conversion may contain group objects
508 // and when working with the original objects the loop itself could
509 // break and the cleanup later would be pretty complicated (only delete group
510 // objects, are these empty, ...?)
511 while(aIter.IsMore())
513 SdrObject* pCandidate = aIter.Next();
514 OSL_ENSURE(pCandidate && dynamic_cast< SdrObjGroup* >(pCandidate) == nullptr, "SdrObjListIter with SdrIterMode::DeepNoGroups error (!)");
515 SdrObject* pNewClone = pCandidate->Clone();
517 if(pNewClone)
519 InsertObj(pNewClone, false);
521 else
523 OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
527 // cleanup temporary conversion objects
528 SdrObject::Free(pConverted);
531 break;
534 else
536 BitmapEx aBitmapEx;
538 if(pSdrGrafObj)
540 aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
543 SdrObject::Free(pObj);
545 if(!aOldRange.isEmpty())
547 // clip against ClipRegion
548 const basegfx::B2DPolyPolygon aNewPoly(
549 basegfx::utils::clipPolyPolygonOnPolyPolygon(
550 aPoly,
551 maClip,
552 true,
553 !aPoly.isClosed()));
554 const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
556 if(!aNewRange.isEmpty())
558 pObj = new SdrPathObj(
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((double)aOrigSizePixel.Width(), aPixel.getWidth()))),
583 basegfx::fround(ceil(std::min((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)
601 // #i111954# check object for visibility
602 // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
603 bool bVisible(false);
605 if(pObj->HasLineStyle())
607 bVisible = true;
610 if(!bVisible && pObj->HasFillStyle())
612 bVisible = true;
615 if(!bVisible)
617 SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >(pObj);
619 if(pTextObj && pTextObj->HasText())
621 bVisible = true;
625 if(!bVisible)
627 SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
629 if(pGrafObj)
631 // this may be refined to check if the graphic really is visible. It
632 // is here to ensure that graphic objects without fill, line and text
633 // get created
634 bVisible = true;
638 if(!bVisible)
640 SdrObject::Free(pObj);
642 else
644 maTmpList.push_back(pObj);
646 if(dynamic_cast< SdrPathObj* >(pObj))
648 const bool bClosed(pObj->IsClosedObj());
650 mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
651 mbLastObjWasLine = !bClosed;
653 else
655 mbLastObjWasPolyWithoutLine = false;
656 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))
670 basegfx::B2DPolygon aLine;
671 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
673 aLine.append(aStart);
674 aLine.append(aEnd);
675 aLine.transform(aTransform);
677 const LineInfo& rLineInfo = rAct.GetLineInfo();
678 const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
679 bool bCreateLineObject(true);
681 if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aLine))
683 bCreateLineObject = false;
686 if(bCreateLineObject)
688 SdrPathObj* pPath = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aLine));
689 mnLineWidth = nNewLineWidth;
690 maLineJoin = rLineInfo.GetLineJoin();
691 maLineCap = rLineInfo.GetLineCap();
692 maDash = XDash(css::drawing::DashStyle_RECT,
693 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
694 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
695 rLineInfo.GetDistance());
696 SetAttributes(pPath);
697 mnLineWidth = 0;
698 maLineJoin = basegfx::B2DLineJoin::NONE;
699 maDash = XDash();
700 InsertObj(pPath, false);
705 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction const & rAct)
707 SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
708 SetAttributes(pRect);
709 InsertObj(pRect);
712 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction const & rAct)
714 SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
715 SetAttributes(pRect);
716 long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
717 if (nRad!=0) {
718 SfxItemSet aSet(*mpLineAttr->GetPool(), svl::Items<SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS>{});
719 aSet.Put(SdrMetricItem(SDRATTR_ECKENRADIUS, nRad));
720 pRect->SetMergedItemSet(aSet);
722 InsertObj(pRect);
725 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction const & rAct)
727 SdrCircObj* pCirc=new SdrCircObj(OBJ_CIRC,rAct.GetRect());
728 SetAttributes(pCirc);
729 InsertObj(pCirc);
732 void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction const & rAct)
734 Point aCenter(rAct.GetRect().Center());
735 long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
736 long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
737 SdrCircObj* pCirc=new SdrCircObj(OBJ_CARC,rAct.GetRect(),nStart,nEnd);
738 SetAttributes(pCirc);
739 InsertObj(pCirc);
742 void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction const & rAct)
744 Point aCenter(rAct.GetRect().Center());
745 long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
746 long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
747 SdrCircObj* pCirc=new SdrCircObj(OBJ_SECT,rAct.GetRect(),nStart,nEnd);
748 SetAttributes(pCirc);
749 InsertObj(pCirc);
752 void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction const & rAct)
754 Point aCenter(rAct.GetRect().Center());
755 long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
756 long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
757 SdrCircObj* pCirc=new SdrCircObj(OBJ_CCUT,rAct.GetRect(),nStart,nEnd);
758 SetAttributes(pCirc);
759 InsertObj(pCirc);
762 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
764 // #i102706# Do not merge closed polygons
765 if(rSrcPoly.isClosed())
767 return false;
770 // #i73407# reformulation to use new B2DPolygon classes
771 if(mbLastObjWasLine && (maOldLineColor == mpVD->GetLineColor()) && rSrcPoly.count())
773 SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : nullptr;
774 SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
776 if(pLastPoly)
778 if(1 == pLastPoly->GetPathPoly().count())
780 bool bOk(false);
781 basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0));
783 // #i102706# Do not merge closed polygons
784 if(aDstPoly.isClosed())
786 return false;
789 if(aDstPoly.count())
791 const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1);
792 const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1);
794 if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0))
796 aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
797 bOk = true;
799 else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
801 basegfx::B2DPolygon aNew(rSrcPoly);
802 aNew.append(aDstPoly, 1, aDstPoly.count() - 1);
803 aDstPoly = aNew;
804 bOk = true;
806 else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(0))
808 aDstPoly.flip();
809 aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
810 bOk = true;
812 else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
814 basegfx::B2DPolygon aNew(rSrcPoly);
815 aNew.flip();
816 aDstPoly.append(aNew, 1, aNew.count() - 1);
817 bOk = true;
821 if(bOk)
823 pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
826 return bOk;
831 return false;
834 bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
836 // #i73407# reformulation to use new B2DPolygon classes
837 if(mbLastObjWasPolyWithoutLine)
839 SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : nullptr;
840 SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
842 if(pLastPoly)
844 if(pLastPoly->GetPathPoly() == rPolyPolygon)
846 SetAttributes(nullptr);
848 if(!mbNoLine && mbNoFill)
850 pLastPoly->SetMergedItemSet(*mpLineAttr);
852 return true;
858 return false;
861 void ImpSdrGDIMetaFileImport::checkClip()
863 if(mpVD->IsClipRegion())
865 maClip = mpVD->GetClipRegion().GetAsB2DPolyPolygon();
867 if(isClip())
869 const basegfx::B2DHomMatrix aTransform(
870 basegfx::utils::createScaleTranslateB2DHomMatrix(
871 mfScaleX,
872 mfScaleY,
873 maOfs.X(),
874 maOfs.Y()));
876 maClip.transform(aTransform);
881 bool ImpSdrGDIMetaFileImport::isClip() const
883 return !maClip.getB2DRange().isEmpty();
886 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction const & rAct )
888 // #i73407# reformulation to use new B2DPolygon classes
889 basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
891 if(aSource.count())
893 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
894 aSource.transform(aTransform);
897 const LineInfo& rLineInfo = rAct.GetLineInfo();
898 const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
899 bool bCreateLineObject(true);
901 if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aSource))
903 bCreateLineObject = false;
905 else if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
907 bCreateLineObject = false;
910 if(bCreateLineObject)
912 SdrPathObj* pPath = new SdrPathObj(
913 aSource.isClosed() ? OBJ_POLY : OBJ_PLIN,
914 basegfx::B2DPolyPolygon(aSource));
915 mnLineWidth = nNewLineWidth;
916 maLineJoin = rLineInfo.GetLineJoin();
917 maLineCap = rLineInfo.GetLineCap();
918 maDash = XDash(css::drawing::DashStyle_RECT,
919 rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
920 rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
921 rLineInfo.GetDistance());
922 SetAttributes(pPath);
923 mnLineWidth = 0;
924 maLineJoin = basegfx::B2DLineJoin::NONE;
925 maDash = XDash();
926 InsertObj(pPath, false);
930 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction const & rAct )
932 // #i73407# reformulation to use new B2DPolygon classes
933 basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
935 if(aSource.count())
937 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
938 aSource.transform(aTransform);
940 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
942 // #i73407# make sure polygon is closed, it's a filled primitive
943 aSource.setClosed(true);
944 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource));
945 SetAttributes(pPath);
946 InsertObj(pPath, false);
951 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction const & rAct)
953 // #i73407# reformulation to use new B2DPolygon classes
954 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
956 if(aSource.count())
958 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
959 aSource.transform(aTransform);
961 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
963 // #i73407# make sure polygon is closed, it's a filled primitive
964 aSource.setClosed(true);
965 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
966 SetAttributes(pPath);
967 InsertObj(pPath, false);
972 void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const OUString& rStr, const MetaAction& rAct )
974 // calc text box size, add 5% to make it fit safely
976 FontMetric aFontMetric( mpVD->GetFontMetric() );
977 vcl::Font aFnt( mpVD->GetFont() );
978 FontAlign eAlg( aFnt.GetAlignment() );
980 sal_Int32 nTextWidth = (sal_Int32)( mpVD->GetTextWidth( rStr ) * mfScaleX );
981 sal_Int32 nTextHeight = (sal_Int32)( mpVD->GetTextHeight() * mfScaleY );
983 Point aPos( FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()) );
984 Size aSize( nTextWidth, nTextHeight );
986 if ( eAlg == ALIGN_BASELINE )
987 aPos.Y() -= FRound(aFontMetric.GetAscent() * mfScaleY);
988 else if ( eAlg == ALIGN_BOTTOM )
989 aPos.Y() -= nTextHeight;
991 tools::Rectangle aTextRect( aPos, aSize );
992 SdrRectObj* pText =new SdrRectObj( OBJ_TEXT, aTextRect );
994 pText->SetMergedItem ( makeSdrTextUpperDistItem (0));
995 pText->SetMergedItem ( makeSdrTextLowerDistItem (0));
996 pText->SetMergedItem ( makeSdrTextRightDistItem (0));
997 pText->SetMergedItem ( makeSdrTextLeftDistItem (0));
999 if ( aFnt.GetAverageFontWidth() || ( rAct.GetType() == MetaActionType::STRETCHTEXT ) )
1001 pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
1002 pText->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
1003 // don't let the margins eat the space needed for the text
1004 pText->SetMergedItem( SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_ALLLINES) );
1006 else
1008 pText->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
1011 pText->SetModel(mpModel);
1012 pText->SetLayer(mnLayer);
1013 pText->NbcSetText( rStr );
1014 SetAttributes( pText, true );
1015 pText->SetSnapRect( aTextRect );
1017 if (!aFnt.IsTransparent())
1019 SfxItemSet aAttr(*mpFillAttr->GetPool(), svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{});
1020 aAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID));
1021 aAttr.Put(XFillColorItem(OUString(), aFnt.GetFillColor()));
1022 pText->SetMergedItemSet(aAttr);
1024 sal_uInt32 nAngle = aFnt.GetOrientation();
1025 if ( nAngle )
1027 nAngle*=10;
1028 double a=nAngle*nPi180;
1029 double nSin=sin(a);
1030 double nCos=cos(a);
1031 pText->NbcRotate(aPos,nAngle,nSin,nCos);
1033 InsertObj( pText, false );
1036 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction const & rAct)
1038 OUString aStr(rAct.GetText());
1039 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1040 ImportText( rAct.GetPoint(), aStr, rAct );
1043 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction const & rAct)
1045 OUString aStr(rAct.GetText());
1046 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1047 ImportText( rAct.GetPoint(), aStr, rAct );
1050 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction const & rAct)
1052 OUString aStr(rAct.GetText());
1053 aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1054 ImportText( rAct.GetPoint(), aStr, rAct );
1057 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction const & rAct)
1059 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
1060 aRect.Right()++; aRect.Bottom()++;
1061 SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
1063 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1064 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1065 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1066 InsertObj(pGraf);
1069 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction const & rAct)
1071 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1072 aRect.Right()++; aRect.Bottom()++;
1073 SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
1075 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1076 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1077 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1078 InsertObj(pGraf);
1081 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction const & rAct)
1083 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
1084 aRect.Right()++; aRect.Bottom()++;
1085 SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
1087 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1088 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1089 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1090 InsertObj(pGraf);
1093 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction const & rAct)
1095 tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1096 aRect.Right()++; aRect.Bottom()++;
1097 SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
1099 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1100 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1101 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1102 InsertObj(pGraf);
1106 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction const & rAct )
1108 // #i73407# reformulation to use new B2DPolygon classes
1109 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1111 if(aSource.count())
1113 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1114 aSource.transform(aTransform);
1116 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1118 const Hatch& rHatch = rAct.GetHatch();
1119 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1120 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1121 SfxItemSet aHatchAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1122 css::drawing::HatchStyle eStyle;
1124 switch(rHatch.GetStyle())
1126 case HatchStyle::Triple :
1128 eStyle = css::drawing::HatchStyle_TRIPLE;
1129 break;
1132 case HatchStyle::Double :
1134 eStyle = css::drawing::HatchStyle_DOUBLE;
1135 break;
1138 default:
1140 eStyle = css::drawing::HatchStyle_SINGLE;
1141 break;
1145 SetAttributes(pPath);
1146 aHatchAttr.Put(XFillStyleItem(drawing::FillStyle_HATCH));
1147 aHatchAttr.Put(XFillHatchItem(XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
1148 pPath->SetMergedItemSet(aHatchAttr);
1150 InsertObj(pPath, false);
1156 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
1158 rAct.Execute(mpVD);
1161 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
1163 MapScaling();
1164 rAct.Execute(mpVD);
1165 mbLastObjWasPolyWithoutLine = false;
1166 mbLastObjWasLine = false;
1169 void ImpSdrGDIMetaFileImport::MapScaling()
1171 const size_t nCount(maTmpList.size());
1172 const MapMode& rMap = mpVD->GetMapMode();
1173 Point aMapOrg( rMap.GetOrigin() );
1174 bool bMov2(aMapOrg.X() != 0 || aMapOrg.Y() != 0);
1176 if(bMov2)
1178 for(size_t i = mnMapScalingOfs; i < nCount; i++)
1180 SdrObject* pObj = maTmpList[i];
1182 pObj->NbcMove(Size(aMapOrg.X(), aMapOrg.Y()));
1186 mnMapScalingOfs = nCount;
1190 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction const & rAct, GDIMetaFile const & rMtf, sal_uLong& a) // GDIMetaFile* pMtf )
1192 bool aSkipComment = false;
1194 if (a < rMtf.GetActionSize() && rAct.GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
1196 // #i125211# Check if next action is a MetaGradientExAction
1197 MetaGradientExAction* pAct = dynamic_cast< MetaGradientExAction* >(rMtf.GetAction(a + 1));
1199 if( pAct && pAct->GetType() == MetaActionType::GRADIENTEX )
1201 // #i73407# reformulation to use new B2DPolygon classes
1202 basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
1204 if(aSource.count())
1206 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1208 const Gradient& rGrad = pAct->GetGradient();
1209 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1210 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1211 SfxItemSet aGradAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1212 XGradient aXGradient;
1214 aXGradient.SetGradientStyle((css::awt::GradientStyle)rGrad.GetStyle());
1215 aXGradient.SetStartColor(rGrad.GetStartColor());
1216 aXGradient.SetEndColor(rGrad.GetEndColor());
1217 aXGradient.SetAngle(rGrad.GetAngle());
1218 aXGradient.SetBorder(rGrad.GetBorder());
1219 aXGradient.SetXOffset(rGrad.GetOfsX());
1220 aXGradient.SetYOffset(rGrad.GetOfsY());
1221 aXGradient.SetStartIntens(rGrad.GetStartIntensity());
1222 aXGradient.SetEndIntens(rGrad.GetEndIntensity());
1223 aXGradient.SetSteps(rGrad.GetSteps());
1225 // no need to use SetAttributes(..) here since line and fill style
1226 // need to be set individually
1227 // SetAttributes(pPath);
1229 // switch line off; if there was one there will be a
1230 // MetaActionType::POLYLINE following creating another object
1231 aGradAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
1233 // add detected gradient fillstyle
1234 aGradAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT));
1235 aGradAttr.Put(XFillGradientItem(aXGradient));
1237 pPath->SetMergedItemSet(aGradAttr);
1239 InsertObj(pPath);
1243 aSkipComment = true;
1247 if(aSkipComment)
1249 // #i125211# forward until closing MetaCommentAction
1250 MetaAction* pSkipAct = rMtf.GetAction(++a);
1252 while( pSkipAct
1253 && ((pSkipAct->GetType() != MetaActionType::COMMENT )
1254 || !(static_cast<MetaCommentAction*>(pSkipAct)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END"))))
1256 pSkipAct = rMtf.GetAction(++a);
1261 void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction const & rAct)
1263 GDIMetaFile aTemp;
1265 mpVD->AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
1266 DoLoopActions(aTemp, nullptr, nullptr);
1269 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction const & rAct)
1271 tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1272 Bitmap aBitmap(rAct.GetBitmap());
1274 aRect.Right()++;
1275 aRect.Bottom()++;
1276 aBitmap.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1277 SdrGrafObj* pGraf = new SdrGrafObj(aBitmap, aRect);
1279 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1280 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1281 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1282 InsertObj(pGraf);
1285 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction const & rAct)
1287 tools::Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
1288 BitmapEx aBitmapEx(rAct.GetBitmapEx());
1290 aRect.Right()++;
1291 aRect.Bottom()++;
1292 aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1293 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1295 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1296 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1297 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1298 InsertObj(pGraf);
1301 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction const & rAct)
1303 tools::Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
1304 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1306 aRect.Right()++; aRect.Bottom()++;
1307 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1309 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1310 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1311 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1312 InsertObj(pGraf);
1315 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction const & rAct)
1317 tools::Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
1318 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1320 aRect.Right()++; aRect.Bottom()++;
1321 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1323 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1324 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1325 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1326 InsertObj(pGraf);
1329 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction const & rAct)
1331 tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1332 BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
1334 aRect.Right()++; aRect.Bottom()++;
1335 aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1336 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1338 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1339 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1340 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1341 InsertObj(pGraf);
1344 namespace
1346 css::awt::GradientStyle getXGradientStyleFromGradientStyle(const GradientStyle& rGradientStyle)
1348 css::awt::GradientStyle aXGradientStyle(css::awt::GradientStyle_LINEAR);
1350 switch(rGradientStyle)
1352 case GradientStyle::Linear: aXGradientStyle = css::awt::GradientStyle_LINEAR; break;
1353 case GradientStyle::Axial: aXGradientStyle = css::awt::GradientStyle_AXIAL; break;
1354 case GradientStyle::Radial: aXGradientStyle = css::awt::GradientStyle_RADIAL; break;
1355 case GradientStyle::Elliptical: aXGradientStyle = css::awt::GradientStyle_ELLIPTICAL; break;
1356 case GradientStyle::Square: aXGradientStyle = css::awt::GradientStyle_SQUARE; break;
1357 case GradientStyle::Rect: aXGradientStyle = css::awt::GradientStyle_RECT; break;
1359 // Needed due to GradientStyle::FORCE_EQUAL_SIZE; this again is needed
1360 // to force the enum defines in VCL to a defined size for the compilers,
1361 // so despite it is never used it cannot be removed (would break the
1362 // API implementation probably).
1363 case GradientStyle::FORCE_EQUAL_SIZE: break;
1364 default:
1365 break;
1368 return aXGradientStyle;
1372 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction const & rAct)
1374 basegfx::B2DRange aRange(rAct.GetRect().Left(), rAct.GetRect().Top(), rAct.GetRect().Right(), rAct.GetRect().Bottom());
1376 if(aRange.isEmpty())
1377 return;
1379 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1380 aRange.transform(aTransform);
1381 const Gradient& rGradient = rAct.GetGradient();
1382 SdrRectObj* pRect = new SdrRectObj(
1383 tools::Rectangle(
1384 floor(aRange.getMinX()),
1385 floor(aRange.getMinY()),
1386 ceil(aRange.getMaxX()),
1387 ceil(aRange.getMaxY())));
1388 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1389 SfxItemSet aGradientAttr(mpModel->GetItemPool(), pRect->GetMergedItemSet().GetRanges());
1390 const css::awt::GradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1391 const XFillGradientItem aXFillGradientItem(
1392 XGradient(
1393 rGradient.GetStartColor(),
1394 rGradient.GetEndColor(),
1395 aXGradientStyle,
1396 rGradient.GetAngle(),
1397 rGradient.GetOfsX(),
1398 rGradient.GetOfsY(),
1399 rGradient.GetBorder(),
1400 rGradient.GetStartIntensity(),
1401 rGradient.GetEndIntensity(),
1402 rGradient.GetSteps()));
1404 SetAttributes(pRect);
1405 aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1406 aGradientAttr.Put(aXFillGradientItem);
1407 pRect->SetMergedItemSet(aGradientAttr);
1409 InsertObj(pRect, false);
1412 void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction const & rAct)
1414 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1416 if(aSource.count())
1418 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1419 aSource.transform(aTransform);
1420 aSource.setClosed(true);
1422 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1423 SetAttributes(pPath);
1424 pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
1425 InsertObj(pPath, false);
1429 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction const & rAct)
1431 basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1433 if(aSource.count())
1435 const basegfx::B2DHomMatrix aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1436 aSource.transform(aTransform);
1438 if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1440 const Gradient& rGradient = rAct.GetGradient();
1441 SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
1442 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1443 SfxItemSet aGradientAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1444 const css::awt::GradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
1445 const XFillGradientItem aXFillGradientItem(
1446 XGradient(
1447 rGradient.GetStartColor(),
1448 rGradient.GetEndColor(),
1449 aXGradientStyle,
1450 rGradient.GetAngle(),
1451 rGradient.GetOfsX(),
1452 rGradient.GetOfsY(),
1453 rGradient.GetBorder(),
1454 rGradient.GetStartIntensity(),
1455 rGradient.GetEndIntensity(),
1456 rGradient.GetSteps()));
1458 SetAttributes(pPath);
1459 aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1460 aGradientAttr.Put(aXFillGradientItem);
1461 pPath->SetMergedItemSet(aGradientAttr);
1463 InsertObj(pPath, false);
1468 void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction const & rAct)
1470 const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
1472 if(!rMtf.GetActionSize())
1473 return;
1475 const tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1477 // convert metafile sub-content to BitmapEx
1478 BitmapEx aBitmapEx(
1479 convertMetafileToBitmapEx(
1480 rMtf,
1481 basegfx::B2DRange(
1482 aRect.Left(), aRect.Top(),
1483 aRect.Right(), aRect.Bottom()),
1484 125000));
1486 // handle colors
1487 const Gradient& rGradient = rAct.GetGradient();
1488 basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
1489 basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
1491 if(100 != rGradient.GetStartIntensity())
1493 aStart *= (double)rGradient.GetStartIntensity() / 100.0;
1496 if(100 != rGradient.GetEndIntensity())
1498 aEnd *= (double)rGradient.GetEndIntensity() / 100.0;
1501 const bool bEqualColors(aStart == aEnd);
1502 const bool bNoSteps(1 == rGradient.GetSteps());
1503 bool bCreateObject(true);
1504 bool bHasNewMask(false);
1505 AlphaMask aNewMask;
1506 double fTransparence(0.0);
1507 bool bFixedTransparence(false);
1509 if(bEqualColors || bNoSteps)
1511 // single transparence
1512 const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
1513 fTransparence = aMedium.luminance();
1515 if(basegfx::fTools::lessOrEqual(fTransparence, 0.0))
1517 // no transparence needed, all done
1519 else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
1521 // all transparent, no object
1522 bCreateObject = false;
1524 else
1526 // 0.0 < transparence < 1.0, apply fixed transparence
1527 bFixedTransparence = true;
1530 else
1532 // gradient transparence
1533 ScopedVclPtrInstance< VirtualDevice > pVDev;
1535 pVDev->SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
1536 pVDev->DrawGradient(tools::Rectangle(Point(0, 0), pVDev->GetOutputSizePixel()), rGradient);
1538 aNewMask = AlphaMask(pVDev->GetBitmap(Point(0, 0), pVDev->GetOutputSizePixel()));
1539 bHasNewMask = true;
1542 if(bCreateObject)
1544 if(bHasNewMask || bFixedTransparence)
1546 if(!aBitmapEx.IsAlpha() && !aBitmapEx.IsTransparent())
1548 // no transparence yet, apply new one
1549 if(bFixedTransparence)
1551 sal_uInt8 aAlpha(basegfx::fround(fTransparence * 255.0));
1553 aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), &aAlpha);
1556 aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
1558 else
1560 // mix existing and new alpha mask
1561 AlphaMask aOldMask;
1563 if(aBitmapEx.IsAlpha())
1565 aOldMask = aBitmapEx.GetAlpha();
1567 else if(TransparentType::Bitmap == aBitmapEx.GetTransparentType())
1569 aOldMask = aBitmapEx.GetMask();
1571 else if(TransparentType::Color == aBitmapEx.GetTransparentType())
1573 aOldMask = aBitmapEx.GetBitmap().CreateMask(aBitmapEx.GetTransparentColor());
1576 AlphaMask::ScopedWriteAccess pOld(aOldMask);
1578 if(pOld)
1580 const double fFactor(1.0 / 255.0);
1582 if(bFixedTransparence)
1584 const double fOpNew(1.0 - fTransparence);
1586 for(long y(0); y < pOld->Height(); y++)
1588 for(long x(0); x < pOld->Width(); x++)
1590 const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1591 const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1593 pOld->SetPixel(y, x, BitmapColor(aCol));
1597 else
1599 AlphaMask::ScopedReadAccess pNew(aNewMask);
1601 if(pNew)
1603 if(pOld->Width() == pNew->Width() && pOld->Height() == pNew->Height())
1605 for(long y(0); y < pOld->Height(); y++)
1607 for(long x(0); x < pOld->Width(); x++)
1609 const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
1610 const double fOpNew(1.0 - (pNew->GetPixel(y, x).GetIndex() * fFactor));
1611 const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
1613 pOld->SetPixel(y, x, BitmapColor(aCol));
1617 else
1619 OSL_ENSURE(false, "Alpha masks have different sizes (!)");
1622 pNew.reset();
1624 else
1626 OSL_ENSURE(false, "Got no access to new alpha mask (!)");
1630 pOld.reset();
1632 else
1634 OSL_ENSURE(false, "Got no access to old alpha mask (!)");
1637 // apply combined bitmap as mask
1638 aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aOldMask);
1642 // create and add object
1643 SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
1645 // for MetaFloatTransparentAction, do not use SetAttributes(...)
1646 // since these metafile content is not used to draw line/fill
1647 // dependent of these setting at the device content
1648 pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1649 pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1650 InsertObj(pGraf);
1654 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */