[rkward-cvs] SF.net SVN: rkward-code:[4628] branches/development_branches/ rkward_graphpics_device/rkward/rbackend/rkwarddevice
tfry at users.sf.net
tfry at users.sf.net
Mon Mar 25 18:18:18 UTC 2013
Revision: 4628
http://sourceforge.net/p/rkward/code/4628
Author: tfry
Date: 2013-03-25 18:18:17 +0000 (Mon, 25 Mar 2013)
Log Message:
-----------
More bits on the graphics device.
- All drawing ops are now implemented (although I have not tested some things, importantly plotmath)
- Interaction ops, including resizing are still unimplemented
- The QGraphicsScene shows its performance limitations: Everything works smoothly up to around 10,000 points / items. At 100,000 items, the thing becomes completely unusable.
- I played with optimiazation flags and delayed updates to no real avail
- One successful attempt was rendering every 5k or 10k items to a pixmap.
- Of course this begs the question: Why not render everything to a pixmap in the first place? And so that's what I'll try, next.
- Text selection might be added later, on top of this, if that seems important enough.
Modified Paths:
--------------
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_backendtransmitter.cpp
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_backendtransmitter.h
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp 2013-03-24 19:29:41 UTC (rev 4627)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp 2013-03-25 18:18:17 UTC (rev 4628)
@@ -31,14 +31,23 @@
#include "../../debug.h"
+#define UPDATE_INTERVAL 100
+
QHash<int, RKGraphicsDevice*> RKGraphicsDevice::devices;
RKGraphicsDevice::RKGraphicsDevice (double width, double height) : QObject () {
RK_TRACE (GRAPHICS_DEVICE);
scene = new QGraphicsScene (0, 0, width, height, this);
view = new QGraphicsView (scene);
+// view->setOptimizationFlags (QGraphicsView::DontSavePainterState);
+// view->setRenderHints (QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+// scene->setItemIndexMethod (QGraphicsScene::NoIndex);
+// scene->setBspTreeDepth (16);
+// view->setViewportUpdateMode (QGraphicsView::NoViewportUpdate);
+ connect (&updatetimer, SIGNAL (timeout ()), this, SLOT (updateNow ()));
view->show ();
item_z = clip_z = 0;
+ clip = 0;
setClip (scene->sceneRect ());
}
@@ -47,6 +56,19 @@
delete view;
}
+void RKGraphicsDevice::triggerUpdate () {
+ view->setUpdatesEnabled (false);
+ updatetimer.start (UPDATE_INTERVAL);
+}
+
+void RKGraphicsDevice::updateNow () {
+// QList<QRectF> dummy;
+// dummy.append (scene->sceneRect ());
+// view->updateScene (dummy);
+ view->setUpdatesEnabled (true);
+ view->update ();
+}
+
RKGraphicsDevice* RKGraphicsDevice::newDevice (int devnum, double width, double height) {
RK_TRACE (GRAPHICS_DEVICE);
@@ -66,61 +88,142 @@
devices.take (devnum)->deleteLater ();
}
+void RKGraphicsDevice::clear (const QBrush& bg) {
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ scene->clear ();
+ clip = 0;
+ setClip (scene->sceneRect ());
+ rect (scene->sceneRect (), QPen (Qt::NoPen), bg);
+ view->show ();
+ updatetimer.start (UPDATE_INTERVAL);
+}
+
void RKGraphicsDevice::setClip (const QRectF& new_clip) {
RK_TRACE (GRAPHICS_DEVICE);
+
+// QGraphicsItem* old_clip = clip;
clip = scene->addRect (new_clip, QPen (Qt::NoPen));
clip->setZValue (clip_z += .1);
clip->setFlags (QGraphicsItem::ItemClipsChildrenToShape);
item_z = 0;
+// if (old_clip) old_clip->setCacheMode (QGraphicsItem::DeviceCoordinateCache);
}
+void RKGraphicsDevice::addItem (QGraphicsItem* item) {
+ if (item_z > 1000) {
+ updatetimer.stop ();
+ QGraphicsItem *old_clip = clip;
+ QRectF brect = clip->rect ().normalized ();
+ QPixmap cache (brect.width () + 1, brect.height () + 1);
+ cache.fill (QColor (0, 0, 0, 0));
+ QPainter painter;
+ painter.begin (&cache);
+ scene->render (&painter, cache.rect (), brect);
+ painter.end ();
+ setClip (brect);
+ QGraphicsPixmapItem *cached = new QGraphicsPixmapItem (cache);
+ cached->setPos (brect.x (), brect.y ());
+ addItem (cached);
+ delete old_clip;
+ }
+ item->setZValue (item_z += .1);
+ item->setParentItem (clip);
+ triggerUpdate ();
+}
+
void RKGraphicsDevice::circle (double x, double y, double r, const QPen& pen, const QBrush& brush) {
- QGraphicsEllipseItem* circle = new QGraphicsEllipseItem (x - r, y - r, r+r, r+r, clip);
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ QGraphicsEllipseItem* circle = new QGraphicsEllipseItem (x - r, y - r, r+r, r+r);
circle->setPen (pen);
circle->setBrush (brush);
- circle->setZValue (item_z += .1);
+ addItem (circle);
}
void RKGraphicsDevice::line (double x1, double y1, double x2, double y2, const QPen& pen) {
- QGraphicsLineItem* line = new QGraphicsLineItem (x1, y1, x2, y2, clip);
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ QGraphicsLineItem* line = new QGraphicsLineItem (x1, y1, x2, y2);
line->setPen (pen);
- line->setZValue (item_z += .1);
+ addItem (line);
}
+void RKGraphicsDevice::rect (const QRectF& rec, const QPen& pen, const QBrush& brush) {
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ QGraphicsRectItem* rect = new QGraphicsRectItem (rec);
+ rect->setPen (pen);
+ rect->setBrush (brush);
+ addItem (rect);
+}
+
double RKGraphicsDevice::strWidth (const QString& text, const QFont& font) {
- QGraphicsSimpleTextItem t (text, 0);
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ QGraphicsTextItem t (text);
t.setFont (font);
return t.boundingRect ().width ();
}
void RKGraphicsDevice::text (double x, double y, const QString& _text, double rot, double hadj, const QColor& col, const QFont& font) {
- QGraphicsTextItem *text = new QGraphicsTextItem (clip);
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ QGraphicsTextItem *text = new QGraphicsTextItem ();
text->setPlainText (_text);
text->setFont (font);
- QRectF brect = text->boundingRect();
+ text->setDefaultTextColor (col);
+ QRectF brect = text->boundingRect ();
text->rotate (-rot);
text->translate (-hadj * brect.width (), - QFontMetricsF (font).height ());
text->setPos (x, y);
- text->setZValue (item_z += .1);
text->setTextInteractionFlags (Qt::TextSelectableByMouse);
+ addItem (text);
}
void RKGraphicsDevice::metricInfo (const QChar& c, const QFont& font, double* ascent, double* descent, double* width) {
+ RK_TRACE (GRAPHICS_DEVICE);
+
QFontMetricsF fm (font);
*ascent = fm.ascent (); // TODO: or should we return the metrics of this particular char (similar to strWidth)
*descent = fm.descent ();
*width = fm.width (c);
+/* QGraphicsTextItem t;
+ t.setPlainText (QString (c));
+ t.setFont (font);
+ *ascent = t.boundingRect().height();
+ *descent = 0;
+ *width = t.boundingRect().width(); */
}
void RKGraphicsDevice::polygon (const QPolygonF& pol, const QPen& pen, const QBrush& brush) {
- QGraphicsPolygonItem *poli = new QGraphicsPolygonItem (pol, clip);
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ QGraphicsPolygonItem *poli = new QGraphicsPolygonItem (pol);
poli->setPen (pen);
poli->setBrush (brush);
- poli->setZValue (item_z += .1);
+ addItem (poli);
}
void RKGraphicsDevice::polyline (const QPolygonF& pol, const QPen& pen) {
- QGraphicsPolygonItem *poli = new QGraphicsPolygonItem (pol, clip);
+ RK_TRACE (GRAPHICS_DEVICE);
+// Qt insistes that all QGraphicsPolygonItems must be closed. So the this does not work:
+// QGraphicsPolygonItem *poli = new QGraphicsPolygonItem (pol, clip);
+ if (pol.isEmpty ()) return;
+
+ QPainterPath path;
+ path.moveTo (pol[0]);
+ for (int i = 1; i < pol.size (); ++i) {
+ path.lineTo (pol[i]);
+ }
+ QGraphicsPathItem *poli = new QGraphicsPathItem (path);
poli->setPen (pen);
- poli->setZValue (item_z += .1);
+ addItem (poli);
}
+
+void RKGraphicsDevice::setActive (bool active) {
+ RK_TRACE (GRAPHICS_DEVICE);
+ emit (activeChanged (active));
+}
+
+#include "rkgraphicsdevice.moc"
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h 2013-03-24 19:29:41 UTC (rev 4627)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h 2013-03-25 18:18:17 UTC (rev 4628)
@@ -20,13 +20,16 @@
#include <QHash>
#include <QPen>
+#include <QTimer>
class QGraphicsRectItem;
class QGraphicsView;
class QGraphicsScene;
+class QGraphicsItem;
/** This is the class that actually does all the drawing for the RKGraphicsDevice */
class RKGraphicsDevice : public QObject {
+ Q_OBJECT
protected:
RKGraphicsDevice (double width, double height);
~RKGraphicsDevice ();
@@ -37,13 +40,23 @@
void circle (double x, double y, double r, const QPen& pen, const QBrush& brush);
void line (double x1, double y1, double x2, double y2, const QPen& pen);
+ void rect (const QRectF& rec, const QPen& pen, const QBrush& brush);
double strWidth (const QString &text, const QFont& font);
void text (double x, double y, const QString &text, double rot, double hadj, const QColor& col, const QFont& font);
void metricInfo (const QChar& c, const QFont& font, double *ascent, double *descent, double *width);
void setClip (const QRectF& new_clip);
void polygon (const QPolygonF& pol, const QPen& pen, const QBrush &brush);
void polyline (const QPolygonF& pol, const QPen& pen);
+ void clear (const QBrush& bg);
+ void setActive (bool active);
+ void triggerUpdate ();
+signals:
+ void activeChanged (bool);
+private slots:
+ void updateNow ();
private:
+ void addItem (QGraphicsItem *item);
+ QTimer updatetimer;
QGraphicsScene* scene;
QGraphicsView* view;
QGraphicsRectItem* clip;
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_backendtransmitter.cpp
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_backendtransmitter.cpp 2013-03-24 19:29:41 UTC (rev 4627)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_backendtransmitter.cpp 2013-03-25 18:18:17 UTC (rev 4628)
@@ -29,7 +29,7 @@
QMutex RKGraphicsDeviceBackendTransmitter::mutex;
RKGraphicsDeviceBackendTransmitter* RKGraphicsDeviceBackendTransmitter::_instance = 0;
-RKGraphicsDeviceBackendTransmitter::RKGraphicsDeviceBackendTransmitter (QIODevice* _connection) : QThread () {
+RKGraphicsDeviceBackendTransmitter::RKGraphicsDeviceBackendTransmitter (QIODevice* _connection, bool is_q_local_socket) : QThread () {
RK_TRACE (GRAPHICS_DEVICE);
RK_ASSERT (!connection);
@@ -37,6 +37,7 @@
connection = _connection;
streamer.setIODevice (connection);
alive = true;
+ is_local_socket = is_q_local_socket;
start ();
}
@@ -56,12 +57,18 @@
con->write (RKRBackendTransmitter::instance ()->connectionToken ().toLocal8Bit ().data ());
con->write ("\n");
con->waitForBytesWritten (1000);
- _instance = new RKGraphicsDeviceBackendTransmitter (con);
+ _instance = new RKGraphicsDeviceBackendTransmitter (con, true);
return _instance;
}
return 0;
}
+bool RKGraphicsDeviceBackendTransmitter::connectionAlive () {
+ if (!_instance) return false;
+ if (!_instance->is_local_socket) return true;
+ return static_cast<QLocalSocket*> (_instance->connection)->state () == QLocalSocket::ConnectedState;
+}
+
void RKGraphicsDeviceBackendTransmitter::run () {
RK_TRACE (GRAPHICS_DEVICE);
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_backendtransmitter.h
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_backendtransmitter.h 2013-03-24 19:29:41 UTC (rev 4627)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_backendtransmitter.h 2013-03-25 18:18:17 UTC (rev 4628)
@@ -28,10 +28,11 @@
Also it provides the namespace for some statics.
As the protocol is really quite simple (only the backend send requests, only one request at a time), so is the transmitter. */
class RKGraphicsDeviceBackendTransmitter : public QThread {
- RKGraphicsDeviceBackendTransmitter (QIODevice *connection);
+ RKGraphicsDeviceBackendTransmitter (QIODevice *connection, bool is_q_local_socket);
~RKGraphicsDeviceBackendTransmitter ();
public:
static void kill ();
+ static bool connectionAlive ();
static RKGraphicsDeviceBackendTransmitter* instance ();
static RKAsyncDataStreamHelper streamer;
static QIODevice* connection;
@@ -39,6 +40,7 @@
private:
static RKGraphicsDeviceBackendTransmitter* _instance;
bool alive;
+ bool is_local_socket;
void run ();
};
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp 2013-03-24 19:29:41 UTC (rev 4627)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp 2013-03-25 18:18:17 UTC (rev 4628)
@@ -81,15 +81,35 @@
connect (connection, SIGNAL (readyRead ()), this, SLOT (newData ()));
}
+static QColor readColor (QDataStream &instream) {
+ quint8 r, g, b, a;
+ instream >> r >> g >> b >> a;
+ if (a == 0x00) return QColor ();
+ return QColor (r, g, b, a);
+}
+
static QPen readSimplePen (QDataStream &instream) {
- quint8 r, g, b, a;
+ QColor col = readColor (instream);
double lwd;
qint32 lty;
- instream >> r >> g >> b >> a >> lwd >> lty;
-#warning: Line style!
+ instream >> lwd >> lty;
+ if (!col.isValid () || (lty == -1L)) return QPen (Qt::NoPen);
+
+ lwd = qMax (1.0001, lwd); // minimum 1 px (+rounding margin!) as in X11 device
QPen ret;
+ if (lty != 0) { // solid
+ QVector<qreal> dashes;
+ quint32 nlty = lty;
+ for (int i = 0; i < 8; ++i) {
+ if (!nlty) break;
+ quint8 j = nlty & 0xF;
+ dashes.append (j * lwd * 96/72 + .5); // 96/72: value taken from X11 device
+ nlty >>= 4;
+ }
+ if (!dashes.isEmpty ()) ret.setDashPattern (dashes);
+ }
ret.setWidthF (lwd);
- ret.setColor (QColor (r, g, b, a));
+ ret.setColor (col);
return ret;
}
@@ -98,22 +118,27 @@
quint8 lends, ljoin;
double lmitre;
instream >> lends >> ljoin >> lmitre;
-#warning: Apply attribs!
+ ret.setCapStyle (lends == RoundLineCap ? Qt::RoundCap : (lends == ButtLineCap ? Qt::FlatCap : Qt::SquareCap));
+ ret.setJoinStyle (ljoin == RoundJoin ? Qt::RoundJoin : (ljoin == BevelJoin ? Qt::BevelJoin : Qt::MiterJoin));
+ ret.setMiterLimit (lmitre);
return ret;
}
static QBrush readBrush (QDataStream &instream) {
-#warning: Read brush!
- return QBrush ();
+ QColor col = readColor (instream);
+ if (!col.isValid ()) return QBrush ();
+ return QBrush (col);
}
static QFont readFont (QDataStream &instream) {
-#warning: Handle all attribs!
double cex, ps, lineheight;
quint8 fontface;
QString fontfamily;
instream >> cex >> ps >> lineheight >> fontface >> fontfamily;
+#warning TODO deal with line-height
QFont ret (fontfamily);
+ if (fontface == 2 || fontface == 4) ret.setWeight (QFont::Bold);
+ if (fontface == 3 || fontface == 4) ret.setItalic (true);
ret.setPointSizeF (cex*ps);
return ret;
}
@@ -123,7 +148,7 @@
instream >> n;
QVector<QPointF> points;
points.reserve (n + (close ? 1 : 0));
- for (int i = 0; i < n; ++i) {
+ for (quint32 i = 0; i < n; ++i) {
double x, y;
instream >> x >> y;
points.append (QPointF (x, y));
@@ -156,32 +181,34 @@
}
}
+/* WARNING: No fixed evaluation order of function arguments. Do not use several readXYZ() calls in the same function call! Use dummy variables, instead. */
if (opcode == RKDCircle) {
double x, y, r;
streamer.instream >> x >> y >> r;
- device->circle (x, y, r, readSimplePen (streamer.instream), readBrush (streamer.instream));
- continue;
+ QPen pen = readSimplePen (streamer.instream);
+ device->circle (x, y, r, pen, readBrush (streamer.instream));
} else if (opcode == RKDLine) {
double x1, y1, x2, y2;
streamer.instream >> x1 >> y1 >> x2 >> y2;
device->line (x1, y1, x2, y2, readPen (streamer.instream));
- continue;
} else if (opcode == RKDPolygon) {
QPolygonF pol (readPoints (streamer.instream, true));
- device->polygon (pol, readPen (streamer.instream), readBrush (streamer.instream));
- continue;
+ QPen pen = readPen (streamer.instream);
+ device->polygon (pol, pen, readBrush (streamer.instream));
} else if (opcode == RKDPolyline) {
QPolygonF pol (readPoints (streamer.instream, false));
device->polyline (pol, readPen (streamer.instream));
- continue;
} else if (opcode == RKDRect) {
+ QRectF rect;
+ streamer.instream >> rect;
+ QPen pen = readPen (streamer.instream);
+ device->rect (rect, pen, readBrush (streamer.instream));
} else if (opcode == RKDStrWidthUTF8) {
QString out;
streamer.instream >> out;
double w = device->strWidth (out, readFont (streamer.instream));
streamer.outstream << w;
streamer.writeOutBuffer ();
- continue;
} else if (opcode == RKDMetricInfo) {
QChar c;
double ascent, descent, width;
@@ -189,29 +216,41 @@
device->metricInfo (c, readFont (streamer.instream), &ascent, &descent, &width);
streamer.outstream << ascent << descent << width;
streamer.writeOutBuffer ();
- continue;
} else if (opcode == RKDTextUTF8) {
double x, y, rot, hadj;
QString out;
- QRgb col;
- streamer.instream >> x >> y >> out >> rot >> hadj >> col;
+ streamer.instream >> x >> y >> out >> rot >> hadj;
+ QColor col = readColor (streamer.instream);
device->text (x, y, out, rot, hadj, col, readFont (streamer.instream));
- continue;
} else if (opcode == RKDNewPage) {
+ device->clear (readBrush (streamer.instream));
} else if (opcode == RKDClose) {
+ RKGraphicsDevice::closeDevice (devnum);
} else if (opcode == RKDActivate) {
+ RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Unhandled operation of type %d for device number %d. Skippping.", opcode, devnum);
} else if (opcode == RKDDeActivate) {
+ RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Unhandled operation of type %d for device number %d. Skippping.", opcode, devnum);
} else if (opcode == RKDClip) {
+ QRectF clip;
+ streamer.instream >> clip;
+ device->setClip (clip);
} else if (opcode == RKDMode) {
+ quint8 m;
+ streamer.instream >> m;
+ if (m == 0) device->triggerUpdate ();
} else if (opcode == RKDLocator) {
+ RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Unhandled operation of type %d for device number %d. Skippping.", opcode, devnum);
+ sendDummyReply (opcode);
} else if (opcode == RKDNewPageConfirm) {
+ RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Unhandled operation of type %d for device number %d. Skippping.", opcode, devnum);
+ sendDummyReply (opcode);
+ } else {
+ RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Unhandled operation of type %d for device number %d. Skippping.", opcode, devnum);
}
- RK_ASSERT (streamer.instream.atEnd ());
- RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Unhandled operation of type %d for device number %d. Skippping.", opcode, devnum);
-
-#warning TODO: Actually handle the data!
- sendDummyReply (opcode);
+ if (!streamer.instream.atEnd ()) {
+ RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Failed to read all data for operation of type %d on device number %d.", opcode, devnum);
+ }
}
}
@@ -219,7 +258,7 @@
RK_TRACE (GRAPHICS_DEVICE);
if (opcode == RKDLocator) {
- bool ok = true;
+ bool ok = false;
double x, y;
x = y = 0;
streamer.outstream << ok << x << y;
@@ -228,7 +267,7 @@
ascent = descent = width = 0.1;
streamer.outstream << ascent << descent << width;
} else if (opcode == RKDNewPageConfirm) {
- bool ok = true;
+ bool ok = false;
streamer.outstream << ok;
} else if (opcode == RKDStrWidthUTF8) {
double width = 1;
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h 2013-03-24 19:29:41 UTC (rev 4627)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h 2013-03-25 18:18:17 UTC (rev 4628)
@@ -38,6 +38,22 @@
*
*/
+/** This enum simply repeats R's line end definitions. It is used to ensure compatiblity, without the need to include
+ * any R headers in the frontend. */
+enum RKLineEndStyles {
+ RoundLineCap = 1,
+ ButtLineCap = 2,
+ SquareLineCap = 3
+};
+
+/** This enum simply repeats R's line join definitions. It is used to ensure compatiblity, without the need to include
+ * any R headers in the frontend. */
+enum RKLineJoinStyles {
+ RoundJoin = 1,
+ MitreJoin = 2,
+ BevelJoin = 3
+};
+
enum RKDOpcodes {
// Asynchronous operations
RKDCreate, // 0
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp 2013-03-24 19:29:41 UTC (rev 4627)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp 2013-03-25 18:18:17 UTC (rev 4628)
@@ -114,8 +114,8 @@
dev->right = dev->clipRight = width;
dev->bottom = dev->clipBottom = height;
dev->top = dev->clipTop = 0;
- dev->cra[0] = 0.9 * pointsize;
- dev->cra[1] = 1.2 * pointsize;
+ dev->cra[0] = 0.9 * pointsize * 96/72;
+ dev->cra[1] = 1.2 * pointsize * 96/72;
dev->xCharOffset = 0.4900;
dev->yCharOffset = 0.3333;
dev->yLineBias = 0.1;
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp 2013-03-24 19:29:41 UTC (rev 4627)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp 2013-03-25 18:18:17 UTC (rev 4628)
@@ -42,13 +42,23 @@
QIODevice* connection = RKGraphicsDeviceBackendTransmitter::connection;
BEGIN_SUSPEND_INTERRUPTS {
while (connection->bytesToWrite ()) {
- connection->waitForBytesWritten (10);
+ if (!connection->waitForBytesWritten (10)) {
+ if (!RKGraphicsDeviceBackendTransmitter::connectionAlive ()) { // Don't go into endless loop, if e.g. frontend has crashed
+ RKGraphicsDeviceBackendTransmitter::mutex.unlock ();
+ Rf_error ("RKWard Graphics connection has shut down");
+ }
+ }
#warning TODO: Use R_CheckUserInterrupt(), instead?
if (connection->bytesToWrite ()) RKRBackend::processX11Events ();
}
while (!RKGraphicsDeviceBackendTransmitter::streamer.readInBuffer ()) {
RKRBackend::processX11Events ();
- connection->waitForReadyRead (10);
+ if (!connection->waitForReadyRead (10)) {
+ if (!RKGraphicsDeviceBackendTransmitter::connectionAlive ()) {
+ RKGraphicsDeviceBackendTransmitter::mutex.unlock ();
+ Rf_error ("RKWard Graphics connection has shut down");
+ }
+ }
}
} END_SUSPEND_INTERRUPTS;
}
@@ -72,80 +82,89 @@
#include <QRectF>
-#define RK_TEST_COL 0xABCDEF01
-#if not ((R_RED(RK_TEST_COL) == 0x01) && (R_GREEN(RK_TEST_COL) == 0xEF) && (R_BLUE(RK_TEST_COL) == 0xCD) && (R_ALPHA(RK_TEST_COL) == 0xAB))
-#error R color format has changed!
-#endif
+// This ought to be optimized away by the compiler:
+#define SAFE_LINE_END(lend) (quint8) (lend == GE_ROUND_CAP ? RoundLineCap : (lend == GE_BUTT_CAP ? ButtLineCap : SquareLineCap))
+// This ought to be optimized away by the compiler:
+#define SAFE_LINE_JOIN(ljoin) (quint8) (ljoin == GE_ROUND_JOIN ? RoundJoin : (ljoin == GE_BEVEL_JOIN ? BevelJoin : MitreJoin))
// I'd love to convert to QColor, directly, but that's in QtGui, not QtCore. QRgb used different byte ordering
-#define WRITE_COLOR_BYTES(col) (quint8) R_RED (col) << (quint8) R_GREEN (col) << (quint8) R_BLUE (col) << (quint8) R_ALPHA (col)
-#define WRITE_HEADER(x,dev) (qint8) x << (quint8) static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->devnum
-#define WRITE_COL() WRITE_COLOR_BYTES (gc->col)
-#define WRITE_PEN() WRITE_COL() << (double) gc->lwd << (qint32) gc->lty
-#define WRITE_LINE_ENDS() (quint8) gc->lend << (quint8) gc->ljoin << gc->lmitre
-#define WRITE_FILL() WRITE_COLOR_BYTES (gc->fill)
-#define WRITE_FONT(dev) gc->cex << gc->ps << gc->lineheight << (quint8) gc->fontface << (gc->fontfamily[0] ? QString (gc->fontfamily) : (static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->default_family))
+#define WRITE_COLOR_BYTES(col) \
+ if (col == NA_INTEGER) RKD_OUT_STREAM << (quint8) 0xFF << (quint8) 0xFF << (quint8) 0xFF << (quint8) 0x00; \
+ else RKD_OUT_STREAM << (quint8) R_RED (col) << (quint8) R_GREEN (col) << (quint8) R_BLUE (col) << (quint8) R_ALPHA (col)
+#define WRITE_HEADER(x,dev) \
+ RKD_OUT_STREAM << (qint8) x << (quint8) static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->devnum
+#define WRITE_COL() \
+ WRITE_COLOR_BYTES (gc->col)
+#define WRITE_PEN() \
+ WRITE_COL(); RKD_OUT_STREAM << (double) gc->lwd << (qint32) gc->lty
+// actually lmitre is only needed if linejoin is GE_MITRE_JOIN, so we could optimize a bit
+#define WRITE_LINE_ENDS() \
+ RKD_OUT_STREAM << SAFE_LINE_END (gc->lend) << SAFE_LINE_JOIN (gc->ljoin) << gc->lmitre
+#define WRITE_FILL() \
+ WRITE_COLOR_BYTES (gc->fill)
+#define WRITE_FONT(dev) \
+ RKD_OUT_STREAM << gc->cex << gc->ps << gc->lineheight << (quint8) gc->fontface << (gc->fontfamily[0] ? QString (gc->fontfamily) : (static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->default_family))
static void RKD_Create (double width, double height, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDCreate, dev);
+ WRITE_HEADER (RKDCreate, dev);
RKD_OUT_STREAM << width << height;
}
static void RKD_Circle (double x, double y, double r, R_GE_gcontext *gc, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDCircle, dev);
+ WRITE_HEADER (RKDCircle, dev);
RKD_OUT_STREAM << x << y << r;
- RKD_OUT_STREAM << WRITE_PEN ();
- RKD_OUT_STREAM << WRITE_FILL ();
+ WRITE_PEN ();
+ WRITE_FILL ();
}
static void RKD_Line (double x1, double y1, double x2, double y2, R_GE_gcontext *gc, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDLine, dev);
+ WRITE_HEADER (RKDLine, dev);
RKD_OUT_STREAM << x1 << y1 << x2 << y2;
- RKD_OUT_STREAM << WRITE_PEN ();
- RKD_OUT_STREAM << WRITE_LINE_ENDS ();
+ WRITE_PEN ();
+ WRITE_LINE_ENDS ();
}
static void RKD_Polygon (int n, double *x, double *y, R_GE_gcontext *gc, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDPolygon, dev);
+ WRITE_HEADER (RKDPolygon, dev);
quint32 _n = qMin (n, 1 << 25); // skip stuff exceeding reasonable limits to keep protocol simple
RKD_OUT_STREAM << _n;
for (quint32 i = 0; i < _n; ++i) {
RKD_OUT_STREAM << x[i] << y[i];
}
- RKD_OUT_STREAM << WRITE_PEN ();
- RKD_OUT_STREAM << WRITE_LINE_ENDS ();
- RKD_OUT_STREAM << WRITE_FILL ();
+ WRITE_PEN ();
+ WRITE_LINE_ENDS ();
+ WRITE_FILL ();
}
static void RKD_Polyline (int n, double *x, double *y, R_GE_gcontext *gc, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDPolyline, dev);
+ WRITE_HEADER (RKDPolyline, dev);
quint32 _n = qMin (n, 1 << 25); // skip stuff exceeding reasonable limits to keep protocol simple
RKD_OUT_STREAM << _n;
for (quint32 i = 0; i < _n; ++i) {
RKD_OUT_STREAM << x[i] << y[i];
}
- RKD_OUT_STREAM << WRITE_PEN ();
- RKD_OUT_STREAM << WRITE_LINE_ENDS ();
+ WRITE_PEN ();
+ WRITE_LINE_ENDS ();
}
static void RKD_Rect (double x0, double y0, double x1, double y1, R_GE_gcontext *gc, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDPolyline, dev);
+ WRITE_HEADER (RKDRect, dev);
RKD_OUT_STREAM << QRectF (x0, y0, x1-x0, y1-y0);
- RKD_OUT_STREAM << WRITE_PEN ();
- RKD_OUT_STREAM << WRITE_LINE_ENDS ();
- RKD_OUT_STREAM << WRITE_FILL ();
+ WRITE_PEN ();
+ WRITE_LINE_ENDS ();
+ WRITE_FILL ();
}
static QString RToQString (const char *str, bool is_symbol) {
if (is_symbol) {
int n = strlen (str);
- char outbuf[n*4 + 4];
+ char outbuf[n*4 + 16];
Rf_AdobeSymbol2utf8 (outbuf, str, n*4);
return QString::fromUtf8 (outbuf);
}
@@ -154,18 +173,18 @@
static void RKD_TextUTF8 (double x, double y, const char *str, double rot, double hadj, R_GE_gcontext *gc, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDTextUTF8, dev);
+ WRITE_HEADER (RKDTextUTF8, dev);
RKD_OUT_STREAM << x << y << RToQString (str, gc->fontface == 5) << rot << hadj;
- RKD_OUT_STREAM << WRITE_COL ();
- RKD_OUT_STREAM << WRITE_FONT (dev);
+ WRITE_COL ();
+ WRITE_FONT (dev);
}
static double RKD_StrWidthUTF8 (const char *str, R_GE_gcontext *gc, pDevDesc dev) {
{
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDStrWidthUTF8, dev);
+ WRITE_HEADER (RKDStrWidthUTF8, dev);
RKD_OUT_STREAM << RToQString (str, gc->fontface == 5);
- RKD_OUT_STREAM << WRITE_FONT (dev);
+ WRITE_FONT (dev);
}
double ret;
{
@@ -177,14 +196,14 @@
static void RKD_NewPage (R_GE_gcontext *gc, pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDNewPage, dev);
- RKD_OUT_STREAM << WRITE_FILL ();
+ WRITE_HEADER (RKDNewPage, dev);
+ WRITE_FILL ();
}
static void RKD_MetricInfo (int c, R_GE_gcontext *gc, double* ascent, double* descent, double* width, pDevDesc dev) {
{
RKGraphicsDataStreamWriteGuard wguard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDMetricInfo, dev);
+ WRITE_HEADER (RKDMetricInfo, dev);
QChar unichar;
if (c < 0) { unichar = QChar (-c); }
else if ((gc->fontface == 5) || (!mbcslocale)) {
@@ -198,28 +217,27 @@
unichar = QChar (c);
}
RKD_OUT_STREAM << unichar;
- RKD_OUT_STREAM << WRITE_FONT (dev);
+ WRITE_FONT (dev);
}
{
RKGraphicsDataStreamReadGuard rguard;
RKD_IN_STREAM >> *ascent >> *descent >> *width;
-//qDebug ("for char %d: a %f, d %f, w %f", c, *ascent, *descent, *width);
}
}
static void RKD_Close (pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDClose, dev);
+ WRITE_HEADER (RKDClose, dev);
}
static void RKD_Activate (pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDActivate, dev);
+ WRITE_HEADER (RKDActivate, dev);
}
static void RKD_Deactivate (pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDDeActivate, dev);
+ WRITE_HEADER (RKDDeActivate, dev);
}
static void RKD_Clip (double left, double right, double top, double bottom, pDevDesc dev) {
@@ -228,7 +246,7 @@
dev->clipTop = top;
dev->clipBottom = bottom;
RKGraphicsDataStreamWriteGuard guard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDClip, dev);
+ WRITE_HEADER (RKDClip, dev);
RKD_OUT_STREAM << QRectF (left, top, right - left, bottom - top);
}
@@ -245,14 +263,12 @@
static Rboolean RKD_Locator (double *x, double *y, pDevDesc dev) {
{
RKGraphicsDataStreamWriteGuard wguard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDLocator, dev);
+ WRITE_HEADER (RKDLocator, dev);
}
{
RKGraphicsDataStreamReadGuard rguard;
bool ok;
- RKD_IN_STREAM >> ok;
- RKD_IN_STREAM >> *x;
- RKD_IN_STREAM >> *y;
+ RKD_IN_STREAM >> ok >> *x >> *y;
if (ok) return (Rboolean) TRUE;
return (Rboolean) FALSE;
}
@@ -261,7 +277,7 @@
static Rboolean RKD_NewFrameConfirm (pDevDesc dev) {
{
RKGraphicsDataStreamWriteGuard wguard;
- RKD_OUT_STREAM << WRITE_HEADER (RKDNewPageConfirm, dev);
+ WRITE_HEADER (RKDNewPageConfirm, dev);
}
{
RKGraphicsDataStreamReadGuard rguard;
More information about the rkward-tracker
mailing list