lib

kowmfwrite.cpp
1/* This file is part of the KDE libraries
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 <math.h>
20#include <tqfile.h>
21#include <tqdatastream.h>
22
23#include <kdebug.h>
24
25#include "kowmfstruct.h"
26#include "kowmfreadprivate.h"
27#include "kowmfwrite.h"
28
32class KoWmfWritePrivate
33{
34public:
35 TQRect mBBox; // bounding rectangle
36 int mDpi; // number of point per inch for the default size
37 int mMaxRecordSize;
38
39 // memory allocation for WMF file
40 TQFile mFileOut;
41 TQDataStream mSt;
42};
43
44
45
46KoWmfWrite::KoWmfWrite( const TQString& fileName ) {
47 d = new KoWmfWritePrivate;
48
49 d->mDpi = 1024;
50 d->mMaxRecordSize = 0;
51 d->mFileOut.setName( fileName );
52}
53
54KoWmfWrite::~KoWmfWrite() {
55 delete d;
56}
57
58
59void KoWmfWrite::setDefaultDpi( int dpi ) {
60 d->mDpi = dpi;
61}
62
63
64//-----------------------------------------------------------------------------
65// Virtual Painter => create the WMF
66
68
69 if ( !d->mFileOut.open( IO_WriteOnly ) )
70 {
71 kdDebug() << "Cannot open file " << TQString(TQFile::encodeName(d->mFileOut.name())) << endl;
72 return false;
73 }
74 d->mSt.setDevice( &d->mFileOut );
75 d->mSt.setByteOrder( TQDataStream::LittleEndian );
76
77 // reserved placeable and standard header
78 for ( int i=0 ; i < 10 ; i++ ) {
79 d->mSt << (TQ_UINT32)0;
80 }
81
82 // initialize the stack of objects
83 // Pen
84 d->mSt << (TQ_UINT32)8 << (TQ_UINT16)0x02FA;
85 d->mSt << (TQ_UINT16)5 << (TQ_UINT16)0 << (TQ_UINT16)0 << (TQ_UINT32)0;
86 // Brush
87 d->mSt << (TQ_UINT32)7 << (TQ_UINT16)0x02FC;
88 d->mSt << (TQ_UINT16)1 << (TQ_UINT32)0 << (TQ_UINT16)0;
89 for ( int i=0 ; i < 4 ; i++ ) {
90 d->mSt << (TQ_UINT32)8 << (TQ_UINT16)0x02FA << (TQ_UINT16)0 << (TQ_UINT32)0 << (TQ_UINT32)0;
91 }
92 d->mMaxRecordSize = 8;
93
94 return true;
95}
96
97
99 WmfPlaceableHeader pheader = { 0x9AC6CDD7, 0, 0, 0, 0, 0, 0, 0, 0 };
100 TQ_UINT16 checksum;
101
102 // End of the wmf file
103 d->mSt << (TQ_UINT32)3 << (TQ_UINT16)0;
104
105 // adjust header
106 pheader.left = d->mBBox.left();
107 pheader.top = d->mBBox.top();
108 pheader.right = d->mBBox.right();
109 pheader.bottom = d->mBBox.bottom();
110 pheader.inch = d->mDpi;
111 checksum = KoWmfReadPrivate::calcCheckSum( &pheader );
112
113 // write headers
114 d->mFileOut.at( 0 );
115 d->mSt << (TQ_UINT32)0x9AC6CDD7 << (TQ_UINT16)0;
116 d->mSt << (TQ_INT16)d->mBBox.left() << (TQ_INT16)d->mBBox.top() << (TQ_INT16)d->mBBox.right() << (TQ_INT16)d->mBBox.bottom();
117 d->mSt << (TQ_UINT16)d->mDpi << (TQ_UINT32)0 << checksum;
118 d->mSt << (TQ_UINT16)1 << (TQ_UINT16)9 << (TQ_UINT16)0x300 << (TQ_UINT32)(d->mFileOut.size()/2);
119 d->mSt << (TQ_UINT16)6 << (TQ_UINT32)d->mMaxRecordSize << (TQ_UINT16)0;
120
121 d->mFileOut.close();
122
123 return true;
124}
125
126
127void KoWmfWrite::save() {
128 d->mSt << (TQ_UINT32)3 << (TQ_UINT16)0x001E;
129}
130
131
132void KoWmfWrite::restore() {
133 d->mSt << (TQ_UINT32)4 << (TQ_UINT16)0x0127 << (TQ_UINT16)1;
134}
135
136
137void KoWmfWrite::setPen( const TQPen &pen ) {
138 int style;
139 int max = sizeof(koWmfStylePen) / sizeof(TQt::SolidLine);
140
141 // we can't delete an object currently selected
142 // select another object
143 d->mSt << (TQ_UINT32)4 << (TQ_UINT16)0x012D << (TQ_UINT16)0;
144 // delete object
145 d->mSt << (TQ_UINT32)4 << (TQ_UINT16)0x01f0 << (TQ_UINT16)2;
146
147 for ( style=0 ; style < max ; style++ ) {
148 if ( koWmfStylePen[ style ] == pen.style() ) break;
149 }
150 if ( style == max ) {
151 // SolidLine
152 style = 0;
153 }
154 d->mSt << (TQ_UINT32)8 << (TQ_UINT16)0x02FA;
155 d->mSt << (TQ_UINT16)style << (TQ_UINT16)pen.width() << (TQ_UINT16)0 << (TQ_UINT32)winColor( pen.color() );
156
157 // select object
158 d->mSt << (TQ_UINT32)4 << (TQ_UINT16)0x012D << (TQ_UINT16)2;
159}
160
161
162void KoWmfWrite::setBrush( const TQBrush &brush ) {
163 int style;
164 int max = sizeof(koWmfStyleBrush) / sizeof(TQt::NoBrush);
165
166 // we can't delete an object currently selected
167 // select another object
168 d->mSt << (TQ_UINT32)4 << (TQ_UINT16)0x012D << (TQ_UINT16)1;
169 // delete object
170 d->mSt << (TQ_UINT32)4 << (TQ_UINT16)0x01f0 << (TQ_UINT16)3;
171
172 for ( style=0 ; style < max ; style++ ) {
173 if ( koWmfStyleBrush[ style ] == brush.style() ) break;
174 }
175 if ( style == max ) {
176 // SolidPattern
177 style = 0;
178 }
179 d->mSt << (TQ_UINT32)7 << (TQ_UINT16)0x02FC;
180 d->mSt << (TQ_UINT16)style << (TQ_UINT32)winColor( brush.color() ) << (TQ_UINT16)0;
181
182 // select object
183 d->mSt << (TQ_UINT32)4 << (TQ_UINT16)0x012D << (TQ_UINT16)3;
184}
185
186
187void KoWmfWrite::setFont( const TQFont & ) {
188}
189
190
191void KoWmfWrite::setBackgroundColor( const TQColor &c ) {
192 d->mSt << (TQ_UINT32)5 << (TQ_UINT16)0x0201 << (TQ_UINT32)winColor( c );
193}
194
195
196void KoWmfWrite::setBackgroundMode( TQt::BGMode mode ) {
197 d->mSt << (TQ_UINT32)4 << (TQ_UINT16)0x0102;
198 if ( mode == TQt::TransparentMode )
199 d->mSt << (TQ_UINT16)1;
200 else
201 d->mSt << (TQ_UINT16)0;
202}
203
204
205void KoWmfWrite::setRasterOp( TQt::RasterOp op ) {
206 d->mSt << (TQ_UINT32)5 << (TQ_UINT16)0x0104 << (TQ_UINT32)qtRasterToWin32( op );
207}
208
209
210void KoWmfWrite::setWindow( int left, int top, int width, int height ) {
211 d->mBBox.setRect( left, top, width, height );
212
213 // windowOrg
214 d->mSt << (TQ_UINT32)5 << (TQ_UINT16)0x020B << (TQ_UINT16)top << (TQ_UINT16)left;
215
216 // windowExt
217 d->mSt << (TQ_UINT32)5 << (TQ_UINT16)0x020C << (TQ_UINT16)height << (TQ_UINT16)width;
218}
219
220
221void KoWmfWrite::setClipRegion( const TQRegion & ) {
222
223}
224
225
226void KoWmfWrite::clipping( bool enable ) {
227 if ( !enable ) {
228 // clipping region == bounding rectangle
229 setClipRegion( d->mBBox );
230 }
231}
232
233
234void KoWmfWrite::moveTo( int left, int top ) {
235 d->mSt << (TQ_UINT32)5 << (TQ_UINT16)0x0214 << (TQ_UINT16)top << (TQ_UINT16)left;
236}
237
238
239void KoWmfWrite::lineTo( int left, int top ) {
240 d->mSt << (TQ_UINT32)5 << (TQ_UINT16)0x0213 << (TQ_UINT16)top << (TQ_UINT16)left;
241}
242
243
244void KoWmfWrite::drawRect( int left, int top, int width, int height ) {
245 TQRect rec( left, top, width, height );
246
247 d->mSt << (TQ_UINT32)7 << (TQ_UINT16)0x041B;
248 d->mSt << (TQ_UINT16)rec.bottom() << (TQ_UINT16)rec.right() << (TQ_UINT16)rec.top() << (TQ_UINT16)rec.left();
249}
250
251
252void KoWmfWrite::drawRoundRect( int left, int top, int width, int height , int roudw, int roudh ) {
253 int widthCorner, heightCorner;
254 TQRect rec( left, top, width, height );
255
256 // convert percentage (roundw, roudh) in (widthCorner, heightCorner)
257 widthCorner = ( roudw * width ) / 100;
258 heightCorner = ( roudh * height ) / 100;
259
260 d->mSt << (TQ_UINT32)9 << (TQ_UINT16)0x061C << (TQ_UINT16)heightCorner << (TQ_UINT16)widthCorner;
261 d->mSt << (TQ_UINT16)rec.bottom() << (TQ_UINT16)rec.right() << (TQ_UINT16)rec.top() << (TQ_UINT16)rec.left();
262
263 d->mMaxRecordSize = TQMAX( d->mMaxRecordSize, 9 );
264}
265
266
267void KoWmfWrite::drawEllipse( int left, int top, int width, int height ) {
268 TQRect rec( left, top, width, height );
269
270 d->mSt << (TQ_UINT32)7 << (TQ_UINT16)0x0418;
271 d->mSt << (TQ_UINT16)rec.bottom() << (TQ_UINT16)rec.right() << (TQ_UINT16)rec.top() << (TQ_UINT16)rec.left();
272}
273
274
275void KoWmfWrite::drawArc( int left, int top, int width, int height , int a, int alen ) {
276 int xCenter, yCenter;
277 int offXStart, offYStart, offXEnd, offYEnd;
278
279 angleToxy( offXStart, offYStart, offXEnd, offYEnd, a, alen );
280 xCenter = left + (width / 2);
281 yCenter = top + (height / 2);
282
283 d->mSt << (TQ_UINT32)11 << (TQ_UINT16)0x0817;
284 d->mSt << (TQ_UINT16)(yCenter + offYEnd) << (TQ_UINT16)(xCenter + offXEnd);
285 d->mSt << (TQ_UINT16)(yCenter + offYStart) << (TQ_UINT16)(xCenter + offXStart);
286 d->mSt << (TQ_UINT16)(top + height) << (TQ_UINT16)(left + width);
287 d->mSt << (TQ_UINT16)top << (TQ_UINT16)left;
288
289 d->mMaxRecordSize = TQMAX( d->mMaxRecordSize, 11 );
290}
291
292
293void KoWmfWrite::drawPie( int left, int top, int width, int height , int a, int alen ) {
294 int xCenter, yCenter;
295 int offXStart, offYStart, offXEnd, offYEnd;
296
297 angleToxy( offXStart, offYStart, offXEnd, offYEnd, a, alen );
298 xCenter = left + (width / 2);
299 yCenter = top + (height / 2);
300
301 d->mSt << (TQ_UINT32)11 << (TQ_UINT16)0x081A;
302 d->mSt << (TQ_UINT16)(yCenter + offYEnd) << (TQ_UINT16)(xCenter + offXEnd);
303 d->mSt << (TQ_UINT16)(yCenter + offYStart) << (TQ_UINT16)(xCenter + offXStart);
304 d->mSt << (TQ_UINT16)(top + height) << (TQ_UINT16)(left + width);
305 d->mSt << (TQ_UINT16)top << (TQ_UINT16)left;
306
307 d->mMaxRecordSize = TQMAX( d->mMaxRecordSize, 11 );
308}
309
310
311void KoWmfWrite::drawChord( int left, int top, int width, int height , int a, int alen ) {
312 int xCenter, yCenter;
313 int offXStart, offYStart, offXEnd, offYEnd;
314
315 angleToxy( offXStart, offYStart, offXEnd, offYEnd, a, alen );
316 xCenter = left + (width / 2);
317 yCenter = top + (height / 2);
318
319 d->mSt << (TQ_UINT32)11 << (TQ_UINT16)0x0830;
320 d->mSt << (TQ_UINT16)(yCenter + offYEnd) << (TQ_UINT16)(xCenter + offXEnd);
321 d->mSt << (TQ_UINT16)(yCenter + offYStart) << (TQ_UINT16)(xCenter + offXStart);
322 d->mSt << (TQ_UINT16)(top + height) << (TQ_UINT16)(left + width);
323 d->mSt << (TQ_UINT16)top << (TQ_UINT16)left;
324
325 d->mMaxRecordSize = TQMAX( d->mMaxRecordSize, 11 );
326}
327
328
329void KoWmfWrite::drawPolyline( const TQPointArray &pa ) {
330 int size = 4 + (pa.size() * 2);
331
332 d->mSt << (TQ_UINT32)size << (TQ_UINT16)0x0325 << (TQ_UINT16)pa.size();
333 pointArray( pa );
334
335 d->mMaxRecordSize = TQMAX( d->mMaxRecordSize, size );
336}
337
338
339void KoWmfWrite::drawPolygon( const TQPointArray &pa, bool ) {
340 int size = 4 + (pa.size() * 2);
341
342 d->mSt << (TQ_UINT32)size << (TQ_UINT16)0x0324 << (TQ_UINT16)pa.size();
343 pointArray( pa );
344
345 d->mMaxRecordSize = TQMAX( d->mMaxRecordSize, size );
346}
347
348
349void KoWmfWrite::drawPolyPolygon( TQPtrList<TQPointArray>& listPa, bool ) {
350
351 TQPointArray *pa;
352 int sizeArrayPoly = 0;
353
354 for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
355 sizeArrayPoly += (pa->size() * 2);
356 }
357 int size = 4 + listPa.count() + sizeArrayPoly;
358 d->mSt << (TQ_UINT32)size << (TQ_UINT16)0x0538 << (TQ_UINT16)listPa.count();
359
360 // number of point for each Polygon
361 for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
362 d->mSt << (TQ_UINT16)pa->size();
363 }
364
365 // list of points
366 for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
367 pointArray( *pa );
368 }
369
370 d->mMaxRecordSize = TQMAX( d->mMaxRecordSize, size );
371
372}
373
374
375void KoWmfWrite::drawImage( int , int , const TQImage &, int , int , int , int ) {
376/*
377 TQImage img;
378
379 img = image;
380 img.setFormat( "BMP" );
381
382 TQIODevice io = img.ioDevice();
383 io.at( 14 ); // skip the BMP header
384 d->mSt << io.readAll();
385*/
386}
387
388
389void KoWmfWrite::drawText( int , int , int , int , int , const TQString& , double ) {
390// d->mSt << (TQ_UINT32)3 << (TQ_UINT16)0x0A32;
391}
392
393//-----------------------------------------------------------------------------
394// Utilities and conversion TQt --> Wmf
395
396void KoWmfWrite::pointArray( const TQPointArray &pa ) {
397 int left, top, i, max;
398
399 for ( i=0, max=pa.size() ; i < max ; i++ ) {
400 pa.point( i, &left, &top );
401 d->mSt << (TQ_INT16)left << (TQ_INT16)top;
402 }
403}
404
405
406TQ_UINT32 KoWmfWrite::winColor( TQColor color ) {
407 TQ_UINT32 c;
408
409 c = (color.red() & 0xFF);
410 c += ( (color.green() & 0xFF) << 8 );
411 c += ( (color.blue() & 0xFF) << 16 );
412
413 return c;
414}
415
416
417void KoWmfWrite::angleToxy( int &xStart, int &yStart, int &xEnd, int &yEnd, int a, int alen ) {
418 double angleStart, angleLength;
419
420 angleStart = ((double)a * 3.14166) / 2880;
421 angleLength = ((double)alen * 3.14166) / 2880;
422
423 xStart = (int)(cos(angleStart) * 50);
424 yStart = -(int)(sin(angleStart) * 50);
425 xEnd = (int)(cos(angleLength) * 50);
426 yEnd = -(int)(sin(angleLength) * 50);
427}
428
429
430TQ_UINT16 KoWmfWrite::qtRasterToWin16( TQt::RasterOp op ) const {
431 int i;
432
433 for ( i=0 ; i < 17 ; i++ ) {
434 if ( koWmfOpTab16[ i ] == op ) break;
435 }
436
437 if ( i < 17 )
438 return (TQ_UINT16)i;
439 else
440 return (TQ_UINT16)0;
441}
442
443
444TQ_UINT32 KoWmfWrite::qtRasterToWin32( TQt::RasterOp op ) const {
445 int i;
446
447 for ( i=0 ; i < 15 ; i++ ) {
448 if ( koWmfOpTab32[ i ].qtRasterOp == op ) break;
449 }
450
451 if ( i < 15 )
452 return koWmfOpTab32[ i ].winRasterOp;
453 else
454 return koWmfOpTab32[ 0 ].winRasterOp;
455}
456
static TQ_UINT16 calcCheckSum(WmfPlaceableHeader *)
Calculate header checksum.
void setDefaultDpi(int dpi)
Placeable WMF's use logical coordinates and have a default DPI.
bool begin()
Open the file.
bool end()
Close the file.