00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00090
00091
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
00245
00246 for (i = 0; funcTab[i].name; i++)
00247 {
00248 if (funcTab[i].opcode == opcode)
00249 {
00250 break;
00251 }
00252 }
00253
00254
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
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
00283
00284
00285
00286
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);
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;
00391 S32 nSize;
00392
00393 RECTL rclBounds;
00394 RECTL rclFrame;
00395
00396 S32 dSignature;
00397 S32 nVersion;
00398 S32 nBytes;
00399 S32 nRecords;
00400 S16 nHandles;
00401
00402 S16 sReserved;
00403 S32 nDescription;
00404
00405 S32 offDescription;
00406
00407 S32 nPalEntries;
00408 SIZEL szlDevice;
00409 SIZEL szlMillimeters;
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
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
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
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)
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
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 return false;
00537 }
00538 else
00539 {
00540
00541
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
00552
00553
00554
00555
00556
00557
00558
00559 }
00560
00561 walk((size - (stream.device()->at() - startedAt)) / 2, stream);
00562 return true;
00563 }
00564
00565 void KWmf::opArc(
00566 U32 ,
00567 QDataStream &operands)
00568 {
00569 genericArc("arc", operands);
00570 }
00571
00572 void KWmf::opBrushCreateIndirect(
00573 U32 ,
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,
00589 Qt::Dense4Pattern,
00590 Qt::HorPattern,
00591 Qt::VerPattern,
00592 Qt::Dense6Pattern,
00593 Qt::Dense2Pattern,
00594 Qt::Dense3Pattern
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 ,
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 ,
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
00660
00661 m_lineFrom = lineTo;
00662 }
00663
00664 void KWmf::opMoveTo(
00665 U32 ,
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 ,
00681 QDataStream &operands)
00682 {
00683 S16 idx;
00684
00685 operands >> idx;
00686 handleDelete(idx);
00687 }
00688
00689
00690 void KWmf::opObjectSelect(
00691 U32 ,
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 ,
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,
00718 Qt::SolidLine,
00719 Qt::SolidLine
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 ,
00743 QDataStream &operands)
00744 {
00745 genericArc("pie", operands);
00746 }
00747
00748 void KWmf::opPolygonSetFillMode(
00749 U32 ,
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 ,
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 ,
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 ,
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 ,
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 ,
00825 QDataStream &)
00826 {
00827 m_savedDcs.push(m_dc);
00828
00829
00830 }
00831
00832 void KWmf::opWindowSetOrg(
00833 U32 ,
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 ,
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
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
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
00924 if (length + wordCount > words)
00925 {
00926 wordCount = words - length;
00927 }
00928 length += wordCount;
00929 if (opcode == 0)
00930 {
00931
00932 break;
00933 }
00934
00935
00936
00937 invokeHandler(opcode, wordCount - 3, operands);
00938 }
00939
00940
00941 skip(words - length, operands);
00942 }
00943
00944 KWmf::DrawContext::DrawContext()
00945 {
00946
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 }