fdo#78241 PDF Import: add dashes support

Change-Id: Ifd9fbce44c7d18114d5be466bfb9d92192573205
Reviewed-on: https://gerrit.libreoffice.org/9246
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Vort
2014-05-04 08:49:18 +03:00
committed by Caolán McNamara
parent bb2d5c40e4
commit b27fca822c
5 changed files with 127 additions and 90 deletions

View File

@@ -28,6 +28,8 @@
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <com/sun/star/rendering/XColorSpace.hpp>
#include "com/sun/star/rendering/PathCapType.hpp"
#include "com/sun/star/rendering/PathJoinType.hpp"
#include <vector>
#include <boost/unordered_map.hpp>
@@ -71,6 +73,9 @@ namespace pdfi
/// Convert color to "#FEFEFE" color notation
OUString getColorString( const ::com::sun::star::rendering::ARGBColor& );
double GetAverageTransformationScale(const basegfx::B2DHomMatrix& matrix);
void FillDashStyleProps(PropertyMap& props, const std::vector<double>& dashArray, double scale);
struct FontAttrHash
{
size_t operator()(const FontAttributes& rFont ) const
@@ -140,6 +145,34 @@ namespace pdfi
Clip == rRight.Clip;
}
OUString GetLineJoinString() const
{
switch (LineJoin)
{
default:
case ::com::sun::star::rendering::PathJoinType::MITER:
return "miter";
case ::com::sun::star::rendering::PathJoinType::ROUND:
return "round";
case ::com::sun::star::rendering::PathJoinType::BEVEL:
return "bevel";
}
}
OUString GetLineCapString() const
{
switch (LineCap)
{
default:
case ::com::sun::star::rendering::PathCapType::BUTT:
return "butt";
case ::com::sun::star::rendering::PathCapType::ROUND:
return "round";
case ::com::sun::star::rendering::PathCapType::SQUARE:
return "square";
}
}
bool isRotatedOrSkewed() const
{ return Transformation.get( 0, 1 ) != 0.0 ||
Transformation.get( 1, 0 ) != 0.0; }

View File

