filters

wmfexport.cpp
1/* This file is part of the KDE project
2 * Copyright (c) 2003 thierry lorthiois (lorthioist@wanadoo.fr)
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 version 2 as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
12 *
13 * You should have received a copy of the GNU Library General Public License
14 * along with this library; see the file COPYING.LIB. If not, write to
15 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17*/
18
19#include <config.h>
20#include <tqdom.h>
21#include <tqcstring.h>
22#include <kdebug.h>
23#include <kgenericfactory.h>
24#include <KoFilterChain.h>
25#include <KoStore.h>
26#include <KoStoreDevice.h>
27#include "vdocument.h"
28#include "vcolor.h"
29#include "vcomposite.h"
30#include "vdashpattern.h"
31#include "vdocument.h"
32#include "vlayer.h"
33#include "vpath.h"
34#include "vsegment.h"
35#include "vfill.h"
36#include "vstroke.h"
37#include "vtext.h"
38#include "vflattencmd.h"
39
40#include "wmfexport.h"
41#include "kowmfwrite.h"
42
43/*
44TODO: bs.wmf stroke in red with MSword and in brown with Kword ??
45*/
46
47typedef KGenericFactory<WmfExport, KoFilter> WmfExportFactory;
48K_EXPORT_COMPONENT_FACTORY( libwmfexport, WmfExportFactory( "kofficefilters" ) )
49
50
51WmfExport::WmfExport( KoFilter *, const char *, const TQStringList&) :
52 KoFilter()
53{
54}
55
56WmfExport::~WmfExport()
57{
58}
59
60KoFilter::ConversionStatus WmfExport::convert( const TQCString& from, const TQCString& to )
61{
62 if( to != "image/x-wmf" || from != "application/x-karbon" ) {
63 return KoFilter::NotImplemented;
64 }
65
66 KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
67
68 if( !storeIn ) {
69 return KoFilter::StupidError;
70 }
71
72 // open Placeable Wmf file
73 mWmf = new KoWmfWrite( m_chain->outputFile() );
74 if( !mWmf->begin() ) {
75 delete mWmf;
76 return KoFilter::WrongFormat;
77 }
78
79 TQDomDocument domIn;
80 domIn.setContent( storeIn );
81 TQDomElement docNode = domIn.documentElement();
82
83 // Load the document.
84 mDoc = new VDocument;
85 mDoc->load( docNode );
86
87 // Process the document.
88 mDoc->accept( *this );
89
90 mWmf->end();
91
92 delete mWmf;
93 delete mDoc;
94
95 return KoFilter::OK;
96}
97
98
99void WmfExport::visitVDocument( VDocument& document ) {
100 int width;
101 int height;
102
103 mDoc = &document;
104 mListPa.setAutoDelete( true );
105
106 // resolution
107 mDpi = 1000;
108 width = (int)(POINT_TO_INCH( document.width() ) * mDpi);
109 height = (int)(POINT_TO_INCH( document.height() ) * mDpi);
110
111 mWmf->setDefaultDpi( mDpi );
112 mWmf->setWindow( 0, 0, width, height );
113
114 if ( (document.width() != 0) && (document.height() != 0) ) {
115 mScaleX = (double)width / document.width();
116 mScaleY = (double)height / document.height();
117 }
118
119 // Export layers.
120 VVisitor::visitVDocument( document );
121
122}
123
124
125void WmfExport::visitVPath( VPath& composite ) {
126 TQPen pen;
127 TQBrush brush;
128
129 getPen( pen, composite.stroke() );
130 getBrush( brush, composite.fill() );
131
132 VVisitor::visitVPath( composite );
133
134 if ( mListPa.count() > 0 ) {
135 mWmf->setPen( pen );
136 if( (brush.style() == TQt::NoBrush)
137 && (mListPa.count() == 1) ) {
138 mWmf->drawPolyline( *mListPa.first() );
139 }
140 else {
141 mWmf->setBrush( brush );
142
143 if ( mListPa.count() == 1 ) {
144 mWmf->drawPolygon( *mListPa.first() );
145 }
146 else {
147 // combined path
148 mWmf->drawPolyPolygon( mListPa );
149 }
150 }
151 }
152 mListPa.clear();
153}
154
155
156// Export segment.
157void WmfExport::visitVSubpath( VSubpath& path ) {
158 VSubpath *newPath;
159 VSubpathIterator itr( path );
160 VFlattenCmd cmd( 0L, INCH_TO_POINT(0.3 / (double)mDpi) );
161 TQPointArray *pa = new TQPointArray( path.count() );
162 int nbrPoint=0; // number of points in the path
163
164 for( ; itr.current(); ++itr ) {
165 VSegment *segment= itr.current();
166 if (segment->isCurve()) {
167 newPath = new VSubpath( mDoc );
168
169 // newPath duplicate the list of curve
170 newPath->moveTo( itr.current()->prev()->knot() );
171 newPath->append( itr.current()->clone() );
172 while( itr.current()->next() ) {
173 if ( itr.current()->next()->isCurve() ) {
174 newPath->append( itr.current()->next()->clone() );
175 }
176 else {
177 break;
178 }
179 ++itr;
180 }
181
182 // flatten the curve
183 cmd.visit( *newPath );
184
185 // adjust the number of points
186 pa->resize( pa->size() + newPath->count() - 2 );
187
188 // Ommit the first segment and insert points
189 newPath->first();
190 while( newPath->next() ) {
191 pa->setPoint( nbrPoint++, coordX( newPath->current()->knot().x() ),
192 coordY( newPath->current()->knot().y() ) );
193 }
194 delete newPath;
195 } else if (segment->isLine()) {
196 pa->setPoint( nbrPoint++, coordX( itr.current()->knot().x() ),
197 coordY( itr.current()->knot().y() ) );
198 } else if (segment->isBegin()) {
199 // start a new polygon
200 pa->setPoint( nbrPoint++, coordX( itr.current()->knot().x() ),
201 coordY( itr.current()->knot().y() ) );
202 }
203 }
204
205 // adjust the number of points
206 if ( nbrPoint > 1 ) {
207 pa->resize( nbrPoint );
208 mListPa.append( pa );
209 }
210 else {
211 delete pa;
212 // TODO: check why we have empty path
213 kdDebug() << "WmfExport::visitVSubpath : Empty path ?" << endl;
214 }
215}
216
217
218void WmfExport::visitVText( VText& text ) {
219 // TODO: export text
220 visitVSubpath( text.basePath() );
221}
222
223
224void WmfExport::getBrush( TQBrush& brush, const VFill *fill ) {
225 if( (fill->type() == VFill::solid) || (fill->type() == VFill::grad)
226 || (fill->type() == VFill::patt) ) {
227 if ( fill->color().opacity() < 0.1 ) {
228 brush.setStyle( TQt::NoBrush );
229 }
230 else {
231 brush.setStyle( TQt::SolidPattern );
232 brush.setColor( fill->color() );
233 }
234 }
235 else {
236 brush.setStyle( TQt::NoBrush );
237 }
238}
239
240
241void WmfExport::getPen( TQPen& pen, const VStroke *stroke ) {
242 if( (stroke->type() == VStroke::solid) || (stroke->type() == VStroke::grad)
243 || (stroke->type() == VStroke::patt) ) {
244 // TODO : Dash pattern.
245
246 if ( stroke->lineCap() == VStroke::capRound ) {
247 pen.setCapStyle( TQt::RoundCap );
248 }
249 else {
250 pen.setCapStyle( TQt::SquareCap );
251 }
252 pen.setStyle( TQt::SolidLine );
253 pen.setColor( stroke->color() );
254 pen.setWidth( coordX( stroke->lineWidth() ) );
255 }
256 else {
257 pen.setStyle( TQt::NoPen );
258 }
259}
260
261
262#include <wmfexport.moc>
263