Tk Source Code

Artifact [e0d90918]
Login

Artifact e0d9091838af95f907d20ea02d568bdcadf9071cf6aef49f6b09baf737fea506:

Attachment "unixrfont-3.diff" to ticket [3767882e] added by chw 2020-04-13 10:29:44.
Index: unix/tkUnixRFont.c
==================================================================
--- unix/tkUnixRFont.c
+++ unix/tkUnixRFont.c
@@ -252,10 +252,27 @@
  * Results:
  * 	On error, frees fontPtr and returns NULL, otherwise returns fontPtr.
  *
  *---------------------------------------------------------------------------
  */
+
+static void
+FinishedWithFont(
+    UnixFtFont *fontPtr);
+
+static int
+InitFontErrorProc(
+    ClientData clientData,
+    XErrorEvent *errorPtr)
+{
+    int *errorFlagPtr = (int *) clientData;
+
+    if (errorFlagPtr != NULL) {
+	*errorFlagPtr = 1;
+    }
+    return 0;
+}
 
 static UnixFtFont *
 InitFont(
     Tk_Window tkwin,
     FcPattern *pattern,
@@ -263,11 +280,12 @@
 {
     FcFontSet *set;
     FcCharSet *charset;
     FcResult result;
     XftFont *ftFont;
-    int i, iWidth;
+    int i, iWidth, errorFlag;
+    Tk_ErrorHandler handler;
 
     if (!fontPtr) {
 	fontPtr = ckalloc(sizeof(UnixFtFont));
     }
 
@@ -314,14 +332,29 @@
 
     /*
      * Fill in platform-specific fields of TkFont.
      */
 
+    handler = Tk_CreateErrorHandler(Tk_Display(tkwin),
+		    -1, -1, -1, InitFontErrorProc, (ClientData) &errorFlag);
+    errorFlag = 0;
     ftFont = GetFont(fontPtr, 0, 0.0);
+    if (ftFont == NULL || errorFlag) {
+	Tk_DeleteErrorHandler(handler);
+	FinishedWithFont(fontPtr);
+	ckfree(fontPtr);
+	return NULL;
+    }
     fontPtr->font.fid = XLoadFont(Tk_Display(tkwin), "fixed");
     GetTkFontAttributes(ftFont, &fontPtr->font.fa);
     GetTkFontMetrics(ftFont, &fontPtr->font.fm);
+    Tk_DeleteErrorHandler(handler);
+    if (errorFlag) {
+	FinishedWithFont(fontPtr);
+	ckfree(fontPtr);
+	return NULL;
+    }
 
     /*
      * Fontconfig can't report any information about the position or thickness
      * of underlines or overstrikes. Thus, we use some defaults that are
      * hacked around from backup defaults in tkUnixFont.c, which are in turn
@@ -667,16 +700,20 @@
     UnixFtFont *fontPtr = (UnixFtFont *) tkfont;
     XftFont *ftFont;
     FcChar32 c;
     XGlyphInfo extents;
     int clen, curX, newX, curByte, newByte, sawNonSpace;
-    int termByte = 0, termX = 0;
+    int termByte = 0, termX = 0, errorFlag;
+    Tk_ErrorHandler handler;
 #if DEBUG_FONTSEL
     char string[256];
     int len = 0;
 #endif /* DEBUG_FONTSEL */
 
+    handler = Tk_CreateErrorHandler(fontPtr->display,
+		    -1, -1, -1, InitFontErrorProc, (ClientData) &errorFlag);
+    errorFlag = 0;
     curX = 0;
     curByte = 0;
     sawNonSpace = 0;
     while (numBytes > 0) {
 	int unichar;
@@ -707,12 +744,16 @@
 
 #if DEBUG_FONTSEL
 	string[len++] = (char) c;
 #endif /* DEBUG_FONTSEL */
 	ftFont = GetFont(fontPtr, c, 0.0);
-
-	XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents);
+	if (!errorFlag) {
+	    XftTextExtents32(fontPtr->display, ftFont, &c, 1, &extents);
+	} else {
+	    extents.xOff = 0;
+	    errorFlag = 0;
+	}
 
 	newX = curX + extents.xOff;
 	newByte = curByte + clen;
 	if (maxLength >= 0 && newX > maxLength) {
 	    if (flags & TK_PARTIAL_OK ||
@@ -737,10 +778,11 @@
 	}
 
 	curX = newX;
 	curByte = newByte;
     }
+    Tk_DeleteErrorHandler(handler);
 #if DEBUG_FONTSEL
     string[len] = '\0';
     printf("MeasureChars %s length %d bytes %d\n", string, curX, curByte);
 #endif /* DEBUG_FONTSEL */
     *lengthPtr = curX;