30#include <tqpointarray.h>
34#define PI (3.14159265358979323846)
36const int KWmf::s_area = 30504;
37const int KWmf::s_maxHandles = 64;
43 m_objectHandles = new WinObjHandle*[s_maxHandles];
48 delete[] m_objectHandles;
59 m_dc.m_brushColour = colour;
60 m_dc.m_brushStyle = style;
64unsigned KWmf::getColour(
67 unsigned red, green, blue;
70 green = (colour >> 8) & 255;
71 blue = (colour >> 16) & 255;
72 return (red << 16) + (green << 8) + blue;
77 TQDataStream &operands)
84 topLeft = normalisePoint(operands);
85 bottomRight = normalisePoint(operands);
86 start = normalisePoint(operands);
87 end = normalisePoint(operands);
93 TQRect ellipse(topLeft, bottomRight);
94 TQPoint centre = ellipse.center();
95 double startAngle = atan2(( double)(centre.y() - start.y()), ( double)(centre.x() - start.x()));
96 double stopAngle = atan2(( double)(centre.y() - end.y()), ( double)(centre.x() - end.x()));
98 startAngle = 180 * startAngle / PI;
99 stopAngle = 180 * stopAngle / PI;
101 gotEllipse(m_dc, type, centre, ellipse.size() / 2,
102 static_cast<unsigned int>(startAngle),
103 static_cast<unsigned int>(stopAngle));
106int KWmf::handleIndex( void) const
110 for (i = 0; i < s_maxHandles; i++)
112 if (!m_objectHandles[i])
115 kdError(s_area) << "handle table full !" << endl;
120KWmf::WinObjPenHandle *KWmf::handleCreatePen( void)
122 WinObjPenHandle *handle = new WinObjPenHandle;
123 int idx = handleIndex();
126 m_objectHandles[idx] = handle;
131KWmf::WinObjBrushHandle *KWmf::handleCreateBrush( void)
133 WinObjBrushHandle *handle = new WinObjBrushHandle;
134 int idx = handleIndex();
137 m_objectHandles[idx] = handle;
142void KWmf::handleDelete( int idx)
144 if (idx >= 0 && idx < s_maxHandles && m_objectHandles[idx])
146 delete m_objectHandles[idx];
147 m_objectHandles[idx] = NULL;
155void KWmf::invokeHandler(
158 TQDataStream &operands)
160 typedef void (KWmf::*method)(U32 words, TQDataStream &operands);
165 unsigned short opcode;
169 static const opcodeEntry funcTab[] =
171 { "ANIMATEPALETTE", 0x0436, 0 },
172 { "ARC", 0x0817, &KWmf::opArc },
173 { "BITBLT", 0x0922, 0 },
174 { "CHORD", 0x0830, 0 },
175 { "CREATEBRUSHINDIRECT", 0x02FC, &KWmf::opBrushCreateIndirect },
176 { "CREATEFONTINDIRECT", 0x02FB, 0 },
177 { "CREATEPALETTE", 0x00F7, 0 },
178 { "CREATEPATTERNBRUSH", 0x01F9, 0 },
179 { "CREATEPENINDIRECT", 0x02FA, &KWmf::opPenCreateIndirect },
180 { "CREATEREGION", 0x06FF, 0 },
181 { "DELETEOBJECT", 0x01F0, &KWmf::opObjectDelete },
182 { "DIBBITBLT", 0x0940, 0 },
183 { "DIBCREATEPATTERNBRUSH",0x0142, 0 },
184 { "DIBSTRETCHBLT", 0x0b41, 0 },
185 { "ELLIPSE", 0x0418, &KWmf::opEllipse },
186 { "ESCAPE", 0x0626, &KWmf::opNoop },
187 { "EXCLUDECLIPRECT", 0x0415, 0 },
188 { "EXTFLOODFILL", 0x0548, 0 },
189 { "EXTTEXTOUT", 0x0a32, 0 },
190 { "FILLREGION", 0x0228, 0 },
191 { "FLOODFILL", 0x0419, 0 },
192 { "FRAMEREGION", 0x0429, 0 },
193 { "INTERSECTCLIPRECT", 0x0416, 0 },
194 { "INVERTREGION", 0x012A, 0 },
195 { "LINETO", 0x0213, &KWmf::opLineTo },
196 { "MOVETO", 0x0214, &KWmf::opMoveTo },
197 { "OFFSETCLIPRGN", 0x0220, 0 },
198 { "OFFSETVIEWPORTORG", 0x0211, 0 },
199 { "OFFSETWINDOWORG", 0x020F, 0 },
200 { "PAINTREGION", 0x012B, 0 },
201 { "PATBLT", 0x061D, 0 },
202 { "PIE", 0x081A, &KWmf::opPie },
203 { "POLYGON", 0x0324, &KWmf::opPolygon },
204 { "POLYLINE", 0x0325, &KWmf::opPolyline },
205 { "POLYPOLYGON", 0x0538, 0 },
206 { "REALIZEPALETTE", 0x0035, 0 },
207 { "RECTANGLE", 0x041B, &KWmf::opRectangle },
208 { "RESIZEPALETTE", 0x0139, 0 },
209 { "RESTOREDC", 0x0127, &KWmf::opRestoreDc },
210 { "ROUNDRECT", 0x061C, 0 },
211 { "SAVEDC", 0x001E, &KWmf::opSaveDc },
212 { "SCALEVIEWPORTEXT", 0x0412, 0 },
213 { "SCALEWINDOWEXT", 0x0410, 0 },
214 { "SELECTCLIPREGION", 0x012C, 0 },
215 { "SELECTOBJECT", 0x012D, &KWmf::opObjectSelect },
216 { "SELECTPALETTE", 0x0234, 0 },
217 { "SETBKCOLOR", 0x0201, 0 },
218 { "SETBKMODE", 0x0102, 0 },
219 { "SETDIBTODEV", 0x0d33, 0 },
220 { "SETMAPMODE", 0x0103, 0 },
221 { "SETMAPPERFLAGS", 0x0231, 0 },
222 { "SETPALENTRIES", 0x0037, 0 },
223 { "SETPIXEL", 0x041F, 0 },
224 { "SETPOLYFILLMODE", 0x0106, &KWmf::opPolygonSetFillMode },
225 { "SETRELABS", 0x0105, 0 },
226 { "SETROP2", 0x0104, 0 },
227 { "SETSTRETCHBLTMODE", 0x0107, 0 },
228 { "SETTEXTALIGN", 0x012E, 0 },
229 { "SETTEXTCHAREXTRA", 0x0108, 0 },
230 { "SETTEXTCOLOR", 0x0209, 0 },
231 { "SETTEXTJUSTIFICATION", 0x020A, 0 },
232 { "SETVIEWPORTEXT", 0x020E, 0 },
233 { "SETVIEWPORTORG", 0x020D, 0 },
234 { "SETWINDOWEXT", 0x020C, &KWmf::opWindowSetExt },
235 { "SETWINDOWORG", 0x020B, &KWmf::opWindowSetOrg },
236 { "STRETCHBLT", 0x0B23, 0 },
237 { "STRETCHDIB", 0x0f43, 0 },
238 { "TEXTOUT", 0x0521, 0 },
246 for (i = 0; funcTab[i].name; i++)
248 if (funcTab[i].opcode == opcode)
256 result = funcTab[i].handler;
260 kdError(s_area) << "invokeHandler: unsupported opcode: " <<
262 " operands: " << words << endl;
264 kdError(s_area) << "invokeHandler: unsupported opcode: 0x" <<
265 TQString::number(opcode, 16) <<
266 " operands: " << words << endl;
270 for (i = 0; i < words; i++)
279 kdDebug(s_area) << "invokeHandler: opcode: " << funcTab[i].name <<
280 " operands: " << words << endl;
290 TQByteArray *record = new TQByteArray(words * 2);
293 operands.readRawBytes(record->data(), words * 2);
294 body = new TQDataStream(*record, IO_ReadOnly);
295 body->setByteOrder(TQDataStream::LittleEndian);
296 (this->*result)(words, *body);
302 TQDataStream *body = new TQDataStream();
304 (this->*result)(words, *body);
310TQPoint KWmf::normalisePoint(
311 TQDataStream &operands)
317 return TQPoint((x - m_windowOrgX) * m_windowFlipX / m_dpi, (y - m_windowOrgY) * m_windowFlipY / m_dpi);
320TQSize KWmf::normaliseSize(
321 TQDataStream &operands)
326 operands >> width >> height;
327 return TQSize(width / m_dpi, height / m_dpi);
331 const TQString &file)
334 if (!in.open(IO_ReadOnly))
336 kdError(s_area) << "Unable to open input file!" << endl;
340 TQDataStream stream(&in);
341 bool result = parse(stream, in.size());
347 TQDataStream &stream,
354 startedAt = stream.device()->at();
355 stream.setByteOrder(TQDataStream::LittleEndian);
357 for ( int i = 0; i < s_maxHandles; i++)
358 m_objectHandles[i] = NULL;
388 struct WmfEnhMetaHeader
409 SIZEL szlMillimeters;
411 #define ENHMETA_SIGNATURE 0x464D4520
424 struct WmfPlaceableHeader
433 #define APMHEADER_KEY 0x9AC6CDD7L
435 WmfPlaceableHeader pheader;
436 WmfEnhMetaHeader eheader;
437 WmfMetaHeader header;
443 stream >> pheader.key;
444 isPlaceable = (pheader.key == (S32)APMHEADER_KEY);
447 stream >> pheader.hmf;
448 stream >> pheader.bbox.left;
449 stream >> pheader.bbox.top;
450 stream >> pheader.bbox.right;
451 stream >> pheader.bbox.bottom;
452 stream >> pheader.inch;
453 stream >> pheader.reserved;
454 stream >> pheader.checksum;
456 S16 *ptr = (S16 *)&pheader;
460 for ( unsigned i = 0; i < sizeof(WmfPlaceableHeader)/ sizeof(S16); i++)
464 if (pheader.checksum != checksum)
466 m_dpi = (unsigned)(( double)pheader.inch / m_dpi);
467 m_windowOrgX = pheader.bbox.left;
468 m_windowOrgY = pheader.bbox.top;
469 if (pheader.bbox.right > pheader.bbox.left)
473 if (pheader.bbox.bottom > pheader.bbox.top)
480 stream.device()->at(startedAt);
481 m_dpi = (unsigned)(( double)576 / m_dpi);
490 fileAt = stream.device()->at();
491 stream >> eheader.iType;
492 stream >> eheader.nSize;
493 stream >> eheader.rclBounds.left;
494 stream >> eheader.rclBounds.top;
495 stream >> eheader.rclBounds.right;
496 stream >> eheader.rclBounds.bottom;
497 stream >> eheader.rclFrame.left;
498 stream >> eheader.rclFrame.top;
499 stream >> eheader.rclFrame.right;
500 stream >> eheader.rclFrame.bottom;
501 stream >> eheader.dSignature;
502 isEnhanced = (eheader.dSignature == ENHMETA_SIGNATURE);
505 stream >> eheader.nVersion;
506 stream >> eheader.nBytes;
507 stream >> eheader.nRecords;
508 stream >> eheader.nHandles;
509 stream >> eheader.sReserved;
510 stream >> eheader.nDescription;
511 stream >> eheader.offDescription;
512 stream >> eheader.nPalEntries;
513 stream >> eheader.szlDevice.width;
514 stream >> eheader.szlDevice.height;
515 stream >> eheader.szlMillimeters.width;
516 stream >> eheader.szlMillimeters.height;
518 kdError(s_area) << "WMF Extended Header NOT YET IMPLEMENTED, SORRY." << endl;
542 stream.device()->at(fileAt);
543 stream >> header.mtType;
544 stream >> header.mtHeaderSize;
545 stream >> header.mtVersion;
546 stream >> header.mtSize;
547 stream >> header.mtNoObjects;
548 stream >> header.mtMaxRecord;
549 stream >> header.mtNoParameters;
561 walk((size - (stream.device()->at() - startedAt)) / 2, stream);
567 TQDataStream &operands)
569 genericArc( "arc", operands);
572void KWmf::opBrushCreateIndirect(
574 TQDataStream &operands)
576 static TQt::BrushStyle hatchedStyleTab[] =
582 TQt::DiagCrossPattern
584 static TQt::BrushStyle styleTab[] =
596 TQt::BrushStyle style;
597 WinObjBrushHandle *handle = handleCreateBrush();
602 operands >> arg >> colour;
603 handle->m_colour = getColour(colour);
607 if (arg >= 0 && arg < 6)
609 style = hatchedStyleTab[arg];
613 kdError(s_area) << "createBrushIndirect: invalid hatched brush " << arg << endl;
614 style = TQt::SolidPattern;
618 if (arg >= 0 && arg < 9)
620 style = styleTab[arg];
625 kdError(s_area) << "createBrushIndirect: invalid brush " << arg << endl;
626 style = TQt::SolidPattern;
629 handle->m_style = style;
634 TQDataStream &operands)
639 topLeft = normalisePoint(operands);
640 bottomRight = normalisePoint(operands);
642 TQRect ellipse(topLeft, bottomRight);
644 gotEllipse(m_dc, "full", ellipse.center(), ellipse.size() / 2, 0, 0);
649 TQDataStream &operands)
653 lineTo = normalisePoint(operands);
654 TQPointArray points(2);
655 points.setPoint(0, m_lineFrom);
656 points.setPoint(1, lineTo);
657 gotPolyline(m_dc, points);
666 TQDataStream &operands)
668 m_lineFrom = normalisePoint(operands);
673 TQDataStream &operands)
675 skip(words, operands);
679void KWmf::opObjectDelete(
681 TQDataStream &operands)
690void KWmf::opObjectSelect(
692 TQDataStream &operands)
697 if (idx >= 0 && idx < s_maxHandles && m_objectHandles[idx])
698 m_objectHandles[idx]->apply(* this);
705void KWmf::opPenCreateIndirect(
707 TQDataStream &operands)
709 static TQt::PenStyle styleTab[] =
721 WinObjPenHandle *handle = handleCreatePen();
726 if (arg >= 0 && arg < 8)
728 handle->m_style = styleTab[arg];
732 kdError(s_area) << "createPenIndirect: invalid pen " << arg << endl;
733 handle->m_style = TQt::SolidLine;
736 handle->m_width = arg;
737 operands >> arg >> colour;
738 handle->m_colour = getColour(colour);
743 TQDataStream &operands)
745 genericArc( "pie", operands);
748void KWmf::opPolygonSetFillMode(
750 TQDataStream &operands)
755 m_dc.m_winding = tmp != 0;
760 TQDataStream &operands)
765 TQPointArray points(tmp);
767 for ( int i = 0; i < tmp; i++)
769 points.setPoint(i, normalisePoint(operands));
771 gotPolygon(m_dc, points);
774void KWmf::opPolyline(
776 TQDataStream &operands)
781 TQPointArray points(tmp);
783 for ( int i = 0; i < tmp; i++)
785 points.setPoint(i, normalisePoint(operands));
787 gotPolyline(m_dc, points);
790void KWmf::opRectangle(
792 TQDataStream &operands)
797 topLeft = normalisePoint(operands);
798 size = normaliseSize(operands);
799 TQRect rect(topLeft, size);
800 TQPointArray points(4);
802 points.setPoint(0, topLeft);
803 points.setPoint(1, rect.topRight());
804 points.setPoint(2, rect.bottomRight());
805 points.setPoint(3, rect.bottomLeft());
806 gotRectangle(m_dc, points);
809void KWmf::opRestoreDc(
811 TQDataStream &operands)
817 for (i = 0; i < pop; i++)
819 m_dc = m_savedDcs.pop();
827 m_savedDcs.push(m_dc);
832void KWmf::opWindowSetOrg(
834 TQDataStream &operands)
839 operands >> top >> left;
844void KWmf::opWindowSetExt(
846 TQDataStream &operands)
851 operands >> height >> width;
867 m_dc.m_penColour = colour;
868 m_dc.m_penStyle = style;
869 m_dc.m_penWidth = width;
874 TQDataStream &operands)
878 kdError(s_area) << "skip: " << (int)words << endl;
886 kdDebug(s_area) << "skip: " << words << endl;
887 for (i = 0; i < words; i++)
896 TQDataStream &operands)
918 while (length < words)
920 operands >> wordCount;
924 if (length + wordCount > words)
926 wordCount = words - length;
937 invokeHandler(opcode, wordCount - 3, operands);
941 skip(words - length, operands);
944KWmf::DrawContext::DrawContext()
947 m_brushColour = 0x808080;
949 m_penColour = 0x808080;
954void KWmf::WinObjBrushHandle::apply(
957 p.brushSet(m_colour, m_style);
960void KWmf::WinObjPenHandle::apply(
963 p.penSet(m_colour, m_style, m_width);
const char * name(StdAction id)
|