Logo Search packages:      
Sourcecode: xdrawchem version File versions

render2d_print.cpp

#include <iostream>
#include <math.h>
#include <qwidget.h>
#include <qpainter.h>
#include <qprinter.h>
#include <qpaintdevicemetrics.h>
#include <qpointarray.h>
#include <qrect.h>
#include <qpixmap.h>

#include "paintable.h"
#include "render2d.h"
#include "chemdata.h"
#include "defs.h"

void Render2D::PrintSetup() {
  printer = new QPrinter;
  // the following statement is needed for Qt 3.0 or higher
#if QT_VERSION >= 300
  printer->setResolution(100);  // for convenient calculation of line length
  printer->setMargins(50,50,50,50);  // apparently works on UNIX only
#endif
  printer->setFullPage(true);
  //printer->setPageSize(QPrinter::Letter);
  //printer->setOrientation(QPrinter::Portrait);
  printer->setColorMode(QPrinter::GrayScale);
  UpdatePageGeometry();
}

void Render2D::UpdatePageGeometry() {
  if (preferences.getPageOrientation() == PAGE_PORTRAIT) {
    printer->setOrientation(QPrinter::Portrait);
    switch (preferences.getPageSize()) {
    case PAGE_LETTER:
      printer->setPageSize(QPrinter::Letter);
      renderHeight = 1000;
      renderWidth = 750;
      break;
    case PAGE_LEGAL:
      printer->setPageSize(QPrinter::Legal);
      renderHeight = 1300;
      renderWidth = 750;
      break;
    case PAGE_A4:
      printer->setPageSize(QPrinter::A4);
      renderHeight = 1070;
      renderWidth = 776;
      break;
    case PAGE_640:
      renderWidth = 640;
      renderWidth = 480;
      break;
    case PAGE_800:
      renderWidth = 800;
      renderWidth = 600;
      break;
    case PAGE_1024:
      renderWidth = 1024;
      renderWidth = 768;
      break;
    default:
      break;
    }
  } else { // page_orientation == PAGE_LANDSCAPE
    printer->setOrientation(QPrinter::Landscape);
    switch (preferences.getPageSize()) {
    case PAGE_LETTER:
      printer->setPageSize(QPrinter::Letter);
      renderHeight = 750;
      renderWidth = 1000;
      break;
    case PAGE_LEGAL:
      printer->setPageSize(QPrinter::Legal);
      renderHeight = 750;
      renderWidth = 1300;
      break;
    case PAGE_A4:
      printer->setPageSize(QPrinter::A4);
      renderHeight = 776;
      renderWidth = 1070;
      break;
    case PAGE_640:
      renderWidth = 640;
      renderWidth = 480;
      break;
    case PAGE_800:
      renderWidth = 800;
      renderWidth = 600;
      break;
    case PAGE_1024:
      renderWidth = 1024;
      renderWidth = 768;
      break;
    default:
      break;
    }
  }
  resize(renderWidth, renderHeight);
}

