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>
23 #include <svx/xpoly.hxx>
24 #include <vcl/svapp.hxx>
25 #include <editeng/eeitem.hxx>
26 #include <editeng/fhgtitem.hxx>
27 #include <editeng/wghtitem.hxx>
28 #include <editeng/postitem.hxx>
29 #include <editeng/udlnitem.hxx>
30 #include <editeng/crossedoutitem.hxx>
31 #include <editeng/shdditem.hxx>
32 #include <svx/xlnclit.hxx>
33 #include <svx/xlncapit.hxx>
34 #include <svx/xlnwtit.hxx>
35 #include <svx/xflclit.hxx>
36 #include <svx/xgrad.hxx>
37 #include <svx/xflgrit.hxx>
38 #include <editeng/fontitem.hxx>
39 #include <editeng/autokernitem.hxx>
40 #include <editeng/wrlmitem.hxx>
41 #include <editeng/contouritem.hxx>
42 #include <editeng/colritem.hxx>
43 #include <vcl/metric.hxx>
44 #include <editeng/charscaleitem.hxx>
45 #include <svx/xflhtit.hxx>
46 #include <svx/svdattr.hxx>
47 #include <svx/svdmodel.hxx>
48 #include <svx/svdpage.hxx>
49 #include <svx/svdobj.hxx>
50 #include <svx/svdotext.hxx>
51 #include <svx/svdorect.hxx>
52 #include <svx/svdocirc.hxx>
53 #include <svx/svdograf.hxx>
54 #include <svx/svdopath.hxx>
55 #include <svx/svdetc.hxx>
56 #include <svl/itemset.hxx>
57 #include <basegfx/polygon/b2dpolygon.hxx>
58 #include <tools/helpers.hxx>
59 #include <basegfx/matrix/b2dhommatrix.hxx>
60 #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 #include <svx/xlinjoit.hxx>
62 #include <svx/xlndsit.hxx>
63 #include <basegfx/polygon/b2dpolygonclipper.hxx>
64 #include <svx/xbtmpit.hxx>
65 #include <svx/xfltrit.hxx>
66 #include <vcl/bmpacc.hxx>
67 #include <svx/xflbmtit.hxx>
68 #include <svx/xflbstit.hxx>
69 #include <svx/svdpntv.hxx>
70 #include <basegfx/polygon/b2dpolypolygontools.hxx>
71 #include <svx/svditer.hxx>
72 #include <svx/svdogrp.hxx>
74 using namespace com::sun::star
;
76 ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
79 const Rectangle
& rRect
)
81 mpVD(VclPtr
<VirtualDevice
>::Create()),
91 maLineJoin(basegfx::B2DLINEJOIN_NONE
),
92 maLineCap(com::sun::star::drawing::LineCap_BUTT
),
93 maDash(css::drawing::DashStyle_RECT
, 0, 0, 0, 0, 0),
102 mbLastObjWasPolyWithoutLine(false),
105 mbLastObjWasLine(false),
108 mpVD
->EnableOutput(false);
109 mpVD
->SetLineColor();
110 mpVD
->SetFillColor();
111 maOldLineColor
.SetRed( mpVD
->GetLineColor().GetRed() + 1 );
112 mpLineAttr
= new SfxItemSet(rModel
.GetItemPool(), XATTR_LINE_FIRST
, XATTR_LINE_LAST
, 0, 0);
113 mpFillAttr
= new SfxItemSet(rModel
.GetItemPool(), XATTR_FILL_FIRST
, XATTR_FILL_LAST
, 0, 0);
114 mpTextAttr
= new SfxItemSet(rModel
.GetItemPool(), EE_ITEMS_START
, EE_ITEMS_END
, 0, 0);
118 ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport()
125 void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile
& rMtf
, SvdProgressInfo
* pProgrInfo
, sal_uInt32
* pActionsToReport
)
127 const sal_uLong
nCount(rMtf
.GetActionSize());
129 for(sal_uLong
a(0); a
< nCount
; a
++)
131 MetaAction
* pAct
= rMtf
.GetAction(a
);
135 OSL_ENSURE(false, "OOps, no action at valid position (!)");
136 pAct
= rMtf
.GetAction(0);
139 switch (pAct
->GetType())
141 case MetaActionType::PIXEL
: break;
142 case MetaActionType::POINT
: break;
143 case MetaActionType::LINE
: DoAction(static_cast<MetaLineAction
&>(*pAct
)); break;
144 case MetaActionType::RECT
: DoAction(static_cast<MetaRectAction
&>(*pAct
)); break;
145 case MetaActionType::ROUNDRECT
: DoAction(static_cast<MetaRoundRectAction
&>(*pAct
)); break;
146 case MetaActionType::ELLIPSE
: DoAction(static_cast<MetaEllipseAction
&>(*pAct
)); break;
147 case MetaActionType::ARC
: DoAction(static_cast<MetaArcAction
&>(*pAct
)); break;
148 case MetaActionType::PIE
: DoAction(static_cast<MetaPieAction
&>(*pAct
)); break;
149 case MetaActionType::CHORD
: DoAction(static_cast<MetaChordAction
&>(*pAct
)); break;
150 case MetaActionType::POLYLINE
: DoAction(static_cast<MetaPolyLineAction
&>(*pAct
)); break;
151 case MetaActionType::POLYGON
: DoAction(static_cast<MetaPolygonAction
&>(*pAct
)); break;
152 case MetaActionType::POLYPOLYGON
: DoAction(static_cast<MetaPolyPolygonAction
&>(*pAct
)); break;
153 case MetaActionType::TEXT
: DoAction(static_cast<MetaTextAction
&>(*pAct
)); break;
154 case MetaActionType::TEXTARRAY
: DoAction(static_cast<MetaTextArrayAction
&>(*pAct
)); break;
155 case MetaActionType::STRETCHTEXT
: DoAction(static_cast<MetaStretchTextAction
&>(*pAct
)); break;
156 case MetaActionType::BMP
: DoAction(static_cast<MetaBmpAction
&>(*pAct
)); break;
157 case MetaActionType::BMPSCALE
: DoAction(static_cast<MetaBmpScaleAction
&>(*pAct
)); break;
158 case MetaActionType::BMPEX
: DoAction(static_cast<MetaBmpExAction
&>(*pAct
)); break;
159 case MetaActionType::BMPEXSCALE
: DoAction(static_cast<MetaBmpExScaleAction
&>(*pAct
)); break;
160 case MetaActionType::LINECOLOR
: DoAction(static_cast<MetaLineColorAction
&>(*pAct
)); break;
161 case MetaActionType::FILLCOLOR
: DoAction(static_cast<MetaFillColorAction
&>(*pAct
)); break;
162 case MetaActionType::TEXTCOLOR
: DoAction(static_cast<MetaTextColorAction
&>(*pAct
)); break;
163 case MetaActionType::TEXTFILLCOLOR
: DoAction(static_cast<MetaTextFillColorAction
&>(*pAct
)); break;
164 case MetaActionType::FONT
: DoAction(static_cast<MetaFontAction
&>(*pAct
)); break;
165 case MetaActionType::TEXTALIGN
: DoAction(static_cast<MetaTextAlignAction
&>(*pAct
)); break;
166 case MetaActionType::MAPMODE
: DoAction(static_cast<MetaMapModeAction
&>(*pAct
)); break;
167 case MetaActionType::CLIPREGION
: DoAction(static_cast<MetaClipRegionAction
&>(*pAct
)); break;
168 case MetaActionType::MOVECLIPREGION
: DoAction(static_cast<MetaMoveClipRegionAction
&>(*pAct
)); break;
169 case MetaActionType::ISECTRECTCLIPREGION
: DoAction(static_cast<MetaISectRectClipRegionAction
&>(*pAct
)); break;
170 case MetaActionType::ISECTREGIONCLIPREGION
: DoAction(static_cast<MetaISectRegionClipRegionAction
&>(*pAct
)); break;
171 case MetaActionType::RASTEROP
: DoAction(static_cast<MetaRasterOpAction
&>(*pAct
)); break;
172 case MetaActionType::PUSH
: DoAction(static_cast<MetaPushAction
&>(*pAct
)); break;
173 case MetaActionType::POP
: DoAction(static_cast<MetaPopAction
&>(*pAct
)); break;
174 case MetaActionType::HATCH
: DoAction(static_cast<MetaHatchAction
&>(*pAct
)); break;
176 // #i125211# MetaCommentAction may change index, thus hand it over
177 case MetaActionType::COMMENT
: DoAction(static_cast<MetaCommentAction
&>(*pAct
), rMtf
, a
);
180 // missing actions added
181 case MetaActionType::TEXTRECT
: DoAction(static_cast<MetaTextRectAction
&>(*pAct
)); break;
182 case MetaActionType::BMPSCALEPART
: DoAction(static_cast<MetaBmpScalePartAction
&>(*pAct
)); break;
183 case MetaActionType::BMPEXSCALEPART
: DoAction(static_cast<MetaBmpExScalePartAction
&>(*pAct
)); break;
184 case MetaActionType::MASK
: DoAction(static_cast<MetaMaskAction
&>(*pAct
)); break;
185 case MetaActionType::MASKSCALE
: DoAction(static_cast<MetaMaskScaleAction
&>(*pAct
)); break;
186 case MetaActionType::MASKSCALEPART
: DoAction(static_cast<MetaMaskScalePartAction
&>(*pAct
)); break;
187 case MetaActionType::GRADIENT
: DoAction(static_cast<MetaGradientAction
&>(*pAct
)); break;
188 case MetaActionType::WALLPAPER
: DoAction(static_cast<MetaWallpaperAction
&>(*pAct
)); break;
189 case MetaActionType::Transparent
: DoAction(static_cast<MetaTransparentAction
&>(*pAct
)); break;
190 case MetaActionType::EPS
: DoAction(static_cast<MetaEPSAction
&>(*pAct
)); break;
191 case MetaActionType::REFPOINT
: DoAction(static_cast<MetaRefPointAction
&>(*pAct
)); break;
192 case MetaActionType::TEXTLINECOLOR
: DoAction(static_cast<MetaTextLineColorAction
&>(*pAct
)); break;
193 case MetaActionType::TEXTLINE
: DoAction(static_cast<MetaTextLineAction
&>(*pAct
)); break;
194 case MetaActionType::FLOATTRANSPARENT
: DoAction(static_cast<MetaFloatTransparentAction
&>(*pAct
)); break;
195 case MetaActionType::GRADIENTEX
: DoAction(static_cast<MetaGradientExAction
&>(*pAct
)); break;
196 case MetaActionType::LAYOUTMODE
: DoAction(static_cast<MetaLayoutModeAction
&>(*pAct
)); break;
197 case MetaActionType::TEXTLANGUAGE
: DoAction(static_cast<MetaTextLanguageAction
&>(*pAct
)); break;
198 case MetaActionType::OVERLINECOLOR
: DoAction(static_cast<MetaOverlineColorAction
&>(*pAct
)); break;
202 if(pProgrInfo
&& pActionsToReport
)
204 (*pActionsToReport
)++;
206 if(*pActionsToReport
>= 16) // update all 16 actions
208 if(!pProgrInfo
->ReportActions(*pActionsToReport
))
211 *pActionsToReport
= 0;
217 size_t ImpSdrGDIMetaFileImport::DoImport(
218 const GDIMetaFile
& rMtf
,
221 SvdProgressInfo
* pProgrInfo
)
223 // setup some global scale parameter
224 // mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
225 mfScaleX
= mfScaleY
= 1.0;
226 const Size
aMtfSize(rMtf
.GetPrefSize());
228 if(aMtfSize
.Width() & aMtfSize
.Height() && (!maScaleRect
.IsEmpty()))
230 maOfs
= maScaleRect
.TopLeft();
232 if(aMtfSize
.Width() != (maScaleRect
.GetWidth() - 1))
234 mfScaleX
= (double)( maScaleRect
.GetWidth() - 1 ) / (double)aMtfSize
.Width();
237 if(aMtfSize
.Height() != (maScaleRect
.GetHeight() - 1))
239 mfScaleY
= (double)( maScaleRect
.GetHeight() - 1 ) / (double)aMtfSize
.Height();
243 mbMov
= maOfs
.X()!=0 || maOfs
.Y()!=0;
245 maScaleX
= Fraction( 1, 1 );
246 maScaleY
= Fraction( 1, 1 );
248 if(aMtfSize
.Width() != (maScaleRect
.GetWidth() - 1))
250 maScaleX
= Fraction(maScaleRect
.GetWidth() - 1, aMtfSize
.Width());
254 if(aMtfSize
.Height() != (maScaleRect
.GetHeight() - 1))
256 maScaleY
= Fraction(maScaleRect
.GetHeight() - 1, aMtfSize
.Height());
262 pProgrInfo
->SetActionCount(rMtf
.GetActionSize());
265 sal_uInt32
nActionsToReport(0);
268 DoLoopActions(const_cast< GDIMetaFile
& >(rMtf
), pProgrInfo
, &nActionsToReport
);
272 pProgrInfo
->ReportActions(nActionsToReport
);
273 nActionsToReport
= 0;
279 // To calculate the progress meter, we use GetActionSize()*3.
280 // However, maTmpList has a lower entry count limit than GetActionSize(),
281 // so the actions that were assumed were too much have to be re-added.
282 nActionsToReport
= (rMtf
.GetActionSize() - maTmpList
.size()) * 2;
284 // announce all currently unannounced rescales
287 pProgrInfo
->ReportRescales(nActionsToReport
);
288 pProgrInfo
->SetInsertCount(maTmpList
.size());
291 nActionsToReport
= 0;
293 // insert all objects cached in aTmpList now into rOL from nInsPos
294 nInsPos
= std::min(nInsPos
, rOL
.GetObjCount());
296 SdrInsertReason
aReason(SDRREASON_VIEWCALL
);
298 for(size_t i
= 0; i
< maTmpList
.size(); ++i
)
300 SdrObject
* pObj
= maTmpList
[i
];
301 rOL
.NbcInsertObject(pObj
, nInsPos
, &aReason
);
308 if(nActionsToReport
>= 32) // update all 32 actions
310 pProgrInfo
->ReportInserts(nActionsToReport
);
311 nActionsToReport
= 0;
316 // report all remaining inserts for the last time
319 pProgrInfo
->ReportInserts(nActionsToReport
);
322 return maTmpList
.size();
325 void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject
* pObj
, bool bForceTextAttr
)
329 bool bLine(!bForceTextAttr
);
330 bool bFill(!pObj
|| (pObj
->IsClosedObj() && !bForceTextAttr
));
331 bool bText(bForceTextAttr
|| (pObj
&& pObj
->GetOutlinerParaObject()));
337 mpLineAttr
->Put(XLineWidthItem(mnLineWidth
));
341 mpLineAttr
->Put(XLineWidthItem(0));
344 maOldLineColor
= mpVD
->GetLineColor();
346 if(mpVD
->IsLineColor())
348 mpLineAttr
->Put(XLineStyleItem(drawing::LineStyle_SOLID
));
349 mpLineAttr
->Put(XLineColorItem(OUString(), mpVD
->GetLineColor()));
353 mpLineAttr
->Put(XLineStyleItem(drawing::LineStyle_NONE
));
358 default : // basegfx::B2DLINEJOIN_NONE
359 mpLineAttr
->Put(XLineJointItem(com::sun::star::drawing::LineJoint_NONE
));
361 case basegfx::B2DLINEJOIN_MIDDLE
:
362 mpLineAttr
->Put(XLineJointItem(com::sun::star::drawing::LineJoint_MIDDLE
));
364 case basegfx::B2DLINEJOIN_BEVEL
:
365 mpLineAttr
->Put(XLineJointItem(com::sun::star::drawing::LineJoint_BEVEL
));
367 case basegfx::B2DLINEJOIN_MITER
:
368 mpLineAttr
->Put(XLineJointItem(com::sun::star::drawing::LineJoint_MITER
));
370 case basegfx::B2DLINEJOIN_ROUND
:
371 mpLineAttr
->Put(XLineJointItem(com::sun::star::drawing::LineJoint_ROUND
));
375 // Add LineCap support
376 mpLineAttr
->Put(XLineCapItem(maLineCap
));
378 if(((maDash
.GetDots() && maDash
.GetDotLen()) || (maDash
.GetDashes() && maDash
.GetDashLen())) && maDash
.GetDistance())
380 mpLineAttr
->Put(XLineDashItem(OUString(), maDash
));
384 mpLineAttr
->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT
)));
394 if(mpVD
->IsFillColor())
396 mpFillAttr
->Put(XFillStyleItem(drawing::FillStyle_SOLID
));
397 mpFillAttr
->Put(XFillColorItem(OUString(), mpVD
->GetFillColor()));
401 mpFillAttr
->Put(XFillStyleItem(drawing::FillStyle_NONE
));
409 if(bText
&& mbFntDirty
)
411 vcl::Font
aFnt(mpVD
->GetFont());
412 const sal_uInt32
nHeight(FRound(aFnt
.GetSize().Height() * mfScaleY
));
414 mpTextAttr
->Put( SvxFontItem( aFnt
.GetFamily(), aFnt
.GetName(), aFnt
.GetStyleName(), aFnt
.GetPitch(), aFnt
.GetCharSet(), EE_CHAR_FONTINFO
) );
415 mpTextAttr
->Put( SvxFontItem( aFnt
.GetFamily(), aFnt
.GetName(), aFnt
.GetStyleName(), aFnt
.GetPitch(), aFnt
.GetCharSet(), EE_CHAR_FONTINFO_CJK
) );
416 mpTextAttr
->Put( SvxFontItem( aFnt
.GetFamily(), aFnt
.GetName(), aFnt
.GetStyleName(), aFnt
.GetPitch(), aFnt
.GetCharSet(), EE_CHAR_FONTINFO_CTL
) );
417 mpTextAttr
->Put(SvxPostureItem(aFnt
.GetItalic(), EE_CHAR_ITALIC
));
418 mpTextAttr
->Put(SvxWeightItem(aFnt
.GetWeight(), EE_CHAR_WEIGHT
));
419 mpTextAttr
->Put( SvxFontHeightItem( nHeight
, 100, EE_CHAR_FONTHEIGHT
) );
420 mpTextAttr
->Put( SvxFontHeightItem( nHeight
, 100, EE_CHAR_FONTHEIGHT_CJK
) );
421 mpTextAttr
->Put( SvxFontHeightItem( nHeight
, 100, EE_CHAR_FONTHEIGHT_CTL
) );
422 mpTextAttr
->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH
));
423 mpTextAttr
->Put(SvxUnderlineItem(aFnt
.GetUnderline(), EE_CHAR_UNDERLINE
));
424 mpTextAttr
->Put(SvxOverlineItem(aFnt
.GetOverline(), EE_CHAR_OVERLINE
));
425 mpTextAttr
->Put(SvxCrossedOutItem(aFnt
.GetStrikeout(), EE_CHAR_STRIKEOUT
));
426 mpTextAttr
->Put(SvxShadowedItem(aFnt
.IsShadow(), EE_CHAR_SHADOW
));
428 // #i118485# Setting this item leads to problems (written #i118498# for this)
429 // mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
431 mpTextAttr
->Put(SvxWordLineModeItem(aFnt
.IsWordLineMode(), EE_CHAR_WLM
));
432 mpTextAttr
->Put(SvxContourItem(aFnt
.IsOutline(), EE_CHAR_OUTLINE
));
433 mpTextAttr
->Put(SvxColorItem(mpVD
->GetTextColor(), EE_CHAR_COLOR
));
434 //... svxfont textitem svditext
440 pObj
->SetLayer(mnLayer
);
444 pObj
->SetMergedItemSet(*mpLineAttr
);
449 pObj
->SetMergedItemSet(*mpFillAttr
);
454 pObj
->SetMergedItemSet(*mpTextAttr
);
455 pObj
->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT
));
460 void ImpSdrGDIMetaFileImport::InsertObj(SdrObject
* pObj
, bool bScale
)
462 if(bScale
&& !maScaleRect
.IsEmpty())
466 pObj
->NbcResize(Point(), maScaleX
, maScaleY
);
471 pObj
->NbcMove(Size(maOfs
.X(), maOfs
.Y()));
477 const basegfx::B2DPolyPolygon
aPoly(pObj
->TakeXorPoly());
478 const basegfx::B2DRange
aOldRange(aPoly
.getB2DRange());
479 const SdrLayerID
aOldLayer(pObj
->GetLayer());
480 const SfxItemSet
aOldItemSet(pObj
->GetMergedItemSet());
481 const SdrGrafObj
* pSdrGrafObj
= dynamic_cast< SdrGrafObj
* >(pObj
);
482 const SdrTextObj
* pSdrTextObj
= dynamic_cast< SdrTextObj
* >(pObj
);
484 if(pSdrTextObj
&& pSdrTextObj
->HasText())
486 // all text objects are created from ImportText and have no line or fill attributes, so
487 // it is okay to concentrate on the text itself
490 const basegfx::B2DPolyPolygon
aTextContour(pSdrTextObj
->TakeContour());
491 const basegfx::B2DRange
aTextRange(aTextContour
.getB2DRange());
492 const basegfx::B2DRange
aClipRange(maClip
.getB2DRange());
494 // no overlap -> completely outside
495 if(!aClipRange
.overlaps(aTextRange
))
497 SdrObject::Free(pObj
);
501 // when the clip is a rectangle fast check for inside is possible
502 if(basegfx::tools::isRectangle(maClip
) && aClipRange
.isInside(aTextRange
))
504 // completely inside ClipRect
508 // here text needs to be clipped; to do so, convert to SdrObjects with polygons
509 // and add these recursively. Delete original object, do not add in this run
510 SdrObject
* pConverted
= pSdrTextObj
->ConvertToPolyObj(true, true);
511 SdrObject::Free(pObj
);
515 // recursively add created conversion; per definition this shall not
516 // contain further SdrTextObjs. Visit only non-group objects
517 SdrObjListIter
aIter(*pConverted
, IM_DEEPNOGROUPS
);
519 // work with clones; the created conversion may contain group objects
520 // and when working with the original objects the loop itself could
521 // break and the cleanup later would be pretty complicated (only delete group
522 // objects, are these empty, ...?)
523 while(aIter
.IsMore())
525 SdrObject
* pCandidate
= aIter
.Next();
526 OSL_ENSURE(pCandidate
&& 0 == dynamic_cast< SdrObjGroup
* >(pCandidate
), "SdrObjListIter with IM_DEEPNOGROUPS error (!)");
527 SdrObject
* pNewClone
= pCandidate
->Clone();
531 InsertObj(pNewClone
, false);
535 OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
539 // cleanup temporary conversion objects
540 SdrObject::Free(pConverted
);
552 aBitmapEx
= pSdrGrafObj
->GetGraphic().GetBitmapEx();
555 SdrObject::Free(pObj
);
557 if(!aOldRange
.isEmpty())
559 // clip against ClipRegion
560 const basegfx::B2DPolyPolygon
aNewPoly(
561 basegfx::tools::clipPolyPolygonOnPolyPolygon(
566 const basegfx::B2DRange
aNewRange(aNewPoly
.getB2DRange());
568 if(!aNewRange
.isEmpty())
570 pObj
= new SdrPathObj(
571 aNewPoly
.isClosed() ? OBJ_POLY
: OBJ_PLIN
,
574 pObj
->SetLayer(aOldLayer
);
575 pObj
->SetMergedItemSet(aOldItemSet
);
579 // aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
580 const double fScaleX(aBitmapEx
.GetSizePixel().Width() / (aOldRange
.getWidth() ? aOldRange
.getWidth() : 1.0));
581 const double fScaleY(aBitmapEx
.GetSizePixel().Height() / (aOldRange
.getHeight() ? aOldRange
.getHeight() : 1.0));
582 basegfx::B2DRange
aPixel(aNewRange
);
583 basegfx::B2DHomMatrix aTrans
;
585 aTrans
.translate(-aOldRange
.getMinX(), -aOldRange
.getMinY());
586 aTrans
.scale(fScaleX
, fScaleY
);
587 aPixel
.transform(aTrans
);
589 const Size
aOrigSizePixel(aBitmapEx
.GetSizePixel());
590 const Point
aClipTopLeft(
591 basegfx::fround(floor(std::max(0.0, aPixel
.getMinX()))),
592 basegfx::fround(floor(std::max(0.0, aPixel
.getMinY()))));
593 const Size
aClipSize(
594 basegfx::fround(ceil(std::min((double)aOrigSizePixel
.Width(), aPixel
.getWidth()))),
595 basegfx::fround(ceil(std::min((double)aOrigSizePixel
.Height(), aPixel
.getHeight()))));
596 const BitmapEx
aClippedBitmap(
601 pObj
->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP
));
602 pObj
->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap
)));
603 pObj
->SetMergedItem(XFillBmpTileItem(false));
604 pObj
->SetMergedItem(XFillBmpStretchItem(true));
613 // #i111954# check object for visibility
614 // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
615 bool bVisible(false);
617 if(pObj
->HasLineStyle())
622 if(!bVisible
&& pObj
->HasFillStyle())
629 SdrTextObj
* pTextObj
= dynamic_cast< SdrTextObj
* >(pObj
);
631 if(pTextObj
&& pTextObj
->HasText())
639 SdrGrafObj
* pGrafObj
= dynamic_cast< SdrGrafObj
* >(pObj
);
643 // this may be refined to check if the graphic really is visible. It
644 // is here to ensure that graphic objects without fill, line and text
652 SdrObject::Free(pObj
);
656 maTmpList
.push_back(pObj
);
658 if(dynamic_cast< SdrPathObj
* >(pObj
))
660 const bool bClosed(pObj
->IsClosedObj());
662 mbLastObjWasPolyWithoutLine
= mbNoLine
&& bClosed
;
663 mbLastObjWasLine
= !bClosed
;
667 mbLastObjWasPolyWithoutLine
= false;
668 mbLastObjWasLine
= false;
674 void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction
& rAct
)
676 // #i73407# reformulation to use new B2DPolygon classes
677 const basegfx::B2DPoint
aStart(rAct
.GetStartPoint().X(), rAct
.GetStartPoint().Y());
678 const basegfx::B2DPoint
aEnd(rAct
.GetEndPoint().X(), rAct
.GetEndPoint().Y());
680 if(!aStart
.equal(aEnd
))
682 basegfx::B2DPolygon aLine
;
683 const basegfx::B2DHomMatrix
aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
685 aLine
.append(aStart
);
687 aLine
.transform(aTransform
);
689 const LineInfo
& rLineInfo
= rAct
.GetLineInfo();
690 const sal_Int32
nNewLineWidth(rLineInfo
.GetWidth());
691 bool bCreateLineObject(true);
693 if(mbLastObjWasLine
&& (nNewLineWidth
== mnLineWidth
) && CheckLastLineMerge(aLine
))
695 bCreateLineObject
= false;
698 if(bCreateLineObject
)
700 SdrPathObj
* pPath
= new SdrPathObj(OBJ_LINE
, basegfx::B2DPolyPolygon(aLine
));
701 mnLineWidth
= nNewLineWidth
;
702 maLineJoin
= rLineInfo
.GetLineJoin();
703 maLineCap
= rLineInfo
.GetLineCap();
704 maDash
= XDash(css::drawing::DashStyle_RECT
,
705 rLineInfo
.GetDotCount(), rLineInfo
.GetDotLen(),
706 rLineInfo
.GetDashCount(), rLineInfo
.GetDashLen(),
707 rLineInfo
.GetDistance());
708 SetAttributes(pPath
);
710 maLineJoin
= basegfx::B2DLINEJOIN_NONE
;
712 InsertObj(pPath
, false);
717 void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction
& rAct
)
719 SdrRectObj
* pRect
=new SdrRectObj(rAct
.GetRect());
720 SetAttributes(pRect
);
724 void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction
& rAct
)
726 SdrRectObj
* pRect
=new SdrRectObj(rAct
.GetRect());
727 SetAttributes(pRect
);
728 long nRad
=(rAct
.GetHorzRound()+rAct
.GetVertRound())/2;
730 SfxItemSet
aSet(*mpLineAttr
->GetPool(), SDRATTR_ECKENRADIUS
, SDRATTR_ECKENRADIUS
, 0, 0);
731 aSet
.Put(SdrMetricItem(SDRATTR_ECKENRADIUS
, nRad
));
732 pRect
->SetMergedItemSet(aSet
);
737 void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction
& rAct
)
739 SdrCircObj
* pCirc
=new SdrCircObj(OBJ_CIRC
,rAct
.GetRect());
740 SetAttributes(pCirc
);
744 void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction
& rAct
)
746 Point
aCenter(rAct
.GetRect().Center());
747 long nStart
=GetAngle(rAct
.GetStartPoint()-aCenter
);
748 long nEnd
=GetAngle(rAct
.GetEndPoint()-aCenter
);
749 SdrCircObj
* pCirc
=new SdrCircObj(OBJ_CARC
,rAct
.GetRect(),nStart
,nEnd
);
750 SetAttributes(pCirc
);
754 void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction
& rAct
)
756 Point
aCenter(rAct
.GetRect().Center());
757 long nStart
=GetAngle(rAct
.GetStartPoint()-aCenter
);
758 long nEnd
=GetAngle(rAct
.GetEndPoint()-aCenter
);
759 SdrCircObj
* pCirc
=new SdrCircObj(OBJ_SECT
,rAct
.GetRect(),nStart
,nEnd
);
760 SetAttributes(pCirc
);
764 void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction
& rAct
)
766 Point
aCenter(rAct
.GetRect().Center());
767 long nStart
=GetAngle(rAct
.GetStartPoint()-aCenter
);
768 long nEnd
=GetAngle(rAct
.GetEndPoint()-aCenter
);
769 SdrCircObj
* pCirc
=new SdrCircObj(OBJ_CCUT
,rAct
.GetRect(),nStart
,nEnd
);
770 SetAttributes(pCirc
);
774 bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon
& rSrcPoly
)
776 // #i102706# Do not merge closed polygons
777 if(rSrcPoly
.isClosed())
782 // #i73407# reformulation to use new B2DPolygon classes
783 if(mbLastObjWasLine
&& (maOldLineColor
== mpVD
->GetLineColor()) && rSrcPoly
.count())
785 SdrObject
* pTmpObj
= maTmpList
.size() ? maTmpList
[maTmpList
.size() - 1] : 0;
786 SdrPathObj
* pLastPoly
= dynamic_cast< SdrPathObj
* >(pTmpObj
);
790 if(1L == pLastPoly
->GetPathPoly().count())
793 basegfx::B2DPolygon
aDstPoly(pLastPoly
->GetPathPoly().getB2DPolygon(0L));
795 // #i102706# Do not merge closed polygons
796 if(aDstPoly
.isClosed())
803 const sal_uInt32
nMaxDstPnt(aDstPoly
.count() - 1L);
804 const sal_uInt32
nMaxSrcPnt(rSrcPoly
.count() - 1L);
806 if(aDstPoly
.getB2DPoint(nMaxDstPnt
) == rSrcPoly
.getB2DPoint(0L))
808 aDstPoly
.append(rSrcPoly
, 1L, rSrcPoly
.count() - 1L);
811 else if(aDstPoly
.getB2DPoint(0L) == rSrcPoly
.getB2DPoint(nMaxSrcPnt
))
813 basegfx::B2DPolygon
aNew(rSrcPoly
);
814 aNew
.append(aDstPoly
, 1L, aDstPoly
.count() - 1L);
818 else if(aDstPoly
.getB2DPoint(0L) == rSrcPoly
.getB2DPoint(0L))
821 aDstPoly
.append(rSrcPoly
, 1L, rSrcPoly
.count() - 1L);
824 else if(aDstPoly
.getB2DPoint(nMaxDstPnt
) == rSrcPoly
.getB2DPoint(nMaxSrcPnt
))
826 basegfx::B2DPolygon
aNew(rSrcPoly
);
828 aDstPoly
.append(aNew
, 1L, aNew
.count() - 1L);
835 pLastPoly
->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly
));
846 bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon
& rPolyPolygon
)
848 // #i73407# reformulation to use new B2DPolygon classes
849 if(mbLastObjWasPolyWithoutLine
)
851 SdrObject
* pTmpObj
= maTmpList
.size() ? maTmpList
[maTmpList
.size() - 1] : 0;
852 SdrPathObj
* pLastPoly
= dynamic_cast< SdrPathObj
* >(pTmpObj
);
856 if(pLastPoly
->GetPathPoly() == rPolyPolygon
)
860 if(!mbNoLine
&& mbNoFill
)
862 pLastPoly
->SetMergedItemSet(*mpLineAttr
);
873 void ImpSdrGDIMetaFileImport::checkClip()
875 if(mpVD
->IsClipRegion())
877 maClip
= mpVD
->GetClipRegion().GetAsB2DPolyPolygon();
881 const basegfx::B2DHomMatrix
aTransform(
882 basegfx::tools::createScaleTranslateB2DHomMatrix(
888 maClip
.transform(aTransform
);
893 bool ImpSdrGDIMetaFileImport::isClip() const
895 return !maClip
.getB2DRange().isEmpty();
898 void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction
& rAct
)
900 // #i73407# reformulation to use new B2DPolygon classes
901 basegfx::B2DPolygon
aSource(rAct
.GetPolygon().getB2DPolygon());
905 const basegfx::B2DHomMatrix
aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
906 aSource
.transform(aTransform
);
909 const LineInfo
& rLineInfo
= rAct
.GetLineInfo();
910 const sal_Int32
nNewLineWidth(rLineInfo
.GetWidth());
911 bool bCreateLineObject(true);
913 if(mbLastObjWasLine
&& (nNewLineWidth
== mnLineWidth
) && CheckLastLineMerge(aSource
))
915 bCreateLineObject
= false;
917 else if(mbLastObjWasPolyWithoutLine
&& CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource
)))
919 bCreateLineObject
= false;
922 if(bCreateLineObject
)
924 SdrPathObj
* pPath
= new SdrPathObj(
925 aSource
.isClosed() ? OBJ_POLY
: OBJ_PLIN
,
926 basegfx::B2DPolyPolygon(aSource
));
927 mnLineWidth
= nNewLineWidth
;
928 maLineJoin
= rLineInfo
.GetLineJoin();
929 maLineCap
= rLineInfo
.GetLineCap();
930 maDash
= XDash(css::drawing::DashStyle_RECT
,
931 rLineInfo
.GetDotCount(), rLineInfo
.GetDotLen(),
932 rLineInfo
.GetDashCount(), rLineInfo
.GetDashLen(),
933 rLineInfo
.GetDistance());
934 SetAttributes(pPath
);
936 maLineJoin
= basegfx::B2DLINEJOIN_NONE
;
938 InsertObj(pPath
, false);
942 void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction
& rAct
)
944 // #i73407# reformulation to use new B2DPolygon classes
945 basegfx::B2DPolygon
aSource(rAct
.GetPolygon().getB2DPolygon());
949 const basegfx::B2DHomMatrix
aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
950 aSource
.transform(aTransform
);
952 if(!mbLastObjWasPolyWithoutLine
|| !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource
)))
954 // #i73407# make sure polygon is closed, it's a filled primitive
955 aSource
.setClosed(true);
956 SdrPathObj
* pPath
= new SdrPathObj(OBJ_POLY
, basegfx::B2DPolyPolygon(aSource
));
957 SetAttributes(pPath
);
958 InsertObj(pPath
, false);
963 void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction
& rAct
)
965 // #i73407# reformulation to use new B2DPolygon classes
966 basegfx::B2DPolyPolygon
aSource(rAct
.GetPolyPolygon().getB2DPolyPolygon());
970 const basegfx::B2DHomMatrix
aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
971 aSource
.transform(aTransform
);
973 if(!mbLastObjWasPolyWithoutLine
|| !CheckLastPolyLineAndFillMerge(aSource
))
975 // #i73407# make sure polygon is closed, it's a filled primitive
976 aSource
.setClosed(true);
977 SdrPathObj
* pPath
= new SdrPathObj(OBJ_POLY
, aSource
);
978 SetAttributes(pPath
);
979 InsertObj(pPath
, false);
984 void ImpSdrGDIMetaFileImport::ImportText( const Point
& rPos
, const OUString
& rStr
, const MetaAction
& rAct
)
986 // calc text box size, add 5% to make it fit safely
988 FontMetric
aFontMetric( mpVD
->GetFontMetric() );
989 vcl::Font
aFnt( mpVD
->GetFont() );
990 FontAlign
eAlg( aFnt
.GetAlign() );
992 sal_Int32 nTextWidth
= (sal_Int32
)( mpVD
->GetTextWidth( rStr
) * mfScaleX
);
993 sal_Int32 nTextHeight
= (sal_Int32
)( mpVD
->GetTextHeight() * mfScaleY
);
995 Point
aPos( FRound(rPos
.X() * mfScaleX
+ maOfs
.X()), FRound(rPos
.Y() * mfScaleY
+ maOfs
.Y()) );
996 Size
aSize( nTextWidth
, nTextHeight
);
998 if ( eAlg
== ALIGN_BASELINE
)
999 aPos
.Y() -= FRound(aFontMetric
.GetAscent() * mfScaleY
);
1000 else if ( eAlg
== ALIGN_BOTTOM
)
1001 aPos
.Y() -= nTextHeight
;
1003 Rectangle
aTextRect( aPos
, aSize
);
1004 SdrRectObj
* pText
=new SdrRectObj( OBJ_TEXT
, aTextRect
);
1006 pText
->SetMergedItem ( makeSdrTextUpperDistItem (0));
1007 pText
->SetMergedItem ( makeSdrTextLowerDistItem (0));
1008 pText
->SetMergedItem ( makeSdrTextRightDistItem (0));
1009 pText
->SetMergedItem ( makeSdrTextLeftDistItem (0));
1011 if ( aFnt
.GetWidth() || ( rAct
.GetType() == MetaActionType::STRETCHTEXT
) )
1013 pText
->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH
);
1014 pText
->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
1015 // don't let the margins eat the space needed for the text
1016 pText
->SetMergedItem( SdrTextFitToSizeTypeItem( SDRTEXTFIT_ALLLINES
) );
1020 pText
->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
1023 pText
->SetModel(mpModel
);
1024 pText
->SetLayer(mnLayer
);
1025 pText
->NbcSetText( rStr
);
1026 SetAttributes( pText
, true );
1027 pText
->SetSnapRect( aTextRect
);
1029 if (!aFnt
.IsTransparent())
1031 SfxItemSet
aAttr(*mpFillAttr
->GetPool(), XATTR_FILL_FIRST
, XATTR_FILL_LAST
, 0, 0);
1032 aAttr
.Put(XFillStyleItem(drawing::FillStyle_SOLID
));
1033 aAttr
.Put(XFillColorItem(OUString(), aFnt
.GetFillColor()));
1034 pText
->SetMergedItemSet(aAttr
);
1036 sal_uInt32 nAngle
= aFnt
.GetOrientation();
1040 double a
=nAngle
*nPi180
;
1043 pText
->NbcRotate(aPos
,nAngle
,nSin
,nCos
);
1045 InsertObj( pText
, false );
1048 void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction
& rAct
)
1050 OUString
aStr(rAct
.GetText());
1051 aStr
= aStr
.copy(rAct
.GetIndex(), rAct
.GetLen());
1052 ImportText( rAct
.GetPoint(), aStr
, rAct
);
1055 void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction
& rAct
)
1057 OUString
aStr(rAct
.GetText());
1058 aStr
= aStr
.copy(rAct
.GetIndex(), rAct
.GetLen());
1059 ImportText( rAct
.GetPoint(), aStr
, rAct
);
1062 void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction
& rAct
)
1064 OUString
aStr(rAct
.GetText());
1065 aStr
= aStr
.copy(rAct
.GetIndex(), rAct
.GetLen());
1066 ImportText( rAct
.GetPoint(), aStr
, rAct
);
1069 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction
& rAct
)
1071 Rectangle
aRect(rAct
.GetPoint(),rAct
.GetBitmap().GetSizePixel());
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(MetaBmpScaleAction
& rAct
)
1083 Rectangle
aRect(rAct
.GetPoint(),rAct
.GetSize());
1084 aRect
.Right()++; aRect
.Bottom()++;
1085 SdrGrafObj
* pGraf
=new SdrGrafObj(Graphic(rAct
.GetBitmap()),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(MetaBmpExAction
& rAct
)
1095 Rectangle
aRect(rAct
.GetPoint(),rAct
.GetBitmapEx().GetSizePixel());
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
));
1105 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction
& rAct
)
1107 Rectangle
aRect(rAct
.GetPoint(),rAct
.GetSize());
1108 aRect
.Right()++; aRect
.Bottom()++;
1109 SdrGrafObj
* pGraf
=new SdrGrafObj( rAct
.GetBitmapEx(), aRect
);
1111 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1112 pGraf
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
1113 pGraf
->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE
));
1119 void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction
& rAct
)
1121 // #i73407# reformulation to use new B2DPolygon classes
1122 basegfx::B2DPolyPolygon
aSource(rAct
.GetPolyPolygon().getB2DPolyPolygon());
1126 const basegfx::B2DHomMatrix
aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
1127 aSource
.transform(aTransform
);
1129 if(!mbLastObjWasPolyWithoutLine
|| !CheckLastPolyLineAndFillMerge(aSource
))
1131 const Hatch
& rHatch
= rAct
.GetHatch();
1132 SdrPathObj
* pPath
= new SdrPathObj(OBJ_POLY
, aSource
);
1133 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1134 SfxItemSet
aHatchAttr(mpModel
->GetItemPool(), pPath
->GetMergedItemSet().GetRanges());
1135 css::drawing::HatchStyle eStyle
;
1137 switch(rHatch
.GetStyle())
1139 case(HATCH_TRIPLE
) :
1141 eStyle
= css::drawing::HatchStyle_TRIPLE
;
1145 case(HATCH_DOUBLE
) :
1147 eStyle
= css::drawing::HatchStyle_DOUBLE
;
1153 eStyle
= css::drawing::HatchStyle_SINGLE
;
1158 SetAttributes(pPath
);
1159 aHatchAttr
.Put(XFillStyleItem(drawing::FillStyle_HATCH
));
1160 aHatchAttr
.Put(XFillHatchItem(&mpModel
->GetItemPool(), XHatch(rHatch
.GetColor(), eStyle
, rHatch
.GetDistance(), rHatch
.GetAngle())));
1161 pPath
->SetMergedItemSet(aHatchAttr
);
1163 InsertObj(pPath
, false);
1170 void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction
& rAct
)
1175 void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction
& rAct
)
1179 mbLastObjWasPolyWithoutLine
= false;
1180 mbLastObjWasLine
= false;
1183 void ImpSdrGDIMetaFileImport::MapScaling()
1185 const size_t nCount(maTmpList
.size());
1186 const MapMode
& rMap
= mpVD
->GetMapMode();
1187 Point
aMapOrg( rMap
.GetOrigin() );
1188 bool bMov2(aMapOrg
.X() != 0 || aMapOrg
.Y() != 0);
1192 for(size_t i
= mnMapScalingOfs
; i
< nCount
; i
++)
1194 SdrObject
* pObj
= maTmpList
[i
];
1196 pObj
->NbcMove(Size(aMapOrg
.X(), aMapOrg
.Y()));
1200 mnMapScalingOfs
= nCount
;
1205 void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction
& rAct
, GDIMetaFile
& rMtf
, sal_uLong
& a
) // GDIMetaFile* pMtf )
1207 bool aSkipComment
= false;
1209 if (a
< rMtf
.GetActionSize() && rAct
.GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
1211 // #i125211# Check if next action is a MetaGradientExAction
1212 MetaGradientExAction
* pAct
= dynamic_cast< MetaGradientExAction
* >(rMtf
.GetAction(a
+ 1));
1214 if( pAct
&& pAct
->GetType() == MetaActionType::GRADIENTEX
)
1216 // #i73407# reformulation to use new B2DPolygon classes
1217 basegfx::B2DPolyPolygon
aSource(pAct
->GetPolyPolygon().getB2DPolyPolygon());
1221 if(!mbLastObjWasPolyWithoutLine
|| !CheckLastPolyLineAndFillMerge(aSource
))
1223 const Gradient
& rGrad
= pAct
->GetGradient();
1224 SdrPathObj
* pPath
= new SdrPathObj(OBJ_POLY
, aSource
);
1225 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1226 SfxItemSet
aGradAttr(mpModel
->GetItemPool(), pPath
->GetMergedItemSet().GetRanges());
1227 XGradient aXGradient
;
1229 aXGradient
.SetGradientStyle((css::awt::GradientStyle
)rGrad
.GetStyle());
1230 aXGradient
.SetStartColor(rGrad
.GetStartColor());
1231 aXGradient
.SetEndColor(rGrad
.GetEndColor());
1232 aXGradient
.SetAngle((sal_uInt16
)rGrad
.GetAngle());
1233 aXGradient
.SetBorder(rGrad
.GetBorder());
1234 aXGradient
.SetXOffset(rGrad
.GetOfsX());
1235 aXGradient
.SetYOffset(rGrad
.GetOfsY());
1236 aXGradient
.SetStartIntens(rGrad
.GetStartIntensity());
1237 aXGradient
.SetEndIntens(rGrad
.GetEndIntensity());
1238 aXGradient
.SetSteps(rGrad
.GetSteps());
1240 // no need to use SetAttributes(..) here since line and fill style
1241 // need to be set individually
1242 // SetAttributes(pPath);
1244 // switch line off; if there was one there will be a
1245 // MetaActionType::POLYLINE following creating another object
1246 aGradAttr
.Put(XLineStyleItem(drawing::LineStyle_NONE
));
1248 // add detected gradient fillstyle
1249 aGradAttr
.Put(XFillStyleItem(drawing::FillStyle_GRADIENT
));
1250 aGradAttr
.Put(XFillGradientItem(aXGradient
));
1252 pPath
->SetMergedItemSet(aGradAttr
);
1258 aSkipComment
= true;
1264 // #i125211# forward until closing MetaCommentAction
1265 MetaAction
* pSkipAct
= rMtf
.GetAction(++a
);
1268 && ((pSkipAct
->GetType() != MetaActionType::COMMENT
)
1269 || !(static_cast<MetaCommentAction
*>(pSkipAct
)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END"))))
1271 pSkipAct
= rMtf
.GetAction(++a
);
1276 void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction
& rAct
)
1280 mpVD
->AddTextRectActions(rAct
.GetRect(), rAct
.GetText(), rAct
.GetStyle(), aTemp
);
1281 DoLoopActions(aTemp
, 0, 0);
1284 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction
& rAct
)
1286 Rectangle
aRect(rAct
.GetDestPoint(), rAct
.GetDestSize());
1287 Bitmap
aBitmap(rAct
.GetBitmap());
1291 aBitmap
.Crop(Rectangle(rAct
.GetSrcPoint(), rAct
.GetSrcSize()));
1292 SdrGrafObj
* pGraf
= new SdrGrafObj(aBitmap
, aRect
);
1294 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1295 pGraf
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
1296 pGraf
->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE
));
1300 void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction
& rAct
)
1302 Rectangle
aRect(rAct
.GetDestPoint(),rAct
.GetDestSize());
1303 BitmapEx
aBitmapEx(rAct
.GetBitmapEx());
1307 aBitmapEx
.Crop(Rectangle(rAct
.GetSrcPoint(), rAct
.GetSrcSize()));
1308 SdrGrafObj
* pGraf
= new SdrGrafObj(aBitmapEx
, aRect
);
1310 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1311 pGraf
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
1312 pGraf
->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE
));
1316 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction
& rAct
)
1318 Rectangle
aRect(rAct
.GetPoint(), rAct
.GetBitmap().GetSizePixel());
1319 BitmapEx
aBitmapEx(rAct
.GetBitmap(), rAct
.GetColor());
1321 aRect
.Right()++; aRect
.Bottom()++;
1322 SdrGrafObj
* pGraf
= new SdrGrafObj(aBitmapEx
, aRect
);
1324 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1325 pGraf
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
1326 pGraf
->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE
));
1330 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction
& rAct
)
1332 Rectangle
aRect(rAct
.GetPoint(), rAct
.GetSize());
1333 BitmapEx
aBitmapEx(rAct
.GetBitmap(), rAct
.GetColor());
1335 aRect
.Right()++; aRect
.Bottom()++;
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
));
1344 void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction
& rAct
)
1346 Rectangle
aRect(rAct
.GetDestPoint(), rAct
.GetDestSize());
1347 BitmapEx
aBitmapEx(rAct
.GetBitmap(), rAct
.GetColor());
1349 aRect
.Right()++; aRect
.Bottom()++;
1350 aBitmapEx
.Crop(Rectangle(rAct
.GetSrcPoint(), rAct
.GetSrcSize()));
1351 SdrGrafObj
* pGraf
= new SdrGrafObj(aBitmapEx
, aRect
);
1353 // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1354 pGraf
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
1355 pGraf
->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE
));
1361 css::awt::GradientStyle
getXGradientStyleFromGradientStyle(const GradientStyle
& rGradientStyle
)
1363 css::awt::GradientStyle
aXGradientStyle(css::awt::GradientStyle_LINEAR
);
1365 switch(rGradientStyle
)
1367 case GradientStyle_LINEAR
: aXGradientStyle
= css::awt::GradientStyle_LINEAR
; break;
1368 case GradientStyle_AXIAL
: aXGradientStyle
= css::awt::GradientStyle_AXIAL
; break;
1369 case GradientStyle_RADIAL
: aXGradientStyle
= css::awt::GradientStyle_RADIAL
; break;
1370 case GradientStyle_ELLIPTICAL
: aXGradientStyle
= css::awt::GradientStyle_ELLIPTICAL
; break;
1371 case GradientStyle_SQUARE
: aXGradientStyle
= css::awt::GradientStyle_SQUARE
; break;
1372 case GradientStyle_RECT
: aXGradientStyle
= css::awt::GradientStyle_RECT
; break;
1374 // Needed due to GradientStyle_FORCE_EQUAL_SIZE; this again is needed
1375 // to force the enum defines in VCL to a defined size for the compilers,
1376 // so despite it is never used it cannot be removed (would break the
1377 // API implementation probably).
1378 case GradientStyle_FORCE_EQUAL_SIZE
: break;
1383 return aXGradientStyle
;
1387 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction
& rAct
)
1389 basegfx::B2DRange
aRange(rAct
.GetRect().Left(), rAct
.GetRect().Top(), rAct
.GetRect().Right(), rAct
.GetRect().Bottom());
1391 if(!aRange
.isEmpty())
1393 const basegfx::B2DHomMatrix
aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
1394 aRange
.transform(aTransform
);
1395 const Gradient
& rGradient
= rAct
.GetGradient();
1396 SdrRectObj
* pRect
= new SdrRectObj(
1398 floor(aRange
.getMinX()),
1399 floor(aRange
.getMinY()),
1400 ceil(aRange
.getMaxX()),
1401 ceil(aRange
.getMaxY())));
1402 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1403 SfxItemSet
aGradientAttr(mpModel
->GetItemPool(), pRect
->GetMergedItemSet().GetRanges());
1404 const css::awt::GradientStyle
aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient
.GetStyle()));
1405 const XFillGradientItem
aXFillGradientItem(
1407 rGradient
.GetStartColor(),
1408 rGradient
.GetEndColor(),
1410 rGradient
.GetAngle(),
1411 rGradient
.GetOfsX(),
1412 rGradient
.GetOfsY(),
1413 rGradient
.GetBorder(),
1414 rGradient
.GetStartIntensity(),
1415 rGradient
.GetEndIntensity(),
1416 rGradient
.GetSteps()));
1418 SetAttributes(pRect
);
1419 aGradientAttr
.Put(XFillStyleItem(drawing::FillStyle_GRADIENT
)); // #i125211#
1420 aGradientAttr
.Put(aXFillGradientItem
);
1421 pRect
->SetMergedItemSet(aGradientAttr
);
1423 InsertObj(pRect
, false);
1427 void ImpSdrGDIMetaFileImport::DoAction(MetaWallpaperAction
&)
1429 OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)");
1432 void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction
& rAct
)
1434 basegfx::B2DPolyPolygon
aSource(rAct
.GetPolyPolygon().getB2DPolyPolygon());
1438 const basegfx::B2DHomMatrix
aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
1439 aSource
.transform(aTransform
);
1440 aSource
.setClosed(true);
1442 SdrPathObj
* pPath
= new SdrPathObj(OBJ_POLY
, aSource
);
1443 SetAttributes(pPath
);
1444 pPath
->SetMergedItem(XFillTransparenceItem(rAct
.GetTransparence()));
1445 InsertObj(pPath
, false);
1449 void ImpSdrGDIMetaFileImport::DoAction(MetaEPSAction
&)
1451 OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)");
1454 void ImpSdrGDIMetaFileImport::DoAction(MetaTextLineAction
&)
1456 OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)");
1459 void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction
& rAct
)
1461 basegfx::B2DPolyPolygon
aSource(rAct
.GetPolyPolygon().getB2DPolyPolygon());
1465 const basegfx::B2DHomMatrix
aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX
, mfScaleY
, maOfs
.X(), maOfs
.Y()));
1466 aSource
.transform(aTransform
);
1468 if(!mbLastObjWasPolyWithoutLine
|| !CheckLastPolyLineAndFillMerge(aSource
))
1470 const Gradient
& rGradient
= rAct
.GetGradient();
1471 SdrPathObj
* pPath
= new SdrPathObj(OBJ_POLY
, aSource
);
1472 // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1473 SfxItemSet
aGradientAttr(mpModel
->GetItemPool(), pPath
->GetMergedItemSet().GetRanges());
1474 const css::awt::GradientStyle
aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient
.GetStyle()));
1475 const XFillGradientItem
aXFillGradientItem(
1477 rGradient
.GetStartColor(),
1478 rGradient
.GetEndColor(),
1480 rGradient
.GetAngle(),
1481 rGradient
.GetOfsX(),
1482 rGradient
.GetOfsY(),
1483 rGradient
.GetBorder(),
1484 rGradient
.GetStartIntensity(),
1485 rGradient
.GetEndIntensity(),
1486 rGradient
.GetSteps()));
1488 SetAttributes(pPath
);
1489 aGradientAttr
.Put(XFillStyleItem(drawing::FillStyle_GRADIENT
)); // #i125211#
1490 aGradientAttr
.Put(aXFillGradientItem
);
1491 pPath
->SetMergedItemSet(aGradientAttr
);
1493 InsertObj(pPath
, false);
1498 void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction
& rAct
)
1500 const GDIMetaFile
& rMtf
= rAct
.GetGDIMetaFile();
1502 if(rMtf
.GetActionSize())
1504 const Rectangle
aRect(rAct
.GetPoint(),rAct
.GetSize());
1506 // convert metafile sub-content to BitmapEx
1508 convertMetafileToBitmapEx(
1511 aRect
.Left(), aRect
.Top(),
1512 aRect
.Right(), aRect
.Bottom()),
1516 const Gradient
& rGradient
= rAct
.GetGradient();
1517 basegfx::BColor
aStart(rGradient
.GetStartColor().getBColor());
1518 basegfx::BColor
aEnd(rGradient
.GetEndColor().getBColor());
1520 if(100 != rGradient
.GetStartIntensity())
1522 aStart
*= (double)rGradient
.GetStartIntensity() / 100.0;
1525 if(100 != rGradient
.GetEndIntensity())
1527 aEnd
*= (double)rGradient
.GetEndIntensity() / 100.0;
1530 const bool bEqualColors(aStart
== aEnd
);
1531 const bool bNoSteps(1 == rGradient
.GetSteps());
1532 bool bCreateObject(true);
1533 bool bHasNewMask(false);
1535 double fTransparence(0.0);
1536 bool bFixedTransparence(false);
1538 if(bEqualColors
|| bNoSteps
)
1540 // single transparence
1541 const basegfx::BColor
aMedium(basegfx::average(aStart
, aEnd
));
1542 fTransparence
= aMedium
.luminance();
1544 if(basegfx::fTools::lessOrEqual(fTransparence
, 0.0))
1546 // no transparence needed, all done
1548 else if(basegfx::fTools::moreOrEqual(fTransparence
, 1.0))
1550 // all transparent, no object
1551 bCreateObject
= false;
1555 // 0.0 < transparence < 1.0, apply fixed transparence
1556 bFixedTransparence
= true;
1561 // gradient transparence
1562 ScopedVclPtrInstance
< VirtualDevice
> pVDev
;
1564 pVDev
->SetOutputSizePixel(aBitmapEx
.GetBitmap().GetSizePixel());
1565 pVDev
->DrawGradient(Rectangle(Point(0, 0), pVDev
->GetOutputSizePixel()), rGradient
);
1567 aNewMask
= AlphaMask(pVDev
->GetBitmap(Point(0, 0), pVDev
->GetOutputSizePixel()));
1573 if(bHasNewMask
|| bFixedTransparence
)
1575 if(!aBitmapEx
.IsAlpha() && !aBitmapEx
.IsTransparent())
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 // mix existing and new alpha mask
1592 if(aBitmapEx
.IsAlpha())
1594 aOldMask
= aBitmapEx
.GetAlpha();
1596 else if(TRANSPARENT_BITMAP
== aBitmapEx
.GetTransparentType())
1598 aOldMask
= aBitmapEx
.GetMask();
1600 else if(TRANSPARENT_COLOR
== aBitmapEx
.GetTransparentType())
1602 aOldMask
= aBitmapEx
.GetBitmap().CreateMask(aBitmapEx
.GetTransparentColor());
1605 BitmapWriteAccess
* pOld
= aOldMask
.AcquireWriteAccess();
1609 const double fFactor(1.0 / 255.0);
1611 if(bFixedTransparence
)
1613 const double fOpNew(1.0 - fTransparence
);
1615 for(int y(0); y
< pOld
->Height(); y
++)
1617 for(int x(0); x
< pOld
->Width(); x
++)
1619 const double fOpOld(1.0 - (pOld
->GetPixel(y
, x
).GetIndex() * fFactor
));
1620 const sal_uInt8
aCol(basegfx::fround((1.0 - (fOpOld
* fOpNew
)) * 255.0));
1622 pOld
->SetPixel(y
, x
, BitmapColor(aCol
));
1628 BitmapReadAccess
* pNew
= aNewMask
.AcquireReadAccess();
1632 if(pOld
->Width() == pNew
->Width() && pOld
->Height() == pNew
->Height())
1634 for(int y(0); y
< pOld
->Height(); y
++)
1636 for(int x(0); x
< pOld
->Width(); x
++)
1638 const double fOpOld(1.0 - (pOld
->GetPixel(y
, x
).GetIndex() * fFactor
));
1639 const double fOpNew(1.0 - (pNew
->GetPixel(y
, x
).GetIndex() * fFactor
));
1640 const sal_uInt8
aCol(basegfx::fround((1.0 - (fOpOld
* fOpNew
)) * 255.0));
1642 pOld
->SetPixel(y
, x
, BitmapColor(aCol
));
1648 OSL_ENSURE(false, "Alpha masks have different sizes (!)");
1651 aNewMask
.ReleaseAccess(pNew
);
1655 OSL_ENSURE(false, "Got no access to new alpha mask (!)");
1659 aOldMask
.ReleaseAccess(pOld
);
1663 OSL_ENSURE(false, "Got no access to old alpha mask (!)");
1666 // apply combined bitmap as mask
1667 aBitmapEx
= BitmapEx(aBitmapEx
.GetBitmap(), aOldMask
);
1671 // create and add object
1672 SdrGrafObj
* pGraf
= new SdrGrafObj(aBitmapEx
, aRect
);
1674 // for MetaFloatTransparentAction, do not use SetAttributes(...)
1675 // since these metafile content is not used to draw line/fill
1676 // dependent of these setting at the device content
1677 pGraf
->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE
));
1678 pGraf
->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE
));
1684 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */