Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/svdraw/svdfmtf.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include "svdfmtf.hxx"
21
#include <math.h>
22
#include <editeng/eeitem.hxx>
23
#include <editeng/fhgtitem.hxx>
24
#include <editeng/wghtitem.hxx>
25
#include <editeng/postitem.hxx>
26
#include <editeng/udlnitem.hxx>
27
#include <editeng/crossedoutitem.hxx>
28
#include <editeng/shdditem.hxx>
29
#include <svx/xlineit0.hxx>
30
#include <svx/xlnclit.hxx>
31
#include <svx/xlncapit.hxx>
32
#include <svx/xlnwtit.hxx>
33
#include <svx/xfillit0.hxx>
34
#include <svx/xflclit.hxx>
35
#include <svx/xflgrit.hxx>
36
#include <editeng/fontitem.hxx>
37
#include <editeng/wrlmitem.hxx>
38
#include <editeng/contouritem.hxx>
39
#include <editeng/colritem.hxx>
40
#include <vcl/alpha.hxx>
41
#include <vcl/canvastools.hxx>
42
#include <vcl/metaactiontypes.hxx>
43
#include <vcl/metric.hxx>
44
#include <editeng/charscaleitem.hxx>
45
#include <svx/xflhtit.hxx>
46
#include <svx/sdmetitm.hxx>
47
#include <svx/sdtagitm.hxx>
48
#include <svx/sdtaitm.hxx>
49
#include <svx/sdtditm.hxx>
50
#include <svx/sdtfsitm.hxx>
51
#include <svx/svdmodel.hxx>
52
#include <svx/svdpage.hxx>
53
#include <svx/svdobj.hxx>
54
#include <svx/svdotext.hxx>
55
#include <svx/svdorect.hxx>
56
#include <svx/svdocirc.hxx>
57
#include <svx/svdograf.hxx>
58
#include <svx/svdopath.hxx>
59
#include <svx/svdetc.hxx>
60
#include <svl/itemset.hxx>
61
#include <basegfx/polygon/b2dpolygon.hxx>
62
#include <tools/helpers.hxx>
63
#include <basegfx/matrix/b2dhommatrix.hxx>
64
#include <basegfx/matrix/b2dhommatrixtools.hxx>
65
#include <svx/xlinjoit.hxx>
66
#include <svx/xlndsit.hxx>
67
#include <basegfx/polygon/b2dpolygonclipper.hxx>
68
#include <svx/xbtmpit.hxx>
69
#include <svx/xfltrit.hxx>
70
#include <svx/xflbmtit.hxx>
71
#include <svx/xflbstit.hxx>
72
#include <svx/svdpntv.hxx>
73
#include <basegfx/polygon/b2dpolypolygontools.hxx>
74
#include <svx/svditer.hxx>
75
#include <svx/svdogrp.hxx>
76
#include <vcl/BitmapTools.hxx>
77
#include <osl/diagnose.h>
78
79
using namespace com::sun::star;
80
81
ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
82
    SdrModel& rModel,
83
    SdrLayerID nLay,
84
    const tools::Rectangle& rRect)
85
0
:   mpVD(VclPtr<VirtualDevice>::Create()),
86
0
    maScaleRect(rRect),
87
0
    mpModel(&rModel),
88
0
    mnLayer(nLay),
89
0
    mnLineWidth(0),
90
0
    maLineJoin(basegfx::B2DLineJoin::NONE),
91
0
    maLineCap(css::drawing::LineCap_BUTT),
92
0
    maDash(css::drawing::DashStyle_RECT, 0, 0, 0, 0, 0),
93
0
    mbMov(false),
94
0
    mbSize(false),
95
0
    maOfs(0, 0),
96
0
    mfScaleX(1.0),
97
0
    mfScaleY(1.0),
98
0
    maScaleX(1.0),
99
0
    maScaleY(1.0),
100
0
    mbFntDirty(true),
101
0
    mbLastObjWasPolyWithoutLine(false),
102
0
    mbNoLine(false),
103
0
    mbNoFill(false),
104
0
    mbLastObjWasLine(false)
105
0
{
106
0
    mpVD->EnableOutput(false);
107
0
    mpVD->SetLineColor();
108
0
    mpVD->SetFillColor();
109
0
    maOldLineColor.SetRed( mpVD->GetLineColor().GetRed() + 1 );
110
0
    mpLineAttr = std::make_unique<SfxItemSetFixed<XATTR_LINE_FIRST, XATTR_LINE_LAST>>(rModel.GetItemPool());
111
0
    mpFillAttr = std::make_unique<SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST>>(rModel.GetItemPool());
112
0
    mpTextAttr = std::make_unique<SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END>>(rModel.GetItemPool());
113
0
    checkClip();
114
0
}
115
116
void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile const & rMtf, SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
117
0
{
118
0
    const size_t nCount = rMtf.GetActionSize();
119
120
0
    for(size_t a = 0; a < nCount; a++)
121
0
    {
122
0
        MetaAction* pAct = rMtf.GetAction(a);
123
124
0
        if(!pAct)
125
0
        {
126
0
            OSL_ENSURE(false, "OOps, no action at valid position (!)");
127
0
            pAct = rMtf.GetAction(0);
128
0
        }
129
130
0
        switch (pAct->GetType())
131
0
        {
132
0
            case MetaActionType::PIXEL          : break;
133
0
            case MetaActionType::POINT          : break;
134
0
            case MetaActionType::LINE           : DoAction(static_cast<MetaLineAction           &>(*pAct)); break;
135
0
            case MetaActionType::RECT           : DoAction(static_cast<MetaRectAction           &>(*pAct)); break;
136
0
            case MetaActionType::ROUNDRECT      : DoAction(static_cast<MetaRoundRectAction      &>(*pAct)); break;
137
0
            case MetaActionType::ELLIPSE        : DoAction(static_cast<MetaEllipseAction        &>(*pAct)); break;
138
0
            case MetaActionType::ARC            : DoAction(static_cast<MetaArcAction            &>(*pAct)); break;
139
0
            case MetaActionType::PIE            : DoAction(static_cast<MetaPieAction            &>(*pAct)); break;
140
0
            case MetaActionType::CHORD          : DoAction(static_cast<MetaChordAction          &>(*pAct)); break;
141
0
            case MetaActionType::POLYLINE       : DoAction(static_cast<MetaPolyLineAction       &>(*pAct)); break;
142
0
            case MetaActionType::POLYGON        : DoAction(static_cast<MetaPolygonAction        &>(*pAct)); break;
143
0
            case MetaActionType::POLYPOLYGON    : DoAction(static_cast<MetaPolyPolygonAction    &>(*pAct)); break;
144
0
            case MetaActionType::TEXT           : DoAction(static_cast<MetaTextAction           &>(*pAct)); break;
145
0
            case MetaActionType::TEXTARRAY      : DoAction(static_cast<MetaTextArrayAction      &>(*pAct)); break;
146
0
            case MetaActionType::STRETCHTEXT    : DoAction(static_cast<MetaStretchTextAction    &>(*pAct)); break;
147
0
            case MetaActionType::BMP            : DoAction(static_cast<MetaBmpAction            &>(*pAct)); break;
148
0
            case MetaActionType::BMPSCALE       : DoAction(static_cast<MetaBmpScaleAction       &>(*pAct)); break;
149
0
            case MetaActionType::BMPEX          : DoAction(static_cast<MetaBmpExAction          &>(*pAct)); break;
150
0
            case MetaActionType::BMPEXSCALE     : DoAction(static_cast<MetaBmpExScaleAction     &>(*pAct)); break;
151
0
            case MetaActionType::LINECOLOR      : DoAction(static_cast<MetaLineColorAction      &>(*pAct)); break;
152
0
            case MetaActionType::FILLCOLOR      : DoAction(static_cast<MetaFillColorAction      &>(*pAct)); break;
153
0
            case MetaActionType::TEXTCOLOR      : DoAction(static_cast<MetaTextColorAction      &>(*pAct)); break;
154
0
            case MetaActionType::TEXTFILLCOLOR  : DoAction(static_cast<MetaTextFillColorAction  &>(*pAct)); break;
155
0
            case MetaActionType::FONT           : DoAction(static_cast<MetaFontAction           &>(*pAct)); break;
156
0
            case MetaActionType::TEXTALIGN      : DoAction(static_cast<MetaTextAlignAction      &>(*pAct)); break;
157
0
            case MetaActionType::MAPMODE        : DoAction(static_cast<MetaMapModeAction        &>(*pAct)); break;
158
0
            case MetaActionType::CLIPREGION     : DoAction(static_cast<MetaClipRegionAction     &>(*pAct)); break;
159
0
            case MetaActionType::MOVECLIPREGION : DoAction(static_cast<MetaMoveClipRegionAction &>(*pAct)); break;
160
0
            case MetaActionType::ISECTRECTCLIPREGION: DoAction(static_cast<MetaISectRectClipRegionAction&>(*pAct)); break;
161
0
            case MetaActionType::ISECTREGIONCLIPREGION: DoAction(static_cast<MetaISectRegionClipRegionAction&>(*pAct)); break;
162
0
            case MetaActionType::RASTEROP       : DoAction(static_cast<MetaRasterOpAction       &>(*pAct)); break;
163
0
            case MetaActionType::PUSH           : DoAction(static_cast<MetaPushAction           &>(*pAct)); break;
164
0
            case MetaActionType::POP            : DoAction(static_cast<MetaPopAction            &>(*pAct)); break;
165
0
            case MetaActionType::HATCH          : DoAction(static_cast<MetaHatchAction          &>(*pAct)); break;
166
167
            // #i125211# MetaCommentAction may change index, thus hand it over
168
0
            case MetaActionType::COMMENT        : DoAction(static_cast<MetaCommentAction&>(*pAct), rMtf, a);
169
0
                break;
170
171
            // missing actions added
172
0
            case MetaActionType::TEXTRECT       : DoAction(static_cast<MetaTextRectAction&>(*pAct)); break;
173
0
            case MetaActionType::BMPSCALEPART   : DoAction(static_cast<MetaBmpScalePartAction&>(*pAct)); break;
174
0
            case MetaActionType::BMPEXSCALEPART : DoAction(static_cast<MetaBmpExScalePartAction&>(*pAct)); break;
175
0
            case MetaActionType::MASK           : DoAction(static_cast<MetaMaskAction&>(*pAct)); break;
176
0
            case MetaActionType::MASKSCALE      : DoAction(static_cast<MetaMaskScaleAction&>(*pAct)); break;
177
0
            case MetaActionType::MASKSCALEPART  : DoAction(static_cast<MetaMaskScalePartAction&>(*pAct)); break;
178
0
            case MetaActionType::GRADIENT       : DoAction(static_cast<MetaGradientAction&>(*pAct)); break;
179
0
            case MetaActionType::WALLPAPER      : OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)"); break;
180
0
            case MetaActionType::Transparent    : DoAction(static_cast<MetaTransparentAction&>(*pAct)); break;
181
0
            case MetaActionType::EPS            : OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)"); break;
182
0
            case MetaActionType::REFPOINT       : DoAction(static_cast<MetaRefPointAction&>(*pAct)); break;
183
0
            case MetaActionType::TEXTLINECOLOR  : DoAction(static_cast<MetaTextLineColorAction&>(*pAct)); break;
184
0
            case MetaActionType::TEXTLINE       : OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)"); break;
