37#include <xfigimport.h>
38#include <xfigimport.moc>
43#include <core/vdocument.h>
47#define RAD_FACTOR 180.0 / M_PI
49unsigned int colors[] = {
82 TQFont::Weight weight;
85 { "times", TQFont::Normal, false },
86 { "times", TQFont::Normal, true },
87 { "times", TQFont::Bold, false },
88 { "times", TQFont::Bold, true },
89 { "avantgarde", TQFont::Normal, false },
90 { "avantgarde", TQFont::Normal, true },
91 { "avantgarde", TQFont::DemiBold, false },
92 { "avantgarde", TQFont::DemiBold, true },
93 { "bookman", TQFont::Light, false },
94 { "bookman", TQFont::Light, true },
95 { "bookman", TQFont::DemiBold, false },
96 { "bookman", TQFont::DemiBold, true },
97 { "courier", TQFont::Normal, false },
98 { "courier", TQFont::Normal, true },
99 { "courier", TQFont::Bold, false },
100 { "courier", TQFont::Bold, true },
101 { "helvetica", TQFont::Normal, false },
102 { "helvetica", TQFont::Normal, true },
103 { "helvetica", TQFont::Bold, false },
104 { "helvetica", TQFont::Bold, true },
105 { "helvetica", TQFont::Normal, false },
106 { "helvetica", TQFont::Normal, true },
107 { "helvetica", TQFont::Bold, false },
108 { "helvetica", TQFont::Bold, true },
109 { "newcenturyschoolbook", TQFont::Normal, false },
110 { "newcenturyschoolbook", TQFont::Normal, true },
111 { "newcenturyschoolbook", TQFont::Bold, false },
112 { "newcenturyschoolbook", TQFont::Bold, true },
113 { "palatino", TQFont::Normal, false },
114 { "palatino", TQFont::Normal, true },
115 { "palatino", TQFont::Bold, false },
116 { "palatino", TQFont::Bold, true },
117 { "symbol", TQFont::Normal, false },
118 { "zapfchancery", TQFont::Normal, false },
119 { "zapfdingbats", TQFont::Normal, false },
122int hexstrToInt ( const char *str) {
123 const int fak[] = { 16, 1 };
126 for ( int i = 0; i < 2; i++) {
127 if (str[i] >= '0' && str[i] <= '9')
130 v = str[i] - 'a' + 10;
137XFIGImport::XFIGImport( KoFilter *parent, const char *name ) : KoFilter(parent, name)
139 fig_resolution = 1200.0 / 72.0;
140 coordinate_system = 2;
142 colorTable.insert (0, new TQColor (TQt::black));
143 colorTable.insert (1, new TQColor (TQt::blue));
144 colorTable.insert (2, new TQColor (TQt::green));
145 colorTable.insert (3, new TQColor (TQt::cyan));
146 colorTable.insert (4, new TQColor (TQt::red));
147 colorTable.insert (5, new TQColor (TQt::magenta));
148 colorTable.insert (6, new TQColor (TQt::yellow));
149 colorTable.insert (7, new TQColor (TQt::white));
151 for ( int i = 0; i <= 23; i++)
152 colorTable.insert (i + 8, new TQColor (colors[i]));
157XFIGImport::~XFIGImport()
161bool XFIGImport::filterImport( const TQString &file, KoDocument *doc,
162 const TQString &from, const TQString &to,
165 if( to != "application/x-karbon" || from != "image/x-xfig" )
172 ifstream fin( file.local8Bit() );
176 KIllustratorDocument *kidoc = (KIllustratorDocument *) doc;
177 GDocument *gdoc = kidoc->gdoc();
180 layout = gdoc->activePage()->pageLayout ();
182 fin.getline (buf, 255);
183 if (::strncmp (buf, "#FIG 3", 6)) {
184 kdDebug() << "ERROR: no xfig file or wrong header" << endl;
191 else if (buf[7] == '1') {
195 kdDebug() << "ERROR: unsupported xfig version" << endl;
204 fin.getline (buf, 255);
205 if (::strcmp (buf, "Landscape") == 0)
206 layout.orientation = PG_LANDSCAPE;
207 else if (::strcmp (buf, "Portrait") == 0)
208 layout.orientation = PG_PORTRAIT;
210 kdDebug() << "ERROR: invalid orientation" << endl;
213 fin.getline (buf, 255);
216 fin.getline (buf, 255);
217 if (::strcmp (buf, "Metric") == 0)
219 else if (::strcmp (buf, "Inches") == 0)
220 layout.unit = PG_INCH;
222 kdDebug() << "ERROR: invalid units" << endl;
224 if (version >= 320) {
226 fin.getline (buf, 255);
230 fin >> magnification;
231 fin.ignore (INT_MAX, '\n');
234 fin.getline (buf, 255);
239 fin.ignore (INT_MAX, '\n');
243 fin >> value >> coordinate_system;
244 fig_resolution = value / 72.0;
245 fin.ignore (INT_MAX, '\n');
248 while (! fin.eof ()) {
253 buildDocument (gdoc);
260 parseColorObject (fin);
264 parseEllipse (fin, gdoc);
268 parsePolyline (fin, gdoc);
272 parseSpline (fin, gdoc);
276 parseText (fin, gdoc);
280 parseArc (fin, gdoc);
284 parseCompoundObject (fin, gdoc);
291 kdDebug() << "unknown object type: " << tag << endl;
295 buildDocument (gdoc);
300void XFIGImport::parseColorObject (istream& fin) {
301 int number, red, green, blue;
302 char buf[20], red_str[3], green_str[3], blue_str[3];
304 fin >> number >> buf;
305 strncpy (red_str, &buf[1], 2); red_str[2] = '\0';
306 strncpy (green_str, &buf[3], 2); green_str[2] = '\0';
307 strncpy (blue_str, &buf[5], 2); blue_str[2] = '\0';
309 red = hexstrToInt (red_str);
310 green = hexstrToInt (green_str);
311 blue = hexstrToInt (blue_str);
313 colorTable.insert (number, new TQColor (red, green, blue));
316void XFIGImport::parseArc (istream& fin, GDocument* doc) {
317 int sub_type, line_style, thickness, pen_color, fill_color,
318 depth, pen_style, area_fill, cap_style, direction,
319 forward_arrow, backward_arrow, x1, y1, x2, y2, x3, y3;
320 float center_x, center_y;
322 GOval *obj = new GOval (doc);
325 fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
326 >> depth >> pen_style >> area_fill >> style_val >> cap_style
327 >> direction >> forward_arrow >> backward_arrow
328 >> center_x >> center_y >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
330 if (forward_arrow > 0) {
332 fin.ignore (INT_MAX, '\n');
335 if (backward_arrow > 0) {
337 fin.ignore (INT_MAX, '\n');
341 float dx = x1 - center_x;
342 float dy = y1 - center_y;
343 float radius = sqrt (dx * dx + dy * dy);
350 Coord p1 ((center_x - radius) / fig_resolution,
351 (center_y - radius) / fig_resolution);
352 Coord p2 ((center_x + radius) / fig_resolution,
353 (center_y + radius) / fig_resolution);
355 obj->setStartPoint (p1);
356 obj->setEndPoint (p2);
359 obj->setOutlineShape (GObject::OutlineInfo::PieShape);
360 else if (sub_type == 1)
361 obj->setOutlineShape (GObject::OutlineInfo::ArcShape);
363 p1 = Coord (center_x / fig_resolution, center_y /fig_resolution);
367 p2 = Coord (x1 / fig_resolution, y1 /fig_resolution);
368 if (p2.x () == p1.x ()) {
369 if (p2.y () > p1.y ())
375 m = ((p2.y () - p1.y ()) / (p2.x () - p1.x ()));
376 if ( p2.x () > p1.x ())
377 angle1 = atan (m) * RAD_FACTOR;
379 angle1 = 180 + atan (m) * RAD_FACTOR;
383 p2 = Coord (x3 / fig_resolution, y3 /fig_resolution);
384 if (p2.x () == p1.x ()) {
385 if (p2.y () > p1.y ())
391 m = ((p2.y () - p1.y ()) / (p2.x () - p1.x ()));
392 if ( p2.x () > p1.x ())
393 angle2 = atan (m) * RAD_FACTOR;
395 angle2 = 180 + atan (m) * RAD_FACTOR;
399 obj->setAngles (angle2, angle1);
400 else if (direction==1)
401 obj->setAngles (angle1, angle2);
404 setProperties (obj, pen_color, pen_style, thickness, area_fill, fill_color);
405 objList.append( GObjectListItem( depth, obj ) );
408void XFIGImport::parseEllipse (istream& fin, GDocument* doc) {
409 int sub_type, line_style, thickness, pen_color, fill_color,
410 depth, pen_style, area_fill, direction, center_x, center_y,
411 radius_x, radius_y, start_x, start_y, end_x, end_y;
412 float style_val, angle;
413 GOval *obj = new GOval (doc);
416 fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
417 >> depth >> pen_style >> area_fill >> style_val >> direction
418 >> angle >> center_x >> center_y >> radius_x >> radius_y
419 >> start_x >> start_y >> end_x >> end_y;
422 p1 = Coord ((center_x - radius_x) /fig_resolution,
423 (center_y - radius_y) /fig_resolution);
424 p2 = Coord ((center_x + radius_x) /fig_resolution,
425 (center_y + radius_y) /fig_resolution);
427 obj->setStartPoint (p1);
428 obj->setEndPoint (p2);
431 setProperties (obj, pen_color, pen_style, thickness, area_fill, fill_color);
432 objList.append( GObjectListItem( depth, obj ) );
435void XFIGImport::parsePolyline (istream& fin, GDocument* doc) {
436 int sub_type, line_style, thickness, pen_color, fill_color,
437 depth, pen_style, area_fill, join_style, cap_style, radius,
438 forward_arrow, backward_arrow, npoints;
440 GPolyline *obj = NULL;
443 fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
444 >> depth >> pen_style >> area_fill >> style_val >> join_style
445 >> cap_style >> radius >> forward_arrow >> backward_arrow
447 fin.ignore (INT_MAX, '\n');
451 obj = new GPolyline (doc);
454 obj = new GPolygon (doc);
457 obj = new GPolygon (doc);
460 obj = new GPolygon (doc);
467 kdDebug() << "unknown subtype: " << sub_type << endl;
471 assert (obj != NULL);
473 int arrow_type, arrow_style;
474 float arrow_thickness, arrow_width, arrow_height;
475 GObject::OutlineInfo oinfo;
476 oinfo.mask = GObject::OutlineInfo::Custom;
477 oinfo.startArrowId = oinfo.endArrowId = 0;
479 if (forward_arrow > 0) {
482 fin >> arrow_type >> arrow_style >> arrow_thickness
483 >> arrow_width >> arrow_height;
484 oinfo.endArrowId = arrow_ids[arrow_type];
485 if (oinfo.endArrowId == 1 && arrow_style == 0)
486 oinfo.endArrowId = 4;
487 fin.ignore (INT_MAX, '\n');
490 if (backward_arrow > 0) {
492 fin >> arrow_type >> arrow_style >> arrow_thickness
493 >> arrow_width >> arrow_height;
494 oinfo.startArrowId = arrow_ids[arrow_type];
495 if (oinfo.startArrowId == 1 && arrow_style == 0)
496 oinfo.startArrowId = 4;
497 fin.ignore (INT_MAX, '\n');
500 for ( int i = 0; i < npoints; i++) {
503 if ((sub_type == 2 || sub_type == 3) && i == npoints -1)
507 Coord p (x / fig_resolution, y / fig_resolution);
508 obj->_addPoint (i, p);
511 if (oinfo.startArrowId || oinfo.endArrowId)
512 obj->setOutlineInfo (oinfo);
515 setProperties (obj, pen_color, line_style, thickness, area_fill, fill_color);
518 objList.append( GObjectListItem( depth, obj ) );
521void XFIGImport::parseSpline (istream& fin, GDocument* doc)
523 int sub_type, line_style, thickness, pen_color, fill_color, depth,
524 pen_style, area_fill, cap_style, forward_arrow, backward_arrow, npoints;
529 fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
530 >> depth >> pen_style >> area_fill >> style_val >> cap_style
531 >> forward_arrow >> backward_arrow >> npoints;
532 if (sub_type == 1 || sub_type == 3 || sub_type == 5)
533 obj = new GPolygon (doc);
535 obj = new GPolyline (doc);
537 int arrow_type, arrow_style;
538 float arrow_thickness, arrow_width, arrow_height;
539 GObject::OutlineInfo oinfo;
540 oinfo.mask = GObject::OutlineInfo::Custom;
541 oinfo.startArrowId = oinfo.endArrowId = 0;
543 if (forward_arrow > 0) {
546 fin >> arrow_type >> arrow_style >> arrow_thickness
547 >> arrow_width >> arrow_height;
548 oinfo.endArrowId = arrow_ids[arrow_type];
549 if (oinfo.endArrowId == 1 && arrow_style == 0)
550 oinfo.endArrowId = 4;
551 fin.ignore (INT_MAX, '\n');
554 if (backward_arrow > 0) {
556 fin >> arrow_type >> arrow_style >> arrow_thickness
557 >> arrow_width >> arrow_height;
558 oinfo.startArrowId = arrow_ids[arrow_type];
559 if (oinfo.startArrowId == 1 && arrow_style == 0)
560 oinfo.startArrowId = 4;
561 fin.ignore (INT_MAX, '\n');
565 for ( int i = 0; i < npoints; i++) {
568 if ((sub_type == 1 || sub_type == 3 || sub_type == 5) && i == npoints -1)
572 Coord p (x / fig_resolution, y / fig_resolution);
573 obj->_addPoint (i, p);
577 for ( int i = 0; i < npoints; i++) {
584 if (oinfo.startArrowId || oinfo.endArrowId)
585 obj->setOutlineInfo (oinfo);
588 setProperties (obj, pen_color, line_style, thickness, area_fill, fill_color);
591 objList.append( GObjectListItem( depth, obj ) );
594void XFIGImport::parseText (istream& fin, GDocument* doc)
596 int sub_type, color, depth, pen_style, font, font_flags, x, y;
597 float font_size, angle, height, length;
598 GText *obj = new GText (doc);
601 bool finished = false;
605 fin >> sub_type >> color >> depth >> pen_style >> font >> font_size
606 >> angle >> font_flags >> height >> length >> x >> y;
608 if (font_flags & 4) {
612 qfont = TQFont (psFontTable[font].family, tqRound (font_size),
613 psFontTable[font].weight, psFontTable[font].italic);
619 qfont.setFamily ( "times");
622 qfont.setBold ( true);
625 qfont.setItalic ( true);
628 qfont.setFamily ( "helvetica");
631 qfont.setFamily ( "Courier");
637 qfont.setPointSize (tqRound (font_size));
638 obj->setFont (qfont);
644 int code = (ocode[0] - '0') * 64 +
645 (ocode[1] - '0') * 8 +
658 GText::TextInfo ti = obj->getTextInfo ();
659 ti.align = GText::TextInfo::AlignCenter;
660 obj->setTextInfo (ti);
662 else if (sub_type == 2) {
663 GText::TextInfo ti = obj->getTextInfo ();
664 ti.align = GText::TextInfo::AlignRight;
665 obj->setTextInfo (ti);
667 Coord origin (x / fig_resolution, y / fig_resolution - qfont.pointSize ());
668 obj->setOrigin (origin);
672 float nangle = angle * RAD_FACTOR;
673 TQWMatrix m1, m2, m3;
677 rotCenter = Coord (obj->boundingBox ().left (),
678 obj->boundingBox ().bottom ());
680 else if (sub_type == 1) {
681 rotCenter = Coord (obj->boundingBox ().width () / 2,
682 obj->boundingBox ().bottom ());
684 else if (sub_type == 2) {
685 rotCenter = Coord (obj->boundingBox ().right (),
686 obj->boundingBox ().bottom ());
688 m1.translate (-rotCenter.x (), -rotCenter.y ());
690 m3.translate (rotCenter.x (), rotCenter.y ());
693 obj->transform (m3, true);
696 objList.append( GObjectListItem( depth, obj ) );
699void XFIGImport::parseCompoundObject (istream& fin, GDocument* ) {
700 int upperright_x, upperright_y, lowerleft_x, lowerleft_y;
702 fin >> upperright_x >> upperright_y >> lowerleft_x >> lowerleft_y;
703 fin.ignore (INT_MAX, '\n');
710void XFIGImport::buildDocument (GDocument *doc) {
711 doc->setAutoUpdate ( false);
713 qBubbleSort(objList);
716 TQValueList<GObjectListItem>::Iterator it=objList.begin();
717 for ( ; it != objList.end() ; ++it )
720 GObject* obj = (*it).object;
722 doc->activePage()->insertObject (obj);
724 doc->setAutoUpdate ( true);
728void XFIGImport::setProperties (GObject* obj, int pen_color, int style,
729 int thickness, int area_fill, int fill_color) {
731 obj->setOutlineColor (*colorTable[pen_color]);
734 obj->setOutlineStyle (TQt::SolidLine);
736 obj->setOutlineStyle (TQt::DashLine);
738 obj->setOutlineStyle (TQt::DotLine);
740 obj->setOutlineWidth (thickness * 72.0 / 80.0);
743 obj->setFillStyle (GObject::FillInfo::NoFill);
745 obj->setFillStyle (GObject::FillInfo::SolidFill);
746 if (fill_color < 1) {
748 int val = tqRound ((20 - area_fill) * 255.0 / 20.0);
749 obj->setFillColor (TQColor (val, val, val));
751 else if (fill_color == 7) {
753 int val = tqRound ( area_fill * 255.0 / 20.0);
754 obj->setFillColor (TQColor (val, val, val));
757 obj->setFillColor (*colorTable[fill_color]);
|