[education/rkward] /: Force Qt to actually sync paint operations before and after recording a tiling pattern.

Thomas Friedrichsmeier null at kde.org
Sat Mar 19 21:57:45 GMT 2022


Git commit dc73742f4aec2ab57af17cc7b6aef345d876c68f by Thomas Friedrichsmeier.
Committed on 18/03/2022 at 22:37.
Pushed by tfry into branch 'master'.

Force Qt to actually sync paint operations before and after recording a tiling pattern.

M  +1    -1    ChangeLog
M  +16   -0    rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
M  +1    -0    rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
M  +4    -0    rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
M  +1    -0    rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
M  +16   -0    rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp

https://invent.kde.org/education/rkward/commit/dc73742f4aec2ab57af17cc7b6aef345d876c68f

diff --git a/ChangeLog b/ChangeLog
index d7a93261..023df0e8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,11 @@
 TODO:
 - RKDClose needs to be synchronous to avoid race-condition while closing device
-- Sometimes pattern takes bits from main paint area? Some syncing needed?
 
 TODOS for autotests:
   - Check and update the standards files
   - Use options(warn=1), in order to get warnings into the test?
 
+- Implement new R graphics functions: gradients, patterns, clip paths
 - Add icons to settings dialog for quick visual orientation
 - Merge ktexteditor (script) settings into the main settings dialog
 - Internal: Code cleanup around settings
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
index f5602df2..c0b59e1f 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.cpp
@@ -186,6 +186,22 @@ void RKGraphicsDevice::updateNow () {
 	beginPainter();
 }
 
+/** This is definitely lame, but at least as of Qt 5.12.8, calling QPainter::end() does _not_ mean, changes are synced to the
+ *  paint device. They will be synced, eventually, but when trying to capture a tiling pattern, we want a clean separation
+ *  between the paints going to the main canvas and those going to the pattern space, immediately.
+ *
+ *  This function achieves that. Note that it is also implemented as a synchronous operation on the stream, so Qt will definitely
+ *  get around to process some events after this was called, which is probably also needed.
+ *
+ *  Without this function artifacts will occur inside tiling patterns some, but not all of the time.
+ *
+ *  KF6 TODO: check if still needed with Qt6. */
+void RKGraphicsDevice::forceSync() {
+	RK_TRACE (GRAPHICS_DEVICE);
+	updateNow();
+	if(painter.isActive()) painter.end();
+}
+
 void RKGraphicsDevice::checkSize() {
 	RK_TRACE (GRAPHICS_DEVICE);
 	if (view->size () != area.size ()) {
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
index 954e3d9b..4ebbc72a 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice.h
@@ -103,6 +103,7 @@ public:
 	int cachePath(QPainterPath &path);
 	void destroyCachedPath(int index);
 	bool setClipToCachedPath(int index);
+	void forceSync();
 public slots:
 	void stopInteraction ();
 signals:
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
index 81334090..72c0163e 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_frontendtransmitter.cpp
@@ -440,6 +440,10 @@ void RKGraphicsDeviceFrontendTransmitter::newData () {
 			streamer.writeOutBuffer ();
 		} else if (opcode == RKDNewPageConfirm) {
 			device->confirmNewPage ();
+		} else if (opcode == RKDForceSync) {
+			device->forceSync();
+			streamer.outstream << (qint8) 0;
+			streamer.writeOutBuffer();
 		} else {
 			RK_DEBUG (GRAPHICS_DEVICE, DL_ERROR, "Unhandled operation of type %d for device number %d. Skipping.", opcode, devnum+1);
 		}
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
index a0310b10..afadb26f 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_protocol_shared.h
@@ -123,6 +123,7 @@ enum RKDOpcodes {
 	RKDEndRecordTilingPattern,       // part of setPattern in R
 	RKDSetClipPath,       // 110
 	RKDEndRecordClipPath,
+	RKDForceSync,
 
 	// Protocol operations
 	RKDCancel              = 200
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
index cf992fd4..f82b5d87 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
@@ -613,6 +613,20 @@ SEXP makeInt(int val) {
 	return ret;
 }
 
+void forceSync(pDevDesc dev) {
+// NOTE: See commen7 in RKGraphicsDevice::forceSync();
+// KF6 TODO: Still neded with Qt6?
+	{
+		RKGraphicsDataStreamWriteGuard wguard;
+		WRITE_HEADER(RKDForceSync, dev);
+	}
+	{
+		RKGraphicsDataStreamReadGuard rguard;
+		qint8 dummy;
+		RKD_IN_STREAM >> dummy;
+	}
+}
+
 SEXP RKD_SetPattern (SEXP pattern, pDevDesc dev) {
 	auto ptype = R_GE_patternType(pattern);
 	if ((ptype == R_GE_linearGradientPattern) || (ptype == R_GE_radialGradientPattern)) {
@@ -641,6 +655,7 @@ SEXP RKD_SetPattern (SEXP pattern, pDevDesc dev) {
 			RKD_OUT_STREAM << getGradientExtend(R_GE_radialGradientExtend(pattern));
 		}
 	} else if (ptype == R_GE_tilingPattern) {
+		forceSync(dev);
 		{
 			RKGraphicsDataStreamWriteGuard wguard;
 			WRITE_HEADER(RKDStartRecordTilingPattern, dev);
@@ -653,6 +668,7 @@ SEXP RKD_SetPattern (SEXP pattern, pDevDesc dev) {
 		SEXP pattern_func = PROTECT(Rf_lang1(R_GE_tilingPatternFunction(pattern)));
 		R_tryEval(pattern_func, R_GlobalEnv, &error);
 		UNPROTECT(1);
+		forceSync(dev);
 		{
 			RKGraphicsDataStreamWriteGuard wguard;
 			WRITE_HEADER(RKDEndRecordTilingPattern, dev);



More information about the rkward-tracker mailing list