185
0
            case MetaActionType::FLOATTRANSPARENT : DoAction(static_cast<MetaFloatTransparentAction&>(*pAct)); break;
186
0
            case MetaActionType::GRADIENTEX     : DoAction(static_cast<MetaGradientExAction&>(*pAct)); break;
187
0
            case MetaActionType::LAYOUTMODE     : DoAction(static_cast<MetaLayoutModeAction&>(*pAct)); break;
188
0
            case MetaActionType::TEXTLANGUAGE   : DoAction(static_cast<MetaTextLanguageAction&>(*pAct)); break;
189
0
            case MetaActionType::OVERLINECOLOR  : DoAction(static_cast<MetaOverlineColorAction&>(*pAct)); break;
190
0
            default: break;
191
0
        }
192
193
0
        if(pProgrInfo && pActionsToReport)
194
0
        {
195
0
            (*pActionsToReport)++;
196
197
0
            if(*pActionsToReport >= 16) // update all 16 actions
198
0
            {
199
0
                if(!pProgrInfo->ReportActions(*pActionsToReport))
200
0
                    break;
201
202
0
                *pActionsToReport = 0;
203
0
            }
204
0
        }
205
0
    }
206
0
}
207
208
size_t ImpSdrGDIMetaFileImport::DoImport(
209
    const GDIMetaFile& rMtf,
210
    SdrObjList& rOL,
211
    size_t nInsPos,
212
    SvdProgressInfo* pProgrInfo)
213
0
{
214
0
    maPrefMapMode = rMtf.GetPrefMapMode();
215
0
    mpVD->SetMapMode(maPrefMapMode);
216
217
    // setup some global scale parameter
218
    // mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
219
0
    mfScaleX = mfScaleY = 1.0;
220
0
    const Size aMtfSize(rMtf.GetPrefSize());
221
222
0
    if(aMtfSize.Width() & aMtfSize.Height() && (!maScaleRect.IsEmpty()))
223
0
    {
224
0
        maOfs = maScaleRect.TopLeft();
225
226
0
        if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
227
0
        {
228
0
            mfScaleX = static_cast<double>( maScaleRect.GetWidth() - 1 ) / static_cast<double>(aMtfSize.Width());
229
0
        }
230
231
0
        if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
232
0
        {
233
0
            mfScaleY = static_cast<double>( maScaleRect.GetHeight() - 1 ) / static_cast<double>(aMtfSize.Height());
234
0
        }
235
0
    }
236
237
0
    mbMov = maOfs.X()!=0 || maOfs.Y()!=0;
238
0
    mbSize = false;
239
0
    maScaleX = 1.0;
240
0
    maScaleY = 1.0;
241
242
0
    if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
243
0
    {
244
0
        maScaleX = double(maScaleRect.GetWidth() - 1) / aMtfSize.Width();
245
0
        mbSize = true;
246
0
    }
247
248
0
    if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
249
0
    {
250
0
        maScaleY = double(maScaleRect.GetHeight() - 1) / aMtfSize.Height();
251
0
        mbSize = true;
252
0
    }
253
254
0
    if(pProgrInfo)
255
0
    {
256
0
        pProgrInfo->SetActionCount(rMtf.GetActionSize());
257
0
    }
258
259
0
    sal_uInt32 nActionsToReport(0);
260
261
    // execute
262
0
    DoLoopActions(rMtf, pProgrInfo, &nActionsToReport);
263
264
0
    if(pProgrInfo)
265
0
    {
266
0
        pProgrInfo->ReportActions(nActionsToReport);
267
0
        nActionsToReport = 0;
268
0
    }
269
270
    // To calculate the progress meter, we use GetActionSize()*3.
271
    // However, maTmpList has a lower entry count limit than GetActionSize(),
272
    // so the actions that were assumed were too much have to be re-added.
273
0
    nActionsToReport = (rMtf.GetActionSize() - maTmpList.size()) * 2;
274
275
    // announce all currently unannounced rescales
276
0
    if(pProgrInfo)
277
0
    {
278
0
        pProgrInfo->ReportRescales(nActionsToReport);
279
0
        pProgrInfo->SetInsertCount(maTmpList.size());
280
0
    }
281
282
0
    nActionsToReport = 0;
283
284
    // insert all objects cached in aTmpList now into rOL from nInsPos
285
0
    nInsPos = std::min(nInsPos, rOL.GetObjCount());
286
287
0
    for(rtl::Reference<SdrObject>& pObj : maTmpList)
288
0
    {
289
0
        rOL.NbcInsertObject(pObj.get(), nInsPos);
290
0
        nInsPos++;
291
292
0
        if(pProgrInfo)
293
0
        {
294
0
            nActionsToReport++;
295
296
0
            if(nActionsToReport >= 32) // update all 32 actions
297
0
            {
298
0
                pProgrInfo->ReportInserts(nActionsToReport);
299
0
                nActionsToReport = 0;
300
0
            }
301
0
        }
302
0
    }
303
304
    // report all remaining inserts for the last time
305
0
    if(pProgrInfo)
306
0
    {
307
0
        pProgrInfo->ReportInserts(nActionsToReport);
308
0
    }
309
310
0
    return maTmpList.size();
311
0
}
312
313
void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr)
314
0
{
315
0
    mbNoLine = false;
316
0
    mbNoFill = false;
317
0
    bool bLine(!bForceTextAttr);
318
0
    bool bFill(!pObj || (pObj->IsClosedObj() && !bForceTextAttr));
319
0
    bool bText(bForceTextAttr || (pObj && pObj->GetOutlinerParaObject()));
320
321
0
    if(bLine)
322
0
    {
323
0
        if(mnLineWidth)
324
0
        {
325
0
            mpLineAttr->Put(XLineWidthItem(mnLineWidth));
326
0
        }
327
0
        else
328
0
        {
329
0
            mpLineAttr->Put(XLineWidthItem(0));
330
0
        }
331
332
0
        maOldLineColor = mpVD->GetLineColor();
333
334
0
        if(mpVD->IsLineColor())
335
0
        {
336
0
            mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_SOLID));
337
0
            mpLineAttr->Put(XLineColorItem(OUString(), mpVD->GetLineColor()));
338
0
        }
339
0
        else
340
0
        {
341
0
            mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_NONE));
342
0
        }
343
344
0
        switch(maLineJoin)
345
0
        {
346
0
            case basegfx::B2DLineJoin::NONE:
347
0
                mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_NONE));
348
0
                break;
349
0
            case basegfx::B2DLineJoin::Bevel:
350
0
                mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_BEVEL));
351
0
                break;
352
0
            case basegfx::B2DLineJoin::Miter:
353
0
                mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_MITER));
354
0
                break;
355
0
            case basegfx::B2DLineJoin::Round:
356
0
                mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_ROUND));
357
0
                break;
358
0
        }
359
360
        // Add LineCap support
361
0
        mpLineAttr->Put(XLineCapItem(maLineCap));
362
363
0
        if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance())
364
0
        {
365
0
            mpLineAttr->Put(XLineDashItem(OUString(), maDash));
366
            // tdf#155211 - change line style to dashed
367
0
            mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_DASH));
368
0
        }
369
0
        else
370
0
        {
371
0
            mpLineAttr->Put(XLineDashItem(OUString(), XDash()));
372
0
        }
373
0
    }
374
0
    else
375
0
    {
376
0
        mbNoLine = true;
377
0
    }
378
379
0
    if(bFill)
380
0
    {
381
0
        if(mpVD->IsFillColor())
382
0
        {
383
0
            mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_SOLID));
384
0
            mpFillAttr->Put(XFillColorItem(OUString(), mpVD->GetFillColor()));
385
0
        }
386
0
        else
387
0
        {
388
0
            mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_NONE));
389
0
        }
390
0
    }
391
0
    else
392
0
    {
393
0
        mbNoFill = true;
394
0
    }
395
396
0
    if(bText && mbFntDirty)
397
0
    {
398
0
        vcl::Font aFnt(mpVD->GetFont());
399
0
        const sal_uInt32 nHeight(basegfx::fround(implMap(aFnt.GetFontSize()).Height() * mfScaleY));
400
401
0
        mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyTypeMaybeAskConfig(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitchMaybeAskConfig(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
402
0
        mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyTypeMaybeAskConfig(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitchMaybeAskConfig(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
403
0
        mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyTypeMaybeAskConfig(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitchMaybeAskConfig(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) );
404
0
        mpTextAttr->Put(SvxPostureItem(aFnt.GetItalicMaybeAskConfig(), EE_CHAR_ITALIC));
405
0
        mpTextAttr->Put(SvxWeightItem(aFnt.GetWeightMaybeAskConfig(), EE_CHAR_WEIGHT));
406
0
        mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
407
0
        mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
408
0
        mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
409
0
        mpTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
410
0
        mpTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
411
0
        mpTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
412
0
        mpTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
413
0
        mpTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
414
415
        // #i118485# Setting this item leads to problems (written #i118498# for this)
416
        // mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
417
418
0
        mpTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
419
0
        mpTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
420
0
        mpTextAttr->Put(SvxColorItem(mpVD->GetTextColor(), EE_CHAR_COLOR));
421
        //... svxfont textitem svditext
422
0
        mbFntDirty = false;
423
0
    }
424
425
0
    if(!pObj)
426
0
        return;
427
428
0
    pObj->SetLayer(mnLayer);
429
430
0
    if(bLine)
431
0
    {
432
0
        pObj->SetMergedItemSet(*mpLineAttr);
433
0
    }
434
435
0
    if(bFill)
436
0
    {
437
0
        pObj->SetMergedItemSet(*mpFillAttr);
438
0
    }
439
440
0
    if(bText)
441
0
    {
442
0
        pObj->SetMergedItemSet(*mpTextAttr);
443
0
        pObj->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
444
0
    }
445
0
}
446
447
void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj1, bool bScale)
448
0
{
449
0
    rtl::Reference<SdrObject> pObj = pObj1;
450
0
    if(bScale && !maScaleRect.IsEmpty())
451
0
    {
452
0
        if(mbSize)
453
0
        {
454
0
            pObj->NbcResize(Point(), maScaleX, maScaleY);
455
0
        }
456
457
0
        if(mbMov)
458
0
        {
459
0
            pObj->NbcMove(Size(maOfs.X(), maOfs.Y()));
460
0
        }
461
0
    }
462
463
0
    if(isClip())
464
0
    {
465
0
        const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
466
0
        const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
467
0
        const SdrLayerID aOldLayer(pObj->GetLayer());
468
0
        const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
469
0
        const SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj.get());
470
0
        const SdrTextObj* pSdrTextObj = DynCastSdrTextObj(pObj.get());
471
472
0
        if(pSdrTextObj && pSdrTextObj->HasText())
473
0
        {
474
            // all text objects are created from ImportText and have no line or fill attributes, so
475
            // it is okay to concentrate on the text itself
476
0
            while(true)
477
0
            {
478
0
                const basegfx::B2DPolyPolygon aTextContour(pSdrTextObj->TakeContour());
479
0
                const basegfx::B2DRange aTextRange(aTextContour.getB2DRange());
480
0
                const basegfx::B2DRange aClipRange(maClip.getB2DRange());
481
482
                // no overlap -> completely outside
483
0
                if(!aClipRange.overlaps(aTextRange))
484
0
                {
485
0
                    pObj.clear();
486
0
                    break;
487
0
                }
488
489
                // when the clip is a rectangle fast check for inside is possible
490
0
                if(basegfx::utils::isRectangle(maClip) && aClipRange.isInside(aTextRange))
491
0
                {
492
                    // completely inside ClipRect
493
0
                    break;
494
0
                }
495
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
0
                rtl::Reference<SdrObject> pConverted = pSdrTextObj->ConvertToPolyObj(true, true);
499
0
                pObj.clear();
500
501
0
                if(pConverted)
502
0
                {
503
                    // recursively add created conversion; per definition this shall not
504
                    // contain further SdrTextObjs. Visit only non-group objects
505
0
                    SdrObjListIter aIter(*pConverted, SdrIterMode::DeepNoGroups);
506
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
0
                    while(aIter.IsMore())
512
0
                    {
513
0
                        SdrObject* pCandidate = aIter.Next();
514
0
                        OSL_ENSURE(pCandidate && dynamic_cast< SdrObjGroup* >(pCandidate) ==  nullptr, "SdrObjListIter with SdrIterMode::DeepNoGroups error (!)");
515
0
                        rtl::Reference<SdrObject> pNewClone(pCandidate->CloneSdrObject(pCandidate->getSdrModelFromSdrObject()));
516
517
0
                        if(pNewClone)
518
0
                        {
519
0
                            InsertObj(pNewClone.get(), false);
520
0
                        }
521
0
                        else
522
0
                        {
523
0
                            OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
524
0
                        }
525
0
                    }
526
0
                }
527
528
0
                break;
529
0
            }
530
0
        }
531
0
        else
532
0
        {
533
0
            Bitmap aBitmap;
534
535
0
            if(pSdrGrafObj)
536
0
            {
537
0
                aBitmap = pSdrGrafObj->GetGraphic().GetBitmap();
538
0
            }
539
540
0
            pObj.clear();
541
542
0
            if(!aOldRange.isEmpty())
543
0
            {
544
                // clip against ClipRegion
545
0
                const basegfx::B2DPolyPolygon aNewPoly(
546
0
                    basegfx::utils::clipPolyPolygonOnPolyPolygon(
547
0
                        aPoly,
548
0
                        maClip,
549
0
                        true,
550
0
                        !aPoly.isClosed()));
551
0
                const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
552
553
0
                if(!aNewRange.isEmpty())
554
0
                {
555
0
                    pObj = new SdrPathObj(
556
0
                        *mpModel,
557
0
                        aNewPoly.isClosed() ? SdrObjKind::Polygon : SdrObjKind::PolyLine,
558
0
                        aNewPoly);
559
560
0
                    pObj->SetLayer(aOldLayer);
561
0
                    pObj->SetMergedItemSet(aOldItemSet);
562
563
0
                    if(!aBitmap.IsEmpty())
564
0
                    {
565
                        // aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
566
0
                        const double fScaleX(aBitmap.GetSizePixel().Width() / (aOldRange.getWidth() ? aOldRange.getWidth() : 1.0));
567
0
                        const double fScaleY(aBitmap.GetSizePixel().Height() / (aOldRange.getHeight() ? aOldRange.getHeight() : 1.0));
568
0
                        basegfx::B2DRange aPixel(aNewRange);
569
0
                        basegfx::B2DHomMatrix aTrans;
570
571
0
                        aTrans.translate(-aOldRange.getMinX(), -aOldRange.getMinY());
572
0
                        aTrans.scale(fScaleX, fScaleY);
573
0
                        aPixel.transform(aTrans);
574
575
0
                        const Size aOrigSizePixel(aBitmap.GetSizePixel());
576
0
                        const Point aClipTopLeft(
577
0
                            basegfx::fround<tools::Long>(floor(std::max(0.0, aPixel.getMinX()))),
578
0
                            basegfx::fround<tools::Long>(floor(std::max(0.0, aPixel.getMinY()))));
579
0
                        const Size aClipSize(
580
0
                            basegfx::fround<tools::Long>(ceil(std::min(static_cast<double>(aOrigSizePixel.Width()), aPixel.getWidth()))),
581
0
                            basegfx::fround<tools::Long>(ceil(std::min(static_cast<double>(aOrigSizePixel.Height()), aPixel.getHeight()))));
582
0
                        const Bitmap aClippedBitmap(
583
0
                            aBitmap,
584
0
                            aClipTopLeft,
585
0
                            aClipSize);
586
587
0
                        pObj->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
588
0
                        pObj->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap)));
589
0
                        pObj->SetMergedItem(XFillBmpTileItem(false));
590
0
                        pObj->SetMergedItem(XFillBmpStretchItem(true));
591
0
                    }
592
0
                }
593
0
            }
594
0
        }
