|
|
|
|
/* This file is part of the KDE project
|
|
|
|
|
Copyright (C) 2002, Sven L<EFBFBD>ppken <sven@kde.org>
|
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <kontourimport.h>
|
|
|
|
|
#include <KoFilterChain.h>
|
|
|
|
|
#include <kgenericfactory.h>
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
#include <KoUnit.h>
|
|
|
|
|
#include <KoGlobal.h>
|
|
|
|
|
#include <shapes/vellipse.h>
|
|
|
|
|
#include <shapes/vrectangle.h>
|
|
|
|
|
#include <shapes/vpolygon.h>
|
|
|
|
|
#include <commands/vtransformcmd.h>
|
|
|
|
|
#include <core/vpath.h>
|
|
|
|
|
#include <core/vfill.h>
|
|
|
|
|
#include <core/vstroke.h>
|
|
|
|
|
#include <tqcolor.h>
|
|
|
|
|
#include <tqfile.h>
|
|
|
|
|
|
|
|
|
|
#define DPI 90
|
|
|
|
|
|
|
|
|
|
typedef KGenericFactory<KontourImport, KoFilter> KontourImportFactory;
|
|
|
|
|
K_EXPORT_COMPONENT_FACTORY( libkarbonkontourimport, KontourImportFactory( "kofficefilters" ) )
|
|
|
|
|
|
|
|
|
|
KontourImport::KontourImport(KoFilter *, const char *, const TQStringList&) :
|
|
|
|
|
KoFilter(),
|
|
|
|
|
outdoc( "DOC" )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
KontourImport::~KontourImport()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
KoFilter::ConversionStatus KontourImport::convert(const TQCString& from, const TQCString& to)
|
|
|
|
|
{
|
|
|
|
|
// check for proper conversion
|
|
|
|
|
if ( to != "application/x-karbon" || ( from != "application/x-kontour" && from != "application/x-killustrator") )
|
|
|
|
|
return KoFilter::NotImplemented;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KoStoreDevice* inpdev = m_chain->storageFile( "root", KoStore::Read );
|
|
|
|
|
if ( !inpdev )
|
|
|
|
|
{
|
|
|
|
|
kdError(30502) << "Unable to open input stream" << endl;
|
|
|
|
|
return KoFilter::StorageCreationError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inpdoc.setContent( inpdev );
|
|
|
|
|
|
|
|
|
|
// Do the conversion!
|
|
|
|
|
convert();
|
|
|
|
|
|
|
|
|
|
KoStoreDevice* out = m_chain->storageFile( "root", KoStore::Write );
|
|
|
|
|
if(!out)
|
|
|
|
|
{
|
|
|
|
|
kdError(30502) << "Unable to open output file!" << endl;
|
|
|
|
|
return KoFilter::StorageCreationError;
|
|
|
|
|
}
|
|
|
|
|
TQCString cstring = outdoc.toCString(); // utf-8 already
|
|
|
|
|
out->writeBlock( cstring.data(), cstring.length() );
|
|
|
|
|
|
|
|
|
|
return KoFilter::OK; // was successful
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KontourImport::parseGObject( VObject *object, const TQDomElement &e )
|
|
|
|
|
{
|
|
|
|
|
if( !e.attribute( "fillstyle" ).isEmpty() )
|
|
|
|
|
{
|
|
|
|
|
VFill fill;
|
|
|
|
|
int fillstyle = e.attribute( "fillstyle" ).toInt();
|
|
|
|
|
switch( fillstyle )
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
fill.setType( VFill::solid );
|
|
|
|
|
TQColor c;
|
|
|
|
|
c.setNamedColor( e.attribute( "fillcolor" ) );
|
|
|
|
|
VColor color( c );
|
|
|
|
|
fill.setColor( color );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
{
|
|
|
|
|
VGradient grad;
|
|
|
|
|
// set color stops
|
|
|
|
|
grad.clearStops();
|
|
|
|
|
TQColor c;
|
|
|
|
|
c.setNamedColor( e.attribute( "gradcolor1" ) );
|
|
|
|
|
VColor color( c );
|
|
|
|
|
grad.addStop( color, 0.0, 0.5 );
|
|
|
|
|
c.setNamedColor( e.attribute( "gradcolor2" ) );
|
|
|
|
|
VColor color2( c );
|
|
|
|
|
grad.addStop( color2, 1.0, 0.5 );
|
|
|
|
|
// set coords
|
|
|
|
|
KoRect bbox = object->boundingBox();
|
|
|
|
|
grad.setOrigin( KoPoint( bbox.left(), bbox.y() ) );
|
|
|
|
|
grad.setVector( KoPoint( bbox.right(), bbox.y() ) );
|
|
|
|
|
grad.setType( (VGradient::VGradientType)e.attribute( "gradstyle" ).toInt() );
|
|
|
|
|
fill.setType( VFill::grad );
|
|
|
|
|
fill.gradient() = grad;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
object->setFill( fill );
|
|
|
|
|
}
|
|
|
|
|
if( !e.attribute( "strokecolor" ).isEmpty() )
|
|
|
|
|
{
|
|
|
|
|
VStroke stroke;
|
|
|
|
|
int strokestyle = e.attribute( "strokestyle" ).toInt();
|
|
|
|
|
switch( strokestyle )
|
|
|
|
|
{
|
|
|
|
|
case 0: stroke.setType( VStroke::none );
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
TQColor c;
|
|
|
|
|
c.setNamedColor( e.attribute( "strokecolor" ) );
|
|
|
|
|
VColor color( c );
|
|
|
|
|
stroke.setColor( color );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2: case 3: case 4: case 5:
|
|
|
|
|
{
|
|
|
|
|
TQColor c;
|
|
|
|
|
c.setNamedColor( e.attribute( "strokecolor" ) );
|
|
|
|
|
VColor color( c );
|
|
|
|
|
stroke.setColor( color );
|
|
|
|
|
VDashPattern dash;
|
|
|
|
|
TQValueList<float> list;
|
|
|
|
|
switch ( strokestyle )
|
|
|
|
|
{
|
|
|
|
|
case 2: // dashed line
|
|
|
|
|
list << 10 << 5;
|
|
|
|
|
break;
|
|
|
|
|
case 3: // dotted line
|
|
|
|
|
list << 1 << 5;
|
|
|
|
|
break;
|
|
|
|
|
case 4: // dash-dot
|
|
|
|
|
list << 10 << 5 << 1 << 5;
|
|
|
|
|
break;
|
|
|
|
|
case 5: // dash-dot-dot
|
|
|
|
|
list << 10 << 5 << 1 << 5 << 1 << 5;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dash.setArray( list );
|
|
|
|
|
stroke.dashPattern() = dash;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
float lineWidth = e.attribute( "linewidth" ).toFloat();
|
|
|
|
|
stroke.setLineWidth( lineWidth );
|
|
|
|
|
object->setStroke( stroke );
|
|
|
|
|
}
|
|
|
|
|
// handle matrix
|
|
|
|
|
TQDomElement matrix = e.namedItem( "matrix" ).toElement();
|
|
|
|
|
TQWMatrix mat( matrix.attribute( "m11" ).toDouble(),
|
|
|
|
|
matrix.attribute( "m12" ).toDouble(),
|
|
|
|
|
matrix.attribute( "m21" ).toDouble(),
|
|
|
|
|
matrix.attribute( "m22" ).toDouble(),
|
|
|
|
|
matrix.attribute( "dx" ).toDouble(),
|
|
|
|
|
matrix.attribute( "dy" ).toDouble() );
|
|
|
|
|
|
|
|
|
|
// undo y-mirroring
|
|
|
|
|
mat.scale( 1, -1 );
|
|
|
|
|
mat.translate( 0, -m_document.height() );
|
|
|
|
|
VTransformCmd trafo( 0L, mat );
|
|
|
|
|
trafo.visit( *object );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KontourImport::convert()
|
|
|
|
|
{
|
|
|
|
|
TQDomElement docElem = inpdoc.documentElement();
|
|
|
|
|
TQDomElement lay;
|
|
|
|
|
double height;
|
|
|
|
|
double width;
|
|
|
|
|
if( docElem.attribute( "version" ).toInt() == 2 )
|
|
|
|
|
{
|
|
|
|
|
lay = docElem;
|
|
|
|
|
height = lay.firstChild().namedItem( "layout" ).toElement().attribute( "height" ).toDouble();
|
|
|
|
|
width = lay.firstChild().namedItem( "layout" ).toElement().attribute( "width" ).toDouble();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lay = docElem.namedItem( "page" ).toElement();
|
|
|
|
|
height = lay.firstChild().toElement().attribute( "height" ).toDouble();
|
|
|
|
|
width = lay.firstChild().toElement().attribute( "width" ).toDouble();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_document.setHeight( ( ( height / 72.0 ) * DPI ) );
|
|
|
|
|
m_document.setWidth( ( ( width / 72.0 ) * DPI ) );
|
|
|
|
|
|
|
|
|
|
parseGroup( lay.firstChild().toElement() );
|
|
|
|
|
|
|
|
|
|
outdoc = m_document.saveXML();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
KontourImport::parseGroup( const TQDomElement &e )
|
|
|
|
|
{
|
|
|
|
|
TQDomElement b = e;
|
|
|
|
|
for( ; !b.isNull(); b = b.nextSibling().toElement() )
|
|
|
|
|
{
|
|
|
|
|
if ( b.tagName() == "rectangle" )
|
|
|
|
|
{
|
|
|
|
|
int x = b.attribute( "x" ).toInt();
|
|
|
|
|
int y = b.attribute( "y" ).toInt();
|
|
|
|
|
int width = b.attribute( "width" ).toInt();
|
|
|
|
|
int height = b.attribute( "height" ).toInt();
|
|
|
|
|
VObject *rect = new VRectangle( 0L, KoPoint( x, height + y ) , width, height );
|
|
|
|
|
TQDomElement object = b.namedItem( "polyline" ).namedItem( "gobject" ).toElement();
|
|
|
|
|
parseGObject( rect, object );
|
|
|
|
|
m_document.append( rect );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if ( b.tagName() == "ellipse" )
|
|
|
|
|
{
|
|
|
|
|
TQDomElement object = b.namedItem( "gobject" ).toElement();
|
|
|
|
|
TQDomElement matrix = object.namedItem( "matrix" ).toElement();
|
|
|
|
|
/**
|
|
|
|
|
* Kontour uses a quite different way to display ellipses, so we
|
|
|
|
|
* need to calculate the values for the Karbon ellipse here
|
|
|
|
|
*/
|
|
|
|
|
double left = ( b.attribute( "x" ).toDouble() + matrix.attribute( "dx" ).toInt() ) - ( b.attribute( "rx" ).toDouble() / 2 );
|
|
|
|
|
double right = left + b.attribute( "rx" ).toDouble();
|
|
|
|
|
double top = ( b.attribute( "y" ).toDouble() + matrix.attribute( "dy" ).toInt() ) - ( b.attribute( "ry" ).toDouble() / 2 );
|
|
|
|
|
double bottom = top + b.attribute( "ry" ).toDouble();
|
|
|
|
|
double height = top - bottom;
|
|
|
|
|
double width = right - left;
|
|
|
|
|
// Append the ellipse to the document
|
|
|
|
|
VObject *ellipse = new VEllipse( 0L, KoPoint( left, top ), width, height );
|
|
|
|
|
parseGObject( ellipse, object );
|
|
|
|
|
m_document.append( ellipse );
|
|
|
|
|
}
|
|
|
|
|
else if( b.tagName() == "polyline" )
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Kontour is much simpler because it doesn't support curves, so
|
|
|
|
|
* we're done with connecting points with lines.
|
|
|
|
|
*/
|
|
|
|
|
TQDomElement point = b.firstChild().toElement();
|
|
|
|
|
VPath *path = new VPath( &m_document );
|
|
|
|
|
double x, y;
|
|
|
|
|
x = point.attribute( "x" ).toDouble();
|
|
|
|
|
y = point.attribute( "y" ).toDouble();
|
|
|
|
|
path->moveTo( KoPoint( x, y ) );
|
|
|
|
|
point = point.nextSibling().toElement();
|
|
|
|
|
for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
|
|
|
|
|
{
|
|
|
|
|
x = point.attribute( "x" ).toDouble();
|
|
|
|
|
y = point.attribute( "y" ).toDouble();
|
|
|
|
|
path->lineTo( KoPoint( x, y ) );
|
|
|
|
|
}
|
|
|
|
|
parseGObject( path, point );
|
|
|
|
|
m_document.append( path );
|
|
|
|
|
}
|
|
|
|
|
else if( b.tagName() == "polygon" )
|
|
|
|
|
{
|
|
|
|
|
TQDomElement point = b.namedItem( "polyline" ).firstChild().toElement();
|
|
|
|
|
VPath *path = new VPath( &m_document );
|
|
|
|
|
double x, y;
|
|
|
|
|
x = point.attribute( "x" ).toDouble();
|
|
|
|
|
y = point.attribute( "y" ).toDouble();
|
|
|
|
|
path->moveTo( KoPoint( x, y ) );
|
|
|
|
|
point = point.nextSibling().toElement();
|
|
|
|
|
for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
|
|
|
|
|
{
|
|
|
|
|
x = point.attribute( "x" ).toDouble();
|
|
|
|
|
y = point.attribute( "y" ).toDouble();
|
|
|
|
|
path->lineTo( KoPoint( x, y ) );
|
|
|
|
|
}
|
|
|
|
|
path->close();
|
|
|
|
|
// back to first point
|
|
|
|
|
parseGObject( path, point );
|
|
|
|
|
m_document.append( path );
|
|
|
|
|
}
|
|
|
|
|
else if( b.tagName() == "bezier" )
|
|
|
|
|
{
|
|
|
|
|
TQDomElement point = b.namedItem( "polyline" ).firstChild().toElement();
|
|
|
|
|
VPath *path = new VPath( &m_document );
|
|
|
|
|
double x, y;
|
|
|
|
|
x = point.attribute( "x" ).toDouble();
|
|
|
|
|
y = point.attribute( "y" ).toDouble();
|
|
|
|
|
path->moveTo( KoPoint( x, y ) );
|
|
|
|
|
point = point.nextSibling().toElement();
|
|
|
|
|
for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
|
|
|
|
|
{
|
|
|
|
|
x = point.attribute( "x" ).toDouble();
|
|
|
|
|
y = point.attribute( "y" ).toDouble();
|
|
|
|
|
path->lineTo( KoPoint( x, y ) );
|
|
|
|
|
}
|
|
|
|
|
parseGObject( path, point );
|
|
|
|
|
m_document.append( path );
|
|
|
|
|
}
|
|
|
|
|
else if( b.tagName() == "group" || b.tagName() == "layer" )
|
|
|
|
|
{
|
|
|
|
|
parseGroup( b.toElement().firstChild().toElement() );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#include <kontourimport.moc>
|