lib Library API Documentation

kwmf.cc

00001 /* 00002 Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>. 00003 This file is part of the KDE project 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 00019 00020 DESCRIPTION 00021 00022 This is based on code originally written by Stefan Taferner 00023 (taferner@kde.org) and also borrows from libwmf (by Martin Vermeer and 00024 Caolan McNamara). 00025 */ 00026 00027 #include <kdebug.h> 00028 #include <math.h> 00029 #include <qfile.h> 00030 #include <qpointarray.h> 00031 #include <kwmf.h> 00032 #include <qrect.h> 00033 00034 #define PI (3.14159265358979323846) 00035 00036 const int KWmf::s_area = 30504; 00037 const int KWmf::s_maxHandles = 64; 00038 00039 KWmf::KWmf( 00040 unsigned dpi) 00041 { 00042 m_dpi = dpi; 00043 m_objectHandles = new WinObjHandle*[s_maxHandles]; 00044 } 00045 00046 KWmf::~KWmf() 00047 { 00048 delete[] m_objectHandles; 00049 } 00050 00051 // 00052 // 00053 // 00054 00055 void KWmf::brushSet( 00056 unsigned colour, 00057 unsigned style) 00058 { 00059 m_dc.m_brushColour = colour; 00060 m_dc.m_brushStyle = style; 00061 } 00062 00063 //----------------------------------------------------------------------------- 00064 unsigned KWmf::getColour( 00065 S32 colour) 00066 { 00067 unsigned red, green, blue; 00068 00069 red = colour & 255; 00070 green = (colour >> 8) & 255; 00071 blue = (colour >> 16) & 255; 00072 return (red << 16) + (green << 8) + blue; 00073 } 00074 00075 void KWmf::genericArc( 00076 QString type, 00077 QDataStream &operands) 00078 { 00079 QPoint topLeft; 00080 QPoint bottomRight; 00081 QPoint start; 00082 QPoint end; 00083 00084 topLeft = normalisePoint(operands); 00085 bottomRight = normalisePoint(operands); 00086 start = normalisePoint(operands); 00087 end = normalisePoint(operands); 00088 00089 // WMF defines arcs with the major and minor axes of an ellipse, and two points. 00090 // From each point draw a line to the center of the ellipse: the intercepts define 00091 // the ends of the arc. 00092 00093 QRect ellipse(topLeft, bottomRight); 00094 QPoint centre = ellipse.center(); 00095 double startAngle = atan2((double)(centre.y() - start.y()), (double)(centre.x() - start.x())); 00096 double stopAngle = atan2((double)(centre.y() - end.y()), (double)(centre.x() - end.x())); 00097 00098 startAngle = 180 * startAngle / PI; 00099 stopAngle = 180 * stopAngle / PI; 00100 00101 gotEllipse(m_dc, type, centre, ellipse.size() / 2, 00102 static_cast<unsigned int>(startAngle), 00103 static_cast<unsigned int>(stopAngle)); 00104 } 00105 00106 int KWmf::handleIndex(void) const 00107 { 00108 int i; 00109 00110 for (i = 0; i < s_maxHandles; i++) 00111 { 00112 if (!m_objectHandles[i]) 00113 return i; 00114 } 00115 kdError(s_area) << "handle table full !" << endl; 00116 return -1; 00117 } 00118 00119 //----------------------------------------------------------------------------- 00120 KWmf::WinObjPenHandle *KWmf::handleCreatePen(void) 00121 { 00122 WinObjPenHandle *handle = new WinObjPenHandle; 00123 int idx = handleIndex(); 00124 00125 if (idx >= 0) 00126 m_objectHandles[idx] = handle; 00127 return handle; 00128 } 00129 00130 //----------------------------------------------------------------------------- 00131 KWmf::WinObjBrushHandle *KWmf::handleCreateBrush(void) 00132 { 00133 WinObjBrushHandle *handle = new WinObjBrushHandle; 00134 int idx = handleIndex(); 00135 00136 if (idx >= 0) 00137 m_objectHandles[idx] = handle; 00138 return handle; 00139 } 00140 00141 //----------------------------------------------------------------------------- 00142 void KWmf::handleDelete(int idx) 00143 { 00144 if (idx >= 0 && idx < s_maxHandles && m_objectHandles[idx]) 00145 { 00146 delete m_objectHandles[idx]; 00147 m_objectHandles[idx] = NULL; 00148 } 00149 } 00150 00151 // 00152 // 00153 // 00154 00155 void KWmf::invokeHandler( 00156 S16 opcode, 00157 U32 words, 00158 QDataStream &operands) 00159 { 00160 typedef void (KWmf::*method)(U32 words, QDataStream &operands); 00161 00162 typedef struct 00163 { 00164 const char *name; 00165 unsigned short opcode; 00166 method handler; 00167 } opcodeEntry; 00168 00169 static const opcodeEntry funcTab[] = 00170 { 00171 { "ANIMATEPALETTE", 0x0436, 0 }, 00172 { "ARC", 0x0817, &KWmf::opArc }, 00173 { "BITBLT", 0x0922, 0 }, 00174 { "CHORD", 0x0830, 0 }, 00175 { "CREATEBRUSHINDIRECT", 0x02FC, &KWmf::opBrushCreateIndirect }, 00176 { "CREATEFONTINDIRECT", 0x02FB, 0 }, 00177 { "CREATEPALETTE", 0x00F7, 0 }, 00178 { "CREATEPATTERNBRUSH", 0x01F9, 0 }, 00179 { "CREATEPENINDIRECT", 0x02FA, &KWmf::opPenCreateIndirect }, 00180 { "CREATEREGION", 0x06FF, 0 }, 00181 { "DELETEOBJECT", 0x01F0, &KWmf::opObjectDelete }, 00182 { "DIBBITBLT", 0x0940, 0 }, 00183 { "DIBCREATEPATTERNBRUSH",0x0142, 0 }, 00184 { "DIBSTRETCHBLT", 0x0b41, 0 }, 00185 { "ELLIPSE", 0x0418, &KWmf::opEllipse }, 00186 { "ESCAPE", 0x0626, &KWmf::opNoop }, 00187 { "EXCLUDECLIPRECT", 0x0415, 0 }, 00188 { "EXTFLOODFILL", 0x0548, 0 }, 00189 { "EXTTEXTOUT", 0x0a32, 0 }, 00190 { "FILLREGION", 0x0228, 0 }, 00191 { "FLOODFILL", 0x0419, 0 }, 00192 { "FRAMEREGION", 0x0429, 0 }, 00193 { "INTERSECTCLIPRECT", 0x0416, 0 }, 00194 { "INVERTREGION", 0x012A, 0 }, 00195 { "LINETO", 0x0213, &KWmf::opLineTo }, 00196 { "MOVETO", 0x0214, &KWmf::opMoveTo }, 00197 { "OFFSETCLIPRGN", 0x0220, 0 }, 00198 { "OFFSETVIEWPORTORG", 0x0211, 0 }, 00199 { "OFFSETWINDOWORG", 0x020F, 0 }, 00200 { "PAINTREGION", 0x012B, 0 }, 00201 { "PATBLT", 0x061D, 0 }, 00202 { "PIE", 0x081A, &KWmf::opPie }, 00203 { "POLYGON", 0x0324, &KWmf::opPolygon }, 00204 { "POLYLINE", 0x0325, &KWmf::opPolyline }, 00205 { "POLYPOLYGON", 0x0538, 0 }, 00206 { "REALIZEPALETTE", 0x0035, 0 }, 00207 { "RECTANGLE", 0x041B, &KWmf::opRectangle }, 00208 { "RESIZEPALETTE", 0x0139, 0 }, 00209 { "RESTOREDC", 0x0127, &KWmf::opRestoreDc }, 00210 { "ROUNDRECT", 0x061C, 0 }, 00211 { "SAVEDC", 0x001E, &KWmf::opSaveDc }, 00212 { "SCALEVIEWPORTEXT", 0x0412, 0 }, 00213 { "SCALEWINDOWEXT", 0x0410, 0 }, 00214 { "SELECTCLIPREGION", 0x012C, 0 }, 00215 { "SELECTOBJECT", 0x012D, &KWmf::opObjectSelect }, 00216 { "SELECTPALETTE", 0x0234, 0 }, 00217 { "SETBKCOLOR", 0x0201, 0 }, 00218 { "SETBKMODE", 0x0102, 0 }, 00219 { "SETDIBTODEV", 0x0d33, 0 }, 00220 { "SETMAPMODE", 0x0103, 0 }, 00221 { "SETMAPPERFLAGS", 0x0231, 0 }, 00222 { "SETPALENTRIES", 0x0037, 0 }, 00223 { "SETPIXEL", 0x041F, 0 }, 00224 { "SETPOLYFILLMODE", 0x0106, &KWmf::opPolygonSetFillMode }, 00225 { "SETRELABS", 0x0105, 0 }, 00226 { "SETROP2", 0x0104, 0 }, 00227 { "SETSTRETCHBLTMODE", 0x0107, 0 }, 00228 { "SETTEXTALIGN", 0x012E, 0 }, 00229 { "SETTEXTCHAREXTRA", 0x0108, 0 }, 00230 { "SETTEXTCOLOR", 0x0209, 0 }, 00231 { "SETTEXTJUSTIFICATION", 0x020A, 0 }, 00232 { "SETVIEWPORTEXT", 0x020E, 0 }, 00233 { "SETVIEWPORTORG", 0x020D, 0 }, 00234 { "SETWINDOWEXT", 0x020C, &KWmf::opWindowSetExt }, 00235 { "SETWINDOWORG", 0x020B, &KWmf::opWindowSetOrg }, 00236 { "STRETCHBLT", 0x0B23, 0 }, 00237 { "STRETCHDIB", 0x0f43, 0 }, 00238 { "TEXTOUT", 0x0521, 0 }, 00239 { NULL, 0, 0 } 00240 }; 00241 unsigned i; 00242 method result; 00243 00244 // Scan lookup table for operation. 00245 00246 for (i = 0; funcTab[i].name; i++) 00247 { 00248 if (funcTab[i].opcode == opcode) 00249 { 00250 break; 00251 } 00252 } 00253 00254 // Invoke handler. 00255 00256 result = funcTab[i].handler; 00257 if (!result) 00258 { 00259 if (funcTab[i].name) 00260 kdError(s_area) << "invokeHandler: unsupported opcode: " << 00261 funcTab[i].name << 00262 " operands: " << words << endl; 00263 else 00264 kdError(s_area) << "invokeHandler: unsupported opcode: 0x" << 00265 QString::number(opcode, 16) << 00266 " operands: " << words << endl; 00267 00268 // Skip data we cannot use. 00269 00270 for (i = 0; i < words; i++) 00271 { 00272 S16 discard; 00273 00274 operands >> discard; 00275 } 00276 } 00277 else 00278 { 00279 kdDebug(s_area) << "invokeHandler: opcode: " << funcTab[i].name << 00280 " operands: " << words << endl; 00281 00282 // We don't invoke the handler directly on the incoming operands, but 00283 // via a temporary datastream. This adds overhead, but eliminates the 00284 // need for the individual handlers to read *exactly* the right amount 00285 // of data (thus speeding development, and possibly adding some 00286 // future-proofing). 00287 00288 if (words) 00289 { 00290 QByteArray *record = new QByteArray(words * 2); 00291 QDataStream *body; 00292 00293 operands.readRawBytes(record->data(), words * 2); 00294 body = new QDataStream(*record, IO_ReadOnly); 00295 body->setByteOrder(QDataStream::LittleEndian); 00296 (this->*result)(words, *body); 00297 delete body; 00298 delete record; 00299 } 00300 else 00301 { 00302 QDataStream *body = new QDataStream(); 00303 00304 (this->*result)(words, *body); 00305 delete body; 00306 } 00307 } 00308 } 00309 00310 QPoint KWmf::normalisePoint( 00311 QDataStream &operands) 00312 { 00313 S16 x; 00314 S16 y; 00315 00316 operands >> x >> y; 00317 return QPoint((x - m_windowOrgX) * m_windowFlipX / m_dpi, (y - m_windowOrgY) * m_windowFlipY / m_dpi); 00318 } 00319 00320 QSize KWmf::normaliseSize( 00321 QDataStream &operands) 00322 { 00323 S16 width; 00324 S16 height; 00325 00326 operands >> width >> height; 00327 return QSize(width / m_dpi, height / m_dpi); 00328 } 00329 00330 bool KWmf::parse( 00331 const QString &file) 00332 { 00333 QFile in(file); 00334 if (!in.open(IO_ReadOnly)) 00335 { 00336 kdError(s_area) << "Unable to open input file!" << endl; 00337 in.close(); 00338 return false; 00339 } 00340 QDataStream stream(&in); 00341 bool result = parse(stream, in.size()); 00342 in.close(); 00343 return result; 00344 } 00345 00346 bool KWmf::parse( 00347 QDataStream &stream, 00348 unsigned size) 00349 { 00350 int startedAt; 00351 bool isPlaceable; 00352 bool isEnhanced; 00353 00354 startedAt = stream.device()->at(); 00355 stream.setByteOrder(QDataStream::LittleEndian); // Great, I love Qt ! 00356 00357 for (int i = 0; i < s_maxHandles; i++) 00358 m_objectHandles[i] = NULL; 00359 00360 typedef struct _RECT 00361 { 00362 S16 left; 00363 S16 top; 00364 S16 right; 00365 S16 bottom; 00366 } RECT; 00367 00368 typedef struct _RECTL 00369 { 00370 S32 left; 00371 S32 top; 00372 S32 right; 00373 S32 bottom; 00374 } RECTL; 00375 00376 typedef struct _SIZE 00377 { 00378 S16 width; 00379 S16 height; 00380 } SIZE; 00381 00382 typedef struct _SIZEL 00383 { 00384 S32 width; 00385 S32 height; 00386 } SIZEL; 00387 00388 struct WmfEnhMetaHeader 00389 { 00390 S32 iType; // Record type EMR_HEADER 00391 S32 nSize; // Record size in bytes. This may be greater 00392 // than the sizeof(ENHMETAHEADER). 00393 RECTL rclBounds; // Inclusive-inclusive bounds in device units 00394 RECTL rclFrame; // Inclusive-inclusive Picture Frame of metafile 00395 // in .01 mm units 00396 S32 dSignature; // Signature. Must be ENHMETA_SIGNATURE. 00397 S32 nVersion; // Version number 00398 S32 nBytes; // Size of the metafile in bytes 00399 S32 nRecords; // Number of records in the metafile 00400 S16 nHandles; // Number of handles in the handle table 00401 // Handle index zero is reserved. 00402 S16 sReserved; // Reserved. Must be zero. 00403 S32 nDescription; // Number of chars in the unicode description string 00404 // This is 0 if there is no description string 00405 S32 offDescription; // Offset to the metafile description record. 00406 // This is 0 if there is no description string 00407 S32 nPalEntries; // Number of entries in the metafile palette. 00408 SIZEL szlDevice; // Size of the reference device in pels 00409 SIZEL szlMillimeters; // Size of the reference device in millimeters 00410 }; 00411 #define ENHMETA_SIGNATURE 0x464D4520 00412 00413 struct WmfMetaHeader 00414 { 00415 S16 mtType; 00416 S16 mtHeaderSize; 00417 S16 mtVersion; 00418 S32 mtSize; 00419 S16 mtNoObjects; 00420 S32 mtMaxRecord; 00421 S16 mtNoParameters; 00422 }; 00423 00424 struct WmfPlaceableHeader 00425 { 00426 S32 key; 00427 S16 hmf; 00428 RECT bbox; 00429 S16 inch; 00430 S32 reserved; 00431 S16 checksum; 00432 }; 00433 #define APMHEADER_KEY 0x9AC6CDD7L 00434 00435 WmfPlaceableHeader pheader; 00436 WmfEnhMetaHeader eheader; 00437 WmfMetaHeader header; 00438 S16 checksum; 00439 int fileAt; 00440 00441 //----- Read placeable metafile header 00442 00443 stream >> pheader.key; 00444 isPlaceable = (pheader.key == (S32)APMHEADER_KEY); 00445 if (isPlaceable) 00446 { 00447 stream >> pheader.hmf; 00448 stream >> pheader.bbox.left; 00449 stream >> pheader.bbox.top; 00450 stream >> pheader.bbox.right; 00451 stream >> pheader.bbox.bottom; 00452 stream >> pheader.inch; 00453 stream >> pheader.reserved; 00454 stream >> pheader.checksum; 00455 checksum = 0; 00456 S16 *ptr = (S16 *)&pheader; 00457 00458 // XOR in each of the S16s. 00459 00460 for (unsigned i = 0; i < sizeof(WmfPlaceableHeader)/sizeof(S16); i++) 00461 { 00462 checksum ^= ptr[i]; 00463 } 00464 if (pheader.checksum != checksum) 00465 isPlaceable = false; 00466 m_dpi = (unsigned)((double)pheader.inch / m_dpi); 00467 m_windowOrgX = pheader.bbox.left; 00468 m_windowOrgY = pheader.bbox.top; 00469 if (pheader.bbox.right > pheader.bbox.left) 00470 m_windowFlipX = 1; 00471 else 00472 m_windowFlipX = -1; 00473 if (pheader.bbox.bottom > pheader.bbox.top) 00474 m_windowFlipY = 1; 00475 else 00476 m_windowFlipY = -1; 00477 } 00478 else 00479 { 00480 stream.device()->at(startedAt); 00481 m_dpi = (unsigned)((double)576 / m_dpi); 00482 m_windowOrgX = 0; 00483 m_windowOrgY = 0; 00484 m_windowFlipX = 1; 00485 m_windowFlipY = 1; 00486 } 00487 00488 //----- Read as enhanced metafile header 00489 00490 fileAt = stream.device()->at(); 00491 stream >> eheader.iType; 00492 stream >> eheader.nSize; 00493 stream >> eheader.rclBounds.left; 00494 stream >> eheader.rclBounds.top; 00495 stream >> eheader.rclBounds.right; 00496 stream >> eheader.rclBounds.bottom; 00497 stream >> eheader.rclFrame.left; 00498 stream >> eheader.rclFrame.top; 00499 stream >> eheader.rclFrame.right; 00500 stream >> eheader.rclFrame.bottom; 00501 stream >> eheader.dSignature; 00502 isEnhanced = (eheader.dSignature == ENHMETA_SIGNATURE); 00503 if (isEnhanced) // is it really enhanced ? 00504 { 00505 stream >> eheader.nVersion; 00506 stream >> eheader.nBytes; 00507 stream >> eheader.nRecords; 00508 stream >> eheader.nHandles; 00509 stream >> eheader.sReserved; 00510 stream >> eheader.nDescription; 00511 stream >> eheader.offDescription; 00512 stream >> eheader.nPalEntries; 00513 stream >> eheader.szlDevice.width; 00514 stream >> eheader.szlDevice.height; 00515 stream >> eheader.szlMillimeters.width; 00516 stream >> eheader.szlMillimeters.height; 00517 00518 kdError(s_area) << "WMF Extended Header NOT YET IMPLEMENTED, SORRY." << endl; 00519 /* 00520 if (mSingleStep) 00521 { 00522 debug(" iType=%d", eheader.iType); 00523 debug(" nSize=%d", eheader.nSize); 00524 debug(" rclBounds=(%ld;%ld;%ld;%ld)", 00525 eheader.rclBounds.left, eheader.rclBounds.top, 00526 eheader.rclBounds.right, eheader.rclBounds.bottom); 00527 debug(" rclFrame=(%ld;%ld;%ld;%ld)", 00528 eheader.rclFrame.left, eheader.rclFrame.top, 00529 eheader.rclFrame.right, eheader.rclFrame.bottom); 00530 debug(" dSignature=%d", eheader.dSignature); 00531 debug(" nVersion=%d", eheader.nVersion); 00532 debug(" nBytes=%d", eheader.nBytes); 00533 } 00534 debug("NOT YET IMPLEMENTED, SORRY."); 00535 */ 00536 return false; 00537 } 00538 else // no, not enhanced 00539 { 00540 // debug("WMF Header"); 00541 //----- Read as standard metafile header 00542 stream.device()->at(fileAt); 00543 stream >> header.mtType; 00544 stream >> header.mtHeaderSize; 00545 stream >> header.mtVersion; 00546 stream >> header.mtSize; 00547 stream >> header.mtNoObjects; 00548 stream >> header.mtMaxRecord; 00549 stream >> header.mtNoParameters; 00550 /* 00551 if (mSingleStep) 00552 { 00553 debug(" mtType=%u", header.mtType); 00554 debug(" mtHeaderSize=%u", header.mtHeaderSize); 00555 debug(" mtVersion=%u", header.mtVersion); 00556 debug(" mtSize=%ld", header.mtSize); 00557 } 00558 */ 00559 } 00560 00561 walk((size - (stream.device()->at() - startedAt)) / 2, stream); 00562 return true; 00563 } 00564 00565 void KWmf::opArc( 00566 U32 /*words*/, 00567 QDataStream &operands) 00568 { 00569 genericArc("arc", operands); 00570 } 00571 00572 void KWmf::opBrushCreateIndirect( 00573 U32 /*words*/, 00574 QDataStream &operands) 00575 { 00576 static Qt::BrushStyle hatchedStyleTab[] = 00577 { 00578 Qt::HorPattern, 00579 Qt::FDiagPattern, 00580 Qt::BDiagPattern, 00581 Qt::CrossPattern, 00582 Qt::DiagCrossPattern 00583 }; 00584 static Qt::BrushStyle styleTab[] = 00585 { 00586 Qt::SolidPattern, 00587 Qt::NoBrush, 00588 Qt::FDiagPattern, // hatched 00589 Qt::Dense4Pattern, // should be custom bitmap pattern 00590 Qt::HorPattern, // should be BS_INDEXED (?) 00591 Qt::VerPattern, // should be device-independent bitmap 00592 Qt::Dense6Pattern, // should be device-independent packed-bitmap 00593 Qt::Dense2Pattern, // should be BS_PATTERN8x8 00594 Qt::Dense3Pattern // should be device-independent BS_DIBPATTERN8x8 00595 }; 00596 Qt::BrushStyle style; 00597 WinObjBrushHandle *handle = handleCreateBrush(); 00598 S16 arg; 00599 S32 colour; 00600 S16 discard; 00601 00602 operands >> arg >> colour; 00603 handle->m_colour = getColour(colour); 00604 if (arg == 2) 00605 { 00606 operands >> arg; 00607 if (arg >= 0 && arg < 6) 00608 { 00609 style = hatchedStyleTab[arg]; 00610 } 00611 else 00612 { 00613 kdError(s_area) << "createBrushIndirect: invalid hatched brush " << arg << endl; 00614 style = Qt::SolidPattern; 00615 } 00616 } 00617 else 00618 if (arg >= 0 && arg < 9) 00619 { 00620 style = styleTab[arg]; 00621 operands >> discard; 00622 } 00623 else 00624 { 00625 kdError(s_area) << "createBrushIndirect: invalid brush " << arg << endl; 00626 style = Qt::SolidPattern; 00627 operands >> discard; 00628 } 00629 handle->m_style = style; 00630 } 00631 00632 void KWmf::opEllipse( 00633 U32 /*words*/, 00634 QDataStream &operands) 00635 { 00636 QPoint topLeft; 00637 QPoint bottomRight; 00638 00639 topLeft = normalisePoint(operands); 00640 bottomRight = normalisePoint(operands); 00641 00642 QRect ellipse(topLeft, bottomRight); 00643 00644 gotEllipse(m_dc, "full", ellipse.center(), ellipse.size() / 2, 0, 0); 00645 } 00646 00647 void KWmf::opLineTo( 00648 U32 /*words*/, 00649 QDataStream &operands) 00650 { 00651 QPoint lineTo; 00652 00653 lineTo = normalisePoint(operands); 00654 QPointArray points(2); 00655 points.setPoint(0, m_lineFrom); 00656 points.setPoint(1, lineTo); 00657 gotPolyline(m_dc, points); 00658 00659 // Remember this point for next time. 00660 00661 m_lineFrom = lineTo; 00662 } 00663 00664 void KWmf::opMoveTo( 00665 U32 /*words*/, 00666 QDataStream &operands) 00667 { 00668 m_lineFrom = normalisePoint(operands); 00669 } 00670 00671 void KWmf::opNoop( 00672 U32 words, 00673 QDataStream &operands) 00674 { 00675 skip(words, operands); 00676 } 00677 00678 //----------------------------------------------------------------------------- 00679 void KWmf::opObjectDelete( 00680 U32 /*words*/, 00681 QDataStream &operands) 00682 { 00683 S16 idx; 00684 00685 operands >> idx; 00686 handleDelete(idx); 00687 } 00688 00689 //----------------------------------------------------------------------------- 00690 void KWmf::opObjectSelect( 00691 U32 /*words*/, 00692 QDataStream &operands) 00693 { 00694 S16 idx; 00695 00696 operands >> idx; 00697 if (idx >= 0 && idx < s_maxHandles && m_objectHandles[idx]) 00698 m_objectHandles[idx]->apply(*this); 00699 } 00700 00701 // 00702 // 00703 // 00704 00705 void KWmf::opPenCreateIndirect( 00706 U32 /*words*/, 00707 QDataStream &operands) 00708 { 00709 static Qt::PenStyle styleTab[] = 00710 { 00711 Qt::SolidLine, 00712 Qt::DashLine, 00713 Qt::DotLine, 00714 Qt::DashDotLine, 00715 Qt::DashDotDotLine, 00716 Qt::NoPen, 00717 Qt::SolidLine, // PS_INSIDEFRAME 00718 Qt::SolidLine, // PS_USERSTYLE 00719 Qt::SolidLine // PS_ALTERNATE 00720 }; 00721 WinObjPenHandle *handle = handleCreatePen(); 00722 S16 arg; 00723 S32 colour; 00724 00725 operands >> arg; 00726 if (arg >= 0 && arg < 8) 00727 { 00728 handle->m_style = styleTab[arg]; 00729 } 00730 else 00731 { 00732 kdError(s_area) << "createPenIndirect: invalid pen " << arg << endl; 00733 handle->m_style = Qt::SolidLine; 00734 } 00735 operands >> arg; 00736 handle->m_width = arg; 00737 operands >> arg >> colour; 00738 handle->m_colour = getColour(colour); 00739 } 00740 00741 void KWmf::opPie( 00742 U32 /*words*/, 00743 QDataStream &operands) 00744 { 00745 genericArc("pie", operands); 00746 } 00747 00748 void KWmf::opPolygonSetFillMode( 00749 U32 /*words*/, 00750 QDataStream &operands) 00751 { 00752 S16 tmp; 00753 00754 operands >> tmp; 00755 m_dc.m_winding = tmp != 0; 00756 } 00757 00758 void KWmf::opPolygon( 00759 U32 /*words*/, 00760 QDataStream &operands) 00761 { 00762 S16 tmp; 00763 00764 operands >> tmp; 00765 QPointArray points(tmp); 00766 00767 for (int i = 0; i < tmp; i++) 00768 { 00769 points.setPoint(i, normalisePoint(operands)); 00770 } 00771 gotPolygon(m_dc, points); 00772 } 00773 00774 void KWmf::opPolyline( 00775 U32 /*words*/, 00776 QDataStream &operands) 00777 { 00778 S16 tmp; 00779 00780 operands >> tmp; 00781 QPointArray points(tmp); 00782 00783 for (int i = 0; i < tmp; i++) 00784 { 00785 points.setPoint(i, normalisePoint(operands)); 00786 } 00787 gotPolyline(m_dc, points); 00788 } 00789 00790 void KWmf::opRectangle( 00791 U32 /*words*/, 00792 QDataStream &operands) 00793 { 00794 QPoint topLeft; 00795 QSize size; 00796 00797 topLeft = normalisePoint(operands); 00798 size = normaliseSize(operands); 00799 QRect rect(topLeft, size); 00800 QPointArray points(4); 00801 00802 points.setPoint(0, topLeft); 00803 points.setPoint(1, rect.topRight()); 00804 points.setPoint(2, rect.bottomRight()); 00805 points.setPoint(3, rect.bottomLeft()); 00806 gotRectangle(m_dc, points); 00807 } 00808 00809 void KWmf::opRestoreDc( 00810 U32 /*words*/, 00811 QDataStream &operands) 00812 { 00813 S16 pop; 00814 S16 i; 00815 00816 operands >> pop; 00817 for (i = 0; i < pop; i++) 00818 { 00819 m_dc = m_savedDcs.pop(); 00820 } 00821 } 00822 00823 void KWmf::opSaveDc( 00824 U32 /*words*/, 00825 QDataStream &/*operands*/) 00826 { 00827 m_savedDcs.push(m_dc); 00828 00829 // TBD: reinitialise m_dc. 00830 } 00831 00832 void KWmf::opWindowSetOrg( 00833 U32 /*words*/, 00834 QDataStream &operands) 00835 { 00836 S16 top; 00837 S16 left; 00838 00839 operands >> top >> left; 00840 m_windowOrgX = left; 00841 m_windowOrgY = top; 00842 } 00843 00844 void KWmf::opWindowSetExt( 00845 U32 /*words*/, 00846 QDataStream &operands) 00847 { 00848 S16 height; 00849 S16 width; 00850 00851 operands >> height >> width; 00852 if (width > 0) 00853 m_windowFlipX = 1; 00854 else 00855 m_windowFlipX = -1; 00856 if (height > 0) 00857 m_windowFlipY = 1; 00858 else 00859 m_windowFlipY = -1; 00860 } 00861 00862 void KWmf::penSet( 00863 unsigned colour, 00864 unsigned style, 00865 unsigned width) 00866 { 00867 m_dc.m_penColour = colour; 00868 m_dc.m_penStyle = style; 00869 m_dc.m_penWidth = width; 00870 } 00871 00872 void KWmf::skip( 00873 U32 words, 00874 QDataStream &operands) 00875 { 00876 if ((int)words < 0) 00877 { 00878 kdError(s_area) << "skip: " << (int)words << endl; 00879 return; 00880 } 00881 if (words) 00882 { 00883 U32 i; 00884 S16 discard; 00885 00886 kdDebug(s_area) << "skip: " << words << endl; 00887 for (i = 0; i < words; i++) 00888 { 00889 operands >> discard; 00890 } 00891 } 00892 } 00893 00894 void KWmf::walk( 00895 U32 words, 00896 QDataStream &operands) 00897 { 00898 // Read bits: 00899 // 00900 // struct WmfMetaRecord 00901 // { 00902 // S32 rdSize; // Record size (in words) of the function 00903 // S16 rdFunction; // Record function number 00904 // S16 rdParm[1]; // WORD array of parameters 00905 // }; 00906 // 00907 // struct WmfEnhMetaRecord 00908 // { 00909 // S32 iType; // Record type EMR_xxx 00910 // S32 nSize; // Record size in bytes 00911 // S32 dParm[1]; // DWORD array of parameters 00912 // }; 00913 00914 S32 wordCount; 00915 S16 opcode; 00916 U32 length = 0; 00917 00918 while (length < words) 00919 { 00920 operands >> wordCount; 00921 operands >> opcode; 00922 00923 // If we get some duff data, protect ourselves. 00924 if (length + wordCount > words) 00925 { 00926 wordCount = words - length; 00927 } 00928 length += wordCount; 00929 if (opcode == 0) 00930 { 00931 // This appears to be an EOF marker. 00932 break; 00933 } 00934 00935 // Package the arguments... 00936 00937 invokeHandler(opcode, wordCount - 3, operands); 00938 } 00939 00940 // Eat unexpected data that the caller may expect us to consume. 00941 skip(words - length, operands); 00942 } 00943 00944 KWmf::DrawContext::DrawContext() 00945 { 00946 // TBD: initalise with proper values. 00947 m_brushColour = 0x808080; 00948 m_brushStyle = 1; 00949 m_penColour = 0x808080; 00950 m_penStyle = 1; 00951 m_penWidth = 1; 00952 } 00953 00954 void KWmf::WinObjBrushHandle::apply( 00955 KWmf &p) 00956 { 00957 p.brushSet(m_colour, m_style); 00958 } 00959 00960 void KWmf::WinObjPenHandle::apply( 00961 KWmf &p) 00962 { 00963 p.penSet(m_colour, m_style, m_width); 00964 }
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Nov 17 06:54:20 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003