1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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(
82 const tools::Rectangle
& rRect
)
83 : mpVD(VclPtr
<VirtualDevice
>::Create()),
89 maLineJoin(basegfx::B2DLineJoin::NONE
),
90 maLineCap(css::drawing::LineCap_BUTT
),
91 maDash(css::drawing::DashStyle_RECT
, 0, 0, 0, 0, 0),
100 mbLastObjWasPolyWithoutLine(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());
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
);
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
);
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;
192 if(pProgrInfo
&& pActionsToReport
)
194 (*pActionsToReport
)++;
196 if(*pActionsToReport
>= 16) // update all 16 actions
198 if(!pProgrInfo
->ReportActions(*pActionsToReport
))
201 *pActionsToReport
= 0;
207 size_t ImpSdrGDIMetaFileImport::DoImport(
208 const GDIMetaFile
& rMtf
,
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;
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());
244 if(aMtfSize
.Height() != (maScaleRect
.GetHeight() - 1))
246 maScaleY
= Fraction(maScaleRect
.GetHeight() - 1, aMtfSize
.Height());
252 pProgrInfo
->SetActionCount(rMtf
.GetActionSize());
255 sal_uInt32
nActionsToReport(0);
258 DoLoopActions(rMtf
, pProgrInfo
, &nActionsToReport
);
262 pProgrInfo
->ReportActions(nActionsToReport
);
263 nActionsToReport
= 0;
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
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
);
295 if(nActionsToReport
>= 32) // update all 32 actions
297 pProgrInfo
->ReportInserts(nActionsToReport
);
298 nActionsToReport
= 0;
303 // report all remaining inserts for the last time
306 pProgrInfo
->ReportInserts(nActionsToReport
);
309 return maTmpList
.size();
312 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject
* pObj
, bool bForceTextAttr
)
316 bool bLine(!bForceTextAttr
);
317 bool bFill(!pObj
|| (pObj
->IsClosedObj() && !bForceTextAttr
));
318 bool bText(bForceTextAttr
|| (pObj
&& pObj
->GetOutlinerParaObject()));
324 mpLineAttr
->Put(XLineWidthItem(mnLineWidth
));
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()));
340 mpLineAttr
->Put(XLineStyleItem(drawing::LineStyle_NONE
));
345 case basegfx::B2DLineJoin::NONE
:
346 mpLineAttr
->Put(XLineJointItem(css::drawing::LineJoint_NONE
));
348 case basegfx::B2DLineJoin::Bevel
:
349 mpLineAttr
->Put(XLineJointItem(css::drawing::LineJoint_BEVEL
));
351 case basegfx::B2DLineJoin::Miter
:
352 mpLineAttr
->Put(XLineJointItem(css::drawing::LineJoint_MITER
));
354 case basegfx::B2DLineJoin::Round
:
355 mpLineAttr
->Put(XLineJointItem(css::drawing::LineJoint_ROUND
));
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
));
368 mpLineAttr
->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT
)));
378 if(mpVD
->IsFillColor())
380 mpFillAttr
->Put(XFillStyleItem(drawing::FillStyle_SOLID
));
381 mpFillAttr
->Put(XFillColorItem(OUString(), mpVD
->GetFillColor()));
385 mpFillAttr
->Put(XFillStyleItem(drawing::FillStyle_NONE
));
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
425 pObj
->SetLayer(mnLayer
);
429 pObj
->SetMergedItemSet(*mpLineAttr
);
434 pObj
->SetMergedItemSet(*mpFillAttr
);
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())
451 pObj
->NbcResize(Point(), maScaleX
, maScaleY
);
456 pObj
->NbcMove(Size(maOfs
.X(), maOfs
.Y()));
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
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
))
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
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);
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()));
516 InsertObj(pNewClone
.get(), false);
520 OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
534 aBitmapEx
= pSdrGrafObj
->GetGraphic().GetBitmapEx();
539 if(!aOldRange
.isEmpty())
541 // clip against ClipRegion
542 const basegfx::B2DPolyPolygon
aNewPoly(
543 basegfx::utils::clipPolyPolygonOnPolyPolygon(
548 const basegfx::B2DRange
aNewRange(aNewPoly
.getB2DRange());
550 if(!aNewRange
.isEmpty())
552 pObj
= new SdrPathObj(
554 aNewPoly
.isClosed() ? SdrObjKind::Polygon
: SdrObjKind::PolyLine
,
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(
584 pObj
->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP
));
585 pObj
->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap
)));
586 pObj
->SetMergedItem(XFillBmpTileItem(false));
587 pObj
->SetMergedItem(XFillBmpStretchItem(true));
597 // #i111954# check object for visibility
598 // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
599 bool bVisible(false);
601 if(pObj
->HasLineStyle())
606 if(!bVisible
&& pObj
->HasFillStyle())
613 SdrTextObj
* pTextObj
= DynCastSdrTextObj(pObj
.get());
615 if(pTextObj
&& pTextObj
->HasText())
623 SdrGrafObj
* pGrafObj
= dynamic_cast< SdrGrafObj
* >(pObj
.get());
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
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
;
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
))
662 basegfx::B2DPolygon aLine
;
663 const basegfx::B2DHomMatrix
aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
665 aLine
.append(aStart
);
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
)
681 rtl::Reference
<SdrPathObj
> pPath
= new SdrPathObj(
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());
694 maLineJoin
= basegfx::B2DLineJoin::NONE
;
696 InsertObj(pPath
.get(), false);
699 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction
const & rAct
)
701 rtl::Reference
<SdrRectObj
> pRect
= new SdrRectObj(
704 SetAttributes(pRect
.get());
705 InsertObj(pRect
.get());
708 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction
const & rAct
)
710 rtl::Reference
<SdrRectObj
> pRect
= new SdrRectObj(
713 SetAttributes(pRect
.get());
714 tools::Long nRad
=(rAct
.GetHorzRound()+rAct
.GetVertRound())/2;
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(
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(
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(
753 SdrCircKind::Section
,
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(
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())
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
);
792 if(1 == pLastPoly
->GetPathPoly().count())
795 basegfx::B2DPolygon
aDstPoly(pLastPoly
->GetPathPoly().getB2DPolygon(0));
797 // #i102706# Do not merge closed polygons
798 if(aDstPoly
.isClosed())
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);
813 else if(aDstPoly
.getB2DPoint(0) == rSrcPoly
.getB2DPoint(nMaxSrcPnt
))
815 basegfx::B2DPolygon
aNew(rSrcPoly
);
816 aNew
.append(aDstPoly
, 1, aDstPoly
.count() - 1);
820 else if(aDstPoly
.getB2DPoint(0) == rSrcPoly
.getB2DPoint(0))
823 aDstPoly
.append(rSrcPoly
, 1, rSrcPoly
.count() - 1);
826 else if(aDstPoly
.getB2DPoint(nMaxDstPnt
) == rSrcPoly
.getB2DPoint(nMaxSrcPnt
))
828 basegfx::B2DPolygon
aNew(rSrcPoly
);
830 aDstPoly
.append(aNew
, 1, aNew
.count() - 1);
837 pLastPoly
->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly
));
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
);
858 if(pLastPoly
->GetPathPoly() == rPolyPolygon
)
860 SetAttributes(nullptr);
862 if(!mbNoLine
&& mbNoFill
)
864 pLastPoly
->SetMergedItemSet(*mpLineAttr
);
875 void ImpSdrGDIMetaFileImport::checkClip()
877 if(!mpVD
->IsClipRegion())
880 maClip
= mpVD
->GetClipRegion().GetAsB2DPolyPolygon();
884 const basegfx::B2DHomMatrix
aTransform(
885 basegfx::utils::createScaleTranslateB2DHomMatrix(
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());
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
)
927 rtl::Reference
<SdrPathObj
> pPath
= new SdrPathObj(
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());
940 maLineJoin
= basegfx::B2DLineJoin::NONE
;
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());
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(
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());
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(
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(
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
) );
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());
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(
1080 Graphic(BitmapEx(rAct
.GetBitmap())),
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(
1095 Graphic(BitmapEx(rAct
.GetBitmap())),
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(
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(
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())
1143 const basegfx::B2DHomMatrix
aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
1144 aSource
.transform(aTransform
);
1146 if(mbLastObjWasPolyWithoutLine
&& CheckLastPolyLineAndFillMerge(aSource
))
1149 const Hatch
& rHatch
= rAct
.GetHatch();
1150 rtl::Reference
<SdrPathObj
> pPath
= new SdrPathObj(
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
;
1166 case HatchStyle::Double
:
1168 eStyle
= css::drawing::HatchStyle_DOUBLE
;
1174 eStyle
= css::drawing::HatchStyle_SINGLE
;
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
)
1193 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction
& rAct
)
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);
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());
1238 if(!mbLastObjWasPolyWithoutLine
|| !CheckLastPolyLineAndFillMerge(aSource
))
1240 const Gradient
& rGrad
= pAct
->GetGradient();
1241 rtl::Reference
<SdrPathObj
> pPath
= new SdrPathObj(
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;
1285 // #i125211# forward until closing MetaCommentAction
1286 MetaAction
* pSkipAct
= rMtf
.GetAction(++a
);
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
)
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(
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(
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(
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(
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(
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())
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(
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(
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())
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(
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())
1463 const basegfx::B2DHomMatrix
aTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
1464 aSource
.transform(aTransform
);
1466 if(mbLastObjWasPolyWithoutLine
&& CheckLastPolyLineAndFillMerge(aSource
))
1469 const Gradient
& rGradient
= rAct
.GetGradient();
1470 rtl::Reference
<SdrPathObj
> pPath
= new SdrPathObj(
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(
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())
1505 const tools::Rectangle
aRect(rAct
.GetPoint(),rAct
.GetSize());
1507 // convert metafile sub-content to BitmapEx
1509 convertMetafileToBitmapEx(
1511 vcl::unotools::b2DRectangleFromRectangle(aRect
),
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);
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;
1554 // 0.0 < transparence < 1.0, apply fixed transparence
1555 bFixedTransparence
= true;
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()));
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
);
1589 vcl::bitmap::DrawAlphaBitmapAndAlphaGradient(aBitmapEx
, bFixedTransparence
, fTransparence
, aNewMask
);
1593 // create and add object
1594 rtl::Reference
<SdrGrafObj
> pGraf
= new SdrGrafObj(
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: */