595
0
    }
596
597
0
    if(!pObj)
598
0
        return;
599
600
    // #i111954# check object for visibility
601
    // used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
602
0
    bool bVisible(false);
603
604
0
    if(pObj->HasLineStyle())
605
0
    {
606
0
        bVisible = true;
607
0
    }
608
609
0
    if(!bVisible && pObj->HasFillStyle())
610
0
    {
611
0
        bVisible = true;
612
0
    }
613
614
0
    if(!bVisible)
615
0
    {
616
0
        SdrTextObj* pTextObj = DynCastSdrTextObj(pObj.get());
617
618
0
        if(pTextObj && pTextObj->HasText())
619
0
        {
620
0
            bVisible = true;
621
0
        }
622
0
    }
623
624
0
    if(!bVisible)
625
0
    {
626
0
        SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj.get());
627
628
0
        if(pGrafObj)
629
0
        {
630
            // this may be refined to check if the graphic really is visible. It
631
            // is here to ensure that graphic objects without fill, line and text
632
            // get created
633
0
            bVisible = true;
634
0
        }
635
0
    }
636
637
0
    if(bVisible)
638
0
    {
639
0
        maTmpList.push_back(pObj);
640
641
0
        if(dynamic_cast< SdrPathObj* >(pObj.get()))
642
0
        {
643
0
            const bool bClosed(pObj->IsClosedObj());
644
645
0
            mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
646
0
            mbLastObjWasLine = !bClosed;
647
0
        }
648
0
        else
649
0
        {
650
0
            mbLastObjWasPolyWithoutLine = false;
651
0
            mbLastObjWasLine = false;
652
0
        }
653
0
    }
654
0
}
655
656
void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction const & rAct)
657
0
{
658
    // #i73407# reformulation to use new B2DPolygon classes
659
0
    const basegfx::B2DPoint aStart(rAct.GetStartPoint().X(), rAct.GetStartPoint().Y());
660
0
    const basegfx::B2DPoint aEnd(rAct.GetEndPoint().X(), rAct.GetEndPoint().Y());
661
662
0
    if(aStart.equal(aEnd))
663
0
        return;
664
665
0
    basegfx::B2DPolygon aLine;
666
0
    const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
667
0
                                           basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
668
669
0
    aLine.append(aStart);
670
0
    aLine.append(aEnd);
671
0
    aLine.transform(aTransform);
672
673
0
    const LineInfo& rLineInfo = rAct.GetLineInfo();
674
0
    const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
675
0
    bool bCreateLineObject(true);
676
677
0
    if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aLine))
678
0
    {
679
0
        bCreateLineObject = false;
680
0
    }
681
682
0
    if(!bCreateLineObject)
683
0
        return;
684
685
0
    rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
686
0
        *mpModel,
687
0
        SdrObjKind::Line,
688
0
        basegfx::B2DPolyPolygon(aLine));
689
0
    mnLineWidth = nNewLineWidth;
690
0
    maLineJoin = rLineInfo.GetLineJoin();
691
0
    maLineCap = rLineInfo.GetLineCap();
692
0
    maDash = XDash(css::drawing::DashStyle_RECT,
693
0
        rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
694
0
        rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
695
0
        rLineInfo.GetDistance());
696
0
    SetAttributes(pPath.get());
697
0
    mnLineWidth = 0;
698
0
    maLineJoin = basegfx::B2DLineJoin::NONE;
699
    // tdf#169813 - reset default dash options
700
0
    maDash = XDash(css::drawing::DashStyle_RECT, 0, 0, 0, 0, 0);
701
0
    InsertObj(pPath.get(), false);
702
0
}
703
704
void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction const & rAct)
705
0
{
706
0
    rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
707
0
        *mpModel,
708
0
        rAct.GetRect());
709
0
    SetAttributes(pRect.get());
710
0
    InsertObj(pRect.get());
711
0
}
712
713
void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction const & rAct)
714
0
{
715
0
    rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
716
0
        *mpModel,
717
0
        rAct.GetRect());
718
0
    SetAttributes(pRect.get());
719
0
    tools::Long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
