[PATCH] SVG: use dash parameters from svg file
Chr. Rossmanith
ChrRossmanith at gmx.de
Fri Jun 15 14:27:49 PDT 2012
Change-Id: I86b31156e1a9221d9cfdc40d5670b324ce056a89
---
filter/source/svg/gfxtypes.hxx | 3 +-
filter/source/svg/svgreader.cxx | 182 ++++++++++++++++++++++++++++-----------
2 files changed, 132 insertions(+), 53 deletions(-)
diff --git a/filter/source/svg/gfxtypes.hxx b/filter/source/svg/gfxtypes.hxx
index 68463c8..7cebe1a 100644
--- a/filter/source/svg/gfxtypes.hxx
+++ b/filter/source/svg/gfxtypes.hxx
@@ -143,7 +143,8 @@ enum PaintType
{
NONE,
SOLID,
- GRADIENT
+ GRADIENT,
+ DASH
};
enum FillRule
diff --git a/filter/source/svg/svgreader.cxx b/filter/source/svg/svgreader.cxx
index 6db2eb0..52c2078 100644
--- a/filter/source/svg/svgreader.cxx
+++ b/filter/source/svg/svgreader.cxx
@@ -659,11 +659,17 @@ struct AnnotatingVisitor
else
xAttrs->AddAttribute( "draw:fill", "none");
- if( rState.meStrokeType != NONE )
+ if( rState.meStrokeType == SOLID )
{
xAttrs->AddAttribute( "draw:stroke", "solid");
xAttrs->AddAttribute( "svg:stroke-color", getOdfColor(rState.maStrokeColor));
}
+ else if( rState.meStrokeType == DASH )
+ {
+ xAttrs->AddAttribute( "draw:stroke", "dash");
+ xAttrs->AddAttribute( "draw:stroke-dash", "dash"+rtl::OUString::valueOf(mnCurrStateId));
+ xAttrs->AddAttribute( "svg:stroke-color", getOdfColor(rState.maStrokeColor));
+ }
else
xAttrs->AddAttribute( "draw:stroke", "none");
@@ -694,28 +700,6 @@ struct AnnotatingVisitor
void writeStyle(const uno::Reference<xml::dom::XElement>& xElem, const sal_Int32 nTagId)
{
SAL_INFO ("svg", "writeStyle xElem " << xElem->getTagName());
- sal_Int32 nEmulatedStyleId=0;
- if( maCurrState.maDashArray.size() &&
- maCurrState.meStrokeType != NONE )
- {
- // ODF dashing is severly borked - generate filled shape
- // instead (further down the road - here, we simply
- // emulate a filled style with the next id)
-
- // move all stroke attribs to fill, Clear stroking
- State aEmulatedStrokeState( maCurrState );
- aEmulatedStrokeState.meFillType = maCurrState.meStrokeType;
- aEmulatedStrokeState.mnFillOpacity = maCurrState.mnStrokeOpacity;
- aEmulatedStrokeState.maFillColor = maCurrState.maStrokeColor;
- aEmulatedStrokeState.maFillGradient = maCurrState.maStrokeGradient;
- aEmulatedStrokeState.meFillRule = EVEN_ODD;
- aEmulatedStrokeState.meStrokeType = NONE;
-
- if( writeStyle(aEmulatedStrokeState, nTagId) )
- nEmulatedStyleId = mnCurrStateId;
- else
- nEmulatedStyleId = mrStates.find(aEmulatedStrokeState)->mnStyleId;
- }
sal_Int32 nStyleId=0;
if( writeStyle(maCurrState, nTagId) )
@@ -726,9 +710,7 @@ struct AnnotatingVisitor
xElem->setAttribute("internal-style-ref",
rtl::OUString::valueOf(
nStyleId)
- +"$"
- +rtl::OUString::valueOf(
- nEmulatedStyleId));
+ +"$0");
}
void push()
@@ -969,12 +951,18 @@ struct AnnotatingVisitor
case XML_STROKE_DASHARRAY:
{
if( aValueUtf8 == "none" )
+ {
maCurrState.maDashArray.clear();
+ maCurrState.meStrokeType = SOLID;
+ }
else if( aValueUtf8 == "inherit" )
maCurrState.maDashArray = maParentStates.back().maDashArray;
else
+ {
parseDashArray(aValueUtf8.getStr(),
maCurrState.maDashArray);
+ maCurrState.meStrokeType = DASH;
+ }
break;
}
case XML_STROKE_OPACITY:
@@ -1668,32 +1656,6 @@ struct ShapeWritingVisitor
maCurrState.maCTM.get(1,1),
maCurrState.maCTM.get(1,2));
- if( aState.meStrokeType != NONE && aState.maDashArray.size() )
- {
- // ODF dashing is severly borked - generate filled polygon instead
- aPolys.clear();
- for( sal_uInt32 i=0; i<rPoly.count(); ++i )
- {
- aPolys.push_back(
- basegfx::tools::stripNeutralPolygons(
- basegfx::tools::prepareForPolygonOperation(
- basegfx::tools::createAreaGeometry(
- rPoly.getB2DPolygon(i),
- aState.mnStrokeWidth/2.0,
- aState.meLineJoin))));
- // TODO(F2): line ends
- }
-
- sal_Int32 nDummyIndex(0);
- aStyleId = xElem->getAttribute(
- "internal-style-ref").getToken(1,'$',nDummyIndex);
- StateMap::iterator pAlternateState=mrStateMap.find(aStyleId.toInt32());
- OSL_ASSERT(pAlternateState != mrStateMap.end());
- aState = pAlternateState->second;
- OSL_ENSURE( pAlternateState == mrStateMap.end(),
- "Doh - where's my alternate style entry?!" );
- }
-
// TODO(F2): separate out shear, rotate etc.
// apply transformation to polygon, to keep draw
// import in 100th mm
@@ -1775,6 +1737,119 @@ static void writeShapes( StatePool& rStat
} // namespace
+struct OfficeStylesWritingVisitor
+{
+ OfficeStylesWritingVisitor( StateMap& rStateMap,
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) :
+ mrStateMap(rStateMap),
+ mxDocumentHandler(xDocumentHandler)
+ {}
+ void operator()( const uno::Reference<xml::dom::XElement>& /*xElem*/ )
+ {
+ }
+ void operator()( const uno::Reference<xml::dom::XElement>& xElem,
+ const uno::Reference<xml::dom::XNamedNodeMap>& /*xAttributes*/ )
+ {
+ rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() );
+ uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() );
+
+ sal_Int32 nDummyIndex(0);
+ rtl::OUString sStyleId(
+ xElem->getAttribute("internal-style-ref").getToken(
+ 0,'$',nDummyIndex));
+ StateMap::iterator pOrigState=mrStateMap.find(
+ sStyleId.toInt32());
+
+ if( pOrigState == mrStateMap.end() )
+ return; // non-exportable element, e.g. linearGradient
+
+ maCurrState = pOrigState->second;
+
+ if( maCurrState.meStrokeType == DASH )
+ {
+ sal_Int32 dots1, dots2;
+ double dots1_length, dots2_length, dash_distance;
+ SvgDashArray2Odf( &dots1, &dots1_length, &dots2, &dots2_length, &dash_distance );
+
+ xAttrs->Clear();
+ xAttrs->AddAttribute( "draw:name", "dash"+sStyleId );
+ xAttrs->AddAttribute( "draw:display-name", "dash"+sStyleId );
+ xAttrs->AddAttribute( "draw:style", "rect" );
+ if ( dots1>0 ) {
+ xAttrs->AddAttribute( "draw:dots1", rtl::OUString::valueOf(dots1) );
+ xAttrs->AddAttribute( "draw:dots1-length", rtl::OUString::valueOf(pt2mm(convLength( rtl::OUString::valueOf(dots1_length), maCurrState, 'h' )))+"mm" );
+ }
+ xAttrs->AddAttribute( "draw:distance", rtl::OUString::valueOf(pt2mm(convLength( rtl::OUString::valueOf(dash_distance), maCurrState, 'h' )))+"mm" );
+ if ( dots2>0 ) {
+ xAttrs->AddAttribute( "draw:dots2", rtl::OUString::valueOf(dots2) );
+ xAttrs->AddAttribute( "draw:dots2-length", rtl::OUString::valueOf(pt2mm(convLength( rtl::OUString::valueOf(dots2_length), maCurrState, 'h' )))+"mm" );
+ }
+
+ mxDocumentHandler->startElement( "draw:stroke-dash", xUnoAttrs);
+ mxDocumentHandler->endElement( "draw:stroke-dash" );
+ }
+ }
+
+ void SvgDashArray2Odf( sal_Int32 *dots1, double *dots1_length, sal_Int32 *dots2, double *dots2_length, double *dash_distance )
+ {
+ *dots1 = 0;
+ *dots1_length = 0;
+ *dots2 = 0;
+ *dots2_length = 0;
+ *dash_distance = 0;
+
+ if( maCurrState.maDashArray.size() == 0 ) {
+ return;
+ }
+
+ double effective_dasharray_size = maCurrState.maDashArray.size();
+ if( maCurrState.maDashArray.size() % 2 == 1 )
+ effective_dasharray_size = maCurrState.maDashArray.size()*2;
+
+ *dash_distance = maCurrState.maDashArray[1%maCurrState.maDashArray.size()];
+ sal_Int32 dist_count = 1;
+ for( int i=3; i<effective_dasharray_size; i+=2 ) {
+ *dash_distance = ((dist_count * *dash_distance) + maCurrState.maDashArray[i%maCurrState.maDashArray.size()])/(dist_count+1);
+ ++dist_count;
+ }
+
+ *dots1 = 1;
+ *dots1_length = maCurrState.maDashArray[0];
+ int i=2;
+ while( ( i<effective_dasharray_size ) && ( maCurrState.maDashArray[i%maCurrState.maDashArray.size()] == *dots1_length ) ) {
+ ++(*dots1);
+ i += 2;
+ }
+ if( i<effective_dasharray_size ) {
+ *dots2 = 1;
+ *dots2_length = maCurrState.maDashArray[i];
+ i+=2;
+ while( ( i<effective_dasharray_size ) && ( maCurrState.maDashArray[i%maCurrState.maDashArray.size()] == *dots2_length ) ) {
+ ++(*dots2);
+ i += 2;
+ }
+ }
+
+ SAL_INFO("svg", "SvgDashArray2Odf " << *dash_distance << " " << *dots1 << " " << *dots1_length << " " << *dots2 << " " << *dots2_length );
+
+ return;
+ }
+
+ void push() {}
+ void pop() {}
+
+ State maCurrState;
+ StateMap& mrStateMap;
+ uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler;
+};
+
+static void writeOfficeStyles( StateMap& rStateMap,
+ const uno::Reference<xml::dom::XElement> xElem,
+ const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl )
+{
+ OfficeStylesWritingVisitor aVisitor( rStateMap, xDocHdl );
+ visitElements( aVisitor, xElem );
+}
#if OSL_DEBUG_LEVEL > 2
struct DumpingVisitor
@@ -1994,6 +2069,9 @@ sal_Bool SVGReader::parseAndConvert()
xAttrs->Clear();
m_xDocumentHandler->startElement( "office:styles", xUnoAttrs);
+ writeOfficeStyles( aStateMap,
+ xDocElem,
+ m_xDocumentHandler);
m_xDocumentHandler->endElement( "office:styles" );
////////////////////////////////////////////////////////////////////
--
1.7.9.5
--------------070102080000010106070705--
More information about the LibreOffice
mailing list