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:
@@ -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; }
|
||||
|
@@ -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 );
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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 )
|
||||
|
@@ -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
|
||||
{
|
||||
|
Reference in New Issue
Block a user