Source Code (Use browser search to find items of interest.)

Class Index

killustrator'XfigImport (./koffice/killustrator/filter/XfigImport.h:34)

class XfigImport : public ImportFilter {
public:
  XfigImport ();
  ~XfigImport ();

  bool setup (GDocument* doc, const char* format);
  bool importFromFile (GDocument *doc);

private:
  void parseColorObject (istream& fin);
  void parseArc (istream& fin, GDocument* doc);
  void parseEllipse (istream& fin, GDocument* doc);
  void parsePolyline (istream& fin, GDocument* doc);
  void parseSpline (istream& fin, GDocument* doc);
  void parseText (istream& fin, GDocument* doc);
  void parseCompoundObject (istream& fin, GDocument* doc);
  void buildDocument (GDocument *doc);

  void setProperties (GObject* obj, int pen_color, int style, int thickness,
		      int area_fill, int fill_color);

  float fig_resolution;
  int coordinate_system;
  int version;
  QIntDict<QColor> colorTable;
  
  list<std::pair<int, GObject*> > objList;
};
  

killustrator'XfigImport::XfigImport() (./koffice/killustrator/filter/XfigImport.cc:129)

XfigImport::XfigImport () {
}


killustrator'XfigImport::~XfigImport() (./koffice/killustrator/filter/XfigImport.cc:132)

XfigImport::~XfigImport () {
}


killustrator'XfigImport::setup() (./koffice/killustrator/filter/XfigImport.cc:135)

bool XfigImport::setup (GDocument* , const char* /*format*/) {
  fig_resolution = 1200.0 / 72.0;
  coordinate_system = 2;

  colorTable.insert (0, new QColor (QT_PRFX::black));
  colorTable.insert (1, new QColor (QT_PRFX::blue));
  colorTable.insert (2, new QColor (QT_PRFX::green));
  colorTable.insert (3, new QColor (QT_PRFX::cyan));
  colorTable.insert (4, new QColor (QT_PRFX::red));
  colorTable.insert (5, new QColor (QT_PRFX::magenta));
  colorTable.insert (6, new QColor (QT_PRFX::yellow));
  colorTable.insert (7, new QColor (QT_PRFX::white));

  for (int i = 0; i <= 23; i++)
      colorTable.insert (i + 8, new QColor (colors[i]));

  objList.clear ();

  return true;
}


killustrator'XfigImport::importFromFile() (./koffice/killustrator/filter/XfigImport.cc:156)

bool XfigImport::importFromFile (GDocument *doc) {
  char buf[255];
  int value;
  KoPageLayout layout;

  ifstream fin (inputFileName ());
  if (! fin)
    return false;

  layout = doc->pageLayout ();

  fin.getline (buf, 255);
  if (::strncmp (buf, "#FIG 3", 6)) {
    cerr << "ERROR: no xfig file or wrong header" << endl;
    return false;
  }

  if (buf[7] == '2') {
      version = 320;
  }
  else if (buf[7] == '1') {
      version = 310;
  }
  else {
    cerr << "ERROR: unsupported xfig version" << endl;
    return false;
  }

  /*
   * read the header
   */

  // orientation
  fin.getline (buf, 255);
  if (::strcmp (buf, "Landscape") == 0)
      layout.orientation = PG_LANDSCAPE;
  else if (::strcmp (buf, "Portrait") == 0)
      layout.orientation = PG_PORTRAIT;
  else
      cerr << "ERROR: invalid orientation" << endl;

  // justification (don't know how to handle this)
  fin.getline (buf, 255);

  // units
  fin.getline (buf, 255);
  if (::strcmp (buf, "Metric") == 0)
      layout.unit = PG_MM;
  else if (::strcmp (buf, "Inches") == 0)
      layout.unit = PG_INCH;
  else
      cerr << "ERROR: invalid units" << endl;

  if (version >= 320) {
      // paper size (don't know how to handle this)
      fin.getline (buf, 255);

      // magnification
      float magnification;
      fin >> magnification;
      fin.ignore (INT_MAX, '\n');

      //multiple page (not supported yet)
      fin.getline (buf, 255);

      // transparent color (not supported yet)
      int transColor;
      fin >> transColor;
      fin.ignore (INT_MAX, '\n');
  }

  // resolution and coordinate system
  fin >> value >> coordinate_system;
  fig_resolution = value / 72.0;
  fin.ignore (INT_MAX, '\n');

  // now read in the objects
  while (! fin.eof ()) {
    int tag = -1;
    fin >> tag;
    if (tag == -1) {
      // EOF
      buildDocument (doc);
      return true;
    }

    switch (tag) {
    case 0:
      // a color pseudo object
      parseColorObject (fin);
      break;
    case 1:
      // a ellipse
      parseEllipse (fin, doc);
      break;
    case 2:
      // a polyline
      parsePolyline (fin, doc);
      break;
    case 3:
      // a spline
      parseSpline (fin, doc);
      break;
    case 4:
      // a text
      parseText (fin, doc);
      break;
    case 5:
      // an arc
      parseArc (fin, doc);
      break;
    case 6:
      // a compound object
      parseCompoundObject (fin, doc);
      break;
    case -6:
      // end of compound object --> ignore it
      break;
    default:
      // should not occur
      cerr << "unknown object type: " << tag << endl;
      break;
    }
  }
  buildDocument (doc);
  return true;
}


