You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1341 lines
41 KiB
1341 lines
41 KiB
/*
|
|
Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>.
|
|
This file is part of the KDE project
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
DESCRIPTION
|
|
*/
|
|
|
|
#include <kdebug.h>
|
|
#include <tqdatastream.h>
|
|
#include <tqfile.h>
|
|
#include <tqptrlist.h>
|
|
#include <tqpointarray.h>
|
|
#include <tqrect.h>
|
|
#include <tqsize.h>
|
|
#include <msod.h>
|
|
#include <zlib.h>
|
|
|
|
const int Msod::s_area = 30505;
|
|
|
|
Msod::Msod(
|
|
unsigned dpi) :
|
|
KWmf(dpi)
|
|
{
|
|
m_dpi = dpi;
|
|
m_images.setAutoDelete(true);
|
|
m_opt = new Options(*this);
|
|
m_shape.data = 0L;
|
|
m_shape.length = 0;
|
|
}
|
|
|
|
Msod::~Msod()
|
|
{
|
|
delete [] m_shape.data;
|
|
delete m_opt;
|
|
}
|
|
|
|
void Msod::drawShape(
|
|
unsigned shapeType,
|
|
TQ_UINT32 bytes,
|
|
TQDataStream &operands)
|
|
{
|
|
static const char *funcTab[] =
|
|
{
|
|
"UNKNOWN", // Unknown
|
|
"RECTANGLE", // Rectangle
|
|
"ROUNDRECTANGLE", // Roundrectangle
|
|
"ELLIPSE", // Ellipse
|
|
"DIAMOND", // Diamond
|
|
"ISOCELESTRIANGLE", // Isocelestriangle
|
|
"RIGHTTRIANGLE", // Righttriangle
|
|
"PARALLELOGRAM", // Parallelogram
|
|
"TRAPEZOID", // Trapezoid
|
|
"HEXAGON", // Hexagon
|
|
"OCTAGON", // Octagon
|
|
"PLUS", // Plus
|
|
"STAR", // Star
|
|
"ARROW", // Arrow
|
|
"THICKARROW", // Thickarrow
|
|
"HOMEPLATE", // Homeplate
|
|
"CUBE", // Cube
|
|
"BALLOON", // Balloon
|
|
"SEAL", // Seal
|
|
"ARC", // Arc
|
|
"LINE", // Line
|
|
"PLAQUE", // Plaque
|
|
"CAN", // Can
|
|
"DONUT", // Donut
|
|
"TEXTSIMPLE", // Textsimple
|
|
"TEXTOCTAGON", // Textoctagon
|
|
"TEXTHEXAGON", // Texthexagon
|
|
"TEXTCURVE", // Textcurve
|
|
"TEXTWAVE", // Textwave
|
|
"TEXTRING", // Textring
|
|
"TEXTONCURVE", // Textoncurve
|
|
"TEXTONRING", // Textonring
|
|
"STRAIGHTCONNECTOR1", // Straightconnector1
|
|
"BENTCONNECTOR2", // Bentconnector2
|
|
"BENTCONNECTOR3", // Bentconnector3
|
|
"BENTCONNECTOR4", // Bentconnector4
|
|
"BENTCONNECTOR5", // Bentconnector5
|
|
"CURVEDCONNECTOR2", // Curvedconnector2
|
|
"CURVEDCONNECTOR3", // Curvedconnector3
|
|
"CURVEDCONNECTOR4", // Curvedconnector4
|
|
"CURVEDCONNECTOR5", // Curvedconnector5
|
|
"CALLOUT1", // Callout1
|
|
"CALLOUT2", // Callout2
|
|
"CALLOUT3", // Callout3
|
|
"ACCENTCALLOUT1", // Accentcallout1
|
|
"ACCENTCALLOUT2", // Accentcallout2
|
|
"ACCENTCALLOUT3", // Accentcallout3
|
|
"BORDERCALLOUT1", // bordercallout1
|
|
"BORDERCALLOUT2", // Bordercallout2
|
|
"BORDERCALLOUT3", // Bordercallout3
|
|
"ACCENTBORDERCALLOUT1", // Accentbordercallout1
|
|
"ACCENTBORDERCALLOUT2", // Accentbordercallout2
|
|
"ACCENTBORDERCALLOUT3", // Accentbordercallout3
|
|
"RIBBON", // Ribbon
|
|
"RIBBON2", // Ribbon2
|
|
"CHEVRON", // Chevron
|
|
"PENTAGON", // Pentagon
|
|
"NOSMOKING", // Nosmoking
|
|
"SEAL8", // Seal8
|
|
"SEAL16", // Seal16
|
|
"SEAL32", // Seal32
|
|
"WEDGERECTCALLOUT", // Wedgerectcallout
|
|
"WEDGERRECTCALLOUT", // Wedgerrectcallout
|
|
"WEDGEELLIPSECALLOUT", // Wedgeellipsecallout
|
|
"WAVE", // Wave
|
|
"FOLDEDCORNER", // Foldedcorner
|
|
"LEFTARROW", // Leftarrow
|
|
"DOWNARROW", // Downarrow
|
|
"UPARROW", // Uparrow
|
|
"LEFTRIGHTARROW", // Leftrightarrow
|
|
"UPDOWNARROW", // Updownarrow
|
|
"IRREGULARSEAL1", // Irregularseal1
|
|
"IRREGULARSEAL2", // Irregularseal2
|
|
"LIGHTNINGBOLT", // Lightningbolt
|
|
"HEART", // Heart
|
|
"PICTUREFRAME", // PictureFrame
|
|
"QUADARROW", // Quadarrow
|
|
"LEFTARROWCALLOUT", // Leftarrowcallout
|
|
"RIGHTARROWCALLOUT", // Rightarrowcallout
|
|
"UPARROWCALLOUT", // Uparrowcallout
|
|
"DOWNARROWCALLOUT", // Downarrowcallout
|
|
"LEFTRIGHTARROWCALLOUT", // Leftrightarrowcallout
|
|
"UPDOWNARROWCALLOUT", // Updownarrowcallout
|
|
"QUADARROWCALLOUT", // Quadarrowcallout
|
|
"BEVEL", // Bevel
|
|
"LEFTBRACKET", // Leftbracket
|
|
"RIGHTBRACKET", // Rightbracket
|
|
"LEFTBRACE", // Leftbrace
|
|
"RIGHTBRACE", // Rightbrace
|
|
"LEFTUPARROW", // Leftuparrow
|
|
"BENTUPARROW", // Bentuparrow
|
|
"BENTARROW", // Bentarrow
|
|
"SEAL24", // Seal24
|
|
"STRIPEDRIGHTARROW", // Stripedrightarrow
|
|
"NOTCHEDRIGHTARROW", // Notchedrightarrow
|
|
"BLOCKARC", // Blockarc
|
|
"SMILEYFACE", // Smileyface
|
|
"VERTICALSCROLL", //Qt::Verticalscroll
|
|
"HORIZONTALSCROLL", //Qt::Horizontalscroll
|
|
"CIRCULARARROW", // Circulararrow
|
|
"NOTCHEDCIRCULARARROW", // Notchedcirculararrow
|
|
"UTURNARROW", // Uturnarrow
|
|
"CURVEDRIGHTARROW", // Curvedrightarrow
|
|
"CURVEDLEFTARROW", // Curvedleftarrow
|
|
"CURVEDUPARROW", // Curveduparrow
|
|
"CURVEDDOWNARROW", // Curveddownarrow
|
|
"CLOUDCALLOUT", // Cloudcallout
|
|
"ELLIPSERIBBON", // Ellipseribbon
|
|
"ELLIPSERIBBON2", // Ellipseribbon2
|
|
"FLOWCHARTPROCESS", // Flowchartprocess
|
|
"FLOWCHARTDECISION", // Flowchartdecision
|
|
"FLOWCHARTINPUTOUTPUT", // Flowchartinputoutput
|
|
"FLOWCHARTPREDEFINEDPROCESS", // Flowchartpredefinedprocess
|
|
"FLOWCHARTINTERNALSTORAGE", // Flowchartinternalstorage
|
|
"FLOWCHARTDOCUMENT", // Flowchartdocument
|
|
"FLOWCHARTMULTIDOCUMENT", // Flowchartmultidocument
|
|
"FLOWCHARTTERMINATOR", // Flowchartterminator
|
|
"FLOWCHARTPREPARATION", // Flowchartpreparation
|
|
"FLOWCHARTMANUALINPUT", // Flowchartmanualinput
|
|
"FLOWCHARTMANUALOPERATION", // Flowchartmanualoperation
|
|
"FLOWCHARTCONNECTOR", // Flowchartconnector
|
|
"FLOWCHARTPUNCHEDCARD", // Flowchartpunchedcard
|
|
"FLOWCHARTPUNCHEDTAPE", // Flowchartpunchedtape
|
|
"FLOWCHARTSUMMINGJUNCTION", // Flowchartsummingjunction
|
|
"FLOWCHARTOR", // Flowchartor
|
|
"FLOWCHARTCOLLATE", // Flowchartcollate
|
|
"FLOWCHARTSORT", // Flowchartsort
|
|
"FLOWCHARTEXTRACT", // Flowchartextract
|
|
"FLOWCHARTMERGE", // Flowchartmerge
|
|
"FLOWCHARTOFFLINESTORAGE", // Flowchartofflinestorage
|
|
"FLOWCHARTONLINESTORAGE", // Flowchartonlinestorage
|
|
"FLOWCHARTMAGNETICTAPE", // Flowchartmagnetictape
|
|
"FLOWCHARTMAGNETICDISK", // Flowchartmagneticdisk
|
|
"FLOWCHARTMAGNETICDRUM", // Flowchartmagneticdrum
|
|
"FLOWCHARTDISPLAY", // Flowchartdisplay
|
|
"FLOWCHARTDELAY", // Flowchartdelay
|
|
"TEXTPLAINTEXT", // Textplaintext
|
|
"TEXTSTOP", // Textstop
|
|
"TEXTTRIANGLE", // Texttriangle
|
|
"TEXTTRIANGLEINVERTED", // Texttriangleinverted
|
|
"TEXTCHEVRON", // Textchevron
|
|
"TEXTCHEVRONINVERTED", // Textchevroninverted
|
|
"TEXTRINGINSIDE", // Textringinside
|
|
"TEXTRINGOUTSIDE", // Textringoutside
|
|
"TEXTARCHUPCURVE", // Textarchupcurve
|
|
"TEXTARCHDOWNCURVE", // Textarchdowncurve
|
|
"TEXTCIRCLECURVE", // Textcirclecurve
|
|
"TEXTBUTTONCURVE", // Textbuttoncurve
|
|
"TEXTARCHUPPOUR", // Textarchuppour
|
|
"TEXTARCHDOWNPOUR", // Textarchdownpour
|
|
"TEXTCIRCLEPOUR", // Textcirclepour
|
|
"TEXTBUTTONPOUR", // Textbuttonpour
|
|
"TEXTCURVEUP", // Textcurveup
|
|
"TEXTCURVEDOWN", // Textcurvedown
|
|
"TEXTCASCADEUP", // Textcascadeup
|
|
"TEXTCASCADEDOWN", // Textcascadedown
|
|
"TEXTWAVE1", // Textwave1
|
|
"TEXTWAVE2", // Textwave2
|
|
"TEXTWAVE3", // Textwave3
|
|
"TEXTWAVE4", // Textwave4
|
|
"TEXTINFLATE", // Textinflate
|
|
"TEXTDEFLATE", // Textdeflate
|
|
"TEXTINFLATEBOTTOM", // Textinflatebottom
|
|
"TEXTDEFLATEBOTTOM", // Textdeflatebottom
|
|
"TEXTINFLATETOP", // Textinflatetop
|
|
"TEXTDEFLATETOP", // Textdeflatetop
|
|
"TEXTDEFLATEINFLATE", // Textdeflateinflate
|
|
"TEXTDEFLATEINFLATEDEFLATE", // Textdeflateinflatedeflate
|
|
"TEXTFADERIGHT", // Textfaderight
|
|
"TEXTFADELEFT", // Textfadeleft
|
|
"TEXTFADEUP", // Textfadeup
|
|
"TEXTFADEDOWN", // Textfadedown
|
|
"TEXTSLANTUP", // Textslantup
|
|
"TEXTSLANTDOWN", // Textslantdown
|
|
"TEXTCANUP", // Textcanup
|
|
"TEXTCANDOWN", // Textcandown
|
|
"FLOWCHARTALTERNATEPROCESS", // Flowchartalternateprocess
|
|
"FLOWCHARTOFFPAGECONNECTOR", // Flowchartoffpageconnector
|
|
"CALLOUT90", // Callout90
|
|
"ACCENTCALLOUT90", // Accentcallout90
|
|
"BORDERCALLOUT90", // Bordercallout90
|
|
"ACCENTBORDERCALLOUT90", // Accentbordercallout90
|
|
"LEFTRIGHTUPARROW", // Leftrightuparrow
|
|
"SUN", // Sun
|
|
"MOON", // Moon
|
|
"BRACKETPAIR", // Bracketpair
|
|
"BRACEPAIR", // Bracepair
|
|
"SEAL4", // Seal4
|
|
"DOUBLEWAVE", // Doublewave
|
|
"ACTIONBUTTONBLANK", // Actionbuttonblank
|
|
"ACTIONBUTTONHOME", // Actionbuttonhome
|
|
"ACTIONBUTTONHELP", // Actionbuttonhelp
|
|
"ACTIONBUTTONINFORMATION", // Actionbuttoninformation
|
|
"ACTIONBUTTONFORWARDNEXT", // Actionbuttonforwardnext
|
|
"ACTIONBUTTONBACKPREVIOUS", // Actionbuttonbackprevious
|
|
"ACTIONBUTTONEND", // Actionbuttonend
|
|
"ACTIONBUTTONBEGINNING", // Actionbuttonbeginning
|
|
"ACTIONBUTTONRETURN", // Actionbuttonreturn
|
|
"ACTIONBUTTONDOCUMENT", // Actionbuttondocument
|
|
"ACTIONBUTTONSOUND", // Actionbuttonsound
|
|
"ACTIONBUTTONMOVIE", // Actionbuttonmovie
|
|
"HOSTCONTROL", // Hostcontrol
|
|
"TEXTBOX", // Textbox
|
|
};
|
|
struct
|
|
{
|
|
TQ_UINT32 spid; // The shape id
|
|
union
|
|
{
|
|
TQ_UINT32 info;
|
|
struct
|
|
{
|
|
TQ_UINT32 fGroup : 1; // This shape is a group shape
|
|
TQ_UINT32 fChild : 1; // Not a top-level shape
|
|
TQ_UINT32 fPatriarch : 1; // This is the topmost group shape.
|
|
// Exactly one of these per drawing.
|
|
TQ_UINT32 fDeleted : 1; // The shape.has been deleted
|
|
TQ_UINT32 fOleShape : 1; // The shape is an OLE object
|
|
TQ_UINT32 fHaveMaster : 1; // Shape has a hspMaster property
|
|
TQ_UINT32 fFlipH : 1; // Shape is flipped horizontally
|
|
TQ_UINT32 fFlipV : 1; // Shape is flipped vertically
|
|
TQ_UINT32 fConnector : 1; // Connector type of shape
|
|
TQ_UINT32 fHaveAnchor : 1; // Shape has an anchor of some kind
|
|
TQ_UINT32 fBackground : 1; // Background shape
|
|
TQ_UINT32 fHaveSpt : 1; // Shape has a shape type property
|
|
TQ_UINT32 reserved : 20; // Not yet used
|
|
} fields;
|
|
} grfPersistent;
|
|
} data;
|
|
|
|
// Scan lookup table for operation.
|
|
|
|
operands >> data.spid;
|
|
operands >> data.grfPersistent.info;
|
|
bytes -= 8;
|
|
kdDebug(s_area) << "shape-id: " << data.spid << " type: " << funcTab[shapeType] << " (" << shapeType << ")" <<
|
|
(data.grfPersistent.fields.fGroup ? " group" : "") <<
|
|
(data.grfPersistent.fields.fChild ? " child" : "") <<
|
|
(data.grfPersistent.fields.fPatriarch ? " patriarch" : "") <<
|
|
(data.grfPersistent.fields.fDeleted ? " deleted" : "") <<
|
|
(data.grfPersistent.fields.fOleShape ? " oleshape" : "") <<
|
|
(data.grfPersistent.fields.fHaveMaster ? " master" : "") <<
|
|
(data.grfPersistent.fields.fFlipH ? " flipv" : "") <<
|
|
(data.grfPersistent.fields.fConnector ? " connector" : "") <<
|
|
(data.grfPersistent.fields.fHaveAnchor ? " anchor" : "") <<
|
|
(data.grfPersistent.fields.fBackground ? " background" : "") <<
|
|
(data.grfPersistent.fields.fHaveSpt ? " spt" : "") <<
|
|
" operands: " << bytes << endl;
|
|
if (data.grfPersistent.fields.fDeleted)
|
|
return;
|
|
if ((!m_isRequiredDrawing) && (m_requestedShapeId != data.spid))
|
|
return;
|
|
|
|
// An active shape! Let's draw it...
|
|
|
|
switch (shapeType)
|
|
{
|
|
case 0:
|
|
if (m_opt->m_pVertices)
|
|
{
|
|
gotPolyline(m_dc, *m_opt->m_pVertices);
|
|
}
|
|
break;
|
|
case 1:
|
|
if (bytes > 7)
|
|
{
|
|
TQPoint topLeft;
|
|
TQSize size;
|
|
|
|
topLeft = normalisePoint(operands);
|
|
size = normaliseSize(operands);
|
|
|
|
TQRect rect(topLeft, size);
|
|
TQPointArray points(4);
|
|
|
|
points.setPoint(0, topLeft);
|
|
points.setPoint(1, rect.topRight());
|
|
points.setPoint(2, rect.bottomRight());
|
|
points.setPoint(3, rect.bottomLeft());
|
|
gotRectangle(m_dc, points);
|
|
}
|
|
case 20:
|
|
if (bytes > 7)
|
|
{
|
|
TQPoint lineFrom;
|
|
TQPoint lineTo;
|
|
|
|
lineTo = normalisePoint(operands);
|
|
|
|
TQPointArray points(2);
|
|
|
|
points.setPoint(0, lineFrom);
|
|
points.setPoint(1, lineTo);
|
|
gotPolyline(m_dc, points);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Msod::invokeHandler(
|
|
Header &op,
|
|
TQ_UINT32 bytes,
|
|
TQDataStream &operands)
|
|
{
|
|
typedef void (Msod::*method)(Header &op, TQ_UINT32 bytes, TQDataStream &operands);
|
|
|
|
typedef struct
|
|
{
|
|
const char *name;
|
|
TQ_UINT16 opcode;
|
|
method handler;
|
|
} opcodeEntry;
|
|
|
|
static const opcodeEntry funcTab[] =
|
|
{
|
|
{ "ALIGNRULE", 0xF013, &Msod::opAlignrule },
|
|
{ "ANCHOR", 0xF00E, &Msod::opAnchor },
|
|
{ "ARCRULE", 0xF014, &Msod::opArcrule },
|
|
{ "BSE", 0xF007, &Msod::opBse },
|
|
{ "BSTORECONTAINER", 0xF001, &Msod::opBstorecontainer },
|
|
{ "CALLOUTRULE", 0xF017, &Msod::opCalloutrule },
|
|
{ "CHILDANCHOR", 0xF00F, &Msod::opChildanchor },
|
|
{ "CLIENTANCHOR", 0xF010, &Msod::opClientanchor },
|
|
{ "CLIENTDATA", 0xF011, &Msod::opClientdata },
|
|
{ "CLIENTRULE", 0xF015, &Msod::opClientrule },
|
|
{ "CLIENTTEXTBOX", 0xF00D, &Msod::opClienttextbox },
|
|
{ "CLSID", 0xF016, &Msod::opClsid },
|
|
{ "COLORMRU", 0xF11A, &Msod::opColormru },
|
|
{ "CONNECTORRULE", 0xF012, &Msod::opConnectorrule },
|
|
{ "DELETEDPSPL", 0xF11D, &Msod::opDeletedpspl },
|
|
{ "DG", 0xF008, &Msod::opDg },
|
|
{ "DGCONTAINER", 0xF002, &Msod::opDgcontainer },
|
|
{ "DGG", 0xF006, &Msod::opDgg },
|
|
{ "DGGCONTAINER", 0xF000, &Msod::opDggcontainer },
|
|
{ "OLEOBJECT", 0xF11F, &Msod::opOleobject },
|
|
{ "OPT", 0xF00B, &Msod::opOpt },
|
|
{ "REGROUPITEMS", 0xF118, &Msod::opRegroupitems },
|
|
{ "SELECTION", 0xF119, &Msod::opSelection },
|
|
{ "SOLVERCONTAINER", 0xF005, &Msod::opSolvercontainer },
|
|
{ "SP", 0xF00A, &Msod::opSp },
|
|
{ "SPCONTAINER", 0xF004, &Msod::opSpcontainer },
|
|
{ "SPGR", 0xF009, &Msod::opSpgr },
|
|
{ "SPGRCONTAINER", 0xF003, &Msod::opSpgrcontainer },
|
|
{ "SPLITMENUCOLORS", 0xF11E, &Msod::opSplitmenucolors },
|
|
{ "TEXTBOX", 0xF00C, &Msod::opTextbox },
|
|
{ NULL, 0, 0 },
|
|
{ "BLIP", 0, &Msod::opBlip }
|
|
};
|
|
unsigned i;
|
|
method result;
|
|
|
|
// Scan lookup table for operation.
|
|
|
|
for (i = 0; funcTab[i].name; i++)
|
|
{
|
|
if (funcTab[i].opcode == op.opcode.fields.fbt)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Invoke handler.
|
|
|
|
result = funcTab[i].handler;
|
|
if (!result && (op.opcode.fields.fbt >= 0xF018) && (0xF117 >= op.opcode.fields.fbt))
|
|
result = funcTab[++i].handler;
|
|
if (!result)
|
|
{
|
|
if (funcTab[i].name)
|
|
kdWarning(s_area) << "invokeHandler: unsupported opcode: " <<
|
|
funcTab[i].name <<
|
|
" operands: " << bytes << endl;
|
|
else
|
|
kdWarning(s_area) << "invokeHandler: unsupported opcode: 0x" <<
|
|
TQString::number(op.opcode.fields.fbt, 16) <<
|
|
" operands: " << bytes << endl;
|
|
|
|
// Skip data we cannot use.
|
|
|
|
skip(bytes, operands);
|
|
}
|
|
else
|
|
{
|
|
kdDebug(s_area) << "invokeHandler: opcode: " << funcTab[i].name <<
|
|
" operands: " << bytes << endl;
|
|
|
|
// We don't invoke the handler directly on the incoming operands, but
|
|
// via a temporary datastream. This adds overhead, but eliminates the
|
|
// need for the individual handlers to read *exactly* the right amount
|
|
// of data (thus speeding development, and possibly adding some
|
|
// future-proofing).
|
|
|
|
if (bytes)
|
|
{
|
|
TQByteArray *record = new TQByteArray(bytes);
|
|
TQDataStream *body;
|
|
|
|
operands.readRawBytes(record->data(), bytes);
|
|
body = new TQDataStream(*record, IO_ReadOnly);
|
|
body->setByteOrder(TQDataStream::LittleEndian);
|
|
(this->*result)(op, bytes, *body);
|
|
delete body;
|
|
delete record;
|
|
}
|
|
else
|
|
{
|
|
TQDataStream *body = new TQDataStream();
|
|
|
|
(this->*result)(op, bytes, *body);
|
|
delete body;
|
|
}
|
|
}
|
|
}
|
|
|
|
TQPoint Msod::normalisePoint(
|
|
TQDataStream &operands)
|
|
{
|
|
TQ_UINT16 x;
|
|
TQ_UINT16 y;
|
|
|
|
operands >> x >> y;
|
|
return TQPoint(x / m_dpi, y / m_dpi);
|
|
}
|
|
|
|
TQSize Msod::normaliseSize(
|
|
TQDataStream &operands)
|
|
{
|
|
TQ_UINT16 width;
|
|
TQ_UINT16 height;
|
|
|
|
operands >> width >> height;
|
|
return TQSize(width / m_dpi, height / m_dpi);
|
|
}
|
|
|
|
bool Msod::parse(
|
|
unsigned shapeId,
|
|
const TQString &file,
|
|
const char *delayStream)
|
|
{
|
|
TQFile in(file);
|
|
if (!in.open(IO_ReadOnly))
|
|
{
|
|
kdError(s_area) << "Unable to open input file!" << endl;
|
|
in.close();
|
|
return false;
|
|
}
|
|
TQDataStream stream(&in);
|
|
bool result = parse(shapeId, stream, in.size(), delayStream);
|
|
in.close();
|
|
return result;
|
|
}
|
|
|
|
bool Msod::parse(
|
|
unsigned shapeId,
|
|
TQDataStream &stream,
|
|
unsigned size,
|
|
const char *delayStream)
|
|
{
|
|
stream.setByteOrder(TQDataStream::LittleEndian); // Great, I love TQt !
|
|
m_requestedShapeId = shapeId;
|
|
m_isRequiredDrawing = false;
|
|
m_delayStream = delayStream;
|
|
|
|
// Read bits.
|
|
|
|
walk(size, stream);
|
|
return true;
|
|
}
|
|
|
|
void Msod::opAlignrule(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opAnchor(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opArcrule(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opBlip(Header &, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
typedef enum
|
|
{
|
|
msobiWMF = 0x216, // Metafile header then compressed WMF.
|
|
msobiEMF = 0x3D4, // Metafile header then compressed EMF.
|
|
msobiPICT = 0x542, // Metafile header then compressed PICT.
|
|
msobiPNG = 0x6E0, // One byte tag then PNG data.
|
|
msobiJPEG = 0x46A, // One byte tag then JFIF data.
|
|
msobiDIB = 0x7A8, // One byte tag then DIB data.
|
|
msobiClient = 0x800 // Clients should set this bit.
|
|
} MSOBI;
|
|
typedef enum
|
|
{
|
|
msocompressionDeflate,
|
|
msocompressionNone = 254,
|
|
msocompressionTest
|
|
} MSOBLIPCOMPRESSION;
|
|
|
|
bool hasPrimaryId;
|
|
TQ_UINT32 length = 0;
|
|
struct
|
|
{
|
|
TQ_UINT32 cb;
|
|
struct
|
|
{
|
|
TQ_UINT32 x;
|
|
TQ_UINT32 y;
|
|
TQ_UINT32 w;
|
|
TQ_UINT32 h;
|
|
} bounds;
|
|
struct
|
|
{
|
|
TQ_UINT32 w;
|
|
TQ_UINT32 h;
|
|
} ptSize;
|
|
TQ_UINT32 cbSave;
|
|
TQ_UINT8 compression;
|
|
TQ_UINT8 filter;
|
|
} data;
|
|
|
|
// Skip any explicit primary header (m_rgbUidprimary).
|
|
|
|
switch (m_blipType)
|
|
{
|
|
case msoblipEMF:
|
|
hasPrimaryId = (m_blipType ^ msobiEMF) != 0;
|
|
break;
|
|
case msoblipWMF:
|
|
hasPrimaryId = (m_blipType ^ msobiWMF) != 0;
|
|
break;
|
|
case msoblipPICT:
|
|
hasPrimaryId = (m_blipType ^ msobiPICT) != 0;
|
|
break;
|
|
case msoblipJPEG:
|
|
hasPrimaryId = (m_blipType ^ msobiJPEG) != 0;
|
|
break;
|
|
case msoblipPNG:
|
|
hasPrimaryId = (m_blipType ^ msobiPNG) != 0;
|
|
break;
|
|
case msoblipDIB:
|
|
hasPrimaryId = (m_blipType ^ msobiDIB) != 0;
|
|
break;
|
|
default:
|
|
hasPrimaryId = (m_blipType ^ msobiClient) != 0;
|
|
break;
|
|
}
|
|
if (hasPrimaryId)
|
|
{
|
|
length += 16;
|
|
skip(16, operands);
|
|
}
|
|
|
|
// Process the rest of the header.
|
|
|
|
data.compression = msocompressionNone;
|
|
switch (m_blipType)
|
|
{
|
|
case msoblipEMF:
|
|
case msoblipWMF:
|
|
case msoblipPICT:
|
|
length += 34;
|
|
operands >> data.cb;
|
|
operands >> data.bounds.x >> data.bounds.y >> data.bounds.w >> data.bounds.h;
|
|
operands >> data.ptSize.w >> data.ptSize.h;
|
|
operands >> data.cbSave;
|
|
operands >> data.compression >> data.filter;
|
|
break;
|
|
case msoblipJPEG:
|
|
case msoblipPNG:
|
|
case msoblipDIB:
|
|
// Skip the "tag".
|
|
length += 1;
|
|
skip(1, operands);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Work out the file type.
|
|
|
|
Image *image = new Image();
|
|
switch (m_blipType)
|
|
{
|
|
case msoblipEMF:
|
|
image->extension = "emf";
|
|
break;
|
|
case msoblipWMF:
|
|
image->extension = "wmf";
|
|
break;
|
|
case msoblipPICT:
|
|
image->extension = "pic";
|
|
break;
|
|
case msoblipJPEG:
|
|
image->extension = "jpg";
|
|
break;
|
|
case msoblipPNG:
|
|
image->extension = "png";
|
|
break;
|
|
case msoblipDIB:
|
|
image->extension = "dib";
|
|
break;
|
|
default:
|
|
image->extension = "img";
|
|
break;
|
|
}
|
|
image->length = bytes - length;
|
|
image->data = new char[image->length];
|
|
operands.readRawBytes((char *)image->data, image->length);
|
|
if (data.compression == msocompressionDeflate)
|
|
{
|
|
const char *tmp;
|
|
uLongf destLen = data.cb;
|
|
int result;
|
|
|
|
tmp = new char[data.cb];
|
|
result = uncompress((TQ_UINT8 *)tmp, &destLen, (TQ_UINT8 *)image->data, image->length);
|
|
if (result != Z_OK)
|
|
{
|
|
kdError(s_area) << "opBlip: uncompress failed: " << result << endl;
|
|
}
|
|
if (destLen != data.cb)
|
|
{
|
|
kdError(s_area) << "opBlip: uncompressed " << destLen << " instead of " << data.cb << endl;
|
|
}
|
|
delete [] image->data;
|
|
image->data = tmp;
|
|
image->length = destLen;
|
|
}
|
|
m_images.resize(m_images.size() + 1);
|
|
m_images.insert(m_images.size() - 1, image);
|
|
}
|
|
|
|
// FBSE - File Blip Store Entry
|
|
|
|
void Msod::opBse(Header &op, TQ_UINT32, TQDataStream &operands)
|
|
{
|
|
struct
|
|
{
|
|
TQ_UINT8 btWin32; // Required type on Win32.
|
|
TQ_UINT8 btMacOS; // Required type on Mac.
|
|
TQ_UINT8 rgbUid[16]; // Identifier of blip.
|
|
TQ_UINT16 tag; // currently unused.
|
|
TQ_UINT32 size; // Blip size in stream.
|
|
TQ_UINT32 cRef; // Reference count on the blip.
|
|
TQ_UINT32 foDelay; // File offset in the delay stream.
|
|
TQ_UINT8 usage; // How this blip is used (MSOBLIPUSAGE).
|
|
TQ_UINT8 cbName; // length of the blip name.
|
|
TQ_UINT8 unused2; // for the future.
|
|
TQ_UINT8 unused3; // for the future.
|
|
} data;
|
|
unsigned i;
|
|
|
|
// Work out the type of the BLIP.
|
|
|
|
m_blipType = static_cast<MSOBLIPTYPE>(op.opcode.fields.inst);
|
|
operands >> data.btWin32;
|
|
operands >> data.btMacOS;
|
|
for (i = 0; i < 16; i++)
|
|
operands >> data.rgbUid[i];
|
|
operands >> data.tag >> data.size;
|
|
operands >> data.cRef >> data.foDelay;
|
|
operands >> data.usage >> data.cbName;
|
|
operands >> data.unused2 >> data.unused2;
|
|
|
|
// If the Blip is not in this drawing file, process it "manually".
|
|
|
|
if (m_delayStream)
|
|
{
|
|
// The m_pib refers to images by number, which includes images
|
|
// that are no longer here. Thus, we fake these out so that any
|
|
// references to non-deleted images are still valid (!!!).
|
|
|
|
if (data.size && data.cRef)
|
|
{
|
|
TQByteArray bytes;
|
|
bytes.setRawData(m_delayStream + data.foDelay, data.size);
|
|
TQDataStream stream(bytes, IO_ReadOnly);
|
|
stream.setByteOrder(TQDataStream::LittleEndian);
|
|
walk(data.size, stream);
|
|
bytes.resetRawData(m_delayStream + data.foDelay, data.size);
|
|
}
|
|
else
|
|
{
|
|
m_images.resize(m_images.size() + 1);
|
|
m_images.insert(m_images.size() - 1, 0L);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Msod::opBstorecontainer(Header &, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
walk(bytes, operands);
|
|
}
|
|
|
|
void Msod::opCalloutrule(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opChildanchor(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opClientanchor(Header &, TQ_UINT32, TQDataStream &operands)
|
|
{
|
|
struct
|
|
{
|
|
TQ_UINT32 unknown;
|
|
} data;
|
|
|
|
operands >> data.unknown;
|
|
kdDebug(s_area) << "client anchor: " << data.unknown << endl;
|
|
}
|
|
|
|
void Msod::opClientdata(Header &, TQ_UINT32, TQDataStream &operands)
|
|
{
|
|
struct
|
|
{
|
|
TQ_UINT32 unknown;
|
|
} data;
|
|
|
|
operands >> data.unknown;
|
|
kdDebug(s_area) << "client data: " << data.unknown << endl;
|
|
}
|
|
|
|
void Msod::opClientrule(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opClienttextbox(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &operands)
|
|
{
|
|
struct
|
|
{
|
|
TQ_UINT32 unknown;
|
|
} data;
|
|
|
|
operands >> data.unknown;
|
|
kdDebug(s_area) << "client textbox: 0x" << TQString::number(data.unknown,16) << endl;
|
|
}
|
|
|
|
void Msod::opClsid(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opColormru(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opConnectorrule(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opDeletedpspl(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
// FDG - File DG
|
|
|
|
void Msod::opDg(Header &, TQ_UINT32, TQDataStream &operands)
|
|
{
|
|
struct
|
|
{
|
|
TQ_UINT32 csp; // The number of shapes in this drawing.
|
|
TQ_UINT32 spidCur; // The last shape ID given to an SP in this DG.
|
|
} data;
|
|
|
|
operands >> data.csp >> data.spidCur;
|
|
kdDebug(s_area) << "drawing id: " << data.spidCur << endl;
|
|
m_isRequiredDrawing = (m_requestedShapeId == data.spidCur);
|
|
if (m_isRequiredDrawing)
|
|
{
|
|
kdDebug(s_area) << "found requested drawing" << endl;
|
|
}
|
|
}
|
|
|
|
void Msod::opDgcontainer(Header &, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
walk(bytes, operands);
|
|
}
|
|
|
|
// FDGG - File DGG
|
|
|
|
void Msod::opDgg(Header &, TQ_UINT32, TQDataStream &operands)
|
|
{
|
|
struct
|
|
{
|
|
TQ_UINT32 spidMax; // The current maximum shape ID.
|
|
TQ_UINT32 cidcl; // The number of ID clusters (FIDCLs).
|
|
TQ_UINT32 cspSaved; // The total number of shapes saved.
|
|
// (including deleted shapes, if undo
|
|
// information was saved).
|
|
TQ_UINT32 cdgSaved; // The total number of drawings saved.
|
|
} data;
|
|
|
|
// File ID Cluster - used to save IDCLs
|
|
|
|
struct
|
|
{
|
|
TQ_UINT32 dgid; // DG owning the SPIDs in this cluster
|
|
TQ_UINT32 cspidCur; // number of SPIDs used so far
|
|
} data1;
|
|
unsigned i;
|
|
|
|
operands >> data.spidMax >> data.cidcl >> data.cspSaved >> data.cdgSaved;
|
|
kdDebug(s_area) << data.cspSaved << " shapes in " <<
|
|
data.cidcl - 1 << " clusters in " <<
|
|
data.cdgSaved << " drawings" << endl;
|
|
for (i = 0; i < data.cidcl - 1; i++)
|
|
{
|
|
operands >> data1.dgid >> data1.cspidCur;
|
|
}
|
|
}
|
|
|
|
void Msod::opDggcontainer(Header &, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
walk(bytes, operands);
|
|
}
|
|
|
|
void Msod::opOleobject(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opOpt(Header &, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
m_opt->walk(bytes, operands);
|
|
}
|
|
|
|
void Msod::opRegroupitems(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opSelection(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::opSolvercontainer(Header &, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
walk(bytes, operands);
|
|
}
|
|
|
|
void Msod::opSp(Header &op, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
// We want to defer the act of drawing a shape until we have seen any options
|
|
// that may affect it. Thus, we merely store the data away, and let opSpContainer
|
|
// do all the ahrd work.
|
|
|
|
m_shape.type = op.opcode.fields.inst;
|
|
m_shape.length = bytes;
|
|
m_shape.data = new char [bytes];
|
|
operands.readRawBytes(m_shape.data, bytes);
|
|
}
|
|
|
|
void Msod::opSpcontainer(Header &, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
walk(bytes, operands);
|
|
|
|
// Having gathered all the information for this shape, we can now draw it.
|
|
|
|
TQByteArray a;
|
|
|
|
a.setRawData(m_shape.data, m_shape.length);
|
|
TQDataStream s(a, IO_ReadOnly);
|
|
s.setByteOrder(TQDataStream::LittleEndian); // Great, I love TQt !
|
|
drawShape(m_shape.type, m_shape.length, s);
|
|
a.resetRawData(m_shape.data, m_shape.length);
|
|
delete [] m_shape.data;
|
|
m_shape.data = 0L;
|
|
}
|
|
|
|
void Msod::opSpgr(Header &, TQ_UINT32, TQDataStream &operands)
|
|
{
|
|
struct
|
|
{
|
|
TQ_UINT32 x;
|
|
TQ_UINT32 y;
|
|
TQ_UINT32 w;
|
|
TQ_UINT32 h;
|
|
} data;
|
|
|
|
operands >> data.x >> data.y >> data.w >> data.h;
|
|
}
|
|
|
|
void Msod::opSpgrcontainer(Header &, TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
walk(bytes, operands);
|
|
}
|
|
|
|
void Msod::opSplitmenucolors(Header &, TQ_UINT32, TQDataStream &operands)
|
|
{
|
|
struct
|
|
{
|
|
TQ_UINT32 fill;
|
|
TQ_UINT32 line;
|
|
TQ_UINT32 shadow;
|
|
TQ_UINT32 threeDee;
|
|
} data;
|
|
|
|
operands >> data.fill >> data.line >> data.shadow >> data.threeDee;
|
|
}
|
|
|
|
void Msod::opTextbox(
|
|
Header &,
|
|
TQ_UINT32,
|
|
TQDataStream &)
|
|
{
|
|
}
|
|
|
|
void Msod::skip(TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
if ((int)bytes < 0)
|
|
{
|
|
kdError(s_area) << "skip: " << (int)bytes << endl;
|
|
return;
|
|
}
|
|
if (bytes)
|
|
{
|
|
TQ_UINT32 i;
|
|
TQ_UINT8 discard;
|
|
|
|
kdDebug(s_area) << "skip: " << bytes << endl;
|
|
for (i = 0; i < bytes; i++)
|
|
{
|
|
operands >> discard;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Msod::walk(TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
Header op;
|
|
TQ_UINT32 length = 0;
|
|
|
|
// Stop parsing when there are no more records. Note that we stop as soon
|
|
// as we cannot get a complete header.
|
|
while (length + 8 <= bytes)
|
|
{
|
|
operands >> op.opcode.info >> op.cbLength;
|
|
|
|
// If we get some duff data, protect ourselves.
|
|
if (length + op.cbLength + 8 > bytes)
|
|
{
|
|
op.cbLength = bytes - length - 8;
|
|
}
|
|
length += op.cbLength + 8;
|
|
if (op.opcode.fields.fbt == 0x200)
|
|
{
|
|
// This appears to be an EOF marker.
|
|
break;
|
|
}
|
|
|
|
// Package the arguments...
|
|
|
|
invokeHandler(op, op.cbLength, operands);
|
|
}
|
|
|
|
// Eat unexpected data that the caller may expect us to consume.
|
|
skip(bytes - length, operands);
|
|
}
|
|
|
|
Msod::Options::Options(
|
|
Msod &parent) :
|
|
m_parent(parent)
|
|
{
|
|
m_pVertices = 0L;
|
|
initialise();
|
|
}
|
|
|
|
Msod::Options::~Options()
|
|
{
|
|
delete m_pVertices;
|
|
}
|
|
|
|
double Msod::Options::from1616ToDouble(TQ_UINT32 value)
|
|
{
|
|
return (value >> 16) + 65535.0 / (double)(value & 0xffff);
|
|
}
|
|
|
|
void Msod::Options::initialise()
|
|
{
|
|
m_rotation = 0.0;
|
|
|
|
m_lTxid = 0;
|
|
|
|
m_pib = 0;
|
|
m_pibName = TQString();
|
|
m_pibFlags = 0;
|
|
m_pictureId = 0;
|
|
m_fNoHitTestPicture = false;
|
|
m_pictureGray = false;
|
|
m_pictureBiLevel = false;
|
|
m_pictureActive = false;
|
|
|
|
m_geoLeft = 0;
|
|
m_geoTop = 0;
|
|
m_geoRight = 21600;
|
|
m_geoBottom = 21600;
|
|
m_shapePath = 1;
|
|
delete m_pVertices;
|
|
m_pVertices = 0L;
|
|
m_fShadowOK = true;
|
|
m_f3DOK = true;
|
|
m_fLineOK = true;
|
|
m_fGTextOK = false;
|
|
m_fFillShadeShapeOK = false;
|
|
m_fFillOK = true;
|
|
|
|
m_fFilled = true;
|
|
m_fHitTestFill = true;
|
|
m_fillShape = true;
|
|
m_fillUseRect = false;
|
|
m_fNoFillHitTest = false;
|
|
|
|
m_lineColor = 0;
|
|
m_lineBackColor = 0xffffff;
|
|
m_lineType = 0;
|
|
m_lineWidth = 9525;
|
|
|
|
m_fArrowheadsOK = false;
|
|
m_fLine = true;
|
|
m_fHitTestLine = true;
|
|
m_lineFillShape = true;
|
|
m_fNoLineDrawDash = false;
|
|
|
|
m_bWMode = 1;
|
|
|
|
m_fOleIcon = false;
|
|
m_fPreferRelativeResize = false;
|
|
m_fLockShapeType = false;
|
|
m_fDeleteAttachedObject = false;
|
|
m_fBackground = false;
|
|
}
|
|
|
|
void Msod::Options::walk(TQ_UINT32 bytes, TQDataStream &operands)
|
|
{
|
|
Header op;
|
|
TQ_UINT16 length = 0;
|
|
TQ_UINT16 complexLength = 0;
|
|
|
|
// Reset all options to default values.
|
|
|
|
initialise();
|
|
|
|
// First process all simple options, and add all complex options to a list.
|
|
|
|
TQPtrList<Header> complexOpts;
|
|
complexOpts.setAutoDelete(true);
|
|
bool unsupported;
|
|
while (length + complexLength < (int)bytes)
|
|
{
|
|
operands >> op.opcode.info >> op.value;
|
|
length += 6;
|
|
|
|
// Defer processing of complex options.
|
|
|
|
if (op.opcode.fields.fComplex)
|
|
{
|
|
complexLength += op.value;
|
|
complexOpts.append(new Header(op));
|
|
continue;
|
|
}
|
|
|
|
// Now squirrel away the option value.
|
|
|
|
unsupported = false;
|
|
switch (op.opcode.fields.pid)
|
|
{
|
|
case 4:
|
|
m_rotation = from1616ToDouble(op.value);
|
|
break;
|
|
case 128:
|
|
m_lTxid = op.value;
|
|
kdDebug(s_area) << "textbox: 0x" << TQString::number(op.value,16) << endl;
|
|
break;
|
|
case 260:
|
|
if (op.opcode.fields.fBid)
|
|
{
|
|
m_pib = op.value;
|
|
if (m_parent.m_isRequiredDrawing)
|
|
{
|
|
Image *image = m_parent.m_images[m_pib - 1];
|
|
|
|
// If it is an embedded WMF we don't bother with the
|
|
// part; we just extract it as more vector graphics.
|
|
|
|
if (image->extension == "wmf")
|
|
{
|
|
TQByteArray a;
|
|
a.setRawData(image->data, image->length);
|
|
TQDataStream s(a, IO_ReadOnly);
|
|
m_parent.KWmf::parse(s, image->length);
|
|
a.resetRawData(image->data, image->length);
|
|
}
|
|
else
|
|
{
|
|
m_parent.gotPicture(
|
|
m_pib,
|
|
image->extension,
|
|
image->length,
|
|
image->data);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
kdError(s_area) << "Cannot handle IMsoBlip" << endl;
|
|
}
|
|
break;
|
|
case 262:
|
|
m_pibFlags = op.value;
|
|
break;
|
|
case 267:
|
|
m_pictureId = op.value;
|
|
break;
|
|
case 319:
|
|
m_fNoHitTestPicture = (op.value & 0x0008) != 0;
|
|
m_pictureGray = (op.value & 0x0004) != 0;
|
|
m_pictureBiLevel = (op.value & 0x0002) != 0;
|
|
m_pictureActive = (op.value & 0x0001) != 0;
|
|
break;
|
|
case 320:
|
|
m_geoLeft = op.value;
|
|
break;
|
|
case 321:
|
|
m_geoTop = op.value;
|
|
break;
|
|
case 322:
|
|
m_geoRight = op.value;
|
|
break;
|
|
case 323:
|
|
m_geoBottom = op.value;
|
|
break;
|
|
case 324:
|
|
m_shapePath = op.value;
|
|
break;
|
|
case 383:
|
|
m_fShadowOK = (op.value & 0x0020) != 0;
|
|
m_f3DOK = (op.value & 0x0010) != 0;
|
|
m_fLineOK = (op.value & 0x0008) != 0;
|
|
m_fGTextOK = (op.value & 0x0004) != 0;
|
|
m_fFillShadeShapeOK = (op.value & 0x0002) != 0;
|
|
m_fFillOK = (op.value & 0x0001) != 0;
|
|
break;
|
|
case 447:
|
|
m_fFilled = (op.value & 0x0010) != 0;
|
|
m_fHitTestFill = (op.value & 0x0008) != 0;
|
|
m_fillShape = (op.value & 0x0004) != 0;
|
|
m_fillUseRect = (op.value & 0x0002) != 0;
|
|
m_fNoFillHitTest = (op.value & 0x0001) != 0;
|
|
break;
|
|
case 448:
|
|
m_lineColor = op.value;
|
|
break;
|
|
case 450:
|
|
m_lineBackColor = op.value;
|
|
break;
|
|
case 452:
|
|
m_lineType = op.value;
|
|
break;
|
|
case 459:
|
|
m_lineWidth = op.value;
|
|
break;
|
|
case 511:
|
|
m_fArrowheadsOK = (op.value & 0x0010) != 0;
|
|
m_fLine = (op.value & 0x0008) != 0;
|
|
m_fHitTestLine = (op.value & 0x0004) != 0;
|
|
m_lineFillShape = (op.value & 0x0002) != 0;
|
|
m_fNoLineDrawDash = (op.value & 0x0001) != 0;
|
|
break;
|
|
case 772:
|
|
m_bWMode = op.value;
|
|
break;
|
|
case 831:
|
|
m_fOleIcon = (op.value & 0x0010) != 0;
|
|
m_fPreferRelativeResize = (op.value & 0x0008) != 0;
|
|
m_fLockShapeType = (op.value & 0x0004) != 0;
|
|
m_fDeleteAttachedObject = (op.value & 0x0002) != 0;
|
|
m_fBackground = (op.value & 0x0001) != 0;
|
|
break;
|
|
default:
|
|
unsupported = true;
|
|
kdWarning(s_area) << "unsupported simple option: " <<
|
|
op.opcode.fields.pid << endl;
|
|
break;
|
|
}
|
|
if (!unsupported)
|
|
kdDebug(s_area) << "simple option: " <<
|
|
op.opcode.fields.pid << endl;
|
|
}
|
|
|
|
// Now empty the list of complex options.
|
|
|
|
while (complexOpts.count())
|
|
{
|
|
TQ_INT16 t16;
|
|
unsigned i;
|
|
|
|
op = *complexOpts.getFirst();
|
|
complexOpts.removeFirst();
|
|
unsupported = false;
|
|
switch (op.opcode.fields.pid)
|
|
{
|
|
case 261:
|
|
while (true)
|
|
{
|
|
operands >> t16;
|
|
if (!t16)
|
|
break;
|
|
m_pibName += TQChar(t16);
|
|
};
|
|
break;
|
|
case 325:
|
|
m_pVertices = new TQPointArray(op.value / 4);
|
|
for (i = 0; i < m_pVertices->count(); i++)
|
|
{
|
|
m_pVertices->setPoint(i, m_parent.normalisePoint(operands));
|
|
};
|
|
break;
|
|
case 326:
|
|
operands >> t16;
|
|
i = t16;
|
|
operands >> t16;
|
|
operands >> t16;
|
|
m_parent.skip(i * t16, operands);
|
|
break;
|
|
default:
|
|
unsupported = true;
|
|
kdWarning(s_area) << "unsupported complex option: " <<
|
|
op.opcode.fields.pid << " operands: " << op.value << endl;
|
|
m_parent.skip(op.value, operands);
|
|
break;
|
|
}
|
|
if (!unsupported)
|
|
kdDebug(s_area) << "complex option: " <<
|
|
op.opcode.fields.pid << " operands: " << op.value << endl;
|
|
complexLength -= op.value;
|
|
}
|
|
}
|