720
0
    if (nRad!=0) {
721
0
        SfxItemSetFixed<SDRATTR_CORNER_RADIUS, SDRATTR_CORNER_RADIUS> aSet(*mpLineAttr->GetPool());
722
0
        aSet.Put(SdrMetricItem(SDRATTR_CORNER_RADIUS, nRad));
723
0
        pRect->SetMergedItemSet(aSet);
724
0
    }
725
0
    InsertObj(pRect.get());
726
0
}
727
728
void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction const & rAct)
729
0
{
730
0
    rtl::Reference<SdrCircObj> pCirc=new SdrCircObj(
731
0
        *mpModel,
732
0
        SdrCircKind::Full,
733
0
        rAct.GetRect());
734
0
    SetAttributes(pCirc.get());
735
0
    InsertObj(pCirc.get());
736
0
}
737
738
void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction const & rAct)
739
0
{
740
0
    Point aCenter(rAct.GetRect().Center());
741
0
    Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
742
0
    Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
743
0
    rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
744
0
        *mpModel,
745
0
        SdrCircKind::Arc,
746
0
        rAct.GetRect(),nStart,nEnd);
747
0
    SetAttributes(pCirc.get());
748
0
    InsertObj(pCirc.get());
749
0
}
750
751
void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction const & rAct)
752
0
{
753
0
    Point aCenter(rAct.GetRect().Center());
754
0
    Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
755
0
    Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
756
0
    rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
757
0
        *mpModel,
758
0
        SdrCircKind::Section,
759
0
        rAct.GetRect(),
760
0
        nStart,
761
0
        nEnd);
762
0
    SetAttributes(pCirc.get());
763
0
    InsertObj(pCirc.get());
764
0
}
765
766
void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction const & rAct)
767
0
{
768
0
    Point aCenter(rAct.GetRect().Center());
769
0
    Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
770
0
    Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
771
0
    rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
772
0
        *mpModel,
773
0
        SdrCircKind::Cut,
774
0
        rAct.GetRect(),
775
0
        nStart,
776
0
        nEnd);
777
0
    SetAttributes(pCirc.get());
778
0
    InsertObj(pCirc.get());
779
0
}
780
781
bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
782
0
{
783
    // #i102706# Do not merge closed polygons
784
0
    if(rSrcPoly.isClosed())
785
0
    {
786
0
        return false;
787
0
    }
788
789
    // #i73407# reformulation to use new B2DPolygon classes
790
0
    if(mbLastObjWasLine && (maOldLineColor == mpVD->GetLineColor()) && rSrcPoly.count())
791
0
    {
792
0
        SdrObject* pTmpObj = !maTmpList.empty() ? maTmpList[maTmpList.size() - 1].get() : nullptr;
793
0
        SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
794
795
0
        if(pLastPoly)
796
0
        {
797
0
            if(1 == pLastPoly->GetPathPoly().count())
798
0
            {
799
0
                bool bOk(false);
800
0
                basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0));
801
802
                // #i102706# Do not merge closed polygons
803
0
                if(aDstPoly.isClosed())
804
0
                {
805
0
                    return false;
806
0
                }
807
808
0
                if(aDstPoly.count())
809
0
                {
810
0
                    const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1);
811
0
                    const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1);
812
813
0
                    if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0))
814
0
                    {
815
0
                        aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
816
0
                        bOk = true;
817
0
                    }
818
0
                    else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
819
0
                    {
820
0
                        basegfx::B2DPolygon aNew(rSrcPoly);
821
0
                        aNew.append(aDstPoly, 1, aDstPoly.count() - 1);
822
0
                        aDstPoly = std::move(aNew);
823
0
                        bOk = true;
824
0
                    }
825
0
                    else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(0))
826
0
                    {
827
0
                        aDstPoly.flip();
828
0
                        aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
829
0
                        bOk = true;
830
0
                    }
831
0
                    else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
832
0
                    {
833
0
                        basegfx::B2DPolygon aNew(rSrcPoly);
834
0
                        aNew.flip();
835
0
                        aDstPoly.append(aNew, 1, aNew.count() - 1);
836
0
                        bOk = true;
837
0
                    }
838
0
                }
839
840
0
                if(bOk)
841
0
                {
842
0
                    pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
843
0
                }
844
845
0
                return bOk;
846
0
            }
847
0
        }
848
0
    }
849
850
0
    return false;
851
0
}
852
853
bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
854
0
{
855
    // #i73407# reformulation to use new B2DPolygon classes
856
0
    if(mbLastObjWasPolyWithoutLine)
857
0
    {
858
0
        SdrObject* pTmpObj = !maTmpList.empty() ? maTmpList[maTmpList.size() - 1].get() : nullptr;
859
0
        SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
860
861
0
        if(pLastPoly)
862
0
        {
863
0
            if(pLastPoly->GetPathPoly() == rPolyPolygon)
864
0
            {
865
0
                SetAttributes(nullptr);
866
867
0
                if(!mbNoLine && mbNoFill)
868
0
                {
869
0
                    pLastPoly->SetMergedItemSet(*mpLineAttr);
870
871
0
                    return true;
872
0
                }
873
0
            }
874
0
        }
875
0
    }
876
877
0
    return false;
878
0
}
879
880
void ImpSdrGDIMetaFileImport::checkClip()
881
0
{
882
0
    if(!mpVD->IsClipRegion())
883
0
        return;
884
885
0
    maClip = mpVD->GetClipRegion().GetAsB2DPolyPolygon();
886
887
0
    if(isClip())
888
0
    {
889
0
        const basegfx::B2DHomMatrix aTransform(
890
0
            implMapMatrix() *
891
0
            basegfx::utils::createScaleTranslateB2DHomMatrix(
892
0
                mfScaleX,
893
0
                mfScaleY,
894
0
                maOfs.X(),
895
0
                maOfs.Y()));
896
897
0
        maClip.transform(aTransform);
898
0
    }
899
0
}
900
901
bool ImpSdrGDIMetaFileImport::isClip() const
902
0
{
903
0
    return !maClip.getB2DRange().isEmpty();
904
0
}
905
906
void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction const & rAct )
907
0
{
908
    // #i73407# reformulation to use new B2DPolygon classes
909
0
    basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
910
911
0
    if(aSource.count())
912
0
    {
913
0
        const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
914
0
                                               basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
915
0
        aSource.transform(aTransform);
916
0
    }
917
918
0
    const LineInfo& rLineInfo = rAct.GetLineInfo();
919
0
    const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
920
0
    bool bCreateLineObject(true);
921
922
0
    if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aSource))
923
0
    {
924
0
        bCreateLineObject = false;
925
0
    }
926
0
    else if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
927
0
    {
928
0
        bCreateLineObject = false;
929
0
    }
930
931
0
    if(!bCreateLineObject)
932
0
        return;
933
934
0
    rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
935
0
        *mpModel,
936
0
        aSource.isClosed() ? SdrObjKind::Polygon : SdrObjKind::PolyLine,
937
0
        basegfx::B2DPolyPolygon(aSource));
938
0
    mnLineWidth = nNewLineWidth;
939
0
    maLineJoin = rLineInfo.GetLineJoin();
940
0
    maLineCap = rLineInfo.GetLineCap();
941
0
    maDash = XDash(css::drawing::DashStyle_RECT,
942
0
        rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
943
0
        rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
944
0
        rLineInfo.GetDistance());
945
0
    SetAttributes(pPath.get());
946
0
    mnLineWidth = 0;
947
0
    maLineJoin = basegfx::B2DLineJoin::NONE;
948
    // tdf#169813 - reset default dash options
949
0
    maDash = XDash(css::drawing::DashStyle_RECT, 0, 0, 0, 0, 0);
950
0
    InsertObj(pPath.get(), false);