killustrator'XfigImport::parseColorObject() (./koffice/killustrator/filter/XfigImport.cc:284)

void XfigImport::parseColorObject (istream& fin) {
    int number, red, green, blue;
    char buf[20], red_str[3], green_str[3], blue_str[3];

    fin >> number >> buf;
    strncpy (red_str, &buf[1], 2); red_str[2] = '\0';
    strncpy (green_str, &buf[3], 2); green_str[2] = '\0';
    strncpy (blue_str, &buf[5], 2); blue_str[2] = '\0';

    red = hexstrToInt (red_str);
    green = hexstrToInt (green_str);
    blue = hexstrToInt (blue_str);

    colorTable.insert (number, new QColor (red, green, blue));
}


killustrator'XfigImport::parseArc() (./koffice/killustrator/filter/XfigImport.cc:300)

void XfigImport::parseArc (istream& fin, GDocument* ) {
  int sub_type, line_style, thickness, pen_color, fill_color,
    depth, pen_style, area_fill, cap_style, direction,
    forward_arrow, backward_arrow, x1, y1, x2, y2, x3, y3;
  float center_x, center_y;
  float style_val;
  GOval *obj = new GOval ();

  // first line
  fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
      >> depth >> pen_style >> area_fill >> style_val >> cap_style
      >> direction >> forward_arrow >> backward_arrow
      >> center_x >> center_y >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;

  if (forward_arrow > 0) {
    // forward arow line
    fin.ignore (INT_MAX, '\n');
  }

  if (backward_arrow > 0) {
    // backward arrow line
    fin.ignore (INT_MAX, '\n');
  }

  // compute radius
  float dx = x1 - center_x;
  float dy = y1 - center_y;
  float radius = sqrt (dx * dx + dy * dy);

  if (radius==0) {
    delete obj;
    return;
  }

  Coord p1 ((center_x - radius) / fig_resolution,
	    (center_y - radius) / fig_resolution);
  Coord p2 ((center_x + radius) / fig_resolution,
	    (center_y + radius) / fig_resolution);

  obj->setStartPoint (p1);
  obj->setEndPoint (p2);

  if (sub_type == 0)
      obj->setOutlineShape (GObject::OutlineInfo::PieShape);
  else if (sub_type == 1)
      obj->setOutlineShape (GObject::OutlineInfo::ArcShape);

  p1 = Coord (center_x / fig_resolution, center_y /fig_resolution);
  float m;

  float angle1;
  p2 = Coord (x1 / fig_resolution, y1 /fig_resolution);
  if (p2.x () == p1.x ()) {
    if (p2.y () > p1.y ()) 
      angle1 = 90;
    else
      angle1 = -90;
  }
  else {
    m = ((p2.y () - p1.y ()) / (p2.x () - p1.x ()));
    if ( p2.x () > p1.x ())
      angle1 = atan (m) * RAD_FACTOR;
    else
      angle1 = 180 + atan (m) * RAD_FACTOR;
  }

  float angle2;
  p2 = Coord (x3 / fig_resolution, y3 /fig_resolution);
  if (p2.x () == p1.x ()) {
    if (p2.y () > p1.y ()) 
      angle2 = 90;
    else
      angle2 = -90;
  }
  else {
    m = ((p2.y () - p1.y ()) / (p2.x () - p1.x ()));
    if ( p2.x () > p1.x ())
      angle2 = atan (m) * RAD_FACTOR;
    else
      angle2 = 180 + atan (m) * RAD_FACTOR;
  }

  if (direction==0) // clockwise
    obj->setAngles (angle2, angle1);
  else if (direction==1) // counterclockwise 
    obj->setAngles (angle1, angle2);

  // now set the properties
  setProperties (obj, pen_color, pen_style, thickness, area_fill, fill_color);

  objList.push_back (pair<int, GObject*> (depth, obj));
}


killustrator'XfigImport::parseEllipse() (./koffice/killustrator/filter/XfigImport.cc:393)

void XfigImport::parseEllipse (istream& fin, GDocument* ) {
  int sub_type, line_style, thickness, pen_color, fill_color,
    depth, pen_style, area_fill, direction, center_x, center_y,
    radius_x, radius_y, start_x, start_y, end_x, end_y;
  float style_val, angle;
  GOval *obj = new GOval ();

  // first line
  fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
      >> depth >> pen_style >> area_fill >> style_val >> direction
      >> angle >> center_x >> center_y >> radius_x >> radius_y
      >> start_x >> start_y >> end_x >> end_y;
  Coord p1, p2;

  p1 = Coord ((center_x - radius_x) /fig_resolution,
	      (center_y - radius_y) /fig_resolution);
  p2 = Coord ((center_x + radius_x) /fig_resolution,
	      (center_y + radius_y) /fig_resolution);

  obj->setStartPoint (p1);
  obj->setEndPoint (p2);

  // now set the properties
  setProperties (obj, pen_color, pen_style, thickness, area_fill, fill_color);

  objList.push_back (pair<int, GObject*> (depth, obj));
}


killustrator'XfigImport::parsePolyline() (./koffice/killustrator/filter/XfigImport.cc:421)

void XfigImport::parsePolyline (istream& fin, GDocument* ) {
  int sub_type, line_style, thickness, pen_color, fill_color,
    depth, pen_style, area_fill, join_style, cap_style, radius,
    forward_arrow, backward_arrow, npoints;
  float style_val;
  GPolyline *obj = NULL;

  // first line
  fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
      >> depth >> pen_style >> area_fill >> style_val >> join_style
      >> cap_style >> radius >> forward_arrow >> backward_arrow
      >> npoints;
  fin.ignore (INT_MAX, '\n');

  switch (sub_type) {
  case 1: // polyline
    obj = new GPolyline ();
    break;
  case 2: // box
    obj = new GPolygon ();
    break;
  case 3: // polygon
    obj = new GPolygon ();
    break;
  case 4: // arc-box
    obj = new GPolygon ();
    break;
  case 5: // imported picture
    return;
    break;
  default:
    // doesn't occur
    cout << "unknown subtype: " << sub_type << endl;
    break;
  }

  assert (obj != NULL);

  int arrow_type, arrow_style;
  float arrow_thickness, arrow_width, arrow_height;
  GObject::OutlineInfo oinfo;
  oinfo.mask = GObject::OutlineInfo::Custom;
  oinfo.startArrowId = oinfo.endArrowId = 0;

  if (forward_arrow > 0) {

    // forward arrow line
    fin >> arrow_type >> arrow_style >> arrow_thickness
	>> arrow_width >> arrow_height;
    oinfo.endArrowId = arrow_ids[arrow_type];
    if (oinfo.endArrowId == 1 && arrow_style == 0)
      oinfo.endArrowId = 4;
    fin.ignore (INT_MAX, '\n');
  }

  if (backward_arrow > 0) {
    // backward arrow line
    fin >> arrow_type >> arrow_style >> arrow_thickness
	>> arrow_width >> arrow_height;
    oinfo.startArrowId = arrow_ids[arrow_type];
    if (oinfo.startArrowId == 1 && arrow_style == 0)
      oinfo.startArrowId = 4;
    fin.ignore (INT_MAX, '\n');
  }
  // points line
  for (int i = 0; i < npoints; i++) {
    int x, y;
    fin >> x >> y;
    if ((sub_type == 2 || sub_type == 3) && i == npoints -1)
      // first point == last point
      break;

    Coord p (x / fig_resolution, y / fig_resolution);
    obj->_addPoint (i, p);
  }

  if (oinfo.startArrowId || oinfo.endArrowId)
    obj->setOutlineInfo (oinfo);

  // now set the properties
  setProperties (obj, pen_color, line_style, thickness, area_fill, fill_color);

  // and insert the object
  objList.push_back (pair<int, GObject*> (depth, obj));
}


killustrator'XfigImport::parseSpline() (./koffice/killustrator/filter/XfigImport.cc:507)

void XfigImport::parseSpline (istream& fin, GDocument* ) {
  int sub_type, line_style, thickness, pen_color, fill_color, depth,
    pen_style, area_fill, cap_style, forward_arrow, backward_arrow, npoints;
  float style_val;

  // this should be a spline
  GPolyline *obj = 0L;
  fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
      >>  depth >> pen_style >> area_fill >> style_val >> cap_style
      >> forward_arrow >> backward_arrow >> npoints;
  if (sub_type == 1 || sub_type == 3 || sub_type == 5)
    obj = new GPolygon ();
  else
    obj = new GPolyline ();

  int arrow_type, arrow_style;
  float arrow_thickness, arrow_width, arrow_height;
  GObject::OutlineInfo oinfo;
  oinfo.mask = GObject::OutlineInfo::Custom;
  oinfo.startArrowId = oinfo.endArrowId = 0;

  if (forward_arrow > 0) {

    // forward arrow line
    fin >> arrow_type >> arrow_style >> arrow_thickness
	>> arrow_width >> arrow_height;
    oinfo.endArrowId = arrow_ids[arrow_type];
    if (oinfo.endArrowId == 1 && arrow_style == 0)
      oinfo.endArrowId = 4;
    fin.ignore (INT_MAX, '\n');
  }

  if (backward_arrow > 0) {
    // backward arrow line
    fin >> arrow_type >> arrow_style >> arrow_thickness
	>> arrow_width >> arrow_height;
    oinfo.startArrowId = arrow_ids[arrow_type];
    if (oinfo.startArrowId == 1 && arrow_style == 0)
      oinfo.startArrowId = 4;
    fin.ignore (INT_MAX, '\n');
  }
  // points line
  for (int i = 0; i < npoints; i++) {
    int x, y;
    fin >> x >> y;
    if ((sub_type == 1 || sub_type == 3 || sub_type == 5) && i == npoints -1)
      // first point == last point
      break;

    Coord p (x / fig_resolution, y / fig_resolution);
    obj->_addPoint (i, p);
  }

  // control points line
  for (int i = 0; i < npoints; i++) {
    float fac;
    fin >> fac;
    // ignore it now
    fin.ignore (INT_MAX, '\n');
  }

  if (oinfo.startArrowId || oinfo.endArrowId)
    obj->setOutlineInfo (oinfo);

  // now set the properties
  setProperties (obj, pen_color, line_style, thickness, area_fill, fill_color);

  // and insert the object
  objList.push_back (pair<int, GObject*> (depth, obj));
}


killustrator'XfigImport::parseText() (./koffice/killustrator/filter/XfigImport.cc:578)

