[Libreoffice-commits] core.git: drawinglayer/source solenv/clang-format
Tomaž Vajngerl (via logerrit)
logerrit at kemper.freedesktop.org
Sat May 9 19:09:18 UTC 2020
drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx | 3872 ++++++-------
drawinglayer/source/processor2d/vclmetafileprocessor2d.hxx | 309 -
solenv/clang-format/blacklist | 2
3 files changed, 2113 insertions(+), 2070 deletions(-)
New commits:
commit 9e2a9f4151babc6cb22553798ee70f7f623924db
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Tue May 5 23:20:38 2020 +0200
Commit: Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sat May 9 21:08:28 2020 +0200
remove vclmetafileprocessor2d.{cxx,hxx} from clang-format blacklist
Change-Id: I53f7660a22ed66ab7d50370d871f9d10d1bedc10
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93825
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index d853820abbdc..231bf8bc9259 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -76,2215 +76,2241 @@ using namespace com::sun::star;
// To be on the safe side with the old tools polygon, use slightly less than
// the theoretical maximum (bad experiences with tools polygon)
-#define MAX_POLYGON_POINT_COUNT_METAFILE (0x0000fff0)
+#define MAX_POLYGON_POINT_COUNT_METAFILE (0x0000fff0)
namespace
{
- // #112245# helper to split line polygon in half
- void splitLinePolygon(
- const basegfx::B2DPolygon& rBasePolygon,
- basegfx::B2DPolygon& o_aLeft,
- basegfx::B2DPolygon& o_aRight)
+// #112245# helper to split line polygon in half
+void splitLinePolygon(const basegfx::B2DPolygon& rBasePolygon, basegfx::B2DPolygon& o_aLeft,
+ basegfx::B2DPolygon& o_aRight)
+{
+ const sal_uInt32 nCount(rBasePolygon.count());
+
+ if (nCount)
{
- const sal_uInt32 nCount(rBasePolygon.count());
+ const sal_uInt32 nHalfCount((nCount - 1) >> 1);
- if(nCount)
- {
- const sal_uInt32 nHalfCount((nCount - 1) >> 1);
+ o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1);
+ o_aLeft.setClosed(false);
- o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1);
- o_aLeft.setClosed(false);
+ o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount);
+ o_aRight.setClosed(false);
- o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount);
- o_aRight.setClosed(false);
+ if (rBasePolygon.isClosed())
+ {
+ o_aRight.append(rBasePolygon.getB2DPoint(0));
- if(rBasePolygon.isClosed())
+ if (rBasePolygon.areControlPointsUsed())
{
- o_aRight.append(rBasePolygon.getB2DPoint(0));
-
- if(rBasePolygon.areControlPointsUsed())
- {
- o_aRight.setControlPoints(
- o_aRight.count() - 1,
- rBasePolygon.getPrevControlPoint(0),
- rBasePolygon.getNextControlPoint(0));
- }
+ o_aRight.setControlPoints(o_aRight.count() - 1, rBasePolygon.getPrevControlPoint(0),
+ rBasePolygon.getNextControlPoint(0));
}
}
- else
- {
- o_aLeft.clear();
- o_aRight.clear();
- }
}
-
- // #112245# helper to evtl. split filled polygons to maximum metafile point count
- void fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon)
+ else
{
- const sal_uInt32 nPolyCount(rPolyPolygon.count());
+ o_aLeft.clear();
+ o_aRight.clear();
+ }
+}
- if(!nPolyCount)
- return;
+// #112245# helper to evtl. split filled polygons to maximum metafile point count
+void fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon)
+{
+ const sal_uInt32 nPolyCount(rPolyPolygon.count());
- basegfx::B2DPolyPolygon aSplitted;
+ if (!nPolyCount)
+ return;
- for(sal_uInt32 a(0); a < nPolyCount; a++)
+ basegfx::B2DPolyPolygon aSplitted;
+
+ for (sal_uInt32 a(0); a < nPolyCount; a++)
+ {
+ const basegfx::B2DPolygon& aCandidate(rPolyPolygon.getB2DPolygon(a));
+ const sal_uInt32 nPointCount(aCandidate.count());
+ bool bNeedToSplit(false);
+
+ if (aCandidate.areControlPointsUsed())
+ {
+ // compare with the maximum for bezier curved polygons
+ bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1);
+ }
+ else
{
- const basegfx::B2DPolygon& aCandidate(rPolyPolygon.getB2DPolygon(a));
- const sal_uInt32 nPointCount(aCandidate.count());
- bool bNeedToSplit(false);
+ // compare with the maximum for simple point polygons
+ bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1);
+ }
- if(aCandidate.areControlPointsUsed())
- {
- // compare with the maximum for bezier curved polygons
- bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1);
- }
- else
- {
- // compare with the maximum for simple point polygons
- bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1);
- }
+ if (bNeedToSplit)
+ {
+ // need to split the partial polygon
+ const basegfx::B2DRange aRange(aCandidate.getB2DRange());
+ const basegfx::B2DPoint aCenter(aRange.getCenter());
- if(bNeedToSplit)
+ if (aRange.getWidth() > aRange.getHeight())
{
- // need to split the partial polygon
- const basegfx::B2DRange aRange(aCandidate.getB2DRange());
- const basegfx::B2DPoint aCenter(aRange.getCenter());
-
- if(aRange.getWidth() > aRange.getHeight())
- {
- // clip in left and right
- const basegfx::B2DPolyPolygon aLeft(
- basegfx::utils::clipPolygonOnParallelAxis(
- aCandidate,
- false,
- true,
- aCenter.getX(),
- false));
- const basegfx::B2DPolyPolygon aRight(
- basegfx::utils::clipPolygonOnParallelAxis(
- aCandidate,
- false,
- false,
- aCenter.getX(),
- false));
-
- aSplitted.append(aLeft);
- aSplitted.append(aRight);
- }
- else
- {
- // clip in top and bottom
- const basegfx::B2DPolyPolygon aTop(
- basegfx::utils::clipPolygonOnParallelAxis(
- aCandidate,
- true,
- true,
- aCenter.getY(),
- false));
- const basegfx::B2DPolyPolygon aBottom(
- basegfx::utils::clipPolygonOnParallelAxis(
- aCandidate,
- true,
- false,
- aCenter.getY(),
- false));
-
- aSplitted.append(aTop);
- aSplitted.append(aBottom);
- }
+ // clip in left and right
+ const basegfx::B2DPolyPolygon aLeft(basegfx::utils::clipPolygonOnParallelAxis(
+ aCandidate, false, true, aCenter.getX(), false));
+ const basegfx::B2DPolyPolygon aRight(basegfx::utils::clipPolygonOnParallelAxis(
+ aCandidate, false, false, aCenter.getX(), false));
+
+ aSplitted.append(aLeft);
+ aSplitted.append(aRight);
}
else
{
- aSplitted.append(aCandidate);
+ // clip in top and bottom
+ const basegfx::B2DPolyPolygon aTop(basegfx::utils::clipPolygonOnParallelAxis(
+ aCandidate, true, true, aCenter.getY(), false));
+ const basegfx::B2DPolyPolygon aBottom(basegfx::utils::clipPolygonOnParallelAxis(
+ aCandidate, true, false, aCenter.getY(), false));
+
+ aSplitted.append(aTop);
+ aSplitted.append(aBottom);
}
}
-
- if(aSplitted.count() != nPolyCount)
+ else
{
- rPolyPolygon = aSplitted;
+ aSplitted.append(aCandidate);
}
}
- /** Filter input polypolygon for effectively empty sub-fills
+ if (aSplitted.count() != nPolyCount)
+ {
+ rPolyPolygon = aSplitted;
+ }
+}
+
+/** Filter input polypolygon for effectively empty sub-fills
- Needed to fix fdo#37559
+ Needed to fix fdo#37559
- @param rPoly
- tools::PolyPolygon to filter
+ @param rPoly
+ tools::PolyPolygon to filter
- @return converted tools PolyPolygon, w/o one-point fills
- */
- ::tools::PolyPolygon getFillPolyPolygon( const ::basegfx::B2DPolyPolygon& rPoly )
+ @return converted tools PolyPolygon, w/o one-point fills
+ */
+tools::PolyPolygon getFillPolyPolygon(const ::basegfx::B2DPolyPolygon& rPoly)
+{
+ // filter input rPoly
+ basegfx::B2DPolyPolygon aPoly;
+ sal_uInt32 nCount(rPoly.count());
+ for (sal_uInt32 i = 0; i < nCount; ++i)
{
- // filter input rPoly
- basegfx::B2DPolyPolygon aPoly;
- sal_uInt32 nCount(rPoly.count());
- for( sal_uInt32 i=0; i<nCount; ++i )
- {
- const basegfx::B2DPolygon& aCandidate(rPoly.getB2DPolygon(i));
- if( !aCandidate.isClosed() || aCandidate.count() > 1 )
- aPoly.append(aCandidate);
- }
- return ::tools::PolyPolygon(aPoly);
+ const basegfx::B2DPolygon& aCandidate(rPoly.getB2DPolygon(i));
+ if (!aCandidate.isClosed() || aCandidate.count() > 1)
+ aPoly.append(aCandidate);
}
+ return tools::PolyPolygon(aPoly);
+}
} // end of anonymous namespace
namespace drawinglayer::processor2d
{
- ::tools::Rectangle VclMetafileProcessor2D::impDumpToMetaFile(
- const primitive2d::Primitive2DContainer& rContent,
- GDIMetaFile& o_rContentMetafile)
- {
- // Prepare VDev, MetaFile and connections
- OutputDevice* pLastOutputDevice = mpOutputDevice;
- GDIMetaFile* pLastMetafile = mpMetaFile;
- basegfx::B2DRange aPrimitiveRange(rContent.getB2DRange(getViewInformation2D()));
-
- // transform primitive range with current transformation (e.g shadow offset)
- aPrimitiveRange.transform(maCurrentTransformation);
-
- const ::tools::Rectangle aPrimitiveRectangle(
- basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()),
- basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY()));
- ScopedVclPtrInstance< VirtualDevice > aContentVDev;
- MapMode aNewMapMode(pLastOutputDevice->GetMapMode());
-
- mpOutputDevice = aContentVDev.get();
- mpMetaFile = &o_rContentMetafile;
- aContentVDev->EnableOutput(false);
- aContentVDev->SetMapMode(pLastOutputDevice->GetMapMode());
- o_rContentMetafile.Record(aContentVDev.get());
- aContentVDev->SetLineColor(pLastOutputDevice->GetLineColor());
- aContentVDev->SetFillColor(pLastOutputDevice->GetFillColor());
- aContentVDev->SetFont(pLastOutputDevice->GetFont());
- aContentVDev->SetDrawMode(pLastOutputDevice->GetDrawMode());
- aContentVDev->SetSettings(pLastOutputDevice->GetSettings());
- aContentVDev->SetRefPoint(pLastOutputDevice->GetRefPoint());
-
- // dump to MetaFile
- process(rContent);
-
- // cleanups
- o_rContentMetafile.Stop();
- o_rContentMetafile.WindStart();
- aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft());
- o_rContentMetafile.SetPrefMapMode(aNewMapMode);
- o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize());
- mpOutputDevice = pLastOutputDevice;
- mpMetaFile = pLastMetafile;
-
- return aPrimitiveRectangle;
- }
-
- void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
- Gradient& o_rVCLGradient,
- const attribute::FillGradientAttribute& rFiGrAtt,
- bool bIsTransparenceGradient) const
- {
- if(bIsTransparenceGradient)
- {
- // it's about transparence channel intensities (black/white), do not use color modifier
- o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
- o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
- }
- else
- {
- // use color modifier to influence start/end color of gradient
- o_rVCLGradient.SetStartColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
- o_rVCLGradient.SetEndColor(Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
- }
+tools::Rectangle
+VclMetafileProcessor2D::impDumpToMetaFile(const primitive2d::Primitive2DContainer& rContent,
+ GDIMetaFile& o_rContentMetafile)
+{
+ // Prepare VDev, MetaFile and connections
+ OutputDevice* pLastOutputDevice = mpOutputDevice;
+ GDIMetaFile* pLastMetafile = mpMetaFile;
+ basegfx::B2DRange aPrimitiveRange(rContent.getB2DRange(getViewInformation2D()));
+
+ // transform primitive range with current transformation (e.g shadow offset)
+ aPrimitiveRange.transform(maCurrentTransformation);
+
+ const tools::Rectangle aPrimitiveRectangle(
+ basegfx::fround(aPrimitiveRange.getMinX()), basegfx::fround(aPrimitiveRange.getMinY()),
+ basegfx::fround(aPrimitiveRange.getMaxX()), basegfx::fround(aPrimitiveRange.getMaxY()));
+ ScopedVclPtrInstance<VirtualDevice> aContentVDev;
+ MapMode aNewMapMode(pLastOutputDevice->GetMapMode());
+
+ mpOutputDevice = aContentVDev.get();
+ mpMetaFile = &o_rContentMetafile;
+ aContentVDev->EnableOutput(false);
+ aContentVDev->SetMapMode(pLastOutputDevice->GetMapMode());
+ o_rContentMetafile.Record(aContentVDev.get());
+ aContentVDev->SetLineColor(pLastOutputDevice->GetLineColor());
+ aContentVDev->SetFillColor(pLastOutputDevice->GetFillColor());
+ aContentVDev->SetFont(pLastOutputDevice->GetFont());
+ aContentVDev->SetDrawMode(pLastOutputDevice->GetDrawMode());
+ aContentVDev->SetSettings(pLastOutputDevice->GetSettings());
+ aContentVDev->SetRefPoint(pLastOutputDevice->GetRefPoint());
+
+ // dump to MetaFile
+ process(rContent);
+
+ // cleanups
+ o_rContentMetafile.Stop();
+ o_rContentMetafile.WindStart();
+ aNewMapMode.SetOrigin(aPrimitiveRectangle.TopLeft());
+ o_rContentMetafile.SetPrefMapMode(aNewMapMode);
+ o_rContentMetafile.SetPrefSize(aPrimitiveRectangle.GetSize());
+ mpOutputDevice = pLastOutputDevice;
+ mpMetaFile = pLastMetafile;
+
+ return aPrimitiveRectangle;
+}
+
+void VclMetafileProcessor2D::impConvertFillGradientAttributeToVCLGradient(
+ Gradient& o_rVCLGradient, const attribute::FillGradientAttribute& rFiGrAtt,
+ bool bIsTransparenceGradient) const
+{
+ if (bIsTransparenceGradient)
+ {
+ // it's about transparence channel intensities (black/white), do not use color modifier
+ o_rVCLGradient.SetStartColor(Color(rFiGrAtt.getStartColor()));
+ o_rVCLGradient.SetEndColor(Color(rFiGrAtt.getEndColor()));
+ }
+ else
+ {
+ // use color modifier to influence start/end color of gradient
+ o_rVCLGradient.SetStartColor(
+ Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getStartColor())));
+ o_rVCLGradient.SetEndColor(
+ Color(maBColorModifierStack.getModifiedColor(rFiGrAtt.getEndColor())));
+ }
- o_rVCLGradient.SetAngle(static_cast< sal_uInt16 >(rFiGrAtt.getAngle() * (1.0 / F_PI1800)));
- o_rVCLGradient.SetBorder(static_cast< sal_uInt16 >(rFiGrAtt.getBorder() * 100.0));
- o_rVCLGradient.SetOfsX(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetX() * 100.0));
- o_rVCLGradient.SetOfsY(static_cast< sal_uInt16 >(rFiGrAtt.getOffsetY() * 100.0));
- o_rVCLGradient.SetSteps(rFiGrAtt.getSteps());
+ o_rVCLGradient.SetAngle(static_cast<sal_uInt16>(rFiGrAtt.getAngle() * (1.0 / F_PI1800)));
+ o_rVCLGradient.SetBorder(static_cast<sal_uInt16>(rFiGrAtt.getBorder() * 100.0));
+ o_rVCLGradient.SetOfsX(static_cast<sal_uInt16>(rFiGrAtt.getOffsetX() * 100.0));
+ o_rVCLGradient.SetOfsY(static_cast<sal_uInt16>(rFiGrAtt.getOffsetY() * 100.0));
+ o_rVCLGradient.SetSteps(rFiGrAtt.getSteps());
- // defaults for intensity; those were computed into the start/end colors already
- o_rVCLGradient.SetStartIntensity(100);
- o_rVCLGradient.SetEndIntensity(100);
+ // defaults for intensity; those were computed into the start/end colors already
+ o_rVCLGradient.SetStartIntensity(100);
+ o_rVCLGradient.SetEndIntensity(100);
- switch(rFiGrAtt.getStyle())
- {
- default : // attribute::GradientStyle::Linear :
- {
- o_rVCLGradient.SetStyle(GradientStyle::Linear);
- break;
- }
- case attribute::GradientStyle::Axial :
- {
- o_rVCLGradient.SetStyle(GradientStyle::Axial);
- break;
- }
- case attribute::GradientStyle::Radial :
- {
- o_rVCLGradient.SetStyle(GradientStyle::Radial);
- break;
- }
- case attribute::GradientStyle::Elliptical :
- {
- o_rVCLGradient.SetStyle(GradientStyle::Elliptical);
- break;
- }
- case attribute::GradientStyle::Square :
- {
- o_rVCLGradient.SetStyle(GradientStyle::Square);
- break;
- }
- case attribute::GradientStyle::Rect :
- {
- o_rVCLGradient.SetStyle(GradientStyle::Rect);
- break;
- }
- }
+ switch (rFiGrAtt.getStyle())
+ {
+ default: // attribute::GradientStyle::Linear :
+ {
+ o_rVCLGradient.SetStyle(GradientStyle::Linear);
+ break;
}
-
- void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill const * pSvtGraphicFill)
+ case attribute::GradientStyle::Axial:
{
- if(pSvtGraphicFill && !mnSvtGraphicFillCount)
- {
- SvMemoryStream aMemStm;
-
- WriteSvtGraphicFill( aMemStm, *pSvtGraphicFill );
- mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.TellEnd()));
- mnSvtGraphicFillCount++;
- }
+ o_rVCLGradient.SetStyle(GradientStyle::Axial);
+ break;
}
-
- void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill const * pSvtGraphicFill)
+ case attribute::GradientStyle::Radial:
{
- if(pSvtGraphicFill && mnSvtGraphicFillCount)
- {
- mnSvtGraphicFillCount--;
- mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"));
- }
+ o_rVCLGradient.SetStyle(GradientStyle::Radial);
+ break;
}
-
- double VclMetafileProcessor2D::getTransformedLineWidth( double fWidth ) const
+ case attribute::GradientStyle::Elliptical:
{
- // #i113922# the LineWidth is duplicated in the MetaPolylineAction,
- // and also inside the SvtGraphicStroke and needs transforming into
- // the same space as its coordinates here cf. fdo#61789
- // This is a partial fix. When an object transformation is used which
- // e.g. contains a scaleX != scaleY, an unproportional scaling will happen.
- const basegfx::B2DVector aDiscreteUnit( maCurrentTransformation * basegfx::B2DVector( fWidth, 0.0 ) );
-
- return aDiscreteUnit.getLength();
+ o_rVCLGradient.SetStyle(GradientStyle::Elliptical);
+ break;
}
-
- std::unique_ptr<SvtGraphicStroke> VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke(
- const basegfx::B2DPolygon& rB2DPolygon,
- const basegfx::BColor* pColor,
- const attribute::LineAttribute* pLineAttribute,
- const attribute::StrokeAttribute* pStrokeAttribute,
- const attribute::LineStartEndAttribute* pStart,
- const attribute::LineStartEndAttribute* pEnd)
+ case attribute::GradientStyle::Square:
+ {
+ o_rVCLGradient.SetStyle(GradientStyle::Square);
+ break;
+ }
+ case attribute::GradientStyle::Rect:
{
- std::unique_ptr<SvtGraphicStroke> pRetval;
+ o_rVCLGradient.SetStyle(GradientStyle::Rect);
+ break;
+ }
+ }
+}
- if(rB2DPolygon.count() && !mnSvtGraphicStrokeCount)
- {
- basegfx::B2DPolygon aLocalPolygon(rB2DPolygon);
- basegfx::BColor aStrokeColor;
- basegfx::B2DPolyPolygon aStartArrow;
- basegfx::B2DPolyPolygon aEndArrow;
+void VclMetafileProcessor2D::impStartSvtGraphicFill(SvtGraphicFill const* pSvtGraphicFill)
+{
+ if (pSvtGraphicFill && !mnSvtGraphicFillCount)
+ {
+ SvMemoryStream aMemStm;
- if(pColor)
- {
- aStrokeColor = *pColor;
- }
- else if(pLineAttribute)
- {
- aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor());
- }
+ WriteSvtGraphicFill(aMemStm, *pSvtGraphicFill);
+ mpMetaFile->AddAction(new MetaCommentAction(
+ "XPATHFILL_SEQ_BEGIN", 0, static_cast<const sal_uInt8*>(aMemStm.GetData()),
+ aMemStm.TellEnd()));
+ mnSvtGraphicFillCount++;
+ }
+}
- // It IS needed to record the stroke color at all in the metafile,
- // SvtGraphicStroke has NO entry for stroke color(!)
- mpOutputDevice->SetLineColor(Color(aStrokeColor));
+void VclMetafileProcessor2D::impEndSvtGraphicFill(SvtGraphicFill const* pSvtGraphicFill)
+{
+ if (pSvtGraphicFill && mnSvtGraphicFillCount)
+ {
+ mnSvtGraphicFillCount--;
+ mpMetaFile->AddAction(new MetaCommentAction("XPATHFILL_SEQ_END"));
+ }
+}
- if(!aLocalPolygon.isClosed())
- {
- double fPolyLength(0.0);
- double fStart(0.0);
- double fEnd(0.0);
-
- if(pStart && pStart->isActive())
- {
- fPolyLength = basegfx::utils::getLength(aLocalPolygon);
-
- aStartArrow = basegfx::utils::createAreaGeometryForLineStartEnd(
- aLocalPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
- fPolyLength, pStart->isCentered() ? 0.5 : 0.0, &fStart);
- }
-
- if(pEnd && pEnd->isActive())
- {
- if(basegfx::fTools::equalZero(fPolyLength))
- {
- fPolyLength = basegfx::utils::getLength(aLocalPolygon);
- }
-
- aEndArrow = basegfx::utils::createAreaGeometryForLineStartEnd(
- aLocalPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(),
- fPolyLength, pEnd->isCentered() ? 0.5 : 0.0, &fEnd);
- }
-
- if(0.0 != fStart || 0.0 != fEnd)
- {
- // build new poly, consume something from old poly
- aLocalPolygon = basegfx::utils::getSnippetAbsolute(aLocalPolygon, fStart, fPolyLength - fEnd, fPolyLength);
- }
- }
+double VclMetafileProcessor2D::getTransformedLineWidth(double fWidth) const
+{
+ // #i113922# the LineWidth is duplicated in the MetaPolylineAction,
+ // and also inside the SvtGraphicStroke and needs transforming into
+ // the same space as its coordinates here cf. fdo#61789
+ // This is a partial fix. When an object transformation is used which
+ // e.g. contains a scaleX != scaleY, an unproportional scaling will happen.
+ const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation
+ * basegfx::B2DVector(fWidth, 0.0));
+
+ return aDiscreteUnit.getLength();
+}
+
+std::unique_ptr<SvtGraphicStroke> VclMetafileProcessor2D::impTryToCreateSvtGraphicStroke(
+ const basegfx::B2DPolygon& rB2DPolygon, const basegfx::BColor* pColor,
+ const attribute::LineAttribute* pLineAttribute,
+ const attribute::StrokeAttribute* pStrokeAttribute,
+ const attribute::LineStartEndAttribute* pStart, const attribute::LineStartEndAttribute* pEnd)
+{
+ std::unique_ptr<SvtGraphicStroke> pRetval;
- SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone);
- SvtGraphicStroke::CapType eCap(SvtGraphicStroke::capButt);
- double fLineWidth(0.0);
- double fMiterLength(0.0);
- SvtGraphicStroke::DashArray aDashArray;
+ if (rB2DPolygon.count() && !mnSvtGraphicStrokeCount)
+ {
+ basegfx::B2DPolygon aLocalPolygon(rB2DPolygon);
+ basegfx::BColor aStrokeColor;
+ basegfx::B2DPolyPolygon aStartArrow;
+ basegfx::B2DPolyPolygon aEndArrow;
- if(pLineAttribute)
- {
- fLineWidth = fMiterLength = getTransformedLineWidth( pLineAttribute->getWidth() );
-
- // get Join
- switch(pLineAttribute->getLineJoin())
- {
- case basegfx::B2DLineJoin::NONE :
- {
- eJoin = SvtGraphicStroke::joinNone;
- break;
- }
- case basegfx::B2DLineJoin::Bevel :
- {
- eJoin = SvtGraphicStroke::joinBevel;
- break;
- }
- case basegfx::B2DLineJoin::Miter :
- {
- eJoin = SvtGraphicStroke::joinMiter;
- // ATM 15 degrees is assumed
- fMiterLength /= rtl::math::sin(basegfx::deg2rad(15.0));
- break;
- }
- case basegfx::B2DLineJoin::Round :
- {
- eJoin = SvtGraphicStroke::joinRound;
- break;
- }
- }
-
- // get stroke
- switch(pLineAttribute->getLineCap())
- {
- default: /* css::drawing::LineCap_BUTT */
- {
- eCap = SvtGraphicStroke::capButt;
- break;
- }
- case css::drawing::LineCap_ROUND:
- {
- eCap = SvtGraphicStroke::capRound;
- break;
- }
- case css::drawing::LineCap_SQUARE:
- {
- eCap = SvtGraphicStroke::capSquare;
- break;
- }
- }
- }
+ if (pColor)
+ {
+ aStrokeColor = *pColor;
+ }
+ else if (pLineAttribute)
+ {
+ aStrokeColor = maBColorModifierStack.getModifiedColor(pLineAttribute->getColor());
+ }
- if(pStrokeAttribute)
- {
- // copy dash array
- aDashArray = pStrokeAttribute->getDotDashArray();
- }
+ // It IS needed to record the stroke color at all in the metafile,
+ // SvtGraphicStroke has NO entry for stroke color(!)
+ mpOutputDevice->SetLineColor(Color(aStrokeColor));
- // #i101734# apply current object transformation to created geometry.
- // This is a partial fix. When an object transformation is used which
- // e.g. contains a scaleX != scaleY, an unproportional scaling would
- // have to be applied to the evtl. existing fat line. The current
- // concept of PDF export and SvtGraphicStroke usage does simply not
- // allow handling such definitions. The only clean way would be to
- // add the transformation to SvtGraphicStroke and to handle it there
- aLocalPolygon.transform(maCurrentTransformation);
- aStartArrow.transform(maCurrentTransformation);
- aEndArrow.transform(maCurrentTransformation);
-
- pRetval.reset(new SvtGraphicStroke(
- ::tools::Polygon(aLocalPolygon),
- ::tools::PolyPolygon(aStartArrow),
- ::tools::PolyPolygon(aEndArrow),
- mfCurrentUnifiedTransparence,
- fLineWidth,
- eCap,
- eJoin,
- fMiterLength,
- aDashArray));
- }
+ if (!aLocalPolygon.isClosed())
+ {
+ double fPolyLength(0.0);
+ double fStart(0.0);
+ double fEnd(0.0);
- return pRetval;
- }
+ if (pStart && pStart->isActive())
+ {
+ fPolyLength = basegfx::utils::getLength(aLocalPolygon);
- void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke const * pSvtGraphicStroke)
- {
- if(pSvtGraphicStroke && !mnSvtGraphicStrokeCount)
+ aStartArrow = basegfx::utils::createAreaGeometryForLineStartEnd(
+ aLocalPolygon, pStart->getB2DPolyPolygon(), true, pStart->getWidth(),
+ fPolyLength, pStart->isCentered() ? 0.5 : 0.0, &fStart);
+ }
+
+ if (pEnd && pEnd->isActive())
{
- SvMemoryStream aMemStm;
+ if (basegfx::fTools::equalZero(fPolyLength))
+ {
+ fPolyLength = basegfx::utils::getLength(aLocalPolygon);
+ }
- WriteSvtGraphicStroke( aMemStm, *pSvtGraphicStroke );
- mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_BEGIN", 0, static_cast< const sal_uInt8* >(aMemStm.GetData()), aMemStm.TellEnd()));
- mnSvtGraphicStrokeCount++;
+ aEndArrow = basegfx::utils::createAreaGeometryForLineStartEnd(
+ aLocalPolygon, pEnd->getB2DPolyPolygon(), false, pEnd->getWidth(), fPolyLength,
+ pEnd->isCentered() ? 0.5 : 0.0, &fEnd);
}
- }
- void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke const * pSvtGraphicStroke)
- {
- if(pSvtGraphicStroke && mnSvtGraphicStrokeCount)
+ if (0.0 != fStart || 0.0 != fEnd)
{
- mnSvtGraphicStrokeCount--;
- mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"));
+ // build new poly, consume something from old poly
+ aLocalPolygon = basegfx::utils::getSnippetAbsolute(aLocalPolygon, fStart,
+ fPolyLength - fEnd, fPolyLength);
}
}
- void VclMetafileProcessor2D::popStructureElement(vcl::PDFWriter::StructElement eElem)
- {
- if (!maListElements.empty() && maListElements.top() == eElem)
- {
- maListElements.pop();
- mpPDFExtOutDevData->EndStructureElement();
- }
- }
+ SvtGraphicStroke::JoinType eJoin(SvtGraphicStroke::joinNone);
+ SvtGraphicStroke::CapType eCap(SvtGraphicStroke::capButt);
+ double fLineWidth(0.0);
+ double fMiterLength(0.0);
+ SvtGraphicStroke::DashArray aDashArray;
- void VclMetafileProcessor2D::popListItem()
+ if (pLineAttribute)
{
- popStructureElement(vcl::PDFWriter::LIBody);
- popStructureElement(vcl::PDFWriter::ListItem);
- }
+ fLineWidth = fMiterLength = getTransformedLineWidth(pLineAttribute->getWidth());
- void VclMetafileProcessor2D::popList()
- {
- popListItem();
- popStructureElement(vcl::PDFWriter::List);
- }
-
- // init static break iterator
- uno::Reference< css::i18n::XBreakIterator > VclMetafileProcessor2D::mxBreakIterator;
-
- VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation, OutputDevice& rOutDev)
- : VclProcessor2D(rViewInformation, rOutDev),
- mpMetaFile(rOutDev.GetConnectMetaFile()),
- mnSvtGraphicFillCount(0),
- mnSvtGraphicStrokeCount(0),
- mfCurrentUnifiedTransparence(0.0),
- mpPDFExtOutDevData(dynamic_cast< vcl::PDFExtOutDevData* >(rOutDev.GetExtOutDevData())),
- mnCurrentOutlineLevel(-1),
- mbInListItem(false),
- mbBulletPresent(false)
- {
- OSL_ENSURE(rOutDev.GetConnectMetaFile(), "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)");
- // draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation
- // but only to ObjectTransformation. Do not change MapMode of destination.
- maCurrentTransformation = rViewInformation.getObjectTransformation();
- }
-
- VclMetafileProcessor2D::~VclMetafileProcessor2D()
- {
- // MapMode was not changed, no restore necessary
- }
-
- /***********************************************************************************************
-
- Support of MetaCommentActions in the VclMetafileProcessor2D
- Found MetaCommentActions and how they are supported:
-
- XGRAD_SEQ_BEGIN, XGRAD_SEQ_END:
-
- Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action.
- It is used in various exporters/importers to have direct access to the gradient before it
- is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g.
- the Metafile to SdrObject import creates its gradient objects.
- Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
- map it back to the corresponding tools tools::PolyPolygon and the Gradient and just call
- OutputDevice::DrawGradient which creates the necessary compatible actions.
-
- XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END:
-
- Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed
- inside GDIMetaFile::Rotate, nothing to take care of here.
- The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used
- with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not
- XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it
- to the comment action. A closing end token is created in the destructor.
- Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and
- SdrRectObj.
- The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind
- of filled objects, even simple colored polygons. It is added as extra information; the
- Metafile actions between the two tokens are interpreted as output generated from those
- fills. Thus, users have the choice to use the SvtGraphicFill info or the created output
- actions.
- Even for XFillTransparenceItem it is used, thus it may need to be supported in
- UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon.
- Implemented for:
- PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D,
- PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D,
- PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
- PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D,
- and for PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D when detected unified transparence
-
- XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END:
-
- Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one
- is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the
- contained path accordingly.
- The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and
- only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this
- would hinder to make use of tools::PolyPolygon strokes. I will need to add support at:
- PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
- PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
- PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D
- This can be done hierarchical, too.
- Okay, base implementation done based on those three primitives.
-
- FIELD_SEQ_BEGIN, FIELD_SEQ_END
-
- Used from slideshow for URLs, created from diverse SvxField implementations inside
- createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx
- inside ImpEditEngine::Paint.
- Created TextHierarchyFieldPrimitive2D and added needed infos there; it is a group primitive and wraps
- text primitives (but is not limited to that). It contains the field type if special actions for the
- support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is
- needed, it may be supported there.
- FIELD_SEQ_BEGIN;PageField
- FIELD_SEQ_END
- Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too.
-
- XTEXT
-
- XTEXT_EOC(i) end of character
- XTEXT_EOW(i) end of word
- XTEXT_EOS(i) end of sentence
-
- this three are with index and are created with the help of an i18n::XBreakIterator in
- ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some
- data structure for holding those TEXT infos.
- Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text
- primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage
- that this creations do not need to be done for all paints all the time. This would be
- expensive since the BreakIterator and it's usage is expensive and for each paint also the
- whole character stops would need to be created.
- Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below)
-
- XTEXT_EOL() end of line
- XTEXT_EOP() end of paragraph
-
- First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well,
- i decided to solve it with structure. I added the TextHierarchyPrimitives for this,
- namely:
- - TextHierarchyLinePrimitive2D: Encapsulates single line
- - TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph
- - TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM)
- Those are now supported in hierarchy. This means the MetaFile renderer will support them
- by using them, recursively using their content and adding MetaFile comments as needed.
- This also means that when another text layouter will be used it will be necessary to
- create/support the same HierarchyPrimitives to support users.
- To transport the information using this hierarchy is best suited to all future needs;
- the slideshow will be able to profit from it directly when using primitives; all other
- renderers not interested in the text structure will just ignore the encapsulations.
-
- XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END
- Supported now by the TextHierarchyBlockPrimitive2D.
-
- EPSReplacementGraphic:
- Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to
- hold the original EPS which was imported in the same MetaFile as first 2 entries. Only
- used to export the original again (if exists).
- Not necessary to support with MetaFuleRenderer.
-
- XTEXT_SCROLLRECT, XTEXT_PAINTRECT
- Currently used to get extra MetaFile infos using GraphicExporter which again uses
- SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since
- the rectangle data is added directly by the GraphicsExporter as comment. Does not need
- to be adapted at once.
- When adapting later, the only user - the diashow - should directly use the provided
- Animation infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D)
-
- PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END
- VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as
- a fix (hack) while VCL printing. It is needed to not downscale a bitmap which
- was explicitly created for the printer already again to some default maximum
- bitmap sizes.
- Nothing to do here for the primitive renderer.
-
- Support for vcl::PDFExtOutDevData:
- PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at
- the OutDev. When set, some extra data is written there. Trying simple PDF export and
- watching if I get those infos.
- Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses
- the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check
- if I get a PDFExtOutDevData at the target output device.
- Indeed, I get one. Checking what all may be done when that extra-device-info is there.
-
- All in all I have to talk to SJ. I will need to emulate some of those actions, but
- i need to discuss which ones.
- In the future, all those infos would be taken from the primitive sequence anyways,
- thus these extensions would potentially be temporary, too.
- Discussed with SJ, added the necessary support and tested it. Details follow.
-
- - In ImpEditEngine::Paint, paragraph infos and URL stuff is added.
- Added in primitive MetaFile renderer.
- Checking URL: Indeed, current version exports it, but it is missing in primitive
- CWS version. Adding support.
- Okay, URLs work. Checked, Done.
-
- - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the
- target and uno control data is created in UnoControlPDFExportContact::do_PaintObject.
- This may be added in primitive MetaFile renderer.
- Adding support...
- OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace
- svxform. Have to talk to FS if this has to be like that. Especially since
- vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl.
- Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move
- that stuff to somewhere else, maybe tools or svtools ?!? We will see...
- Moved to toolkit, so I have to link against it. I tried VCL first, but it did
- not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other than the name
- may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself,
- the lowest movement plane is toolkit.
- Checked form control export, it works well. Done.
-
- - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are
- generated. I will need to check what happens here with primitives.
- To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed.
- Added support, but feature is broken in main version, so i cannot test at all.
- Writing a bug to CL (or SJ) and seeing what happens (#i80380#).
- SJ took a look and we got it working. Tested VCL MetaFile Renderer based export,
- as intended, the original file is exported. Works, Done.
-
-
- To be done:
-
- - Maybe there are more places to take care of for vcl::PDFExtOutDevData!
-
-
- ****************************************************************************************************/
-
- void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
- {
- switch(rCandidate.getPrimitive2DID())
+ // get Join
+ switch (pLineAttribute->getLineJoin())
{
- case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
- {
- // directdraw of wrong spell primitive
- // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only
- break;
- }
- case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
- {
- processGraphicPrimitive2D(static_cast<const primitive2d::GraphicPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
- {
- processControlPrimitive2D(static_cast<const primitive2d::ControlPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D :
- {
- processTextHierarchyFieldPrimitive2D(static_cast<const primitive2d::TextHierarchyFieldPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D :
- {
- processTextHierarchyLinePrimitive2D(static_cast<const primitive2d::TextHierarchyLinePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D :
- {
- processTextHierarchyBulletPrimitive2D(static_cast<const primitive2d::TextHierarchyBulletPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D :
- {
- processTextHierarchyParagraphPrimitive2D(static_cast<const primitive2d::TextHierarchyParagraphPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D :
- {
- processTextHierarchyBlockPrimitive2D(static_cast<const primitive2d::TextHierarchyBlockPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
- case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D :
- {
- // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate
- processTextSimplePortionPrimitive2D(static_cast<const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
- {
- processPolygonHairlinePrimitive2D(static_cast<const primitive2d::PolygonHairlinePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D :
- {
- processPolygonStrokePrimitive2D(static_cast<const primitive2d::PolygonStrokePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D :
- {
- processPolygonStrokeArrowPrimitive2D(static_cast<const primitive2d::PolygonStrokeArrowPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
- {
- // direct draw of transformed BitmapEx primitive; use default processing, but without
- // former testing if graphic content is inside discrete local viewport; this is not
- // setup for metafile targets (metafile renderer tries to render in logic coordinates,
- // the mapping is kept to the OutputDevice for better Metafile recording)
- RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
- {
- processPolyPolygonGraphicPrimitive2D(static_cast<const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
- {
- processPolyPolygonHatchPrimitive2D(static_cast<const primitive2d::PolyPolygonHatchPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
- {
- processPolyPolygonGradientPrimitive2D(static_cast<const primitive2d::PolyPolygonGradientPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
- {
- processPolyPolygonColorPrimitive2D(static_cast<const primitive2d::PolyPolygonColorPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
- {
- processMaskPrimitive2D(static_cast<const primitive2d::MaskPrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
- {
- // modified color group. Force output to unified color. Use default pocessing.
- RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
- {
- processUnifiedTransparencePrimitive2D(static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
- {
- processTransparencePrimitive2D(static_cast<const primitive2d::TransparencePrimitive2D&>(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
- {
- // use default transform group pocessing
- RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate));
- break;
- }
- case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
+ case basegfx::B2DLineJoin::NONE:
{
- // new XDrawPage for ViewInformation2D
- RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate));
+ eJoin = SvtGraphicStroke::joinNone;
break;
}
- case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D :
+ case basegfx::B2DLineJoin::Bevel:
{
- // use default marker array pocessing
- RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(rCandidate));
+ eJoin = SvtGraphicStroke::joinBevel;
break;
}
- case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
+ case basegfx::B2DLineJoin::Miter:
{
- // use default point array pocessing
- RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate));
+ eJoin = SvtGraphicStroke::joinMiter;
+ // ATM 15 degrees is assumed
+ fMiterLength /= rtl::math::sin(basegfx::deg2rad(15.0));
break;
}
- case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D :
+ case basegfx::B2DLineJoin::Round:
{
- processStructureTagPrimitive2D(static_cast<const primitive2d::StructureTagPrimitive2D&>(rCandidate));
+ eJoin = SvtGraphicStroke::joinRound;
break;
}
- case PRIMITIVE2D_ID_EPSPRIMITIVE2D :
+ }
+
+ // get stroke
+ switch (pLineAttribute->getLineCap())
+ {
+ default: /* css::drawing::LineCap_BUTT */
{
- RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D& >(rCandidate));
+ eCap = SvtGraphicStroke::capButt;
break;
}
- case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D :
+ case css::drawing::LineCap_ROUND:
{
- RenderObjectInfoPrimitive2D(static_cast< const primitive2d::ObjectInfoPrimitive2D& >(rCandidate));
+ eCap = SvtGraphicStroke::capRound;
break;
}
- default :
+ case css::drawing::LineCap_SQUARE:
{
- // process recursively
- process(rCandidate);
+ eCap = SvtGraphicStroke::capSquare;
break;
}
}
}
- void VclMetafileProcessor2D::processGraphicPrimitive2D(const primitive2d::GraphicPrimitive2D& rGraphicPrimitive)
+ if (pStrokeAttribute)
{
- bool bUsingPDFExtOutDevData(false);
- basegfx::B2DVector aTranslate, aScale;
- static bool bSuppressPDFExtOutDevDataSupport(false); // loplugin:constvars:ignore
+ // copy dash array
+ aDashArray = pStrokeAttribute->getDotDashArray();
+ }
- if(mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
- {
- // emulate data handling from UnoControlPDFExportContact, original see
- // svtools/source/graphic/grfmgr.cxx
- const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
+ // #i101734# apply current object transformation to created geometry.
+ // This is a partial fix. When an object transformation is used which
+ // e.g. contains a scaleX != scaleY, an unproportional scaling would
+ // have to be applied to the evtl. existing fat line. The current
+ // concept of PDF export and SvtGraphicStroke usage does simply not
+ // allow handling such definitions. The only clean way would be to
+ // add the transformation to SvtGraphicStroke and to handle it there
+ aLocalPolygon.transform(maCurrentTransformation);
+ aStartArrow.transform(maCurrentTransformation);
+ aEndArrow.transform(maCurrentTransformation);
+
+ pRetval.reset(
+ new SvtGraphicStroke(tools::Polygon(aLocalPolygon), tools::PolyPolygon(aStartArrow),
+ tools::PolyPolygon(aEndArrow), mfCurrentUnifiedTransparence,
+ fLineWidth, eCap, eJoin, fMiterLength, aDashArray));
+ }
- if(rGraphic.IsGfxLink())
- {
- const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
-
- if(!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
- {
- const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
- double fRotate, fShearX;
- rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
-
- if( basegfx::fTools::equalZero( fRotate ) && ( aScale.getX() > 0.0 ) && ( aScale.getY() > 0.0 ) )
- {
- bUsingPDFExtOutDevData = true;
- mpPDFExtOutDevData->BeginGroup();
- }
- }
- }
- }
+ return pRetval;
+}
- // process recursively and add MetaFile comment
- process(rGraphicPrimitive);
+void VclMetafileProcessor2D::impStartSvtGraphicStroke(SvtGraphicStroke const* pSvtGraphicStroke)
+{
+ if (pSvtGraphicStroke && !mnSvtGraphicStrokeCount)
+ {
+ SvMemoryStream aMemStm;
- if(!bUsingPDFExtOutDevData)
- return;
+ WriteSvtGraphicStroke(aMemStm, *pSvtGraphicStroke);
+ mpMetaFile->AddAction(new MetaCommentAction(
+ "XPATHSTROKE_SEQ_BEGIN", 0, static_cast<const sal_uInt8*>(aMemStm.GetData()),
+ aMemStm.TellEnd()));
+ mnSvtGraphicStrokeCount++;
+ }
+}
- // emulate data handling from UnoControlPDFExportContact, original see
- // svtools/source/graphic/grfmgr.cxx
- const basegfx::B2DRange aCurrentRange(
- aTranslate.getX(), aTranslate.getY(),
- aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
- const ::tools::Rectangle aCurrentRect(
- sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
- sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
+void VclMetafileProcessor2D::impEndSvtGraphicStroke(SvtGraphicStroke const* pSvtGraphicStroke)
+{
+ if (pSvtGraphicStroke && mnSvtGraphicStrokeCount)
+ {
+ mnSvtGraphicStrokeCount--;
+ mpMetaFile->AddAction(new MetaCommentAction("XPATHSTROKE_SEQ_END"));
+ }
+}
+
+void VclMetafileProcessor2D::popStructureElement(vcl::PDFWriter::StructElement eElem)
+{
+ if (!maListElements.empty() && maListElements.top() == eElem)
+ {
+ maListElements.pop();
+ mpPDFExtOutDevData->EndStructureElement();
+ }
+}
+
+void VclMetafileProcessor2D::popListItem()
+{
+ popStructureElement(vcl::PDFWriter::LIBody);
+ popStructureElement(vcl::PDFWriter::ListItem);
+}
+
+void VclMetafileProcessor2D::popList()
+{
+ popListItem();
+ popStructureElement(vcl::PDFWriter::List);
+}
+
+// init static break iterator
+uno::Reference<css::i18n::XBreakIterator> VclMetafileProcessor2D::mxBreakIterator;
+
+VclMetafileProcessor2D::VclMetafileProcessor2D(const geometry::ViewInformation2D& rViewInformation,
+ OutputDevice& rOutDev)
+ : VclProcessor2D(rViewInformation, rOutDev)
+ , mpMetaFile(rOutDev.GetConnectMetaFile())
+ , mnSvtGraphicFillCount(0)
+ , mnSvtGraphicStrokeCount(0)
+ , mfCurrentUnifiedTransparence(0.0)
+ , mpPDFExtOutDevData(dynamic_cast<vcl::PDFExtOutDevData*>(rOutDev.GetExtOutDevData()))
+ , mnCurrentOutlineLevel(-1)
+ , mbInListItem(false)
+ , mbBulletPresent(false)
+{
+ OSL_ENSURE(rOutDev.GetConnectMetaFile(),
+ "VclMetafileProcessor2D: Used on OutDev which has no MetaFile Target (!)");
+ // draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation
+ // but only to ObjectTransformation. Do not change MapMode of destination.
+ maCurrentTransformation = rViewInformation.getObjectTransformation();
+}
+
+VclMetafileProcessor2D::~VclMetafileProcessor2D()
+{
+ // MapMode was not changed, no restore necessary
+}
+
+/***********************************************************************************************
+
+ Support of MetaCommentActions in the VclMetafileProcessor2D
+ Found MetaCommentActions and how they are supported:
+
+ XGRAD_SEQ_BEGIN, XGRAD_SEQ_END:
+
+ Used inside OutputDevice::DrawGradient to mark the start and end of a MetaGradientEx action.
+ It is used in various exporters/importers to have direct access to the gradient before it
+ is rendered by VCL (and thus fragmented to polygon color actions and others). On that base, e.g.
+ the Metafile to SdrObject import creates its gradient objects.
+ Best (and safest) way to support it here is to use PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
+ map it back to the corresponding tools tools::PolyPolygon and the Gradient and just call
+ OutputDevice::DrawGradient which creates the necessary compatible actions.
+
+ XPATHFILL_SEQ_BEGIN, XPATHFILL_SEQ_END:
+
+ Two producers, one is vcl/source/gdi/gdimtf.cxx, line 1273. There, it is transformed
+ inside GDIMetaFile::Rotate, nothing to take care of here.
+ The second producer is in graphics/svx/source/svdraw/impgrfll.cxx, line 374. This is used
+ with each incarnation of Imp_GraphicFill when a metafile is recorded, fillstyle is not
+ XFILL_NONE and not completely transparent. It creates a SvtGraphicFill and streams it
+ to the comment action. A closing end token is created in the destructor.
+ Usages of Imp_GraphicFill are in Do_Paint_Object-methods of SdrCircObj, SdrPathObj and
+ SdrRectObj.
+ The token users pick various actions from SvtGraphicFill, so it may need to be added for all kind
+ of filled objects, even simple colored polygons. It is added as extra information; the
+ Metafile actions between the two tokens are interpreted as output generated from those
+ fills. Thus, users have the choice to use the SvtGraphicFill info or the created output
+ actions.
+ Even for XFillTransparenceItem it is used, thus it may need to be supported in
+ UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon.
+ Implemented for:
+ PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D,
+ PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D,
+ PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
+ PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D,
+ and for PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D when detected unified transparence
+
+ XPATHSTROKE_SEQ_BEGIN, XPATHSTROKE_SEQ_END:
+
+ Similar to pathfill, but using SvtGraphicStroke instead. It also has two producers where one
+ is also the GDIMetaFile::Rotate. Another user is MetaCommentAction::Move which modifies the
+ contained path accordingly.
+ The other one is SdrObject::Imp_DrawLineGeometry. It's done when MetaFile is set at OutDev and
+ only when geometry is a single polygon (!). I see no reason for that; in the PS exporter this
+ would hinder to make use of tools::PolyPolygon strokes. I will need to add support at:
+ PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
+ PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
+ PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D
+ This can be done hierarchical, too.
+ Okay, base implementation done based on those three primitives.
+
+ FIELD_SEQ_BEGIN, FIELD_SEQ_END
+
+ Used from slideshow for URLs, created from diverse SvxField implementations inside
+ createBeginComment()/createEndComment(). createBeginComment() is used from editeng\impedit3.cxx
+ inside ImpEditEngine::Paint.
+ Created TextHierarchyFieldPrimitive2D and added needed infos there; it is a group primitive and wraps
+ text primitives (but is not limited to that). It contains the field type if special actions for the
+ support of FIELD_SEQ_BEGIN/END are needed; this is the case for Page and URL fields. If more is
+ needed, it may be supported there.
+ FIELD_SEQ_BEGIN;PageField
+ FIELD_SEQ_END
+ Okay, these are now completely supported by TextHierarchyFieldPrimitive2D. URL works, too.
+
+ XTEXT
+
+ XTEXT_EOC(i) end of character
+ XTEXT_EOW(i) end of word
+ XTEXT_EOS(i) end of sentence
+
+ this three are with index and are created with the help of an i18n::XBreakIterator in
+ ImplDrawWithComments. Simplifying, moving out text painting, reworking to create some
+ data structure for holding those TEXT infos.
+ Supported directly by TextSimplePortionPrimitive2D with adding a Locale to the basic text
+ primitive. In the MetaFileRenderer, the creation is now done (see below). This has the advantage
+ that this creations do not need to be done for all paints all the time. This would be
+ expensive since the BreakIterator and it's usage is expensive and for each paint also the
+ whole character stops would need to be created.
+ Created only for TextDecoratedPortionPrimitive2D due to XTEXT_EOL and XTEXT_EOP (see below)
+
+ XTEXT_EOL() end of line
+ XTEXT_EOP() end of paragraph
+
+ First try with boolean marks at TextDecoratedPortionPrimitive2D did not work too well,
+ i decided to solve it with structure. I added the TextHierarchyPrimitives for this,
+ namely:
+ - TextHierarchyLinePrimitive2D: Encapsulates single line
+ - TextHierarchyParagraphPrimitive2D: Encapsulates single paragraph
+ - TextHierarchyBlockPrimitive2D: encapsulates object texts (only one ATM)
+ Those are now supported in hierarchy. This means the MetaFile renderer will support them
+ by using them, recursively using their content and adding MetaFile comments as needed.
+ This also means that when another text layouter will be used it will be necessary to
+ create/support the same HierarchyPrimitives to support users.
+ To transport the information using this hierarchy is best suited to all future needs;
+ the slideshow will be able to profit from it directly when using primitives; all other
+ renderers not interested in the text structure will just ignore the encapsulations.
+
+ XTEXT_PAINTSHAPE_BEGIN, XTEXT_PAINTSHAPE_END
+ Supported now by the TextHierarchyBlockPrimitive2D.
+
+ EPSReplacementGraphic:
+ Only used in goodies\source\filter.vcl\ieps\ieps.cxx and svx\source\xml\xmlgrhlp.cxx to
+ hold the original EPS which was imported in the same MetaFile as first 2 entries. Only
+ used to export the original again (if exists).
+ Not necessary to support with MetaFuleRenderer.
+
+ XTEXT_SCROLLRECT, XTEXT_PAINTRECT
+ Currently used to get extra MetaFile infos using GraphicExporter which again uses
+ SdrTextObj::GetTextScrollMetaFileAndRectangle(). ATM works with primitives since
+ the rectangle data is added directly by the GraphicsExporter as comment. Does not need
+ to be adapted at once.
+ When adapting later, the only user - the diashow - should directly use the provided
+ Animation infos in the appropriate primitives (e.g. AnimatedSwitchPrimitive2D)
+
+ PRNSPOOL_TRANSPARENTBITMAP_BEGIN, PRNSPOOL_TRANSPARENTBITMAP_END
+ VCL usage when printing PL -> THB. Okay, THB confirms that it is only used as
+ a fix (hack) while VCL printing. It is needed to not downscale a bitmap which
+ was explicitly created for the printer already again to some default maximum
+ bitmap sizes.
+ Nothing to do here for the primitive renderer.
+
+ Support for vcl::PDFExtOutDevData:
+ PL knows that SJ did that stuff, it's used to hold a pointer to PDFExtOutDevData at
+ the OutDev. When set, some extra data is written there. Trying simple PDF export and
+ watching if I get those infos.
+ Well, a PDF export does not use e.g. ImpEditEngine::Paint since the PdfFilter uses
+ the SdXImpressDocument::render and thus uses the VclMetafileProcessor2D. I will check
+ if I get a PDFExtOutDevData at the target output device.
+ Indeed, I get one. Checking what all may be done when that extra-device-info is there.
+
+ All in all I have to talk to SJ. I will need to emulate some of those actions, but
+ i need to discuss which ones.
+ In the future, all those infos would be taken from the primitive sequence anyways,
+ thus these extensions would potentially be temporary, too.
+ Discussed with SJ, added the necessary support and tested it. Details follow.
+
+ - In ImpEditEngine::Paint, paragraph infos and URL stuff is added.
+ Added in primitive MetaFile renderer.
+ Checking URL: Indeed, current version exports it, but it is missing in primitive
+ CWS version. Adding support.
+ Okay, URLs work. Checked, Done.
+
+ - UnoControlPDFExportContact is only created when PDFExtOutDevData is used at the
+ target and uno control data is created in UnoControlPDFExportContact::do_PaintObject.
+ This may be added in primitive MetaFile renderer.
+ Adding support...
+ OOps, the necessary helper stuff is in svx/source/form/formpdxexport.cxx in namespace
+ svxform. Have to talk to FS if this has to be like that. Especially since
+ vcl::PDFWriter::AnyWidget is filled out, which is already part of vcl.
+ Wrote an eMail to FS, he is on vacation currently. I see no reason why not to move
+ that stuff to somewhere else, maybe tools or svtools ?!? We will see...
+ Moved to toolkit, so I have to link against it. I tried VCL first, but it did
+ not work since VCLUnoHelper::CreateFont is unresolved in VCL (!). Other than the name
+ may imply, it is defined in toolkit (!). Since toolkit is linked against VCL itself,
+ the lowest movement plane is toolkit.
+ Checked form control export, it works well. Done.
+
+ - In goodies, in GraphicObject::Draw, when the used Graphic is linked, infos are
+ generated. I will need to check what happens here with primitives.
+ To support, use of GraphicPrimitive2D (PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D) may be needed.
+ Added support, but feature is broken in main version, so i cannot test at all.
+ Writing a bug to CL (or SJ) and seeing what happens (#i80380#).
+ SJ took a look and we got it working. Tested VCL MetaFile Renderer based export,
+ as intended, the original file is exported. Works, Done.
+
+
+ To be done:
+
+ - Maybe there are more places to take care of for vcl::PDFExtOutDevData!
+
+
+****************************************************************************************************/
+
+void VclMetafileProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
+{
+ switch (rCandidate.getPrimitive2DID())
+ {
+ case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D:
+ {
+ // directdraw of wrong spell primitive
+ // Ignore for VclMetafileProcessor2D, this is for printing and MetaFile recording only
+ break;
+ }
+ case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D:
+ {
+ processGraphicPrimitive2D(
+ static_cast<const primitive2d::GraphicPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D:
+ {
+ processControlPrimitive2D(
+ static_cast<const primitive2d::ControlPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYFIELDPRIMITIVE2D:
+ {
+ processTextHierarchyFieldPrimitive2D(
+ static_cast<const primitive2d::TextHierarchyFieldPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYLINEPRIMITIVE2D:
+ {
+ processTextHierarchyLinePrimitive2D(
+ static_cast<const primitive2d::TextHierarchyLinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYBULLETPRIMITIVE2D:
+ {
+ processTextHierarchyBulletPrimitive2D(
+ static_cast<const primitive2d::TextHierarchyBulletPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYPARAGRAPHPRIMITIVE2D:
+ {
+ processTextHierarchyParagraphPrimitive2D(
+ static_cast<const primitive2d::TextHierarchyParagraphPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTHIERARCHYBLOCKPRIMITIVE2D:
+ {
+ processTextHierarchyBlockPrimitive2D(
+ static_cast<const primitive2d::TextHierarchyBlockPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
+ case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D:
+ {
+ // for supporting TEXT_ MetaFile actions there is more to do here; get the candidate
+ processTextSimplePortionPrimitive2D(
+ static_cast<const primitive2d::TextSimplePortionPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
+ {
+ processPolygonHairlinePrimitive2D(
+ static_cast<const primitive2d::PolygonHairlinePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
+ {
+ processPolygonStrokePrimitive2D(
+ static_cast<const primitive2d::PolygonStrokePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D:
+ {
+ processPolygonStrokeArrowPrimitive2D(
+ static_cast<const primitive2d::PolygonStrokeArrowPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D:
+ {
+ // direct draw of transformed BitmapEx primitive; use default processing, but without
+ // former testing if graphic content is inside discrete local viewport; this is not
+ // setup for metafile targets (metafile renderer tries to render in logic coordinates,
+ // the mapping is kept to the OutputDevice for better Metafile recording)
+ RenderBitmapPrimitive2D(static_cast<const primitive2d::BitmapPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D:
+ {
+ processPolyPolygonGraphicPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonGraphicPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D:
+ {
+ processPolyPolygonHatchPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonHatchPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D:
+ {
+ processPolyPolygonGradientPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonGradientPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
+ {
+ processPolyPolygonColorPrimitive2D(
+ static_cast<const primitive2d::PolyPolygonColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MASKPRIMITIVE2D:
+ {
+ processMaskPrimitive2D(static_cast<const primitive2d::MaskPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D:
+ {
+ // modified color group. Force output to unified color. Use default pocessing.
+ RenderModifiedColorPrimitive2D(
+ static_cast<const primitive2d::ModifiedColorPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D:
+ {
+ processUnifiedTransparencePrimitive2D(
+ static_cast<const primitive2d::UnifiedTransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D:
+ {
+ processTransparencePrimitive2D(
+ static_cast<const primitive2d::TransparencePrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
+ {
+ // use default transform group pocessing
+ RenderTransformPrimitive2D(
+ static_cast<const primitive2d::TransformPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D:
+ {
+ // new XDrawPage for ViewInformation2D
+ RenderPagePreviewPrimitive2D(
+ static_cast<const primitive2d::PagePreviewPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D:
+ {
+ // use default marker array pocessing
+ RenderMarkerArrayPrimitive2D(
+ static_cast<const primitive2d::MarkerArrayPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D:
+ {
+ // use default point array pocessing
+ RenderPointArrayPrimitive2D(
+ static_cast<const primitive2d::PointArrayPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_STRUCTURETAGPRIMITIVE2D:
+ {
+ processStructureTagPrimitive2D(
+ static_cast<const primitive2d::StructureTagPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_EPSPRIMITIVE2D:
+ {
+ RenderEpsPrimitive2D(static_cast<const primitive2d::EpsPrimitive2D&>(rCandidate));
+ break;
+ }
+ case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D:
+ {
+ RenderObjectInfoPrimitive2D(
+ static_cast<const primitive2d::ObjectInfoPrimitive2D&>(rCandidate));
+ break;
+ }
+ default:
+ {
+ // process recursively
+ process(rCandidate);
+ break;
+ }
+ }
+}
+
+void VclMetafileProcessor2D::processGraphicPrimitive2D(
+ const primitive2d::GraphicPrimitive2D& rGraphicPrimitive)
+{
+ bool bUsingPDFExtOutDevData(false);
+ basegfx::B2DVector aTranslate, aScale;
+ static bool bSuppressPDFExtOutDevDataSupport(false); // loplugin:constvars:ignore
+
+ if (mpPDFExtOutDevData && !bSuppressPDFExtOutDevDataSupport)
+ {
+ // emulate data handling from UnoControlPDFExportContact, original see
+ // svtools/source/graphic/grfmgr.cxx
+ const Graphic& rGraphic = rGraphicPrimitive.getGraphicObject().GetGraphic();
+
+ if (rGraphic.IsGfxLink())
+ {
const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
- // fdo#72530 don't pass empty Rectangle to EndGroup
- ::tools::Rectangle aCropRect(aCurrentRect);
- if(rAttr.IsCropped())
+ if (!rAttr.IsSpecialDrawMode() && !rAttr.IsAdjusted())
{
- // calculate scalings between real image size and logic object size. This
- // is necessary since the crop values are relative to original bitmap size
- double fFactorX(1.0);
- double fFactorY(1.0);
+ const basegfx::B2DHomMatrix& rTransform = rGraphicPrimitive.getTransform();
+ double fRotate, fShearX;
+ rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+ if (basegfx::fTools::equalZero(fRotate) && (aScale.getX() > 0.0)
+ && (aScale.getY() > 0.0))
{
- const MapMode aMapMode100thmm(MapUnit::Map100thMM);
- const Size aBitmapSize(OutputDevice::LogicToLogic(
- rGraphicPrimitive.getGraphicObject().GetPrefSize(),
- rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
- const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
- const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
-
- if(!basegfx::fTools::equalZero(fDivX))
- {
- fFactorX = aScale.getX() / fDivX;
- }
-
- if(!basegfx::fTools::equalZero(fDivY))
- {
- fFactorY = aScale.getY() / fDivY;
- }
+ bUsingPDFExtOutDevData = true;
+ mpPDFExtOutDevData->BeginGroup();
}
+ }
+ }
+ }
- // calculate crop range and rect
- basegfx::B2DRange aCropRange;
- aCropRange.expand(aCurrentRange.getMinimum() - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
- aCropRange.expand(aCurrentRange.getMaximum() + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
+ // process recursively and add MetaFile comment
+ process(rGraphicPrimitive);
+
+ if (!bUsingPDFExtOutDevData)
+ return;
+
+ // emulate data handling from UnoControlPDFExportContact, original see
+ // svtools/source/graphic/grfmgr.cxx
+ const basegfx::B2DRange aCurrentRange(aTranslate.getX(), aTranslate.getY(),
+ aTranslate.getX() + aScale.getX(),
+ aTranslate.getY() + aScale.getY());
+ const tools::Rectangle aCurrentRect(
+ sal_Int32(floor(aCurrentRange.getMinX())), sal_Int32(floor(aCurrentRange.getMinY())),
+ sal_Int32(ceil(aCurrentRange.getMaxX())), sal_Int32(ceil(aCurrentRange.getMaxY())));
+ const GraphicAttr& rAttr = rGraphicPrimitive.getGraphicAttr();
+ // fdo#72530 don't pass empty Rectangle to EndGroup
+ tools::Rectangle aCropRect(aCurrentRect);
+
+ if (rAttr.IsCropped())
+ {
+ // calculate scalings between real image size and logic object size. This
+ // is necessary since the crop values are relative to original bitmap size
+ double fFactorX(1.0);
+ double fFactorY(1.0);
- aCropRect = ::tools::Rectangle(
- sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
- sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
+ {
+ const MapMode aMapMode100thmm(MapUnit::Map100thMM);
+ const Size aBitmapSize(OutputDevice::LogicToLogic(
+ rGraphicPrimitive.getGraphicObject().GetPrefSize(),
+ rGraphicPrimitive.getGraphicObject().GetPrefMapMode(), aMapMode100thmm));
+ const double fDivX(aBitmapSize.Width() - rAttr.GetLeftCrop() - rAttr.GetRightCrop());
+ const double fDivY(aBitmapSize.Height() - rAttr.GetTopCrop() - rAttr.GetBottomCrop());
+
+ if (!basegfx::fTools::equalZero(fDivX))
+ {
+ fFactorX = aScale.getX() / fDivX;
}
- // Create image alternative description from ObjectInfoPrimitive2D info
- // for PDF export
- if(mpPDFExtOutDevData->GetIsExportTaggedPDF() && nullptr != getObjectInfoPrimitive2D())
+ if (!basegfx::fTools::equalZero(fDivY))
{
- OUString aAlternateDescription;
+ fFactorY = aScale.getY() / fDivY;
+ }
+ }
- if(!getObjectInfoPrimitive2D()->getTitle().isEmpty())
- {
- aAlternateDescription += getObjectInfoPrimitive2D()->getTitle();
- }
+ // calculate crop range and rect
+ basegfx::B2DRange aCropRange;
+ aCropRange.expand(
+ aCurrentRange.getMinimum()
+ - basegfx::B2DPoint(rAttr.GetLeftCrop() * fFactorX, rAttr.GetTopCrop() * fFactorY));
+ aCropRange.expand(
+ aCurrentRange.getMaximum()
+ + basegfx::B2DPoint(rAttr.GetRightCrop() * fFactorX, rAttr.GetBottomCrop() * fFactorY));
+
+ aCropRect = tools::Rectangle(
+ sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())),
+ sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY())));
+ }
- if(!getObjectInfoPrimitive2D()->getDesc().isEmpty())
- {
- if(!aAlternateDescription.isEmpty())
- {
- aAlternateDescription += " - ";
- }
+ // Create image alternative description from ObjectInfoPrimitive2D info
+ // for PDF export
+ if (mpPDFExtOutDevData->GetIsExportTaggedPDF() && nullptr != getObjectInfoPrimitive2D())
+ {
+ OUString aAlternateDescription;
- aAlternateDescription += getObjectInfoPrimitive2D()->getDesc();
- }
+ if (!getObjectInfoPrimitive2D()->getTitle().isEmpty())
+ {
+ aAlternateDescription += getObjectInfoPrimitive2D()->getTitle();
+ }
- // Use SetAlternateText to set it. This will work as long as some
- // structure is used (see PDFWriterImpl::setAlternateText and
- // m_nCurrentStructElement - tagged PDF export works with this in
- // Draw/Impress/Writer, but not in Calc due to too less structure...)
- //Z maybe add structure to Calc PDF export, may need some BeginGroup/EndGroup stuff ..?
- if(!aAlternateDescription.isEmpty())
- {
- mpPDFExtOutDevData->SetAlternateText(aAlternateDescription);
- }
+ if (!getObjectInfoPrimitive2D()->getDesc().isEmpty())
+ {
+ if (!aAlternateDescription.isEmpty())
+ {
+ aAlternateDescription += " - ";
}
- // #i123295# 3rd param is uncropped rect, 4th is cropped. The primitive has the cropped
- // object transformation, thus aCurrentRect *is* the clip region while aCropRect is the expanded,
- // uncropped region. Thus, correct order is aCropRect, aCurrentRect
- mpPDFExtOutDevData->EndGroup(
- rGraphicPrimitive.getGraphicObject().GetGraphic(),
- rAttr.GetTransparency(),
- aCropRect,
- aCurrentRect);
+ aAlternateDescription += getObjectInfoPrimitive2D()->getDesc();
}
- void VclMetafileProcessor2D::processControlPrimitive2D(const primitive2d::ControlPrimitive2D& rControlPrimitive)
+ // Use SetAlternateText to set it. This will work as long as some
+ // structure is used (see PDFWriterImpl::setAlternateText and
+ // m_nCurrentStructElement - tagged PDF export works with this in
+ // Draw/Impress/Writer, but not in Calc due to too less structure...)
+ //Z maybe add structure to Calc PDF export, may need some BeginGroup/EndGroup stuff ..?
+ if (!aAlternateDescription.isEmpty())
{
- const uno::Reference< awt::XControl >& rXControl(rControlPrimitive.getXControl());
- bool bIsPrintableControl(false);
+ mpPDFExtOutDevData->SetAlternateText(aAlternateDescription);
+ }
+ }
- // find out if control is printable
- if(rXControl.is())
+ // #i123295# 3rd param is uncropped rect, 4th is cropped. The primitive has the cropped
+ // object transformation, thus aCurrentRect *is* the clip region while aCropRect is the expanded,
+ // uncropped region. Thus, correct order is aCropRect, aCurrentRect
+ mpPDFExtOutDevData->EndGroup(rGraphicPrimitive.getGraphicObject().GetGraphic(),
+ rAttr.GetTransparency(), aCropRect, aCurrentRect);
+}
+
+void VclMetafileProcessor2D::processControlPrimitive2D(
+ const primitive2d::ControlPrimitive2D& rControlPrimitive)
+{
+ const uno::Reference<awt::XControl>& rXControl(rControlPrimitive.getXControl());
+ bool bIsPrintableControl(false);
+
+ // find out if control is printable
+ if (rXControl.is())
+ {
+ try
+ {
+ uno::Reference<beans::XPropertySet> xModelProperties(rXControl->getModel(),
+ uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySetInfo> xPropertyInfo(
+ xModelProperties.is() ? xModelProperties->getPropertySetInfo()
+ : uno::Reference<beans::XPropertySetInfo>());
+ const OUString sPrintablePropertyName("Printable");
+
+ if (xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
{
- try
- {
- uno::Reference< beans::XPropertySet > xModelProperties(rXControl->getModel(), uno::UNO_QUERY);
- uno::Reference< beans::XPropertySetInfo > xPropertyInfo(xModelProperties.is()
- ? xModelProperties->getPropertySetInfo()
- : uno::Reference< beans::XPropertySetInfo >());
- const OUString sPrintablePropertyName("Printable");
-
- if(xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(sPrintablePropertyName))
- {
- OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName) >>= bIsPrintableControl);
- }
- }
- catch(const uno::Exception&)
- {
- TOOLS_WARN_EXCEPTION("drawinglayer", "VclMetafileProcessor2D: No access to printable flag of Control");
- }
+ OSL_VERIFY(xModelProperties->getPropertyValue(sPrintablePropertyName)
+ >>= bIsPrintableControl);
}
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("drawinglayer",
+ "VclMetafileProcessor2D: No access to printable flag of Control");
+ }
+ }
- // PDF export and printing only for printable controls
- if(!bIsPrintableControl)
- return;
+ // PDF export and printing only for printable controls
+ if (!bIsPrintableControl)
+ return;
- const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
- bool bDoProcessRecursively(true);
+ const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields());
+ bool bDoProcessRecursively(true);
- if(bPDFExport)
- {
- // PDF export. Emulate data handling from UnoControlPDFExportContact
- // I have now moved describePDFControl to toolkit, thus i can implement the PDF
- // form control support now as follows
- std::unique_ptr< vcl::PDFWriter::AnyWidget > pPDFControl(
- ::toolkitform::describePDFControl( rXControl, *mpPDFExtOutDevData ) );
+ if (bPDFExport)
+ {
+ // PDF export. Emulate data handling from UnoControlPDFExportContact
+ // I have now moved describePDFControl to toolkit, thus i can implement the PDF
+ // form control support now as follows
+ std::unique_ptr<vcl::PDFWriter::AnyWidget> pPDFControl(
+ ::toolkitform::describePDFControl(rXControl, *mpPDFExtOutDevData));
- if (pPDFControl)
- {
- // still need to fill in the location (is a class Rectangle)
- const basegfx::B2DRange aRangeLogic(rControlPrimitive.getB2DRange(getViewInformation2D()));
- const ::tools::Rectangle aRectLogic(
- static_cast<sal_Int32>(floor(aRangeLogic.getMinX())), static_cast<sal_Int32>(floor(aRangeLogic.getMinY())),
- static_cast<sal_Int32>(ceil(aRangeLogic.getMaxX())), static_cast<sal_Int32>(ceil(aRangeLogic.getMaxY())));
- pPDFControl->Location = aRectLogic;
-
- Size aFontSize(pPDFControl->TextFont.GetFontSize());
- aFontSize = OutputDevice::LogicToLogic(aFontSize, MapMode(MapUnit::MapPoint), mpOutputDevice->GetMapMode());
- pPDFControl->TextFont.SetFontSize(aFontSize);
-
- mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
- mpPDFExtOutDevData->CreateControl(*pPDFControl);
- mpPDFExtOutDevData->EndStructureElement();
-
- // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
- // do not process recursively
- bDoProcessRecursively = false;
- }
- else
- {
- // PDF export did not work, try simple output.
- // Fallback to printer output by not setting bDoProcessRecursively
- // to false.
- }
- }
+ if (pPDFControl)
+ {
+ // still need to fill in the location (is a class Rectangle)
+ const basegfx::B2DRange aRangeLogic(
+ rControlPrimitive.getB2DRange(getViewInformation2D()));
+ const tools::Rectangle aRectLogic(static_cast<sal_Int32>(floor(aRangeLogic.getMinX())),
+ static_cast<sal_Int32>(floor(aRangeLogic.getMinY())),
+ static_cast<sal_Int32>(ceil(aRangeLogic.getMaxX())),
+ static_cast<sal_Int32>(ceil(aRangeLogic.getMaxY())));
+ pPDFControl->Location = aRectLogic;
+
+ Size aFontSize(pPDFControl->TextFont.GetFontSize());
+ aFontSize = OutputDevice::LogicToLogic(aFontSize, MapMode(MapUnit::MapPoint),
+ mpOutputDevice->GetMapMode());
+ pPDFControl->TextFont.SetFontSize(aFontSize);
+
+ mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form);
+ mpPDFExtOutDevData->CreateControl(*pPDFControl);
+ mpPDFExtOutDevData->EndStructureElement();
+
+ // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject);
+ // do not process recursively
+ bDoProcessRecursively = false;
+ }
+ else
+ {
+ // PDF export did not work, try simple output.
+ // Fallback to printer output by not setting bDoProcessRecursively
+ // to false.
+ }
+ }
- // #i93169# used flag the wrong way; true means that nothing was done yet
- if(bDoProcessRecursively)
- {
- // printer output
- try
- {
- // remember old graphics and create new
- uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY_THROW);
- const uno::Reference< awt::XGraphics > xOriginalGraphics(xControlView->getGraphics());
- const uno::Reference< awt::XGraphics > xNewGraphics(mpOutputDevice->CreateUnoGraphics());
-
- if(xNewGraphics.is())
- {
- // link graphics and view
- xControlView->setGraphics(xNewGraphics);
-
- // get position
- const basegfx::B2DHomMatrix aObjectToDiscrete(getViewInformation2D().getObjectToViewTransformation() * rControlPrimitive.getTransform());
- const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete * basegfx::B2DPoint(0.0, 0.0));
-
- // draw it
- xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY()));
- bDoProcessRecursively = false;
-
- // restore original graphics
- xControlView->setGraphics(xOriginalGraphics);
- }
- }
- catch( const uno::Exception& )
- {
- TOOLS_WARN_EXCEPTION("drawinglayer", "VclMetafileProcessor2D: Printing of Control failed");
- }
- }
+ // #i93169# used flag the wrong way; true means that nothing was done yet
+ if (bDoProcessRecursively)
+ {
+ // printer output
+ try
+ {
+ // remember old graphics and create new
+ uno::Reference<awt::XView> xControlView(rXControl, uno::UNO_QUERY_THROW);
+ const uno::Reference<awt::XGraphics> xOriginalGraphics(xControlView->getGraphics());
+ const uno::Reference<awt::XGraphics> xNewGraphics(mpOutputDevice->CreateUnoGraphics());
- // process recursively if not done yet to export as decomposition (bitmap)
- if(bDoProcessRecursively)
+ if (xNewGraphics.is())
{
- process(rControlPrimitive);
+ // link graphics and view
+ xControlView->setGraphics(xNewGraphics);
+
+ // get position
+ const basegfx::B2DHomMatrix aObjectToDiscrete(
+ getViewInformation2D().getObjectToViewTransformation()
+ * rControlPrimitive.getTransform());
+ const basegfx::B2DPoint aTopLeftDiscrete(aObjectToDiscrete
+ * basegfx::B2DPoint(0.0, 0.0));
+
+ // draw it
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list