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 @@ ...@@ -68,6 +68,8 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <svx/xlinjoit.hxx> #include <svx/xlinjoit.hxx>
#include <svx/xlndsit.hxx> #include <svx/xlndsit.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <svx/xbtmpit.hxx>
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
...@@ -80,7 +82,11 @@ ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel): ...@@ -80,7 +82,11 @@ ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel):
maLineCap(com::sun::star::drawing::LineCap_BUTT), maLineCap(com::sun::star::drawing::LineCap_BUTT),
maDash(XDASH_RECT, 0, 0, 0, 0, 0), maDash(XDASH_RECT, 0, 0, 0, 0, 0),
bFntDirty(sal_True), 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); aVD.EnableOutput(sal_False);
...@@ -93,6 +99,7 @@ ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel): ...@@ -93,6 +99,7 @@ ImpSdrGDIMetaFileImport::ImpSdrGDIMetaFileImport(SdrModel& rModel):
pFillAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST); pFillAttr=new SfxItemSet(rModel.GetItemPool(),XATTR_FILL_FIRST,XATTR_FILL_LAST);
pTextAttr=new SfxItemSet(rModel.GetItemPool(),EE_ITEMS_START,EE_ITEMS_END); pTextAttr=new SfxItemSet(rModel.GetItemPool(),EE_ITEMS_START,EE_ITEMS_END);
pModel=&rModel; pModel=&rModel;
checkClip();
} }
ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport() ImpSdrGDIMetaFileImport::~ImpSdrGDIMetaFileImport()
...@@ -378,7 +385,7 @@ void ImpSdrGDIMetaFileImport::SetAttributes(SdrObject* pObj, FASTBOOL bForceText ...@@ -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() ) if ( bScale && !aScaleRect.IsEmpty() )
{ {
...@@ -388,60 +395,123 @@ void ImpSdrGDIMetaFileImport::InsertObj( SdrObject* pObj, sal_Bool bScale ) ...@@ -388,60 +395,123 @@ void ImpSdrGDIMetaFileImport::InsertObj( SdrObject* pObj, sal_Bool bScale )
pObj->NbcMove( Size( aOfs.X(), aOfs.Y() ) ); pObj->NbcMove( Size( aOfs.X(), aOfs.Y() ) );
} }
// #i111954# check object for visibility if(isClip())
// used are SdrPathObj, SdrRectObj, SdrCircObj, SdrGrafObj
bool bVisible(false);
if(pObj->HasLineStyle())
{ {
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()) SdrObject::Free(pObj);
{
bVisible = true; 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; 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; bVisible = true;
} }
}
if(!bVisible) if(!bVisible)
{
SdrObject::Free(pObj);
}
else
{
aTmpList.InsertObject( pObj );
if ( HAS_BASE( SdrPathObj, pObj ) )
{ {
FASTBOOL bClosed=pObj->IsClosedObj(); SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >(pObj);
bLastObjWasPolyWithoutLine=bNoLine && bClosed;
bLastObjWasLine=!bClosed; 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 else
{ {
bLastObjWasPolyWithoutLine = sal_False; aTmpList.InsertObject( pObj );
bLastObjWasLine = sal_False; 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 ...@@ -659,6 +729,32 @@ bool ImpSdrGDIMetaFileImport::CheckLastPolyLineAndFillMerge(const basegfx::B2DPo
return false; 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 ) void ImpSdrGDIMetaFileImport::DoAction( MetaPolyLineAction& rAct )
{ {
...@@ -718,7 +814,6 @@ void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct ) ...@@ -718,7 +814,6 @@ void ImpSdrGDIMetaFileImport::DoAction( MetaPolygonAction& rAct )
{ {
// #i73407# make sure polygon is closed, it's a filled primitive // #i73407# make sure polygon is closed, it's a filled primitive
aSource.setClosed(true); aSource.setClosed(true);
SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource)); SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, basegfx::B2DPolyPolygon(aSource));
SetAttributes(pPath); SetAttributes(pPath);
InsertObj(pPath, false); InsertObj(pPath, false);
...@@ -740,7 +835,6 @@ void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct) ...@@ -740,7 +835,6 @@ void ImpSdrGDIMetaFileImport::DoAction(MetaPolyPolygonAction& rAct)
{ {
// #i73407# make sure polygon is closed, it's a filled primitive // #i73407# make sure polygon is closed, it's a filled primitive
aSource.setClosed(true); aSource.setClosed(true);
SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource); SdrPathObj* pPath = new SdrPathObj(OBJ_POLY, aSource);
SetAttributes(pPath); SetAttributes(pPath);
InsertObj(pPath, false); InsertObj(pPath, false);
......
...@@ -101,7 +101,15 @@ protected: ...@@ -101,7 +101,15 @@ protected:
// fuer Optimierung mehrerer Linien zu einer Polyline // fuer Optimierung mehrerer Linien zu einer Polyline
sal_Bool bLastObjWasLine; sal_Bool bLastObjWasLine;
// clipregion
basegfx::B2DPolyPolygon maClip;
protected: protected:
// ckeck for clip and evtl. fill maClip
void checkClip();
bool isClip() const;
// actions
void DoAction(MetaPixelAction & rAct); void DoAction(MetaPixelAction & rAct);
void DoAction(MetaPointAction & rAct); void DoAction(MetaPointAction & rAct);
void DoAction(MetaLineAction & rAct); void DoAction(MetaLineAction & rAct);
...@@ -129,13 +137,13 @@ protected: ...@@ -129,13 +137,13 @@ protected:
void DoAction(MetaTextFillColorAction & rAct) { rAct.Execute(&aVD); } void DoAction(MetaTextFillColorAction & rAct) { rAct.Execute(&aVD); }
void DoAction(MetaFontAction & rAct) { rAct.Execute(&aVD); bFntDirty=sal_True; } void DoAction(MetaFontAction & rAct) { rAct.Execute(&aVD); bFntDirty=sal_True; }
void DoAction(MetaTextAlignAction & 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(MetaRasterOpAction & rAct) { rAct.Execute(&aVD); }
void DoAction(MetaPushAction & rAct) { rAct.Execute(&aVD); } void DoAction(MetaPushAction & rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaPopAction & rAct) { rAct.Execute(&aVD); bFntDirty=sal_True; } void DoAction(MetaPopAction & rAct) { rAct.Execute(&aVD); bFntDirty=sal_True; checkClip(); }
void DoAction(MetaMoveClipRegionAction & rAct) { rAct.Execute(&aVD); } void DoAction(MetaMoveClipRegionAction & rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaISectRectClipRegionAction& rAct) { rAct.Execute(&aVD); } void DoAction(MetaISectRectClipRegionAction& rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaISectRegionClipRegionAction& rAct) { rAct.Execute(&aVD); } void DoAction(MetaISectRegionClipRegionAction& rAct) { rAct.Execute(&aVD); checkClip(); }
void DoAction(MetaCommentAction& rAct, GDIMetaFile* pMtf); void DoAction(MetaCommentAction& rAct, GDIMetaFile* pMtf);
void ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct ); void ImportText( const Point& rPos, const XubString& rStr, const MetaAction& rAct );
......
...@@ -614,27 +614,27 @@ GDIMetaFile SdrExchangeView::GetMarkedObjMetaFile(bool bNoVDevIfOneMtfMarked) co ...@@ -614,27 +614,27 @@ GDIMetaFile SdrExchangeView::GetMarkedObjMetaFile(bool bNoVDevIfOneMtfMarked) co
if( !aMtf.GetActionCount() ) if( !aMtf.GetActionCount() )
{ {
VirtualDevice aOut; VirtualDevice aOut;
Size aDummySize( 2, 2 ); const Size aDummySize(2, 2);
aOut.SetOutputSizePixel( aDummySize );
aOut.EnableOutput( sal_False );
aOut.SetMapMode( aMap );
aOut.SetOutputSizePixel(aDummySize);
aOut.EnableOutput(false);
aOut.SetMapMode(aMap);
aMtf.Clear(); aMtf.Clear();
aMtf.Record( &aOut ); 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);
DrawMarkedObj(aOut); DrawMarkedObj(aOut);
aMtf.Stop(); aMtf.Stop();
aMtf.WindStart(); 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 ); aMtf.SetPrefMapMode( aMap );
// removed PrefSize extension. It is principially wrong to set a reduced size at // 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* ...@@ -718,8 +718,8 @@ Graphic SdrExchangeView::GetObjGraphic( const SdrModel* pModel, const SdrObject*
// #i99268# replace the original offset from using XOutDev's SetOffset // #i99268# replace the original offset from using XOutDev's SetOffset
// NOT (as tried with #i92760#) with another MapMode which gets recorded // NOT (as tried with #i92760#) with another MapMode which gets recorded
// by the Metafile itself (what always leads to problems), but by hardly // by the Metafile itself (what always leads to problems), but by
// moving the result // moving the result directly
aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top()); aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top());
aMtf.SetPrefMapMode( aMap ); aMtf.SetPrefMapMode( aMap );
......
...@@ -3816,6 +3816,9 @@ MetaAction* MetaFloatTransparentAction::Clone() ...@@ -3816,6 +3816,9 @@ MetaAction* MetaFloatTransparentAction::Clone()
void MetaFloatTransparentAction::Move( long nHorzMove, long nVertMove ) void MetaFloatTransparentAction::Move( long nHorzMove, long nVertMove )
{ {
maPoint.Move( nHorzMove, 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, ...@@ -634,7 +634,10 @@ void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos,
const Color aBlack( COL_BLACK ); const Color aBlack( COL_BLACK );
if( mpMetaFile ) if( mpMetaFile )
{
// missing here is to map the data using the DeviceTransformation
mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) ); mpMetaFile->AddAction( new MetaFloatTransparentAction( rMtf, rPos, rSize, rTransparenceGradient ) );
}
if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) || if( ( rTransparenceGradient.GetStartColor() == aBlack && rTransparenceGradient.GetEndColor() == aBlack ) ||
( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) ) ( mnDrawMode & ( DRAWMODE_NOTRANSPARENCY ) ) )
......
...@@ -1658,10 +1658,17 @@ Region OutputDevice::PixelToLogic( const Region& rDeviceRegion ) const ...@@ -1658,10 +1658,17 @@ Region OutputDevice::PixelToLogic( const Region& rDeviceRegion ) const
return rDeviceRegion; return rDeviceRegion;
Region aRegion; 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 ) ); aRegion = Region( PixelToLogic( *pPolyPoly ) );
}
else else
{ {
long nX; 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