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"
21 #include <editeng/editdata.hxx>
22 #include <o3tl/make_unique.hxx>
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(
80 const tools::Rectangle
& rRect
)
82 mpVD(VclPtr
<VirtualDevice
>::Create()),
92 maLineJoin(basegfx::B2DLineJoin::NONE
),
93 maLineCap(css::drawing::LineCap_BUTT
),
94 maDash(css::drawing::DashStyle_RECT
, 0, 0, 0, 0, 0),
103 mbLastObjWasPolyWithoutLine(false),
106 mbLastObjWasLine(false),
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
>{});
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
);
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
);
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;
196 if(pProgrInfo
&& pActionsToReport
)
198 (*pActionsToReport
)++;
200 if(*pActionsToReport
>= 16) // update all 16 actions
202 if(!pProgrInfo
->ReportActions(*pActionsToReport
))
205 *pActionsToReport
= 0;
211 size_t ImpSdrGDIMetaFileImport::DoImport(
212 const GDIMetaFile
& rMtf
,
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;
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());
248 if(aMtfSize
.Height() != (maScaleRect
.GetHeight() - 1))
250 maScaleY
= Fraction(maScaleRect
.GetHeight() - 1, aMtfSize
.Height());
256 pProgrInfo
->SetActionCount(rMtf
.GetActionSize());
259 sal_uInt32
nActionsToReport(0);
262 DoLoopActions(rMtf
, pProgrInfo
, &nActionsToReport
);
266 pProgrInfo
->ReportActions(nActionsToReport
);
267 nActionsToReport
= 0;
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
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
);
299 if(nActionsToReport
>= 32) // update all 32 actions
301 pProgrInfo
->ReportInserts(nActionsToReport
);
302 nActionsToReport
= 0;
307 // report all remaining inserts for the last time
310 pProgrInfo
->ReportInserts(nActionsToReport
);
313 return maTmpList
.size();
316 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject
* pObj
, bool bForceTextAttr
)
320 bool bLine(!bForceTextAttr
);
321 bool bFill(!pObj
|| (pObj
->IsClosedObj() && !bForceTextAttr
));
322 bool bText(bForceTextAttr
|| (pObj
&& pObj
->GetOutlinerParaObject()));
328 mpLineAttr
->Put(XLineWidthItem(mnLineWidth
));
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()));
344 mpLineAttr
->Put(XLineStyleItem(drawing::LineStyle_NONE
));
349 case basegfx::B2DLineJoin::NONE
:
350 mpLineAttr
->Put(XLineJointItem(css::drawing::LineJoint_NONE
));
352 case basegfx::B2DLineJoin::Bevel
:
353 mpLineAttr
->Put(XLineJointItem(css::drawing::LineJoint_BEVEL
));
355 case basegfx::B2DLineJoin::Miter
:
356 mpLineAttr
->Put(XLineJointItem(css::drawing::LineJoint_MITER
));
358 case basegfx::B2DLineJoin::Round
:
359 mpLineAttr
->Put(XLineJointItem(css::drawing::LineJoint_ROUND
));
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
));
372 mpLineAttr
->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT
)));
382 if(mpVD
->IsFillColor())
384 mpFillAttr
->Put(XFillStyleItem(drawing::FillStyle_SOLID
));
385 mpFillAttr
->Put(XFillColorItem(OUString(), mpVD
->GetFillColor()));
389 mpFillAttr
->Put(XFillStyleItem(drawing::FillStyle_NONE
));
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
428 pObj
->SetLayer(mnLayer
);
432 pObj
->SetMergedItemSet(*mpLineAttr
);
437 pObj
->SetMergedItemSet(*mpFillAttr
);
442 pObj
->SetMergedItemSet(*mpTextAttr
);
443 pObj
->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT
));
448 void ImpSdrGDIMetaFileImport::InsertObj(SdrObject
* pObj
, bool bScale
)
450 if(bScale
&& !maScaleRect
.IsEmpty())
454 pObj
->NbcResize(Point(), maScaleX
, maScaleY
);
459 pObj
->NbcMove(Size(maOfs
.X(), maOfs
.Y()));
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
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
);
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
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
);
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();
519 InsertObj(pNewClone
, false);
523 OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
527 // cleanup temporary conversion objects
528 SdrObject::Free(pConverted
);
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(
554 const basegfx::B2DRange
aNewRange(aNewPoly
.getB2DRange());
556 if(!aNewRange
.isEmpty())
558 pObj
= new SdrPathObj(
559 aNewPoly
.isClosed() ? OBJ_POLY
: OBJ_PLIN
,
562 pObj
->SetLayer(aOldLayer
);
563 pObj
->SetMergedItemSet(aOldItemSet
);
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(
589 pObj
->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP
));
590 pObj
->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap
)));
591 pObj
->SetMergedItem(XFillBmpTileItem(false));
592 pObj
->SetMergedItem(XFillBmpStretchItem(true));
601 // #i111954# check object for visibility
602 // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
603 bool bVisible(false);
605 if(pObj
->HasLineStyle())
610 if(!bVisible
&& pObj
->HasFillStyle())
617 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >(pObj
);
619 if(pTextObj
&& pTextObj
->HasText())
627 SdrGrafObj
* pGrafObj
= dynamic_cast< SdrGrafObj
* >(pObj
);
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
640 SdrObject::Free(pObj
);
644 maTmpList
.push_back(pObj
);
646 if(dynamic_cast< SdrPathObj
* >(pObj
))
648 const bool bClosed(pObj
->IsClosedObj());
650 mbLastObjWasPolyWithoutLine
= mbNoLine
&& bClosed
;
651 mbLastObjWasLine
= !bClosed
;
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
);
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
);
698 maLineJoin
= basegfx::B2DLineJoin::NONE
;
700 InsertObj(pPath
, false);
705 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction
const & rAct
)
707 SdrRectObj
* pRect
=new SdrRectObj(rAct
.GetRect());
708 SetAttributes(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;
718 SfxItemSet
aSet(*mpLineAttr
->GetPool(), svl::Items
<SDRATTR_ECKENRADIUS
, SDRATTR_ECKENRADIUS
>{});
719 aSet
.Put(SdrMetricItem(SDRATTR_ECKENRADIUS
, nRad
));
720 pRect
->SetMergedItemSet(aSet
);
725 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction
const & rAct
)
727 SdrCircObj
* pCirc
=new SdrCircObj(OBJ_CIRC
,rAct
.GetRect());
728 SetAttributes(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
);
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
);
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
);
762 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon
& rSrcPoly
)
764 // #i102706# Do not merge closed polygons
765 if(rSrcPoly
.isClosed())
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
);
778 if(1 == pLastPoly
->GetPathPoly().count())
781 basegfx::B2DPolygon
aDstPoly(pLastPoly
->GetPathPoly().getB2DPolygon(0));
783 // #i102706# Do not merge closed polygons
784 if(aDstPoly
.isClosed())
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);
799 else if(aDstPoly
.getB2DPoint(0) == rSrcPoly
.getB2DPoint(nMaxSrcPnt
))
801 basegfx::B2DPolygon
aNew(rSrcPoly
);
802 aNew
.append(aDstPoly
, 1, aDstPoly
.count() - 1);
806 else if(aDstPoly
.getB2DPoint(0) == rSrcPoly
.getB2DPoint(0))
809 aDstPoly
.append(rSrcPoly
, 1, rSrcPoly
.count() - 1);
812 else if(aDstPoly
.getB2DPoint(nMaxDstPnt
) == rSrcPoly
.getB2DPoint(nMaxSrcPnt
))
814 basegfx::B2DPolygon
aNew(rSrcPoly
);
816 aDstPoly
.append(aNew
, 1, aNew
.count() - 1);
823 pLastPoly
->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly
));
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
);
844 if(pLastPoly
->GetPathPoly() == rPolyPolygon
)
846 SetAttributes(nullptr);
848 if(!mbNoLine
&& mbNoFill
)
850 pLastPoly
->SetMergedItemSet(*mpLineAttr
);
861 void ImpSdrGDIMetaFileImport::checkClip()
863 if(mpVD
->IsClipRegion())
865 maClip
= mpVD
->GetClipRegion().GetAsB2DPolyPolygon();
869 const basegfx::B2DHomMatrix
aTransform(
870 basegfx::utils::createScaleTranslateB2DHomMatrix(
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());
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
);
924 maLineJoin
= basegfx::B2DLineJoin::NONE
;
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());
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());
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
) );
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();
1028 double a
=nAngle
*nPi180
;
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
));
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
));
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
));
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
));
1106 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction
const & rAct
)
1108 // #i73407# reformulation to use new B2DPolygon classes
1109 basegfx::B2DPolyPolygon
aSource(rAct
.GetPolyPolygon().getB2DPolyPolygon());
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
;
1132 case HatchStyle::Double
:
1134 eStyle
= css::drawing::HatchStyle_DOUBLE
;
1140 eStyle
= css::drawing::HatchStyle_SINGLE
;
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
)
1161 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction
& rAct
)
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);
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());
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
);
1243 aSkipComment
= true;
1249 // #i125211# forward until closing MetaCommentAction
1250 MetaAction
* pSkipAct
= rMtf
.GetAction(++a
);
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
)
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());
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
));
1285 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction
const & rAct
)
1287 tools::Rectangle
aRect(rAct
.GetDestPoint(),rAct
.GetDestSize());
1288 BitmapEx
aBitmapEx(rAct
.GetBitmapEx());
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
));
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
));
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
));
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
));
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;
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())
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(
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(
1393 rGradient
.GetStartColor(),
1394 rGradient
.GetEndColor(),
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());
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());
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(
1447 rGradient
.GetStartColor(),
1448 rGradient
.GetEndColor(),
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())
1475 const tools::Rectangle
aRect(rAct
.GetPoint(),rAct
.GetSize());
1477 // convert metafile sub-content to BitmapEx
1479 convertMetafileToBitmapEx(
1482 aRect
.Left(), aRect
.Top(),
1483 aRect
.Right(), aRect
.Bottom()),
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);
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;
1526 // 0.0 < transparence < 1.0, apply fixed transparence
1527 bFixedTransparence
= true;
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()));
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
);
1560 // mix existing and new alpha mask
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
);
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
));
1599 AlphaMask::ScopedReadAccess
pNew(aNewMask
);
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
));
1619 OSL_ENSURE(false, "Alpha masks have different sizes (!)");
1626 OSL_ENSURE(false, "Got no access to new alpha mask (!)");
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
));
1654 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */