20#include "xamlimport.h"
22#include <KoFilterChain.h>
23#include <kgenericfactory.h>
27#include <shapes/vellipse.h>
28#include <shapes/vrectangle.h>
29#include <shapes/vpolygon.h>
30#include <commands/vtransformcmd.h>
31#include <core/vsegment.h>
32#include <core/vtext.h>
33#include <core/vglobal.h>
34#include <core/vgroup.h>
35#include <core/vimage.h>
36#include <core/vlayer.h>
39#include <kfilterdev.h>
41typedef KGenericFactory<XAMLImport, KoFilter> XAMLImportFactory;
42K_EXPORT_COMPONENT_FACTORY( libkarbonxamlimport, XAMLImportFactory(
"kofficefilters" ) )
44XAMLImport::XAMLImport(KoFilter *, const
char *, const TQStringList&) :
48 m_gc.setAutoDelete(
true );
51XAMLImport::~XAMLImport()
55KoFilter::ConversionStatus XAMLImport::convert(
const TQCString& from,
const TQCString& to)
58 if( to !=
"application/x-karbon" || from !=
"image/wvg+xml" )
59 return KoFilter::NotImplemented;
63 TQString fileIn ( m_chain->inputFile() );
64 const int result=fileIn.findRev(
'.');
67 strExt=fileIn.mid(result).lower();
73 strMime=
"application/x-gzip";
74 else if (strExt==
".bz2")
75 strMime=
"application/x-bzip2";
79 kdDebug(30514) <<
"File extension: -" << strExt <<
"- Compression: " << strMime << endl;
81 TQIODevice* in = KFilterDev::deviceForFile(fileIn,strMime);
83 if (!in->open(IO_ReadOnly))
85 kdError(30514) <<
"Cannot open file! Aborting!" << endl;
87 return KoFilter::FileNotFound;
91 TQString errormessage;
92 const bool parsed=inpdoc.setContent( in, &errormessage, &line, &col );
97 kdError(30514) <<
"Error while parsing file: "
98 <<
"at line " << line <<
" column: " << col
99 <<
" message: " << errormessage << endl;
101 return KoFilter::ParsingError;
107 KoStoreDevice* out = m_chain->storageFile(
"root", KoStore::Write );
110 kdError(30514) <<
"Unable to open output file!" << endl;
111 return KoFilter::StorageCreationError;
113 TQCString cstring = outdoc.toCString();
114 out->writeBlock( cstring.data(), cstring.length() );
122 XAMLGraphicsContext *gc =
new XAMLGraphicsContext;
123 TQDomElement docElem = inpdoc.documentElement();
124 KoRect bbox( 0, 0, 550.0, 841.0 );
125 double width = !docElem.attribute(
"width" ).isEmpty() ? parseUnit( docElem.attribute(
"width" ),
true,
false, bbox ) : 550.0;
126 double height = !docElem.attribute(
"height" ).isEmpty() ? parseUnit( docElem.attribute(
"height" ),
false,
true, bbox ) : 841.0;
127 m_document.setWidth( width );
128 m_document.setHeight( height );
129 m_outerRect = m_document.boundingBox();
132 if( !docElem.attribute(
"viewBox" ).isEmpty() )
135 TQString viewbox( docElem.attribute(
"viewBox" ) );
136 TQStringList points = TQStringList::split(
' ', viewbox.replace(
',',
' ').simplifyWhiteSpace() );
138 gc->matrix.scale( width / points[2].toFloat() , height / points[3].toFloat() );
139 m_outerRect.setWidth( m_outerRect.width() * ( points[2].toFloat() / width ) );
140 m_outerRect.setHeight( m_outerRect.height() * ( points[3].toFloat() / height ) );
143 parseGroup( 0L, docElem );
147 mat.translate( 0, -m_document.height() );
148 VTransformCmd trafo( 0L, mat );
149 trafo.visit( m_document );
150 outdoc = m_document.saveXML();
156XAMLImport::toPercentage( TQString s )
158 if( s.endsWith(
"%" ) )
159 return s.remove(
'%' ).toDouble();
161 return s.toDouble() * 100.0;
165XAMLImport::fromPercentage( TQString s )
167 if( s.endsWith(
"%" ) )
168 return s.remove(
'%' ).toDouble() / 100.0;
175getNumber(
const char *ptr,
double &number )
177 int integer, exponent;
178 double decimal, frac;
198 while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
199 integer = (integer * 10) + *(ptr++) -
'0';
203 while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
204 decimal += (*(ptr++) -
'0') * (frac *= 0.1);
207 if(*ptr ==
'e' || *ptr ==
'E')
221 while(*ptr !=
'\0' && *ptr >=
'0' && *ptr <=
'9')
224 exponent += *ptr -
'0';
228 number = integer + decimal;
229 number *= sign * pow( (
double)10,
double( expsign * exponent ) );
236XAMLImport::parseUnit(
const TQString &unit,
bool horiz,
bool vert, KoRect bbox )
240 const char *start = unit.latin1();
244 const char *end = getNumber( start, value );
246 if( uint( end - start ) < unit.length() )
248 if( unit.right( 2 ) ==
"pt" )
249 value = ( value / 72.0 ) * DPI;
250 else if( unit.right( 2 ) ==
"cm" )
251 value = ( value / 2.54 ) * DPI;
252 else if( unit.right( 2 ) ==
"pc" )
253 value = ( value / 6.0 ) * DPI;
254 else if( unit.right( 2 ) ==
"mm" )
255 value = ( value / 25.4 ) * DPI;
256 else if( unit.right( 2 ) ==
"in" )
258 else if( unit.right( 2 ) ==
"pt" )
259 value = ( value / 72.0 ) * DPI;
260 else if( unit.right( 2 ) ==
"em" )
261 value = value * m_gc.current()->font.pointSize() / ( sqrt( pow( m_gc.current()->matrix.m11(), 2 ) + pow( m_gc.current()->matrix.m22(), 2 ) ) / sqrt( 2.0 ) );
262 else if( unit.right( 1 ) ==
"%" )
265 value = ( value / 100.0 ) * (sqrt( pow( bbox.width(), 2 ) + pow( bbox.height(), 2 ) ) / sqrt( 2.0 ) );
267 value = ( value / 100.0 ) * bbox.width();
269 value = ( value / 100.0 ) * bbox.height();
288XAMLImport::parseColor(
const TQString &rgbColor )
291 keywordToRGB( rgbColor, r, g, b );
292 return TQColor( r, g, b );
296XAMLImport::parseColor( VColor &color,
const TQString &s )
298 if( s.startsWith(
"rgb(" ) )
300 TQString parse = s.stripWhiteSpace();
301 TQStringList colors = TQStringList::split(
',', parse );
302 TQString r = colors[0].right( ( colors[0].length() - 4 ) );
303 TQString g = colors[1];
304 TQString b = colors[2].left( ( colors[2].length() - 1 ) );
306 if( r.contains(
"%" ) )
308 r = r.left( r.length() - 1 );
309 r = TQString::number(
int( (
double( 255 * r.toDouble() ) / 100.0 ) ) );
312 if( g.contains(
"%" ) )
314 g = g.left( g.length() - 1 );
315 g = TQString::number(
int( (
double( 255 * g.toDouble() ) / 100.0 ) ) );
318 if( b.contains(
"%" ) )
320 b = b.left( b.length() - 1 );
321 b = TQString::number(
int( (
double( 255 * b.toDouble() ) / 100.0 ) ) );
324 TQColor c( r.toInt(), g.toInt(), b.toInt() );
325 color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
329 TQString rgbColor = s.stripWhiteSpace();
331 if( rgbColor.startsWith(
"#" ) )
332 c.setNamedColor( rgbColor );
334 c = parseColor( rgbColor );
335 color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
340XAMLImport::parseColorStops( VGradient *gradient,
const TQDomElement &e )
343 for( TQDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
345 TQDomElement stop = n.toElement();
346 if( stop.tagName() ==
"stop" )
349 TQString temp = stop.attribute(
"offset" );
350 if( temp.contains(
'%' ) )
352 temp = temp.left( temp.length() - 1 );
353 offset = temp.toFloat() / 100.0;
356 offset = temp.toFloat();
358 if( !stop.attribute(
"stop-color" ).isEmpty() )
359 parseColor( c, stop.attribute(
"stop-color" ) );
363 TQString style = stop.attribute(
"style" ).simplifyWhiteSpace();
364 TQStringList substyles = TQStringList::split(
';', style );
365 for( TQStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
367 TQStringList substyle = TQStringList::split(
':', (*it) );
368 TQString command = substyle[0].stripWhiteSpace();
369 TQString params = substyle[1].stripWhiteSpace();
370 if( command ==
"stop-color" )
371 parseColor( c, params );
372 if( command ==
"stop-opacity" )
373 c.setOpacity( params.toDouble() );
377 if( !stop.attribute(
"stop-opacity" ).isEmpty() )
378 c.setOpacity( stop.attribute(
"stop-opacity" ).toDouble() );
379 gradient->addStop( c, offset, 0.5 );
385XAMLImport::parseGradient(
const TQDomElement &e )
387 GradientHelper gradhelper;
388 gradhelper.gradient.clearStops();
389 gradhelper.gradient.setRepeatMethod( VGradient::none );
391 TQString href = e.attribute(
"xlink:href" ).mid( 1 );
392 if( !href.isEmpty() )
395 gradhelper.gradient = m_gradients[ href ].gradient;
398 gradhelper.bbox = e.attribute(
"gradientUnits" ) !=
"userSpaceOnUse";
400 if( e.tagName() ==
"linearGradient" )
402 if( gradhelper.bbox )
404 gradhelper.gradient.setOrigin( KoPoint( toPercentage( e.attribute(
"x1",
"0%" ) ), toPercentage( e.attribute(
"y1",
"0%" ) ) ) );
405 gradhelper.gradient.setVector( KoPoint( toPercentage( e.attribute(
"x2",
"100%" ) ), toPercentage( e.attribute(
"y2",
"0%" ) ) ) );
409 gradhelper.gradient.setOrigin( KoPoint( e.attribute(
"x1" ).toDouble(), e.attribute(
"y1" ).toDouble() ) );
410 gradhelper.gradient.setVector( KoPoint( e.attribute(
"x2" ).toDouble(), e.attribute(
"y2" ).toDouble() ) );
415 if( gradhelper.bbox )
417 gradhelper.gradient.setOrigin( KoPoint( toPercentage( e.attribute(
"cx",
"50%" ) ), toPercentage( e.attribute(
"cy",
"50%" ) ) ) );
418 gradhelper.gradient.setVector( KoPoint( toPercentage( e.attribute(
"cx",
"50%" ) ) + toPercentage( e.attribute(
"r",
"50%" ) ),
419 toPercentage( e.attribute(
"cy",
"50%" ) ) ) );
420 gradhelper.gradient.setFocalPoint( KoPoint( toPercentage( e.attribute(
"fx",
"50%" ) ), toPercentage( e.attribute(
"fy",
"50%" ) ) ) );
424 gradhelper.gradient.setOrigin( KoPoint( e.attribute(
"cx" ).toDouble(), e.attribute(
"cy" ).toDouble() ) );
425 gradhelper.gradient.setFocalPoint( KoPoint( e.attribute(
"fx" ).toDouble(), e.attribute(
"fy" ).toDouble() ) );
426 gradhelper.gradient.setVector( KoPoint( e.attribute(
"cx" ).toDouble() + e.attribute(
"r" ).toDouble(), e.attribute(
"cy" ).toDouble() ) );
428 gradhelper.gradient.setType( VGradient::radial );
431 TQString spreadMethod = e.attribute(
"spreadMethod" );
432 if( !spreadMethod.isEmpty() )
434 if( spreadMethod ==
"reflect" )
435 gradhelper.gradient.setRepeatMethod( VGradient::reflect );
436 else if( spreadMethod ==
"repeat" )
437 gradhelper.gradient.setRepeatMethod( VGradient::repeat );
439 parseColorStops( &gradhelper.gradient, e );
441 gradhelper.gradientTransform = VPath::parseTransform( e.attribute(
"gradientTransform" ) );
442 m_gradients.insert( e.attribute(
"id" ), gradhelper );
446XAMLImport::parsePA( VObject *obj, XAMLGraphicsContext *gc,
const TQString &command,
const TQString ¶ms )
448 VColor fillcolor = gc->fill.color();
449 VColor strokecolor = gc->stroke.color();
451 if( command ==
"fill" )
453 if( params ==
"none" )
454 gc->fill.setType( VFill::none );
455 else if( params.startsWith(
"url(" ) )
457 unsigned int start = params.find(
"#") + 1;
458 unsigned int end = params.findRev(
")");
459 TQString key = params.mid( start, end - start );
460 gc->fill.gradient() = m_gradients[ key ].gradient;
461 if( m_gradients[ key ].bbox )
464 KoRect bbox = obj->boundingBox();
469 double offsetx = parseUnit( TQString(
"%1%" ).arg( gc->fill.gradient().origin().x() ),
true,
false, bbox );
470 double offsety = parseUnit( TQString(
"%1%" ).arg( gc->fill.gradient().origin().y() ),
false,
true, bbox );
471 gc->fill.gradient().setOrigin( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
472 offsetx = parseUnit( TQString(
"%1%" ).arg( gc->fill.gradient().focalPoint().x() ),
true,
false, bbox );
473 offsety = parseUnit( TQString(
"%1%" ).arg( gc->fill.gradient().focalPoint().y() ),
false,
true, bbox );
474 gc->fill.gradient().setFocalPoint( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
475 offsetx = parseUnit( TQString(
"%1%" ).arg( gc->fill.gradient().vector().x() ),
true,
false, bbox );
476 offsety = parseUnit( TQString(
"%1%" ).arg( gc->fill.gradient().vector().y() ),
false,
true, bbox );
477 gc->fill.gradient().setVector( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
484 gc->fill.gradient().transform( m_gradients[ key ].gradientTransform );
485 if( !m_gradients[ key ].bbox )
486 gc->fill.gradient().transform( gc->matrix );
487 gc->fill.setType( VFill::grad );
491 parseColor( fillcolor, params );
492 gc->fill.setType( VFill::solid );
495 else if( command ==
"fill-rule" )
497 if( params ==
"nonzero" )
498 gc->fillRule = winding;
499 else if( params ==
"evenodd" )
500 gc->fillRule = evenOdd;
502 else if( command ==
"stroke" )
504 if( params ==
"none" )
505 gc->stroke.setType( VStroke::none );
506 else if( params.startsWith(
"url(" ) )
508 unsigned int start = params.find(
"#") + 1;
509 unsigned int end = params.findRev(
")");
510 TQString key = params.mid( start, end - start );
511 gc->stroke.gradient() = m_gradients[ key ].gradient;
512 gc->stroke.gradient().transform( m_gradients[ key ].gradientTransform );
513 gc->stroke.gradient().transform( gc->matrix );
514 gc->stroke.setType( VStroke::grad );
518 parseColor( strokecolor, params );
519 gc->stroke.setType( VStroke::solid );
522 else if( command ==
"stroke-width" )
523 gc->stroke.setLineWidth( parseUnit( params,
true,
true, m_outerRect ) );
524 else if( command ==
"stroke-linejoin" )
526 if( params ==
"miter" )
527 gc->stroke.setLineJoin( VStroke::joinMiter );
528 else if( params ==
"round" )
529 gc->stroke.setLineJoin( VStroke::joinRound );
530 else if( params ==
"bevel" )
531 gc->stroke.setLineJoin( VStroke::joinBevel );
533 else if( command ==
"stroke-linecap" )
535 if( params ==
"butt" )
536 gc->stroke.setLineCap( VStroke::capButt );
537 else if( params ==
"round" )
538 gc->stroke.setLineCap( VStroke::capRound );
539 else if( params ==
"square" )
540 gc->stroke.setLineCap( VStroke::capSquare );
542 else if( command ==
"stroke-miterlimit" )
543 gc->stroke.setMiterLimit( params.toFloat() );
544 else if( command ==
"stroke-dasharray" )
546 TQValueList<float> array;
549 TQStringList dashes = TQStringList::split(
' ', params );
550 for( TQStringList::Iterator it = dashes.begin(); it != dashes.end(); ++it )
551 array.append( (*it).toFloat() );
553 gc->stroke.dashPattern().setArray( array );
555 else if( command ==
"stroke-dashoffset" )
556 gc->stroke.dashPattern().setOffset( params.toFloat() );
558 else if( command ==
"stroke-opacity" )
559 strokecolor.setOpacity( fromPercentage( params ) );
560 else if( command ==
"fill-opacity" )
561 fillcolor.setOpacity( fromPercentage( params ) );
562 else if( command ==
"opacity" )
564 fillcolor.setOpacity( fromPercentage( params ) );
565 strokecolor.setOpacity( fromPercentage( params ) );
567 else if( command ==
"font-family" )
569 TQString family = params;
570 family.replace(
'\'' ,
' ' );
571 gc->font.setFamily( family );
573 else if( command ==
"font-size" )
575 float pointSize = parseUnit( params );
576 pointSize *= gc->matrix.m22() > 0 ? gc->matrix.m22() : -1.0 * gc->matrix.m22();
577 gc->font.setPointSizeFloat( pointSize );
579 else if( command ==
"text-decoration" )
581 if( params ==
"line-through" )
582 gc->font.setStrikeOut(
true );
583 else if( params ==
"underline" )
584 gc->font.setUnderline(
true );
586 if( gc->fill.type() != VFill::none )
587 gc->fill.setColor( fillcolor,
false );
589 gc->stroke.setColor( strokecolor );
593XAMLImport::addGraphicContext()
595 XAMLGraphicsContext *gc =
new XAMLGraphicsContext;
598 *gc = *( m_gc.current() );
603XAMLImport::setupTransform(
const TQDomElement &e )
605 XAMLGraphicsContext *gc = m_gc.current();
607 TQWMatrix mat = VPath::parseTransform( e.attribute(
"transform" ) );
608 gc->matrix = mat * gc->matrix;
612XAMLImport::parseStyle( VObject *obj,
const TQDomElement &e )
614 XAMLGraphicsContext *gc = m_gc.current();
618 if( !e.attribute(
"fill" ).isEmpty() )
619 parsePA( obj, gc,
"fill", e.attribute(
"fill" ) );
620 if( !e.attribute(
"fill-rule" ).isEmpty() )
621 parsePA( obj, gc,
"fill-rule", e.attribute(
"fill-rule" ) );
622 if( !e.attribute(
"stroke" ).isEmpty() )
623 parsePA( obj, gc,
"stroke", e.attribute(
"stroke" ) );
624 if( !e.attribute(
"stroke-width" ).isEmpty() )
625 parsePA( obj, gc,
"stroke-width", e.attribute(
"stroke-width" ) );
626 if( !e.attribute(
"stroke-linejoin" ).isEmpty() )
627 parsePA( obj, gc,
"stroke-linejoin", e.attribute(
"stroke-linejoin" ) );
628 if( !e.attribute(
"stroke-linecap" ).isEmpty() )
629 parsePA( obj, gc,
"stroke-linecap", e.attribute(
"stroke-linecap" ) );
630 if( !e.attribute(
"stroke-dasharray" ).isEmpty() )
631 parsePA( obj, gc,
"stroke-dasharray", e.attribute(
"stroke-dasharray" ) );
632 if( !e.attribute(
"stroke-dashoffset" ).isEmpty() )
633 parsePA( obj, gc,
"stroke-dashoffset", e.attribute(
"stroke-dashoffset" ) );
634 if( !e.attribute(
"stroke-opacity" ).isEmpty() )
635 parsePA( obj, gc,
"stroke-opacity", e.attribute(
"stroke-opacity" ) );
636 if( !e.attribute(
"stroke-miterlimit" ).isEmpty() )
637 parsePA( obj, gc,
"stroke-miterlimit", e.attribute(
"stroke-miterlimit" ) );
638 if( !e.attribute(
"fill-opacity" ).isEmpty() )
639 parsePA( obj, gc,
"fill-opacity", e.attribute(
"fill-opacity" ) );
640 if( !e.attribute(
"opacity" ).isEmpty() )
641 parsePA( obj, gc,
"opacity", e.attribute(
"opacity" ) );
644 TQString style = e.attribute(
"style" ).simplifyWhiteSpace();
645 TQStringList substyles = TQStringList::split(
';', style );
646 for( TQStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
648 TQStringList substyle = TQStringList::split(
':', (*it) );
649 TQString command = substyle[0].stripWhiteSpace();
650 TQString params = substyle[1].stripWhiteSpace();
651 parsePA( obj, gc, command, params );
654 obj->setFill( gc->fill );
655 if(
dynamic_cast<VPath *
>( obj ) )
656 dynamic_cast<VPath *
>( obj )->setFillRule( gc->fillRule );
658 double lineWidth = gc->stroke.lineWidth();
659 gc->stroke.setLineWidth( lineWidth * sqrt( pow( m_gc.current()->matrix.m11(), 2 ) + pow( m_gc.current()->matrix.m22(), 2 ) ) / sqrt( 2.0 ) );
660 obj->setStroke( gc->stroke );
661 gc->stroke.setLineWidth( lineWidth );
665XAMLImport::parseFont(
const TQDomElement &e )
667 XAMLGraphicsContext *gc = m_gc.current();
670 if( ! e.attribute(
"font-family" ).isEmpty() )
671 parsePA( 0L, m_gc.current(),
"font-family", e.attribute(
"font-family" ) );
672 if( ! e.attribute(
"font-size" ).isEmpty() )
673 parsePA( 0L, m_gc.current(),
"font-size", e.attribute(
"font-size" ) );
674 if( ! e.attribute(
"text-decoration" ).isEmpty() )
675 parsePA( 0L, m_gc.current(),
"text-decoration", e.attribute(
"text-decoration" ) );
679XAMLImport::parseGroup( VGroup *grp,
const TQDomElement &e )
682 if( e.tagName() ==
"defs" )
685 for( TQDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
687 TQDomElement b = n.toElement();
688 if( b.isNull() )
continue;
690 if( b.tagName() ==
"g" )
694 group =
new VGroup( grp );
696 group =
new VGroup( &m_document );
700 parseStyle( group, b );
702 parseGroup( group, b );
705 if( !b.attribute(
"id").isEmpty() )
706 group->setName( b.attribute(
"id") );
708 grp->append( group );
710 m_document.append( group );
711 delete( m_gc.pop() );
714 if( b.tagName() ==
"defs" )
719 else if( b.tagName() ==
"linearGradient" || b.tagName() ==
"radialGradient" )
724 else if( b.tagName() ==
"rect" ||
725 b.tagName() ==
"ellipse" ||
726 b.tagName() ==
"circle" ||
727 b.tagName() ==
"line" ||
728 b.tagName() ==
"polyline" ||
729 b.tagName() ==
"polygon" ||
730 b.tagName() ==
"path" ||
731 b.tagName() ==
"image" )
734 obj = createObject( b );
736 m_paths.insert( b.attribute(
"id" ), b );
738 else if( b.tagName() ==
"text" )
741 m_paths.insert( b.attribute(
"id" ), b );
743 createText( grp, b );
745 else if( b.tagName() ==
"use" )
747 double tx = b.attribute(
"x" ).toDouble();
748 double ty = b.attribute(
"y" ).toDouble();
750 if( !b.attribute(
"xlink:href" ).isEmpty() )
752 TQString params = b.attribute(
"xlink:href" );
753 unsigned int start = params.find(
"#") + 1;
754 unsigned int end = params.findRev(
")");
755 TQString key = params.mid( start, end - start );
756 if(m_paths.contains(key))
758 TQDomElement a = m_paths[key];
759 obj = createObject( a );
760 m_gc.current()->matrix.translate(tx,ty);
761 parsePA( grp, m_gc.current(),
"fill", b.attribute(
"fill" ) );
766 VTransformCmd trafo( 0L, m_gc.current()->matrix );
768 parseStyle( obj, b );
770 if( !b.attribute(
"id").isEmpty() )
771 obj->setName( b.attribute(
"id") );
775 m_document.append( obj );
776 delete( m_gc.pop() );
780VObject* XAMLImport::findObject(
const TQString &name, VGroup* group )
785 VObjectListIterator itr = group->objects();
787 for( uint objcount = 1; itr.current(); ++itr, objcount++ )
788 if( itr.current()->state() != VObject::deleted )
790 if( itr.current()->name() == name )
791 return itr.current();
793 if(
dynamic_cast<VGroup *
>( itr.current() ) )
795 VObject *obj = findObject( name,
dynamic_cast<VGroup *
>( itr.current() ) );
804VObject* XAMLImport::findObject(
const TQString &name )
806 TQPtrVector<VLayer> vector;
807 m_document.layers().toVector( &vector );
808 for(
int i = vector.count() - 1; i >= 0; i-- )
810 if ( vector[i]->state() != VObject::deleted )
812 VObject* obj = findObject( name,
dynamic_cast<VGroup *
>( vector[i] ) );
821void XAMLImport::createText( VGroup *grp,
const TQDomElement &b )
830 VTransformCmd trafo( 0L, m_gc.current()->matrix );
834 if( b.hasChildNodes() )
836 if( base.isEmpty() && ! b.attribute(
"x" ).isEmpty() && ! b.attribute(
"y" ).isEmpty() )
838 double x = parseUnit( b.attribute(
"x" ) );
839 double y = parseUnit( b.attribute(
"y" ) );
840 base.moveTo( KoPoint( x, y ) );
841 base.lineTo( KoPoint( x + 10, y ) );
844 for( TQDomNode n = b.firstChild(); !n.isNull(); n = n.nextSibling() )
846 TQDomElement e = n.toElement();
849 content += n.toCharacterData().data();
851 else if( e.tagName() ==
"textPath" )
853 if( e.attribute(
"xlink:href" ).isEmpty() )
856 TQString uri = e.attribute(
"xlink:href" );
857 unsigned int start = uri.find(
"#") + 1;
858 unsigned int end = uri.findRev(
")");
859 TQString key = uri.mid( start, end - start );
860 if( ! m_paths.contains(key) )
862 VObject* obj = findObject( key );
864 path =
dynamic_cast<VPath*
>( obj );
868 TQDomElement p = m_paths[key];
869 path =
dynamic_cast<VPath*
>( createObject( p ) );
871 path->setState( VObject::deleted );
875 base = *path->paths().getFirst();
878 else if( e.tagName() ==
"tspan" )
883 if( base.isEmpty() && ! e.attribute(
"x" ).isEmpty() && ! e.attribute(
"y" ).isEmpty() )
885 TQStringList posX = TQStringList::split(
", ", e.attribute(
"x" ) );
886 TQStringList posY = TQStringList::split(
", ", e.attribute(
"y" ) );
887 if( posX.count() && posY.count() )
889 double x = parseUnit( posX.first() );
890 double y = parseUnit( posY.first() );
891 base.moveTo( KoPoint( x, y ) );
892 base.lineTo( KoPoint( x + 10, y ) );
896 else if( e.tagName() ==
"tref" )
898 if( e.attribute(
"xlink:href" ).isEmpty() )
901 TQString uri = e.attribute(
"xlink:href" );
902 unsigned int start = uri.find(
"#") + 1;
903 unsigned int end = uri.findRev(
")");
904 TQString key = uri.mid( start, end - start );
906 if( ! m_paths.contains(key) )
908 VObject* obj = findObject( key );
910 content +=
dynamic_cast<VText*
>( obj )->text();
914 TQDomElement p = m_paths[key];
921 text =
new VText( m_gc.current()->font, base, VText::Above, VText::Left, content.simplifyWhiteSpace() );
926 double x = parseUnit( b.attribute(
"x" ) );
927 double y = parseUnit( b.attribute(
"y" ) );
928 base.moveTo( KoPoint( x, y ) );
929 base.lineTo( KoPoint( x + 10, y ) );
930 text =
new VText( m_gc.current()->font, base, VText::Above, VText::Left, b.text().simplifyWhiteSpace() );
935 text->setParent( &m_document );
937 parseStyle( text, b );
938 trafo.visit( *text );
940 if( !b.attribute(
"id").isEmpty() )
941 text->setName( b.attribute(
"id") );
946 m_document.append( text );
948 delete( m_gc.pop() );
951VObject* XAMLImport::createObject(
const TQDomElement &b )
953 if( b.tagName() ==
"rect" )
956 double x = parseUnit( b.attribute(
"x" ),
true,
false, m_outerRect );
957 double y = parseUnit( b.attribute(
"y" ),
false,
true, m_outerRect );
958 double width = parseUnit( b.attribute(
"width" ),
true,
false, m_outerRect );
959 double height = parseUnit( b.attribute(
"height" ),
false,
true, m_outerRect );
961 return new VRectangle( 0L, KoPoint( x, height + y ) , width, height );
963 else if( b.tagName() ==
"ellipse" )
967 double rx = parseUnit( b.attribute(
"rx" ) );
968 double ry = parseUnit( b.attribute(
"ry" ) );
969 double left = parseUnit( b.attribute(
"cx" ) ) - rx;
970 double top = parseUnit( b.attribute(
"cy" ) ) - ry;
971 return new VEllipse( 0L, KoPoint( left, top ), rx * 2.0, ry * 2.0 );
973 else if( b.tagName() ==
"circle" )
977 double r = parseUnit( b.attribute(
"r" ) );
978 double left = parseUnit( b.attribute(
"cx" ) ) - r;
979 double top = parseUnit( b.attribute(
"cy" ) ) - r;
980 return new VEllipse( 0L, KoPoint( left, top ), r * 2.0, r * 2.0 );
982 else if( b.tagName() ==
"line" )
986 VPath *path =
new VPath( &m_document );
987 double x1 = b.attribute(
"x1" ).isEmpty() ? 0.0 : parseUnit( b.attribute(
"x1" ) );
988 double y1 = b.attribute(
"y1" ).isEmpty() ? 0.0 : parseUnit( b.attribute(
"y1" ) );
989 double x2 = b.attribute(
"x2" ).isEmpty() ? 0.0 : parseUnit( b.attribute(
"x2" ) );
990 double y2 = b.attribute(
"y2" ).isEmpty() ? 0.0 : parseUnit( b.attribute(
"y2" ) );
991 path->moveTo( KoPoint( x1, y1 ) );
992 path->lineTo( KoPoint( x2, y2 ) );
995 else if( b.tagName() ==
"polyline" || b.tagName() ==
"polygon" )
999 VPath *path =
new VPath( &m_document );
1002 TQString points = b.attribute(
"points" ).simplifyWhiteSpace();
1003 points.replace(
',',
' ' );
1004 points.remove(
'\r' );
1005 points.remove(
'\n' );
1006 TQStringList pointList = TQStringList::split(
' ', points );
1007 for( TQStringList::Iterator it = pointList.begin(); it != pointList.end(); ++it)
1010 point.setX( (*it).toDouble() );
1011 point.setY( (*it).toDouble() );
1014 path->moveTo( point );
1018 path->lineTo( point );
1020 if( b.tagName() ==
"polygon" ) path->close();
1023 else if( b.tagName() ==
"path" )
1025 addGraphicContext();
1026 setupTransform( b );
1027 VPath *path =
new VPath( &m_document );
1028 path->loadSvgPath( b.attribute(
"d" ) );
1031 else if( b.tagName() ==
"image" )
1033 addGraphicContext();
1034 setupTransform( b );
1035 TQString fname = b.attribute(
"xlink:href");
1036 return new VImage( 0L, fname );
1042#include <xamlimport.moc>