951
0
}
952
953
void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction const & rAct )
954
0
{
955
    // #i73407# reformulation to use new B2DPolygon classes
956
0
    basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
957
958
0
    if(!aSource.count())
959
0
        return;
960
961
0
    const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
962
0
                                           basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
963
0
    aSource.transform(aTransform);
964
965
0
    if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
966
0
    {
967
        // #i73407# make sure polygon is closed, it's a filled primitive
968
0
        aSource.setClosed(true);
969
0
        rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
970
0
            *mpModel,
971
0
            SdrObjKind::Polygon,
972
0
            basegfx::B2DPolyPolygon(aSource));
973
0
        SetAttributes(pPath.get());
974
0
        InsertObj(pPath.get(), false);
975
0
    }
976
0
}
977
978
void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction const & rAct)
979
0
{
980
    // #i73407# reformulation to use new B2DPolygon classes
981
0
    basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
982
983
0
    if(!aSource.count())
984
0
        return;
985
986
0
    const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
987
0
                                           basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
988
0
    aSource.transform(aTransform);
989
990
0
    if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
991
0
    {
992
        // #i73407# make sure polygon is closed, it's a filled primitive
993
0
        aSource.setClosed(true);
994
0
        rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
995
0
            *mpModel,
996
0
            SdrObjKind::Polygon,
997
0
            std::move(aSource));
998
0
        SetAttributes(pPath.get());
999
0
        InsertObj(pPath.get(), false);
1000
0
    }
1001
0
}
1002
1003
Size ImpSdrGDIMetaFileImport::implMap(const Size& rSz) const
1004
0
{
1005
0
    return OutputDevice::LogicToLogic(rSz, mpVD->GetMapMode(), maPrefMapMode);
1006
0
}
1007
1008
Point ImpSdrGDIMetaFileImport::implMap(const Point& rPt) const
1009
0
{
1010
0
    return OutputDevice::LogicToLogic(rPt, mpVD->GetMapMode(), maPrefMapMode);
1011
0
}
1012
1013
basegfx::B2DHomMatrix ImpSdrGDIMetaFileImport::implMapMatrix() const
1014
0
{
1015
0
    return OutputDevice::LogicToLogic(mpVD->GetMapMode(), maPrefMapMode);
1016
0
}
1017
1018
void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const OUString& rStr, const MetaAction& rAct )
1019
0
{
1020
    // calc text box size, add 5% to make it fit safely
1021
1022
0
    FontMetric aFontMetric( mpVD->GetFontMetric() );
1023
0
    vcl::Font aFnt( mpVD->GetFont() );
1024
0
    TextAlign eAlg( aFnt.GetAlignment() );
1025
1026
0
    Size aTextSizeMapped(implMap(Size(mpVD->GetTextWidth(rStr), mpVD->GetTextHeight())));
1027
1028
0
    sal_Int32 nTextWidth = static_cast<sal_Int32>(aTextSizeMapped.Width() * mfScaleX);
1029
0
    sal_Int32 nTextHeight = static_cast<sal_Int32>(aTextSizeMapped.Height() * mfScaleY);
1030
1031
0
    Point aPosMapped(implMap(rPos));
1032
1033
0
    Point aPos(basegfx::fround<tools::Long>(aPosMapped.X() * mfScaleX + maOfs.X()),
1034
0
               basegfx::fround<tools::Long>(aPosMapped.Y() * mfScaleY + maOfs.Y()));
1035
0
    Size aSize( nTextWidth, nTextHeight );
1036
1037
0
    if ( eAlg == ALIGN_BASELINE )
1038
0
    {
1039
0
        auto nAscent = implMap(Size(0, aFontMetric.GetAscent())).Height();
1040
0
        aPos.AdjustY(basegfx::fround<tools::Long>(nAscent * -mfScaleY));
1041
0
    }
1042
0
    else if ( eAlg == ALIGN_BOTTOM )
1043
0
        aPos.AdjustY( -nTextHeight );
1044
1045
0
    tools::Rectangle aTextRect( aPos, aSize );
1046
0
    rtl::Reference<SdrRectObj> pText = new SdrRectObj(*mpModel, aTextRect, SdrObjKind::Text);
1047
1048
0
    pText->SetMergedItem ( makeSdrTextUpperDistItem (0));
1049
0
    pText->SetMergedItem ( makeSdrTextLowerDistItem (0));
1050
0
    pText->SetMergedItem ( makeSdrTextRightDistItem (0));
1051
0
    pText->SetMergedItem ( makeSdrTextLeftDistItem (0));
1052
1053
0
    if ( aFnt.GetAverageFontWidth() || ( rAct.GetType() == MetaActionType::STRETCHTEXT ) )
1054
0
    {
1055
0
        pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
1056
0
        pText->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
1057
        // don't let the margins eat the space needed for the text
1058
0
        pText->SetMergedItem( SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_ALLLINES) );
1059
0
    }
1060
0
    else
1061
0
    {
1062
0
        pText->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
1063
0
    }
1064
1065
0
    pText->SetLayer(mnLayer);
1066
0
    pText->NbcSetText( rStr );
1067
0
    SetAttributes( pText.get(), true );
1068
0
    pText->SetSnapRect( aTextRect );
1069
1070
0
    if (!aFnt.IsTransparent())
1071
0
    {
1072
0
        SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aAttr(*mpFillAttr->GetPool());
1073
0
        aAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID));
1074
0
        aAttr.Put(XFillColorItem(OUString(), aFnt.GetFillColor()));
1075
0
        pText->SetMergedItemSet(aAttr);
1076
0
    }
1077
0
    Degree100 nAngle = to<Degree100>(aFnt.GetOrientation());
1078
0
    if ( nAngle )
1079
0
        pText->SdrAttrObj::NbcRotate(aPos,nAngle);
1080
0
    InsertObj( pText.get(), false );
1081
0
}
1082
1083
void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction const & rAct)
1084
0
{
1085
0
    OUString aStr(rAct.GetText());
1086
0
    aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1087
0
    ImportText( rAct.GetPoint(), aStr, rAct );
1088
0
}
1089
1090
void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction const & rAct)
1091
0
{
1092
0
    OUString aStr(rAct.GetText());
1093
0
    aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1094
0
    ImportText( rAct.GetPoint(), aStr, rAct );
1095
0
}
1096
1097
void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction const & rAct)
1098
0
{
1099
0
    OUString aStr(rAct.GetText());
1100
0
    aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
1101
0
    ImportText( rAct.GetPoint(), aStr, rAct );
1102
0
}
1103
1104
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction const & rAct)
1105
0
{
1106
0
    tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
1107
0
    aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1108
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1109
0
        *mpModel,
1110
0
        Graphic(rAct.GetBitmap()),
1111
0
        aRect);
1112
1113
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1114
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1115
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1116
0
    InsertObj(pGraf.get());
1117
0
}
1118
1119
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction const & rAct)
1120
0
{
1121
0
    tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1122
0
    aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1123
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1124
0
        *mpModel,
1125
0
        Graphic(rAct.GetBitmap()),
1126
0
        aRect);
1127
1128
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1129
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1130
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1131
0
    InsertObj(pGraf.get());
1132
0
}
1133
1134
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction const & rAct)
1135
0
{
1136
0
    tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
1137
0
    aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1138
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1139
0
        *mpModel,
1140
0
        rAct.GetBitmap(),
1141
0
        aRect);
1142
1143
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1144
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1145
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1146
0
    InsertObj(pGraf.get());
1147
0
}
1148
1149
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction const & rAct)
1150
0
{
1151
0
    tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1152
0
    aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1153
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1154
0
        *mpModel,
1155
0
        rAct.GetBitmap(),
1156
0
        aRect);
1157
1158
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1159
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1160
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1161
0
    InsertObj(pGraf.get());
1162
0
}
1163
1164
1165
void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction const & rAct )
1166
0
{
1167
    // #i73407# reformulation to use new B2DPolygon classes
1168
0
    basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1169
1170
0
    if(!aSource.count())
1171
0
        return;
1172
1173
0
    const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
1174
0
                                           basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1175
0
    aSource.transform(aTransform);
1176
1177
0
    if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(aSource))
1178
0
        return;
1179
1180
0
    const Hatch& rHatch = rAct.GetHatch();