void XfigImport::parseText (istream& fin, GDocument* ) {
  int sub_type, color, depth, pen_style, font, font_flags, x, y;
  float font_size, angle, height, length;
  GText *obj = new GText ();
  char c;
  char ocode[4];
  bool finished = false;
  QString text;
  QFont qfont;

  fin >> sub_type >> color >> depth >> pen_style >> font >> font_size
      >> angle >> font_flags >> height >> length >> x >> y;

  if (font_flags & 4) {
    // PostScript font
    if (font == -1)
      font = 0;
    qfont = QFont (psFontTable[font].family, qRound (font_size),
		   psFontTable[font].weight, psFontTable[font].italic);
  }
  else {
    // LaTeX font
    switch (font) {
    case 1: // Roman
      qfont.setFamily ("times");
      break;
    case 2: // Bold
      qfont.setBold (true);
      break;
    case 3: // Italic
      qfont.setItalic (true);
      break;
    case 4: // Sans Serif
      qfont.setFamily ("helvetica");
      break;
    case 5: // Typewriter
      qfont.setFamily ("Courier");
      break;
    default:
      break;
    }
  }
  qfont.setPointSize (qRound (font_size));
  obj->setFont (qfont);

  while (! finished) {
    fin.get (c);
    if (c == '\\') {
      fin.get (ocode, 4);
      int code = (ocode[0] - '0') * 64 +
	(ocode[1] - '0') * 8 +
	(ocode[2] - '0');
      if (code == 1)
	finished = true;
      else
	text += (char) code;
    }
    else
      text += c;
  }
  obj->setText (text);

  if (sub_type == 1) {
    GText::TextInfo ti = obj->getTextInfo ();
    ti.align = GText::TextInfo::AlignCenter;
    obj->setTextInfo (ti);
  }
  else if (sub_type == 2) {
    GText::TextInfo ti = obj->getTextInfo ();
    ti.align = GText::TextInfo::AlignRight;
    obj->setTextInfo (ti);
  }
  Coord origin (x / fig_resolution, y / fig_resolution - qfont.pointSize ());
  obj->setOrigin (origin);

  if (angle != 0) {
    // rotate the text
    float nangle = angle * RAD_FACTOR;
    QWMatrix m1, m2, m3;
    Coord rotCenter;

    if (sub_type == 0) {
      rotCenter = Coord (obj->boundingBox ().left (),
			 obj->boundingBox ().bottom ());
    }
    else if (sub_type == 1) {
      rotCenter = Coord (obj->boundingBox ().width () / 2,
			 obj->boundingBox ().bottom ());
    }
    else if (sub_type == 2) {
      rotCenter = Coord (obj->boundingBox ().right (),
			 obj->boundingBox ().bottom ());
    }
    m1.translate (-rotCenter.x (), -rotCenter.y ());
    m2.rotate (-nangle);
    m3.translate (rotCenter.x (), rotCenter.y ());
    obj->transform (m1);
    obj->transform (m2);
    obj->transform (m3, true);
  }

  objList.push_back (pair<int, GObject*> (depth, obj));
}


killustrator'XfigImport::parseCompoundObject() (./koffice/killustrator/filter/XfigImport.cc:682)

void XfigImport::parseCompoundObject (istream& fin, GDocument* ) {
  int upperright_x, upperright_y, lowerleft_x, lowerleft_y;

  fin >> upperright_x >> upperright_y >> lowerleft_x >> lowerleft_y;
  fin.ignore (INT_MAX, '\n');
}


/**
 * Copy all parsed objects from the sorted list to the document.
 */

killustrator'XfigImport::buildDocument() (./koffice/killustrator/filter/XfigImport.cc:693)

void XfigImport::buildDocument (GDocument *doc) {
  doc->setAutoUpdate (false);
  // the following operation is surely slower than sort(greater), but
  // unfortunatly this feature of STL is not as portable ;(
  objList.sort();
  objList.reverse();
  list<pair<int, GObject*> >::iterator i = objList.begin ();
  for (; i != objList.end (); i++) {
    GObject* obj = i->second;
    obj->ref ();
    doc->insertObject (obj);
  }
  doc->setAutoUpdate (true);
}


killustrator'XfigImport::setProperties() (./koffice/killustrator/filter/XfigImport.cc:708)

void XfigImport::setProperties (GObject* obj, int pen_color, int style,
				int thickness, int area_fill, int fill_color) {
  if (pen_color >= 0)
    obj->setOutlineColor (*colorTable[pen_color]);

  if (style < 1)
    obj->setOutlineStyle (QT_PRFX::SolidLine);
  else if (style == 1)
    obj->setOutlineStyle (QT_PRFX::DashLine);
  else if (style == 2)
    obj->setOutlineStyle (QT_PRFX::DotLine);

  obj->setOutlineWidth (thickness * 72.0 / 80.0);

  if (area_fill == -1)
    obj->setFillStyle (GObject::FillInfo::NoFill);
  else {
    obj->setFillStyle (GObject::FillInfo::SolidFill);
    if (fill_color < 1) {
      // for BLACK or DEFAULT color
      int val = qRound ((20 - area_fill) * 255.0 / 20.0);
      obj->setFillColor (QColor (val, val, val));
    }
    else if (fill_color == 7) {
      // for WHITE color
      int val = qRound ( area_fill * 255.0 / 20.0);
      obj->setFillColor (QColor (val, val, val));
    }
    else
      obj->setFillColor (*colorTable[fill_color]);
  }
}