summaryrefslogtreecommitdiff
path: root/cppcanvas
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@collabora.com>2013-11-25 21:35:26 +0100
committerJan Holesovsky <kendy@collabora.com>2013-11-25 22:11:31 +0100
commitff98a070eb03b5c3fe97053ce7afda70b1e74677 (patch)
tree7cddbd74edc4d2076574597335818d3fc78535c1 /cppcanvas
parent983e0332737c9bdb114ca2132f4c90d33428dbba (diff)
EMF+: Render custom line cap data.
Change-Id: Ic5e2e2d105fb006503b63e4e162d4dc09dab9e68
Diffstat (limited to 'cppcanvas')
-rw-r--r--cppcanvas/source/inc/implrenderer.hxx7
-rw-r--r--cppcanvas/source/mtfrenderer/emfplus.cxx130
2 files changed, 107 insertions, 30 deletions
diff --git a/cppcanvas/source/inc/implrenderer.hxx b/cppcanvas/source/inc/implrenderer.hxx
index 02fc0032c575..c649db32c750 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 69568d337734..2fa121f065dc 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);
+ }
+ }
+
}
}