lib

kowmfreadprivate.cpp
1/* This file is part of the KDE libraries
2 * Copyright (c) 1998 Stefan Taferner
3 * 2001/2003 thierry lorthiois (lorthioist@wanadoo.fr)
4 * With the help of WMF documentation by Caolan Mc Namara
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License version 2 as published by the Free Software Foundation.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include <math.h>
22#include <tqfileinfo.h>
23#include <tqimage.h>
24#include <tqwmatrix.h>
25#include <tqptrlist.h>
26#include <tqpointarray.h>
27#include <tqdatastream.h>
28#include <kdebug.h>
29
30#include "kowmfreadprivate.h"
31#include "kowmfread.h"
32
33
34KoWmfReadPrivate::KoWmfReadPrivate()
35{
36 mNbrFunc = 0;
37 mValid = false;
38 mStandard = false;
39 mPlaceable = false;
40 mEnhanced = false;
41 mBuffer = 0;
42 mObjHandleTab = 0;
43}
44
45
46KoWmfReadPrivate::~KoWmfReadPrivate()
47{
48 if ( mObjHandleTab != 0 ) {
49 for ( int i=0 ; i < mNbrObject ; i++ ) {
50 if ( mObjHandleTab[i] != 0 )
51 delete mObjHandleTab[i];
52 }
53 delete[] mObjHandleTab;
54 }
55 if ( mBuffer != 0 ) {
56 mBuffer->close();
57 delete mBuffer;
58 }
59}
60
61
62bool KoWmfReadPrivate::load( const TQByteArray& array )
63{
64 // delete previous buffer
65 if ( mBuffer != 0 ) {
66 mBuffer->close();
67 delete mBuffer;
68 }
69
70 // load into buffer
71 mBuffer = new TQBuffer( array );
72 mBuffer->open( IO_ReadOnly );
73
74 // read and check the header
75 WmfEnhMetaHeader eheader;
76 WmfMetaHeader header;
77 WmfPlaceableHeader pheader;
78 unsigned short checksum;
79 int filePos;
80
81 TQDataStream st( mBuffer );
82 st.setByteOrder( TQDataStream::LittleEndian );
83 mStackOverflow = mWinding = false;
84 mTextAlign = mTextRotation = 0;
85 mTextColor = TQt::black;
86 mValid = false;
87 mStandard = false;
88 mPlaceable = false;
89 mEnhanced = false;
90
91 //----- Read placeable metafile header
92 st >> pheader.key;
93 if ( pheader.key==( TQ_UINT32 )APMHEADER_KEY ) {
94 mPlaceable = true;
95 st >> pheader.handle;
96 st >> pheader.left;
97 st >> pheader.top;
98 st >> pheader.right;
99 st >> pheader.bottom;
100 st >> pheader.inch;
101 st >> pheader.reserved;
102 st >> pheader.checksum;
103 checksum = calcCheckSum( &pheader );
104 if ( pheader.checksum!=checksum ) {
105 return false;
106 }
107 st >> header.fileType;
108 st >> header.headerSize;
109 st >> header.version;
110 st >> header.fileSize;
111 st >> header.numOfObjects;
112 st >> header.maxRecordSize;
113 st >> header.numOfParameters;
114 mNbrObject = header.numOfObjects;
115 mBBox.setLeft( pheader.left );
116 mBBox.setTop( pheader.top );
117 mBBox.setRight( pheader.right );
118 mBBox.setBottom( pheader.bottom );
119 mDpi = pheader.inch;
120 }
121 else {
122 mBuffer->at( 0 );
123 //----- Read as enhanced metafile header
124 filePos = mBuffer->at();
125 st >> eheader.recordType;
126 st >> eheader.recordSize;
127 st >> eheader.boundsLeft;
128 st >> eheader.boundsTop;
129 st >> eheader.boundsRight;
130 st >> eheader.boundsBottom;
131 st >> eheader.frameLeft;
132 st >> eheader.frameTop;
133 st >> eheader.frameRight;
134 st >> eheader.frameBottom;
135 st >> eheader.signature;
136 if ( eheader.signature==ENHMETA_SIGNATURE ) {
137 mEnhanced = true;
138 st >> eheader.version;
139 st >> eheader.size;
140 st >> eheader.numOfRecords;
141 st >> eheader.numHandles;
142 st >> eheader.reserved;
143 st >> eheader.sizeOfDescription;
144 st >> eheader.offsetOfDescription;
145 st >> eheader.numPaletteEntries;
146 st >> eheader.widthDevicePixels;
147 st >> eheader.heightDevicePixels;
148 st >> eheader.widthDeviceMM;
149 st >> eheader.heightDeviceMM;
150 }
151 else {
152 //----- Read as standard metafile header
153 mStandard = true;
154 mBuffer->at( filePos );
155 st >> header.fileType;
156 st >> header.headerSize;
157 st >> header.version;
158 st >> header.fileSize;
159 st >> header.numOfObjects;
160 st >> header.maxRecordSize;
161 st >> header.numOfParameters;
162 mNbrObject = header.numOfObjects;
163 }
164 }
165 mOffsetFirstRecord = mBuffer->at();
166
167 //----- Test header validity
168 if ( ((header.headerSize == 9) && (header.numOfParameters == 0)) || (mPlaceable) ) {
169 // valid wmf file
170 mValid = true;
171 }
172 else {
173 kdDebug() << "KoWmfReadPrivate : incorrect file format !" << endl;
174 }
175
176 // check bounding rectangle for standard meta file
177 if ( (mValid) && (mStandard) ) {
178 TQ_UINT16 numFunction = 1;
179 TQ_UINT32 size;
180 bool firstOrg=true, firstExt=true;
181
182 // search functions setWindowOrg and setWindowExt
183 while ( numFunction ) {
184 filePos = mBuffer->at();
185 st >> size >> numFunction;
186
187 if ( size == 0 ) {
188 kdDebug() << "KoWmfReadPrivate : incorrect file!" << endl;
189 mValid = 0;
190 break;
191 }
192
193 numFunction &= 0xFF;
194 if ( numFunction == 11 ) {
195 TQ_INT16 top, left;
196
197 st >> top >> left;
198 if ( firstOrg ) {
199 firstOrg = false;
200 mBBox.setLeft( left );
201 mBBox.setTop( top );
202 }
203 else {
204 if ( left < mBBox.left() ) mBBox.setLeft( left );
205 if ( top < mBBox.top() ) mBBox.setTop( top );
206 }
207 }
208 if ( numFunction == 12 ) {
209 TQ_INT16 width, height;
210
211 st >> height >> width;
212 if ( width < 0 ) width = -width;
213 if ( height < 0 ) height = -height;
214 if ( firstExt ) {
215 firstExt = false;
216 mBBox.setWidth( width );
217 mBBox.setHeight( height );
218 }
219 else {
220 if ( width > mBBox.width() ) mBBox.setWidth( width );
221 if ( height > mBBox.height() ) mBBox.setHeight( height );
222 }
223 }
224 mBuffer->at( filePos + (size<<1) );
225 // ## shouldn't we break from the loop as soon as we found what we were looking for?
226 }
227 }
228
229 return (mValid);
230}
231
232
234{
235 if ( !(mValid) ) {
236 kdDebug() << "KoWmfReadPrivate::play : invalid WMF file" << endl;
237 return false;
238 }
239
240 if ( mNbrFunc ) {
241 if ( (mStandard) ) {
242 kdDebug() << "Standard : " << mBBox.left() << " " << mBBox.top() << " " << mBBox.width() << " " << mBBox.height() << endl;
243 }
244 else {
245 kdDebug() << "DPI : " << mDpi << " : " << mBBox.left() << " " << mBBox.top() << " " << mBBox.width() << " " << mBBox.height() << endl;
246 kdDebug() << "inch : " << mBBox.width()/mDpi << " " << mBBox.height()/mDpi << endl;
247 kdDebug() << "mm : " << mBBox.width()*25.4/mDpi << " " << mBBox.height()*25.4/mDpi << endl;
248 }
249 kdDebug() << mValid << " " << mStandard << " " << mPlaceable << endl;
250 }
251
252 // stack of handle
253 mObjHandleTab = new KoWmfHandle* [ mNbrObject ];
254 for ( int i=0; i < mNbrObject ; i++ ) {
255 mObjHandleTab[ i ] = 0;
256 }
257
258 TQ_UINT16 numFunction;
259 TQ_UINT32 size;
260 int bufferOffset, j;
261
262 // buffer with functions
263 TQDataStream st( mBuffer );
264 st.setByteOrder( TQDataStream::LittleEndian );
265
266 mReadWmf = readWmf;
267 mWindow = mBBox;
268 if ( mReadWmf->begin() ) {
269 // play wmf functions
270 mBuffer->at( mOffsetFirstRecord );
271 numFunction = j = 1;
272 mWinding = false;
273
274 while ( ( numFunction ) && ( !mStackOverflow ) ) {
275 bufferOffset = mBuffer->at();
276 st >> size >> numFunction;
277
282 numFunction &= 0xFF;
283 if ( numFunction > 0x5F ) {
284 numFunction -= 0x90;
285 }
286 if ( (numFunction > 111) || (koWmfFunc[ numFunction ].method == 0) ) {
287 // function outside WMF specification
288 kdDebug() << "KoWmfReadPrivate::paint : BROKEN WMF file" << endl;
289 mValid = false;
290 break;
291 }
292
293 if ( mNbrFunc ) {
294 // debug mode
295 if ( (j+12) > mNbrFunc ) {
296 // output last 12 functions
297 int offBuff = mBuffer->at();
298 TQ_UINT16 param;
299
300 kdDebug() << j << " : " << numFunction << " : ";
301 for ( TQ_UINT16 i=0 ; i < (size-3) ; i++ ) {
302 st >> param;
303 kdDebug() << param << " ";
304 }
305 kdDebug() << endl;
306 mBuffer->at( offBuff );
307 }
308 if ( j >= mNbrFunc ) {
309 break;
310 }
311 j++;
312 }
313
314 // execute the function
315 (this->*koWmfFunc[ numFunction ].method)( size, st );
316
317 mBuffer->at( bufferOffset + (size<<1) );
318 }
319
320 mReadWmf->end();
321 }
322
323 for ( int i=0 ; i < mNbrObject ; i++ ) {
324 if ( mObjHandleTab[ i ] != 0 )
325 delete mObjHandleTab[ i ];
326 }
327 delete[] mObjHandleTab;
328 mObjHandleTab = 0;
329
330 return true;
331}
332
333
334//-----------------------------------------------------------------------------
335// Metafile painter methods
336
337void KoWmfReadPrivate::setWindowOrg( TQ_UINT32, TQDataStream& stream )
338{
339 TQ_INT16 top, left;
340
341 stream >> top >> left;
342 mReadWmf->setWindowOrg( left, top );
343 mWindow.setLeft( left );
344 mWindow.setTop( top );
345// kdDebug() << "Org : (" << left << ", " << top << ") " << endl;
346}
347
348/* TODO : deeper look in negative width and height
349*/
350
351void KoWmfReadPrivate::setWindowExt( TQ_UINT32, TQDataStream& stream )
352{
353 TQ_INT16 width, height;
354
355 // negative value allowed for width and height
356 stream >> height >> width;
357 mReadWmf->setWindowExt( width, height );
358 mWindow.setWidth( width );
359 mWindow.setHeight( height );
360// kdDebug() << "Ext : (" << width << ", " << height << ") "<< endl;
361}
362
363
364void KoWmfReadPrivate::OffsetWindowOrg( TQ_UINT32, TQDataStream &stream )
365{
366 TQ_INT16 offTop, offLeft;
367
368 stream >> offTop >> offLeft;
369 mReadWmf->setWindowOrg( mWindow.left() + offLeft, mWindow.top() + offTop );
370 mWindow.setLeft( mWindow.left() + offLeft );
371 mWindow.setTop( mWindow.top() + offTop );
372}
373
374
375void KoWmfReadPrivate::ScaleWindowExt( TQ_UINT32, TQDataStream &stream )
376{
377 TQ_INT16 width, height;
378 TQ_INT16 heightDenom, heightNum, widthDenom, widthNum;
379
380 stream >> heightDenom >> heightNum >> widthDenom >> widthNum;
381
382 if ( ( widthDenom != 0 ) && ( heightDenom != 0 ) ) {
383 width = (mWindow.width() * widthNum) / widthDenom;
384 height = (mWindow.height() * heightNum) / heightDenom;
385 mReadWmf->setWindowExt( width, height );
386 mWindow.setWidth( width );
387 mWindow.setHeight( height );
388 }
389// kdDebug() << "KoWmfReadPrivate::ScaleWindowExt : " << widthDenom << " " << heightDenom << endl;
390}
391
392
393//-----------------------------------------------------------------------------
394// Drawing
395
396void KoWmfReadPrivate::lineTo( TQ_UINT32, TQDataStream& stream )
397{
398 TQ_INT16 top, left;
399
400 stream >> top >> left;
401 mReadWmf->lineTo( left, top );
402}
403
404
405void KoWmfReadPrivate::moveTo( TQ_UINT32, TQDataStream& stream )
406{
407 TQ_INT16 top, left;
408
409 stream >> top >> left;
410 mReadWmf->moveTo( left, top );
411}
412
413
414void KoWmfReadPrivate::ellipse( TQ_UINT32, TQDataStream& stream )
415{
416 TQ_INT16 top, left, right, bottom;
417
418 stream >> bottom >> right >> top >> left;
419 mReadWmf->drawEllipse( left, top, right-left, bottom-top );
420}
421
422
423void KoWmfReadPrivate::polygon( TQ_UINT32, TQDataStream& stream )
424{
425 TQ_UINT16 num;
426
427 stream >> num;
428
429 TQPointArray pa( num );
430
431 pointArray( stream, pa );
432 mReadWmf->drawPolygon( pa, mWinding );
433}
434
435
436void KoWmfReadPrivate::polyPolygon( TQ_UINT32, TQDataStream& stream )
437{
438 TQ_UINT16 numberPoly;
439 TQ_UINT16 sizePoly;
440 TQPtrList<TQPointArray> listPa;
441
442 stream >> numberPoly;
443
444 listPa.setAutoDelete( true );
445 for ( int i=0 ; i < numberPoly ; i++ ) {
446 stream >> sizePoly;
447 listPa.append( new TQPointArray( sizePoly ) );
448 }
449
450 // list of point array
451 TQPointArray *pa;
452 for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
453 pointArray( stream, *pa );
454 }
455
456 // draw polygon's
457 mReadWmf->drawPolyPolygon( listPa, mWinding );
458 listPa.clear();
459}
460
461
462void KoWmfReadPrivate::polyline( TQ_UINT32, TQDataStream& stream )
463{
464 TQ_UINT16 num;
465
466 stream >> num;
467 TQPointArray pa( num );
468
469 pointArray( stream, pa );
470 mReadWmf->drawPolyline( pa );
471}
472
473
474void KoWmfReadPrivate::rectangle( TQ_UINT32, TQDataStream& stream )
475{
476 TQ_INT16 top, left, right, bottom;
477
478 stream >> bottom >> right >> top >> left;
479 mReadWmf->drawRect( left, top, right-left, bottom-top );
480}
481
482
483void KoWmfReadPrivate::roundRect( TQ_UINT32, TQDataStream& stream )
484{
485 int xRnd = 0, yRnd = 0;
486 TQ_UINT16 widthCorner, heightCorner;
487 TQ_INT16 top, left, right, bottom;
488
489 stream >> heightCorner >> widthCorner;
490 stream >> bottom >> right >> top >> left;
491
492 // convert (widthCorner, heightCorner) in percentage
493 if ( (right - left) != 0 )
494 xRnd = (widthCorner * 100) / (right - left);
495 if ( (bottom - top) != 0 )
496 yRnd = (heightCorner * 100) / (bottom - top);
497
498 mReadWmf->drawRoundRect( left, top, right-left, bottom-top, xRnd, yRnd );
499}
500
501
502void KoWmfReadPrivate::arc( TQ_UINT32, TQDataStream& stream )
503{
504 int xCenter, yCenter, angleStart, aLength;
505 TQ_INT16 topEnd, leftEnd, topStart, leftStart;
506 TQ_INT16 top, left, right, bottom;
507
508 stream >> topEnd >> leftEnd >> topStart >> leftStart;
509 stream >> bottom >> right >> top >> left;
510
511 xCenter = left + ((right-left) / 2);
512 yCenter = top + ((bottom-top) / 2);
513 xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
514
515 mReadWmf->drawArc( left, top, right-left, bottom-top, angleStart, aLength);
516}
517
518
519void KoWmfReadPrivate::chord( TQ_UINT32, TQDataStream& stream )
520{
521 int xCenter, yCenter, angleStart, aLength;
522 TQ_INT16 topEnd, leftEnd, topStart, leftStart;
523 TQ_INT16 top, left, right, bottom;
524
525 stream >> topEnd >> leftEnd >> topStart >> leftStart;
526 stream >> bottom >> right >> top >> left;
527
528 xCenter = left + ((right-left) / 2);
529 yCenter = top + ((bottom-top) / 2);
530 xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
531
532 mReadWmf->drawChord( left, top, right-left, bottom-top, angleStart, aLength);
533}
534
535
536void KoWmfReadPrivate::pie( TQ_UINT32, TQDataStream& stream )
537{
538 int xCenter, yCenter, angleStart, aLength;
539 TQ_INT16 topEnd, leftEnd, topStart, leftStart;
540 TQ_INT16 top, left, right, bottom;
541
542 stream >> topEnd >> leftEnd >> topStart >> leftStart;
543 stream >> bottom >> right >> top >> left;
544
545 xCenter = left + ((right-left) / 2);
546 yCenter = top + ((bottom-top) / 2);
547 xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
548
549 mReadWmf->drawPie( left, top, right-left, bottom-top, angleStart, aLength);
550}
551
552
553void KoWmfReadPrivate::setPolyFillMode( TQ_UINT32, TQDataStream& stream )
554{
555 TQ_UINT16 winding;
556
557 stream >> winding;
558 mWinding = (winding != 0);
559}
560
561
562void KoWmfReadPrivate::setBkColor( TQ_UINT32, TQDataStream& stream )
563{
564 TQ_UINT32 color;
565
566 stream >> color;
567 mReadWmf->setBackgroundColor( qtColor( color ) );
568}
569
570
571void KoWmfReadPrivate::setBkMode( TQ_UINT32, TQDataStream& stream )
572{
573 TQ_UINT16 bkMode;
574
575 stream >> bkMode;
576 if ( bkMode == 1 )
577 mReadWmf->setBackgroundMode( TQt::TransparentMode );
578 else
579 mReadWmf->setBackgroundMode( TQt::OpaqueMode );
580}
581
582
583void KoWmfReadPrivate::setPixel( TQ_UINT32, TQDataStream& stream )
584{
585 TQ_INT16 top, left;
586 TQ_UINT32 color;
587
588 stream >> color >> top >> left;
589
590 TQPen oldPen = mReadWmf->pen();
591 TQPen pen = oldPen;
592 pen.setColor( qtColor( color ) );
593 mReadWmf->setPen( pen );
594 mReadWmf->moveTo( left, top );
595 mReadWmf->lineTo( left, top );
596 mReadWmf->setPen( oldPen );
597}
598
599
600void KoWmfReadPrivate::setRop( TQ_UINT32, TQDataStream& stream )
601{
602 TQ_UINT16 rop;
603
604 stream >> rop;
605 mReadWmf->setRasterOp( winToTQtRaster( rop ) );
606}
607
608
609void KoWmfReadPrivate::saveDC( TQ_UINT32, TQDataStream& )
610{
611 mReadWmf->save();
612}
613
614
615void KoWmfReadPrivate::restoreDC( TQ_UINT32, TQDataStream& stream )
616{
617 TQ_INT16 num;
618
619 stream >> num;
620 for ( int i=0; i > num ; i-- )
621 mReadWmf->restore();
622}
623
624
625void KoWmfReadPrivate::intersectClipRect( TQ_UINT32, TQDataStream& stream )
626{
627 TQ_INT16 top, left, right, bottom;
628
629 stream >> bottom >> right >> top >> left;
630
631 TQRegion region = mReadWmf->clipRegion();
632 TQRegion newRegion( left, top, right-left, bottom-top );
633 if ( region.isEmpty() ) {
634 region = newRegion;
635 }
636 else {
637 region = region.intersect( newRegion );
638 }
639
640 mReadWmf->setClipRegion( region );
641}
642
643
644void KoWmfReadPrivate::excludeClipRect( TQ_UINT32, TQDataStream& stream )
645{
646 TQ_INT16 top, left, right, bottom;
647
648 stream >> bottom >> right >> top >> left;
649
650 TQRegion region = mReadWmf->clipRegion();
651 TQRegion newRegion( left, top, right-left, bottom-top );
652 if ( region.isEmpty() ) {
653 region = newRegion;
654 }
655 else {
656 region = region.subtract( newRegion );
657 }
658
659 mReadWmf->setClipRegion( region );
660}
661
662
663//-----------------------------------------------------------------------------
664// Text
665
666void KoWmfReadPrivate::setTextColor( TQ_UINT32, TQDataStream& stream )
667{
668 TQ_UINT32 color;
669
670 stream >> color;
671 mTextColor = qtColor( color );
672}
673
674
675void KoWmfReadPrivate::setTextAlign( TQ_UINT32, TQDataStream& stream )
676{
677 stream >> mTextAlign;
678}
679
680
681void KoWmfReadPrivate::textOut( TQ_UINT32, TQDataStream& )
682{
683 if ( mNbrFunc ) {
684 kdDebug() << "textOut : unimplemented " << endl;
685 }
686}
687
688
689void KoWmfReadPrivate::extTextOut( TQ_UINT32 , TQDataStream& )
690{
691 if ( mNbrFunc ) {
692 kdDebug() << "extTextOut : unimplemented " << endl;
693 }
694}
695
696
697
698//-----------------------------------------------------------------------------
699// Bitmap
700
701void KoWmfReadPrivate::SetStretchBltMode( TQ_UINT32, TQDataStream& )
702{
703 if ( mNbrFunc ) {
704 kdDebug() << "SetStretchBltMode : unimplemented " << endl;
705 }
706}
707
708
709void KoWmfReadPrivate::dibBitBlt( TQ_UINT32 size, TQDataStream& stream )
710{
711 TQ_UINT32 raster;
712 TQ_INT16 topSrc, leftSrc, widthSrc, heightSrc;
713 TQ_INT16 topDst, leftDst;
714
715 stream >> raster;
716 stream >> topSrc >> leftSrc >> heightSrc >> widthSrc;
717 stream >> topDst >> leftDst;
718
719 if ( size > 11 ) { // DIB image
720 TQImage bmpSrc;
721
722 if ( dibToBmp( bmpSrc, stream, (size - 11) * 2 ) ) {
723 mReadWmf->setRasterOp( winToTQtRaster( raster ) );
724
725 mReadWmf->save();
726 if ( widthSrc < 0 ) {
727 // negative width => horizontal flip
728 TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
729 mReadWmf->setWorldMatrix( m, true );
730 }
731 if ( heightSrc < 0 ) {
732 // negative height => vertical flip
733 TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
734 mReadWmf->setWorldMatrix( m, true );
735 }
736 mReadWmf->drawImage( leftDst, topDst, bmpSrc, leftSrc, topSrc, widthSrc, heightSrc );
737 mReadWmf->restore();
738 }
739 }
740 else {
741 kdDebug() << "KoWmfReadPrivate::dibBitBlt without image not implemented " << endl;
742 }
743}
744
745
746void KoWmfReadPrivate::dibStretchBlt( TQ_UINT32 size, TQDataStream& stream )
747{
748 TQ_UINT32 raster;
749 TQ_INT16 topSrc, leftSrc, widthSrc, heightSrc;
750 TQ_INT16 topDst, leftDst, widthDst, heightDst;
751 TQImage bmpSrc;
752
753 stream >> raster;
754 stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
755 stream >> heightDst >> widthDst >> topDst >> leftDst;
756
757 if ( dibToBmp( bmpSrc, stream, (size - 13) * 2 ) ) {
758 mReadWmf->setRasterOp( winToTQtRaster( raster ) );
759
760 mReadWmf->save();
761 if ( widthDst < 0 ) {
762 // negative width => horizontal flip
763 TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
764 mReadWmf->setWorldMatrix( m, true );
765 }
766 if ( heightDst < 0 ) {
767 // negative height => vertical flip
768 TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
769 mReadWmf->setWorldMatrix( m, true );
770 }
771 bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
772 // TODO: scale the bitmap : TQImage::scale(widthDst, heightDst)
773 // is actually too slow
774
775 mReadWmf->drawImage( leftDst, topDst, bmpSrc );
776 mReadWmf->restore();
777 }
778}
779
780
781void KoWmfReadPrivate::stretchDib( TQ_UINT32 size, TQDataStream& stream )
782{
783 TQ_UINT32 raster;
784 TQ_INT16 arg, topSrc, leftSrc, widthSrc, heightSrc;
785 TQ_INT16 topDst, leftDst, widthDst, heightDst;
786 TQImage bmpSrc;
787
788 stream >> raster >> arg;
789 stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
790 stream >> heightDst >> widthDst >> topDst >> leftDst;
791
792 if ( dibToBmp( bmpSrc, stream, (size - 14) * 2 ) ) {
793 mReadWmf->setRasterOp( winToTQtRaster( raster ) );
794
795 mReadWmf->save();
796 if ( widthDst < 0 ) {
797 // negative width => horizontal flip
798 TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
799 mReadWmf->setWorldMatrix( m, true );
800 }
801 if ( heightDst < 0 ) {
802 // negative height => vertical flip
803 TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
804 mReadWmf->setWorldMatrix( m, true );
805 }
806 bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
807 // TODO: scale the bitmap ( TQImage::scale(param[ 8 ], param[ 7 ]) is actually too slow )
808
809 mReadWmf->drawImage( leftDst, topDst, bmpSrc );
810 mReadWmf->restore();
811 }
812}
813
814
815void KoWmfReadPrivate::dibCreatePatternBrush( TQ_UINT32 size, TQDataStream& stream )
816{
817 KoWmfPatternBrushHandle* handle = new KoWmfPatternBrushHandle;
818
819 if ( addHandle( handle ) ) {
820 TQ_UINT32 arg;
821 TQImage bmpSrc;
822
823 stream >> arg;
824 if ( dibToBmp( bmpSrc, stream, (size - 5) * 2 ) ) {
825 handle->image = bmpSrc;
826 handle->brush.setPixmap( handle->image );
827 }
828 else {
829 kdDebug() << "KoWmfReadPrivate::dibCreatePatternBrush : incorrect DIB image" << endl;
830 }
831 }
832}
833
834
835//-----------------------------------------------------------------------------
836// Object handle
837
838void KoWmfReadPrivate::selectObject( TQ_UINT32, TQDataStream& stream )
839{
840 TQ_UINT16 idx;
841
842 stream >> idx;
843 if ( (idx < mNbrObject) && (mObjHandleTab[ idx ] != 0) )
844 mObjHandleTab[ idx ]->apply( mReadWmf );
845 else
846 kdDebug() << "KoWmfReadPrivate::selectObject : selection of an empty object" << endl;
847}
848
849
850void KoWmfReadPrivate::deleteObject( TQ_UINT32, TQDataStream& stream )
851{
852 TQ_UINT16 idx;
853
854 stream >> idx;
855 deleteHandle( idx );
856}
857
858
860{
861 // allocation of an empty object (to keep object counting in sync)
862 KoWmfPenHandle* handle = new KoWmfPenHandle;
863
864 addHandle( handle );
865}
866
867
868void KoWmfReadPrivate::createBrushIndirect( TQ_UINT32, TQDataStream& stream )
869{
870 TQt::BrushStyle style;
871 TQ_UINT16 sty, arg2;
872 TQ_UINT32 color;
873 KoWmfBrushHandle* handle = new KoWmfBrushHandle;
874
875 if ( addHandle( handle ) ) {
876 stream >> sty >> color >> arg2;
877
878 if ( sty == 2 ) {
879 if ( arg2 < 6 )
880 style = koWmfHatchedStyleBrush[ arg2 ];
881 else
882 {
883 kdDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid hatched brush " << arg2 << endl;
884 style = TQt::SolidPattern;
885 }
886 }
887 else {
888 if ( sty < 9 )
889 style = koWmfStyleBrush[ sty ];
890 else {
891 kdDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid brush " << sty << endl;
892 style = TQt::SolidPattern;
893 }
894 }
895 handle->brush.setStyle( style );
896 handle->brush.setColor( qtColor( color ) );
897 }
898}
899
900
901void KoWmfReadPrivate::createPenIndirect( TQ_UINT32, TQDataStream& stream )
902{
903 // TODO: userStyle and alternateStyle
904 TQt::PenStyle penStyle;
905 TQ_UINT32 color;
906 TQ_UINT16 style, width, arg;
907
908 KoWmfPenHandle* handle = new KoWmfPenHandle;
909
910 if ( addHandle( handle ) ) {
911 stream >> style >> width >> arg >> color;
912
913 if ( style < 7 )
914 penStyle=koWmfStylePen[ style ];
915 else {
916 kdDebug() << "KoWmfReadPrivate::createPenIndirect: invalid pen " << style << endl;
917 penStyle = TQt::SolidLine;
918 }
919
920 handle->pen.setStyle( penStyle );
921 handle->pen.setColor( qtColor( color ) );
922 handle->pen.setCapStyle( TQt::RoundCap );
923 handle->pen.setWidth( width );
924 }
925}
926
927
928void KoWmfReadPrivate::createFontIndirect( TQ_UINT32 size, TQDataStream& stream )
929{
930 TQ_INT16 pointSize, rotation;
931 TQ_UINT16 weight, property, fixedPitch, arg;
932
933 KoWmfFontHandle* handle = new KoWmfFontHandle;
934
935 if ( addHandle( handle ) ) {
936 stream >> pointSize >> arg;
937 stream >> rotation >> arg;
938 stream >> weight >> property >> arg >> arg;
939 stream >> fixedPitch;
940
941 // text rotation (in 1/10 degree)
942 // TODO: memorisation of rotation in object Font
943 mTextRotation = -rotation / 10;
944 handle->font.setFixedPitch( ((fixedPitch & 0x01) == 0) );
945 // TODO: investigation why some test case need -2
946 // size of font in logical point
947 handle->font.setPointSize( TQABS(pointSize) - 2 );
948 handle->font.setWeight( (weight >> 3) );
949 handle->font.setItalic( (property & 0x01) );
950 handle->font.setUnderline( (property & 0x100) );
951
952 // font name
953 int maxChar = (size-12) * 2;
954 char* nameFont = new char[maxChar];
955 stream.readRawBytes( nameFont, maxChar );
956 handle->font.setFamily( nameFont );
957 delete[] nameFont;
958 }
959}
960
961
962//-----------------------------------------------------------------------------
963// Misc functions
964
965void KoWmfReadPrivate::end( TQ_UINT32, TQDataStream& )
966{
967}
968
969TQ_UINT16 KoWmfReadPrivate::calcCheckSum( WmfPlaceableHeader* apmfh )
970{
971 TQ_UINT16* lpWord;
972 TQ_UINT16 wResult, i;
973
974 // Start with the first word
975 wResult = *( lpWord = ( TQ_UINT16* )( apmfh ) );
976 // XOR in each of the other 9 words
977 for( i=1; i<=9; i++ )
978 {
979 wResult ^= lpWord[ i ];
980 }
981 return wResult;
982}
983
984
985void KoWmfReadPrivate::notyet( TQ_UINT32, TQDataStream& )
986{
987 if ( mNbrFunc ) {
988 kdDebug() << "unimplemented " << endl;
989 }
990}
991
992void KoWmfReadPrivate::region( TQ_UINT32, TQDataStream& )
993{
994 if ( mNbrFunc ) {
995 kdDebug() << "region : unimplemented " << endl;
996 }
997}
998
999void KoWmfReadPrivate::palette( TQ_UINT32, TQDataStream& )
1000{
1001 if ( mNbrFunc ) {
1002 kdDebug() << "palette : unimplemented " << endl;
1003 }
1004}
1005
1006void KoWmfReadPrivate::escape( TQ_UINT32, TQDataStream& )
1007{
1008 if ( mNbrFunc ) {
1009 kdDebug() << "escape : unimplemented " << endl;
1010 }
1011}
1012
1013void KoWmfReadPrivate::setRelAbs( TQ_UINT32, TQDataStream& )
1014{
1015 if ( mNbrFunc ) {
1016 kdDebug() << "setRelAbs : unimplemented " << endl;
1017 }
1018}
1019
1020void KoWmfReadPrivate::setMapMode( TQ_UINT32, TQDataStream& )
1021{
1022 if ( mNbrFunc ) {
1023 kdDebug() << "setMapMode : unimplemented " << endl;
1024 }
1025}
1026
1027void KoWmfReadPrivate::extFloodFill( TQ_UINT32, TQDataStream& )
1028{
1029 if ( mNbrFunc ) {
1030 kdDebug() << "extFloodFill : unimplemented " << endl;
1031 }
1032}
1033
1034void KoWmfReadPrivate::startDoc( TQ_UINT32, TQDataStream& )
1035{
1036 if ( mNbrFunc ) {
1037 kdDebug() << "startDoc : unimplemented " << endl;
1038 }
1039}
1040
1041void KoWmfReadPrivate::startPage( TQ_UINT32, TQDataStream& )
1042{
1043 if ( mNbrFunc ) {
1044 kdDebug() << "startPage : unimplemented " << endl;
1045 }
1046}
1047
1048void KoWmfReadPrivate::endDoc( TQ_UINT32, TQDataStream& )
1049{
1050 if ( mNbrFunc ) {
1051 kdDebug() << "endDoc : unimplemented " << endl;
1052 }
1053}
1054
1055void KoWmfReadPrivate::endPage( TQ_UINT32, TQDataStream& )
1056{
1057 if ( mNbrFunc ) {
1058 kdDebug() << "endPage : unimplemented " << endl;
1059 }
1060}
1061
1062void KoWmfReadPrivate::resetDC( TQ_UINT32, TQDataStream& )
1063{
1064 if ( mNbrFunc ) {
1065 kdDebug() << "resetDC : unimplemented " << endl;
1066 }
1067}
1068
1069void KoWmfReadPrivate::bitBlt( TQ_UINT32, TQDataStream& )
1070{
1071 if ( mNbrFunc ) {
1072 kdDebug() << "bitBlt : unimplemented " << endl;
1073 }
1074}
1075
1076void KoWmfReadPrivate::setDibToDev( TQ_UINT32, TQDataStream& )
1077{
1078 if ( mNbrFunc ) {
1079 kdDebug() << "setDibToDev : unimplemented " << endl;
1080 }
1081}
1082
1083void KoWmfReadPrivate::createBrush( TQ_UINT32, TQDataStream& )
1084{
1085 if ( mNbrFunc ) {
1086 kdDebug() << "createBrush : unimplemented " << endl;
1087 }
1088}
1089
1090void KoWmfReadPrivate::createPatternBrush( TQ_UINT32, TQDataStream& )
1091{
1092 if ( mNbrFunc ) {
1093 kdDebug() << "createPatternBrush : unimplemented " << endl;
1094 }
1095}
1096
1097void KoWmfReadPrivate::createBitmap( TQ_UINT32, TQDataStream& )
1098{
1099 if ( mNbrFunc ) {
1100 kdDebug() << "createBitmap : unimplemented " << endl;
1101 }
1102}
1103
1104void KoWmfReadPrivate::createBitmapIndirect( TQ_UINT32, TQDataStream& )
1105{
1107 if ( mNbrFunc ) {
1108 kdDebug() << "createBitmapIndirect : unimplemented " << endl;
1109 }
1110}
1111
1112void KoWmfReadPrivate::createPalette( TQ_UINT32, TQDataStream& )
1113{
1115 if ( mNbrFunc ) {
1116 kdDebug() << "createPalette : unimplemented " << endl;
1117 }
1118}
1119
1120void KoWmfReadPrivate::createRegion( TQ_UINT32, TQDataStream& )
1121{
1123 if ( mNbrFunc ) {
1124 kdDebug() << "createRegion : unimplemented " << endl;
1125 }
1126}
1127
1128
1129
1130//-----------------------------------------------------------------------------
1131// Utilities and conversion Wmf -> TQt
1132
1133bool KoWmfReadPrivate::addHandle( KoWmfHandle* handle )
1134{
1135 int idx;
1136
1137 for ( idx=0; idx < mNbrObject ; idx++ ) {
1138 if ( mObjHandleTab[ idx ] == 0 ) break;
1139 }
1140
1141 if ( idx < mNbrObject ) {
1142 mObjHandleTab[ idx ] = handle;
1143 return true;
1144 }
1145 else {
1146 delete handle;
1147 mStackOverflow = true;
1148 kdDebug() << "KoWmfReadPrivate::addHandle : stack overflow = broken file !" << endl;
1149 return false;
1150 }
1151}
1152
1153
1154void KoWmfReadPrivate::deleteHandle( int idx )
1155{
1156 if ( (idx < mNbrObject) && (mObjHandleTab[idx] != 0) ) {
1157 delete mObjHandleTab[ idx ];
1158 mObjHandleTab[ idx ] = 0;
1159 }
1160 else {
1161 kdDebug() << "KoWmfReadPrivate::deletehandle() : bad index number" << endl;
1162 }
1163}
1164
1165
1166void KoWmfReadPrivate::pointArray( TQDataStream& stream, TQPointArray& pa )
1167{
1168 TQ_INT16 left, top;
1169 int i, max;
1170
1171 for ( i=0, max=pa.size() ; i < max ; i++ ) {
1172 stream >> left >> top;
1173 pa.setPoint( i, left, top );
1174 }
1175}
1176
1177
1178void KoWmfReadPrivate::xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angleStart, int& angleLength )
1179{
1180 double aStart, aLength;
1181
1182 aStart = atan2( yStart, xStart );
1183 aLength = atan2( yEnd, xEnd ) - aStart;
1184
1185 angleStart = (int)((aStart * 2880) / 3.14166);
1186 angleLength = (int)((aLength * 2880) / 3.14166);
1187 if ( angleLength < 0 ) angleLength = 5760 + angleLength;
1188}
1189
1190
1191TQt::RasterOp KoWmfReadPrivate::winToTQtRaster( TQ_UINT16 param ) const
1192{
1193 if ( param < 17 )
1194 return koWmfOpTab16[ param ];
1195 else
1196 return TQt::CopyROP;
1197}
1198
1199
1200TQt::RasterOp KoWmfReadPrivate::winToTQtRaster( TQ_UINT32 param ) const
1201{
1202 /* TODO: Ternary raster operations
1203 0x00C000CA dest = (source AND pattern)
1204 0x00F00021 dest = pattern
1205 0x00FB0A09 dest = DPSnoo
1206 0x005A0049 dest = pattern XOR dest */
1207 int i;
1208
1209 for ( i=0 ; i < 15 ; i++ ) {
1210 if ( koWmfOpTab32[ i ].winRasterOp == param ) break;
1211 }
1212
1213 if ( i < 15 )
1214 return koWmfOpTab32[ i ].qtRasterOp;
1215 else
1216 return TQt::CopyROP;
1217}
1218
1219
1220bool KoWmfReadPrivate::dibToBmp( TQImage& bmp, TQDataStream& stream, TQ_UINT32 size )
1221{
1222 typedef struct _BMPFILEHEADER {
1223 TQ_UINT16 bmType;
1224 TQ_UINT32 bmSize;
1225 TQ_UINT16 bmReserved1;
1226 TQ_UINT16 bmReserved2;
1227 TQ_UINT32 bmOffBits;
1228 } BMPFILEHEADER;
1229
1230 int sizeBmp = size + 14;
1231
1232 TQByteArray pattern( sizeBmp ); // BMP header and DIB data
1233 pattern.fill(0);
1234 stream.readRawBytes( &pattern[ 14 ], size );
1235
1236 // add BMP header
1237 BMPFILEHEADER* bmpHeader;
1238 bmpHeader = (BMPFILEHEADER*)(pattern.data());
1239 bmpHeader->bmType = 0x4D42;
1240 bmpHeader->bmSize = sizeBmp;
1241
1242// if ( !bmp.loadFromData( (const uchar*)bmpHeader, pattern.size(), "BMP" ) ) {
1243 if ( !bmp.loadFromData( pattern, "BMP" ) ) {
1244 kdDebug() << "KoWmfReadPrivate::dibToBmp: invalid bitmap " << endl;
1245 return false;
1246 }
1247 else {
1248 return true;
1249 }
1250}
1251
WMF file allows manipulation on a stack of object.
Definition kowmfstack.h:35
void arc(TQ_UINT32 size, TQDataStream &stream)
draw arc
TQRect mBBox
bounding rectangle
void createEmptyObject()
create an empty object in the object list
void setPixel(TQ_UINT32 size, TQDataStream &stream)
set a pixel
bool load(const TQByteArray &array)
Load WMF file.
void ellipse(TQ_UINT32 size, TQDataStream &stream)
draw ellipse
void moveTo(TQ_UINT32 size, TQDataStream &stream)
move pen to coord
void createFontIndirect(TQ_UINT32 size, TQDataStream &stream)
create a logical font
int mDpi
number of points per inch for the default size
void saveDC(TQ_UINT32 size, TQDataStream &stream)
save device context *‍/
void roundRect(TQ_UINT32 size, TQDataStream &stream)
draw round rectangle
void dibCreatePatternBrush(TQ_UINT32 size, TQDataStream &stream)
create a pattern brush
int mNbrFunc
number of functions to draw (==0 for all)
static TQ_UINT16 calcCheckSum(WmfPlaceableHeader *)
Calculate header checksum.
void createBrushIndirect(TQ_UINT32 size, TQDataStream &stream)
create a logical brush
void rectangle(TQ_UINT32 size, TQDataStream &stream)
draw a rectangle
void dibStretchBlt(TQ_UINT32 size, TQDataStream &stream)
stretches a DIB into a dest location
void chord(TQ_UINT32 size, TQDataStream &stream)
draw chord
void polyline(TQ_UINT32 size, TQDataStream &stream)
draw series of lines
void polygon(TQ_UINT32 size, TQDataStream &stream)
draw polygon
void excludeClipRect(TQ_UINT32 size, TQDataStream &stream)
delete a clipping rectangle of the original region
void end(TQ_UINT32, TQDataStream &stream)
end of meta file
void pie(TQ_UINT32 size, TQDataStream &stream)
draw pie
void deleteObject(TQ_UINT32 size, TQDataStream &stream)
free object handle
void lineTo(TQ_UINT32 size, TQDataStream &stream)
draw line to coord
void createPenIndirect(TQ_UINT32 size, TQDataStream &stream)
create a logical pen
bool play(KoWmfRead *readKwmf)
Plays a metafile in readKwmf and returns true on success.
void selectObject(TQ_UINT32 size, TQDataStream &stream)
activate object handle
void restoreDC(TQ_UINT32 size, TQDataStream &stream)
restore device context
void textOut(TQ_UINT32 size, TQDataStream &stream)
draw text
void OffsetWindowOrg(TQ_UINT32, TQDataStream &stream)
offset in window origin
void setWindowExt(TQ_UINT32 size, TQDataStream &stream)
set window extents
void dibBitBlt(TQ_UINT32 size, TQDataStream &stream)
copies a DIB into a dest location
void ScaleWindowExt(TQ_UINT32, TQDataStream &stream)
scale window extents
void setTextAlign(TQ_UINT32 size, TQDataStream &stream)
set text alignment
void setPolyFillMode(TQ_UINT32 size, TQDataStream &stream)
set polygon fill mode
void polyPolygon(TQ_UINT32 size, TQDataStream &stream)
draw a list of polygons
void setTextColor(TQ_UINT32 size, TQDataStream &stream)
set text color
void setWindowOrg(TQ_UINT32 size, TQDataStream &stream)
set window origin
void setBkColor(TQ_UINT32 size, TQDataStream &stream)
set background pen color
void setRop(TQ_UINT32 size, TQDataStream &stream)
set raster operation mode
void intersectClipRect(TQ_UINT32 size, TQDataStream &stream)
clipping region is the intersection of this region and the original region
void setBkMode(TQ_UINT32 size, TQDataStream &stream)
set background pen mode
KoWmfRead allows the redirection of the actions stored in a WMF file.
Definition kowmfread.h:47