1181
0
    rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
1182
0
        *mpModel,
1183
0
        SdrObjKind::Polygon,
1184
0
        std::move(aSource));
1185
    // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1186
0
    SfxItemSet aHatchAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1187
0
    css::drawing::HatchStyle eStyle;
1188
1189
0
    switch(rHatch.GetStyle())
1190
0
    {
1191
0
        case HatchStyle::Triple :
1192
0
        {
1193
0
            eStyle = css::drawing::HatchStyle_TRIPLE;
1194
0
            break;
1195
0
        }
1196
1197
0
        case HatchStyle::Double :
1198
0
        {
1199
0
            eStyle = css::drawing::HatchStyle_DOUBLE;
1200
0
            break;
1201
0
        }
1202
1203
0
        default:
1204
0
        {
1205
0
            eStyle = css::drawing::HatchStyle_SINGLE;
1206
0
            break;
1207
0
        }
1208
0
    }
1209
1210
0
    SetAttributes(pPath.get());
1211
0
    aHatchAttr.Put(XFillStyleItem(drawing::FillStyle_HATCH));
1212
0
    aHatchAttr.Put(XFillHatchItem(XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
1213
0
    pPath->SetMergedItemSet(aHatchAttr);
1214
1215
0
    InsertObj(pPath.get(), false);
1216
0
}
1217
1218
1219
void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
1220
0
{
1221
0
    rAct.Execute(mpVD);
1222
0
}
1223
1224
void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
1225
0
{
1226
0
    rAct.Execute(mpVD);
1227
0
    mbLastObjWasPolyWithoutLine = false;
1228
0
    mbLastObjWasLine = false;
1229
0
}
1230
1231
void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction const & rAct, GDIMetaFile const & rMtf, size_t& a) // GDIMetaFile* pMtf )
1232
0
{
1233
0
    bool aSkipComment = false;
1234
1235
0
    if (a < rMtf.GetActionSize() && rAct.GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
1236
0
    {
1237
        // #i125211# Check if next action is a MetaGradientExAction
1238
0
        MetaGradientExAction* pAct = dynamic_cast< MetaGradientExAction* >(rMtf.GetAction(a + 1));
1239
1240
0
        if( pAct && pAct->GetType() == MetaActionType::GRADIENTEX )
1241
0
        {
1242
            // #i73407# reformulation to use new B2DPolygon classes
1243
0
            basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
1244
1245
0
            if(aSource.count())
1246
0
            {
1247
0
                if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
1248
0
                {
1249
0
                    const Gradient& rGrad = pAct->GetGradient();
1250
0
                    rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
1251
0
                        *mpModel,
1252
0
                        SdrObjKind::Polygon,
1253
0
                        std::move(aSource));
1254
                    // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1255
0
                    SfxItemSet aGradAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1256
0
                    basegfx::BGradient aBGradient(
1257
0
                        basegfx::BColorStops(
1258
0
                            rGrad.GetStartColor().getBColor(),
1259
0
                            rGrad.GetEndColor().getBColor()));
1260
1261
0
                    aBGradient.SetGradientStyle(rGrad.GetStyle());
1262
0
                    aBGradient.SetAngle(rGrad.GetAngle());
1263
0
                    aBGradient.SetBorder(rGrad.GetBorder());
1264
0
                    aBGradient.SetXOffset(rGrad.GetOfsX());
1265
0
                    aBGradient.SetYOffset(rGrad.GetOfsY());
1266
0
                    aBGradient.SetStartIntens(rGrad.GetStartIntensity());
1267
0
                    aBGradient.SetEndIntens(rGrad.GetEndIntensity());
1268
0
                    aBGradient.SetSteps(rGrad.GetSteps());
1269
1270
                    // no need to use SetAttributes(..) here since line and fill style
1271
                    // need to be set individually
1272
                    // SetAttributes(pPath);
1273
1274
                    // switch line off; if there was one there will be a
1275
                    // MetaActionType::POLYLINE following creating another object
1276
0
                    aGradAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
1277
1278
                    // add detected gradient fillstyle
1279
0
                    aGradAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT));
1280
0
                    aGradAttr.Put(XFillGradientItem(aBGradient));
1281
1282
0
                    pPath->SetMergedItemSet(aGradAttr);
1283
1284
0
                    InsertObj(pPath.get());
1285
0
                }
1286
0
            }
1287
1288
0
            aSkipComment = true;
1289
0
        }
1290
0
    }
1291
1292
0
    if(aSkipComment)
1293
0
    {
1294
        // #i125211# forward until closing MetaCommentAction
1295
0
        MetaAction* pSkipAct = rMtf.GetAction(++a);
1296
1297
0
        while( pSkipAct
1298
0
            && ((pSkipAct->GetType() != MetaActionType::COMMENT )
1299
0
                || !(static_cast<MetaCommentAction*>(pSkipAct)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END"))))
1300
0
        {
1301
0
            pSkipAct = rMtf.GetAction(++a);
1302
0
        }
1303
0
    }
1304
0
}
1305
1306
void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction const & rAct)
1307
0
{
1308
0
    GDIMetaFile aTemp;
1309
1310
0
    mpVD->AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
1311
0
    DoLoopActions(aTemp, nullptr, nullptr);
1312
0
}
1313
1314
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction const & rAct)
1315
0
{
1316
0
    tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1317
0
    Bitmap aBitmap(rAct.GetBitmap());
1318
1319
0
    aRect.AdjustRight( 1 );
1320
0
    aRect.AdjustBottom( 1 );
1321
0
    aBitmap.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1322
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1323
0
        *mpModel,
1324
0
        aBitmap,
1325
0
        aRect);
1326
1327
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1328
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1329
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1330
0
    InsertObj(pGraf.get());
1331
0
}
1332
1333
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction const & rAct)
1334
0
{
1335
0
    tools::Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
1336
0
    Bitmap aBitmap(rAct.GetBitmap());
1337
1338
0
    aRect.AdjustRight( 1 );
1339
0
    aRect.AdjustBottom( 1 );
1340
0
    aBitmap.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1341
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1342
0
        *mpModel,
1343
0
        aBitmap,
1344
0
        aRect);
1345
1346
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1347
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1348
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1349
0
    InsertObj(pGraf.get());
1350
0
}
1351
1352
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction const & rAct)
1353
0
{
1354
0
    tools::Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
1355
0
    Bitmap aBitmap(rAct.GetBitmap(), rAct.GetColor());
1356
1357
0
    aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1358
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1359
0
        *mpModel,
1360
0
        aBitmap,
1361
0
        aRect);
1362
1363
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1364
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1365
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1366
0
    InsertObj(pGraf.get());
1367
0
}
1368
1369
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction const & rAct)
1370
0
{
1371
0
    tools::Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
1372
0
    Bitmap aBitmap(rAct.GetBitmap(), rAct.GetColor());
1373
1374
0
    aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1375
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1376
0
        *mpModel,
1377
0
        aBitmap,
1378
0
        aRect);
1379
1380
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1381
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1382
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1383
0
    InsertObj(pGraf.get());
1384
0
}
1385
1386
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction const & rAct)
1387
0
{
1388
0
    tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
1389
0
    Bitmap aBitmap(rAct.GetBitmap(), rAct.GetColor());
1390
1391
0
    aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
1392
0
    aBitmap.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
1393
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1394
0
        *mpModel,
1395
0
        aBitmap,
1396
0
        aRect);
1397
1398
    // This action is not creating line and fill, set directly, do not use SetAttributes(..)
1399
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1400
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1401
0
    InsertObj(pGraf.get());
