20#include "oodrawimport.h"
24#include <tqdatetime.h>
25#include <tqfileinfo.h>
32#include <KoPageLayout.h>
33#include <KoDocumentInfo.h>
34#include <KoDocument.h>
38#include <kgenericfactory.h>
39#include <KoFilterChain.h>
42#include <shapes/vellipse.h>
43#include <shapes/vrectangle.h>
44#include <shapes/vpolygon.h>
46#include <core/vfill.h>
47#include <core/vgroup.h>
49typedef KGenericFactory<OoDrawImport, KoFilter> OoDrawImportFactory;
50K_EXPORT_COMPONENT_FACTORY( liboodrawimport, OoDrawImportFactory(
"kofficefilters" ) )
53OoDrawImport::OoDrawImport( KoFilter *, const
char *, const TQStringList & )
56 m_styleStack( ooNS::style, ooNS::fo )
58 m_styles.setAutoDelete(
true );
61OoDrawImport::~OoDrawImport()
65KoFilter::ConversionStatus OoDrawImport::convert( TQCString
const & from, TQCString
const & to )
67 kdDebug() <<
"Entering Oodraw Import filter: " << from <<
" - " << to << endl;
69 if( from !=
"application/vnd.sun.xml.draw" || to !=
"application/x-karbon" )
71 kdWarning() <<
"Invalid mimetypes " << from <<
" " << to << endl;
72 return KoFilter::NotImplemented;
75 m_zip =
new KZip( m_chain->inputFile() );
77 if ( !m_zip->open( IO_ReadOnly ) )
79 kdError(30518) <<
"Couldn't open the requested file "<< m_chain->inputFile() << endl;
81 return KoFilter::FileNotFound;
84 KoFilter::ConversionStatus preStatus = openFile();
86 if( preStatus != KoFilter::OK )
104 TQDomDocument docinfo;
105 createDocumentInfo( docinfo );
107 KoStoreDevice* out = m_chain->storageFile(
"documentinfo.xml", KoStore::Write );
110 TQCString info = docinfo.toCString();
113 out->writeBlock( info , info.length() );
117 TQDomDocument outdoc = m_document.saveXML();
119 TQDomElement paper = outdoc.createElement(
"PAPER" );
120 outdoc.documentElement().appendChild( paper );
121 paper.setAttribute(
"format", PG_CUSTOM );
122 paper.setAttribute(
"width", m_document.width() );
123 paper.setAttribute(
"height", m_document.height() );
126 out = m_chain->storageFile(
"maindoc.xml", KoStore::Write );
129 TQCString content = outdoc.toCString();
130 kdDebug() <<
" content :" << content << endl;
131 out->writeBlock( content , content.length() );
136 kdDebug() <<
"######################## OoDrawImport::convert done ####################" << endl;
142void OoDrawImport::createDocumentInfo( TQDomDocument &docinfo )
144 docinfo = KoDocument::createDomDocument(
"document-info" ,
"document-info" ,
"1.1" );
146 OoUtils::createDocumentInfo(m_meta, docinfo);
152KoFilter::ConversionStatus OoDrawImport::openFile()
154 KoFilter::ConversionStatus status = loadAndParse(
"content.xml", m_content );
155 if ( status != KoFilter::OK )
157 kdError(30518) <<
"Content.xml could not be parsed correctly! Aborting!" << endl;
162 TQDomDocument styles;
163 loadAndParse(
"styles.xml", styles );
164 loadAndParse(
"meta.xml", m_meta );
165 loadAndParse(
"settings.xml", m_settings );
167 emit sigProgress( 10 );
168 createStyleMap( styles );
173void OoDrawImport::convert()
175 m_document.saveAsPath(
false );
177 TQDomElement content = m_content.documentElement();
180 TQDomNode automaticStyles = KoDom::namedItemNS( content, ooNS::office,
"automatic-styles" );
181 if( !automaticStyles.isNull() )
182 insertStyles( automaticStyles.toElement() );
184 TQDomNode body = KoDom::namedItemNS( content, ooNS::office,
"body" );
189 TQDomElement drawPage = KoDom::namedItemNS( body, ooNS::draw,
"page" );
190 if( drawPage.isNull() )
193 TQDomElement *master = m_styles[drawPage.attributeNS( ooNS::draw,
"master-page-name", TQString() )];
194 TQDomElement *style = m_styles[master->attributeNS( ooNS::style,
"page-master-name", TQString() )];
195 TQDomElement properties = KoDom::namedItemNS( *style, ooNS::style,
"properties" ).toElement();
197 if( properties.isNull() )
199 m_document.setWidth( 550.0 );
200 m_document.setHeight( 841.0 );
204 m_document.setWidth( KoUnit::parseValue(properties.attributeNS( ooNS::fo,
"page-width", TQString() ) ) );
205 m_document.setHeight( KoUnit::parseValue(properties.attributeNS( ooNS::fo,
"page-height", TQString() ) ) );
209 for( TQDomNode drawPage = body.firstChild(); !drawPage.isNull(); drawPage = drawPage.nextSibling() )
211 TQDomElement dp = drawPage.toElement();
212 m_styleStack.clear();
213 fillStyleStack( dp );
221 parseGroup( 0L, dp );
226KoFilter::ConversionStatus OoDrawImport::loadAndParse(
const TQString& filename, TQDomDocument& doc)
228 return OoUtils::loadAndParse( filename, doc, m_zip);
232OoDrawImport::parseGroup( VGroup *parent,
const TQDomElement& parentobject )
235 for( TQDomNode
object = parentobject.firstChild(); !
object.isNull();
object =
object.nextSibling() )
237 TQDomElement o =
object.toElement();
238 if( o.namespaceURI() != ooNS::draw )
continue;
239 TQString name = o.localName();
240 TQString drawID = o.attributeNS( ooNS::draw,
"id", TQString() );
245 storeObjectStyles( o );
246 VGroup *group =
new VGroup( parent );
248 appendBrush( *group );
250 parseGroup( group, o );
252 else if( name ==
"rect" )
254 storeObjectStyles( o );
255 double x = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"x", TQString() ) );
256 double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg,
"y", TQString() ) ) );
257 double w = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"width", TQString() ) );
258 double h = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"height", TQString() ) );
259 int corner =
static_cast<int>( KoUnit::parseValue( o.attributeNS( ooNS::draw,
"corner-radius", TQString() ) ) );
260 VRectangle *rect =
new VRectangle( parent, KoPoint( x, y ), w, h, corner );
262 appendBrush( *rect );
265 else if( name ==
"circle" || name ==
"ellipse" )
267 storeObjectStyles( o );
268 double w = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"width", TQString() ) );
269 double h = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"height", TQString() ) );
270 double x = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"x", TQString() ) );
271 double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg,
"y", TQString() ) ) ) - h;
272 double start = o.attributeNS( ooNS::draw,
"start-angle", TQString() ).toDouble();
273 double end = o.attributeNS( ooNS::draw,
"end-angle", TQString() ).toDouble();
274 TQString kind = o.attributeNS( ooNS::draw,
"kind", TQString() );
275 VEllipse::VEllipseType type = VEllipse::full;
276 if( !kind.isEmpty() )
278 if( kind ==
"section" )
279 type = VEllipse::cut;
280 else if( kind ==
"cut" )
281 type = VEllipse::section;
282 else if( kind ==
"arc" )
283 type = VEllipse::arc;
285 VEllipse *ellipse =
new VEllipse( parent, KoPoint( x, y ), w, h, type, start, end );
286 appendPen( *ellipse );
289 appendBrush( *ellipse );
292 else if( name ==
"line" )
294 storeObjectStyles( o );
295 VPath *line =
new VPath( parent );
296 double x1 = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"x1", TQString() ) );
297 double y1 = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg,
"y1", TQString() ) ) );
298 double x2 = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"x2", TQString() ) );
299 double y2 = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg,
"y2", TQString() ) ) );
300 line->moveTo( KoPoint( x1, y1 ) );
301 line->lineTo( KoPoint( x2, y2 ) );
303 appendBrush( *line );
306 else if( name ==
"polyline" )
308 storeObjectStyles( o );
309 VPath *polyline =
new VPath( parent );
310 appendPoints( *polyline, o);
311 appendPen( *polyline );
312 appendBrush( *polyline );
315 else if( name ==
"polygon" )
317 storeObjectStyles( o );
320 VPath *polygon =
new VPath( parent );
321 appendPoints( *polygon, o );
322 appendPen( *polygon );
323 appendBrush( *polygon );
326 else if( name ==
"path" )
328 storeObjectStyles( o );
329 VPath *path =
new VPath( parent );
330 path->loadSvgPath( o.attributeNS( ooNS::svg,
"d", TQString() ) );
331 KoRect rect = parseViewBox( o );
332 double x = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"x", TQString() ) );
333 double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg,
"y", TQString() ) ) );
334 double w = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"width", TQString() ) );
335 double h = KoUnit::parseValue( o.attributeNS( ooNS::svg,
"height", TQString() ) );
337 mat.translate( x, y );
338 mat.scale( w / rect.width(), -h / rect.height() );
339 path->transform( mat );
341 appendBrush( *path );
353 kdDebug() <<
"Unsupported object '" << name <<
"'" << endl;
357 parent->append( obj );
359 m_document.append( obj );
364OoDrawImport::appendPen( VObject &obj )
366 if( m_styleStack.hasAttributeNS( ooNS::draw,
"stroke" ) )
370 if( m_styleStack.attributeNS( ooNS::draw,
"stroke" ) ==
"none" )
371 stroke.setType( VStroke::none );
372 else if( m_styleStack.attributeNS( ooNS::draw,
"stroke" ) ==
"solid" )
373 stroke.setType( VStroke::solid );
374 else if( m_styleStack.attributeNS( ooNS::draw,
"stroke" ) ==
"dash" )
376 TQValueList<float> dashes;
377 stroke.setType( VStroke::solid );
378 TQString style = m_styleStack.attributeNS( ooNS::draw,
"stroke-dash" );
379 if( style ==
"Ultrafine Dashed" ||
380 style ==
"Fine Dashed (var)" || style ==
"Dashed (var)" )
381 stroke.dashPattern().setArray( dashes << 2 << 2 );
382 else if( style ==
"Fine Dashed" )
383 stroke.dashPattern().setArray( dashes << 10 << 10 );
384 else if( style ==
"Fine Dotted" || style ==
"Ultrafine Dotted (var)" ||
385 style ==
"Line with Fine Dots" )
386 stroke.dashPattern().setArray( dashes << 2 << 10 );
387 else if( style ==
"3 Dashes 3 Dots (var)" || style ==
"Ultrafine 2 Dots 3 Dashes" )
388 stroke.dashPattern().setArray( dashes << 3 << 3 );
389 else if( style ==
"2 Dots 1 Dash" )
390 stroke.dashPattern().setArray( dashes << 2 << 1 );
392 if( m_styleStack.hasAttributeNS( ooNS::svg,
"stroke-width" ) )
394 double lwidth = KoUnit::parseValue( m_styleStack.attributeNS( ooNS::svg,
"stroke-width" ) );
397 stroke.setLineWidth( lwidth );
399 if( m_styleStack.hasAttributeNS( ooNS::svg,
"stroke-color" ) )
402 parseColor( c, m_styleStack.attributeNS( ooNS::svg,
"stroke-color" ) );
403 stroke.setColor( c );
406 obj.setStroke( stroke );
411OoDrawImport::appendBrush( VObject &obj )
413 if( m_styleStack.hasAttributeNS( ooNS::draw,
"fill" ) )
415 const TQString fill = m_styleStack.attributeNS( ooNS::draw,
"fill" );
418 if( fill ==
"solid" )
420 f.setType( VFill::solid );
421 if( m_styleStack.hasAttributeNS( ooNS::draw,
"fill-color" ) )
424 parseColor( c, m_styleStack.attributeNS( ooNS::draw,
"fill-color" ) );
428 else if( fill ==
"gradient" )
431 gradient.clearStops();
432 gradient.setRepeatMethod( VGradient::none );
433 TQString style = m_styleStack.attributeNS( ooNS::draw,
"fill-gradient-name" );
435 TQDomElement* draw = m_draws[style];
439 if( draw->hasAttributeNS( ooNS::draw,
"border" ) )
440 border += draw->attributeNS( ooNS::draw,
"border", TQString() ).remove(
'%' ).toDouble() / 100.0;
442 parseColor( c, draw->attributeNS( ooNS::draw,
"start-color", TQString() ) );
443 gradient.addStop( c, border, 0.5 );
444 parseColor( c, draw->attributeNS( ooNS::draw,
"end-color", TQString() ) );
445 gradient.addStop( c, 1.0, 0.5 );
447 TQString type = draw->attributeNS( ooNS::draw,
"style", TQString() );
448 if( type ==
"linear" || type ==
"axial" )
450 gradient.setType( VGradient::linear );
451 int angle = draw->attributeNS( ooNS::draw,
"angle", TQString() ).toInt() / 10;
454 angle = abs( angle );
455 angle -= ( (int) ( angle / 360 ) ) * 360;
459 int lower, upper, nearAngle = 0;
460 for ( lower = 0, upper = 45; upper < 360; lower += 45, upper += 45 )
464 int distanceToUpper = abs( angle - upper );
465 int distanceToLower = abs( angle - lower );
466 nearAngle = distanceToUpper > distanceToLower ? lower : upper;
470 KoRect rect = obj.boundingBox();
471 KoPoint origin, vector;
473 kdDebug() <<
"nearAngle: " << nearAngle << endl;
474 if( nearAngle == 0 || nearAngle == 180 )
476 origin.setX( rect.x() + rect.width() );
477 origin.setY( rect.y() + rect.height());
478 vector.setX( rect.x() + rect.width() );
479 vector.setY( rect.y() );
481 else if( nearAngle == 90 || nearAngle == 270 )
483 origin.setX( rect.x() );
484 origin.setY( rect.y() + rect.height() );
485 vector.setX( rect.x() + rect.width() );
486 vector.setY( rect.y() + rect.height() );
488 else if( nearAngle == 45 || nearAngle == 225 )
490 origin.setX( rect.x() );
491 origin.setY( rect.y() );
492 vector.setX( rect.x() + rect.width() );
493 vector.setY( rect.y() + rect.height() );
495 else if( nearAngle == 135 || nearAngle == 315 )
497 origin.setX( rect.x() + rect.width() );
498 origin.setY( rect.y() + rect.height() );
499 vector.setX( rect.x() );
500 vector.setY( rect.y() );
503 gradient.setOrigin( origin );
504 gradient.setVector( vector );
506 else if( type ==
"radial" || type ==
"ellipsoid" )
508 gradient.setType( VGradient::radial );
517 if( draw->hasAttributeNS( ooNS::draw,
"cx" ) )
518 x = draw->attributeNS( ooNS::draw,
"cx", TQString() ).remove(
'%' ).toDouble() / 100.0;
522 if( draw->hasAttributeNS( ooNS::draw,
"cy" ) )
523 y = draw->attributeNS( ooNS::draw,
"cy", TQString() ).remove(
'%' ).toDouble() / 100.0;
527 KoRect rect = obj.boundingBox();
528 gradient.setOrigin( KoPoint( rect.x() + x * rect.width(),
529 rect.y() + y * rect.height() ) );
530 gradient.setFocalPoint( KoPoint( rect.x() + x * rect.width(),
531 rect.y() + y * rect.height() ) );
532 gradient.setVector( KoPoint( rect.x() + rect.width(),
533 rect.y() + y * rect.height() ) );
535 f.gradient() = gradient;
536 f.setType( VFill::grad );
566OoDrawImport::createStyleMap( TQDomDocument &docstyles )
568 TQDomElement styles = docstyles.documentElement();
569 if( styles.isNull() )
572 TQDomNode fixedStyles = KoDom::namedItemNS( styles, ooNS::office,
"styles" );
573 if( !fixedStyles.isNull() )
575 insertDraws( fixedStyles.toElement() );
576 insertStyles( fixedStyles.toElement() );
578 TQDomNode automaticStyles = KoDom::namedItemNS( styles, ooNS::office,
"automatic-styles" );
579 if( !automaticStyles.isNull() )
580 insertStyles( automaticStyles.toElement() );
582 TQDomNode masterStyles = KoDom::namedItemNS( styles, ooNS::office,
"master-styles" );
583 if( !masterStyles.isNull() )
584 insertStyles( masterStyles.toElement() );
588OoDrawImport::insertDraws(
const TQDomElement& styles )
590 for( TQDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
592 TQDomElement e = n.toElement();
594 if( !e.hasAttributeNS( ooNS::draw,
"name" ) )
597 TQString name = e.attributeNS( ooNS::draw,
"name", TQString() );
598 m_draws.insert( name,
new TQDomElement( e ) );
604OoDrawImport::insertStyles(
const TQDomElement& styles )
606 for ( TQDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
608 TQDomElement e = n.toElement();
610 if( !e.hasAttributeNS( ooNS::style,
"name" ) )
613 TQString name = e.attributeNS( ooNS::style,
"name", TQString() );
614 m_styles.insert( name,
new TQDomElement( e ) );
620OoDrawImport::fillStyleStack(
const TQDomElement&
object )
623 if(
object.hasAttributeNS( ooNS::presentation,
"style-name" ) )
624 addStyles( m_styles[
object.attributeNS( ooNS::presentation,
"style-name", TQString() )] );
626 if(
object.hasAttributeNS( ooNS::draw,
"style-name" ) )
627 addStyles( m_styles[
object.attributeNS( ooNS::draw,
"style-name", TQString() )] );
629 if(
object.hasAttributeNS( ooNS::draw,
"text-style-name" ) )
630 addStyles( m_styles[
object.attributeNS( ooNS::draw,
"text-style-name", TQString() )] );
632 if(
object.hasAttributeNS( ooNS::text,
"style-name" ) )
633 addStyles( m_styles[
object.attributeNS( ooNS::text,
"style-name", TQString() )] );
637OoDrawImport::addStyles(
const TQDomElement* style )
640 if( style->hasAttributeNS( ooNS::style,
"parent-style-name" ) )
641 addStyles( m_styles[style->attributeNS( ooNS::style,
"parent-style-name", TQString() )] );
643 m_styleStack.push( *style );
647OoDrawImport::storeObjectStyles(
const TQDomElement&
object )
650 fillStyleStack(
object );
655OoDrawImport::parseViewBox(
const TQDomElement&
object )
658 if( !
object.attributeNS( ooNS::svg,
"viewBox", TQString() ).isEmpty() )
661 TQString viewbox(
object.attributeNS( ooNS::svg,
"viewBox", TQString() ) );
662 TQStringList points = TQStringList::split(
' ', viewbox.replace(
',',
' ').simplifyWhiteSpace() );
664 rect.setX( points[0].toFloat() );
665 rect.setY( points[1].toFloat() );
666 rect.setWidth( points[2].toFloat() );
667 rect.setHeight( points[3].toFloat() );
673OoDrawImport::appendPoints(VPath &path,
const TQDomElement&
object)
675 double x = KoUnit::parseValue(
object.attributeNS( ooNS::svg,
"x", TQString() ) );
676 double y = KoUnit::parseValue(
object.attributeNS( ooNS::svg,
"y", TQString() ) );
677 double w = KoUnit::parseValue(
object.attributeNS( ooNS::svg,
"width", TQString() ) );
678 double h = KoUnit::parseValue(
object.attributeNS( ooNS::svg,
"height", TQString() ) );
680 KoRect rect = parseViewBox(
object );
681 rect.setX( rect.x() + x );
682 rect.setY( rect.y() + y );
684 TQStringList ptList = TQStringList::split(
' ',
object.attributeNS( ooNS::draw,
"points", TQString() ) );
690 for( TQStringList::Iterator it = ptList.begin(); it != ptList.end(); ++it )
692 tmp_x = rect.x() + ( (*it).section(
',', 0, 0 ).toInt() * w ) / rect.width();
693 tmp_y = rect.y() + ( (*it).section(
',', 1, 1 ).toInt() * h ) / rect.height();
696 point.setY( ymirror( tmp_y ) );
699 path.moveTo( point );
703 path.lineTo( point );
708OoDrawImport::parseColor( VColor &color,
const TQString &s )
710 if( s.startsWith(
"rgb(" ) )
712 TQString parse = s.stripWhiteSpace();
713 TQStringList colors = TQStringList::split(
',', parse );
714 TQString r = colors[0].right( ( colors[0].length() - 4 ) );
715 TQString g = colors[1];
716 TQString b = colors[2].left( ( colors[2].length() - 1 ) );
718 if( r.contains(
"%" ) )
720 r = r.left( r.length() - 1 );
721 r = TQString::number(
int( (
double( 255 * r.toDouble() ) / 100.0 ) ) );
724 if( g.contains(
"%" ) )
726 g = g.left( g.length() - 1 );
727 g = TQString::number(
int( (
double( 255 * g.toDouble() ) / 100.0 ) ) );
730 if( b.contains(
"%" ) )
732 b = b.left( b.length() - 1 );
733 b = TQString::number(
int( (
double( 255 * b.toDouble() ) / 100.0 ) ) );
736 TQColor c( r.toInt(), g.toInt(), b.toInt() );
737 color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
741 TQString rgbColor = s.stripWhiteSpace();
743 if( rgbColor.startsWith(
"#" ) )
744 c.setNamedColor( rgbColor );
747 color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
752OoDrawImport::ymirror(
double y )
754 return m_document.height() - y;
757#include "oodrawimport.moc"