text: /*
   * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  #ifndef HEADLESS
  
  #include "awt_p.h"
  #include <string.h>
  #include "java_awt_Component.h"
  #include "java_awt_Font.h"
  #include "java_awt_FontMetrics.h"
  #include "sun_awt_X11GraphicsEnvironment.h"
  
  #include "awt_Font.h"
  
  #include "java_awt_Dimension.h"
  #include "multi_font.h"
  #include "Disposer.h"
  #endif /* !HEADLESS */
  #include <jni.h>
  #ifndef HEADLESS
  #include <jni_util.h>
  
  #define defaultXLFD "-*-helvetica-*-*-*-*-12-*-*-*-*-*-iso8859-1"
  
  struct FontIDs fontIDs;
  struct PlatformFontIDs platformFontIDs;
  
  static void pDataDisposeMethod(JNIEnv *env, jlong pData);
  
  /* #define FONT_DEBUG 2 */
  /* 1- print failures, 2- print all, 3- terminate on failure */
  #if FONT_DEBUG
  static XFontStruct *XLoadQueryFontX(Display *display, char *name)
  {
      XFontStruct *result = NULL;
      result = XLoadQueryFont(display, name);
  #if FONT_DEBUG < 2
      if (result == NULL)
  #endif
          fprintf(stderr, "XLoadQueryFont(\"%s\") -> 0x%x.\n", name, result);
  #if FONT_DEBUG >= 3
      if (result == NULL)
          exit(-1);
  #endif
      return result;
  }
  #define XLoadQueryFont XLoadQueryFontX
  #endif
  #endif /* !HEADLESS */
  
  /*
   * Class:     java_awt_Font
   * Method:    initIDs
   * Signature: ()V
   */
  
  /* This function gets called from the static initializer for Font.java
     to initialize the fieldIDs for fields that may be accessed from C */
  
  JNIEXPORT void JNICALL
  Java_java_awt_Font_initIDs
    (JNIEnv *env, jclass cls)
  {
  #ifndef HEADLESS
      CHECK_NULL(fontIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"));
      CHECK_NULL(fontIDs.style = (*env)->GetFieldID(env, cls, "style", "I"));
      CHECK_NULL(fontIDs.size = (*env)->GetFieldID(env, cls, "size", "I"));
      CHECK_NULL(fontIDs.getPeer = (*env)->GetMethodID(env, cls, "getFontPeer",
                                                       "()Ljava/awt/peer/FontPeer;"));
      CHECK_NULL(fontIDs.getFamily = (*env)->GetMethodID(env, cls, "getFamily_NoClientCode",
                                                         "()Ljava/lang/String;"));
  #endif /* !HEADLESS */
  }
  
  #ifndef HEADLESS
  /* fieldIDs for FontDescriptor fields that may be accessed from C */
  static struct FontDescriptorIDs {
      jfieldID nativeName;
      jfieldID charsetName;
  } fontDescriptorIDs;
  #endif /* !HEADLESS */
  
  /*
   * Class:     sun_awt_FontDescriptor
   * Method:    initIDs
   * Signature: ()V
   */
  
  /* This function gets called from the static initializer for
     FontDescriptor.java to initialize the fieldIDs for fields
     that may be accessed from C */
  
  JNIEXPORT void JNICALL
  Java_sun_awt_FontDescriptor_initIDs
    (JNIEnv *env, jclass cls)
  {
  #ifndef HEADLESS
      CHECK_NULL(fontDescriptorIDs.nativeName =
                 (*env)->GetFieldID(env, cls, "nativeName", "Ljava/lang/String;"));
      CHECK_NULL(fontDescriptorIDs.charsetName =
                 (*env)->GetFieldID(env, cls, "charsetName", "Ljava/lang/String;"));
  #endif /* !HEADLESS */
  }
  
  /*
   * Class:     sun_awt_PlatformFont
   * Method:    initIDs
   * Signature: ()V
   */
  
  /* This function gets called from the static initializer for
     PlatformFont.java to initialize the fieldIDs for fields
     that may be accessed from C */
  
  JNIEXPORT void JNICALL
  Java_sun_awt_PlatformFont_initIDs
    (JNIEnv *env, jclass cls)
  {
  #ifndef HEADLESS
      CHECK_NULL(platformFontIDs.componentFonts =
                 (*env)->GetFieldID(env, cls, "componentFonts",
                                    "[Lsun/awt/FontDescriptor;"));
      CHECK_NULL(platformFontIDs.fontConfig =
                 (*env)->GetFieldID(env,cls, "fontConfig",
                                    "Lsun/awt/FontConfiguration;"));
      CHECK_NULL(platformFontIDs.makeConvertedMultiFontString =
                 (*env)->GetMethodID(env, cls, "makeConvertedMultiFontString",
                                     "(Ljava/lang/String;)[Ljava/lang/Object;"));
      CHECK_NULL(platformFontIDs.makeConvertedMultiFontChars =
                 (*env)->GetMethodID(env, cls, "makeConvertedMultiFontChars",
                                     "([CII)[Ljava/lang/Object;"));
  #endif /* !HEADLESS */
  }
  
  #ifndef HEADLESS
  XFontStruct *
  loadFont(Display * display, char *name, int32_t pointSize)
  {
      XFontStruct *f = NULL;
  
      /* try the exact xlfd name in font configuration file */
      f = XLoadQueryFont(display, name);
      if (f != NULL) {
          return f;
      }
  
      /*
       * try nearly font
       *
       *  1. specify FAMILY_NAME, WEIGHT_NAME, SLANT, POINT_SIZE,
       *     CHARSET_REGISTRY and CHARSET_ENCODING.
       *  2. change POINT_SIZE to PIXEL_SIZE
       *  3. change FAMILY_NAME to *
       *  4. specify only PIXEL_SIZE and CHARSET_REGISTRY/ENCODING
       *  5. change PIXEL_SIZE +1/-1/+2/-2...+4/-4
       *  6. default font pattern
       */
      {
          /*
           * This code assumes the name contains exactly 14 '-' delimiter.
           * If not use default pattern.
           */
          int32_t i, length, pixelSize;
          Boolean useDefault = FALSE;
  
          char buffer[BUFSIZ], buffer2[BUFSIZ];
          char *family = NULL, *style = NULL, *slant = NULL, *encoding = NULL;
          char *start = NULL, *end = NULL;
  
          if (strlen(name) > BUFSIZ - 1) {
              useDefault = TRUE;
          } else {
              strcpy(buffer, name);
          }
  
  #define NEXT_HYPHEN\
          start = end + 1;\
          end = strchr(start, '-');\
          if (end == NULL) {\
                                useDefault = TRUE;\
          break;\
          }\
          *end = '\0'
  
               do {
                   end = buffer;
  
                   /* skip FOUNDRY */
                   NEXT_HYPHEN;
  
                   /* set FAMILY_NAME */
                   NEXT_HYPHEN;
                   family = start;
  
                   /* set STYLE_NAME */
                   NEXT_HYPHEN;
                   style = start;
  
                   /* set SLANT */
                   NEXT_HYPHEN;
                   slant = start;
  
                   /* skip SETWIDTH_NAME, ADD_STYLE_NAME, PIXEL_SIZE
                      POINT_SIZE, RESOLUTION_X, RESOLUTION_Y, SPACING
                      and AVERAGE_WIDTH */
                   NEXT_HYPHEN;
                   NEXT_HYPHEN;
                   NEXT_HYPHEN;
                   NEXT_HYPHEN;
                   NEXT_HYPHEN;
                   NEXT_HYPHEN;
                   NEXT_HYPHEN;
                   NEXT_HYPHEN;
  
                   /* set CHARSET_REGISTRY and CHARSET_ENCODING */
                   encoding = end + 1;
               }
               while (0);
  
  #define TRY_LOAD\
          f = XLoadQueryFont(display, buffer2);\
          if (f != NULL) {\
                              strcpy(name, buffer2);\
          return f;\
          }
  
          if (!useDefault) {
              char *altstyle = NULL;
  
              /* Regular is the style for TrueType fonts -- Type1, F3 use roman */
              if (strcmp(style, "regular") == 0) {
                  altstyle = "roman";
              }
  #if defined(__linux__) || defined(MACOSX)
              if (!strcmp(family, "lucidasans")) {
                  family = "lucida";
              }
  #endif
              /* try 1. */
              jio_snprintf(buffer2, sizeof(buffer2),
                           "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s",
                           family, style, slant, pointSize, encoding);
              TRY_LOAD;
  
              if (altstyle != NULL) {
                  jio_snprintf(buffer2, sizeof(buffer2),
                               "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s",
                               family, altstyle, slant, pointSize, encoding);
                  TRY_LOAD;
              }
  
              /* search bitmap font */
              pixelSize = pointSize / 10;
  
              /* try 2. */
              jio_snprintf(buffer2, sizeof(buffer2),
                           "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
                           family, style, slant, pixelSize, encoding);
              TRY_LOAD;
  
              if (altstyle != NULL) {
                  jio_snprintf(buffer2, sizeof(buffer2),
                               "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
                               family, altstyle, slant, pixelSize, encoding);
                  TRY_LOAD;
              }
  
              /* try 3 */
              jio_snprintf(buffer2, sizeof(buffer2),
                           "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s",
                           style, slant, pixelSize, encoding);
              TRY_LOAD;
              if (altstyle != NULL) {
                  jio_snprintf(buffer2, sizeof(buffer2),
                               "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s",
                               altstyle, slant, pixelSize, encoding);
                  TRY_LOAD;
              }
  
              /* try 4 */
              jio_snprintf(buffer2, sizeof(buffer2),
                           "-*-*-*-%s-*-*-%d-*-*-*-*-*-%s",
                           slant, pixelSize, encoding);
  
              TRY_LOAD;
  
              /* try 5. */
              jio_snprintf(buffer2, sizeof(buffer2),
                           "-*-*-*-*-*-*-%d-*-*-*-*-*-%s",
                           pixelSize, encoding);
              TRY_LOAD;
  
              /* try 6. */
              for (i = 1; i < 4; i++) {
                  if (pixelSize < i)
                      break;
                  jio_snprintf(buffer2, sizeof(buffer2),
                               "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
                               family, style, slant, pixelSize + i, encoding);
                  TRY_LOAD;
  
                  jio_snprintf(buffer2, sizeof(buffer2),
                               "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
                               family, style, slant, pixelSize - i, encoding);
                  TRY_LOAD;
  
                  jio_snprintf(buffer2, sizeof(buffer2),
                               "-*-*-*-*-*-*-%d-*-*-*-*-*-%s",
                               pixelSize + i, encoding);
                  TRY_LOAD;
  
                  jio_snprintf(buffer2, sizeof(buffer2),
                               "-*-*-*-*-*-*-%d-*-*-*-*-*-%s",
                               pixelSize - i, encoding);
                  TRY_LOAD;
              }
          }
      }
  
      strcpy(name, defaultXLFD);
      return XLoadQueryFont(display, defaultXLFD);
  }
  
  /*
   * Hardwired list of mappings for generic font names "Helvetica",
   * "TimesRoman", "Courier", "Dialog", and "DialogInput".
   */
  static char *defaultfontname = "fixed";
  static char *defaultfoundry = "misc";
  static char *anyfoundry = "*";
  static char *anystyle = "*-*";
  static char *isolatin1 = "iso8859-1";
  
  static char *
  Style(int32_t s)
  {
      switch (s) {
          case java_awt_Font_ITALIC:
              return "medium-i";
          case java_awt_Font_BOLD:
              return "bold-r";
          case java_awt_Font_BOLD + java_awt_Font_ITALIC:
              return "bold-i";
          case java_awt_Font_PLAIN:
          default:
              return "medium-r";
      }
  }
  
  static int32_t
  awtJNI_FontName(JNIEnv * env, jstring name, char **foundry, char **facename, char **encoding)
  {
      char *cname = NULL;
  
      if (JNU_IsNull(env, name)) {
          return 0;
      }
      cname = (char *) JNU_GetStringPlatformChars(env, name, NULL);
      if (cname == NULL) {
          (*env)->ExceptionClear(env);
          JNU_ThrowOutOfMemoryError(env, "Could not create font name");
          return 0;
      }
  
      /* additional default font names */
      if (strcmp(cname, "serif") == 0) {
          *foundry = "adobe";
          *facename = "times";
          *encoding = isolatin1;
      } else if (strcmp(cname, "sansserif") == 0) {
          *foundry = "adobe";
          *facename = "helvetica";
          *encoding = isolatin1;
      } else if (strcmp(cname, "monospaced") == 0) {
          *foundry = "adobe";
          *facename = "courier";
          *encoding = isolatin1;
      } else if (strcmp(cname, "helvetica") == 0) {
          *foundry = "adobe";
          *facename = "helvetica";
          *encoding = isolatin1;
      } else if (strcmp(cname, "timesroman") == 0) {
          *foundry = "adobe";
          *facename = "times";
          *encoding = isolatin1;
      } else if (strcmp(cname, "courier") == 0) {
          *foundry = "adobe";
          *facename = "courier";
          *encoding = isolatin1;
      } else if (strcmp(cname, "dialog") == 0) {
          *foundry = "b&h";
          *facename = "lucida";
          *encoding = isolatin1;
      } else if (strcmp(cname, "dialoginput") == 0) {
          *foundry = "b&h";
          *facename = "lucidatypewriter";
          *encoding = isolatin1;
      } else if (strcmp(cname, "zapfdingbats") == 0) {
          *foundry = "itc";
          *facename = "zapfdingbats";
          *encoding = "*-*";
      } else {
  #ifdef DEBUG
          jio_fprintf(stderr, "Unknown font: %s\n", cname);
  #endif
          *foundry = defaultfoundry;
          *facename = defaultfontname;
          *encoding = isolatin1;
      }
  
      if (cname != NULL)
          JNU_ReleaseStringPlatformChars(env, name, (const char *) cname);
  
      return 1;
  }
  
  struct FontData *
  awtJNI_GetFontData(JNIEnv * env, jobject font, char **errmsg)
  {
      /* We are going to create at most 4 outstanding local refs in this
       * function. */
      if ((*env)->EnsureLocalCapacity(env, 4) < 0) {
          return NULL;
      }
  
      if (!JNU_IsNull(env, font) && awtJNI_IsMultiFont(env, font)) {
          JNU_CHECK_EXCEPTION_RETURN(env, NULL);
  
          struct FontData *fdata = NULL;
          int32_t i, size;
          char *fontsetname = NULL;
          char *nativename = NULL;
          Boolean doFree = FALSE;
          jobjectArray componentFonts = NULL;
          jobject peer = NULL;
          jobject fontDescriptor = NULL;
          jstring fontDescriptorName = NULL;
          jstring charsetName = NULL;
  
          fdata = (struct FontData *) JNU_GetLongFieldAsPtr(env,font,
                                                           fontIDs.pData);
  
          if (fdata != NULL && fdata->flist != NULL) {
              return fdata;
          }
          size = (*env)->GetIntField(env, font, fontIDs.size);
          fdata = (struct FontData *) malloc(sizeof(struct FontData));
  
          peer = (*env)->CallObjectMethod(env, font, fontIDs.getPeer);
  
          componentFonts =
            (*env)->GetObjectField(env, peer, platformFontIDs.componentFonts);
          /* We no longer need peer */
          (*env)->DeleteLocalRef(env, peer);
  
          fdata->charset_num = (*env)->GetArrayLength(env, componentFonts);
  
          fdata->flist = (awtFontList *) malloc(sizeof(awtFontList)
                                                * fdata->charset_num);
          fdata->xfont = NULL;
          for (i = 0; i < fdata->charset_num; i++) {
              /*
               * set xlfd name
               */
  
              fontDescriptor = (*env)->GetObjectArrayElement(env, componentFonts, i);
              fontDescriptorName =
                (*env)->GetObjectField(env, fontDescriptor,
                                       fontDescriptorIDs.nativeName);
  
              if (!JNU_IsNull(env, fontDescriptorName)) {
                  nativename = (char *) JNU_GetStringPlatformChars(env, fontDescriptorName, NULL);
                  if (nativename == NULL) {
                      nativename = "";
                      doFree = FALSE;
                  } else {
                      doFree = TRUE;
                  }
              } else {
                  nativename = "";
                  doFree = FALSE;
              }
  
              fdata->flist[i].xlfd = malloc(strlen(nativename)
                                            + strlen(defaultXLFD));
              jio_snprintf(fdata->flist[i].xlfd, strlen(nativename) + 10,
                           nativename, size * 10);
  
              if (nativename != NULL && doFree)
                  JNU_ReleaseStringPlatformChars(env, fontDescriptorName, (const char *) nativename);
  
              /*
               * set charset_name
               */
  
              charsetName =
                (*env)->GetObjectField(env, fontDescriptor,
                                       fontDescriptorIDs.charsetName);
  
              fdata->flist[i].charset_name = (char *)
                  JNU_GetStringPlatformChars(env, charsetName, NULL);
              if (fdata->flist[i].charset_name == NULL) {
                  (*env)->ExceptionClear(env);
                  JNU_ThrowOutOfMemoryError(env, "Could not create charset name");
                  return NULL;
              }
  
              /* We are done with the objects. */
              (*env)->DeleteLocalRef(env, fontDescriptor);
              (*env)->DeleteLocalRef(env, fontDescriptorName);
              (*env)->DeleteLocalRef(env, charsetName);
  
              /*
               * set load & XFontStruct
               */
              fdata->flist[i].load = 0;
  
              /*
               * This appears to be a bogus check.  The actual intent appears
               * to be to find out whether this is the "base" font in a set,
               * rather than iso8859_1 explicitly.  Note that iso8859_15 will
               * and must also pass this test.
               */
  
              if (fdata->xfont == NULL &&
                  strstr(fdata->flist[i].charset_name, "8859_1")) {
                  fdata->flist[i].xfont =
                      loadFont(awt_display, fdata->flist[i].xlfd, size * 10);
                  if (fdata->flist[i].xfont != NULL) {
                      fdata->flist[i].load = 1;
                      fdata->xfont = fdata->flist[i].xfont;
                      fdata->flist[i].index_length = 1;
                  } else {
                      /* Free any already allocated storage and fonts */
                      int j = i;
                      for (j = 0; j <= i; j++) {
                          free((void *)fdata->flist[j].xlfd);
                          JNU_ReleaseStringPlatformChars(env, NULL,
                              fdata->flist[j].charset_name);
                          if (fdata->flist[j].load) {
                              XFreeFont(awt_display, fdata->flist[j].xfont);
                          }
                      }
                      free((void *)fdata->flist);
                      free((void *)fdata);
  
                      if (errmsg != NULL) {
                          *errmsg = "java/lang" "NullPointerException";
                      }
                      (*env)->DeleteLocalRef(env, componentFonts);
                      return NULL;
                  }
              }
          }
          (*env)->DeleteLocalRef(env, componentFonts);
          /*
           * XFontSet will create if the peer of TextField/TextArea
           * are used.
           */
          fdata->xfs = NULL;
  
          JNU_SetLongFieldFromPtr(env,font,fontIDs.pData,fdata);
          Disposer_AddRecord(env, font, pDataDisposeMethod, ptr_to_jlong(fdata));
          return fdata;
      } else {
          JNU_CHECK_EXCEPTION_RETURN(env, NULL);
          Display *display = NULL;
          struct FontData *fdata = NULL;
          char fontSpec[1024];
          int32_t height;
          int32_t oheight;
          int32_t above = 0;              /* tries above height */
          int32_t below = 0;              /* tries below height */
          char *foundry = NULL;
          char *name = NULL;
          char *encoding = NULL;
          char *style = NULL;
          XFontStruct *xfont = NULL;
          jstring family = NULL;
  
          if (JNU_IsNull(env, font)) {
              if (errmsg != NULL) {
                  *errmsg = "java/lang" "NullPointerException";
              }
              return (struct FontData *) NULL;
          }
          display = XDISPLAY;
  
          fdata = (struct FontData *) JNU_GetLongFieldAsPtr(env,font,fontIDs.pData);
          if (fdata != NULL && fdata->xfont != NULL) {
              return fdata;
          }
  
          family = (*env)->CallObjectMethod(env, font, fontIDs.getFamily);
  
          if (!awtJNI_FontName(env, family, &foundry, &name, &encoding)) {
              if (errmsg != NULL) {
                  *errmsg = "java/lang" "NullPointerException";
              }
              (*env)->DeleteLocalRef(env, family);
              return (struct FontData *) NULL;
          }
          style = Style((*env)->GetIntField(env, font, fontIDs.style));
          oheight = height = (*env)->GetIntField(env, font, fontIDs.size);
  
          while (1) {
              jio_snprintf(fontSpec, sizeof(fontSpec), "-%s-%s-%s-*-*-%d-*-*-*-*-*-%s",
                           foundry,
                           name,
                           style,
                           height,
                           encoding);
  
              /*fprintf(stderr,"LoadFont: %s\n", fontSpec); */
              xfont = XLoadQueryFont(display, fontSpec);
  
              /* XXX: sometimes XLoadQueryFont returns a bogus font structure */
              /* with negative ascent. */
              if (xfont == (Font) NULL || xfont->ascent < 0) {
                  if (xfont != NULL) {
                      XFreeFont(display, xfont);
                  }
                  if (foundry != anyfoundry) {  /* Use ptr comparison here, not strcmp */
                      /* Try any other foundry before messing with the sizes */
                      foundry = anyfoundry;
                      continue;
                  }
                  /* We couldn't find the font. We'll try to find an */
                  /* alternate by searching for heights above and below our */
                  /* preferred height. We try for 4 heights above and below. */
                  /* If we still can't find a font we repeat the algorithm */
                  /* using misc-fixed as the font. If we then fail, then we */
                  /* give up and signal an error. */
                  if (above == below) {
                      above++;
                      height = oheight + above;
                  } else {
                      below++;
                      if (below > 4) {
                          if (name != defaultfontname || style != anystyle) {
                              name = defaultfontname;
                              foundry = defaultfoundry;
                              height = oheight;
                              style = anystyle;
                              encoding = isolatin1;
                              above = below = 0;
                              continue;
                          } else {
                              if (errmsg != NULL) {
                                  *errmsg = "java/io/" "FileNotFoundException";
                              }
                              (*env)->DeleteLocalRef(env, family);
                              return (struct FontData *) NULL;
                          }
                      }
                      height = oheight - below;
                  }
                  continue;
              } else {
                  fdata = ZALLOC(FontData);
  
                  if (fdata == NULL) {
                      if (errmsg != NULL) {
                          *errmsg = "java/lang" "OutOfMemoryError";
                      }
                  } else {
                      fdata->xfont = xfont;
                      JNU_SetLongFieldFromPtr(env,font,fontIDs.pData,fdata);
                      Disposer_AddRecord(env, font, pDataDisposeMethod,
                                         ptr_to_jlong(fdata));
                  }
                  (*env)->DeleteLocalRef(env, family);
                  return fdata;
              }
          }
          /* not reached */
      }
  }
  
  /*
   * Registered with the 2D disposer to be called after the Font is GC'd.
   */
  static void pDataDisposeMethod(JNIEnv *env, jlong pData)
  {
      struct FontData *fdata = NULL;
      int32_t i = 0;
      Display *display = XDISPLAY;
  
      AWT_LOCK();
      fdata = (struct FontData *)pData;
  
      if (fdata == NULL) {
          AWT_UNLOCK();
          return;
      }
  
      if (fdata->xfs != NULL) {
          XFreeFontSet(display, fdata->xfs);
      }
  
      /* AWT fonts are always "multifonts" and probably have been in
       * all post 1.0 releases, so this test for multi fonts is
       * probably not needed, and the singleton xfont is probably never used.
       */
      if (fdata->charset_num > 0) {
          for (i = 0; i < fdata->charset_num; i++) {
              free((void *)fdata->flist[i].xlfd);
              JNU_ReleaseStringPlatformChars(env, NULL,
                                             fdata->flist[i].charset_name);
              if (fdata->flist[i].load) {
                  XFreeFont(display, fdata->flist[i].xfont);
              }
          }
  
          free((void *)fdata->flist);
  
          /* Don't free fdata->xfont because it is equal to fdata->flist[i].xfont
             for some 'i' */
      } else {
          if (fdata->xfont != NULL) {
              XFreeFont(display, fdata->xfont);
          }
      }
  
      free((void *)fdata);
  
      AWT_UNLOCK();
  }
  #endif /* !HEADLESS */
  