[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