EMF+: Render custom line cap data.
Change-Id: Ic5e2e2d105fb006503b63e4e162d4dc09dab9e68
This commit is contained in:
@@ -280,6 +280,13 @@ static float GetSwapFloat( SvStream& rSt )
|
|||||||
/* EMF+ */
|
/* EMF+ */
|
||||||
void processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms, OutDevState& rState, const CanvasSharedPtr& rCanvas );
|
void processEMFPlus( MetaCommentAction* pAct, const ActionFactoryParameters& rFactoryParms, OutDevState& rState, const CanvasSharedPtr& rCanvas );
|
||||||
double setFont( sal_uInt8 objectId, const ActionFactoryParameters& rParms, OutDevState& rState );
|
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 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);
|
void EMFPPlusFillPolygon (::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, OutDevState& rState, const CanvasSharedPtr& rCanvas, bool isColor, sal_uInt32 brushIndexOrColor);
|
||||||
|
|
||||||
|
@@ -597,6 +597,7 @@ namespace cppcanvas
|
|||||||
struct EMFPCustomLineCap : public EMFPObject
|
struct EMFPCustomLineCap : public EMFPObject
|
||||||
{
|
{
|
||||||
sal_uInt32 type;
|
sal_uInt32 type;
|
||||||
|
basegfx::B2DPolyPolygon polygon;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EMFPCustomLineCap() : EMFPObject()
|
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)
|
void Read (SvStream& s, ImplRenderer& rR)
|
||||||
{
|
{
|
||||||
sal_uInt32 header;
|
sal_uInt32 header;
|
||||||
@@ -618,9 +646,10 @@ namespace cppcanvas
|
|||||||
|
|
||||||
if (type == EmfPlusCustomLineCapDataTypeDefault)
|
if (type == EmfPlusCustomLineCapDataTypeDefault)
|
||||||
{
|
{
|
||||||
sal_Int32 customLineCapDataFlags, baseCap, baseInset;
|
sal_uInt32 customLineCapDataFlags, baseCap;
|
||||||
sal_Int32 strokeStartCap, strokeEndCap, strokeJoin;
|
float baseInset;
|
||||||
sal_Int32 strokeMiterLimit, widthScale;
|
sal_uInt32 strokeStartCap, strokeEndCap, strokeJoin;
|
||||||
|
float strokeMiterLimit, widthScale;
|
||||||
float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
|
float fillHotSpotX, fillHotSpotY, strokeHotSpotX, strokeHotSpotY;
|
||||||
|
|
||||||
s >> customLineCapDataFlags >> baseCap >> baseInset
|
s >> customLineCapDataFlags >> baseCap >> baseInset
|
||||||
@@ -628,40 +657,23 @@ namespace cppcanvas
|
|||||||
>> strokeMiterLimit >> widthScale
|
>> strokeMiterLimit >> widthScale
|
||||||
>> fillHotSpotX >> fillHotSpotY >> strokeHotSpotX >> strokeHotSpotY;
|
>> 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)
|
if (customLineCapDataFlags & EmfPlusCustomLineCapDataFillPath)
|
||||||
{
|
{
|
||||||
sal_Int32 pathLength;
|
ReadPath(s, rR, true);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
|
if (customLineCapDataFlags & EmfPlusCustomLineCapDataLinePath)
|
||||||
{
|
{
|
||||||
sal_Int32 pathLength;
|
ReadPath(s, rR, false);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == EmfPlusCustomLineCapDataTypeAdjustableArrow)
|
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,
|
void ImplRenderer::EMFPPlusDrawPolygon (const ::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms,
|
||||||
OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex)
|
OutDevState& rState, const CanvasSharedPtr& rCanvas, sal_uInt32 penIndex)
|
||||||
{
|
{
|
||||||
@@ -1298,6 +1342,32 @@ namespace cppcanvas
|
|||||||
maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex));
|
maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex));
|
||||||
rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user