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) {