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 Sun Mar 20 14:25:28 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003