kontourimport.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002, Sven Lüppken <sven@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 <kontourimport.h>
21#include <KoFilterChain.h>
22#include <kgenericfactory.h>
23#include <kdebug.h>
24#include <KoUnit.h>
25#include <KoGlobal.h>
26#include <shapes/vellipse.h>
27#include <shapes/vrectangle.h>
28#include <shapes/vpolygon.h>
29#include <commands/vtransformcmd.h>
30#include <core/vpath.h>
31#include <core/vfill.h>
32#include <core/vstroke.h>
33#include <tqcolor.h>
34#include <tqfile.h>
35
36#define DPI 90
37
38typedef KGenericFactory<KontourImport, KoFilter> KontourImportFactory;
39K_EXPORT_COMPONENT_FACTORY( libkarbonkontourimport, KontourImportFactory( "kofficefilters" ) )
40
41KontourImport::KontourImport(KoFilter *, const char *, const TQStringList&) :
42 KoFilter(),
43 outdoc( "DOC" )
44{
45}
46
47KontourImport::~KontourImport()
48{
49
50}
51
52KoFilter::ConversionStatus KontourImport::convert(const TQCString& from, const TQCString& to)
53{
54 // check for proper conversion
55 if ( to != "application/x-karbon" || ( from != "application/x-kontour" && from != "application/x-killustrator") )
56 return KoFilter::NotImplemented;
57
58
59 KoStoreDevice* inpdev = m_chain->storageFile( "root", KoStore::Read );
60 if ( !inpdev )
61 {
62 kdError(30502) << "Unable to open input stream" << endl;
63 return KoFilter::StorageCreationError;
64 }
65
66 inpdoc.setContent( inpdev );
67
68 // Do the conversion!
69 convert();
70
71 KoStoreDevice* out = m_chain->storageFile( "root", KoStore::Write );
72 if(!out)
73 {
74 kdError(30502) << "Unable to open output file!" << endl;
75 return KoFilter::StorageCreationError;
76 }
77 TQCString cstring = outdoc.toCString(); // utf-8 already
78 out->writeBlock( cstring.data(), cstring.length() );
79
80 return KoFilter::OK; // was successful
81}
82
83void
84KontourImport::parseGObject( VObject *object, const TQDomElement &e )
85{
86 if( !e.attribute( "fillstyle" ).isEmpty() )
87 {
88 VFill fill;
89 int fillstyle = e.attribute( "fillstyle" ).toInt();
90 switch( fillstyle )
91 {
92 case 1:
93 {
94 fill.setType( VFill::solid );
95 TQColor c;
96 c.setNamedColor( e.attribute( "fillcolor" ) );
97 VColor color( c );
98 fill.setColor( color );
99 }
100 break;
101 case 4:
102 {
103 VGradient grad;
104 // set color stops
105 grad.clearStops();
106 TQColor c;
107 c.setNamedColor( e.attribute( "gradcolor1" ) );
108 VColor color( c );
109 grad.addStop( color, 0.0, 0.5 );
110 c.setNamedColor( e.attribute( "gradcolor2" ) );
111 VColor color2( c );
112 grad.addStop( color2, 1.0, 0.5 );
113 // set coords
114 KoRect bbox = object->boundingBox();
115 grad.setOrigin( KoPoint( bbox.left(), bbox.y() ) );
116 grad.setVector( KoPoint( bbox.right(), bbox.y() ) );
117 grad.setType( (VGradient::VGradientType)e.attribute( "gradstyle" ).toInt() );
118 fill.setType( VFill::grad );
119 fill.gradient() = grad;
120 }
121 break;
122 }
123 object->setFill( fill );
124 }
125 if( !e.attribute( "strokecolor" ).isEmpty() )
126 {
127 VStroke stroke;
128 int strokestyle = e.attribute( "strokestyle" ).toInt();
129 switch( strokestyle )
130 {
131 case 0: stroke.setType( VStroke::none );
132 break;
133 case 1:
134 {
135 TQColor c;
136 c.setNamedColor( e.attribute( "strokecolor" ) );
137 VColor color( c );
138 stroke.setColor( color );
139 }
140 break;
141 case 2: case 3: case 4: case 5:
142 {
143 TQColor c;
144 c.setNamedColor( e.attribute( "strokecolor" ) );
145 VColor color( c );
146 stroke.setColor( color );
147 VDashPattern dash;
148 TQValueList<float> list;
149 switch ( strokestyle )
150 {
151 case 2: // dashed line
152 list << 10 << 5;
153 break;
154 case 3: // dotted line
155 list << 1 << 5;
156 break;
157 case 4: // dash-dot
158 list << 10 << 5 << 1 << 5;
159 break;
160 case 5: // dash-dot-dot
161 list << 10 << 5 << 1 << 5 << 1 << 5;
162 break;
163 }
164
165 dash.setArray( list );
166 stroke.dashPattern() = dash;
167 }
168 break;
169 }
170 float lineWidth = e.attribute( "linewidth" ).toFloat();
171 stroke.setLineWidth( lineWidth );
172 object->setStroke( stroke );
173 }
174 // handle matrix
175 TQDomElement matrix = e.namedItem( "matrix" ).toElement();
176 TQWMatrix mat( matrix.attribute( "m11" ).toDouble(),
177 matrix.attribute( "m12" ).toDouble(),
178 matrix.attribute( "m21" ).toDouble(),
179 matrix.attribute( "m22" ).toDouble(),
180 matrix.attribute( "dx" ).toDouble(),
181 matrix.attribute( "dy" ).toDouble() );
182
183 // undo y-mirroring
184 mat.scale( 1, -1 );
185 mat.translate( 0, -m_document.height() );
186 VTransformCmd trafo( 0L, mat );
187 trafo.visit( *object );
188
189}
190
191void
192KontourImport::convert()
193{
194 TQDomElement docElem = inpdoc.documentElement();
195 TQDomElement lay;
196 double height;
197 double width;
198 if( docElem.attribute( "version" ).toInt() == 2 )
199 {
200 lay = docElem;
201 height = lay.firstChild().namedItem( "layout" ).toElement().attribute( "height" ).toDouble();
202 width = lay.firstChild().namedItem( "layout" ).toElement().attribute( "width" ).toDouble();
203 }
204 else
205 {
206 lay = docElem.namedItem( "page" ).toElement();
207 height = lay.firstChild().toElement().attribute( "height" ).toDouble();
208 width = lay.firstChild().toElement().attribute( "width" ).toDouble();
209 }
210
211 m_document.setHeight( ( ( height / 72.0 ) * DPI ) );
212 m_document.setWidth( ( ( width / 72.0 ) * DPI ) );
213
214 parseGroup( lay.firstChild().toElement() );
215
216 outdoc = m_document.saveXML();
217}
218
219void
220KontourImport::parseGroup( const TQDomElement &e )
221{
222 TQDomElement b = e;
223 for( ; !b.isNull(); b = b.nextSibling().toElement() )
224 {
225 if ( b.tagName() == "rectangle" )
226 {
227 int x = b.attribute( "x" ).toInt();
228 int y = b.attribute( "y" ).toInt();
229 int width = b.attribute( "width" ).toInt();
230 int height = b.attribute( "height" ).toInt();
231 VObject *rect = new VRectangle( 0L, KoPoint( x, height + y ) , width, height );
232 TQDomElement object = b.namedItem( "polyline" ).namedItem( "gobject" ).toElement();
233 parseGObject( rect, object );
234 m_document.append( rect );
235 }
236 else
237 if ( b.tagName() == "ellipse" )
238 {
239 TQDomElement object = b.namedItem( "gobject" ).toElement();
240 TQDomElement matrix = object.namedItem( "matrix" ).toElement();
245 double left = ( b.attribute( "x" ).toDouble() + matrix.attribute( "dx" ).toInt() ) - ( b.attribute( "rx" ).toDouble() / 2 );
246 double right = left + b.attribute( "rx" ).toDouble();
247 double top = ( b.attribute( "y" ).toDouble() + matrix.attribute( "dy" ).toInt() ) - ( b.attribute( "ry" ).toDouble() / 2 );
248 double bottom = top + b.attribute( "ry" ).toDouble();
249 double height = top - bottom;
250 double width = right - left;
251 // Append the ellipse to the document
252 VObject *ellipse = new VEllipse( 0L, KoPoint( left, top ), width, height );
253 parseGObject( ellipse, object );
254 m_document.append( ellipse );
255 }
256 else if( b.tagName() == "polyline" )
257 {
262 TQDomElement point = b.firstChild().toElement();
263 VPath *path = new VPath( &m_document );
264 double x, y;
265 x = point.attribute( "x" ).toDouble();
266 y = point.attribute( "y" ).toDouble();
267 path->moveTo( KoPoint( x, y ) );
268 point = point.nextSibling().toElement();
269 for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
270 {
271 x = point.attribute( "x" ).toDouble();
272 y = point.attribute( "y" ).toDouble();
273 path->lineTo( KoPoint( x, y ) );
274 }
275 parseGObject( path, point );
276 m_document.append( path );
277 }
278 else if( b.tagName() == "polygon" )
279 {
280 TQDomElement point = b.namedItem( "polyline" ).firstChild().toElement();
281 VPath *path = new VPath( &m_document );
282 double x, y;
283 x = point.attribute( "x" ).toDouble();
284 y = point.attribute( "y" ).toDouble();
285 path->moveTo( KoPoint( x, y ) );
286 point = point.nextSibling().toElement();
287 for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
288 {
289 x = point.attribute( "x" ).toDouble();
290 y = point.attribute( "y" ).toDouble();
291 path->lineTo( KoPoint( x, y ) );
292 }
293 path->close();
294 // back to first point
295 parseGObject( path, point );
296 m_document.append( path );
297 }
298 else if( b.tagName() == "bezier" )
299 {
300 TQDomElement point = b.namedItem( "polyline" ).firstChild().toElement();
301 VPath *path = new VPath( &m_document );
302 double x, y;
303 x = point.attribute( "x" ).toDouble();
304 y = point.attribute( "y" ).toDouble();
305 path->moveTo( KoPoint( x, y ) );
306 point = point.nextSibling().toElement();
307 for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
308 {
309 x = point.attribute( "x" ).toDouble();
310 y = point.attribute( "y" ).toDouble();
311 path->lineTo( KoPoint( x, y ) );
312 }
313 parseGObject( path, point );
314 m_document.append( path );
315 }
316 else if( b.tagName() == "group" || b.tagName() == "layer" )
317 {
318 parseGroup( b.toElement().firstChild().toElement() );
319 }
320 }
321}
322
323#include <kontourimport.moc>