filters

oodrawimport.cpp
1/* This file is part of the KDE project
2 Copyright (c) 2003 Rob Buis <buis@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "oodrawimport.h"
21
22#include <math.h>
23
24#include <tqdatetime.h>
25#include <tqfileinfo.h>
26#include <tqdir.h>
27
28#include <kzip.h>
29#include <karchive.h>
30#include <kdebug.h>
31#include <KoUnit.h>
32#include <KoPageLayout.h>
33#include <KoDocumentInfo.h>
34#include <KoDocument.h>
35#include <ooutils.h>
36#include <KoDom.h>
37
38#include <kgenericfactory.h>
39#include <KoFilterChain.h>
40#include <KoGlobal.h>
41
42#include <shapes/vellipse.h>
43#include <shapes/vrectangle.h>
44#include <shapes/vpolygon.h>
45
46#include <core/vfill.h>
47#include <core/vgroup.h>
48
49typedef KGenericFactory<OoDrawImport, KoFilter> OoDrawImportFactory;
50K_EXPORT_COMPONENT_FACTORY( liboodrawimport, OoDrawImportFactory( "kofficefilters" ) )
51
52
53OoDrawImport::OoDrawImport( KoFilter *, const char *, const TQStringList & )
54 : KoFilter(),
55 m_styles( 23, true ),
56 m_styleStack( ooNS::style, ooNS::fo )
57{
58 m_styles.setAutoDelete( true );
59}
60
61OoDrawImport::~OoDrawImport()
62{
63}
64
65KoFilter::ConversionStatus OoDrawImport::convert( TQCString const & from, TQCString const & to )
66{
67 kdDebug() << "Entering Oodraw Import filter: " << from << " - " << to << endl;
68
69 if( from != "application/vnd.sun.xml.draw" || to != "application/x-karbon" )
70 {
71 kdWarning() << "Invalid mimetypes " << from << " " << to << endl;
72 return KoFilter::NotImplemented;
73 }
74
75 m_zip = new KZip( m_chain->inputFile() );
76
77 if ( !m_zip->open( IO_ReadOnly ) )
78 {
79 kdError(30518) << "Couldn't open the requested file "<< m_chain->inputFile() << endl;
80 delete m_zip;
81 return KoFilter::FileNotFound;
82 }
83
84 KoFilter::ConversionStatus preStatus = openFile();
85
86 if( preStatus != KoFilter::OK )
87 {
88 m_zip->close();
89 delete m_zip;
90 return preStatus;
91 }
92/*TQDomDocument docinfo;
93 createDocumentInfo( docinfo );
94
95// store document info
96KoStoreDevice* out = m_chain->storageFile( "documentinfo.xml", KoStore::Write );
97if( out )
98{
99TQCString info = docinfo.toCString();
100//kdDebug() << " info :" << info << endl;
101// WARNING: we cannot use KoStore::write(const TQByteArray&) because it gives an extra NULL character at the end.
102out->writeBlock( info , info.length() );
103}*/
104 TQDomDocument docinfo;
105 createDocumentInfo( docinfo );
106 // store document info
107 KoStoreDevice* out = m_chain->storageFile( "documentinfo.xml", KoStore::Write );
108 if( out )
109 {
110 TQCString info = docinfo.toCString();
111 //kdDebug(30518) << " info :" << info << endl;
112 // WARNING: we cannot use KoStore::write(const TQByteArray&) because it gives an extra NULL character at the end.
113 out->writeBlock( info , info.length() );
114 }
115
116 convert();
117 TQDomDocument outdoc = m_document.saveXML();
118 // add paper info, we always need custom for svg (Rob)
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() );
124
125 // store document content
126 out = m_chain->storageFile( "maindoc.xml", KoStore::Write );
127 if( out )
128 {
129 TQCString content = outdoc.toCString();
130 kdDebug() << " content :" << content << endl;
131 out->writeBlock( content , content.length() );
132 }
133 m_zip->close();
134 delete m_zip;
135
136 kdDebug() << "######################## OoDrawImport::convert done ####################" << endl;
137
138 return KoFilter::OK;
139}
140
141// Very related to OoWriterImport::createDocumentInfo
142void OoDrawImport::createDocumentInfo( TQDomDocument &docinfo )
143{
144 docinfo = KoDocument::createDomDocument( "document-info" /*DTD name*/, "document-info" /*tag name*/, "1.1" );
145
146 OoUtils::createDocumentInfo(m_meta, docinfo);
147 //kdDebug(30518) << " meta-info :" << m_meta.toCString() << endl;
148}
149
150
151// Very related to OoWriterImport::openFile()
152KoFilter::ConversionStatus OoDrawImport::openFile()
153{
154 KoFilter::ConversionStatus status = loadAndParse( "content.xml", m_content );
155 if ( status != KoFilter::OK )
156 {
157 kdError(30518) << "Content.xml could not be parsed correctly! Aborting!" << endl;
158 return status;
159 }
160
161 // We do not stop if the following calls fail.
162 TQDomDocument styles;
163 loadAndParse( "styles.xml", styles );
164 loadAndParse( "meta.xml", m_meta );
165 loadAndParse( "settings.xml", m_settings );
166
167 emit sigProgress( 10 );
168 createStyleMap( styles );
169
170 return KoFilter::OK;
171}
172
173void OoDrawImport::convert()
174{
175 m_document.saveAsPath( false );
176
177 TQDomElement content = m_content.documentElement();
178
179 // content.xml contains some automatic-styles that we need to store
180 TQDomNode automaticStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
181 if( !automaticStyles.isNull() )
182 insertStyles( automaticStyles.toElement() );
183
184 TQDomNode body = KoDom::namedItemNS( content, ooNS::office, "body" );
185 if( body.isNull() )
186 return;
187
188 // we take the settings of the first slide for the whole document.
189 TQDomElement drawPage = KoDom::namedItemNS( body, ooNS::draw, "page" );
190 if( drawPage.isNull() ) // no pages? give up.
191 return;
192
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();
196
197 if( properties.isNull() )
198 {
199 m_document.setWidth( 550.0 );
200 m_document.setHeight( 841.0 );
201 }
202 else
203 {
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() ) ) );
206 }
207
208 // parse all pages
209 for( TQDomNode drawPage = body.firstChild(); !drawPage.isNull(); drawPage = drawPage.nextSibling() )
210 {
211 TQDomElement dp = drawPage.toElement();
212 m_styleStack.clear(); // remove all styles
213 fillStyleStack( dp );
214 //m_styleStack.setPageMark();
215
216 // set the pagetitle
217 //TQDomElement titleElement = doc.createElement( "Title" );
218 //titleElement.setAttribute( "title", dp.attributeNS( "name" ) );
219 //pageTitleElement.appendChild( titleElement );
220
221 parseGroup( 0L, dp );
222 }
223}
224
225
226KoFilter::ConversionStatus OoDrawImport::loadAndParse(const TQString& filename, TQDomDocument& doc)
227{
228 return OoUtils::loadAndParse( filename, doc, m_zip);
229}
230
231void
232OoDrawImport::parseGroup( VGroup *parent, const TQDomElement& parentobject )
233{
234 // parse all objects
235 for( TQDomNode object = parentobject.firstChild(); !object.isNull(); object = object.nextSibling() )
236 {
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() );
241 VObject *obj = 0L;
242
243 if( name == "g" ) // polyline
244 {
245 storeObjectStyles( o );
246 VGroup *group = new VGroup( parent );
247 appendPen( *group );
248 appendBrush( *group );
249 obj = group;
250 parseGroup( group, o );
251 }
252 else if( name == "rect" ) // rectangle
253 {
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 );
261 appendPen( *rect );
262 appendBrush( *rect );
263 obj = rect;
264 }
265 else if( name == "circle" || name == "ellipse" )
266 {
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() )
277 {
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;
284 }
285 VEllipse *ellipse = new VEllipse( parent, KoPoint( x, y ), w, h, type, start, end );
286 appendPen( *ellipse );
287 // arc has no brush
288 if( kind != "arc" )
289 appendBrush( *ellipse );
290 obj = ellipse;
291 }
292 else if( name == "line" ) // line
293 {
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 ) );
302 appendPen( *line );
303 appendBrush( *line );
304 obj = line;
305 }
306 else if( name == "polyline" ) // polyline
307 {
308 storeObjectStyles( o );
309 VPath *polyline = new VPath( parent );
310 appendPoints( *polyline, o);
311 appendPen( *polyline );
312 appendBrush( *polyline );
313 obj = polyline;
314 }
315 else if( name == "polygon" ) // polygon
316 {
317 storeObjectStyles( o );
318 //VPolygon *polygon = new VPolygon( parent );
319 //polygon->load( o );
320 VPath *polygon = new VPath( parent );
321 appendPoints( *polygon, o );
322 appendPen( *polygon );
323 appendBrush( *polygon );
324 obj = polygon;
325 }
326 else if( name == "path" ) // path
327 {
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() ) );
336 TQWMatrix mat;
337 mat.translate( x, y );
338 mat.scale( w / rect.width(), -h / rect.height() );
339 path->transform( mat );
340 appendPen( *path );
341 appendBrush( *path );
342 obj = path;
343 }
344/*else if( name == "draw:image" ) // image
345{
346storeObjectStyles( o );
347e = doc.createElement( "OBJECT" );
348e.setAttribute( "type", 0 );
349appendImage( doc, e, pictureElement, o );
350}*/
351 else
352 {
353 kdDebug() << "Unsupported object '" << name << "'" << endl;
354 continue;
355 }
356 if( parent && obj )
357 parent->append( obj );
358 else if( obj )
359 m_document.append( obj );
360 }
361}
362
363void
364OoDrawImport::appendPen( VObject &obj )
365{
366 if( m_styleStack.hasAttributeNS( ooNS::draw, "stroke" ) )
367 {
368 VStroke stroke;
369
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" )
375 {
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 );
391 }
392 if( m_styleStack.hasAttributeNS( ooNS::svg, "stroke-width" ) )
393 {
394 double lwidth = KoUnit::parseValue( m_styleStack.attributeNS( ooNS::svg, "stroke-width" ) );
395 if( lwidth == 0 )
396 lwidth = 1.0;
397 stroke.setLineWidth( lwidth );
398 }
399 if( m_styleStack.hasAttributeNS( ooNS::svg, "stroke-color" ) )
400 {
401 VColor c;
402 parseColor( c, m_styleStack.attributeNS( ooNS::svg, "stroke-color" ) );
403 stroke.setColor( c );
404 }
405
406 obj.setStroke( stroke );
407 }
408}
409
410void
411OoDrawImport::appendBrush( VObject &obj )
412{
413 if( m_styleStack.hasAttributeNS( ooNS::draw, "fill" ) )
414 {
415 const TQString fill = m_styleStack.attributeNS( ooNS::draw, "fill" );
416 VFill f;
417
418 if( fill == "solid" )
419 {
420 f.setType( VFill::solid );
421 if( m_styleStack.hasAttributeNS( ooNS::draw, "fill-color" ) )
422 {
423 VColor c;
424 parseColor( c, m_styleStack.attributeNS( ooNS::draw, "fill-color" ) );
425 f.setColor( c );
426 }
427 }
428 else if( fill == "gradient" )
429 {
430 VGradient gradient;
431 gradient.clearStops();
432 gradient.setRepeatMethod( VGradient::none );
433 TQString style = m_styleStack.attributeNS( ooNS::draw, "fill-gradient-name" );
434
435 TQDomElement* draw = m_draws[style];
436 if( draw )
437 {
438 double border = 0.0;
439 if( draw->hasAttributeNS( ooNS::draw, "border" ) )
440 border += draw->attributeNS( ooNS::draw, "border", TQString() ).remove( '%' ).toDouble() / 100.0;
441 VColor c;
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 );
446
447 TQString type = draw->attributeNS( ooNS::draw, "style", TQString() );
448 if( type == "linear" || type == "axial" )
449 {
450 gradient.setType( VGradient::linear );
451 int angle = draw->attributeNS( ooNS::draw, "angle", TQString() ).toInt() / 10;
452
453 // make sure the angle is between 0 and 359
454 angle = abs( angle );
455 angle -= ( (int) ( angle / 360 ) ) * 360;
456
457 // What we are trying to do here is to find out if the given
458 // angle belongs to a horizontal, vertical or diagonal gradient.
459 int lower, upper, nearAngle = 0;
460 for ( lower = 0, upper = 45; upper < 360; lower += 45, upper += 45 )
461 {
462 if( upper >= angle )
463 {
464 int distanceToUpper = abs( angle - upper );
465 int distanceToLower = abs( angle - lower );
466 nearAngle = distanceToUpper > distanceToLower ? lower : upper;
467 break;
468 }
469 }
470 KoRect rect = obj.boundingBox();
471 KoPoint origin, vector;
472 // nearAngle should now be one of: 0, 45, 90, 135, 180...
473 kdDebug() << "nearAngle: " << nearAngle << endl;
474 if( nearAngle == 0 || nearAngle == 180 )
475 {
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() );
480 }
481 else if( nearAngle == 90 || nearAngle == 270 )
482 {
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() );
487 }
488 else if( nearAngle == 45 || nearAngle == 225 )
489 {
490 origin.setX( rect.x() );
491 origin.setY( rect.y() );
492 vector.setX( rect.x() + rect.width() );
493 vector.setY( rect.y() + rect.height() );
494 }
495 else if( nearAngle == 135 || nearAngle == 315 )
496 {
497 origin.setX( rect.x() + rect.width() );
498 origin.setY( rect.y() + rect.height() );
499 vector.setX( rect.x() );
500 vector.setY( rect.y() );
501 }
502
503 gradient.setOrigin( origin );
504 gradient.setVector( vector );
505 }
506 else if( type == "radial" || type == "ellipsoid" )
507 {
508 gradient.setType( VGradient::radial );
509//else if( type == "square" || type == "rectangular" )
510//gradient.setAttribute( "type", 6 ); // rectangle
511//else if( type == "axial" )
512//gradient.setAttribute( "type", 7 ); // pipecross
513
514 // Hard to map between x- and y-center settings of oodraw
515 // and (un-)balanced settings of kpresenter. Let's try it.
516 double x, y;
517 if( draw->hasAttributeNS( ooNS::draw, "cx" ) )
518 x = draw->attributeNS( ooNS::draw, "cx", TQString() ).remove( '%' ).toDouble() / 100.0;
519 else
520 x = 0.5;
521
522 if( draw->hasAttributeNS( ooNS::draw, "cy" ) )
523 y = draw->attributeNS( ooNS::draw, "cy", TQString() ).remove( '%' ).toDouble() / 100.0;
524 else
525 y = 0.5;
526
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() ) );
534 }
535 f.gradient() = gradient;
536 f.setType( VFill::grad );
537 }
538 }
539 obj.setFill( f );
540 }
541/*else if( fill == "hatch" )
542{
543TQDomElement brush = doc.createElement( "BRUSH" );
544TQString style = m_styleStack.attributeNS( "fill-hatch-name" );
545if( style == "Black 0 Degrees" )
546brush.setAttribute( "style", 9 );
547else if( style == "Black 90 Degrees" )
548brush.setAttribute( "style", 10 );
549else if( style == "Red Crossed 0 Degrees" || style == "Blue Crossed 0 Degrees" )
550brush.setAttribute( "style", 11 );
551else if( style == "Black 45 Degrees" || style == "Black 45 Degrees Wide" )
552brush.setAttribute( "style", 12 );
553else if( style == "Black -45 Degrees" )
554brush.setAttribute( "style", 13 );
555else if( style == "Red Crossed 45 Degrees" || style == "Blue Crossed 45 Degrees" )
556brush.setAttribute( "style", 14 );
557
558TQDomElement* draw = m_draws[style];
559if( draw && draw->hasAttributeNS( "color" ) )
560brush.setAttribute( "color", draw->attributeNS( "color" ) );
561e.appendChild( brush );
562}*/
563}
564
565void
566OoDrawImport::createStyleMap( TQDomDocument &docstyles )
567{
568 TQDomElement styles = docstyles.documentElement();
569 if( styles.isNull() )
570 return;
571
572 TQDomNode fixedStyles = KoDom::namedItemNS( styles, ooNS::office, "styles" );
573 if( !fixedStyles.isNull() )
574 {
575 insertDraws( fixedStyles.toElement() );
576 insertStyles( fixedStyles.toElement() );
577 }
578 TQDomNode automaticStyles = KoDom::namedItemNS( styles, ooNS::office, "automatic-styles" );
579 if( !automaticStyles.isNull() )
580 insertStyles( automaticStyles.toElement() );
581
582 TQDomNode masterStyles = KoDom::namedItemNS( styles, ooNS::office, "master-styles" );
583 if( !masterStyles.isNull() )
584 insertStyles( masterStyles.toElement() );
585}
586
587void
588OoDrawImport::insertDraws( const TQDomElement& styles )
589{
590 for( TQDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
591 {
592 TQDomElement e = n.toElement();
593
594 if( !e.hasAttributeNS( ooNS::draw, "name" ) )
595 continue;
596
597 TQString name = e.attributeNS( ooNS::draw, "name", TQString() );
598 m_draws.insert( name, new TQDomElement( e ) );
599 }
600}
601
602
603void
604OoDrawImport::insertStyles( const TQDomElement& styles )
605{
606 for ( TQDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
607 {
608 TQDomElement e = n.toElement();
609
610 if( !e.hasAttributeNS( ooNS::style, "name" ) )
611 continue;
612
613 TQString name = e.attributeNS( ooNS::style, "name", TQString() );
614 m_styles.insert( name, new TQDomElement( e ) );
615 //kdDebug() << "Style: '" << name << "' loaded " << endl;
616 }
617}
618
619void
620OoDrawImport::fillStyleStack( const TQDomElement& object )
621{
622 // find all styles associated with an object and push them on the stack
623 if( object.hasAttributeNS( ooNS::presentation, "style-name" ) )
624 addStyles( m_styles[object.attributeNS( ooNS::presentation, "style-name", TQString() )] );
625
626 if( object.hasAttributeNS( ooNS::draw, "style-name" ) )
627 addStyles( m_styles[object.attributeNS( ooNS::draw, "style-name", TQString() )] );
628
629 if( object.hasAttributeNS( ooNS::draw, "text-style-name" ) )
630 addStyles( m_styles[object.attributeNS( ooNS::draw, "text-style-name", TQString() )] );
631
632 if( object.hasAttributeNS( ooNS::text, "style-name" ) )
633 addStyles( m_styles[object.attributeNS( ooNS::text, "style-name", TQString() )] );
634}
635
636void
637OoDrawImport::addStyles( const TQDomElement* style )
638{
639 // this function is necessary as parent styles can have parents themself
640 if( style->hasAttributeNS( ooNS::style, "parent-style-name" ) )
641 addStyles( m_styles[style->attributeNS( ooNS::style, "parent-style-name", TQString() )] );
642
643 m_styleStack.push( *style );
644}
645
646void
647OoDrawImport::storeObjectStyles( const TQDomElement& object )
648{
649 //m_styleStack.clearPageMark(); // remove styles of previous object
650 fillStyleStack( object );
651 //m_styleStack.setObjectMark();
652}
653
654KoRect
655OoDrawImport::parseViewBox( const TQDomElement& object )
656{
657 KoRect rect;
658 if( !object.attributeNS( ooNS::svg, "viewBox", TQString() ).isEmpty() )
659 {
660 // allow for viewbox def with ',' or whitespace
661 TQString viewbox( object.attributeNS( ooNS::svg, "viewBox", TQString() ) );
662 TQStringList points = TQStringList::split( ' ', viewbox.replace( ',', ' ').simplifyWhiteSpace() );
663
664 rect.setX( points[0].toFloat() );
665 rect.setY( points[1].toFloat() );
666 rect.setWidth( points[2].toFloat() );
667 rect.setHeight( points[3].toFloat() );
668 }
669 return rect;
670}
671
672void
673OoDrawImport::appendPoints(VPath &path, const TQDomElement& object)
674{
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() ) );
679
680 KoRect rect = parseViewBox( object );
681 rect.setX( rect.x() + x );
682 rect.setY( rect.y() + y );
683
684 TQStringList ptList = TQStringList::split( ' ', object.attributeNS( ooNS::draw, "points", TQString() ) );
685
686 TQString pt_x, pt_y;
687 double tmp_x, tmp_y;
688 KoPoint point;
689 bool bFirst = true;
690 for( TQStringList::Iterator it = ptList.begin(); it != ptList.end(); ++it )
691 {
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();
694
695 point.setX( tmp_x );
696 point.setY( ymirror( tmp_y ) );
697 if( bFirst )
698 {
699 path.moveTo( point );
700 bFirst = false;
701 }
702 else
703 path.lineTo( point );
704 }
705}
706
707void
708OoDrawImport::parseColor( VColor &color, const TQString &s )
709{
710 if( s.startsWith( "rgb(" ) )
711 {
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 ) );
717
718 if( r.contains( "%" ) )
719 {
720 r = r.left( r.length() - 1 );
721 r = TQString::number( int( ( double( 255 * r.toDouble() ) / 100.0 ) ) );
722 }
723
724 if( g.contains( "%" ) )
725 {
726 g = g.left( g.length() - 1 );
727 g = TQString::number( int( ( double( 255 * g.toDouble() ) / 100.0 ) ) );
728 }
729
730 if( b.contains( "%" ) )
731 {
732 b = b.left( b.length() - 1 );
733 b = TQString::number( int( ( double( 255 * b.toDouble() ) / 100.0 ) ) );
734 }
735
736 TQColor c( r.toInt(), g.toInt(), b.toInt() );
737 color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
738 }
739 else
740 {
741 TQString rgbColor = s.stripWhiteSpace();
742 TQColor c;
743 if( rgbColor.startsWith( "#" ) )
744 c.setNamedColor( rgbColor );
745 //else
746 // c = parseColor( rgbColor );
747 color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
748 }
749}
750
751double
752OoDrawImport::ymirror( double y )
753{
754 return m_document.height() - y;
755}
756
757#include "oodrawimport.moc"