blob: 33fdd2765b60dcb51a4eeb09cc3484433296247c [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
#include "svdfmtf.hxx"
#include <editeng/editdata.hxx>
#include <math.h>
#include <svx/xpoly.hxx>
#include <vcl/svapp.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/wghtitem.hxx>
#include <editeng/postitem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/crsditem.hxx>
#include <editeng/shdditem.hxx>
#include <svx/xlnclit.hxx>
#include <svx/xlncapit.hxx>
#include <svx/xlnwtit.hxx>
#include <svx/xflclit.hxx>
#include <svx/xgrad.hxx>
#include <svx/xflgrit.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/akrnitem.hxx>
#include <editeng/wrlmitem.hxx>
#include <editeng/cntritem.hxx>
#include <editeng/colritem.hxx>
#include <vcl/metric.hxx>
#include <editeng/charscaleitem.hxx>
#include <svx/xflhtit.hxx>
#include <svx/svdattr.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdpage.hxx>
#include <svx/svdobj.hxx>
#include "svx/svditext.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 <vcl/salbtype.hxx> // FRound
#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 <vcl/bmpacc.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>
////////////////////////////////////////////////////////////////////////////////////////////////////
ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(
SdrModel& rModel,
SdrLayerID nLay,
const Rectangle& rRect)
: maTmpList(),
maVD(),
maScaleRect(rRect),
mnMapScalingOfs(0),
mpLineAttr(0),
mpFillAttr(0),
mpTextAttr(0),
mpModel(&rModel),
mnLayer(nLay),
maOldLineColor(),
mnLineWidth(0),
maLineJoin(basegfx::B2DLINEJOIN_NONE),
maLineCap(com::sun::star::drawing::LineCap_BUTT),
maDash(XDASH_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),
maClip()
{
maVD.EnableOutput(false);
maVD.SetLineColor();
maVD.SetFillColor();
maOldLineColor.SetRed( maVD.GetLineColor().GetRed() + 1 );
mpLineAttr = new SfxItemSet(rModel.GetItemPool(), XATTR_LINE_FIRST, XATTR_LINE_LAST, 0, 0);
mpFillAttr = new SfxItemSet(rModel.GetItemPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST, 0, 0);
mpTextAttr = new SfxItemSet(rModel.GetItemPool(), EE_ITEMS_START, EE_ITEMS_END, 0, 0);
checkClip();
}
ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport()
{
delete mpLineAttr;
delete mpFillAttr;
delete mpTextAttr;
}
void ImpSdrGDIMetaFileImport::DoLoopActions(GDIMetaFile& rMtf, SvdProgressInfo* pProgrInfo, sal_uInt32* pActionsToReport)
{
const sal_uLong nCount(rMtf.GetActionCount());
for(sal_uLong 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 META_PIXEL_ACTION : DoAction((MetaPixelAction &)*pAct); break;
case META_POINT_ACTION : DoAction((MetaPointAction &)*pAct); break;
case META_LINE_ACTION : DoAction((MetaLineAction &)*pAct); break;
case META_RECT_ACTION : DoAction((MetaRectAction &)*pAct); break;
case META_ROUNDRECT_ACTION : DoAction((MetaRoundRectAction &)*pAct); break;
case META_ELLIPSE_ACTION : DoAction((MetaEllipseAction &)*pAct); break;
case META_ARC_ACTION : DoAction((MetaArcAction &)*pAct); break;
case META_PIE_ACTION : DoAction((MetaPieAction &)*pAct); break;
case META_CHORD_ACTION : DoAction((MetaChordAction &)*pAct); break;
case META_POLYLINE_ACTION : DoAction((MetaPolyLineAction &)*pAct); break;
case META_POLYGON_ACTION : DoAction((MetaPolygonAction &)*pAct); break;
case META_POLYPOLYGON_ACTION : DoAction((MetaPolyPolygonAction &)*pAct); break;
case META_TEXT_ACTION : DoAction((MetaTextAction &)*pAct); break;
case META_TEXTARRAY_ACTION : DoAction((MetaTextArrayAction &)*pAct); break;
case META_STRETCHTEXT_ACTION : DoAction((MetaStretchTextAction &)*pAct); break;
case META_BMP_ACTION : DoAction((MetaBmpAction &)*pAct); break;
case META_BMPSCALE_ACTION : DoAction((MetaBmpScaleAction &)*pAct); break;
case META_BMPEX_ACTION : DoAction((MetaBmpExAction &)*pAct); break;
case META_BMPEXSCALE_ACTION : DoAction((MetaBmpExScaleAction &)*pAct); break;
case META_LINECOLOR_ACTION : DoAction((MetaLineColorAction &)*pAct); break;
case META_FILLCOLOR_ACTION : DoAction((MetaFillColorAction &)*pAct); break;
case META_TEXTCOLOR_ACTION : DoAction((MetaTextColorAction &)*pAct); break;
case META_TEXTFILLCOLOR_ACTION : DoAction((MetaTextFillColorAction &)*pAct); break;
case META_FONT_ACTION : DoAction((MetaFontAction &)*pAct); break;
case META_TEXTALIGN_ACTION : DoAction((MetaTextAlignAction &)*pAct); break;
case META_MAPMODE_ACTION : DoAction((MetaMapModeAction &)*pAct); break;
case META_CLIPREGION_ACTION : DoAction((MetaClipRegionAction &)*pAct); break;
case META_MOVECLIPREGION_ACTION : DoAction((MetaMoveClipRegionAction &)*pAct); break;
case META_ISECTRECTCLIPREGION_ACTION: DoAction((MetaISectRectClipRegionAction&)*pAct); break;
case META_ISECTREGIONCLIPREGION_ACTION: DoAction((MetaISectRegionClipRegionAction&)*pAct); break;
case META_RASTEROP_ACTION : DoAction((MetaRasterOpAction &)*pAct); break;
case META_PUSH_ACTION : DoAction((MetaPushAction &)*pAct); break;
case META_POP_ACTION : DoAction((MetaPopAction &)*pAct); break;
case META_HATCH_ACTION : DoAction((MetaHatchAction &)*pAct); break;
case META_COMMENT_ACTION : DoAction((MetaCommentAction &)*pAct, &rMtf); break;
// missing actions added
case META_TEXTRECT_ACTION : DoAction((MetaTextRectAction&)*pAct); break;
case META_BMPSCALEPART_ACTION : DoAction((MetaBmpScalePartAction&)*pAct); break;
case META_BMPEXSCALEPART_ACTION : DoAction((MetaBmpExScalePartAction&)*pAct); break;
case META_MASK_ACTION : DoAction((MetaMaskAction&)*pAct); break;
case META_MASKSCALE_ACTION : DoAction((MetaMaskScaleAction&)*pAct); break;
case META_MASKSCALEPART_ACTION : DoAction((MetaMaskScalePartAction&)*pAct); break;
case META_GRADIENT_ACTION : DoAction((MetaGradientAction&)*pAct); break;
case META_WALLPAPER_ACTION : DoAction((MetaWallpaperAction&)*pAct); break;
case META_TRANSPARENT_ACTION : DoAction((MetaTransparentAction&)*pAct); break;
case META_EPS_ACTION : DoAction((MetaEPSAction&)*pAct); break;
case META_REFPOINT_ACTION : DoAction((MetaRefPointAction&)*pAct); break;
case META_TEXTLINECOLOR_ACTION : DoAction((MetaTextLineColorAction&)*pAct); break;
case META_TEXTLINE_ACTION : DoAction((MetaTextLineAction&)*pAct); break;
case META_FLOATTRANSPARENT_ACTION : DoAction((MetaFloatTransparentAction&)*pAct); break;
case META_GRADIENTEX_ACTION : DoAction((MetaGradientExAction&)*pAct); break;
case META_LAYOUTMODE_ACTION : DoAction((MetaLayoutModeAction&)*pAct); break;
case META_TEXTLANGUAGE_ACTION : DoAction((MetaTextLanguageAction&)*pAct); break;
case META_OVERLINECOLOR_ACTION : DoAction((MetaOverlineColorAction&)*pAct); break;
}
if(pProgrInfo && pActionsToReport)
{
(*pActionsToReport)++;
if(*pActionsToReport >= 16) // Alle 16 Action updaten
{
if(!pProgrInfo->ReportActions(*pActionsToReport))
break;
*pActionsToReport = 0;
}
}
}
}
sal_uInt32 ImpSdrGDIMetaFileImport::DoImport(
const GDIMetaFile& rMtf,
SdrObjList& rOL,
sal_uInt32 nInsPos,
SvdProgressInfo* pProgrInfo)
{
// 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 = (double)( maScaleRect.GetWidth() - 1 ) / (double)aMtfSize.Width();
}
if(aMtfSize.Height() != (maScaleRect.GetHeight() - 1))
{
mfScaleY = (double)( maScaleRect.GetHeight() - 1 ) / (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.GetActionCount());
}
sal_uInt32 nActionsToReport(0);
// execute
DoLoopActions(const_cast< GDIMetaFile& >(rMtf), pProgrInfo, &nActionsToReport);
if(pProgrInfo)
{
pProgrInfo->ReportActions(nActionsToReport);
nActionsToReport = 0;
}
// MapMode-Scaling vornehmen
MapScaling();
// Beim berechnen der Fortschrittsanzeige wird GetActionCount()*3 benutzt.
// Da in maTmpList allerdings weniger eintraege als GetActionCount()
// existieren koennen, muessen hier die zuviel vermuteten Actionen wieder
// hinzugefuegt werden.
nActionsToReport = (rMtf.GetActionCount() - maTmpList.size()) * 2;
// Alle noch nicht gemeldeten Rescales melden
if(pProgrInfo)
{
pProgrInfo->ReportRescales(nActionsToReport);
pProgrInfo->SetInsertCount(maTmpList.size());
}
nActionsToReport = 0;
// alle in maTmpList zwischengespeicherten Objekte nun in rOL ab der Position nInsPos einfuegen
if(nInsPos > rOL.GetObjCount())
{
nInsPos = rOL.GetObjCount();
}
SdrInsertReason aReason(SDRREASON_VIEWCALL);
for(sal_uInt32 i(0); i < maTmpList.size(); i++)
{
SdrObject* pObj = maTmpList[i];
rOL.NbcInsertObject(pObj, nInsPos, &aReason);
nInsPos++;
if(pProgrInfo)
{
nActionsToReport++;
if(nActionsToReport >= 32) // Alle 32 Action updaten
{
pProgrInfo->ReportInserts(nActionsToReport);
nActionsToReport = 0;
}
}
}
// ein letztesmal alle verbliebennen Inserts reporten
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 = maVD.GetLineColor();
if(maVD.IsLineColor())
{
mpLineAttr->Put(XLineStyleItem(XLINE_SOLID));
mpLineAttr->Put(XLineColorItem(String(), maVD.GetLineColor()));
}
else
{
mpLineAttr->Put(XLineStyleItem(XLINE_NONE));
}
switch(maLineJoin)
{
default : // basegfx::B2DLINEJOIN_NONE
mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_NONE));
break;
case basegfx::B2DLINEJOIN_MIDDLE:
mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_MIDDLE));
break;
case basegfx::B2DLINEJOIN_BEVEL:
mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_BEVEL));
break;
case basegfx::B2DLINEJOIN_MITER:
mpLineAttr->Put(XLineJointItem(com::sun::star::drawing::LineJoint_MITER));
break;
case basegfx::B2DLINEJOIN_ROUND:
mpLineAttr->Put(XLineJointItem(com::sun::star::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(String(), maDash));
}
else
{
mpLineAttr->Put(XLineDashItem(String(), XDash(XDASH_RECT)));
}
}
else
{
mbNoLine = true;
}
if(bFill)
{
if(maVD.IsFillColor())
{
mpFillAttr->Put(XFillStyleItem(XFILL_SOLID));
mpFillAttr->Put(XFillColorItem(String(), maVD.GetFillColor()));
}
else
{
mpFillAttr->Put(XFillStyleItem(XFILL_NONE));
}
}
else
{
mbNoFill = true;
}
if(bText && mbFntDirty)
{
Font aFnt(maVD.GetFont());
const sal_uInt32 nHeight(FRound(aFnt.GetSize().Height() * mfScaleY));
mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO ) );
mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), aFnt.GetStyleName(), aFnt.GetPitch(), aFnt.GetCharSet(), EE_CHAR_FONTINFO_CJK ) );
mpTextAttr->Put( SvxFontItem( aFnt.GetFamily(), aFnt.GetName(), 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(maVD.GetTextColor(), EE_CHAR_COLOR));
//... svxfont textitem svditext
mbFntDirty = false;
}
if(pObj)
{
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* pObj, bool bScale)
{
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);
const SdrTextObj* pSdrTextObj = dynamic_cast< SdrTextObj* >(pObj);
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))
{
SdrObject::Free(pObj);
break;
}
// when the clip is a rectangle fast check for inside is possible
if(basegfx::tools::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
SdrObject* pConverted = pSdrTextObj->ConvertToPolyObj(true, true);
SdrObject::Free(pObj);
if(pConverted)
{
// recursively add created conversion; per definition this shall not
// contain further SdrTextObjs. Visit only non-group objects
SdrObjListIter aIter(*pConverted, IM_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 && 0 == dynamic_cast< SdrObjGroup* >(pCandidate), "SdrObjListIter with IM_DEEPNOGROUPS error (!)");
SdrObject* pNewClone = pCandidate->Clone();
if(pNewClone)
{
InsertObj(pNewClone, false);
}
else
{
OSL_ENSURE(false, "SdrObject::Clone() failed (!)");
}
}
// cleanup temporary conversion objects
SdrObject::Free(pConverted);
}
break;
}
}
else
{
BitmapEx aBitmapEx;
if(pSdrGrafObj)
{
aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
}
SdrObject::Free(pObj);
if(!aOldRange.isEmpty())
{
// clip against ClipRegion
const basegfx::B2DPolyPolygon aNewPoly(
basegfx::tools::clipPolyPolygonOnPolyPolygon(
aPoly,
maClip,
true,
aPoly.isClosed() ? false : true));
const basegfx::B2DRange aNewRange(aNewPoly.getB2DRange());
if(!aNewRange.isEmpty())
{
pObj = new SdrPathObj(
aNewPoly.isClosed() ? OBJ_POLY : OBJ_PLIN,
aNewPoly);
pObj->SetLayer(aOldLayer);
pObj->SetMergedItemSet(aOldItemSet);
if(!!aBitmapEx)
{
// 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(floor(std::max(0.0, aPixel.getMinX()))),
basegfx::fround(floor(std::max(0.0, aPixel.getMinY()))));
const Size aClipSize(
basegfx::fround(ceil(std::min((double)aOrigSizePixel.Width(), aPixel.getWidth()))),
basegfx::fround(ceil(std::min((double)aOrigSizePixel.Height(), aPixel.getHeight()))));
const BitmapEx aClippedBitmap(
aBitmapEx,
aClipTopLeft,
aClipSize);
pObj->SetMergedItem(XFillStyleItem(XFILL_BITMAP));
pObj->SetMergedItem(XFillBitmapItem(String(), Graphic(aClippedBitmap)));
pObj->SetMergedItem(XFillBmpTileItem(false));
pObj->SetMergedItem(XFillBmpStretchItem(true));
}
}
}
}
}
if(pObj)
{
// #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 = dynamic_cast< SdrTextObj* >(pObj);
if(pTextObj && pTextObj->HasText())
{
bVisible = true;
}
}
if(!bVisible)
{
SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
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)
{
SdrObject::Free(pObj);
}
else
{
maTmpList.push_back(pObj);
if(dynamic_cast< SdrPathObj* >(pObj))
{
const bool bClosed(pObj->IsClosedObj());
mbLastObjWasPolyWithoutLine = mbNoLine && bClosed;
mbLastObjWasLine = !bClosed;
}
else
{
mbLastObjWasPolyWithoutLine = false;
mbLastObjWasLine = false;
}
}
}
}
/**************************************************************************************************/
void ImpSdrGDIMetaFileImport::DoAction(MetaPixelAction& /*rAct*/)
{
}
void ImpSdrGDIMetaFileImport::DoAction(MetaPointAction& /*rAct*/)
{
}
void ImpSdrGDIMetaFileImport::DoAction(MetaLineAction& 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))
{
basegfx::B2DPolygon aLine;
const basegfx::B2DHomMatrix aTransform(basegfx::tools::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)
{
SdrPathObj* pPath = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aLine));
mnLineWidth = nNewLineWidth;
maLineJoin = rLineInfo.GetLineJoin();
maLineCap = rLineInfo.GetLineCap();
maDash = XDash(XDASH_RECT,
rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
rLineInfo.GetDistance());
SetAttributes(pPath);
mnLineWidth = 0;
maLineJoin = basegfx::B2DLINEJOIN_NONE;
maDash = XDash();
InsertObj(pPath, false);
}
}
}
void ImpSdrGDIMetaFileImport::DoAction(MetaRectAction& rAct)
{
SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
SetAttributes(pRect);
InsertObj(pRect);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaRoundRectAction& rAct)
{
SdrRectObj* pRect=new SdrRectObj(rAct.GetRect());
SetAttributes(pRect);
long nRad=(rAct.GetHorzRound()+rAct.GetVertRound())/2;
if (nRad!=0) {
SfxItemSet aSet(*mpLineAttr->GetPool(), SDRATTR_ECKENRADIUS, SDRATTR_ECKENRADIUS, 0, 0);
aSet.Put(SdrEckenradiusItem(nRad));
pRect->SetMergedItemSet(aSet);
}
InsertObj(pRect);
}
/**************************************************************************************************/
void ImpSdrGDIMetaFileImport::DoAction(MetaEllipseAction& rAct)
{
SdrCircObj* pCirc=new SdrCircObj(OBJ_CIRC,rAct.GetRect());
SetAttributes(pCirc);
InsertObj(pCirc);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaArcAction& rAct)
{
Point aCenter(rAct.GetRect().Center());
long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
SdrCircObj* pCirc=new SdrCircObj(OBJ_CARC,rAct.GetRect(),nStart,nEnd);
SetAttributes(pCirc);
InsertObj(pCirc);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaPieAction& rAct)
{
Point aCenter(rAct.GetRect().Center());
long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
SdrCircObj* pCirc=new SdrCircObj(OBJ_SECT,rAct.GetRect(),nStart,nEnd);
SetAttributes(pCirc);
InsertObj(pCirc);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaChordAction& rAct)
{
Point aCenter(rAct.GetRect().Center());
long nStart=GetAngle(rAct.GetStartPoint()-aCenter);
long nEnd=GetAngle(rAct.GetEndPoint()-aCenter);
SdrCircObj* pCirc=new SdrCircObj(OBJ_CCUT,rAct.GetRect(),nStart,nEnd);
SetAttributes(pCirc);
InsertObj(pCirc);
}
/**************************************************************************************************/
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 == maVD.GetLineColor()) && rSrcPoly.count())
{
SdrObject* pTmpObj = maTmpList.size() ? maTmpList[maTmpList.size() - 1] : 0;
SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
if(pLastPoly)
{
if(1L == pLastPoly->GetPathPoly().count())
{
bool bOk(false);
basegfx::B2DPolygon aDstPoly(pLastPoly->GetPathPoly().getB2DPolygon(0L));
// #i102706# Do not merge closed polygons
if(aDstPoly.isClosed())
{
return false;
}
if(aDstPoly.count())
{
const sal_uInt32 nMaxDstPnt(aDstPoly.count() - 1L);
const sal_uInt32 nMaxSrcPnt(rSrcPoly.count() - 1L);
if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(0L))
{
aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
bOk = true;
}
else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
{
basegfx::B2DPolygon aNew(rSrcPoly);
aNew.append(aDstPoly, 1L, aDstPoly.count() - 1L);
aDstPoly = aNew;
bOk = true;
}
else if(aDstPoly.getB2DPoint(0L) == rSrcPoly.getB2DPoint(0L))
{
aDstPoly.flip();
aDstPoly.append(rSrcPoly, 1L, rSrcPoly.count() - 1L);
bOk = true;
}
else if(aDstPoly.getB2DPoint(nMaxDstPnt) == rSrcPoly.getB2DPoint(nMaxSrcPnt))
{
basegfx::B2DPolygon aNew(rSrcPoly);
aNew.flip();
aDstPoly.append(aNew, 1L, aNew.count() - 1L);
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.size() ? maTmpList[maTmpList.size() - 1] : 0;
SdrPathObj* pLastPoly = dynamic_cast< SdrPathObj* >(pTmpObj);
if(pLastPoly)
{
if(pLastPoly->GetPathPoly() == rPolyPolygon)
{
SetAttributes(NULL);
if(!mbNoLine && mbNoFill)
{
pLastPoly->SetMergedItemSet(*mpLineAttr);
return true;
}
}
}
}
return false;
}
void ImpSdrGDIMetaFileImport::checkClip()
{
if(maVD.IsClipRegion())
{
maClip = maVD.GetClipRegion().GetAsB2DPolyPolygon();
if(isClip())
{
const basegfx::B2DHomMatrix aTransform(
basegfx::tools::createScaleTranslateB2DHomMatrix(
mfScaleX,
mfScaleY,
maOfs.X(),
maOfs.Y()));
maClip.transform(aTransform);
}
}
}
bool ImpSdrGDIMetaFileImport::isClip() const
{
return !maClip.getB2DRange().isEmpty();
}
void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct )
{
// #i73407# reformulation to use new B2DPolygon classes
basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
if(aSource.count())
{
const basegfx::B2DHomMatrix aTransform(basegfx::tools::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)
{
SdrPathObj* pPath = new SdrPathObj(
aSource.isClosed() ? OBJ_POLY : OBJ_PLIN,
basegfx::B2DPolyPolygon(aSource));
mnLineWidth = nNewLineWidth;
maLineJoin = rLineInfo.GetLineJoin();
maLineCap = rLineInfo.GetLineCap();
maDash = XDash(XDASH_RECT,
rLineInfo.GetDotCount(), rLineInfo.GetDotLen(),
rLineInfo.GetDashCount(), rLineInfo.GetDashLen(),
rLineInfo.GetDistance());
SetAttributes(pPath);
mnLineWidth = 0;
maLineJoin = basegfx::B2DLINEJOIN_NONE;
maDash = XDash();
InsertObj(pPath, false);
}
}
void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct )
{
// #i73407# reformulation to use new B2DPolygon classes
basegfx::B2DPolygon aSource(rAct.GetPolygon().getB2DPolygon());
if(aSource.count())
{
const basegfx::B2DHomMatrix aTransform(basegfx::tools::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);
SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource));
SetAttributes(pPath);
InsertObj(pPath, false);
}
}
}
void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct)
{
// #i73407# reformulation to use new B2DPolygon classes
basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
if(aSource.count())
{
const basegfx::B2DHomMatrix aTransform(basegfx::tools::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);
SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
SetAttributes(pPath);
InsertObj(pPath, false);
}
}
}
/**************************************************************************************************/
void ImpSdrGDIMetaFileImport::ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct )
{
// calc text box size, add 5% to make it fit safely
FontMetric aFontMetric( maVD.GetFontMetric() );
Font aFnt( maVD.GetFont() );
FontAlign eAlg( aFnt.GetAlign() );
sal_Int32 nTextWidth = (sal_Int32)( maVD.GetTextWidth( rStr ) * mfScaleX );
sal_Int32 nTextHeight = (sal_Int32)( maVD.GetTextHeight() * mfScaleY );
//sal_Int32 nDxWidth = 0;
//sal_Int32 nLen = rStr.Len();
Point aPos( FRound(rPos.X() * mfScaleX + maOfs.X()), FRound(rPos.Y() * mfScaleY + maOfs.Y()) );
Size aSize( nTextWidth, nTextHeight );
if ( eAlg == ALIGN_BASELINE )
aPos.Y() -= FRound(aFontMetric.GetAscent() * mfScaleY);
else if ( eAlg == ALIGN_BOTTOM )
aPos.Y() -= nTextHeight;
Rectangle aTextRect( aPos, aSize );
SdrRectObj* pText =new SdrRectObj( OBJ_TEXT, aTextRect );
pText->SetMergedItem ( SdrTextUpperDistItem (0));
pText->SetMergedItem ( SdrTextLowerDistItem (0));
pText->SetMergedItem ( SdrTextRightDistItem (0));
pText->SetMergedItem ( SdrTextLeftDistItem (0));
if ( aFnt.GetWidth() || ( rAct.GetType() == META_STRETCHTEXT_ACTION ) )
{
pText->ClearMergedItem( SDRATTR_TEXT_AUTOGROWWIDTH );
pText->SetMergedItem( SdrTextAutoGrowHeightItem( false ) );
// don't let the margins eat the space needed for the text
pText->SetMergedItem( SdrTextFitToSizeTypeItem( SDRTEXTFIT_ALLLINES ) );
}
else
{
pText->SetMergedItem( SdrTextAutoGrowWidthItem( true ) );
}
pText->SetModel(mpModel);
pText->SetLayer(mnLayer);
pText->NbcSetText( rStr );
SetAttributes( pText, true );
pText->SetSnapRect( aTextRect );
if (!aFnt.IsTransparent())
{
SfxItemSet aAttr(*mpFillAttr->GetPool(), XATTR_FILL_FIRST, XATTR_FILL_LAST, 0, 0);
aAttr.Put(XFillStyleItem(XFILL_SOLID));
aAttr.Put(XFillColorItem(String(), aFnt.GetFillColor()));
pText->SetMergedItemSet(aAttr);
}
sal_uInt32 nWink = aFnt.GetOrientation();
if ( nWink )
{
nWink*=10;
double a=nWink*nPi180;
double nSin=sin(a);
double nCos=cos(a);
pText->NbcRotate(aPos,nWink,nSin,nCos);
}
InsertObj( pText, false );
}
void ImpSdrGDIMetaFileImport::DoAction(MetaTextAction& rAct)
{
XubString aStr(rAct.GetText());
aStr.Erase(0,rAct.GetIndex());
aStr.Erase(rAct.GetLen());
ImportText( rAct.GetPoint(), aStr, rAct );
}
void ImpSdrGDIMetaFileImport::DoAction(MetaTextArrayAction& rAct)
{
XubString aStr(rAct.GetText());
aStr.Erase(0,rAct.GetIndex());
aStr.Erase(rAct.GetLen());
ImportText( rAct.GetPoint(), aStr, rAct );
}
void ImpSdrGDIMetaFileImport::DoAction(MetaStretchTextAction& rAct)
{
XubString aStr(rAct.GetText());
aStr.Erase(0,rAct.GetIndex());
aStr.Erase(rAct.GetLen());
ImportText( rAct.GetPoint(), aStr, rAct );
}
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpAction& rAct)
{
Rectangle aRect(rAct.GetPoint(),rAct.GetBitmap().GetSizePixel());
aRect.Right()++; aRect.Bottom()++;
SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScaleAction& rAct)
{
Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
aRect.Right()++; aRect.Bottom()++;
SdrGrafObj* pGraf=new SdrGrafObj(Graphic(rAct.GetBitmap()),aRect);
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExAction& rAct)
{
Rectangle aRect(rAct.GetPoint(),rAct.GetBitmapEx().GetSizePixel());
aRect.Right()++; aRect.Bottom()++;
SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScaleAction& rAct)
{
Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
aRect.Right()++; aRect.Bottom()++;
SdrGrafObj* pGraf=new SdrGrafObj( rAct.GetBitmapEx(), aRect );
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ImpSdrGDIMetaFileImport::DoAction( MetaHatchAction& rAct )
{
// #i73407# reformulation to use new B2DPolygon classes
basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
if(aSource.count())
{
const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
aSource.transform(aTransform);
if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
{
const Hatch& rHatch = rAct.GetHatch();
SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
SfxItemSet aHatchAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLHATCH, XATTR_FILLHATCH, 0, 0);
XHatchStyle eStyle;
switch(rHatch.GetStyle())
{
case(HATCH_TRIPLE) :
{
eStyle = XHATCH_TRIPLE;
break;
}
case(HATCH_DOUBLE) :
{
eStyle = XHATCH_DOUBLE;
break;
}
default:
{
eStyle = XHATCH_SINGLE;
break;
}
}
SetAttributes(pPath);
aHatchAttr.Put(XFillStyleItem(XFILL_HATCH));
aHatchAttr.Put(XFillHatchItem(&mpModel->GetItemPool(), XHatch(rHatch.GetColor(), eStyle, rHatch.GetDistance(), rHatch.GetAngle())));
pPath->SetMergedItemSet(aHatchAttr);
InsertObj(pPath, false);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ImpSdrGDIMetaFileImport::DoAction(MetaLineColorAction& rAct)
{
rAct.Execute(&maVD);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaMapModeAction& rAct)
{
MapScaling();
rAct.Execute(&maVD);
mbLastObjWasPolyWithoutLine = false;
mbLastObjWasLine = false;
}
void ImpSdrGDIMetaFileImport::MapScaling()
{
const sal_uInt32 nAnz(maTmpList.size());
sal_uInt32 i(0);
const MapMode& rMap = maVD.GetMapMode();
Point aMapOrg( rMap.GetOrigin() );
bool bMov2(aMapOrg.X() != 0 || aMapOrg.Y() != 0);
if(bMov2)
{
for(i = mnMapScalingOfs; i < nAnz; i++)
{
SdrObject* pObj = maTmpList[i];
pObj->NbcMove(Size(aMapOrg.X(), aMapOrg.Y()));
}
}
mnMapScalingOfs = nAnz;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ImpSdrGDIMetaFileImport::DoAction( MetaCommentAction& rAct, GDIMetaFile* pMtf )
{
ByteString aSkipComment;
if( rAct.GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
{
MetaGradientExAction* pAct = (MetaGradientExAction*) pMtf->NextAction();
if( pAct && pAct->GetType() == META_GRADIENTEX_ACTION )
{
// #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();
SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
SfxItemSet aGradAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
XGradient aXGradient;
aXGradient.SetGradientStyle((XGradientStyle)rGrad.GetStyle());
aXGradient.SetStartColor(rGrad.GetStartColor());
aXGradient.SetEndColor(rGrad.GetEndColor());
aXGradient.SetAngle((sal_uInt16)rGrad.GetAngle());
aXGradient.SetBorder(rGrad.GetBorder());
aXGradient.SetXOffset(rGrad.GetOfsX());
aXGradient.SetYOffset(rGrad.GetOfsY());
aXGradient.SetStartIntens(rGrad.GetStartIntensity());
aXGradient.SetEndIntens(rGrad.GetEndIntensity());
aXGradient.SetSteps(rGrad.GetSteps());
// no need to use SetAttributes(..) here since line and fill style
// need to be set individually
// SetAttributes(pPath);
// switch line off; when there was one there will be a
// META_POLYLINE_ACTION following creating another object
aGradAttr.Put(XLineStyleItem(XLINE_NONE));
// add detected gradient fillstyle
aGradAttr.Put(XFillStyleItem(XFILL_GRADIENT));
aGradAttr.Put(XFillGradientItem(&mpModel->GetItemPool(), aXGradient));
pPath->SetMergedItemSet(aGradAttr);
InsertObj(pPath);
}
}
aSkipComment = "XGRAD_SEQ_END";
}
}
if(aSkipComment.Len())
{
MetaAction* pSkipAct = pMtf->NextAction();
while( pSkipAct
&& ((pSkipAct->GetType() != META_COMMENT_ACTION )
|| (((MetaCommentAction*)pSkipAct)->GetComment().CompareIgnoreCaseToAscii(aSkipComment.GetBuffer()) != COMPARE_EQUAL)))
{
pSkipAct = pMtf->NextAction();
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ImpSdrGDIMetaFileImport::DoAction(MetaTextRectAction& rAct)
{
GDIMetaFile aTemp;
maVD.AddTextRectActions(rAct.GetRect(), rAct.GetText(), rAct.GetStyle(), aTemp);
DoLoopActions(aTemp, 0, 0);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpScalePartAction& rAct)
{
Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
Bitmap aBitmap(rAct.GetBitmap());
aRect.Right()++;
aRect.Bottom()++;
aBitmap.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
SdrGrafObj* pGraf = new SdrGrafObj(aBitmap, aRect);
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaBmpExScalePartAction& rAct)
{
Rectangle aRect(rAct.GetDestPoint(),rAct.GetDestSize());
BitmapEx aBitmapEx(rAct.GetBitmapEx());
aRect.Right()++;
aRect.Bottom()++;
aBitmapEx.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskAction& rAct)
{
Rectangle aRect(rAct.GetPoint(), rAct.GetBitmap().GetSizePixel());
BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
aRect.Right()++; aRect.Bottom()++;
SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScaleAction& rAct)
{
Rectangle aRect(rAct.GetPoint(), rAct.GetSize());
BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
aRect.Right()++; aRect.Bottom()++;
SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
void ImpSdrGDIMetaFileImport::DoAction(MetaMaskScalePartAction& rAct)
{
Rectangle aRect(rAct.GetDestPoint(), rAct.GetDestSize());
BitmapEx aBitmapEx(rAct.GetBitmap(), rAct.GetColor());
aRect.Right()++; aRect.Bottom()++;
aBitmapEx.Crop(Rectangle(rAct.GetSrcPoint(), rAct.GetSrcSize()));
SdrGrafObj* pGraf = new SdrGrafObj(aBitmapEx, aRect);
// This action is not creating line and fill, set directly, do not use SetAttributes(..)
pGraf->SetMergedItem(XLineStyleItem(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
XGradientStyle getXGradientStyleFromGradientStyle(const GradientStyle& rGradientStyle)
{
XGradientStyle aXGradientStyle(XGRAD_LINEAR);
switch(rGradientStyle)
{
case GRADIENT_LINEAR: aXGradientStyle = XGRAD_LINEAR; break;
case GRADIENT_AXIAL: aXGradientStyle = XGRAD_AXIAL; break;
case GRADIENT_RADIAL: aXGradientStyle = XGRAD_RADIAL; break;
case GRADIENT_ELLIPTICAL: aXGradientStyle = XGRAD_ELLIPTICAL; break;
case GRADIENT_SQUARE: aXGradientStyle = XGRAD_SQUARE; break;
case GRADIENT_RECT: aXGradientStyle = XGRAD_RECT; break;
// Needed due to GRADIENT_FORCE_EQUAL_SIZE; this again is needed
// to force the enum defines in VCL to a defined size for the compilers,
// so despite it is never used it cannot be removed (would break the
// API implementation probably).
default: break;
}
return aXGradientStyle;
}
void ImpSdrGDIMetaFileImport::DoAction(MetaGradientAction& rAct)
{
basegfx::B2DRange aRange(rAct.GetRect().Left(), rAct.GetRect().Top(), rAct.GetRect().Right(), rAct.GetRect().Bottom());
if(!aRange.isEmpty())
{
const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
aRange.transform(aTransform);
const Gradient& rGradient = rAct.GetGradient();
SdrRectObj* pRect = new SdrRectObj(
Rectangle(
floor(aRange.getMinX()),
floor(aRange.getMinY()),
ceil(aRange.getMaxX()),
ceil(aRange.getMaxY())));
SfxItemSet aGradientAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
const XGradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
const XFillGradientItem aXFillGradientItem(
&mpModel->GetItemPool(),
XGradient(
rGradient.GetStartColor(),
rGradient.GetEndColor(),
aXGradientStyle,
rGradient.GetAngle(),
rGradient.GetOfsX(),
rGradient.GetOfsY(),
rGradient.GetBorder(),
rGradient.GetStartIntensity(),
rGradient.GetEndIntensity(),
rGradient.GetSteps()));
SetAttributes(pRect);
aGradientAttr.Put(XFillStyleItem(XFILL_HATCH));
aGradientAttr.Put(aXFillGradientItem);
pRect->SetMergedItemSet(aGradientAttr);
InsertObj(pRect, false);
}
}
void ImpSdrGDIMetaFileImport::DoAction(MetaWallpaperAction& /*rAct*/)
{
OSL_ENSURE(false, "Tried to construct SdrObject from MetaWallpaperAction: not supported (!)");
}
void ImpSdrGDIMetaFileImport::DoAction(MetaTransparentAction& rAct)
{
basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
if(aSource.count())
{
const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
aSource.transform(aTransform);
aSource.setClosed(true);
SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
SetAttributes(pPath);
pPath->SetMergedItem(XFillTransparenceItem(rAct.GetTransparence()));
InsertObj(pPath, false);
}
}
void ImpSdrGDIMetaFileImport::DoAction(MetaEPSAction& /*rAct*/)
{
OSL_ENSURE(false, "Tried to construct SdrObject from MetaEPSAction: not supported (!)");
}
void ImpSdrGDIMetaFileImport::DoAction(MetaTextLineAction& /*rAct*/)
{
OSL_ENSURE(false, "Tried to construct SdrObject from MetaTextLineAction: not supported (!)");
}
void ImpSdrGDIMetaFileImport::DoAction(MetaGradientExAction& rAct)
{
basegfx::B2DPolyPolygon aSource(rAct.GetPolyPolygon().getB2DPolyPolygon());
if(aSource.count())
{
const basegfx::B2DHomMatrix aTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(mfScaleX, mfScaleY, maOfs.X(), maOfs.Y()));
aSource.transform(aTransform);
if(!mbLastObjWasPolyWithoutLine || !CheckLastPolyLineAndFillMerge(aSource))
{
const Gradient& rGradient = rAct.GetGradient();
SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
SfxItemSet aGradientAttr(mpModel->GetItemPool(), XATTR_FILLSTYLE, XATTR_FILLSTYLE, XATTR_FILLGRADIENT, XATTR_FILLGRADIENT, 0, 0);
const XGradientStyle aXGradientStyle(getXGradientStyleFromGradientStyle(rGradient.GetStyle()));
const XFillGradientItem aXFillGradientItem(
&mpModel->GetItemPool(),
XGradient(
rGradient.GetStartColor(),
rGradient.GetEndColor(),
aXGradientStyle,
rGradient.GetAngle(),
rGradient.GetOfsX(),
rGradient.GetOfsY(),
rGradient.GetBorder(),
rGradient.GetStartIntensity(),
rGradient.GetEndIntensity(),
rGradient.GetSteps()));
SetAttributes(pPath);
aGradientAttr.Put(XFillStyleItem(XFILL_HATCH));
aGradientAttr.Put(aXFillGradientItem);
pPath->SetMergedItemSet(aGradientAttr);
InsertObj(pPath, false);
}
}
}
void ImpSdrGDIMetaFileImport::DoAction(MetaFloatTransparentAction& rAct)
{
const GDIMetaFile& rMtf = rAct.GetGDIMetaFile();
if(rMtf.GetActionCount())
{
const Rectangle aRect(rAct.GetPoint(),rAct.GetSize());
Rectangle aHairline;
const Rectangle aBoundRect(rMtf.GetBoundRect(*Application::GetDefaultDevice(), &aHairline));
// convert metafile sub-content to BitmapEx
BitmapEx aBitmapEx(
convertMetafileToBitmapEx(
rMtf,
basegfx::B2DRange(
aRect.Left(), aRect.Top(),
aRect.Right(), aRect.Bottom()),
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 *= (double)rGradient.GetStartIntensity() / 100.0;
}
if(100 != rGradient.GetEndIntensity())
{
aEnd *= (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(basegfx::fTools::lessOrEqual(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
VirtualDevice aVDev;
aVDev.SetOutputSizePixel(aBitmapEx.GetBitmap().GetSizePixel());
aVDev.DrawGradient(Rectangle(Point(0, 0), aVDev.GetOutputSizePixel()), rGradient);
aNewMask = AlphaMask(aVDev.GetBitmap(Point(0, 0), aVDev.GetOutputSizePixel()));
bHasNewMask = true;
}
if(bCreateObject)
{
if(bHasNewMask || bFixedTransparence)
{
if(!aBitmapEx.IsAlpha() && !aBitmapEx.IsTransparent())
{
// no transparence yet, apply new one
if(bFixedTransparence)
{
sal_uInt8 aAlpha(basegfx::fround(fTransparence * 255.0));
aNewMask = AlphaMask(aBitmapEx.GetBitmap().GetSizePixel(), &aAlpha);
}
aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aNewMask);
}
else
{
// mix existing and new alpha mask
AlphaMask aOldMask;
if(aBitmapEx.IsAlpha())
{
aOldMask = aBitmapEx.GetAlpha();
}
else if(TRANSPARENT_BITMAP == aBitmapEx.GetTransparentType())
{
aOldMask = aBitmapEx.GetMask();
}
else if(TRANSPARENT_COLOR == aBitmapEx.GetTransparentType())
{
aOldMask = aBitmapEx.GetBitmap().CreateMask(aBitmapEx.GetTransparentColor());
}
BitmapWriteAccess* pOld = aOldMask.AcquireWriteAccess();
if(pOld)
{
const double fFactor(1.0 / 255.0);
if(bFixedTransparence)
{
const double fOpNew(1.0 - fTransparence);
for(sal_uInt32 y(0); y < static_cast< sal_uInt32 >(pOld->Height()); y++)
{
for(sal_uInt32 x(0); x < static_cast< sal_uInt32 >(pOld->Width()); x++)
{
const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
pOld->SetPixel(y, x, BitmapColor(aCol));
}
}
}
else
{
BitmapReadAccess* pNew = aNewMask.AcquireReadAccess();
if(pNew)
{
if(pOld->Width() == pNew->Width() && pOld->Height() == pNew->Height())
{
for(sal_uInt32 y(0); y < static_cast< sal_uInt32 >(pOld->Height()); y++)
{
for(sal_uInt32 x(0); x < static_cast< sal_uInt32 >(pOld->Width()); x++)
{
const double fOpOld(1.0 - (pOld->GetPixel(y, x).GetIndex() * fFactor));
const double fOpNew(1.0 - (pNew->GetPixel(y, x).GetIndex() * fFactor));
const sal_uInt8 aCol(basegfx::fround((1.0 - (fOpOld * fOpNew)) * 255.0));
pOld->SetPixel(y, x, BitmapColor(aCol));
}
}
}
else
{
OSL_ENSURE(false, "Alpha masks have different sizes (!)");
}
aNewMask.ReleaseAccess(pNew);
}
else
{
OSL_ENSURE(false, "Got no access to new alpha mask (!)");
}
}
aOldMask.ReleaseAccess(pOld);
}
else
{
OSL_ENSURE(false, "Got no access to old alpha mask (!)");
}
// apply combined bitmap as mask
aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aOldMask);
}
}
// create and add object
SdrGrafObj* pGraf = new SdrGrafObj(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(XLINE_NONE));
pGraf->SetMergedItem(XFillStyleItem(XFILL_NONE));
InsertObj(pGraf);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// eof