00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <kdebug.h>
00024 #include <qdatastream.h>
00025 #include <qfile.h>
00026 #include <qptrlist.h>
00027 #include <qpointarray.h>
00028 #include <qrect.h>
00029 #include <qsize.h>
00030 #include <msod.h>
00031 #include <zlib.h>
00032
00033 const int Msod::s_area = 30505;
00034
00035 Msod::Msod(
00036 unsigned dpi) :
00037 KWmf(dpi)
00038 {
00039 m_dpi = dpi;
00040 m_images.setAutoDelete(true);
00041 m_opt = new Options(*this);
00042 m_shape.data = 0L;
00043 m_shape.length = 0;
00044 }
00045
00046 Msod::~Msod()
00047 {
00048 delete [] m_shape.data;
00049 delete m_opt;
00050 }
00051
00052 void Msod::drawShape(
00053 unsigned shapeType,
00054 Q_UINT32 bytes,
00055 QDataStream &operands)
00056 {
00057 static const char *funcTab[] =
00058 {
00059 "UNKNOWN",
00060 "RECTANGLE",
00061 "ROUNDRECTANGLE",
00062 "ELLIPSE",
00063 "DIAMOND",
00064 "ISOCELESTRIANGLE",
00065 "RIGHTTRIANGLE",
00066 "PARALLELOGRAM",
00067 "TRAPEZOID",
00068 "HEXAGON",
00069 "OCTAGON",
00070 "PLUS",
00071 "STAR",
00072 "ARROW",
00073 "THICKARROW",
00074 "HOMEPLATE",
00075 "CUBE",
00076 "BALLOON",
00077 "SEAL",
00078 "ARC",
00079 "LINE",
00080 "PLAQUE",
00081 "CAN",
00082 "DONUT",
00083 "TEXTSIMPLE",
00084 "TEXTOCTAGON",
00085 "TEXTHEXAGON",
00086 "TEXTCURVE",
00087 "TEXTWAVE",
00088 "TEXTRING",
00089 "TEXTONCURVE",
00090 "TEXTONRING",
00091 "STRAIGHTCONNECTOR1",
00092 "BENTCONNECTOR2",
00093 "BENTCONNECTOR3",
00094 "BENTCONNECTOR4",
00095 "BENTCONNECTOR5",
00096 "CURVEDCONNECTOR2",
00097 "CURVEDCONNECTOR3",
00098 "CURVEDCONNECTOR4",
00099 "CURVEDCONNECTOR5",
00100 "CALLOUT1",
00101 "CALLOUT2",
00102 "CALLOUT3",
00103 "ACCENTCALLOUT1",
00104 "ACCENTCALLOUT2",
00105 "ACCENTCALLOUT3",
00106 "BORDERCALLOUT1",
00107 "BORDERCALLOUT2",
00108 "BORDERCALLOUT3",
00109 "ACCENTBORDERCALLOUT1",
00110 "ACCENTBORDERCALLOUT2",
00111 "ACCENTBORDERCALLOUT3",
00112 "RIBBON",
00113 "RIBBON2",
00114 "CHEVRON",
00115 "PENTAGON",
00116 "NOSMOKING",
00117 "SEAL8",
00118 "SEAL16",
00119 "SEAL32",
00120 "WEDGERECTCALLOUT",
00121 "WEDGERRECTCALLOUT",
00122 "WEDGEELLIPSECALLOUT",
00123 "WAVE",
00124 "FOLDEDCORNER",
00125 "LEFTARROW",
00126 "DOWNARROW",
00127 "UPARROW",
00128 "LEFTRIGHTARROW",
00129 "UPDOWNARROW",
00130 "IRREGULARSEAL1",
00131 "IRREGULARSEAL2",
00132 "LIGHTNINGBOLT",
00133 "HEART",
00134 "PICTUREFRAME",
00135 "QUADARROW",
00136 "LEFTARROWCALLOUT",
00137 "RIGHTARROWCALLOUT",
00138 "UPARROWCALLOUT",
00139 "DOWNARROWCALLOUT",
00140 "LEFTRIGHTARROWCALLOUT",
00141 "UPDOWNARROWCALLOUT",
00142 "QUADARROWCALLOUT",
00143 "BEVEL",
00144 "LEFTBRACKET",
00145 "RIGHTBRACKET",
00146 "LEFTBRACE",
00147 "RIGHTBRACE",
00148 "LEFTUPARROW",
00149 "BENTUPARROW",
00150 "BENTARROW",
00151 "SEAL24",
00152 "STRIPEDRIGHTARROW",
00153 "NOTCHEDRIGHTARROW",
00154 "BLOCKARC",
00155 "SMILEYFACE",
00156 "VERTICALSCROLL",
00157 "HORIZONTALSCROLL",
00158 "CIRCULARARROW",
00159 "NOTCHEDCIRCULARARROW",
00160 "UTURNARROW",
00161 "CURVEDRIGHTARROW",
00162 "CURVEDLEFTARROW",
00163 "CURVEDUPARROW",
00164 "CURVEDDOWNARROW",
00165 "CLOUDCALLOUT",
00166 "ELLIPSERIBBON",
00167 "ELLIPSERIBBON2",
00168 "FLOWCHARTPROCESS",
00169 "FLOWCHARTDECISION",
00170 "FLOWCHARTINPUTOUTPUT",
00171 "FLOWCHARTPREDEFINEDPROCESS",
00172 "FLOWCHARTINTERNALSTORAGE",
00173 "FLOWCHARTDOCUMENT",
00174 "FLOWCHARTMULTIDOCUMENT",
00175 "FLOWCHARTTERMINATOR",
00176 "FLOWCHARTPREPARATION",
00177 "FLOWCHARTMANUALINPUT",
00178 "FLOWCHARTMANUALOPERATION",
00179 "FLOWCHARTCONNECTOR",
00180 "FLOWCHARTPUNCHEDCARD",
00181 "FLOWCHARTPUNCHEDTAPE",
00182 "FLOWCHARTSUMMINGJUNCTION",
00183 "FLOWCHARTOR",
00184 "FLOWCHARTCOLLATE",
00185 "FLOWCHARTSORT",
00186 "FLOWCHARTEXTRACT",
00187 "FLOWCHARTMERGE",
00188 "FLOWCHARTOFFLINESTORAGE",
00189 "FLOWCHARTONLINESTORAGE",
00190 "FLOWCHARTMAGNETICTAPE",
00191 "FLOWCHARTMAGNETICDISK",
00192 "FLOWCHARTMAGNETICDRUM",
00193 "FLOWCHARTDISPLAY",
00194 "FLOWCHARTDELAY",
00195 "TEXTPLAINTEXT",
00196 "TEXTSTOP",
00197 "TEXTTRIANGLE",
00198 "TEXTTRIANGLEINVERTED",
00199 "TEXTCHEVRON",
00200 "TEXTCHEVRONINVERTED",
00201 "TEXTRINGINSIDE",
00202 "TEXTRINGOUTSIDE",
00203 "TEXTARCHUPCURVE",
00204 "TEXTARCHDOWNCURVE",
00205 "TEXTCIRCLECURVE",
00206 "TEXTBUTTONCURVE",
00207 "TEXTARCHUPPOUR",
00208 "TEXTARCHDOWNPOUR",
00209 "TEXTCIRCLEPOUR",
00210 "TEXTBUTTONPOUR",
00211 "TEXTCURVEUP",
00212 "TEXTCURVEDOWN",
00213 "TEXTCASCADEUP",
00214 "TEXTCASCADEDOWN",
00215 "TEXTWAVE1",
00216 "TEXTWAVE2",
00217 "TEXTWAVE3",
00218 "TEXTWAVE4",
00219 "TEXTINFLATE",
00220 "TEXTDEFLATE",
00221 "TEXTINFLATEBOTTOM",
00222 "TEXTDEFLATEBOTTOM",
00223 "TEXTINFLATETOP",
00224 "TEXTDEFLATETOP",
00225 "TEXTDEFLATEINFLATE",
00226 "TEXTDEFLATEINFLATEDEFLATE",
00227 "TEXTFADERIGHT",
00228 "TEXTFADELEFT",
00229 "TEXTFADEUP",
00230 "TEXTFADEDOWN",
00231 "TEXTSLANTUP",
00232 "TEXTSLANTDOWN",
00233 "TEXTCANUP",
00234 "TEXTCANDOWN",
00235 "FLOWCHARTALTERNATEPROCESS",
00236 "FLOWCHARTOFFPAGECONNECTOR",
00237 "CALLOUT90",
00238 "ACCENTCALLOUT90",
00239 "BORDERCALLOUT90",
00240 "ACCENTBORDERCALLOUT90",
00241 "LEFTRIGHTUPARROW",
00242 "SUN",
00243 "MOON",
00244 "BRACKETPAIR",
00245 "BRACEPAIR",
00246 "SEAL4",
00247 "DOUBLEWAVE",
00248 "ACTIONBUTTONBLANK",
00249 "ACTIONBUTTONHOME",
00250 "ACTIONBUTTONHELP",
00251 "ACTIONBUTTONINFORMATION",
00252 "ACTIONBUTTONFORWARDNEXT",
00253 "ACTIONBUTTONBACKPREVIOUS",
00254 "ACTIONBUTTONEND",
00255 "ACTIONBUTTONBEGINNING",
00256 "ACTIONBUTTONRETURN",
00257 "ACTIONBUTTONDOCUMENT",
00258 "ACTIONBUTTONSOUND",
00259 "ACTIONBUTTONMOVIE",
00260 "HOSTCONTROL",
00261 "TEXTBOX",
00262 };
00263 struct
00264 {
00265 Q_UINT32 spid;
00266 union
00267 {
00268 Q_UINT32 info;
00269 struct
00270 {
00271 Q_UINT32 fGroup : 1;
00272 Q_UINT32 fChild : 1;
00273 Q_UINT32 fPatriarch : 1;
00274
00275 Q_UINT32 fDeleted : 1;
00276 Q_UINT32 fOleShape : 1;
00277 Q_UINT32 fHaveMaster : 1;
00278 Q_UINT32 fFlipH : 1;
00279 Q_UINT32 fFlipV : 1;
00280 Q_UINT32 fConnector : 1;
00281 Q_UINT32 fHaveAnchor : 1;
00282 Q_UINT32 fBackground : 1;
00283 Q_UINT32 fHaveSpt : 1;
00284 Q_UINT32 reserved : 20;
00285 } fields;
00286 } grfPersistent;
00287 } data;
00288
00289
00290
00291 operands >> data.spid;
00292 operands >> data.grfPersistent.info;
00293 bytes -= 8;
00294 kdDebug(s_area) << "shape-id: " << data.spid << " type: " << funcTab[shapeType] << " (" << shapeType << ")" <<
00295 (data.grfPersistent.fields.fGroup ? " group" : "") <<
00296 (data.grfPersistent.fields.fChild ? " child" : "") <<
00297 (data.grfPersistent.fields.fPatriarch ? " patriarch" : "") <<
00298 (data.grfPersistent.fields.fDeleted ? " deleted" : "") <<
00299 (data.grfPersistent.fields.fOleShape ? " oleshape" : "") <<
00300 (data.grfPersistent.fields.fHaveMaster ? " master" : "") <<
00301 (data.grfPersistent.fields.fFlipH ? " flipv" : "") <<
00302 (data.grfPersistent.fields.fConnector ? " connector" : "") <<
00303 (data.grfPersistent.fields.fHaveAnchor ? " anchor" : "") <<
00304 (data.grfPersistent.fields.fBackground ? " background" : "") <<
00305 (data.grfPersistent.fields.fHaveSpt ? " spt" : "") <<
00306 " operands: " << bytes << endl;
00307 if (data.grfPersistent.fields.fDeleted)
00308 return;
00309 if ((!m_isRequiredDrawing) && (m_requestedShapeId != data.spid))
00310 return;
00311
00312
00313
00314 switch (shapeType)
00315 {
00316 case 0:
00317 if (m_opt->m_pVertices)
00318 {
00319 gotPolyline(m_dc, *m_opt->m_pVertices);
00320 }
00321 break;
00322 case 1:
00323 if (bytes > 7)
00324 {
00325 QPoint topLeft;
00326 QSize size;
00327
00328 topLeft = normalisePoint(operands);
00329 size = normaliseSize(operands);
00330
00331 QRect rect(topLeft, size);
00332 QPointArray points(4);
00333
00334 points.setPoint(0, topLeft);
00335 points.setPoint(1, rect.topRight());
00336 points.setPoint(2, rect.bottomRight());
00337 points.setPoint(3, rect.bottomLeft());
00338 gotRectangle(m_dc, points);
00339 }
00340 case 20:
00341 if (bytes > 7)
00342 {
00343 QPoint lineFrom;
00344 QPoint lineTo;
00345
00346 lineTo = normalisePoint(operands);
00347
00348 QPointArray points(2);
00349
00350 points.setPoint(0, lineFrom);
00351 points.setPoint(1, lineTo);
00352 gotPolyline(m_dc, points);
00353 }
00354 break;
00355 default:
00356 break;
00357 }
00358 }
00359
00360 void Msod::invokeHandler(
00361 Header &op,
00362 Q_UINT32 bytes,
00363 QDataStream &operands)
00364 {
00365 typedef void (Msod::*method)(Header &op, Q_UINT32 bytes, QDataStream &operands);
00366
00367 typedef struct
00368 {
00369 const char *name;
00370 Q_UINT16 opcode;
00371 method handler;
00372 } opcodeEntry;
00373
00374 static const opcodeEntry funcTab[] =
00375 {
00376 { "ALIGNRULE", 0xF013, &Msod::opAlignrule },
00377 { "ANCHOR", 0xF00E, &Msod::opAnchor },
00378 { "ARCRULE", 0xF014, &Msod::opArcrule },
00379 { "BSE", 0xF007, &Msod::opBse },
00380 { "BSTORECONTAINER", 0xF001, &Msod::opBstorecontainer },
00381 { "CALLOUTRULE", 0xF017, &Msod::opCalloutrule },
00382 { "CHILDANCHOR", 0xF00F, &Msod::opChildanchor },
00383 { "CLIENTANCHOR", 0xF010, &Msod::opClientanchor },
00384 { "CLIENTDATA", 0xF011, &Msod::opClientdata },
00385 { "CLIENTRULE", 0xF015, &Msod::opClientrule },
00386 { "CLIENTTEXTBOX", 0xF00D, &Msod::opClienttextbox },
00387 { "CLSID", 0xF016, &Msod::opClsid },
00388 { "COLORMRU", 0xF11A, &Msod::opColormru },
00389 { "CONNECTORRULE", 0xF012, &Msod::opConnectorrule },
00390 { "DELETEDPSPL", 0xF11D, &Msod::opDeletedpspl },
00391 { "DG", 0xF008, &Msod::opDg },
00392 { "DGCONTAINER", 0xF002, &Msod::opDgcontainer },
00393 { "DGG", 0xF006, &Msod::opDgg },
00394 { "DGGCONTAINER", 0xF000, &Msod::opDggcontainer },
00395 { "OLEOBJECT", 0xF11F, &Msod::opOleobject },
00396 { "OPT", 0xF00B, &Msod::opOpt },
00397 { "REGROUPITEMS", 0xF118, &Msod::opRegroupitems },
00398 { "SELECTION", 0xF119, &Msod::opSelection },
00399 { "SOLVERCONTAINER", 0xF005, &Msod::opSolvercontainer },
00400 { "SP", 0xF00A, &Msod::opSp },
00401 { "SPCONTAINER", 0xF004, &Msod::opSpcontainer },
00402 { "SPGR", 0xF009, &Msod::opSpgr },
00403 { "SPGRCONTAINER", 0xF003, &Msod::opSpgrcontainer },
00404 { "SPLITMENUCOLORS", 0xF11E, &Msod::opSplitmenucolors },
00405 { "TEXTBOX", 0xF00C, &Msod::opTextbox },
00406 { NULL, 0, 0 },
00407 { "BLIP", 0, &Msod::opBlip }
00408 };
00409 unsigned i;
00410 method result;
00411
00412
00413
00414 for (i = 0; funcTab[i].name; i++)
00415 {
00416 if (funcTab[i].opcode == op.opcode.fields.fbt)
00417 {
00418 break;
00419 }
00420 }
00421
00422
00423
00424 result = funcTab[i].handler;
00425 if (!result && (op.opcode.fields.fbt >= 0xF018) && (0xF117 >= op.opcode.fields.fbt))
00426 result = funcTab[++i].handler;
00427 if (!result)
00428 {
00429 if (funcTab[i].name)
00430 kdWarning(s_area) << "invokeHandler: unsupported opcode: " <<
00431 funcTab[i].name <<
00432 " operands: " << bytes << endl;
00433 else
00434 kdWarning(s_area) << "invokeHandler: unsupported opcode: 0x" <<
00435 QString::number(op.opcode.fields.fbt, 16) <<
00436 " operands: " << bytes << endl;
00437
00438
00439
00440 skip(bytes, operands);
00441 }
00442 else
00443 {
00444 kdDebug(s_area) << "invokeHandler: opcode: " << funcTab[i].name <<
00445 " operands: " << bytes << endl;
00446
00447
00448
00449
00450
00451
00452
00453 if (bytes)
00454 {
00455 QByteArray *record = new QByteArray(bytes);
00456 QDataStream *body;
00457
00458 operands.readRawBytes(record->data(), bytes);
00459 body = new QDataStream(*record, IO_ReadOnly);
00460 body->setByteOrder(QDataStream::LittleEndian);
00461 (this->*result)(op, bytes, *body);
00462 delete body;
00463 delete record;
00464 }
00465 else
00466 {
00467 QDataStream *body = new QDataStream();
00468
00469 (this->*result)(op, bytes, *body);
00470 delete body;
00471 }
00472 }
00473 }
00474
00475 QPoint Msod::normalisePoint(
00476 QDataStream &operands)
00477 {
00478 Q_UINT16 x;
00479 Q_UINT16 y;
00480
00481 operands >> x >> y;
00482 return QPoint(x / m_dpi, y / m_dpi);
00483 }
00484
00485 QSize Msod::normaliseSize(
00486 QDataStream &operands)
00487 {
00488 Q_UINT16 width;
00489 Q_UINT16 height;
00490
00491 operands >> width >> height;
00492 return QSize(width / m_dpi, height / m_dpi);
00493 }
00494
00495 bool Msod::parse(
00496 unsigned shapeId,
00497 const QString &file,
00498 const char *delayStream)
00499 {
00500 QFile in(file);
00501 if (!in.open(IO_ReadOnly))
00502 {
00503 kdError(s_area) << "Unable to open input file!" << endl;
00504 in.close();
00505 return false;
00506 }
00507 QDataStream stream(&in);
00508 bool result = parse(shapeId, stream, in.size(), delayStream);
00509 in.close();
00510 return result;
00511 }
00512
00513 bool Msod::parse(
00514 unsigned shapeId,
00515 QDataStream &stream,
00516 unsigned size,
00517 const char *delayStream)
00518 {
00519 stream.setByteOrder(QDataStream::LittleEndian);
00520 m_requestedShapeId = shapeId;
00521 m_isRequiredDrawing = false;
00522 m_delayStream = delayStream;
00523
00524
00525
00526 walk(size, stream);
00527 return true;
00528 }
00529
00530 void Msod::opAlignrule(
00531 Header &,
00532 Q_UINT32,
00533 QDataStream &)
00534 {
00535 }
00536
00537 void Msod::opAnchor(
00538 Header &,
00539 Q_UINT32,
00540 QDataStream &)
00541 {
00542 }
00543
00544 void Msod::opArcrule(
00545 Header &,
00546 Q_UINT32,
00547 QDataStream &)
00548 {
00549 }
00550
00551 void Msod::opBlip(Header &, Q_UINT32 bytes, QDataStream &operands)
00552 {
00553 typedef enum
00554 {
00555 msobiWMF = 0x216,
00556 msobiEMF = 0x3D4,
00557 msobiPICT = 0x542,
00558 msobiPNG = 0x6E0,
00559 msobiJPEG = 0x46A,
00560 msobiDIB = 0x7A8,
00561 msobiClient = 0x800
00562 } MSOBI;
00563 typedef enum
00564 {
00565 msocompressionDeflate,
00566 msocompressionNone = 254,
00567 msocompressionTest
00568 } MSOBLIPCOMPRESSION;
00569
00570 bool hasPrimaryId;
00571 Q_UINT32 length = 0;
00572 struct
00573 {
00574 Q_UINT32 cb;
00575 struct
00576 {
00577 Q_UINT32 x;
00578 Q_UINT32 y;
00579 Q_UINT32 w;
00580 Q_UINT32 h;
00581 } bounds;
00582 struct
00583 {
00584 Q_UINT32 w;
00585 Q_UINT32 h;
00586 } ptSize;
00587 Q_UINT32 cbSave;
00588 Q_UINT8 compression;
00589 Q_UINT8 filter;
00590 } data;
00591
00592
00593
00594 switch (m_blipType)
00595 {
00596 case msoblipEMF:
00597 hasPrimaryId = (m_blipType ^ msobiEMF) != 0;
00598 break;
00599 case msoblipWMF:
00600 hasPrimaryId = (m_blipType ^ msobiWMF) != 0;
00601 break;
00602 case msoblipPICT:
00603 hasPrimaryId = (m_blipType ^ msobiPICT) != 0;
00604 break;
00605 case msoblipJPEG:
00606 hasPrimaryId = (m_blipType ^ msobiJPEG) != 0;
00607 break;
00608 case msoblipPNG:
00609 hasPrimaryId = (m_blipType ^ msobiPNG) != 0;
00610 break;
00611 case msoblipDIB:
00612 hasPrimaryId = (m_blipType ^ msobiDIB) != 0;
00613 break;
00614 default:
00615 hasPrimaryId = (m_blipType ^ msobiClient) != 0;
00616 break;
00617 }
00618 if (hasPrimaryId)
00619 {
00620 length += 16;
00621 skip(16, operands);
00622 }
00623
00624
00625
00626 data.compression = msocompressionNone;
00627 switch (m_blipType)
00628 {
00629 case msoblipEMF:
00630 case msoblipWMF:
00631 case msoblipPICT:
00632 length += 34;
00633 operands >> data.cb;
00634 operands >> data.bounds.x >> data.bounds.y >> data.bounds.w >> data.bounds.h;
00635 operands >> data.ptSize.w >> data.ptSize.h;
00636 operands >> data.cbSave;
00637 operands >> data.compression >> data.filter;
00638 break;
00639 case msoblipJPEG:
00640 case msoblipPNG:
00641 case msoblipDIB:
00642
00643 length += 1;
00644 skip(1, operands);
00645 break;
00646 default:
00647 break;
00648 }
00649
00650
00651
00652 Image *image = new Image();
00653 switch (m_blipType)
00654 {
00655 case msoblipEMF:
00656 image->extension = "emf";
00657 break;
00658 case msoblipWMF:
00659 image->extension = "wmf";
00660 break;
00661 case msoblipPICT:
00662 image->extension = "pic";
00663 break;
00664 case msoblipJPEG:
00665 image->extension = "jpg";
00666 break;
00667 case msoblipPNG:
00668 image->extension = "png";
00669 break;
00670 case msoblipDIB:
00671 image->extension = "dib";
00672 break;
00673 default:
00674 image->extension = "img";
00675 break;
00676 }
00677 image->length = bytes - length;
00678 image->data = new char[image->length];
00679 operands.readRawBytes((char *)image->data, image->length);
00680 if (data.compression == msocompressionDeflate)
00681 {
00682 const char *tmp;
00683 uLongf destLen = data.cb;
00684 int result;
00685
00686 tmp = new char[data.cb];
00687 result = uncompress((Q_UINT8 *)tmp, &destLen, (Q_UINT8 *)image->data, image->length);
00688 if (result != Z_OK)
00689 {
00690 kdError(s_area) << "opBlip: uncompress failed: " << result << endl;
00691 }
00692 if (destLen != data.cb)
00693 {
00694 kdError(s_area) << "opBlip: uncompressed " << destLen << " instead of " << data.cb << endl;
00695 }
00696 delete [] image->data;
00697 image->data = tmp;
00698 image->length = destLen;
00699 }
00700 m_images.resize(m_images.size() + 1);
00701 m_images.insert(m_images.size() - 1, image);
00702 }
00703
00704
00705
00706 void Msod::opBse(Header &op, Q_UINT32, QDataStream &operands)
00707 {
00708 struct
00709 {
00710 Q_UINT8 btWin32;
00711 Q_UINT8 btMacOS;
00712 Q_UINT8 rgbUid[16];
00713 Q_UINT16 tag;
00714 Q_UINT32 size;
00715 Q_UINT32 cRef;
00716 Q_UINT32 foDelay;
00717 Q_UINT8 usage;
00718 Q_UINT8 cbName;
00719 Q_UINT8 unused2;
00720 Q_UINT8 unused3;
00721 } data;
00722 unsigned i;
00723
00724
00725
00726 m_blipType = static_cast<MSOBLIPTYPE>(op.opcode.fields.inst);
00727 operands >> data.btWin32;
00728 operands >> data.btMacOS;
00729 for (i = 0; i < 16; i++)
00730 operands >> data.rgbUid[i];
00731 operands >> data.tag >> data.size;
00732 operands >> data.cRef >> data.foDelay;
00733 operands >> data.usage >> data.cbName;
00734 operands >> data.unused2 >> data.unused2;
00735
00736
00737
00738 if (m_delayStream)
00739 {
00740
00741
00742
00743
00744 if (data.size && data.cRef)
00745 {
00746 QByteArray bytes;
00747 bytes.setRawData(m_delayStream + data.foDelay, data.size);
00748 QDataStream stream(bytes, IO_ReadOnly);
00749 stream.setByteOrder(QDataStream::LittleEndian);
00750 walk(data.size, stream);
00751 bytes.resetRawData(m_delayStream + data.foDelay, data.size);
00752 }
00753 else
00754 {
00755 m_images.resize(m_images.size() + 1);
00756 m_images.insert(m_images.size() - 1, 0L);
00757 }
00758 }
00759 }
00760
00761 void Msod::opBstorecontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00762 {
00763 walk(bytes, operands);
00764 }
00765
00766 void Msod::opCalloutrule(
00767 Header &,
00768 Q_UINT32,
00769 QDataStream &)
00770 {
00771 }
00772
00773 void Msod::opChildanchor(
00774 Header &,
00775 Q_UINT32,
00776 QDataStream &)
00777 {
00778 }
00779
00780 void Msod::opClientanchor(Header &, Q_UINT32, QDataStream &operands)
00781 {
00782 struct
00783 {
00784 Q_UINT32 unknown;
00785 } data;
00786
00787 operands >> data.unknown;
00788 kdDebug(s_area) << "client anchor: " << data.unknown << endl;
00789 }
00790
00791 void Msod::opClientdata(Header &, Q_UINT32, QDataStream &operands)
00792 {
00793 struct
00794 {
00795 Q_UINT32 unknown;
00796 } data;
00797
00798 operands >> data.unknown;
00799 kdDebug(s_area) << "client data: " << data.unknown << endl;
00800 }
00801
00802 void Msod::opClientrule(
00803 Header &,
00804 Q_UINT32,
00805 QDataStream &)
00806 {
00807 }
00808
00809 void Msod::opClienttextbox(
00810 Header &,
00811 Q_UINT32,
00812 QDataStream &operands)
00813 {
00814 struct
00815 {
00816 Q_UINT32 unknown;
00817 } data;
00818
00819 operands >> data.unknown;
00820 kdDebug(s_area) << "client textbox: 0x" << QString::number(data.unknown,16) << endl;
00821 }
00822
00823 void Msod::opClsid(
00824 Header &,
00825 Q_UINT32,
00826 QDataStream &)
00827 {
00828 }
00829
00830 void Msod::opColormru(
00831 Header &,
00832 Q_UINT32,
00833 QDataStream &)
00834 {
00835 }
00836
00837 void Msod::opConnectorrule(
00838 Header &,
00839 Q_UINT32,
00840 QDataStream &)
00841 {
00842 }
00843
00844 void Msod::opDeletedpspl(
00845 Header &,
00846 Q_UINT32,
00847 QDataStream &)
00848 {
00849 }
00850
00851
00852
00853 void Msod::opDg(Header &, Q_UINT32, QDataStream &operands)
00854 {
00855 struct
00856 {
00857 Q_UINT32 csp;
00858 Q_UINT32 spidCur;
00859 } data;
00860
00861 operands >> data.csp >> data.spidCur;
00862 kdDebug(s_area) << "drawing id: " << data.spidCur << endl;
00863 m_isRequiredDrawing = (m_requestedShapeId == data.spidCur);
00864 if (m_isRequiredDrawing)
00865 {
00866 kdDebug(s_area) << "found requested drawing" << endl;
00867 }
00868 }
00869
00870 void Msod::opDgcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00871 {
00872 walk(bytes, operands);
00873 }
00874
00875
00876
00877 void Msod::opDgg(Header &, Q_UINT32, QDataStream &operands)
00878 {
00879 struct
00880 {
00881 Q_UINT32 spidMax;
00882 Q_UINT32 cidcl;
00883 Q_UINT32 cspSaved;
00884
00885
00886 Q_UINT32 cdgSaved;
00887 } data;
00888
00889
00890
00891 struct
00892 {
00893 Q_UINT32 dgid;
00894 Q_UINT32 cspidCur;
00895 } data1;
00896 unsigned i;
00897
00898 operands >> data.spidMax >> data.cidcl >> data.cspSaved >> data.cdgSaved;
00899 kdDebug(s_area) << data.cspSaved << " shapes in " <<
00900 data.cidcl - 1 << " clusters in " <<
00901 data.cdgSaved << " drawings" << endl;
00902 for (i = 0; i < data.cidcl - 1; i++)
00903 {
00904 operands >> data1.dgid >> data1.cspidCur;
00905 }
00906 }
00907
00908 void Msod::opDggcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00909 {
00910 walk(bytes, operands);
00911 }
00912
00913 void Msod::opOleobject(
00914 Header &,
00915 Q_UINT32,
00916 QDataStream &)
00917 {
00918 }
00919
00920 void Msod::opOpt(Header &, Q_UINT32 bytes, QDataStream &operands)
00921 {
00922 m_opt->walk(bytes, operands);
00923 }
00924
00925 void Msod::opRegroupitems(
00926 Header &,
00927 Q_UINT32,
00928 QDataStream &)
00929 {
00930 }
00931
00932 void Msod::opSelection(
00933 Header &,
00934 Q_UINT32,
00935 QDataStream &)
00936 {
00937 }
00938
00939 void Msod::opSolvercontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00940 {
00941 walk(bytes, operands);
00942 }
00943
00944 void Msod::opSp(Header &op, Q_UINT32 bytes, QDataStream &operands)
00945 {
00946
00947
00948
00949
00950 m_shape.type = op.opcode.fields.inst;
00951 m_shape.length = bytes;
00952 m_shape.data = new char [bytes];
00953 operands.readRawBytes(m_shape.data, bytes);
00954 }
00955
00956 void Msod::opSpcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00957 {
00958 walk(bytes, operands);
00959
00960
00961
00962 QByteArray a;
00963
00964 a.setRawData(m_shape.data, m_shape.length);
00965 QDataStream s(a, IO_ReadOnly);
00966 s.setByteOrder(QDataStream::LittleEndian);
00967 drawShape(m_shape.type, m_shape.length, s);
00968 a.resetRawData(m_shape.data, m_shape.length);
00969 delete [] m_shape.data;
00970 m_shape.data = 0L;
00971 }
00972
00973 void Msod::opSpgr(Header &, Q_UINT32, QDataStream &operands)
00974 {
00975 struct
00976 {
00977 Q_UINT32 x;
00978 Q_UINT32 y;
00979 Q_UINT32 w;
00980 Q_UINT32 h;
00981 } data;
00982
00983 operands >> data.x >> data.y >> data.w >> data.h;
00984 }
00985
00986 void Msod::opSpgrcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
00987 {
00988 walk(bytes, operands);
00989 }
00990
00991 void Msod::opSplitmenucolors(Header &, Q_UINT32, QDataStream &operands)
00992 {
00993 struct
00994 {
00995 Q_UINT32 fill;
00996 Q_UINT32 line;
00997 Q_UINT32 shadow;
00998 Q_UINT32 threeDee;
00999 } data;
01000
01001 operands >> data.fill >> data.line >> data.shadow >> data.threeDee;
01002 }
01003
01004 void Msod::opTextbox(
01005 Header &,
01006 Q_UINT32,
01007 QDataStream &)
01008 {
01009 }
01010
01011 void Msod::skip(Q_UINT32 bytes, QDataStream &operands)
01012 {
01013 if ((int)bytes < 0)
01014 {
01015 kdError(s_area) << "skip: " << (int)bytes << endl;
01016 return;
01017 }
01018 if (bytes)
01019 {
01020 Q_UINT32 i;
01021 Q_UINT8 discard;
01022
01023 kdDebug(s_area) << "skip: " << bytes << endl;
01024 for (i = 0; i < bytes; i++)
01025 {
01026 operands >> discard;
01027 }
01028 }
01029 }
01030
01031 void Msod::walk(Q_UINT32 bytes, QDataStream &operands)
01032 {
01033 Header op;
01034 Q_UINT32 length = 0;
01035
01036
01037
01038 while (length + 8 <= bytes)
01039 {
01040 operands >> op.opcode.info >> op.cbLength;
01041
01042
01043 if (length + op.cbLength + 8 > bytes)
01044 {
01045 op.cbLength = bytes - length - 8;
01046 }
01047 length += op.cbLength + 8;
01048 if (op.opcode.fields.fbt == 0x200)
01049 {
01050
01051 break;
01052 }
01053
01054
01055
01056 invokeHandler(op, op.cbLength, operands);
01057 }
01058
01059
01060 skip(bytes - length, operands);
01061 }
01062
01063 Msod::Options::Options(
01064 Msod &parent) :
01065 m_parent(parent)
01066 {
01067 m_pVertices = 0L;
01068 initialise();
01069 }
01070
01071 Msod::Options::~Options()
01072 {
01073 delete m_pVertices;
01074 }
01075
01076 double Msod::Options::from1616ToDouble(Q_UINT32 value)
01077 {
01078 return (value >> 16) + 65535.0 / (double)(value & 0xffff);
01079 }
01080
01081 void Msod::Options::initialise()
01082 {
01083 m_rotation = 0.0;
01084
01085 m_lTxid = 0;
01086
01087 m_pib = 0;
01088 m_pibName = QString::null;
01089 m_pibFlags = 0;
01090 m_pictureId = 0;
01091 m_fNoHitTestPicture = false;
01092 m_pictureGray = false;
01093 m_pictureBiLevel = false;
01094 m_pictureActive = false;
01095
01096 m_geoLeft = 0;
01097 m_geoTop = 0;
01098 m_geoRight = 21600;
01099 m_geoBottom = 21600;
01100 m_shapePath = 1;
01101 delete m_pVertices;
01102 m_pVertices = 0L;
01103 m_fShadowOK = true;
01104 m_f3DOK = true;
01105 m_fLineOK = true;
01106 m_fGTextOK = false;
01107 m_fFillShadeShapeOK = false;
01108 m_fFillOK = true;
01109
01110 m_fFilled = true;
01111 m_fHitTestFill = true;
01112 m_fillShape = true;
01113 m_fillUseRect = false;
01114 m_fNoFillHitTest = false;
01115
01116 m_lineColor = 0;
01117 m_lineBackColor = 0xffffff;
01118 m_lineType = 0;
01119 m_lineWidth = 9525;
01120
01121 m_fArrowheadsOK = false;
01122 m_fLine = true;
01123 m_fHitTestLine = true;
01124 m_lineFillShape = true;
01125 m_fNoLineDrawDash = false;
01126
01127 m_bWMode = 1;
01128
01129 m_fOleIcon = false;
01130 m_fPreferRelativeResize = false;
01131 m_fLockShapeType = false;
01132 m_fDeleteAttachedObject = false;
01133 m_fBackground = false;
01134 }
01135
01136 void Msod::Options::walk(Q_UINT32 bytes, QDataStream &operands)
01137 {
01138 Header op;
01139 Q_UINT16 length = 0;
01140 Q_UINT16 complexLength = 0;
01141
01142
01143
01144 initialise();
01145
01146
01147
01148 QPtrList<Header> complexOpts;
01149 complexOpts.setAutoDelete(true);
01150 bool unsupported;
01151 while (length + complexLength < (int)bytes)
01152 {
01153 operands >> op.opcode.info >> op.value;
01154 length += 6;
01155
01156
01157
01158 if (op.opcode.fields.fComplex)
01159 {
01160 complexLength += op.value;
01161 complexOpts.append(new Header(op));
01162 continue;
01163 }
01164
01165
01166
01167 unsupported = false;
01168 switch (op.opcode.fields.pid)
01169 {
01170 case 4:
01171 m_rotation = from1616ToDouble(op.value);
01172 break;
01173 case 128:
01174 m_lTxid = op.value;
01175 kdDebug(s_area) << "textbox: 0x" << QString::number(op.value,16) << endl;
01176 break;
01177 case 260:
01178 if (op.opcode.fields.fBid)
01179 {
01180 m_pib = op.value;
01181 if (m_parent.m_isRequiredDrawing)
01182 {
01183 Image *image = m_parent.m_images[m_pib - 1];
01184
01185
01186
01187
01188 if (image->extension == "wmf")
01189 {
01190 QByteArray a;
01191 a.setRawData(image->data, image->length);
01192 QDataStream s(a, IO_ReadOnly);
01193 m_parent.KWmf::parse(s, image->length);
01194 a.resetRawData(image->data, image->length);
01195 }
01196 else
01197 {
01198 m_parent.gotPicture(
01199 m_pib,
01200 image->extension,
01201 image->length,
01202 image->data);
01203 }
01204 }
01205 }
01206 else
01207 {
01208 kdError(s_area) << "Cannot handle IMsoBlip" << endl;
01209 }
01210 break;
01211 case 262:
01212 m_pibFlags = op.value;
01213 break;
01214 case 267:
01215 m_pictureId = op.value;
01216 break;
01217 case 319:
01218 m_fNoHitTestPicture = (op.value & 0x0008) != 0;
01219 m_pictureGray = (op.value & 0x0004) != 0;
01220 m_pictureBiLevel = (op.value & 0x0002) != 0;
01221 m_pictureActive = (op.value & 0x0001) != 0;
01222 break;
01223 case 320:
01224 m_geoLeft = op.value;
01225 break;
01226 case 321:
01227 m_geoTop = op.value;
01228 break;
01229 case 322:
01230 m_geoRight = op.value;
01231 break;
01232 case 323:
01233 m_geoBottom = op.value;
01234 break;
01235 case 324:
01236 m_shapePath = op.value;
01237 break;
01238 case 383:
01239 m_fShadowOK = (op.value & 0x0020) != 0;
01240 m_f3DOK = (op.value & 0x0010) != 0;
01241 m_fLineOK = (op.value & 0x0008) != 0;
01242 m_fGTextOK = (op.value & 0x0004) != 0;
01243 m_fFillShadeShapeOK = (op.value & 0x0002) != 0;
01244 m_fFillOK = (op.value & 0x0001) != 0;
01245 break;
01246 case 447:
01247 m_fFilled = (op.value & 0x0010) != 0;
01248 m_fHitTestFill = (op.value & 0x0008) != 0;
01249 m_fillShape = (op.value & 0x0004) != 0;
01250 m_fillUseRect = (op.value & 0x0002) != 0;
01251 m_fNoFillHitTest = (op.value & 0x0001) != 0;
01252 break;
01253 case 448:
01254 m_lineColor = op.value;
01255 break;
01256 case 450:
01257 m_lineBackColor = op.value;
01258 break;
01259 case 452:
01260 m_lineType = op.value;
01261 break;
01262 case 459:
01263 m_lineWidth = op.value;
01264 break;
01265 case 511:
01266 m_fArrowheadsOK = (op.value & 0x0010) != 0;
01267 m_fLine = (op.value & 0x0008) != 0;
01268 m_fHitTestLine = (op.value & 0x0004) != 0;
01269 m_lineFillShape = (op.value & 0x0002) != 0;
01270 m_fNoLineDrawDash = (op.value & 0x0001) != 0;
01271 break;
01272 case 772:
01273 m_bWMode = op.value;
01274 break;
01275 case 831:
01276 m_fOleIcon = (op.value & 0x0010) != 0;
01277 m_fPreferRelativeResize = (op.value & 0x0008) != 0;
01278 m_fLockShapeType = (op.value & 0x0004) != 0;
01279 m_fDeleteAttachedObject = (op.value & 0x0002) != 0;
01280 m_fBackground = (op.value & 0x0001) != 0;
01281 break;
01282 default:
01283 unsupported = true;
01284 kdWarning(s_area) << "unsupported simple option: " <<
01285 op.opcode.fields.pid << endl;
01286 break;
01287 }
01288 if (!unsupported)
01289 kdDebug(s_area) << "simple option: " <<
01290 op.opcode.fields.pid << endl;
01291 }
01292
01293
01294
01295 while (complexOpts.count())
01296 {
01297 Q_INT16 t16;
01298 unsigned i;
01299
01300 op = *complexOpts.getFirst();
01301 complexOpts.removeFirst();
01302 unsupported = false;
01303 switch (op.opcode.fields.pid)
01304 {
01305 case 261:
01306 while (true)
01307 {
01308 operands >> t16;
01309 if (!t16)
01310 break;
01311 m_pibName += QChar(t16);
01312 };
01313 break;
01314 case 325:
01315 m_pVertices = new QPointArray(op.value / 4);
01316 for (i = 0; i < m_pVertices->count(); i++)
01317 {
01318 m_pVertices->setPoint(i, m_parent.normalisePoint(operands));
01319 };
01320 break;
01321 case 326:
01322 operands >> t16;
01323 i = t16;
01324 operands >> t16;
01325 operands >> t16;
01326 m_parent.skip(i * t16, operands);
01327 break;
01328 default:
01329 unsupported = true;
01330 kdWarning(s_area) << "unsupported complex option: " <<
01331 op.opcode.fields.pid << " operands: " << op.value << endl;
01332 m_parent.skip(op.value, operands);
01333 break;
01334 }
01335 if (!unsupported)
01336 kdDebug(s_area) << "complex option: " <<
01337 op.opcode.fields.pid << " operands: " << op.value << endl;
01338 complexLength -= op.value;
01339 }
01340 }