void Render2D::Print(QString epsname) {
  if (epsname.length() > 4) {
    // setup printer...
    printer->setOutputToFile(true);
    printer->setColorMode( QPrinter::Color );
    printer->setOutputFileName(epsname);
  } else {  // print from File/Print or Ctrl+P
    if (!printer->setup(this)) {
      emit SignalSetStatusBar( QString("Printing canceled.") );
      return;
    }
  }

  //QPaintDeviceMetrics pm(printer);

  c->DeselectAll();
  // set output device
  outputDevice = OUTPUT_PRINTER;
  // render all objects
  paintqueue.clear();
  repaint();
  QPainter p(printer);
  Paintable *tmp_paint;

  for (tmp_paint = paintqueue.first(); tmp_paint != NULL;
       tmp_paint = paintqueue.next()) {
    QPoint a = tmp_paint->a;
    QPoint b = tmp_paint->b;
    QColor c1 = tmp_paint->c;
    if (tmp_paint->op == OP_LINE) {
      if (tmp_paint->s == 0)
      p.setPen(tmp_paint->c);
      if (tmp_paint->s == 1)  // dashed line
      p.setPen(QPen(tmp_paint->c,1,DotLine));
      p.drawLine(tmp_paint->a, tmp_paint->b);
    }
    if (tmp_paint->op == OP_FILLBOX) {
      p.setPen(c1);
      p.fillRect(QRect(a, b), c1);
    }
    if (tmp_paint->op == OP_UP_LINE) {
      p.setPen(c1);
      p.setBrush(QBrush(c1));
      QPointArray triangle(3);
      triangle.setPoint(0, a);
      triangle.setPoint(1, b);
      triangle.setPoint(2, tmp_paint->b1);
      p.drawPolygon(triangle);
    }
    if (tmp_paint->op == OP_DASH_LINE) {
      p.setPen(QPen(tmp_paint->c,0,DotLine));
      p.drawLine(tmp_paint->a, tmp_paint->b);
    }
    if (tmp_paint->op == OP_TEXT) {
      p.setPen(tmp_paint->c);
      p.setFont(tmp_paint->f);
      /*
      QRect b = GetTextDimensions(displayText, font);
      QPoint t = GetTopLeftPoint();
      b.moveBy( t.x(), t.y() );
      r->drawFillBox(b.topLeft(), b.bottomRight(), r->getBGColor(), false,
                 QColor(0,0,0), 1);
      */
      p.drawText(tmp_paint->a, tmp_paint->ch);
    }
    if (tmp_paint->op == OP_STRING) {
      p.setPen(tmp_paint->c);
      p.setFont(tmp_paint->f);
      p.drawText(tmp_paint->a, tmp_paint->st);
    }
    if (tmp_paint->op == OP_CURVE_CW180) {
      // calculate curve
      p.setPen(tmp_paint->c);
      QPoint ce = Midpoint(tmp_paint->a, tmp_paint->b);
      int d = RoundOff(DistanceBetween(tmp_paint->a, ce));
      double sa = getAngle(ce, tmp_paint->a);
      QPointArray pa;
      pa.makeArc(ce.x() - d, ce.y() - d, 2*d, 2*d, my_round(-sa*16), -2880);
      p.drawPolyline(pa);
      // calculate arrowhead
      // if curve too small, don't draw arrowhead
      if (pa.count() == 0) return;
      QPoint realb(pa.at(pa.count() - 1));
      sa = getAngle(tmp_paint->b, tmp_paint->a);
      double newang1 = sa + 60.0;
      double newang2 = sa + 120.0;
      QPoint a1( my_round(realb.x() + (cos(newang1/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang1/MOL_ARAD) * 10.0)) );
      QPoint a2( my_round(realb.x() + (cos(newang2/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang2/MOL_ARAD) * 10.0)) );
      p.drawLine(realb, a1);
      p.drawLine(realb, a2);
    }
    if (tmp_paint->op == OP_CURVE_CCW180) {
      // calculate curve
      p.setPen(tmp_paint->c);
      QPoint ce = Midpoint(tmp_paint->a, tmp_paint->b);
      int d = RoundOff(DistanceBetween(tmp_paint->a, ce));
      double sa = getAngle(ce, tmp_paint->a);
      QPointArray pa;
      pa.makeArc(ce.x() - d, ce.y() - d, 2*d, 2*d, my_round(-sa*16), 2880);
      p.drawPolyline(pa);
      // calculate arrowhead
      // if curve too small, don't draw arrowhead
      if (pa.count() == 0) return;
      QPoint realb(pa.at(pa.count() - 1));
      sa = getAngle(tmp_paint->b, tmp_paint->a);
      double newang1 = sa + 60.0;
      double newang2 = sa + 120.0;
      QPoint a1( my_round(realb.x() + (cos(newang1/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang1/MOL_ARAD) * 10.0)) );
      QPoint a2( my_round(realb.x() + (cos(newang2/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang2/MOL_ARAD) * 10.0)) );
      p.drawLine(realb, a1);
      p.drawLine(realb, a2);
    }
    if (tmp_paint->op == OP_PIXMAP) {
      p.drawPixmap(tmp_paint->a, tmp_paint->p);
    }
    if (tmp_paint->op == OP_CURVE_CW90) {
      // first, figure out where middle of circle is
      double d1 = DistanceBetween(a, b);
      double ia = getAngle(a, b);
      d1 = d1 / 1.4142136;
      ia = 45.0;
      double dx1 = ( (double)b.x() - (double)a.x() ) / 1.4142136;
      double dy1 = ( (double)b.y() - (double)a.y() ) / 1.4142136;
      // rotate vector (dx1, dy1) 45 degrees clockwise
      double ia_rad = ia * M_PI / 180.0;
      double dx2 = dx1*cos(ia_rad) - dy1*sin(ia_rad);
      double dy2 = dx1*sin(ia_rad) + dy1*cos(ia_rad);
      QPoint ce(a.x() + RoundOff(dx2), a.y() + RoundOff(dy2));
      double sa = getAngle(ce, a);
      QPointArray pa;
      int d = RoundOff(d1);
      pa.makeArc(ce.x() - d, ce.y() - d, 2*d, 2*d, my_round(-sa*16), -1440);
      drawPolyline(pa, c1);    
      // calculate arrowhead
      // if curve too small, don't draw arrowhead
      if (pa.count() == 0) return;
      QPoint realb(pa.at(pa.count() - 1));
      sa = getAngle(b, a);
      double newang1 = sa + 15.0;
      double newang2 = sa + 75.0;
      QPoint a1( my_round(realb.x() + (cos(newang1/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang1/MOL_ARAD) * 10.0)) );
      QPoint a2( my_round(realb.x() + (cos(newang2/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang2/MOL_ARAD) * 10.0)) );
      drawLine(realb, a1, 1, c1);
      drawLine(realb, a2, 1, c1);
    }
    if (tmp_paint->op == OP_CURVE_CCW90) {
      // first, figure out where middle of circle is
      double d1 = DistanceBetween(a, b);
      double ia = getAngle(a, b);
      d1 = d1 / 1.4142136;
      ia = -45.0;
      double dx1 = ( (double)b.x() - (double)a.x() ) / 1.4142136;
      double dy1 = ( (double)b.y() - (double)a.y() ) / 1.4142136;
      // rotate vector (dx1, dy1) 45 degrees clockwise
      double ia_rad = ia * M_PI / 180.0;
      double dx2 = dx1*cos(ia_rad) - dy1*sin(ia_rad);
      double dy2 = dx1*sin(ia_rad) + dy1*cos(ia_rad);
      QPoint ce(a.x() + RoundOff(dx2), a.y() + RoundOff(dy2));
      double sa = getAngle(ce, a);
      QPointArray pa;
      int d = RoundOff(d1);
      pa.makeArc(ce.x() - d, ce.y() - d, 2*d, 2*d, my_round(-sa*16), 1440);
      drawPolyline(pa, c1);    
      // calculate arrowhead
      // if curve too small, don't draw arrowhead
      if (pa.count() == 0) return;
      QPoint realb(pa.at(pa.count() - 1));
      sa = getAngle(b, a);
      double newang1 = sa - 15.0;
      double newang2 = sa - 75.0;
      QPoint a1( my_round(realb.x() + (cos(newang1/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang1/MOL_ARAD) * 10.0)) );
      QPoint a2( my_round(realb.x() + (cos(newang2/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang2/MOL_ARAD) * 10.0)) );
      drawLine(realb, a1, 1, c1);
      drawLine(realb, a2, 1, c1);
    }    
    if (tmp_paint->op == OP_CURVE_CW270) {
      // first, figure out where middle of circle is
      double d1 = DistanceBetween(a, b);
      double ia = getAngle(a, b);
      d1 = d1 / 1.4142136;
      ia = -45.0;
      double dx1 = ( (double)b.x() - (double)a.x() ) / 1.4142136;
      double dy1 = ( (double)b.y() - (double)a.y() ) / 1.4142136;
      // rotate vector (dx1, dy1) 45 degrees clockwise
      double ia_rad = ia * M_PI / 180.0;
      double dx2 = dx1*cos(ia_rad) - dy1*sin(ia_rad);
      double dy2 = dx1*sin(ia_rad) + dy1*cos(ia_rad);
      QPoint ce(a.x() + RoundOff(dx2), a.y() + RoundOff(dy2));
      double sa = getAngle(ce, a);
      QPointArray pa;
      int d = RoundOff(d1);
      pa.makeArc(ce.x() - d, ce.y() - d, 2*d, 2*d, my_round(-sa*16), -4320);
      drawPolyline(pa, c1);    
      // calculate arrowhead
      // if curve too small, don't draw arrowhead
      if (pa.count() == 0) return;
      QPoint realb(pa.at(pa.count() - 1));
      sa = getAngle(b, a);
      double newang1 = sa + 165.0;
      double newang2 = sa + 105.0;
      QPoint a1( my_round(realb.x() + (cos(newang1/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang1/MOL_ARAD) * 10.0)) );
      QPoint a2( my_round(realb.x() + (cos(newang2/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang2/MOL_ARAD) * 10.0)) );
      drawLine(realb, a1, 1, c1);
      drawLine(realb, a2, 1, c1);
    }
    if (tmp_paint->op == OP_CURVE_CCW270) {
      // first, figure out where middle of circle is
      double d1 = DistanceBetween(a, b);
      double ia = getAngle(a, b);
      d1 = d1 / 1.4142136;
      ia = 45.0;
      double dx1 = ( (double)b.x() - (double)a.x() ) / 1.4142136;
      double dy1 = ( (double)b.y() - (double)a.y() ) / 1.4142136;
      // rotate vector (dx1, dy1) 45 degrees clockwise
      double ia_rad = ia * M_PI / 180.0;
      double dx2 = dx1*cos(ia_rad) - dy1*sin(ia_rad);
      double dy2 = dx1*sin(ia_rad) + dy1*cos(ia_rad);
      QPoint ce(a.x() + RoundOff(dx2), a.y() + RoundOff(dy2));
      double sa = getAngle(ce, a);
      QPointArray pa;
      int d = RoundOff(d1);
      pa.makeArc(ce.x() - d, ce.y() - d, 2*d, 2*d, my_round(-sa*16), 4320);
      drawPolyline(pa, c1);    
      // calculate arrowhead
      // if curve too small, don't draw arrowhead
      if (pa.count() == 0) return;
      QPoint realb(pa.at(pa.count() - 1));
      sa = getAngle(b, a);
      double newang1 = sa - 165.0;
      double newang2 = sa - 105.0;
      QPoint a1( my_round(realb.x() + (cos(newang1/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang1/MOL_ARAD) * 10.0)) );
      QPoint a2( my_round(realb.x() + (cos(newang2/MOL_ARAD) * 10.0)),
             my_round(realb.y() + (sin(newang2/MOL_ARAD) * 10.0)) );
      drawLine(realb, a1, 1, c1);
      drawLine(realb, a2, 1, c1);
    }
  }
  // set output to screen
  outputDevice = OUTPUT_SCREEN;
  repaint(false);
}

Generated by  Doxygen 1.6.0   Back to index