[rkward-cvs] SF.net SVN: rkward-code:[4612] branches/development_branches/ rkward_graphpics_device/rkward/rbackend
tfry at users.sf.net
tfry at users.sf.net
Wed Mar 20 19:54:31 UTC 2013
Revision: 4612
http://sourceforge.net/p/rkward/code/4612
Author: tfry
Date: 2013-03-20 19:54:28 +0000 (Wed, 20 Mar 2013)
Log Message:
-----------
Add first chunk of code for the experimental new graphics device. This is nowhere near compilable.
Added Paths:
-----------
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.h
Added: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp (rev 0)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp 2013-03-20 19:54:28 UTC (rev 4612)
@@ -0,0 +1,160 @@
+/***************************************************************************
+ rkgraphicsdevice - 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 ***************************
+ *
+ * Much of the code in this file is based on, or 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 <QRect>
+#include "../rkrsupport.h"
+#include "rkgraphicsdevice_stubs.h"
+
+struct RKGraphicsDeviceDesc {
+ bool initRDevDesc (pDevDesc dev, double pointsize);
+ int devnum;
+ double width, height;
+ QString default_family;
+ pDevDesc rdevdesc;
+};
+
+#define RKGD_DPI 72
+
+void RKStartGraphicsDevice (double width, double height, double pointsize, const QString &family) {
+ if (width <= 0 || height <= 0) {
+ Rf_error ("Invalid width or height: (%g, %g)", width, height);
+ }
+ RKGraphicsDeviceDesc *desc = new RKGraphicsDeviceDesc;
+ desc->width = width * RKGD_DPI;
+ desc->height = height * RKGD_DPI;
+ desc->default_family = family;
+// _scene->setSceneRect(0.0, 0.0, width, height);
+
+ R_GE_checkVersionOrDie (R_GE_version);
+ R_CheckDeviceAvailable ();
+ BEGIN_SUSPEND_INTERRUPTS {
+ pDevDesc dev;
+ /* Allocate and initialize the device driver data */
+ if (!(dev = (pDevDesc) calloc (1, sizeof(DevDesc))))
+ return 0; /* or error() */
+ /* set up device driver or free 'dev' and error() */
+ if (!desc->initRDevDesc (dev, pointsize, desc)) {
+ free (dev);
+ delete (desc);
+ Rf_error("unable to start device");
+ }
+ pGEDevDesc gdd = GEcreateDevDesc (dev);
+ gdd->displayList = R_NilValue;
+ GEaddDevice2 (gdd, "QTScene");
+ } END_SUSPEND_INTERRUPTS;
+
+ desc->devnum = curDevice ();
+}
+
+SEXP RKStartGraphicsDevice (SEXP width, SEXP height, SEXP pointsize, SEXP family
+#warning TODO: add more params for compatibility with X11
+) {
+ RKStartGraphicsDevice (Rf_asReal (width), Rf_asReal (height), Rf_asReal (pointsize), RKRSupport::SEXPToString (family));
+ return R_NilValue;
+}
+
+bool RKGraphicsDeviceDesc::initRDevDesc (pDevDesc dev, double pointsize) {
+ dev->deviceSpecific = (void *) this;
+
+ // pointsize?
+
+ /*
+ * Initial graphical settings
+ */
+ dev->startfont = 1;
+ dev->startps = pointsize;
+ dev->startcol = R_RGB(0, 0, 0);
+ dev->startfill = R_TRANWHITE;
+ dev->startlty = LTY_SOLID;
+ dev->startgamma = 1;
+ /*
+ * Device physical characteristics
+ */
+ dev->left = dev->clipLeft = 0;
+ 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->xCharOffset = 0.4900;
+ dev->yCharOffset = 0.3333;
+ dev->yLineBias = 0.1;
+ dev->ipr[0] = 1.0 / RKGD_DPI;
+ dev->ipr[1] = 1.0 / RKGD_DPI;
+ /*
+ * Device capabilities
+ */
+ dev->canClip = FALSE; // FIXME. can clip, but then selection becomes weird
+ dev->canHAdj = 2;
+ dev->canChangeGamma = FALSE;
+ dev->displayListOn = TRUE;
+
+ dev->hasTextUTF8 = TRUE;
+ dev->textUTF8 = (void (*)()) RKD_TextUTF8;
+ dev->strWidthUTF8 = (double (*)()) RKD_StrWidthUTF8;
+ dev->wantSymbolUTF8 = TRUE;
+ dev->useRotatedTextInContour = TRUE;
+
+ dev->haveTransparency = 2;
+ dev->haveTransparentBg = 2; // FIXME. Do we really? Check.
+ dev->haveRaster = 1;
+ dev->haveCapture = 1;
+ dev->haveLocator = 2;
+
+ /*
+ * Mouse events
+ */
+// dev->canGenMouseDown = TRUE;
+// dev->canGenMouseMove = TRUE;
+// dev->canGenMouseUp = TRUE;
+// dev->canGenKeybd = TRUE;
+
+ // gettingEvent; This is set while getGraphicsEvent is actively
+ // looking for events
+
+ /*
+ * Device functions
+ */
+ dev->activate = (void (*)()) RKD_Activate;
+ dev->circle = (void (*)()) RKD_Circle;
+ dev->clip = (void (*)()) RKD_Clip;
+ dev->close = (void (*)()) RKD_Close;
+ dev->deactivate = (void (*)()) RKD_Deactivate;
+ dev->locator = (Rboolean (*)()) RKD_Locator;
+ dev->line = (void (*)()) RKD_Line;
+ dev->metricInfo = (void (*)()) RKD_MetricInfo;
+ dev->mode = (void (*)()) RKD_Mode;
+ dev->newPage = (void (*)()) RKD_NewPage;
+ dev->polygon = (void (*)()) RKD_Polygon;
+ dev->polyline = (void (*)()) RKD_Polyline;
+ dev->rect = (void (*)()) RKD_Rect;
+ dev->size = NULL; // (void (*)()) RKD_Size;
+ // dev->onexit = (void (*)()) RKD_OnExit; NULL is OK
+ // dev->getEvent = SEXP (*getEvent)(SEXP, const char *);
+ dev->newFrameConfirm = (Rboolean (*)()) RKD_NewFrameConfirm;
+
+ return true;
+}
+
Added: branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.h
===================================================================
--- branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.h (rev 0)
+++ branches/development_branches/rkward_graphpics_device/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.h 2013-03-20 19:54:28 UTC (rev 4612)
@@ -0,0 +1,210 @@
+// NOTE: heavy copying from QGraphicsSceneDevice
+#include <QRect>
+#include <R_ext/GraphicsEngine.h>
+#include <limits.h>
+
+#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() << (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_FONT(dev) gc->cex << gc->ps << gc->lineheight << (quint8) gc->fontface << gc->fontfamily[0] ? QString (gc->fontfamily) : (static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->default_family)
+
+QByteArray aux_buffer;
+QDataStream aux_stream;
+QByteArray buffer;
+QDataStream connection (&buffer);
+QMutex rkwarddeviceprotocolmutex;
+
+class RKSocketDataStreamWriteGuard {
+ RKSocketDataStreamWriteGuard () {
+ rkwarddeviceprotocolmutex.lock ();
+ }
+ ~RKSocketDataStreamWriteGuard () {
+ aux_stream << (quint32) buffer.size ();
+ device.write (aux_stream);
+ aux_stream.resize (0);
+ device.write (buffer);
+ buffer.resize (0);
+ rkwarddeviceprotocolmutex.unlock ();
+ }
+};
+
+enum {
+ // Asynchronous operations
+ RKDCircle,
+ RKDLine,
+ RKDPolygon,
+ RKDPolyline,
+ RKDRect,
+ RKDTextUTF8,
+ RKDNewPage,
+ RKDClose,
+ RKDActivate,
+ RKDDeActivate,
+ RKDClip,
+ RKDMode,
+
+ // Synchronous operations
+ RKD_First_Synchronous_Request,
+ RKDStrWidthUTF8,
+ RKDMetricInfo,
+ RKDLocator,
+ RKDNewPageConfirm
+} OpCodes;
+
+static void RKD_Circle (double x, double y, double r, R_GE_gcontext *gc, pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDCircle, dev);
+ connection << x << y << r;
+ connection << WRITE_PEN ();
+}
+
+static void RKD_Line (double x1, double y1, double x2, double y2, R_GE_gcontext *gc, pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDLine, dev);
+ connection << x1 << y1 << x2 << y2;
+ connection << WRITE_PEN ();
+}
+
+static void RKD_Polygon (int n, double *x, double *y, R_GE_gcontext *gc, pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDPolygon, dev);
+ quint32 _n = qMax (n, std::numeric_limits<quint32>::max());
+ connection << _n;
+ for (quint32 i; i < n; ++i) {
+ connection << x[i] << y[i];
+ }
+ connection << WRITE_PEN ();
+ connection << WRITE_LINE_ENDS ();
+ connection << WRITE_FILL ();
+}
+
+static void RKD_Polyline (int n, double *x, double *y, R_GE_gcontext *gc, pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDPolyline, dev);
+ quint32 _n = qMax (n, std::numeric_limits<quint32>::max());
+ connection << _n;
+ for (quint32 i; i < n; ++i) {
+ connection << x[i] << y[i];
+ }
+ connection << WRITE_PEN ();
+ connection << WRITE_LINE_ENDS ();
+}
+
+static void RKD_Rect (double x0, double y0, double x1, double y1, R_GE_gcontext *gc, pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDPolyline, dev);
+ connection << QRectF (x0, y0, x1-x0, y1-y0);
+ connection << WRITE_PEN ();
+ connection << WRITE_LINE_ENDS ();
+ connection << WRITE_FILL ();
+}
+
+static void RKD_TextUTF8 (double x, double y, char *str, double rot, double hadj, R_GE_gcontext *gc, pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDTextUTF8, dev);
+ connection << x << y << QString::fromUtf8 (str) << rot << hadj;
+ connection << WRITE_COL ();
+ connection << WRITE_FONT (dev);
+}
+
+static double RKD_StrWidthUTF8 (char *str, R_GE_gcontext *gc, pDevDesc dev) {
+ {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDStrWidthUTF8, dev);
+ connection << QString::fromUtf8 (str);
+ connection << WRITE_FONT (dev);
+ }
+ double ret;
+ {
+ RKSocketDataStreamReadGuard guard;
+ ret << connection;
+ }
+ return ret;
+}
+
+static void RKD_NewPage (R_GE_gcontext *gc, pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDNewPage, dev);
+ connection << WRITE_FILL ();
+}
+
+static void RKD_MetricInfo (int c, R_GE_gcontext *gc, double* ascent, double* descent, double* width, pDevDesc dev) {
+ {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDMetricInfo, dev);
+ connection << QChar (c);
+ connection << WRITE_FONT (dev);
+ }
+ {
+ RKSocketDataStreamReadGuard guard;
+ *ascent << connection;
+ *descent << connection;
+ *width << connection;
+ }
+}
+
+static void RKD_Close (pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDClose, dev);
+}
+
+static void RKD_Activate(pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDActivate, dev);
+}
+
+static void RKD_Deactivate(pDevDesc dev) {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDDeActivate, dev);
+}
+
+static void RKD_Clip(double left, double right, double top, double bottom, pDevDesc dev) {
+ dev->clipLeft = left;
+ dev->clipRight = right;
+ dev->clipTop = top;
+ dev->clipBottom = bottom;
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDClip, dev);
+ connection << QRectF (left, top, right - left, bottom - top);
+}
+
+static void RKD_Mode (int mode, pDevDesc dev) {
+/* Left empty for now. 1 is start signal, 0 is stop signal. Might be useful for flushing, though.
+
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDMode, dev);
+ connectoin << (qint8) mode; */
+}
+
+static Rboolean RKD_Locator (double *x, double *y, pDevDesc dev) {
+ {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDLocator, dev);
+ }
+#warning TODO: handle cancellation from backend
+ {
+ RKSocketDataStreamReadGuard guard;
+ bool ok;
+ ok << connection;
+ *x << connection;
+ *y << connection;
+ if (ok) return TRUE;
+ return FALSE;
+ }
+}
+
+static Rboolean RKD_NewFrameConfirm (pDevDesc dev) {
+ {
+ RKSocketDataStreamWriteGuard guard;
+ connection << WRITE_HEADER (RKDNewPageConfirm, dev);
+ }
+#warning TODO: handle cancellation from backend
+ {
+ RKSocketDataStreamReadGuard guard;
+ bool ok << connection;
+ if (ok) return TRUE;
+ return FALSE;
+ }
+}
More information about the rkward-tracker
mailing list