1402
0
}
1403
1404
void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction const & rAct)
1405
0
{
1406
0
    basegfx::B2DRange aRange = vcl::unotools::b2DRectangleFromRectangle(rAct.GetRect());
1407
1408
0
    if(aRange.isEmpty())
1409
0
        return;
1410
1411
0
    const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
1412
0
                                           basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1413
0
    aRange.transform(aTransform);
1414
0
    const Gradient& rGradient = rAct.GetGradient();
1415
0
    rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
1416
0
        *mpModel,
1417
0
        tools::Rectangle(
1418
0
            floor(aRange.getMinX()),
1419
0
            floor(aRange.getMinY()),
1420
0
            ceil(aRange.getMaxX()),
1421
0
            ceil(aRange.getMaxY())),
1422
0
        SdrObjKind::Text);
1423
    // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1424
0
    SfxItemSet aGradientAttr(mpModel->GetItemPool(), pRect->GetMergedItemSet().GetRanges());
1425
0
    const XFillGradientItem aXFillGradientItem(
1426
0
        basegfx::BGradient(
1427
0
            basegfx::BColorStops(
1428
0
                rGradient.GetStartColor().getBColor(),
1429
0
                rGradient.GetEndColor().getBColor()),
1430
0
            rGradient.GetStyle(),
1431
0
            rGradient.GetAngle(),
1432
0
            rGradient.GetOfsX(),
1433
0
            rGradient.GetOfsY(),
1434
0
            rGradient.GetBorder(),
1435
0
            rGradient.GetStartIntensity(),
1436
0
            rGradient.GetEndIntensity(),
1437
0
            rGradient.GetSteps()));
1438
1439
0
    SetAttributes(pRect.get());
1440
0
    aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1441
0
    aGradientAttr.Put(aXFillGradientItem);
1442
0
    pRect->SetMergedItemSet(aGradientAttr);
1443
1444
0
    InsertObj(pRect.get(), false);
1445
0
}
1446
1447
void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction const & rAct)
1448
0
{
1449
0
    basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1450
1451
0
    if(!aSource.count())
1452
0
        return;
1453
1454
0
    const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
1455
0
                                           basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1456
0
    aSource.transform(aTransform);
1457
0
    aSource.setClosed(true);
1458
1459
0
    rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
1460
0
        *mpModel,
1461
0
        SdrObjKind::Polygon,
1462
0
        std::move(aSource));
1463
0
    SetAttributes(pPath.get());
1464
0
    pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
1465
0
    InsertObj(pPath.get(), false);
1466
0
}
1467
1468
void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction const & rAct)
1469
0
{
1470
0
    basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
1471
1472
0
    if(!aSource.count())
1473
0
        return;
1474
1475
0
    const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
1476
0
                                           basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
1477
0
    aSource.transform(aTransform);
1478
1479
0
    if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(aSource))
1480
0
        return;
1481
1482
0
    const Gradient& rGradient = rAct.GetGradient();
1483
0
    rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
1484
0
        *mpModel,
1485
0
        SdrObjKind::Polygon,
1486
0
        std::move(aSource));
1487
    // #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
1488
0
    SfxItemSet aGradientAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
1489
0
    const XFillGradientItem aXFillGradientItem(
1490
0
        basegfx::BGradient(
1491
0
            basegfx::BColorStops(
1492
0
                rGradient.GetStartColor().getBColor(),
1493
0
                rGradient.GetEndColor().getBColor()),
1494
0
            rGradient.GetStyle(),
1495
0
            rGradient.GetAngle(),
1496
0
            rGradient.GetOfsX(),
1497
0
            rGradient.GetOfsY(),
1498
0
            rGradient.GetBorder(),
1499
0
            rGradient.GetStartIntensity(),
1500
0
            rGradient.GetEndIntensity(),
1501
0
            rGradient.GetSteps()));
1502
1503
0
    SetAttributes(pPath.get());
1504
0
    aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
1505
0
    aGradientAttr.Put(aXFillGradientItem);
1506
0
    pPath->SetMergedItemSet(aGradientAttr);
1507
1508
0
    InsertObj(pPath.get(), false);
1509
0
}
1510
1511
void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction const & rAct)
1512
0
{
1513
0
    const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
1514
1515
0
    if(!rMtf.GetActionSize())
1516
0
        return;
1517
1518
0
    const tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
1519
1520
    // convert metafile sub-content to Bitmap
1521
0
    Bitmap aBitmap(
1522
0
        convertMetafileToBitmap(
1523
0
            rMtf,
1524
0
            vcl::unotools::b2DRectangleFromRectangle(aRect),
1525
0
            125000));
1526
1527
    // handle colors
1528
0
    const Gradient& rGradient = rAct.GetGradient();
1529
0
    basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
1530
0
    basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
1531
1532
0
    if(100 != rGradient.GetStartIntensity())
1533
0
    {
1534
0
        aStart *= static_cast<double>(rGradient.GetStartIntensity()) / 100.0;
1535
0
    }
1536
1537
0
    if(100 != rGradient.GetEndIntensity())
1538
0
    {
1539
0
        aEnd *= static_cast<double>(rGradient.GetEndIntensity()) / 100.0;
1540
0
    }
1541
1542
0
    const bool bEqualColors(aStart == aEnd);
1543
0
    const bool bNoSteps(1 == rGradient.GetSteps());
1544
0
    bool bCreateObject(true);
1545
0
    bool bHasNewMask(false);
1546
0
    AlphaMask aNewMask;
1547
0
    double fTransparence(0.0);
1548
0
    bool bFixedTransparence(false);
1549
1550
0
    if(bEqualColors || bNoSteps)
1551
0
    {
1552
        // single transparence
1553
0
        const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
1554
0
        fTransparence = aMedium.luminance();
1555
1556
0
        if(fTransparence <= 0.0)
1557
0
        {
1558
            // no transparence needed, all done
1559
0
        }
1560
0
        else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
1561
0
        {
1562
            // all transparent, no object
1563
0
            bCreateObject = false;
1564
0
        }
1565
0
        else
1566
0
        {
1567
            // 0.0 < transparence < 1.0, apply fixed transparence
1568
0
            bFixedTransparence = true;
1569
0
        }
1570
0
    }
1571
0
    else
1572
0
    {
1573
        // gradient transparence
1574
0
        ScopedVclPtrInstance< VirtualDevice > pVDev;
1575
1576
0
        pVDev->SetOutputSizePixel(aBitmap.GetSizePixel());
1577
0
        pVDev->DrawGradient(tools::Rectangle(Point(0, 0), pVDev->GetOutputSizePixel()), rGradient);
1578
1579
0
        aNewMask = AlphaMask(pVDev->GetBitmap(Point(0, 0), pVDev->GetOutputSizePixel()));
1580
0
        aNewMask.Invert(); // convert transparency to alpha
1581
0
        bHasNewMask = true;
1582
0
    }
1583
1584
0
    if(!bCreateObject)
1585
0
        return;
1586
1587
0
    if(bHasNewMask || bFixedTransparence)
1588
0
    {
1589
0
        if(!aBitmap.HasAlpha())
1590
0
        {
1591
            // no transparence yet, apply new one
1592
0
            if(bFixedTransparence)
1593
0
            {
1594
0
                sal_uInt8 nTransparence(basegfx::fround(fTransparence * 255.0));
1595
1596
0
                aNewMask = AlphaMask(aBitmap.GetSizePixel(), &nTransparence);
1597
0
            }
1598
1599
0
            aBitmap = Bitmap(aBitmap.CreateColorBitmap(), aNewMask);
1600
0
        }
1601
0
        else
1602
0
        {
1603
0
            vcl::bitmap::DrawAlphaBitmapAndAlphaGradient(aBitmap, bFixedTransparence, fTransparence, aNewMask);
1604
0
        }
1605
0
    }
1606
1607
    // create and add object
1608
0
    rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
1609
0
        *mpModel,
1610
0
        aBitmap,
1611
0
        aRect);
1612
1613
    // for MetaFloatTransparentAction, do not use SetAttributes(...)
1614
    // since these metafile content is not used to draw line/fill
1615
    // dependent of these setting at the device content
1616
0
    pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
1617
0
    pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
1618
0
    InsertObj(pGraf.get());
1619
0
}
1620
1621
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */