1617 lines
58 KiB
C++
1617 lines
58 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include "svdfmtf.hxx"
|
|
#include <math.h>
|
|
#include <editeng/eeitem.hxx>
|
|
#include <editeng/fhgtitem.hxx>
|
|
#include <editeng/wghtitem.hxx>
|
|
#include <editeng/postitem.hxx>
|
|
#include <editeng/udlnitem.hxx>
|
|
#include <editeng/crossedoutitem.hxx>
|
|
#include <editeng/shdditem.hxx>
|
|
#include <svx/xlineit0.hxx>
|
|
#include <svx/xlnclit.hxx>
|
|
#include <svx/xlncapit.hxx>
|
|
#include <svx/xlnwtit.hxx>
|
|
#include <svx/xfillit0.hxx>
|
|
#include <svx/xflclit.hxx>
|
|
#include <svx/xflgrit.hxx>
|
|
#include <editeng/fontitem.hxx>
|
|
#include <editeng/wrlmitem.hxx>
|
|
#include <editeng/contouritem.hxx>
|
|
#include <editeng/colritem.hxx>
|
|
#include <vcl/canvastools.hxx>
|
|
#include <vcl/metric.hxx>
|
|
#include <editeng/charscaleitem.hxx>
|
|
#include <svx/xflhtit.hxx>
|
|
#include <svx/sdmetitm.hxx>
|
|
#include <svx/sdtagitm.hxx>
|
|
#include <svx/sdtaitm.hxx>
|
|
#include <svx/sdtditm.hxx>
|
|
#include <svx/sdtfsitm.hxx>
|
|
#include <svx/svdmodel.hxx>
|
|
#include <svx/svdpage.hxx>
|
|
#include <svx/svdobj.hxx>
|
|
#include <svx/svdotext.hxx>
|
|
#include <svx/svdorect.hxx>
|
|
#include <svx/svdocirc.hxx>
|
|
#include <svx/svdograf.hxx>
|
|
#include <svx/svdopath.hxx>
|
|
#include <svx/svdetc.hxx>
|
|
#include <svl/itemset.hxx>
|
|
#include <basegfx/polygon/b2dpolygon.hxx>
|
|
#include <tools/helpers.hxx>
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
|
#include <svx/xlinjoit.hxx>
|
|
#include <svx/xlndsit.hxx>
|
|
#include <basegfx/polygon/b2dpolygonclipper.hxx>
|
|
#include <svx/xbtmpit.hxx>
|
|
#include <svx/xfltrit.hxx>
|
|
#include <svx/xflbmtit.hxx>
|
|
#include <svx/xflbstit.hxx>
|
|
#include <svx/svdpntv.hxx>
|
|
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
|
#include <svx/svditer.hxx>
|
|
#include <svx/svdogrp.hxx>
|
|
#include <vcl/BitmapTools.hxx>
|
|
#include <osl/diagnose.h>
|
|
|
|
using namespace com::sun::star;
|
|
|
|
ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
|
|
SdrModel& rModel,
|
|
SdrLayerID nLay,
|
|
const tools::Rectangle& rRect)
|
|
: mpVD(VclPtr<VirtualDevice>::Create()),
|
|
maScaleRect(rRect),
|
|
mpModel(&rModel),
|
|
mnLayer(nLay),
|
|
mnLineWidth(0),
|
|
maLineJoin(basegfx::B2DLineJoin::NONE),
|
|
maLineCap(css::drawing::LineCap_BUTT),
|
|
maDash(css::drawing::DashStyle_RECT, 0, 0, 0, 0, 0),
|
|
mbMov(false),
|
|
mbSize(false),
|
|
maOfs(0, 0),
|
|
mfScaleX(1.0),
|
|
mfScaleY(1.0),
|
|
maScaleX(1.0),
|
|
maScaleY(1.0),
|
|
mbFntDirty(true),
|
|
mbLastObjWasPolyWithoutLine(false),
|
|
mbNoLine(false),
|
|
mbNoFill(false),
|
|
mbLastObjWasLine(false)
|
|
{
|
|
mpVD->EnableOutput(false);
|
|
mpVD->SetLineColor();
|
|
mpVD->SetFillColor();
|
|
maOldLineColor.SetRed( mpVD->GetLineColor().GetRed() + 1 );
|
|
mpLineAttr = std::make_unique<SfxItemSetFixed<XATTR_LINE_FIRST, XATTR_LINE_LAST>>(rModel.GetItemPool());
|
|
mpFillAttr = std::make_unique<SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST>>(rModel.GetItemPool());
|
|
mpTextAttr = std::make_unique<SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END>>(rModel.GetItemPool());
|
|
checkClip();
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile const & rMtf, SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
|
|
{
|
|
const size_t nCount = rMtf.GetActionSize();
|
|
|
|
for(size_t a = 0; a < nCount; a++)
|
|
{
|
|
MetaAction* pAct = rMtf.GetAction(a);
|
|
|
|
if(!pAct)
|
|
{
|
|
OSL_ENSURE(false, "OOps, no action at valid position (!)");
|
|
pAct = rMtf.GetAction(0);
|
|
}
|
|
|
|
switch (pAct->GetType())
|
|
{
|
|
case MetaActionType::PIXEL : break;
|
|
case MetaActionType::POINT : break;
|
|
case MetaActionType::LINE : DoAction(static_cast<MetaLineAction &>(*pAct)); break;
|
|
case MetaActionType::RECT : DoAction(static_cast<MetaRectAction &>(*pAct)); break;
|
|
case MetaActionType::ROUNDRECT : DoAction(static_cast<MetaRoundRectAction &>(*pAct)); break;
|
|
case MetaActionType::ELLIPSE : DoAction(static_cast<MetaEllipseAction &>(*pAct)); break;
|
|
case MetaActionType::ARC : DoAction(static_cast<MetaArcAction &>(*pAct)); break;
|
|
case MetaActionType::PIE : DoAction(static_cast<MetaPieAction &>(*pAct)); break;
|
|
case MetaActionType::CHORD : DoAction(static_cast<MetaChordAction &>(*pAct)); break;
|
|
case MetaActionType::POLYLINE : DoAction(static_cast<MetaPolyLineAction &>(*pAct)); break;
|
|
case MetaActionType::POLYGON : DoAction(static_cast<MetaPolygonAction &>(*pAct)); break;
|
|
case MetaActionType::POLYPOLYGON : DoAction(static_cast<MetaPolyPolygonAction &>(*pAct)); break;
|
|
case MetaActionType::TEXT : DoAction(static_cast<MetaTextAction &>(*pAct)); break;
|
|
case MetaActionType::TEXTARRAY : DoAction(static_cast<MetaTextArrayAction &>(*pAct)); break;
|
|
case MetaActionType::STRETCHTEXT : DoAction(static_cast<MetaStretchTextAction &>(*pAct)); break;
|
|
case MetaActionType::BMP : DoAction(static_cast<MetaBmpAction &>(*pAct)); break;
|
|
case MetaActionType::BMPSCALE : DoAction(static_cast<MetaBmpScaleAction &>(*pAct)); break;
|
|
case MetaActionType::BMPEX : DoAction(static_cast<MetaBmpExAction &>(*pAct)); break;
|
|
case MetaActionType::BMPEXSCALE : DoAction(static_cast<MetaBmpExScaleAction &>(*pAct)); break;
|
|
case MetaActionType::LINECOLOR : DoAction(static_cast<MetaLineColorAction &>(*pAct)); break;
|
|
case MetaActionType::FILLCOLOR : DoAction(static_cast<MetaFillColorAction &>(*pAct)); break;
|
|
case MetaActionType::TEXTCOLOR : DoAction(static_cast<MetaTextColorAction &>(*pAct)); break;
|
|
case MetaActionType::TEXTFILLCOLOR : DoAction(static_cast<MetaTextFillColorAction &>(*pAct)); break;
|
|
case MetaActionType::FONT : DoAction(static_cast<MetaFontAction &>(*pAct)); break;
|
|
case MetaActionType::TEXTALIGN : DoAction(static_cast<MetaTextAlignAction &>(*pAct)); break;
|
|
case MetaActionType::MAPMODE : DoAction(static_cast<MetaMapModeAction &>(*pAct)); break;
|
|
case MetaActionType::CLIPREGION : DoAction(static_cast<MetaClipRegionAction &>(*pAct)); break;
|
|
case MetaActionType::MOVECLIPREGION : DoAction(static_cast<MetaMoveClipRegionAction &>(*pAct)); break;
|
|
case MetaActionType::ISECTRECTCLIPREGION: DoAction(static_cast<MetaISectRectClipRegionAction&>(*pAct)); break;
|
|
case MetaActionType::ISECTREGIONCLIPREGION: DoAction(static_cast<MetaISectRegionClipRegionAction&>(*pAct)); break;
|
|
case MetaActionType::RASTEROP : DoAction(static_cast<MetaRasterOpAction &>(*pAct)); break;
|
|
case MetaActionType::PUSH : DoAction(static_cast<MetaPushAction &>(*pAct)); break;
|
|
case MetaActionType::POP : DoAction(static_cast<MetaPopAction &>(*pAct)); break;
|
|
case MetaActionType::HATCH : DoAction(static_cast<MetaHatchAction &>(*pAct)); break;
|
|
|
|
// #i125211# MetaCommentAction may change index, thus hand it over
|
|
case MetaActionType::COMMENT : DoAction(static_cast<MetaCommentAction&>(*pAct), rMtf, a);
|
|
break;
|
|
|
|
// missing actions added
|
|
case MetaActionType::TEXTRECT : DoAction(static_cast<MetaTextRectAction&>(*pAct)); break;
|
|
case MetaActionType::BMPSCALEPART : DoAction(static_cast<MetaBmpScalePartAction&>(*pAct)); break;
|
|
case MetaActionType::BMPEXSCALEPART : DoAction(static_cast<MetaBmpExScalePartAction&>(*pAct)); break;
|
|
case MetaActionType::MASK : DoAction(static_cast<MetaMaskAction&>(*pAct)); break;
|
|
case MetaActionType::MASKSCALE : DoAction(static_cast<MetaMaskScaleAction&>(*pAct)); break;
|
|
case MetaActionType::MASKSCALEPART : DoAction(static_cast<MetaMaskScalePartAction&>(*pAct)); break;
|
|
case MetaActionType::GRADIENT : DoAction(static_cast<MetaGradientAction&>(*pAct)); break;
|
|
case MetaActionType::WALLPAPER : OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)"); break;
|
|
case MetaActionType::Transparent : DoAction(static_cast<MetaTransparentAction&>(*pAct)); break;
|
|
case MetaActionType::EPS : OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)"); break;
|
|
case MetaActionType::REFPOINT : DoAction(static_cast<MetaRefPointAction&>(*pAct)); break;
|
|
case MetaActionType::TEXTLINECOLOR : DoAction(static_cast<MetaTextLineColorAction&>(*pAct)); break;
|
|
case MetaActionType::TEXTLINE : OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)"); break;
|
|
case MetaActionType::FLOATTRANSPARENT : DoAction(static_cast<MetaFloatTransparentAction&>(*pAct)); break;
|
|
case MetaActionType::GRADIENTEX : DoAction(static_cast<MetaGradientExAction&>(*pAct)); break;
|
|
case MetaActionType::LAYOUTMODE : DoAction(static_cast<MetaLayoutModeAction&>(*pAct)); break;
|
|
case MetaActionType::TEXTLANGUAGE : DoAction(static_cast<MetaTextLanguageAction&>(*pAct)); break;
|
|
case MetaActionType::OVERLINECOLOR : DoAction(static_cast<MetaOverlineColorAction&>(*pAct)); break;
|
|
default: break;
|
|
}
|
|
|
|
if(pProgrInfo && pActionsToReport)
|
|
{
|
|
(*pActionsToReport)++;
|
|
|
|
if(*pActionsToReport >= 16) // update all 16 actions
|
|
{
|
|
if(!pProgrInfo->ReportActions(*pActionsToReport))
|
|
break;
|
|
|
|
*pActionsToReport = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t ImpSdrGDIMetaFileImport::DoImport(
|
|
const GDIMetaFile& rMtf,
|
|
SdrObjList& rOL,
|
|
size_t nInsPos,
|
|
SvdProgressInfo* pProgrInfo)
|
|
{
|
|
maPrefMapMode = rMtf.GetPrefMapMode();
|
|
mpVD->SetMapMode(maPrefMapMode);
|
|
|
|
// setup some global scale parameter
|
|
// mfScaleX, mfScaleY, maScaleX, maScaleY, mbMov, mbSize
|
|
mfScaleX = mfScaleY = 1.0;
|
|
const Size aMtfSize(rMtf.GetPrefSize());
|
|
|
|
if(aMtfSize.Width() & aMtfSize.Height() && (!maScaleRect.IsEmpty()))
|
|
{
|
|
maOfs = maScaleRect.TopLeft();
|
|
|
|
if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
|
|
{
|
|
mfScaleX = static_cast<double>( maScaleRect.GetWidth() - 1 ) / static_cast<double>(aMtfSize.Width());
|
|
}
|
|
|
|
if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
|
|
{
|
|
mfScaleY = static_cast<double>( maScaleRect.GetHeight() - 1 ) / static_cast<double>(aMtfSize.Height());
|
|
}
|
|
}
|
|
|
|
mbMov = maOfs.X()!=0 || maOfs.Y()!=0;
|
|
mbSize = false;
|
|
maScaleX = Fraction( 1, 1 );
|
|
maScaleY = Fraction( 1, 1 );
|
|
|
|
if(aMtfSize.Width() != (maScaleRect.GetWidth() - 1))
|
|
{
|
|
maScaleX = Fraction(maScaleRect.GetWidth() - 1, aMtfSize.Width());
|
|
mbSize = true;
|
|
}
|
|
|
|
if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
|
|
{
|
|
maScaleY = Fraction(maScaleRect.GetHeight() - 1, aMtfSize.Height());
|
|
mbSize = true;
|
|
}
|
|
|
|
if(pProgrInfo)
|
|
{
|
|
pProgrInfo->SetActionCount(rMtf.GetActionSize());
|
|
}
|
|
|
|
sal_uInt32 nActionsToReport(0);
|
|
|
|
// execute
|
|
DoLoopActions(rMtf, pProgrInfo, &nActionsToReport);
|
|
|
|
if(pProgrInfo)
|
|
{
|
|
pProgrInfo->ReportActions(nActionsToReport);
|
|
nActionsToReport = 0;
|
|
}
|
|
|
|
// To calculate the progress meter, we use GetActionSize()*3.
|
|
// However, maTmpList has a lower entry count limit than GetActionSize(),
|
|
// so the actions that were assumed were too much have to be re-added.
|
|
nActionsToReport = (rMtf.GetActionSize() - maTmpList.size()) * 2;
|
|
|
|
// announce all currently unannounced rescales
|
|
if(pProgrInfo)
|
|
{
|
|
pProgrInfo->ReportRescales(nActionsToReport);
|
|
pProgrInfo->SetInsertCount(maTmpList.size());
|
|
}
|
|
|
|
nActionsToReport = 0;
|
|
|
|
// insert all objects cached in aTmpList now into rOL from nInsPos
|
|
nInsPos = std::min(nInsPos, rOL.GetObjCount());
|
|
|
|
for(rtl::Reference<SdrObject>& pObj : maTmpList)
|
|
{
|
|
rOL.NbcInsertObject(pObj.get(), nInsPos);
|
|
nInsPos++;
|
|
|
|
if(pProgrInfo)
|
|
{
|
|
nActionsToReport++;
|
|
|
|
if(nActionsToReport >= 32) // update all 32 actions
|
|
{
|
|
pProgrInfo->ReportInserts(nActionsToReport);
|
|
nActionsToReport = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// report all remaining inserts for the last time
|
|
if(pProgrInfo)
|
|
{
|
|
pProgrInfo->ReportInserts(nActionsToReport);
|
|
}
|
|
|
|
return maTmpList.size();
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, bool bForceTextAttr)
|
|
{
|
|
mbNoLine = false;
|
|
mbNoFill = false;
|
|
bool bLine(!bForceTextAttr);
|
|
bool bFill(!pObj || (pObj->IsClosedObj() && !bForceTextAttr));
|
|
bool bText(bForceTextAttr || (pObj && pObj->GetOutlinerParaObject()));
|
|
|
|
if(bLine)
|
|
{
|
|
if(mnLineWidth)
|
|
{
|
|
mpLineAttr->Put(XLineWidthItem(mnLineWidth));
|
|
}
|
|
else
|
|
{
|
|
mpLineAttr->Put(XLineWidthItem(0));
|
|
}
|
|
|
|
maOldLineColor = mpVD->GetLineColor();
|
|
|
|
if(mpVD->IsLineColor())
|
|
{
|
|
mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_SOLID));
|
|
mpLineAttr->Put(XLineColorItem(OUString(), mpVD->GetLineColor()));
|
|
}
|
|
else
|
|
{
|
|
mpLineAttr->Put(XLineStyleItem(drawing::LineStyle_NONE));
|
|
}
|
|
|
|
switch(maLineJoin)
|
|
{
|
|
case basegfx::B2DLineJoin::NONE:
|
|
mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_NONE));
|
|
break;
|
|
case basegfx::B2DLineJoin::Bevel:
|
|
mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_BEVEL));
|
|
break;
|
|
case basegfx::B2DLineJoin::Miter:
|
|
mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_MITER));
|
|
break;
|
|
case basegfx::B2DLineJoin::Round:
|
|
mpLineAttr->Put(XLineJointItem(css::drawing::LineJoint_ROUND));
|
|
break;
|
|
}
|
|
|
|
// Add LineCap support
|
|
mpLineAttr->Put(XLineCapItem(maLineCap));
|
|
|
|
if(((maDash.GetDots() && maDash.GetDotLen()) || (maDash.GetDashes() && maDash.GetDashLen())) && maDash.GetDistance())
|
|
{
|
|
mpLineAttr->Put(XLineDashItem(OUString(), maDash));
|
|
}
|
|
else
|
|
{
|
|
mpLineAttr->Put(XLineDashItem(OUString(), XDash(css::drawing::DashStyle_RECT)));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mbNoLine = true;
|
|
}
|
|
|
|
if(bFill)
|
|
{
|
|
if(mpVD->IsFillColor())
|
|
{
|
|
mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_SOLID));
|
|
mpFillAttr->Put(XFillColorItem(OUString(), mpVD->GetFillColor()));
|
|
}
|
|
else
|
|
{
|
|
mpFillAttr->Put(XFillStyleItem(drawing::FillStyle_NONE));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mbNoFill = true;
|
|
}
|
|
|
|
if(bText && mbFntDirty)
|
|
{
|
|
vcl::Font aFnt(mpVD->GetFont());
|
|
const sal_uInt32 nHeight(basegfx::fround(implMap(aFnt.GetFontSize()).Height() * mfScaleY));
|
|
|
|
mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
|
|
mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
|
|
mpTextAttr->Put( SvxFontItem( aFnt.GetFamilyType(), aFnt.GetFamilyName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CTL ) );
|
|
mpTextAttr->Put(SvxPostureItem(aFnt.GetItalic(), EE_CHAR_ITALIC));
|
|
mpTextAttr->Put(SvxWeightItem(aFnt.GetWeight(), EE_CHAR_WEIGHT));
|
|
mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
|
|
mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
|
|
mpTextAttr->Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
|
|
mpTextAttr->Put(SvxCharScaleWidthItem(100, EE_CHAR_FONTWIDTH));
|
|
mpTextAttr->Put(SvxUnderlineItem(aFnt.GetUnderline(), EE_CHAR_UNDERLINE));
|
|
mpTextAttr->Put(SvxOverlineItem(aFnt.GetOverline(), EE_CHAR_OVERLINE));
|
|
mpTextAttr->Put(SvxCrossedOutItem(aFnt.GetStrikeout(), EE_CHAR_STRIKEOUT));
|
|
mpTextAttr->Put(SvxShadowedItem(aFnt.IsShadow(), EE_CHAR_SHADOW));
|
|
|
|
// #i118485# Setting this item leads to problems (written #i118498# for this)
|
|
// mpTextAttr->Put(SvxAutoKernItem(aFnt.IsKerning(), EE_CHAR_KERNING));
|
|
|
|
mpTextAttr->Put(SvxWordLineModeItem(aFnt.IsWordLineMode(), EE_CHAR_WLM));
|
|
mpTextAttr->Put(SvxContourItem(aFnt.IsOutline(), EE_CHAR_OUTLINE));
|
|
mpTextAttr->Put(SvxColorItem(mpVD->GetTextColor(), EE_CHAR_COLOR));
|
|
//... svxfont textitem svditext
|
|
mbFntDirty = false;
|
|
}
|
|
|
|
if(!pObj)
|
|
return;
|
|
|
|
pObj->SetLayer(mnLayer);
|
|
|
|
if(bLine)
|
|
{
|
|
pObj->SetMergedItemSet(*mpLineAttr);
|
|
}
|
|
|
|
if(bFill)
|
|
{
|
|
pObj->SetMergedItemSet(*mpFillAttr);
|
|
}
|
|
|
|
if(bText)
|
|
{
|
|
pObj->SetMergedItemSet(*mpTextAttr);
|
|
pObj->SetMergedItem(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
|
|
}
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj1, bool bScale)
|
|
{
|
|
rtl::Reference<SdrObject> pObj = pObj1;
|
|
if(bScale && !maScaleRect.IsEmpty())
|
|
{
|
|
if(mbSize)
|
|
{
|
|
pObj->NbcResize(Point(), maScaleX, maScaleY);
|
|
}
|
|
|
|
if(mbMov)
|
|
{
|
|
pObj->NbcMove(Size(maOfs.X(), maOfs.Y()));
|
|
}
|
|
}
|
|
|
|
if(isClip())
|
|
{
|
|
const basegfx::B2DPolyPolygon aPoly(pObj->TakeXorPoly());
|
|
const basegfx::B2DRange aOldRange(aPoly.getB2DRange());
|
|
const SdrLayerID aOldLayer(pObj->GetLayer());
|
|
const SfxItemSet aOldItemSet(pObj->GetMergedItemSet());
|
|
const SdrGrafObj* pSdrGrafObj = dynamic_cast< SdrGrafObj* >(pObj.get());
|
|
const SdrTextObj* pSdrTextObj = DynCastSdrTextObj(pObj.get());
|
|
|
|
if(pSdrTextObj && pSdrTextObj->HasText())
|
|
{
|
|
// all text objects are created from ImportText and have no line or fill attributes, so
|
|
// it is okay to concentrate on the text itself
|
|
while(true)
|
|
{
|
|
const basegfx::B2DPolyPolygon aTextContour(pSdrTextObj->TakeContour());
|
|
const basegfx::B2DRange aTextRange(aTextContour.getB2DRange());
|
|
const basegfx::B2DRange aClipRange(maClip.getB2DRange());
|
|
|
|
// no overlap -> completely outside
|
|
if(!aClipRange.overlaps(aTextRange))
|
|
{
|
|
pObj.clear();
|
|
break;
|
|
}
|
|
|
|
// when the clip is a rectangle fast check for inside is possible
|
|
if(basegfx::utils::isRectangle(maClip) && aClipRange.isInside(aTextRange))
|
|
{
|
|
// completely inside ClipRect
|
|
break;
|
|
}
|
|
|
|
// here text needs to be clipped; to do so, convert to SdrObjects with polygons
|
|
// and add these recursively. Delete original object, do not add in this run
|
|
rtl::Reference<SdrObject> pConverted = pSdrTextObj->ConvertToPolyObj(true, true);
|
|
pObj.clear();
|
|
|
|
if(pConverted)
|
|
{
|
|
// recursively add created conversion; per definition this shall not
|
|
// contain further SdrTextObjs. Visit only non-group objects
|
|
SdrObjListIter aIter(*pConverted, SdrIterMode::DeepNoGroups);
|
|
|
|
// work with clones; the created conversion may contain group objects
|
|
// and when working with the original objects the loop itself could
|
|
// break and the cleanup later would be pretty complicated (only delete group
|
|
// objects, are these empty, ...?)
|
|
while(aIter.IsMore())
|
|
{
|
|
SdrObject* pCandidate = aIter.Next();
|
|
OSL_ENSURE(pCandidate && dynamic_cast< SdrObjGroup* >(pCandidate) == nullptr, "SdrObjListIter with SdrIterMode::DeepNoGroups error (!)");
|
|
rtl::Reference<SdrObject> pNewClone(pCandidate->CloneSdrObject(pCandidate->getSdrModelFromSdrObject()));
|
|
|
|
if(pNewClone)
|
|
{
|
|
InsertObj(pNewClone.get(), false);
|
|
}
|
|
else
|
|
{
|
|
OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BitmapEx aBitmapEx;
|
|
|
|
if(pSdrGrafObj)
|
|
{
|
|
aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
|
|
}
|
|
|
|
pObj.clear();
|
|
|
|
if(!aOldRange.isEmpty())
|
|
{
|
|
// clip against ClipRegion
|
|
const basegfx::B2DPolyPolygon aNewPoly(
|
|
basegfx::utils::clipPolyPolygonOnPolyPolygon(
|
|
aPoly,
|
|
maClip,
|
|
true,
|
|
!aPoly.isClosed()));
|
|
const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
|
|
|
|
if(!aNewRange.isEmpty())
|
|
{
|
|
pObj = new SdrPathObj(
|
|
*mpModel,
|
|
aNewPoly.isClosed() ? SdrObjKind::Polygon : SdrObjKind::PolyLine,
|
|
aNewPoly);
|
|
|
|
pObj->SetLayer(aOldLayer);
|
|
pObj->SetMergedItemSet(aOldItemSet);
|
|
|
|
if(!aBitmapEx.IsEmpty())
|
|
{
|
|
// aNewRange is inside of aOldRange and defines which part of aBitmapEx is used
|
|
const double fScaleX(aBitmapEx.GetSizePixel().Width() / (aOldRange.getWidth() ? aOldRange.getWidth() : 1.0));
|
|
const double fScaleY(aBitmapEx.GetSizePixel().Height() / (aOldRange.getHeight() ? aOldRange.getHeight() : 1.0));
|
|
basegfx::B2DRange aPixel(aNewRange);
|
|
basegfx::B2DHomMatrix aTrans;
|
|
|
|
aTrans.translate(-aOldRange.getMinX(), -aOldRange.getMinY());
|
|
aTrans.scale(fScaleX, fScaleY);
|
|
aPixel.transform(aTrans);
|
|
|
|
const Size aOrigSizePixel(aBitmapEx.GetSizePixel());
|
|
const Point aClipTopLeft(
|
|
basegfx::fround<tools::Long>(floor(std::max(0.0, aPixel.getMinX()))),
|
|
basegfx::fround<tools::Long>(floor(std::max(0.0, aPixel.getMinY()))));
|
|
const Size aClipSize(
|
|
basegfx::fround<tools::Long>(ceil(std::min(static_cast<double>(aOrigSizePixel.Width()), aPixel.getWidth()))),
|
|
basegfx::fround<tools::Long>(ceil(std::min(static_cast<double>(aOrigSizePixel.Height()), aPixel.getHeight()))));
|
|
const BitmapEx aClippedBitmap(
|
|
aBitmapEx,
|
|
aClipTopLeft,
|
|
aClipSize);
|
|
|
|
pObj->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
|
|
pObj->SetMergedItem(XFillBitmapItem(OUString(), Graphic(aClippedBitmap)));
|
|
pObj->SetMergedItem(XFillBmpTileItem(false));
|
|
pObj->SetMergedItem(XFillBmpStretchItem(true));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!pObj)
|
|
return;
|
|
|
|
// #i111954# check object for visibility
|
|
// used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
|
|
bool bVisible(false);
|
|
|
|
if(pObj->HasLineStyle())
|
|
{
|
|
bVisible = true;
|
|
}
|
|
|
|
if(!bVisible && pObj->HasFillStyle())
|
|
{
|
|
bVisible = true;
|
|
}
|
|
|
|
if(!bVisible)
|
|
{
|
|
SdrTextObj* pTextObj = DynCastSdrTextObj(pObj.get());
|
|
|
|
if(pTextObj && pTextObj->HasText())
|
|
{
|
|
bVisible = true;
|
|
}
|
|
}
|
|
|
|
if(!bVisible)
|
|
{
|
|
SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj.get());
|
|
|
|
if(pGrafObj)
|
|
{
|
|
// this may be refined to check if the graphic really is visible. It
|
|
// is here to ensure that graphic objects without fill, line and text
|
|
// get created
|
|
bVisible = true;
|
|
}
|
|
}
|
|
|
|
if(bVisible)
|
|
{
|
|
maTmpList.push_back(pObj);
|
|
|
|
if(dynamic_cast< SdrPathObj* >(pObj.get()))
|
|
{
|
|
const bool bClosed(pObj->IsClosedObj());
|
|
|
|
mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
|
|
mbLastObjWasLine = !bClosed;
|
|
}
|
|
else
|
|
{
|
|
mbLastObjWasPolyWithoutLine = false;
|
|
mbLastObjWasLine = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction const & rAct)
|
|
{
|
|
// #i73407# reformulation to use new B2DPolygon classes
|
|
const basegfx::B2DPoint aStart(rAct.GetStartPoint().X(), rAct.GetStartPoint().Y());
|
|
const basegfx::B2DPoint aEnd(rAct.GetEndPoint().X(), rAct.GetEndPoint().Y());
|
|
|
|
if(aStart.equal(aEnd))
|
|
return;
|
|
|
|
basegfx::B2DPolygon aLine;
|
|
const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
|
|
|
|
aLine.append(aStart);
|
|
aLine.append(aEnd);
|
|
aLine.transform(aTransform);
|
|
|
|
const LineInfo& rLineInfo = rAct.GetLineInfo();
|
|
const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
|
|
bool bCreateLineObject(true);
|
|
|
|
if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aLine))
|
|
{
|
|
bCreateLineObject = false;
|
|
}
|
|
|
|
if(!bCreateLineObject)
|
|
return;
|
|
|
|
rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
|
|
*mpModel,
|
|
SdrObjKind::Line,
|
|
basegfx::B2DPolyPolygon(aLine));
|
|
mnLineWidth = nNewLineWidth;
|
|
maLineJoin = rLineInfo.GetLineJoin();
|
|
maLineCap = rLineInfo.GetLineCap();
|
|
maDash = XDash(css::drawing::DashStyle_RECT,
|
|
rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
|
|
rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
|
|
rLineInfo.GetDistance());
|
|
SetAttributes(pPath.get());
|
|
mnLineWidth = 0;
|
|
maLineJoin = basegfx::B2DLineJoin::NONE;
|
|
maDash = XDash();
|
|
InsertObj(pPath.get(), false);
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction const & rAct)
|
|
{
|
|
rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
|
|
*mpModel,
|
|
rAct.GetRect());
|
|
SetAttributes(pRect.get());
|
|
InsertObj(pRect.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction const & rAct)
|
|
{
|
|
rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
|
|
*mpModel,
|
|
rAct.GetRect());
|
|
SetAttributes(pRect.get());
|
|
tools::Long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
|
|
if (nRad!=0) {
|
|
SfxItemSetFixed<SDRATTR_CORNER_RADIUS, SDRATTR_CORNER_RADIUS> aSet(*mpLineAttr->GetPool());
|
|
aSet.Put(SdrMetricItem(SDRATTR_CORNER_RADIUS, nRad));
|
|
pRect->SetMergedItemSet(aSet);
|
|
}
|
|
InsertObj(pRect.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction const & rAct)
|
|
{
|
|
rtl::Reference<SdrCircObj> pCirc=new SdrCircObj(
|
|
*mpModel,
|
|
SdrCircKind::Full,
|
|
rAct.GetRect());
|
|
SetAttributes(pCirc.get());
|
|
InsertObj(pCirc.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction const & rAct)
|
|
{
|
|
Point aCenter(rAct.GetRect().Center());
|
|
Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
|
|
Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
|
|
rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
|
|
*mpModel,
|
|
SdrCircKind::Arc,
|
|
rAct.GetRect(),nStart,nEnd);
|
|
SetAttributes(pCirc.get());
|
|
InsertObj(pCirc.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction const & rAct)
|
|
{
|
|
Point aCenter(rAct.GetRect().Center());
|
|
Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
|
|
Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
|
|
rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
|
|
*mpModel,
|
|
SdrCircKind::Section,
|
|
rAct.GetRect(),
|
|
nStart,
|
|
nEnd);
|
|
SetAttributes(pCirc.get());
|
|
InsertObj(pCirc.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction const & rAct)
|
|
{
|
|
Point aCenter(rAct.GetRect().Center());
|
|
Degree100 nStart=GetAngle(rAct.GetStartPoint()-aCenter);
|
|
Degree100 nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
|
|
rtl::Reference<SdrCircObj> pCirc = new SdrCircObj(
|
|
*mpModel,
|
|
SdrCircKind::Cut,
|
|
rAct.GetRect(),
|
|
nStart,
|
|
nEnd);
|
|
SetAttributes(pCirc.get());
|
|
InsertObj(pCirc.get());
|
|
}
|
|
|
|
bool ImpSdrGDIMetaFileImport::CheckLastLineMerge(const basegfx::B2DPolygon& rSrcPoly)
|
|
{
|
|
// #i102706# Do not merge closed polygons
|
|
if(rSrcPoly.isClosed())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// #i73407# reformulation to use new B2DPolygon classes
|
|
if(mbLastObjWasLine && (maOldLineColor == mpVD->GetLineColor()) && rSrcPoly.count())
|
|
{
|
|
SdrObject* pTmpObj = !maTmpList.empty() ? maTmpList[maTmpList.size() - 1].get() : nullptr;
|
|
SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
|
|
|
|
if(pLastPoly)
|
|
{
|
|
if(1 == pLastPoly->GetPathPoly().count())
|
|
{
|
|
bool bOk(false);
|
|
basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0));
|
|
|
|
// #i102706# Do not merge closed polygons
|
|
if(aDstPoly.isClosed())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(aDstPoly.count())
|
|
{
|
|
const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1);
|
|
const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1);
|
|
|
|
if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0))
|
|
{
|
|
aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
|
|
bOk = true;
|
|
}
|
|
else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
|
|
{
|
|
basegfx::B2DPolygon aNew(rSrcPoly);
|
|
aNew.append(aDstPoly, 1, aDstPoly.count() - 1);
|
|
aDstPoly = std::move(aNew);
|
|
bOk = true;
|
|
}
|
|
else if(aDstPoly.getB2DPoint(0) == rSrcPoly.getB2DPoint(0))
|
|
{
|
|
aDstPoly.flip();
|
|
aDstPoly.append(rSrcPoly, 1, rSrcPoly.count() - 1);
|
|
bOk = true;
|
|
}
|
|
else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
|
|
{
|
|
basegfx::B2DPolygon aNew(rSrcPoly);
|
|
aNew.flip();
|
|
aDstPoly.append(aNew, 1, aNew.count() - 1);
|
|
bOk = true;
|
|
}
|
|
}
|
|
|
|
if(bOk)
|
|
{
|
|
pLastPoly->NbcSetPathPoly(basegfx::B2DPolyPolygon(aDstPoly));
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPolyPolygon & rPolyPolygon)
|
|
{
|
|
// #i73407# reformulation to use new B2DPolygon classes
|
|
if(mbLastObjWasPolyWithoutLine)
|
|
{
|
|
SdrObject* pTmpObj = !maTmpList.empty() ? maTmpList[maTmpList.size() - 1].get() : nullptr;
|
|
SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
|
|
|
|
if(pLastPoly)
|
|
{
|
|
if(pLastPoly->GetPathPoly() == rPolyPolygon)
|
|
{
|
|
SetAttributes(nullptr);
|
|
|
|
if(!mbNoLine && mbNoFill)
|
|
{
|
|
pLastPoly->SetMergedItemSet(*mpLineAttr);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::checkClip()
|
|
{
|
|
if(!mpVD->IsClipRegion())
|
|
return;
|
|
|
|
maClip = mpVD->GetClipRegion().GetAsB2DPolyPolygon();
|
|
|
|
if(isClip())
|
|
{
|
|
const basegfx::B2DHomMatrix aTransform(
|
|
implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(
|
|
mfScaleX,
|
|
mfScaleY,
|
|
maOfs.X(),
|
|
maOfs.Y()));
|
|
|
|
maClip.transform(aTransform);
|
|
}
|
|
}
|
|
|
|
bool ImpSdrGDIMetaFileImport::isClip() const
|
|
{
|
|
return !maClip.getB2DRange().isEmpty();
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction const & rAct )
|
|
{
|
|
// #i73407# reformulation to use new B2DPolygon classes
|
|
basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
|
|
|
|
if(aSource.count())
|
|
{
|
|
const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
|
|
aSource.transform(aTransform);
|
|
}
|
|
|
|
const LineInfo& rLineInfo = rAct.GetLineInfo();
|
|
const sal_Int32 nNewLineWidth(rLineInfo.GetWidth());
|
|
bool bCreateLineObject(true);
|
|
|
|
if(mbLastObjWasLine && (nNewLineWidth == mnLineWidth) && CheckLastLineMerge(aSource))
|
|
{
|
|
bCreateLineObject = false;
|
|
}
|
|
else if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
|
|
{
|
|
bCreateLineObject = false;
|
|
}
|
|
|
|
if(!bCreateLineObject)
|
|
return;
|
|
|
|
rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
|
|
*mpModel,
|
|
aSource.isClosed() ? SdrObjKind::Polygon : SdrObjKind::PolyLine,
|
|
basegfx::B2DPolyPolygon(aSource));
|
|
mnLineWidth = nNewLineWidth;
|
|
maLineJoin = rLineInfo.GetLineJoin();
|
|
maLineCap = rLineInfo.GetLineCap();
|
|
maDash = XDash(css::drawing::DashStyle_RECT,
|
|
rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
|
|
rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
|
|
rLineInfo.GetDistance());
|
|
SetAttributes(pPath.get());
|
|
mnLineWidth = 0;
|
|
maLineJoin = basegfx::B2DLineJoin::NONE;
|
|
maDash = XDash();
|
|
InsertObj(pPath.get(), false);
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction const & rAct )
|
|
{
|
|
// #i73407# reformulation to use new B2DPolygon classes
|
|
basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
|
|
|
|
if(!aSource.count())
|
|
return;
|
|
|
|
const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
|
|
aSource.transform(aTransform);
|
|
|
|
if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(basegfx::B2DPolyPolygon(aSource)))
|
|
{
|
|
// #i73407# make sure polygon is closed, it's a filled primitive
|
|
aSource.setClosed(true);
|
|
rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
|
|
*mpModel,
|
|
SdrObjKind::Polygon,
|
|
basegfx::B2DPolyPolygon(aSource));
|
|
SetAttributes(pPath.get());
|
|
InsertObj(pPath.get(), false);
|
|
}
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction const & rAct)
|
|
{
|
|
// #i73407# reformulation to use new B2DPolygon classes
|
|
basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
|
|
|
|
if(!aSource.count())
|
|
return;
|
|
|
|
const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
|
|
aSource.transform(aTransform);
|
|
|
|
if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
|
|
{
|
|
// #i73407# make sure polygon is closed, it's a filled primitive
|
|
aSource.setClosed(true);
|
|
rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
|
|
*mpModel,
|
|
SdrObjKind::Polygon,
|
|
std::move(aSource));
|
|
SetAttributes(pPath.get());
|
|
InsertObj(pPath.get(), false);
|
|
}
|
|
}
|
|
|
|
Size ImpSdrGDIMetaFileImport::implMap(const Size& rSz) const
|
|
{
|
|
return OutputDevice::LogicToLogic(rSz, mpVD->GetMapMode(), maPrefMapMode);
|
|
}
|
|
|
|
Point ImpSdrGDIMetaFileImport::implMap(const Point& rPt) const
|
|
{
|
|
return OutputDevice::LogicToLogic(rPt, mpVD->GetMapMode(), maPrefMapMode);
|
|
}
|
|
|
|
basegfx::B2DHomMatrix ImpSdrGDIMetaFileImport::implMapMatrix() const
|
|
{
|
|
return OutputDevice::LogicToLogic(mpVD->GetMapMode(), maPrefMapMode);
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const OUString& rStr, const MetaAction& rAct )
|
|
{
|
|
// calc text box size, add 5% to make it fit safely
|
|
|
|
FontMetric aFontMetric( mpVD->GetFontMetric() );
|
|
vcl::Font aFnt( mpVD->GetFont() );
|
|
TextAlign eAlg( aFnt.GetAlignment() );
|
|
|
|
Size aTextSizeMapped(implMap(Size(mpVD->GetTextWidth(rStr), mpVD->GetTextHeight())));
|
|
|
|
sal_Int32 nTextWidth = static_cast<sal_Int32>(aTextSizeMapped.Width() * mfScaleX);
|
|
sal_Int32 nTextHeight = static_cast<sal_Int32>(aTextSizeMapped.Height() * mfScaleY);
|
|
|
|
Point aPosMapped(implMap(rPos));
|
|
|
|
Point aPos(basegfx::fround<tools::Long>(aPosMapped.X() * mfScaleX + maOfs.X()),
|
|
basegfx::fround<tools::Long>(aPosMapped.Y() * mfScaleY + maOfs.Y()));
|
|
Size aSize( nTextWidth, nTextHeight );
|
|
|
|
if ( eAlg == ALIGN_BASELINE )
|
|
{
|
|
auto nAscent = implMap(Size(0, aFontMetric.GetAscent())).Height();
|
|
aPos.AdjustY(basegfx::fround<tools::Long>(nAscent * -mfScaleY));
|
|
}
|
|
else if ( eAlg == ALIGN_BOTTOM )
|
|
aPos.AdjustY( -nTextHeight );
|
|
|
|
tools::Rectangle aTextRect( aPos, aSize );
|
|
rtl::Reference<SdrRectObj> pText = new SdrRectObj(
|
|
*mpModel,
|
|
SdrObjKind::Text,
|
|
aTextRect);
|
|
|
|
pText->SetMergedItem ( makeSdrTextUpperDistItem (0));
|
|
pText->SetMergedItem ( makeSdrTextLowerDistItem (0));
|
|
pText->SetMergedItem ( makeSdrTextRightDistItem (0));
|
|
pText->SetMergedItem ( makeSdrTextLeftDistItem (0));
|
|
|
|
if ( aFnt.GetAverageFontWidth() || ( rAct.GetType() == MetaActionType::STRETCHTEXT ) )
|
|
{
|
|
pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
|
|
pText->SetMergedItem( makeSdrTextAutoGrowHeightItem( false ) );
|
|
// don't let the margins eat the space needed for the text
|
|
pText->SetMergedItem( SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_ALLLINES) );
|
|
}
|
|
else
|
|
{
|
|
pText->SetMergedItem( makeSdrTextAutoGrowWidthItem( true ) );
|
|
}
|
|
|
|
pText->SetLayer(mnLayer);
|
|
pText->NbcSetText( rStr );
|
|
SetAttributes( pText.get(), true );
|
|
pText->SetSnapRect( aTextRect );
|
|
|
|
if (!aFnt.IsTransparent())
|
|
{
|
|
SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aAttr(*mpFillAttr->GetPool());
|
|
aAttr.Put(XFillStyleItem(drawing::FillStyle_SOLID));
|
|
aAttr.Put(XFillColorItem(OUString(), aFnt.GetFillColor()));
|
|
pText->SetMergedItemSet(aAttr);
|
|
}
|
|
Degree100 nAngle = to<Degree100>(aFnt.GetOrientation());
|
|
if ( nAngle )
|
|
pText->SdrAttrObj::NbcRotate(aPos,nAngle);
|
|
InsertObj( pText.get(), false );
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction const & rAct)
|
|
{
|
|
OUString aStr(rAct.GetText());
|
|
aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
|
|
ImportText( rAct.GetPoint(), aStr, rAct );
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction const & rAct)
|
|
{
|
|
OUString aStr(rAct.GetText());
|
|
aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
|
|
ImportText( rAct.GetPoint(), aStr, rAct );
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction const & rAct)
|
|
{
|
|
OUString aStr(rAct.GetText());
|
|
aStr = aStr.copy(rAct.GetIndex(), rAct.GetLen());
|
|
ImportText( rAct.GetPoint(), aStr, rAct );
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
|
|
aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
Graphic(BitmapEx(rAct.GetBitmap())),
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
|
|
aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
Graphic(BitmapEx(rAct.GetBitmap())),
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
|
|
aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
rAct.GetBitmapEx(),
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
|
|
aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
rAct.GetBitmapEx(),
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction const & rAct )
|
|
{
|
|
// #i73407# reformulation to use new B2DPolygon classes
|
|
basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
|
|
|
|
if(!aSource.count())
|
|
return;
|
|
|
|
const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
|
|
aSource.transform(aTransform);
|
|
|
|
if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(aSource))
|
|
return;
|
|
|
|
const Hatch& rHatch = rAct.GetHatch();
|
|
rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
|
|
*mpModel,
|
|
SdrObjKind::Polygon,
|
|
std::move(aSource));
|
|
// #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
|
|
SfxItemSet aHatchAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
|
|
css::drawing::HatchStyle eStyle;
|
|
|
|
switch(rHatch.GetStyle())
|
|
{
|
|
case HatchStyle::Triple :
|
|
{
|
|
eStyle = css::drawing::HatchStyle_TRIPLE;
|
|
break;
|
|
}
|
|
|
|
case HatchStyle::Double :
|
|
{
|
|
eStyle = css::drawing::HatchStyle_DOUBLE;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
eStyle = css::drawing::HatchStyle_SINGLE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
SetAttributes(pPath.get());
|
|
aHatchAttr.Put(XFillStyleItem(drawing::FillStyle_HATCH));
|
|
aHatchAttr.Put(XFillHatchItem(XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
|
|
pPath->SetMergedItemSet(aHatchAttr);
|
|
|
|
InsertObj(pPath.get(), false);
|
|
}
|
|
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
|
|
{
|
|
rAct.Execute(mpVD);
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
|
|
{
|
|
rAct.Execute(mpVD);
|
|
mbLastObjWasPolyWithoutLine = false;
|
|
mbLastObjWasLine = false;
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction const & rAct, GDIMetaFile const & rMtf, size_t& a) // GDIMetaFile* pMtf )
|
|
{
|
|
bool aSkipComment = false;
|
|
|
|
if (a < rMtf.GetActionSize() && rAct.GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN"))
|
|
{
|
|
// #i125211# Check if next action is a MetaGradientExAction
|
|
MetaGradientExAction* pAct = dynamic_cast< MetaGradientExAction* >(rMtf.GetAction(a + 1));
|
|
|
|
if( pAct && pAct->GetType() == MetaActionType::GRADIENTEX )
|
|
{
|
|
// #i73407# reformulation to use new B2DPolygon classes
|
|
basegfx::B2DPolyPolygon aSource(pAct->GetPolyPolygon().getB2DPolyPolygon());
|
|
|
|
if(aSource.count())
|
|
{
|
|
if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
|
|
{
|
|
const Gradient& rGrad = pAct->GetGradient();
|
|
rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
|
|
*mpModel,
|
|
SdrObjKind::Polygon,
|
|
std::move(aSource));
|
|
// #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
|
|
SfxItemSet aGradAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
|
|
basegfx::BGradient aBGradient(
|
|
basegfx::BColorStops(
|
|
rGrad.GetStartColor().getBColor(),
|
|
rGrad.GetEndColor().getBColor()));
|
|
|
|
aBGradient.SetGradientStyle(rGrad.GetStyle());
|
|
aBGradient.SetAngle(rGrad.GetAngle());
|
|
aBGradient.SetBorder(rGrad.GetBorder());
|
|
aBGradient.SetXOffset(rGrad.GetOfsX());
|
|
aBGradient.SetYOffset(rGrad.GetOfsY());
|
|
aBGradient.SetStartIntens(rGrad.GetStartIntensity());
|
|
aBGradient.SetEndIntens(rGrad.GetEndIntensity());
|
|
aBGradient.SetSteps(rGrad.GetSteps());
|
|
|
|
// no need to use SetAttributes(..) here since line and fill style
|
|
// need to be set individually
|
|
// SetAttributes(pPath);
|
|
|
|
// switch line off; if there was one there will be a
|
|
// MetaActionType::POLYLINE following creating another object
|
|
aGradAttr.Put(XLineStyleItem(drawing::LineStyle_NONE));
|
|
|
|
// add detected gradient fillstyle
|
|
aGradAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT));
|
|
aGradAttr.Put(XFillGradientItem(aBGradient));
|
|
|
|
pPath->SetMergedItemSet(aGradAttr);
|
|
|
|
InsertObj(pPath.get());
|
|
}
|
|
}
|
|
|
|
aSkipComment = true;
|
|
}
|
|
}
|
|
|
|
if(aSkipComment)
|
|
{
|
|
// #i125211# forward until closing MetaCommentAction
|
|
MetaAction* pSkipAct = rMtf.GetAction(++a);
|
|
|
|
while( pSkipAct
|
|
&& ((pSkipAct->GetType() != MetaActionType::COMMENT )
|
|
|| !(static_cast<MetaCommentAction*>(pSkipAct)->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_END"))))
|
|
{
|
|
pSkipAct = rMtf.GetAction(++a);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction const & rAct)
|
|
{
|
|
GDIMetaFile aTemp;
|
|
|
|
mpVD->AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
|
|
DoLoopActions(aTemp, nullptr, nullptr);
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
|
|
BitmapEx aBitmapEx(rAct.GetBitmap());
|
|
|
|
aRect.AdjustRight( 1 );
|
|
aRect.AdjustBottom( 1 );
|
|
aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
aBitmapEx,
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
|
|
BitmapEx aBitmapEx(rAct.GetBitmapEx());
|
|
|
|
aRect.AdjustRight( 1 );
|
|
aRect.AdjustBottom( 1 );
|
|
aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
aBitmapEx,
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
|
|
BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
|
|
|
|
aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
aBitmapEx,
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
|
|
BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
|
|
|
|
aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
aBitmapEx,
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction const & rAct)
|
|
{
|
|
tools::Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
|
|
BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
|
|
|
|
aRect.AdjustRight( 1 ); aRect.AdjustBottom( 1 );
|
|
aBitmapEx.Crop(tools::Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
aBitmapEx,
|
|
aRect);
|
|
|
|
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction const & rAct)
|
|
{
|
|
basegfx::B2DRange aRange = vcl::unotools::b2DRectangleFromRectangle(rAct.GetRect());
|
|
|
|
if(aRange.isEmpty())
|
|
return;
|
|
|
|
const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
|
|
aRange.transform(aTransform);
|
|
const Gradient& rGradient = rAct.GetGradient();
|
|
rtl::Reference<SdrRectObj> pRect = new SdrRectObj(
|
|
*mpModel,
|
|
tools::Rectangle(
|
|
floor(aRange.getMinX()),
|
|
floor(aRange.getMinY()),
|
|
ceil(aRange.getMaxX()),
|
|
ceil(aRange.getMaxY())));
|
|
// #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
|
|
SfxItemSet aGradientAttr(mpModel->GetItemPool(), pRect->GetMergedItemSet().GetRanges());
|
|
const XFillGradientItem aXFillGradientItem(
|
|
basegfx::BGradient(
|
|
basegfx::BColorStops(
|
|
rGradient.GetStartColor().getBColor(),
|
|
rGradient.GetEndColor().getBColor()),
|
|
rGradient.GetStyle(),
|
|
rGradient.GetAngle(),
|
|
rGradient.GetOfsX(),
|
|
rGradient.GetOfsY(),
|
|
rGradient.GetBorder(),
|
|
rGradient.GetStartIntensity(),
|
|
rGradient.GetEndIntensity(),
|
|
rGradient.GetSteps()));
|
|
|
|
SetAttributes(pRect.get());
|
|
aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
|
|
aGradientAttr.Put(aXFillGradientItem);
|
|
pRect->SetMergedItemSet(aGradientAttr);
|
|
|
|
InsertObj(pRect.get(), false);
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction const & rAct)
|
|
{
|
|
basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
|
|
|
|
if(!aSource.count())
|
|
return;
|
|
|
|
const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
|
|
aSource.transform(aTransform);
|
|
aSource.setClosed(true);
|
|
|
|
rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
|
|
*mpModel,
|
|
SdrObjKind::Polygon,
|
|
std::move(aSource));
|
|
SetAttributes(pPath.get());
|
|
pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
|
|
InsertObj(pPath.get(), false);
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction const & rAct)
|
|
{
|
|
basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
|
|
|
|
if(!aSource.count())
|
|
return;
|
|
|
|
const basegfx::B2DHomMatrix aTransform(implMapMatrix() *
|
|
basegfx::utils::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
|
|
aSource.transform(aTransform);
|
|
|
|
if(mbLastObjWasPolyWithoutLine && CheckLastPolyLineAndFillMerge(aSource))
|
|
return;
|
|
|
|
const Gradient& rGradient = rAct.GetGradient();
|
|
rtl::Reference<SdrPathObj> pPath = new SdrPathObj(
|
|
*mpModel,
|
|
SdrObjKind::Polygon,
|
|
std::move(aSource));
|
|
// #i125211# Use the ranges from the SdrObject to create a new empty SfxItemSet
|
|
SfxItemSet aGradientAttr(mpModel->GetItemPool(), pPath->GetMergedItemSet().GetRanges());
|
|
const XFillGradientItem aXFillGradientItem(
|
|
basegfx::BGradient(
|
|
basegfx::BColorStops(
|
|
rGradient.GetStartColor().getBColor(),
|
|
rGradient.GetEndColor().getBColor()),
|
|
rGradient.GetStyle(),
|
|
rGradient.GetAngle(),
|
|
rGradient.GetOfsX(),
|
|
rGradient.GetOfsY(),
|
|
rGradient.GetBorder(),
|
|
rGradient.GetStartIntensity(),
|
|
rGradient.GetEndIntensity(),
|
|
rGradient.GetSteps()));
|
|
|
|
SetAttributes(pPath.get());
|
|
aGradientAttr.Put(XFillStyleItem(drawing::FillStyle_GRADIENT)); // #i125211#
|
|
aGradientAttr.Put(aXFillGradientItem);
|
|
pPath->SetMergedItemSet(aGradientAttr);
|
|
|
|
InsertObj(pPath.get(), false);
|
|
}
|
|
|
|
void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction const & rAct)
|
|
{
|
|
const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
|
|
|
|
if(!rMtf.GetActionSize())
|
|
return;
|
|
|
|
const tools::Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
|
|
|
|
// convert metafile sub-content to BitmapEx
|
|
BitmapEx aBitmapEx(
|
|
convertMetafileToBitmapEx(
|
|
rMtf,
|
|
vcl::unotools::b2DRectangleFromRectangle(aRect),
|
|
125000));
|
|
|
|
// handle colors
|
|
const Gradient& rGradient = rAct.GetGradient();
|
|
basegfx::BColor aStart(rGradient.GetStartColor().getBColor());
|
|
basegfx::BColor aEnd(rGradient.GetEndColor().getBColor());
|
|
|
|
if(100 != rGradient.GetStartIntensity())
|
|
{
|
|
aStart *= static_cast<double>(rGradient.GetStartIntensity()) / 100.0;
|
|
}
|
|
|
|
if(100 != rGradient.GetEndIntensity())
|
|
{
|
|
aEnd *= static_cast<double>(rGradient.GetEndIntensity()) / 100.0;
|
|
}
|
|
|
|
const bool bEqualColors(aStart == aEnd);
|
|
const bool bNoSteps(1 == rGradient.GetSteps());
|
|
bool bCreateObject(true);
|
|
bool bHasNewMask(false);
|
|
AlphaMask aNewMask;
|
|
double fTransparence(0.0);
|
|
bool bFixedTransparence(false);
|
|
|
|
if(bEqualColors || bNoSteps)
|
|
{
|
|
// single transparence
|
|
const basegfx::BColor aMedium(basegfx::average(aStart, aEnd));
|
|
fTransparence = aMedium.luminance();
|
|
|
|
if(fTransparence <= 0.0)
|
|
{
|
|
// no transparence needed, all done
|
|
}
|
|
else if(basegfx::fTools::moreOrEqual(fTransparence, 1.0))
|
|
{
|
|
// all transparent, no object
|
|
bCreateObject = false;
|
|
}
|
|
else
|
|
{
|
|
// 0.0 < transparence < 1.0, apply fixed transparence
|
|
bFixedTransparence = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// gradient transparence
|
|
ScopedVclPtrInstance< VirtualDevice > pVDev;
|
|
|
|
pVDev->SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
|
|
pVDev->DrawGradient(tools::Rectangle(Point(0, 0), pVDev->GetOutputSizePixel()), rGradient);
|
|
|
|
aNewMask = AlphaMask(pVDev->GetBitmap(Point(0, 0), pVDev->GetOutputSizePixel()));
|
|
aNewMask.Invert(); // convert transparency to alpha
|
|
bHasNewMask = true;
|
|
}
|
|
|
|
if(!bCreateObject)
|
|
return;
|
|
|
|
if(bHasNewMask || bFixedTransparence)
|
|
{
|
|
if(!aBitmapEx.IsAlpha())
|
|
{
|
|
// no transparence yet, apply new one
|
|
if(bFixedTransparence)
|
|
{
|
|
sal_uInt8 nTransparence(basegfx::fround(fTransparence * 255.0));
|
|
|
|
aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), &nTransparence);
|
|
}
|
|
|
|
aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
|
|
}
|
|
else
|
|
{
|
|
vcl::bitmap::DrawAlphaBitmapAndAlphaGradient(aBitmapEx, bFixedTransparence, fTransparence, aNewMask);
|
|
}
|
|
}
|
|
|
|
// create and add object
|
|
rtl::Reference<SdrGrafObj> pGraf = new SdrGrafObj(
|
|
*mpModel,
|
|
aBitmapEx,
|
|
aRect);
|
|
|
|
// for MetaFloatTransparentAction, do not use SetAttributes(...)
|
|
// since these metafile content is not used to draw line/fill
|
|
// dependent of these setting at the device content
|
|
pGraf->SetMergedItem(XLineStyleItem(drawing::LineStyle_NONE));
|
|
pGraf->SetMergedItem(XFillStyleItem(drawing::FillStyle_NONE));
|
|
InsertObj(pGraf.get());
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|