F:/KPlato/koffice/libs/kwmf/kwmf.cc

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

Généré le Wed Nov 22 23:41:13 2006 pour KPlato par  doxygen 1.5.1-p1