[education/rkward] /: Implement capabilities report for RK()-device
Thomas Friedrichsmeier
null at kde.org
Tue Jul 30 17:00:07 BST 2024
Git commit 1ca0fed0b7377f80b8664766a25ee663db4504e5 by Thomas Friedrichsmeier.
Committed on 30/07/2024 at 15:59.
Pushed by tfry into branch 'master'.
Implement capabilities report for RK()-device
M +1 -0 ChangeLog
M +1 -0 rkward/rbackend/rkrapi.h
M +1 -1 rkward/rbackend/rkrbackendprotocol_backend.cpp
M +72 -3 rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
M +2 -2 rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
M +4 -0 rkward/rkward.cpp
https://invent.kde.org/education/rkward/-/commit/1ca0fed0b7377f80b8664766a25ee663db4504e5
diff --git a/ChangeLog b/ChangeLog
index bb0ef5bf4..a3d126f76 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,5 @@
--- Version 0.8.1 - UNRELEASED
+- Fixed: Implement capbilities report for RK() device (may fix graphics limitation, but also potential crashes with R >= 4.2.0)
- Fixed: Adjustments to changes in R devel (for compatibility with the future R 4.5.x)
- Fixed: Potential crash on "spontaneous" R output (originating from event handlers such as tcl)
- Fixed: commandArgs() would show incorrect options
diff --git a/rkward/rbackend/rkrapi.h b/rkward/rbackend/rkrapi.h
index e72f817e2..80e7fef3e 100644
--- a/rkward/rbackend/rkrapi.h
+++ b/rkward/rbackend/rkrapi.h
@@ -282,6 +282,7 @@ IMPORT_R_API(SET_TAG);
IMPORT_R_API(SET_TYPEOF);
IMPORT_R_API(STRING_ELT);
IMPORT_R_API(SET_STRING_ELT);
+IMPORT_R_API(SET_VECTOR_ELT);
IMPORT_R_API(SET_PRENV);
IMPORT_R_API(SET_PRVALUE);
IMPORT_R_API(TYPEOF);
diff --git a/rkward/rbackend/rkrbackendprotocol_backend.cpp b/rkward/rbackend/rkrbackendprotocol_backend.cpp
index 4289d3591..efb310cf4 100644
--- a/rkward/rbackend/rkrbackendprotocol_backend.cpp
+++ b/rkward/rbackend/rkrbackendprotocol_backend.cpp
@@ -88,7 +88,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
- RK_Debug::RK_Debug_Flags = RBACKEND;
+ RK_Debug::RK_Debug_Flags = RBACKEND | GRAPHICS_DEVICE;
if (RK_Debug::setupLogFile (QDir::tempPath () + "/rkward.rbackend")) qInstallMessageHandler (RKDebugMessageOutput);
QString servername, rkd_server_name;
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
index b55e578b7..86f80fdf6 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
@@ -34,6 +34,7 @@ struct RKGraphicsDeviceDesc {
};
#include "rkgraphicsdevice_stubs.cpp"
+static SEXP RKD_capabilities(SEXP capabilities);
// No, I do not really understand what this is for.
// Mostly trying to mimick the X11 device's behavior, here.
@@ -192,8 +193,9 @@ bool RKGraphicsDeviceDesc::init (pDevDesc dev, double pointsize, const QStringLi
dev->holdflush = RKD_HoldFlush;
#if R_VERSION >= R_Version (4, 1, 0)
+ static_assert(RKD_RGE_VERSION >= 13);
// NOTE: We need both a compiletime and a runtime check, in order to support running with an R older than what was used at compile time
- if (RFn::R_GE_getVersion() >= 15) {
+ if (RFn::R_GE_getVersion() >= 13) {
// patterns and gradients
dev->setPattern = RKD_SetPattern;
dev->releasePattern = RKD_ReleasePattern;
@@ -204,12 +206,15 @@ bool RKGraphicsDeviceDesc::init (pDevDesc dev, double pointsize, const QStringLi
dev->setMask = RKD_SetMask;
dev->releaseMask = RKD_ReleaseMask;
dev->deviceVersion = qMin(qMin(15, R_GE_version), RFn::R_GE_getVersion());
- dev->deviceClip = TRUE; // for now
+ if (RFn::R_GE_getVersion() >= 14) {
+ dev->deviceClip = TRUE; // for now
+ }
}
#endif
#if R_VERSION >= R_Version (4, 2, 0)
- if (RFn::R_GE_getVersion() >= 16) {
+ static_assert(RKD_RGE_VERSION >= 15);
+ if (RFn::R_GE_getVersion() >= 15) {
// groups
dev->defineGroup = RKD_DefineGroup;
dev->useGroup = RKD_UseGroup;
@@ -219,7 +224,71 @@ bool RKGraphicsDeviceDesc::init (pDevDesc dev, double pointsize, const QStringLi
dev->stroke = RKD_Stroke;
dev->fill = RKD_Fill;
dev->fillStroke = RKD_FillStroke;
+ dev->capabilities = RKD_capabilities;
}
#endif
+
+ // NOTE: When extending support don't forget to adjust dev->devicVersion, above!
+
return true;
}
+
+#if R_VERSION >= R_Version (4, 2, 0)
+static void setCapabilityStruct(SEXP capabilities, int category, std::initializer_list<int> values) {
+ SEXP sub;
+ RFn::Rf_protect(sub = RFn::Rf_allocVector(INTSXP, values.size()));
+ int i = 0;
+ for (auto it = values.begin(); it != values.end(); ++i, ++it) {
+ RFn::INTEGER(sub)[i] = *it;
+ }
+ RFn::SET_VECTOR_ELT(capabilities, category, sub);
+ RFn::Rf_unprotect(1);
+}
+
+static SEXP RKD_capabilities(SEXP capabilities) {
+ RK_TRACE(GRAPHICS_DEVICE);
+
+ setCapabilityStruct(capabilities, R_GE_capability_patterns, {
+ R_GE_linearGradientPattern,
+ R_GE_radialGradientPattern,
+ R_GE_tilingPattern
+ });
+ setCapabilityStruct(capabilities, R_GE_capability_clippingPaths, { 1 });
+ setCapabilityStruct(capabilities, R_GE_capability_masks, { R_GE_luminanceMask });
+ setCapabilityStruct(capabilities, R_GE_capability_compositing, {
+ R_GE_compositeMultiply,
+ R_GE_compositeScreen,
+ R_GE_compositeOverlay,
+ R_GE_compositeDarken,
+ R_GE_compositeLighten,
+ R_GE_compositeColorDodge,
+ R_GE_compositeColorBurn,
+ R_GE_compositeHardLight,
+ R_GE_compositeSoftLight,
+ R_GE_compositeDifference,
+ R_GE_compositeExclusion,
+ R_GE_compositeClear,
+ R_GE_compositeSource,
+ R_GE_compositeOver,
+ R_GE_compositeIn,
+ R_GE_compositeOut,
+ R_GE_compositeAtop,
+ R_GE_compositeDest,
+ R_GE_compositeDestOver,
+ R_GE_compositeDestIn,
+ R_GE_compositeDestOut,
+ R_GE_compositeDestAtop,
+ R_GE_compositeXor,
+ R_GE_compositeAdd,
+ //R_GE_compositeSaturate // not supported in QPainter
+ });
+ setCapabilityStruct(capabilities, R_GE_capability_transformations, { 1 });
+ setCapabilityStruct(capabilities, R_GE_capability_paths, { 1 });
+/*
+#if RKD_RGE_VERSION >= 16 // R >= 4.3.0
+ setCapabilityStruct(capabilities, R_GE_capability_glyphs, { 1 });
+#endif
+*/
+ return capabilities;
+}
+#endif
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
index 06467ad46..3b513b97a 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
@@ -247,8 +247,8 @@ SEXP RKD_AdjustSize(SEXP _devnum, SEXP _id) {
pDevDesc dev = gdev->dev;
// This is called from rkward:::RK.resize(), which in turn may be out of sync with R's device list. Before doing anything,
// double check that this is really the device we think it is.
- if (dev->activate != RKD_Activate) RFn::Rf_error("Not an RKWard device", devnum);
- if (static_cast<RKGraphicsDeviceDesc*>(dev->deviceSpecific)->id != id) RFn::Rf_error("Graphics device mismatch", devnum);
+ if (dev->activate != RKD_Activate) RFn::Rf_error("Not an RKWard device %d", devnum);
+ if (static_cast<RKGraphicsDeviceDesc*>(dev->deviceSpecific)->id != id) RFn::Rf_error("Graphics device mismatch %d", devnum);
{
RKGraphicsDataStreamWriteGuard wguard;
diff --git a/rkward/rkward.cpp b/rkward/rkward.cpp
index a9976fb26..de116d2ca 100644
--- a/rkward/rkward.cpp
+++ b/rkward/rkward.cpp
@@ -964,6 +964,10 @@ void RKWardMainWindow::setRStatus (int status) {
if (rstatus_message) rstatus_message->hide();
setIndictatorColor(statusbar_r_status, KColorScheme::NeutralText, KColorScheme::NeutralBackground);
statusbar_r_status->setToolTip(i18n("The <b>R</b> engine is being initialized."));
+ if (rstatus_message) {
+ delete rstatus_message;
+ rstatus_message = nullptr;
+ }
} else {
setIndictatorColor(statusbar_r_status, KColorScheme::NegativeText, KColorScheme::NegativeBackground);
statusbar_r_status->setToolTip(i18n("The <b>R</b> engine is unavailable."));
More information about the rkward-tracker
mailing list