[education/rkward] rkward/rbackend/rkwarddevice: More transparent mapping of graphics enums that have a direct correspondence between R and Qt
Thomas Friedrichsmeier
null at kde.org
Sat Mar 26 08:53:32 GMT 2022
Git commit 7f98f6874f5933286c3350c448c104edae5ba2cf by Thomas Friedrichsmeier.
Committed on 26/03/2022 at 08:31.
Pushed by tfry into branch 'master'.
More transparent mapping of graphics enums that have a direct correspondence between R and Qt
M +1 -0 rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
M +4 -4 rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
M +29 -21 rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
M +1 -6 rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
https://invent.kde.org/education/rkward/commit/7f98f6874f5933286c3350c448c104edae5ba2cf
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
index a0bf9815..c442c235 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
@@ -273,6 +273,7 @@ void RKGraphicsDevice::destroyPattern(int id) {
void RKGraphicsDevice::startRecordPath() {
RK_TRACE(GRAPHICS_DEVICE);
+ // Not really sure whether R uses nested clipping paths at all, but not a big deal to support them, here.
stashed_paths.append(recorded_path);
recorded_path = QPainterPath();
recording_path = true;
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
index 50fc0f90..b659db46 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
@@ -128,16 +128,16 @@ static QPen readPen (QDataStream &instream) {
quint8 lends, ljoin;
double lmitre;
instream >> lends >> ljoin >> lmitre;
- 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);
+ ret.setCapStyle((Qt::PenCapStyle) mapLineEndStyle(lends));
+ ret.setJoinStyle((Qt::PenJoinStyle) mapLineJoinStyle(ljoin));
+ ret.setMiterLimit(lmitre);
return ret;
}
static QBrush readBrush(QDataStream &instream, RKGraphicsDevice *dev) {
qint8 filltype;
instream >> filltype;
- if (filltype == ColorFill) {
+ if (filltype == ColorFill) {
QColor col = readColor(instream);
return QBrush(col);
} else {
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
index 80e4dc2e..645a804c 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
@@ -44,22 +44,6 @@
*
*/
-/** This enum simply repeats R's line end definitions. It is used to ensure compatibility, 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 compatibility, without the need to include
- * any R headers in the frontend. */
-enum RKLineJoinStyles {
- RoundJoin = 1,
- MitreJoin = 2,
- BevelJoin = 3
-};
-
enum RKDFillType {
ColorFill,
PatternFill
@@ -152,7 +136,7 @@ enum RKDEventCodes {
* While in most cases there _is_ a direct correspondence, the underlying int values cannot be assumed to be the same (and in many cases differ).
* Thus we need a lot of code along the lines "if(value = r_enum_value) return qt_enum_value;".
*
- * As a further complication, we cannot easily include R headers in frontend code, and not easily (arbitray) Qt headers in backend code, thus the
+ * As a further complication, we cannot easily include R headers in frontend code, or (arbitray) Qt headers in backend code, thus the
* above pseudo code will lack either the Qt or the R defintion. At some point we need to map to a value we set ourselves, either a third, rk-specific, enum,
* or a naked int.
*
@@ -164,15 +148,39 @@ enum RKDEventCodes {
*/
#if defined(RKD_BACKEND_CODE)
#define MapEnum(Rval,Ival,Qval) case Rval: return Ival;
-#define MapDefault(Ival,Qval) return Ival;
+#define MapDefault(Message,Ival,Qval) Message; return Ival;
+#define RKD_IN_FRONTEND false
#else
#define MapEnum(Rval,Ival,Qval) case Ival: static_assert(Ival == (int) Qval, "Enum mismatch"); return Qval;
-#define MapDefault(Ival,Qval) return Qval;
+#define MapDefault(Message,Ival,Qval) return Qval;
+#define RKD_IN_FRONTEND true
#define RKD_RGE_VERSION 99999
#endif
+static inline quint8 mapLineEndStyle(quint8 from) {
+ if (RKD_IN_FRONTEND) return from;
+ switch(from) {
+ MapEnum(GE_BUTT_CAP, 0x00, Qt::FlatCap);
+ MapEnum(GE_SQUARE_CAP, 0x10, Qt::SquareCap);
+ MapEnum(GE_ROUND_CAP, 0x20, Qt::RoundCap);
+ }
+ MapDefault({}, 0x00, Qt::FlatCap);
+}
+
+static inline quint8 mapLineJoinStyle(quint8 from) {
+ if (RKD_IN_FRONTEND) return from;
+ switch(from) {
+ MapEnum(GE_MITRE_JOIN, 0x00, Qt::MiterJoin);
+ MapEnum(GE_BEVEL_JOIN, 0x40, Qt::BevelJoin);
+ MapEnum(GE_ROUND_JOIN, 0x80, Qt::RoundJoin);
+ //MapEnum(GE_ROUND_JOIN, 0x100, Qt::SvgMiterJoin); // not available in R, and wouldn't fit in quint8
+ }
+ MapDefault({}, 0x00, Qt::MiterJoin);
+}
+
#if RKD_RGE_VERSION >= 15
-static int mapCompostionModeEnum(int from) {
+static inline int mapCompostionModeEnum(int from) {
+ if (RKD_IN_FRONTEND) return from;
switch(from) {
MapEnum(R_GE_compositeClear, 2, QPainter::CompositionMode_Clear);
MapEnum(R_GE_compositeSource, 3, QPainter::CompositionMode_Source);
@@ -201,7 +209,7 @@ static int mapCompostionModeEnum(int from) {
// Unsupported in Qt:
// MapEnum(R_GE_compositeSaturate, xx, yy)
}
- MapDefault(0, QPainter::CompositionMode_SourceOver);
+ MapDefault(Rf_warning("Unsupported enumeration value %d", from), 0, QPainter::CompositionMode_SourceOver);
}
#endif
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
index 4dc7cdd3..90ed87b4 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
@@ -162,11 +162,6 @@ public:
#include <QRectF>
#include <QSizeF>
-// 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
// TODO: is the check against NA_INTEGER needed at all?
#define WRITE_COLOR_BYTES(col) \
@@ -181,7 +176,7 @@ public:
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
+ RKD_OUT_STREAM << (quint8) mapLineEndStyle(gc->lend) << (quint8) mapLineJoinStyle(gc->ljoin) << gc->lmitre
#if R_VERSION >= R_Version(4, 1, 0)
# define WRITE_FILL() \
if (gc->patternFill != R_NilValue) RKD_OUT_STREAM << (qint8) PatternFill << (qint16) (INTEGER(gc->patternFill)[0]); \
More information about the rkward-tracker
mailing list