Kaydet (Commit) c466b30a authored tarafından Armin Le Grand's avatar Armin Le Grand

#119125# Added usage of the ClipRegion for the dismantle of Metafile to…

#119125# Added usage of the ClipRegion for the dismantle of Metafile to SdrObjects (ImpSdrGDIMetaFileImport) as good as possible with Metafile usage
üst c6e27ea3
......@@ -68,6 +68,8 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <svx/xlinjoit.hxx>
#include <svx/xlndsit.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <svx/xbtmpit.hxx>
////////////////////////////////////////////////////////////////////////////////////////////////////
......@@ -80,7 +82,11 @@ ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel):
maLineCap(com::sun::star::drawing::LineCap_BUTT),
maDash(XDASH_RECT, 0, 0, 0, 0, 0),
bFntDirty(sal_True),
bLastObjWasPolyWithoutLine(sal_False),bNoLine(sal_False),bNoFill(sal_False),bLastObjWasLine(sal_False)
bLastObjWasPolyWithoutLine(sal_False),
bNoLine(sal_False),
bNoFill(sal_False),
bLastObjWasLine(sal_False),
maClip()
{
aVD.EnableOutput(sal_False);
......@@ -93,6 +99,7 @@ ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel):
pFillAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST);
pTextAttr=new SfxItemSet(rModel.GetItemPool(),EE_ITEMS_START,EE_ITEMS_END);
pModel=&rModel;
checkClip();
}
ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport()
......@@ -378,7 +385,7 @@ void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, FASTBOOL bForceText
}
}
void ImpSdrGDIMetaFileImport::InsertObj( SdrObject* pObj, sal_Bool bScale )
void ImpSdrGDIMetaFileImport::InsertObj(SdrObject* pObj, sal_Bool bScale)
{
if ( bScale && !aScaleRect.IsEmpty() )
{
......@@ -388,60 +395,123 @@ void ImpSdrGDIMetaFileImport::InsertObj( SdrObject* pObj, sal_Bool bScale )
pObj->NbcMove( Size( aOfs.X(), aOfs.Y() ) );
}
// #i111954# check object for visibility
// used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
bool bVisible(false);
if(pObj->HasLineStyle())
if(isClip())
{
bVisible = true;
}
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);
BitmapEx aBitmapEx;
if(pSdrGrafObj)
{
aBitmapEx = pSdrGrafObj->GetGraphic().GetBitmapEx();
}
if(!bVisible && pObj->HasFillStyle())
{
bVisible = true;
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 BitmapEx aClippedBitmap(
aBitmapEx,
Point(floor(std::max(0.0, aPixel.getMinX())), floor(std::max(0.0, aPixel.getMinY()))),
Size(ceil(aPixel.getWidth()), ceil(aPixel.getHeight())));
pObj->SetMergedItem(XFillStyleItem(XFILL_BITMAP));
pObj->SetMergedItem(XFillBitmapItem(String(), aClippedBitmap.GetBitmap()));
}
}
}
}
if(!bVisible)
if(pObj)
{
SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >(pObj);
// #i111954# check object for visibility
// used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
bool bVisible(false);
if(pTextObj && pTextObj->HasText())
if(pObj->HasLineStyle())
{
bVisible = true;
}
}
if(!bVisible)
{
SdrGrafObj* pGrafObj = dynamic_cast< SdrGrafObj* >(pObj);
if(pGrafObj)
if(!bVisible && pObj->HasFillStyle())
{
// 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
{
aTmpList.InsertObject( pObj );
if ( HAS_BASE( SdrPathObj, pObj ) )
if(!bVisible)
{
FASTBOOL bClosed=pObj->IsClosedObj();
bLastObjWasPolyWithoutLine=bNoLine && bClosed;
bLastObjWasLine=!bClosed;
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
{
bLastObjWasPolyWithoutLine = sal_False;
bLastObjWasLine = sal_False;
aTmpList.InsertObject( pObj );
if ( HAS_BASE( SdrPathObj, pObj ) )
{
FASTBOOL bClosed=pObj->IsClosedObj();
bLastObjWasPolyWithoutLine=bNoLine && bClosed;
bLastObjWasLine=!bClosed;
}
else
{
bLastObjWasPolyWithoutLine = sal_False;
bLastObjWasLine = sal_False;
}
}
}
}
......@@ -659,6 +729,32 @@ bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPo
return false;
}
void ImpSdrGDIMetaFileImport::checkClip()
{
if(aVD.IsClipRegion())
{
Region aRegion(aVD.GetClipRegion());
maClip = aRegion.ConvertToB2DPolyPolygon();
if(isClip())
{
const basegfx::B2DHomMatrix aTransform(
basegfx::tools::createScaleTranslateB2DHomMatrix(
fScaleX,
fScaleY,
aOfs.X(),
aOfs.Y()));
maClip.transform(aTransform);
}
}
}
bool ImpSdrGDIMetaFileImport::isClip() const
{
return !maClip.getB2DRange().isEmpty();
}
void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct )
{
......@@ -718,7 +814,6 @@ void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct )
{
// #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);
......@@ -740,7 +835,6 @@ void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct)
{
// #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);
......
......@@ -101,7 +101,15 @@ protected:
// fuer Optimierung mehrerer Linien zu einer Polyline
sal_Bool bLastObjWasLine;
// clipregion
basegfx::B2DPolyPolygon maClip;
protected:
// ckeck for clip and evtl. fill maClip
void checkClip();
bool isClip() const;
// actions
void DoAction(MetaPixelAction & rAct);
void DoAction(MetaPointAction & rAct);
void DoAction(MetaLineAction & rAct);
......@@ -129,13 +137,13 @@ protected:
void DoAction(MetaTextFillColorAction & rAct) { rAct.Execute(&aVD); }
void DoAction(MetaFontAction & rAct) { rAct.Execute(&aVD); bFntDirty=sal_True; }
void DoAction(MetaTextAlignAction & rAct) { rAct.Execute(&aVD); bFntDirty=sal_True; }
void DoAction(MetaClipRegionAction & rAct) { rAct.Execute(&aVD); }
void DoAction(MetaClipRegionAction & rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaRasterOpAction & rAct) { rAct.Execute(&aVD); }
void DoAction(MetaPushAction & rAct) { rAct.Execute(&aVD); }
void DoAction(MetaPopAction & rAct) { rAct.Execute(&aVD); bFntDirty=sal_True; }
void DoAction(MetaMoveClipRegionAction & rAct) { rAct.Execute(&aVD); }
void DoAction(MetaISectRectClipRegionAction& rAct) { rAct.Execute(&aVD); }
void DoAction(MetaISectRegionClipRegionAction& rAct) { rAct.Execute(&aVD); }
void DoAction(MetaPushAction & rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaPopAction & rAct) { rAct.Execute(&aVD); bFntDirty=sal_True; checkClip(); }
void DoAction(MetaMoveClipRegionAction & rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaISectRectClipRegionAction& rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaISectRegionClipRegionAction& rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaCommentAction& rAct, GDIMetaFile* pMtf);
void ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct );
......
......@@ -614,27 +614,27 @@ GDIMetaFile SdrExchangeView::GetMarkedObjMetaFile(bool bNoVDevIfOneMtfMarked) co
if( !aMtf.GetActionCount() )
{
VirtualDevice aOut;
Size aDummySize( 2, 2 );
aOut.SetOutputSizePixel( aDummySize );
aOut.EnableOutput( sal_False );
aOut.SetMapMode( aMap );
VirtualDevice aOut;
const Size aDummySize(2, 2);
aOut.SetOutputSizePixel(aDummySize);
aOut.EnableOutput(false);
aOut.SetMapMode(aMap);
aMtf.Clear();
aMtf.Record( &aOut );
// Replace offset given formally to DrawMarkedObj and used at XOutDev with relative
// MapMode (which was also used in XOutDev in that case). Goal is to paint the object
// as if TopLeft point is (0,0)
const Fraction aNeutralFraction(1, 1);
const MapMode aRelativeMapMode(MAP_RELATIVE, Point(-aBound.Left(), -aBound.Top()), aNeutralFraction, aNeutralFraction);
aOut.SetMapMode(aRelativeMapMode);
aMtf.Record(&aOut);
DrawMarkedObj(aOut);
aMtf.Stop();
aMtf.WindStart();
// moving the result is more reliable then setting a relative MapMode at the VDev (used
// before), also see #i99268# in GetObjGraphic() below. Some draw actions at
// the OutDev are simply not handled correctly when a MapMode is set at the
// target devive, e.g. MetaFloatTransparentAction. Even the Move for this action
// was missing the manipulation of the embedded Metafile
aMtf.Move(-aBound.Left(), -aBound.Top());
aMtf.SetPrefMapMode( aMap );
// removed PrefSize extension. It is principially wrong to set a reduced size at
......@@ -718,8 +718,8 @@ Graphic SdrExchangeView::GetObjGraphic( const SdrModel* pModel, const SdrObject*
// #i99268# replace the original offset from using XOutDev's SetOffset
// NOT (as tried with #i92760#) with another MapMode which gets recorded
// by the Metafile itself (what always leads to problems), but by hardly
// moving the result
// by the Metafile itself (what always leads to problems), but by
// moving the result directly
aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top());
aMtf.SetPrefMapMode( aMap );
......
......@@ -3816,6 +3816,9 @@ MetaAction* MetaFloatTransparentAction::Clone()
void MetaFloatTransparentAction::Move( long nHorzMove, long nVertMove )
{
maPoint.Move( nHorzMove, nVertMove );
// also neeed to move the content metafile
maMtf.Move( nHorzMove, nVertMove );
}
// ------------------------------------------------------------------------
......
......@@ -634,7 +634,10 @@ void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
const Color aBlack( COL_BLACK );
if( mpMetaFile )
{
// missing here is to map the data using the DeviceTransformation
mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
}
if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) )
......
......@@ -1658,10 +1658,17 @@ Region OutputDevice::PixelToLogic( const Region& rDeviceRegion ) const
return rDeviceRegion;
Region aRegion;
PolyPolygon* pPolyPoly = rDeviceRegion.ImplGetImplRegion()->mpPolyPoly;
basegfx::B2DPolyPolygon* pB2DPolyPoly = rDeviceRegion.ImplGetImplRegion()->mpB2DPolyPoly;
PolyPolygon* pPolyPoly = pB2DPolyPoly ? 0 : rDeviceRegion.ImplGetImplRegion()->mpPolyPoly;
if ( pPolyPoly )
if ( pB2DPolyPoly ) // conversion with B2DPolyPolygon lost polygon-based ClipRegion
{
aRegion = Region( PixelToLogic( *pB2DPolyPoly ) );
}
else if ( pPolyPoly )
{
aRegion = Region( PixelToLogic( *pPolyPoly ) );
}
else
{
long nX;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment