Tk Source Code

Artifact [69a29d31]
Login

Artifact 69a29d31771f21cce787cf2c97c2a765c2e374880e157082c40c2439e3c4c41f:

Attachment "tkUnixRFont.c.diff" to ticket [8ebed330] added by chw 2021-09-19 09:33:41.
Index: unix/tkUnixRFont.c
==================================================================
--- unix/tkUnixRFont.c
+++ unix/tkUnixRFont.c
@@ -51,10 +51,14 @@
 
 typedef struct {
     Region clipRegion;		/* The clipping region, or None. */
 } ThreadSpecificData;
 static Tcl_ThreadDataKey dataKey;
+
+TCL_DECLARE_MUTEX(xftMutex);
+#define LOCK Tcl_MutexLock(&xftMutex)
+#define UNLOCK Tcl_MutexUnlock(&xftMutex)
 
 /*
  * Package initialization:
  * 	Nothing to do here except register the fact that we're using Xft in
  * 	the TIP 59 configuration database.
@@ -120,24 +124,28 @@
 	mat.xy = -(mat.yx = s);
 
 	if (angle != 0.0) {
 	    FcPatternAddMatrix(pat, FC_MATRIX, &mat);
 	}
+	LOCK;
 	ftFont = XftFontOpenPattern(fontPtr->display, pat);
+	UNLOCK;
 	if (!ftFont) {
 	    /*
 	     * The previous call to XftFontOpenPattern() should not fail, but
 	     * sometimes does anyway. Usual cause appears to be a
 	     * misconfigured fontconfig installation; see [Bug 1090382]. Try a
 	     * fallback:
 	     */
 
+	    LOCK;
 	    ftFont = XftFontOpen(fontPtr->display, fontPtr->screen,
 		    FC_FAMILY, FcTypeString, "sans",
 		    FC_SIZE, FcTypeDouble, 12.0,
 		    FC_MATRIX, FcTypeMatrix, &mat,
 		    NULL);
+	    UNLOCK;
 	}
 	if (!ftFont) {
 	    /*
 	     * The previous call should definitely not fail. Impossible to
 	     * proceed at this point.
@@ -148,11 +156,13 @@
 
 	if (angle == 0.0) {
 	    fontPtr->faces[i].ft0Font = ftFont;
 	} else {
 	    if (fontPtr->faces[i].ftFont) {
+		LOCK;
 		XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont);
+		UNLOCK;
 	    }
 	    fontPtr->faces[i].ftFont = ftFont;
 	    fontPtr->faces[i].angle = angle;
 	}
     }
@@ -407,14 +417,18 @@
     Tk_ErrorHandler handler =
 	    Tk_CreateErrorHandler(display, -1, -1, -1, NULL, NULL);
 
     for (i = 0; i < fontPtr->nfaces; i++) {
 	if (fontPtr->faces[i].ftFont) {
+	    LOCK;
 	    XftFontClose(fontPtr->display, fontPtr->faces[i].ftFont);
+	    UNLOCK;
 	}
 	if (fontPtr->faces[i].ft0Font) {
+	    LOCK;
 	    XftFontClose(fontPtr->display, fontPtr->faces[i].ft0Font);
+	    UNLOCK;
 	}
 	if (fontPtr->faces[i].charset) {
 	    FcCharSetDestroy(fontPtr->faces[i].charset);
 	}
     }
@@ -749,11 +763,13 @@
 	string[len++] = (char) c;
 #endif /* DEBUG_FONTSEL */
 	ftFont = GetFont(fontPtr, c, 0.0);
 
 	if (!errorFlag) {
+	    LOCK;
 	    XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents);
+	    UNLOCK;
 	} else {
 	    extents.xOff = 0;
 	    errorFlag = 0;
 	}
 
@@ -960,12 +976,14 @@
 	numBytes -= clen;
 
 	ftFont = GetFont(fontPtr, c, 0.0);
 	if (ftFont) {
 	    specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
+	    LOCK;
 	    XftGlyphExtents(fontPtr->display, ftFont, &specs[nspec].glyph, 1,
 		    &metrics);
+	    UNLOCK;
 
 	    /*
 	     * Draw glyph only when it fits entirely into 16 bit coords.
 	     */
 
@@ -974,21 +992,25 @@
 		y <= maxCoord - metrics.height) {
 		specs[nspec].font = ftFont;
 		specs[nspec].x = x;
 		specs[nspec].y = y;
 		if (++nspec == NUM_SPEC) {
+		    LOCK;
 		    XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
 			    specs, nspec);
+		    UNLOCK;
 		    nspec = 0;
 		}
 	    }
 	    x += metrics.xOff;
 	    y += metrics.yOff;
 	}
     }
     if (nspec) {
+	LOCK;
 	XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec);
+	UNLOCK;
     }
 
   doUnderlineStrikeout:
     if (tsdPtr->clipRegion != NULL) {
 	XftDrawSetClip(fontPtr->ftDraw, NULL);
@@ -1111,12 +1133,15 @@
 		 * perform better rendering of sub-pixel inter-glyph spacing.
 		 * If only the current Xft implementation could make use of
 		 * this information... but we'll be ready when it does!
 		 */
 
+		LOCK;
 		XftGlyphExtents(fontPtr->display, currentFtFont, glyphs,
 			nglyph, &metrics);
+		UNLOCK;
+
 		/*
 		 * Draw glyph only when it fits entirely into 16 bit coords.
 		 */
 
 		if (x >= minCoord && y >= minCoord &&
@@ -1135,33 +1160,39 @@
                      * not be a huge issue since NUM_SPEC is 1024 and thus able to
                      * cover about 6000 pixels for a 6 pixel wide font (which is
                      * a very small barely readable font)
 		     */
 
+		    LOCK;
 		    XftDrawGlyphs(fontPtr->ftDraw, xftcolor, currentFtFont,
 			    originX, originY, glyphs, nglyph);
+		    UNLOCK;
 		}
 	    }
 	    originX = ROUND16(x);
 	    originY = ROUND16(y);
 	    currentFtFont = ftFont;
 	}
 	glyphs[nglyph++] = XftCharIndex(fontPtr->display, ftFont, c);
     }
     if (nglyph) {
+	LOCK;
 	XftGlyphExtents(fontPtr->display, currentFtFont, glyphs,
 		nglyph, &metrics);
+	UNLOCK;
 
 	/*
 	 * Draw glyph only when it fits entirely into 16 bit coords.
 	 */
 
 	if (x >= minCoord && y >= minCoord &&
 	    x <= maxCoord - metrics.width &&
 	    y <= maxCoord - metrics.height) {
+	    LOCK;
 	    XftDrawGlyphs(fontPtr->ftDraw, xftcolor, currentFtFont,
 		    originX, originY, glyphs, nglyph);
+	    UNLOCK;
 	}
     }
 #else /* !XFT_HAS_FIXED_ROTATED_PLACEMENT */
     int clen, nspec;
     XftGlyphFontSpec specs[NUM_SPEC];
@@ -1205,12 +1236,14 @@
 
 	ftFont = GetFont(fontPtr, c, angle);
 	ft0Font = GetFont(fontPtr, c, 0.0);
 	if (ftFont && ft0Font) {
 	    specs[nspec].glyph = XftCharIndex(fontPtr->display, ftFont, c);
+	    LOCK;
 	    XftGlyphExtents(fontPtr->display, ft0Font, &specs[nspec].glyph, 1,
 		    &metrics);
+	    UNLOCK;
 
 	    /*
 	     * Draw glyph only when it fits entirely into 16 bit coords.
 	     */
 
@@ -1219,21 +1252,25 @@
 		y <= maxCoord - metrics.height) {
 		specs[nspec].font = ftFont;
 		specs[nspec].x = ROUND16(x);
 		specs[nspec].y = ROUND16(y);
 		if (++nspec == NUM_SPEC) {
+		    LOCK;
 		    XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor,
 			    specs, nspec);
+		    UNLOCK;
 		    nspec = 0;
 		}
 	    }
 	    x += metrics.xOff*cosA + metrics.yOff*sinA;
 	    y += metrics.yOff*cosA - metrics.xOff*sinA;
 	}
     }
     if (nspec) {
+	LOCK;
 	XftDrawGlyphFontSpec(fontPtr->ftDraw, xftcolor, specs, nspec);
+	UNLOCK;
     }
 #endif /* XFT_HAS_FIXED_ROTATED_PLACEMENT */
 
   doUnderlineStrikeout:
     if (tsdPtr->clipRegion != NULL) {