@@ -23,9 +23,62 @@
#include <rtl/ustrbuf.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <math.h>
using namespace pdfi;
using namespace com::sun::star;
double pdfi::GetAverageTransformationScale(const basegfx::B2DHomMatrix& matrix)
{
double rotate, shearX;
basegfx::B2DTuple scale, translation;
matrix.decompose(scale, translation, rotate, shearX);
return (fabs(scale.getX()) + fabs(scale.getY())) / 2.0;
}
void pdfi::FillDashStyleProps(PropertyMap& props, const std::vector<double>& dashArray, double scale)
{
size_t pairCount = dashArray.size() / 2;
double distance = 0.0;
for (size_t i = 0; i < pairCount; i++)
distance += dashArray[i * 2 + 1];
distance /= pairCount;
props["draw:style"] = "rect";
props["draw:distance"] = convertPixelToUnitString(distance * scale);
int dotStage = 0;
int dotCounts[3] = {0, 0, 0};
double dotLengths[3] = {0.0, 0.0, 0.0};
for (size_t i = 0; i < pairCount; i++)
{
if (dotLengths[dotStage] != dashArray[i * 2])
{
dotStage++;
if (dotStage == 3)
break;
dotCounts[dotStage] = 1;
dotLengths[dotStage] = dashArray[i * 2];
}
else
{
dotCounts[dotStage]++;
}
}
for (int i = 1; i < 3; i++)
{
if (dotCounts[i] == 0)
continue;
props["draw:dots" + OUString::number(i)] = OUString::number(dotCounts[i]);
props["draw:dots" + OUString::number(i) + "-length"] =
convertPixelToUnitString(dotLengths[i] * scale);
}
}
OUString pdfi::getColorString( const rendering::ARGBColor& rCol )
{
OUStringBuffer aBuf( 7 );

View File

@@ -35,8 +35,6 @@
#include "comphelper/processfactory.hxx"
#include "com/sun/star/i18n/ScriptType.hpp"
#include "com/sun/star/i18n/DirectionProperty.hpp"
#include "com/sun/star/rendering/PathCapType.hpp"
#include "com/sun/star/rendering/PathJoinType.hpp"
#include <string.h>
@@ -778,12 +776,11 @@ void DrawXmlOptimizer::visit( DocumentElement& elem, const std::list< Element* >
}
void DrawXmlFinalizer::visit( PolyPolyElement& elem, const std::list< Element* >::const_iterator& )
{
// xxx TODO copied from DrawElement
const GraphicsContext& rGC = m_rProcessor.getGraphicsContext(elem.GCId );
PropertyMap aProps;
aProps[ "style:family" ] = "graphic";
aProps[ "style:parent-style-name" ] = "standard";
@@ -791,52 +788,29 @@ void DrawXmlFinalizer::visit( PolyPolyElement& elem, const std::list< Element* >
m_rStyleContainer.getStandardStyleId( "graphic" );
PropertyMap aGCProps;
// TODO(F3): proper dash emulation
if( elem.Action & PATH_STROKE )
if (elem.Action & PATH_STROKE)
{
aGCProps[ "draw:stroke" ] = rGC.DashArray.empty() ? OUString("solid") : OUString("dash");
aGCProps[ "svg:stroke-color" ] = getColorString( rGC.LineColor );
if( rGC.LineWidth != 0.0 )
double scale = GetAverageTransformationScale(rGC.Transformation);
if (rGC.DashArray.size() < 2)
{
::basegfx::B2DVector aVec(rGC.LineWidth,0);
aVec *= rGC.Transformation;
aGCProps[ "draw:stroke" ] = "solid";
}
else
{
PropertyMap props;
FillDashStyleProps(props, rGC.DashArray, scale);
StyleContainer::Style style("draw:stroke-dash", props);
aVec.setX ( convPx2mmPrec2( aVec.getX() )*100.0 );
aVec.setY ( convPx2mmPrec2( aVec.getY() )*100.0 );
aGCProps[ "draw:stroke" ] = "dash";
aGCProps[ "draw:stroke-dash" ] =
m_rStyleContainer.getStyleName(
m_rStyleContainer.getStyleId(style));
}
aGCProps[ "svg:stroke-width" ] = OUString::number( aVec.getLength() );
}
OUString strokeLinejoinValue;
OUString strokeLinecapValue;
switch (rGC.LineJoin)
{
default:
case rendering::PathJoinType::MITER:
strokeLinejoinValue = "miter";
break;
case rendering::PathJoinType::ROUND:
strokeLinejoinValue = "round";
break;
case rendering::PathJoinType::BEVEL:
strokeLinejoinValue = "bevel";
break;
}
switch (rGC.LineCap)
{
default:
case rendering::PathCapType::BUTT:
strokeLinecapValue = "butt";
break;
case rendering::PathCapType::ROUND:
strokeLinecapValue = "round";
break;
case rendering::PathCapType::SQUARE:
strokeLinecapValue = "square";
break;
}
aGCProps[ "draw:stroke-linejoin" ] = strokeLinejoinValue;
aGCProps[ "svg:stroke-linecap" ] = strokeLinecapValue;
aGCProps[ "svg:stroke-color" ] = getColorString(rGC.LineColor);
aGCProps[ "svg:stroke-width" ] = convertPixelToUnitString(rGC.LineWidth * scale);
aGCProps[ "draw:stroke-linejoin" ] = rGC.GetLineJoinString();
aGCProps[ "svg:stroke-linecap" ] = rGC.GetLineCapString();
}
else
{

View File

@@ -191,6 +191,8 @@ void StyleContainer::impl_emitStyle( sal_Int32 nStyleId,
PropertyMap aProps( rStyle.Properties );
if( !rStyle.IsSubStyle )
aProps[ "style:name" ] = getStyleName( nStyleId );
if (rStyle.Name == "draw:stroke-dash")
aProps[ "draw:name" ] = aProps[ "style:name" ];
rContext.rEmitter.beginTag( rStyle.Name.getStr(), aProps );
for( unsigned int n = 0; n < rStyle.SubStyles.size(); ++n )

View File

@@ -28,8 +28,6 @@
#include "basegfx/polygon/b2dpolypolygontools.hxx"
#include "basegfx/range/b2drange.hxx"
#include "com/sun/star/rendering/PathCapType.hpp"
#include "com/sun/star/rendering/PathJoinType.hpp"
using namespace ::com::sun::star;
@@ -845,52 +843,29 @@ void WriterXmlFinalizer::visit( PolyPolyElement& elem, const std::list< Element*
aProps[ "style:family" ] = "graphic";
PropertyMap aGCProps;
// TODO(F3): proper dash emulation
if( elem.Action & PATH_STROKE )
if (elem.Action & PATH_STROKE)
{
aGCProps[ "draw:stroke" ] = rGC.DashArray.empty() ? OUString("solid") : OUString("dash");
aGCProps[ "svg:stroke-color" ] = getColorString( rGC.LineColor );
if( rGC.LineWidth != 0.0 )
double scale = GetAverageTransformationScale(rGC.Transformation);
if (rGC.DashArray.size() < 2)
{
::basegfx::B2DVector aVec(rGC.LineWidth,0);
aVec *= rGC.Transformation;
aGCProps[ "draw:stroke" ] = "solid";
}
else
{
PropertyMap props;
FillDashStyleProps(props, rGC.DashArray, scale);
StyleContainer::Style style("draw:stroke-dash", props);
aVec.setX ( convPx2mmPrec2( aVec.getX() )*100.0 );
aVec.setY ( convPx2mmPrec2( aVec.getY() )*100.0 );
aGCProps[ "draw:stroke" ] = "dash";
aGCProps[ "draw:stroke-dash" ] =
m_rStyleContainer.getStyleName(
m_rStyleContainer.getStyleId(style));
}
aGCProps[ "svg:stroke-width" ] = OUString::number( aVec.getLength() );
}
OUString strokeLinejoinValue;
OUString strokeLinecapValue;
switch (rGC.LineJoin)
{
default:
case rendering::PathJoinType::MITER:
strokeLinejoinValue = "miter";
break;
case rendering::PathJoinType::ROUND:
strokeLinejoinValue = "round";
break;
case rendering::PathJoinType::BEVEL:
strokeLinejoinValue = "bevel";
break;
}
switch (rGC.LineCap)
{
default:
case rendering::PathCapType::BUTT:
strokeLinecapValue = "butt";
break;
case rendering::PathCapType::ROUND:
strokeLinecapValue = "round";
break;
case rendering::PathCapType::SQUARE:
strokeLinecapValue = "square";
break;
}
aGCProps[ "draw:stroke-linejoin" ] = strokeLinejoinValue;
aGCProps[ "svg:stroke-linecap" ] = strokeLinecapValue;
aGCProps[ "svg:stroke-color" ] = getColorString(rGC.LineColor);
aGCProps[ "svg:stroke-width" ] = convertPixelToUnitString(rGC.LineWidth * scale);
aGCProps[ "draw:stroke-linejoin" ] = rGC.GetLineJoinString();
aGCProps[ "svg:stroke-linecap" ] = rGC.GetLineCapString();
}
else
{