[Libreoffice-commits] core.git: 2 commits - cppcanvas/source
Jan Holesovsky
kendy at collabora.com
Mon Nov 25 13:11:54 PST 2013
cppcanvas/source/inc/implrenderer.hxx | 7 +
cppcanvas/source/mtfrenderer/emfplus.cxx | 191 +++++++++++++++++++++++++------
2 files changed, 164 insertions(+), 34 deletions(-)
New commits:
commit ad8875e2a007d918636e1e1a2f6214b0fdf0da04
Author: Jan Holesovsky <kendy at collabora.com>
Date: Mon Nov 25 22:09:48 2013 +0100
EMF+: Set the stroke attributes on the custom line caps.
This finally makes the rendering of the custom line caps nice & complete.
Change-Id: If35ef1c44f34f5d5e6c50789c907105d03e96fca
diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index 2fa121f0..4907b6f 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -37,8 +37,10 @@
#include <rtl/ustring.hxx>
#include <sal/alloca.h>
-#include <com/sun/star/rendering/XCanvas.hpp>
+#include <com/sun/star/rendering/PathCapType.hpp>
+#include <com/sun/star/rendering/PathJoinType.hpp>
#include <com/sun/star/rendering/TexturingMode.hpp>
+#include <com/sun/star/rendering/XCanvas.hpp>
#include <bitmapaction.hxx>
#include <implrenderer.hxx>
@@ -103,6 +105,16 @@ const sal_uInt32 EmfPlusCustomLineCapDataTypeAdjustableArrow = 0x00000001;
const sal_uInt32 EmfPlusCustomLineCapDataFillPath = 0x00000001;
const sal_uInt32 EmfPlusCustomLineCapDataLinePath = 0x00000002;
+const sal_uInt32 EmfPlusLineCapTypeFlat = 0x00000000;
+const sal_uInt32 EmfPlusLineCapTypeSquare = 0x00000001;
+const sal_uInt32 EmfPlusLineCapTypeRound = 0x00000002;
+const sal_uInt32 EmfPlusLineCapTypeTriangle = 0x00000003;
+
+const sal_uInt32 EmfPlusLineJoinTypeMiter = 0x00000000;
+const sal_uInt32 EmfPlusLineJoinTypeBevel = 0x00000001;
+const sal_uInt32 EmfPlusLineJoinTypeRound = 0x00000002;
+const sal_uInt32 EmfPlusLineJoinTypeMiterClipped = 0x00000003;
+
using namespace ::com::sun::star;
using namespace ::basegfx;
@@ -594,9 +606,25 @@ namespace cppcanvas
}
};
+ /// Convert stroke caps between EMF+ and rendering API
+ sal_Int8 lcl_convertStrokeCap(sal_uInt32 nEmfStroke)
+ {
+ switch (nEmfStroke)
+ {
+ case EmfPlusLineCapTypeSquare: return rendering::PathCapType::SQUARE;
+ case EmfPlusLineCapTypeRound: return rendering::PathCapType::ROUND;
+ }
+
+ // we have no mapping for EmfPlusLineCapTypeTriangle, so return
+ // BUTT always
+ return rendering::PathCapType::BUTT;
+ }
+
struct EMFPCustomLineCap : public EMFPObject
{
sal_uInt32 type;
+ sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
+ float miterLimit;
basegfx::B2DPolyPolygon polygon;
public:
@@ -608,6 +636,22 @@ namespace cppcanvas
{
}
+ void SetAttributes(rendering::StrokeAttributes& aAttributes)
+ {
+ aAttributes.StartCapType = lcl_convertStrokeCap(strokeStartCap);
+ aAttributes.EndCapType = lcl_convertStrokeCap(strokeEndCap);
+
+ switch (strokeJoin)
+ {
+ case EmfPlusLineJoinTypeMiter: // fall-through
+ case EmfPlusLineJoinTypeMiterClipped: aAttributes.JoinType = rendering::PathJoinType::MITER; break;
+ case EmfPlusLineJoinTypeBevel: aAttributes.JoinType = rendering::PathJoinType::BEVEL; break;
+ case EmfPlusLineJoinTypeRound: aAttributes.JoinType = rendering::PathJoinType::ROUND; break;
+ }
+
+ aAttributes.MiterLimit = miterLimit;
+ }
+
void ReadPath(SvStream& s, ImplRenderer& rR, bool bClosed)
{
sal_Int32 pathLength;
@@ -648,13 +692,12 @@ namespace cppcanvas
{
sal_uInt32 customLineCapDataFlags, baseCap;
float baseInset;
- sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
- float strokeMiterLimit, widthScale;
+ float widthScale;
float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
s >> customLineCapDataFlags >> baseCap >> baseInset
>> strokeStartCap >> strokeEndCap >> strokeJoin
- >> strokeMiterLimit >> widthScale
+ >> miterLimit >> widthScale
>> fillHotSpotX >> fillHotSpotY >> strokeHotSpotX >> strokeHotSpotY;
SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
@@ -663,7 +706,7 @@ namespace cppcanvas
SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
- SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeMiterLimit: " << strokeMiterLimit);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tmiterLimit: " << miterLimit);
SAL_INFO("cppcanvas.emf", "EMF+\t\twidthScale: " << widthScale);
if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
@@ -682,11 +725,11 @@ namespace cppcanvas
// no test document to be able to implement it]
sal_Int32 width, height, middleInset, fillState, lineStartCap;
- sal_Int32 lineEndCap, lineJoin, lineMiterLimit, widthScale;
+ sal_Int32 lineEndCap, lineJoin, widthScale;
float fillHotSpotX, fillHotSpotY, lineHotSpotX, lineHotSpotY;
s >> width >> height >> middleInset >> fillState >> lineStartCap
- >> lineEndCap >> lineJoin >> lineMiterLimit >> widthScale
+ >> lineEndCap >> lineJoin >> miterLimit >> widthScale
>> fillHotSpotX >> fillHotSpotY >> lineHotSpotX >> lineHotSpotY;
SAL_INFO("cppcanvas.emf", "EMF+\t\tTODO - actually read EmfPlusCustomLineCapArrowData object (section 2.2.2.12)");
@@ -1358,13 +1401,23 @@ namespace cppcanvas
// line start
if (pen->customStartCap)
+ {
+ rendering::StrokeAttributes aAttributes(aCommonAttributes);
+ pen->customStartCap->SetAttributes(aAttributes);
+
EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customStartCap->polygon,
- true, aCommonAttributes, rParms, rState);
+ true, aAttributes, rParms, rState);
+ }
// line end
if (pen->customEndCap)
+ {
+ rendering::StrokeAttributes aAttributes(aCommonAttributes);
+ pen->customEndCap->SetAttributes(aAttributes);
+
EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customEndCap->polygon,
- false, aCommonAttributes, rParms, rState);
+ false, aAttributes, rParms, rState);
+ }
}
}
commit ff98a070eb03b5c3fe97053ce7afda70b1e74677
Author: Jan Holesovsky <kendy at collabora.com>
Date: Mon Nov 25 21:35:26 2013 +0100
EMF+: Render custom line cap data.
Change-Id: Ic5e2e2d105fb006503b63e4e162d4dc09dab9e68
diff --git a/cppcanvas/source/inc/implrenderer.hxx b/cppcanvas/source/inc/implrenderer.hxx
index 02fc003..c649db3 100644
--- a/cppcanvas/source/inc/implrenderer.hxx
+++ b/cppcanvas/source/inc/implrenderer.hxx
@@ -280,6 +280,13 @@ static float GetSwapFloat( SvStream& rSt )
/* EMF+ */
void processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms, OutDevState& rState, const CanvasSharedPtr& rCanvas );
double setFont( sal_uInt8 objectId, const ActionFactoryParameters& rParms, OutDevState& rState );
+
+ /// Render LineCap, like the start or end arrow of a polygon.
+ void EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
+ const ::basegfx::B2DPolyPolygon& rLineCap, bool bStart,
+ const com::sun::star::rendering::StrokeAttributes& rAttributes,
+ const ActionFactoryParameters& rParms, OutDevState& rState);
+
void EMFPPlusDrawPolygon (const ::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex);
void EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor);
diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx
index 69568d3..2fa121f0 100644
--- a/cppcanvas/source/mtfrenderer/emfplus.cxx
+++ b/cppcanvas/source/mtfrenderer/emfplus.cxx
@@ -597,6 +597,7 @@ namespace cppcanvas
struct EMFPCustomLineCap : public EMFPObject
{
sal_uInt32 type;
+ basegfx::B2DPolyPolygon polygon;
public:
EMFPCustomLineCap() : EMFPObject()
@@ -607,6 +608,33 @@ namespace cppcanvas
{
}
+ void ReadPath(SvStream& s, ImplRenderer& rR, bool bClosed)
+ {
+ sal_Int32 pathLength;
+ s >> pathLength;
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
+
+ sal_uInt32 pathHeader;
+ sal_Int32 pathPoints, pathFlags;
+ s >> pathHeader >> pathPoints >> pathFlags;
+
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)");
+ SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
+
+ EMFPPath path(pathPoints);
+ path.Read(s, pathFlags, rR);
+
+ polygon = path.GetPolygon(rR, false);
+ polygon.setClosed(bClosed);
+
+ // transformation to convert the path to what LibreOffice
+ // expects
+ B2DHomMatrix aMatrix;
+ aMatrix.scale(1.0, -1.0);
+
+ polygon.transform(aMatrix);
+ };
+
void Read (SvStream& s, ImplRenderer& rR)
{
sal_uInt32 header;
@@ -618,9 +646,10 @@ namespace cppcanvas
if (type == EmfPlusCustomLineCapDataTypeDefault)
{
- sal_Int32 customLineCapDataFlags, baseCap, baseInset;
- sal_Int32 strokeStartCap, strokeEndCap, strokeJoin;
- sal_Int32 strokeMiterLimit, widthScale;
+ sal_uInt32 customLineCapDataFlags, baseCap;
+ float baseInset;
+ sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
+ float strokeMiterLimit, widthScale;
float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
s >> customLineCapDataFlags >> baseCap >> baseInset
@@ -628,40 +657,23 @@ namespace cppcanvas
>> strokeMiterLimit >> widthScale
>> fillHotSpotX >> fillHotSpotY >> strokeHotSpotX >> strokeHotSpotY;
- SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLinCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tcustomLineCapDataFlags: 0x" << std::hex << customLineCapDataFlags);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseCap: 0x" << std::hex << baseCap);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tbaseInset: " << baseInset);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeStartCap: 0x" << std::hex << strokeStartCap);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeEndCap: 0x" << std::hex << strokeEndCap);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeJoin: 0x" << std::hex << strokeJoin);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\tstrokeMiterLimit: " << strokeMiterLimit);
+ SAL_INFO("cppcanvas.emf", "EMF+\t\twidthScale: " << widthScale);
if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
{
- sal_Int32 pathLength;
- s >> pathLength;
- SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
-
- sal_uInt32 pathHeader;
- sal_Int32 pathPoints, pathFlags;
- s >> pathHeader >> pathPoints >> pathFlags;
-
- SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap fill path)");
- SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
-
- EMFPPath path(pathPoints);
- path.Read(s, pathFlags, rR);
+ ReadPath(s, rR, true);
}
if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
{
- sal_Int32 pathLength;
- s >> pathLength;
- SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength);
-
- sal_uInt32 pathHeader;
- sal_Int32 pathPoints, pathFlags;
- s >> pathHeader >> pathPoints >> pathFlags;
-
- SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)");
- SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec );
-
- EMFPPath path(pathPoints);
- path.Read(s, pathFlags, rR);
+ ReadPath(s, rR, false);
}
}
else if (type == EmfPlusCustomLineCapDataTypeAdjustableArrow)
@@ -1264,6 +1276,38 @@ namespace cppcanvas
}
}
+
+ void ImplRenderer::EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength,
+ const ::basegfx::B2DPolyPolygon& rLineCap, bool bStart, const rendering::StrokeAttributes& rAttributes,
+ const ActionFactoryParameters& rParms, OutDevState& rState)
+ {
+ if (!rLineCap.count())
+ return;
+
+ // it seems the line caps in EMF+ are 4*larger than what
+ // LibreOffice expects, and the mapping in
+ // createAreaGeometryForLineStartEnd scales that down, so
+ // correct it
+ // [unfortunately found no proof for this in the spec :-( - please
+ // feel free to correct this if it causes trouble]
+ double fWidth = rAttributes.StrokeWidth*4;
+
+ basegfx::B2DPolyPolygon aArrow(basegfx::tools::createAreaGeometryForLineStartEnd(
+ rPolygon, rLineCap, bStart,
+ fWidth, fPolyLength, 0.0, NULL));
+
+ // createAreaGeometryForLineStartEnd from some reason always sets
+ // the path as closed, correct it
+ aArrow.setClosed(rLineCap.isClosed());
+
+ ActionSharedPtr pAction(internal::PolyPolyActionFactory::createPolyPolyAction(aArrow, rParms.mrCanvas, rState, rAttributes));
+ if (pAction)
+ {
+ maActions.push_back(MtfAction(pAction, rParms.mrCurrActionIndex));
+ rParms.mrCurrActionIndex += pAction->getActionCount()-1;
+ }
+ }
+
void ImplRenderer::EMFPPlusDrawPolygon (const ::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex)
{
@@ -1298,6 +1342,32 @@ namespace cppcanvas
maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex));
rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
}
+
+ // render line starts & ends
+ if (pen->customStartCap || pen->customEndCap)
+ {
+ for (sal_uInt32 i = 0; i < aPolyPolygon.count(); ++i)
+ {
+ // break the polypolygon into polygons
+ basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(i));
+
+ if (aPolygon.isClosed())
+ continue;
+
+ double fPolyLength = basegfx::tools::getLength(aPolygon);
+
+ // line start
+ if (pen->customStartCap)
+ EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customStartCap->polygon,
+ true, aCommonAttributes, rParms, rState);
+
+ // line end
+ if (pen->customEndCap)
+ EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customEndCap->polygon,
+ false, aCommonAttributes, rParms, rState);
+ }
+ }
+
}
}
More information about the Libreoffice-commits
mailing list