[rkward-cvs] SF.net SVN: rkward-code:[4626] branches/development_branches/ rkward_graphpics_device/rkward/rbackend/rkwarddevice
tfry at users.sf.net
tfry at users.sf.net
Sat Mar 23 19:27:05 UTC 2013
Revision: 4626
http://sourceforge.net/p/rkward/code/4626
Author: tfry
Date: 2013-03-23 19:27:03 +0000 (Sat, 23 Mar 2013)
Log Message:
-----------
It starts to become visible (most drawing ops not yet implemented)
Modified Paths:
--------------
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/CMakeLists.txt
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.h
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
Added Paths:
-----------
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/CMakeLists.txt
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/CMakeLists.txt 2013-03-23 14:51:00 UTC (rev 4625)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/CMakeLists.txt 2013-03-23 19:27:03 UTC (rev 4626)
@@ -10,6 +10,7 @@
SET (
rkgraphicsdevice_frontend_SRCS
rkgraphicsdevice_frontendtransmitter.cpp
+ rkgraphicsdevice.cpp
)
QT4_AUTOMOC(${rkgraphicsdevice_frontend_SRCS})
Added: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp (rev 0)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp 2013-03-23 19:27:03 UTC (rev 4626)
@@ -0,0 +1,106 @@
+/***************************************************************************
+ rkgraphicsdevice_backendtransmitter - description
+ -------------------
+ begin : Mon Mar 18 20:06:08 CET 2013
+ copyright : (C) 2013 by Thomas Friedrichsmeier
+ email : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/******************************* ACKNOWLEDGEMENT ***************************
+ *
+ * The drawing functions in this file are heavily inspired, in some parts even copied from package qtutils, version 0.1-3
+ * by Deepayan Sarkar. Package qtutils is available from http://qtinterfaces.r-forge.r-project.org
+ * under GNU LPGL 2 or later.
+ *
+ ***************************************************************************/
+
+#include "rkgraphicsdevice.h"
+
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QGraphicsRectItem>
+
+#include "../../debug.h"
+
+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->show ();
+ item_z = clip_z = 0;
+ setClip (scene->sceneRect ());
+}
+
+RKGraphicsDevice::~RKGraphicsDevice () {
+ RK_TRACE (GRAPHICS_DEVICE);
+ delete view;
+}
+
+RKGraphicsDevice* RKGraphicsDevice::newDevice (int devnum, double width, double height) {
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ if (devices.contains (devnum)) {
+ RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Graphics device number %d already exists while trying to create it", devnum);
+ closeDevice (devnum);
+ }
+ RKGraphicsDevice* dev = new RKGraphicsDevice (width, height);
+ devices.insert (devnum, dev);
+ return (dev);
+}
+
+void RKGraphicsDevice::closeDevice (int devnum) {
+ RK_TRACE (GRAPHICS_DEVICE);
+
+ RK_ASSERT (devices.contains (devnum));
+ devices.take (devnum)->deleteLater ();
+}
+
+void RKGraphicsDevice::setClip (const QRectF& new_clip) {
+ RK_TRACE (GRAPHICS_DEVICE);
+ clip = scene->addRect (new_clip, QPen (Qt::NoPen));
+ clip->setZValue (clip_z += .1);
+ clip->setFlags (QGraphicsItem::ItemClipsChildrenToShape);
+ item_z = 0;
+}
+
+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, clip);
+ circle->setPen (pen);
+ circle->setBrush (brush);
+ circle->setZValue (item_z += .1);
+}
+
+void RKGraphicsDevice::line (double x1, double y1, double x2, double y2, const QPen& pen) {
+ QGraphicsLineItem* line = new QGraphicsLineItem (x1, y1, x2, y2, clip);
+ line->setPen (pen);
+ line->setZValue (item_z += .1);
+}
+
+double RKGraphicsDevice::strWidth (const QString& text, const QFont& font) {
+ QGraphicsSimpleTextItem t (text, 0);
+ 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);
+ text->setPlainText (_text);
+ text->setFont (font);
+ 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);
+}
Added: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h (rev 0)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h 2013-03-23 19:27:03 UTC (rev 4626)
@@ -0,0 +1,51 @@
+/***************************************************************************
+ rkgraphicsdevice_backendtransmitter - description
+ -------------------
+ begin : Mon Mar 18 20:06:08 CET 2013
+ copyright : (C) 2013 by Thomas Friedrichsmeier
+ email : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef RKGRAPHICSDEVICE_H
+#define RKGRAPHICSDEVICE_H
+
+#include <QHash>
+#include <QPen>
+
+class QGraphicsRectItem;
+class QGraphicsView;
+class QGraphicsScene;
+
+/** This is the class that actually does all the drawing for the RKGraphicsDevice */
+class RKGraphicsDevice : public QObject {
+protected:
+ RKGraphicsDevice (double width, double height);
+ ~RKGraphicsDevice ();
+public:
+ static RKGraphicsDevice* newDevice (int devnum, double width, double height);
+ static void closeDevice (int devnum);
+ static QHash<int, RKGraphicsDevice*> devices;
+
+ 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);
+ 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 setClip (const QRectF& new_clip);
+private:
+ QGraphicsScene* scene;
+ QGraphicsView* view;
+ QGraphicsRectItem* clip;
+ double clip_z;
+ double item_z;
+};
+
+#endif
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-23 14:51:00 UTC (rev 4625)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp 2013-03-23 19:27:03 UTC (rev 4626)
@@ -21,11 +21,14 @@
#include <QLocalSocket>
#include <QIODevice>
#include <krandom.h>
+#include <kmessagebox.h>
+#include <klocale.h>
// NOTE: This is but the latest nail in the coffin of the single process variant of RKWard.
// *IF* the RKWard Graphics Device works out as hoped, the single process variant can finally be ditched for good.
#define RKWARD_SPLIT_PROCESS 1
#include "../rkfrontendtransmitter.h"
+#include "rkgraphicsdevice.h"
#include "../../version.h"
#include "../../debug.h"
@@ -68,7 +71,7 @@
QString token_c = QString::fromLocal8Bit (con->readLine ());
token_c.chop (1);
if (token_c != token) {
-#warning TODO error handling
+ KMessageBox::detailedError (0, QString ("<p>%1</p>").arg (i18n ("There has been an error while trying to connect the on-screen graphics backend. This means, on-screen graphics using the RKWard device will not work in this session.")), i18n ("Expected connection token %1, but read connection token %2").arg (token).arg (token_c), i18n ("Error while connection graphics backend"));
con->close ();
return;
}
@@ -78,39 +81,135 @@
connect (connection, SIGNAL (readyRead ()), this, SLOT (newData ()));
}
+static QPen readSimplePen (QDataStream &instream) {
+ quint8 r, g, b, a;
+ double lwd;
+ qint32 lty;
+ instream >> r >> g >> b >> a >> lwd >> lty;
+#warning: Line style!
+ QPen ret;
+ ret.setWidthF (lwd);
+ ret.setColor (QColor (r, g, b, a));
+ return ret;
+}
+
+static QPen readPen (QDataStream &instream) {
+ QPen ret = readSimplePen (instream);
+#warning: Read further attribs!
+ return ret;
+}
+
+static QBrush readBrush (QDataStream &instream) {
+#warning: Read brush!
+ return QBrush ();
+}
+
+static QFont readFont (QDataStream &instream) {
+#warning: Handle all attribs!
+ double cex, ps, lineheight;
+ quint8 fontface;
+ QString fontfamily;
+ instream >> cex >> ps >> lineheight >> fontface >> fontfamily;
+ QFont ret (fontfamily);
+ ret.setPointSizeF (cex*ps);
+ return ret;
+}
+
void RKGraphicsDeviceFrontendTransmitter::newData () {
-// RK_TRACE (GRAPHICS_DEVICE);
+ RK_TRACE (GRAPHICS_DEVICE);
- if (!streamer.readInBuffer ()) return; // wait for more data to come in
+ while (connection->bytesAvailable ()) {
+ if (!streamer.readInBuffer ()) return; // wait for more data to come in
- quint8 opcode, devnum;
- streamer.instream >> opcode;
- streamer.instream >> devnum;
- RK_DEBUG (DL_WARNING, GRAPHICS_DEVICE, "Received transmission of type %d, devnum %d, size %d", opcode, devnum, streamer.inSize ());
+ quint8 opcode, devnum;
+ streamer.instream >> opcode >> devnum;
+ RK_DEBUG (GRAPHICS_DEVICE, DL_DEBUG, "Received transmission of type %d, devnum %d, size %d", opcode, devnum, streamer.inSize ());
+ RKGraphicsDevice *device = 0;
+ if (devnum && opcode == RKDCreate) {
+ double width, height;
+ streamer.instream >> width >> height;
+ device = RKGraphicsDevice::newDevice (devnum, width, height);
+ } else if (devnum) {
+ device = RKGraphicsDevice::devices.value (devnum);
+ if (!device) {
+ RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Received transmission of type %d for unknown device number %d. Skippping.", opcode, devnum);
+ sendDummyReply (opcode);
+ continue;
+ }
+ }
+
+ if (opcode == RKDCircle) {
+ double x, y, r;
+ streamer.instream >> x >> y >> r;
+ device->circle (x, y, r, readSimplePen (streamer.instream), readBrush (streamer.instream));
+ continue;
+ } 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) {
+ } else if (opcode == RKDPolyline) {
+ } else if (opcode == RKDRect) {
+ } 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) {
+ } else if (opcode == RKDTextUTF8) {
+ double x, y, rot, hadj;
+ QString out;
+ QRgb col;
+ streamer.instream >> x >> y >> out >> rot >> hadj >> col;
+ device->text (x, y, out, rot, hadj, col, readFont (streamer.instream));
+ continue;
+ } else if (opcode == RKDNewPage) {
+ } else if (opcode == RKDClose) {
+ } else if (opcode == RKDActivate) {
+ } else if (opcode == RKDDeActivate) {
+ } else if (opcode == RKDClip) {
+ } else if (opcode == RKDMode) {
+ } else if (opcode == RKDClip) {
+ } else if (opcode == RKDLocator) {
+ } else if (opcode == RKDNewPageConfirm) {
+ }
+
+ 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);
+ }
+}
+
+void RKGraphicsDeviceFrontendTransmitter::sendDummyReply (quint8 opcode) {
+ RK_TRACE (GRAPHICS_DEVICE);
+
if (opcode == RKDLocator) {
bool ok = true;
double x, y;
x = y = 0;
streamer.outstream << ok << x << y;
- streamer.writeOutBuffer ();
} else if (opcode == RKDMetricInfo) {
double ascent, descent, width;
ascent = descent = width = 0.1;
streamer.outstream << ascent << descent << width;
- streamer.writeOutBuffer ();
} else if (opcode == RKDNewPageConfirm) {
bool ok = true;
streamer.outstream << ok;
- streamer.writeOutBuffer ();
} else if (opcode == RKDStrWidthUTF8) {
double width = 1;
streamer.outstream << width;
- streamer.writeOutBuffer ();
+ } else {
+ return; // nothing to write
}
- if (connection->bytesAvailable ()) newData ();
+ streamer.writeOutBuffer ();
}
-#include "rkgraphicsdevice_frontendtransmitter.moc"
\ No newline at end of file
+
+#include "rkgraphicsdevice_frontendtransmitter.moc"
Modified: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.h
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.h 2013-03-23 14:51:00 UTC (rev 4625)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.h 2013-03-23 19:27:03 UTC (rev 4626)
@@ -36,6 +36,7 @@
void newConnection ();
private:
void setupServer ();
+ void sendDummyReply (quint8 opcode);
QString server_name;
QIODevice *connection;
QLocalServer *local_server;
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-23 14:51:00 UTC (rev 4625)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h 2013-03-23 19:27:03 UTC (rev 4626)
@@ -40,24 +40,24 @@
enum RKDOpcodes {
// Asynchronous operations
- RKDCreate,
+ RKDCreate, // 0
RKDCircle,
RKDLine,
RKDPolygon,
RKDPolyline,
- RKDRect,
+ RKDRect, // 5
RKDTextUTF8,
RKDNewPage,
RKDClose,
RKDActivate,
- RKDDeActivate,
+ RKDDeActivate, // 10
RKDClip,
RKDMode,
// Synchronous operations
RKD_First_Synchronous_Request,
RKDStrWidthUTF8,
- RKDMetricInfo,
+ RKDMetricInfo, // 15
RKDLocator,
RKDNewPageConfirm
};
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-23 14:51:00 UTC (rev 4625)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp 2013-03-23 19:27:03 UTC (rev 4626)
@@ -69,15 +69,19 @@
delete (desc);
desc = 0;
} else {
- desc->devnum = curDevice ();
- RKD_Create (desc->width, desc->height, dev);
+ desc->devnum = 0; // graphics engine will send an Activate-event, before we were even
+ // able to see our own devnum and call RKD_Create. Therefore, intialize
+ // devnum to 0, so as not to confuse the frontend
pGEDevDesc gdd = GEcreateDevDesc (dev);
gdd->displayList = R_NilValue;
GEaddDevice2 (gdd, "RKGraphicsDevice");
}
} END_SUSPEND_INTERRUPTS;
- if (!desc) {
+ if (desc) {
+ desc->devnum = curDevice ();
+ RKD_Create (desc->width, desc->height, dev);
+ } else {
Rf_error("unable to start device");
}
}
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-23 14:51:00 UTC (rev 4625)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp 2013-03-23 19:27:03 UTC (rev 4626)
@@ -27,8 +27,6 @@
#include <R_ext/GraphicsEngine.h>
}
-#include <QRectF>
-
#define RKD_IN_STREAM RKGraphicsDeviceBackendTransmitter::streamer.instream
#define RKD_OUT_STREAM RKGraphicsDeviceBackendTransmitter::streamer.outstream
@@ -72,11 +70,20 @@
}
};
+#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
+
+// 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() (qint32) gc->col
-#define WRITE_PEN() WRITE_COL() << gc->col << (double) gc->lwd << (qint32) gc->lty
+#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() (qint32) gc->fill
+#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))
static void RKD_Create (double width, double height, pDevDesc dev) {
@@ -90,6 +97,7 @@
RKD_OUT_STREAM << WRITE_HEADER (RKDCircle, dev);
RKD_OUT_STREAM << x << y << r;
RKD_OUT_STREAM << WRITE_PEN ();
+ RKD_OUT_STREAM << WRITE_FILL ();
}
static void RKD_Line (double x1, double y1, double x2, double y2, R_GE_gcontext *gc, pDevDesc dev) {
@@ -97,6 +105,7 @@
RKD_OUT_STREAM << WRITE_HEADER (RKDLine, dev);
RKD_OUT_STREAM << x1 << y1 << x2 << y2;
RKD_OUT_STREAM << WRITE_PEN ();
+ RKD_OUT_STREAM << WRITE_LINE_ENDS ();
}
static void RKD_Polygon (int n, double *x, double *y, R_GE_gcontext *gc, pDevDesc dev) {
More information about the rkward-tracker
mailing list