1 /* 2 * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #ifndef HEADLESS 27 28 #include "awt_p.h" 29 #include <string.h> 30 #include "java_awt_Component.h" 31 #include "java_awt_Font.h" 32 #include "java_awt_FontMetrics.h" 33 #include "sun_awt_X11GraphicsEnvironment.h" 34 35 #include "awt_Font.h" 36 37 #include "java_awt_Dimension.h" 38 #include "multi_font.h" 39 #include "Disposer.h" 40 #endif /* !HEADLESS */ 41 #include <jni.h> 42 #ifndef HEADLESS 43 #include <jni_util.h> 44 45 #define defaultXLFD "-*-helvetica-*-*-*-*-12-*-*-*-*-*-iso8859-1" 46 47 struct FontIDs fontIDs; 48 struct PlatformFontIDs platformFontIDs; 49 50 static void pDataDisposeMethod(JNIEnv *env, jlong pData); 51 52 /* #define FONT_DEBUG 2 */ 53 /* 1- print failures, 2- print all, 3- terminate on failure */ 54 #if FONT_DEBUG 55 static XFontStruct *XLoadQueryFontX(Display *display, char *name) 56 { 57 XFontStruct *result = NULL; 58 result = XLoadQueryFont(display, name); 59 #if FONT_DEBUG < 2 60 if (result == NULL) 61 #endif 62 fprintf(stderr, "XLoadQueryFont(\"%s\") -> 0x%x.\n", name, result); 63 #if FONT_DEBUG >= 3 64 if (result == NULL) 65 exit(-1); 66 #endif 67 return result; 68 } 69 #define XLoadQueryFont XLoadQueryFontX 70 #endif 71 #endif /* !HEADLESS */ 72 73 /* 74 * Class: java_awt_Font 75 * Method: initIDs 76 * Signature: ()V 77 */ 78 79 /* This function gets called from the static initializer for Font.java 80 to initialize the fieldIDs for fields that may be accessed from C */ 81 82 JNIEXPORT void JNICALL 83 Java_java_awt_Font_initIDs 84 (JNIEnv *env, jclass cls) 85 { 86 #ifndef HEADLESS 87 /** We call "NoClientCode" methods because they won't invoke client 88 code on the privileged toolkit thread **/ 89 fontIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"); 90 fontIDs.style = (*env)->GetFieldID(env, cls, "style", "I"); 91 fontIDs.size = (*env)->GetFieldID(env, cls, "size", "I"); 92 fontIDs.getPeer = (*env)->GetMethodID(env, cls, "getPeer_NoClientCode", 93 "()Ljava/awt/peer/FontPeer;"); 94 fontIDs.getFamily = 95 (*env)->GetMethodID(env, cls, "getFamily_NoClientCode", 96 "()Ljava/lang/String;"); 97 #endif /* !HEADLESS */ 98 } 99 100 #ifndef HEADLESS 101 /* fieldIDs for FontDescriptor fields that may be accessed from C */ 102 static struct FontDescriptorIDs { 103 jfieldID nativeName; 104 jfieldID charsetName; 105 } fontDescriptorIDs; 106 #endif /* !HEADLESS */ 107 108 /* 109 * Class: sun_awt_FontDescriptor 110 * Method: initIDs 111 * Signature: ()V 112 */ 113 114 /* This function gets called from the static initializer for 115 FontDescriptor.java to initialize the fieldIDs for fields 116 that may be accessed from C */ 117 118 JNIEXPORT void JNICALL 119 Java_sun_awt_FontDescriptor_initIDs 120 (JNIEnv *env, jclass cls) 121 { 122 #ifndef HEADLESS 123 fontDescriptorIDs.nativeName = 124 (*env)->GetFieldID(env, cls, "nativeName", 125 "Ljava/lang/String;"); 126 fontDescriptorIDs.charsetName = 127 (*env)->GetFieldID(env, cls, "charsetName", 128 "Ljava/lang/String;"); 129 #endif /* !HEADLESS */ 130 } 131 132 /* 133 * Class: sun_awt_PlatformFont 134 * Method: initIDs 135 * Signature: ()V 136 */ 137 138 /* This function gets called from the static initializer for 139 PlatformFont.java to initialize the fieldIDs for fields 140 that may be accessed from C */ 141 142 JNIEXPORT void JNICALL 143 Java_sun_awt_PlatformFont_initIDs 144 (JNIEnv *env, jclass cls) 145 { 146 #ifndef HEADLESS 147 platformFontIDs.componentFonts = 148 (*env)->GetFieldID(env, cls, "componentFonts", 149 "[Lsun/awt/FontDescriptor;"); 150 platformFontIDs.fontConfig = 151 (*env)->GetFieldID(env,cls, "fontConfig", 152 "Lsun/awt/FontConfiguration;"); 153 154 platformFontIDs.makeConvertedMultiFontString = 155 (*env)->GetMethodID(env, cls, "makeConvertedMultiFontString", 156 "(Ljava/lang/String;)[Ljava/lang/Object;"); 157 158 platformFontIDs.makeConvertedMultiFontChars = 159 (*env)->GetMethodID(env, cls, "makeConvertedMultiFontChars", 160 "([CII)[Ljava/lang/Object;"); 161 #endif /* !HEADLESS */ 162 } 163 164 #ifndef HEADLESS 165 XFontStruct * 166 loadFont(Display * display, char *name, int32_t pointSize) 167 { 168 XFontStruct *f = NULL; 169 170 /* try the exact xlfd name in font configuration file */ 171 f = XLoadQueryFont(display, name); 172 if (f != NULL) { 173 return f; 174 } 175 176 /* 177 * try nearly font 178 * 179 * 1. specify FAMILY_NAME, WEIGHT_NAME, SLANT, POINT_SIZE, 180 * CHARSET_REGISTRY and CHARSET_ENCODING. 181 * 2. change POINT_SIZE to PIXEL_SIZE 182 * 3. change FAMILY_NAME to * 183 * 4. specify only PIXEL_SIZE and CHARSET_REGISTRY/ENCODING 184 * 5. change PIXEL_SIZE +1/-1/+2/-2...+4/-4 185 * 6. default font pattern 186 */ 187 { 188 /* 189 * This code assumes the name contains exactly 14 '-' delimiter. 190 * If not use default pattern. 191 */ 192 int32_t i, length, pixelSize; 193 Boolean useDefault = FALSE; 194 195 char buffer[BUFSIZ], buffer2[BUFSIZ]; 196 char *family = NULL, *style = NULL, *slant = NULL, *encoding = NULL; 197 char *start = NULL, *end = NULL; 198 199 if (strlen(name) > BUFSIZ - 1) { 200 useDefault = TRUE; 201 } else { 202 strcpy(buffer, name); 203 } 204 205 #define NEXT_HYPHEN\ 206 start = end + 1;\ 207 end = strchr(start, '-');\ 208 if (end == NULL) {\ 209 useDefault = TRUE;\ 210 break;\ 211 }\ 212 *end = '\0' 213 214 do { 215 end = buffer; 216 217 /* skip FOUNDRY */ 218 NEXT_HYPHEN; 219 220 /* set FAMILY_NAME */ 221 NEXT_HYPHEN; 222 family = start; 223 224 /* set STYLE_NAME */ 225 NEXT_HYPHEN; 226 style = start; 227 228 /* set SLANT */ 229 NEXT_HYPHEN; 230 slant = start; 231 232 /* skip SETWIDTH_NAME, ADD_STYLE_NAME, PIXEL_SIZE 233 POINT_SIZE, RESOLUTION_X, RESOLUTION_Y, SPACING 234 and AVERAGE_WIDTH */ 235 NEXT_HYPHEN; 236 NEXT_HYPHEN; 237 NEXT_HYPHEN; 238 NEXT_HYPHEN; 239 NEXT_HYPHEN; 240 NEXT_HYPHEN; 241 NEXT_HYPHEN; 242 NEXT_HYPHEN; 243 244 /* set CHARSET_REGISTRY and CHARSET_ENCODING */ 245 encoding = end + 1; 246 } 247 while (0); 248 249 #define TRY_LOAD\ 250 f = XLoadQueryFont(display, buffer2);\ 251 if (f != NULL) {\ 252 strcpy(name, buffer2);\ 253 return f;\ 254 } 255 256 if (!useDefault) { 257 char *altstyle = NULL; 258 259 /* Regular is the style for TrueType fonts -- Type1, F3 use roman */ 260 if (strcmp(style, "regular") == 0) { 261 altstyle = "roman"; 262 } 263 #if defined(__linux__) || defined(MACOSX) 264 if (!strcmp(family, "lucidasans")) { 265 family = "lucida"; 266 } 267 #endif 268 /* try 1. */ 269 jio_snprintf(buffer2, sizeof(buffer2), 270 "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s", 271 family, style, slant, pointSize, encoding); 272 TRY_LOAD; 273 274 if (altstyle != NULL) { 275 jio_snprintf(buffer2, sizeof(buffer2), 276 "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s", 277 family, altstyle, slant, pointSize, encoding); 278 TRY_LOAD; 279 } 280 281 /* search bitmap font */ 282 pixelSize = pointSize / 10; 283 284 /* try 2. */ 285 jio_snprintf(buffer2, sizeof(buffer2), 286 "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 287 family, style, slant, pixelSize, encoding); 288 TRY_LOAD; 289 290 if (altstyle != NULL) { 291 jio_snprintf(buffer2, sizeof(buffer2), 292 "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 293 family, altstyle, slant, pixelSize, encoding); 294 TRY_LOAD; 295 } 296 297 /* try 3 */ 298 jio_snprintf(buffer2, sizeof(buffer2), 299 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s", 300 style, slant, pixelSize, encoding); 301 TRY_LOAD; 302 if (altstyle != NULL) { 303 jio_snprintf(buffer2, sizeof(buffer2), 304 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s", 305 altstyle, slant, pixelSize, encoding); 306 TRY_LOAD; 307 } 308 309 /* try 4 */ 310 jio_snprintf(buffer2, sizeof(buffer2), 311 "-*-*-*-%s-*-*-%d-*-*-*-*-*-%s", 312 slant, pixelSize, encoding); 313 314 TRY_LOAD; 315 316 /* try 5. */ 317 jio_snprintf(buffer2, sizeof(buffer2), 318 "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", 319 pixelSize, encoding); 320 TRY_LOAD; 321 322 /* try 6. */ 323 for (i = 1; i < 4; i++) { 324 if (pixelSize < i) 325 break; 326 jio_snprintf(buffer2, sizeof(buffer2), 327 "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 328 family, style, slant, pixelSize + i, encoding); 329 TRY_LOAD; 330 331 jio_snprintf(buffer2, sizeof(buffer2), 332 "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 333 family, style, slant, pixelSize - i, encoding); 334 TRY_LOAD; 335 336 jio_snprintf(buffer2, sizeof(buffer2), 337 "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", 338 pixelSize + i, encoding); 339 TRY_LOAD; 340 341 jio_snprintf(buffer2, sizeof(buffer2), 342 "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", 343 pixelSize - i, encoding); 344 TRY_LOAD; 345 } 346 } 347 } 348 349 strcpy(name, defaultXLFD); 350 return XLoadQueryFont(display, defaultXLFD); 351 } 352 353 /* 354 * Hardwired list of mappings for generic font names "Helvetica", 355 * "TimesRoman", "Courier", "Dialog", and "DialogInput". 356 */ 357 static char *defaultfontname = "fixed"; 358 static char *defaultfoundry = "misc"; 359 static char *anyfoundry = "*"; 360 static char *anystyle = "*-*"; 361 static char *isolatin1 = "iso8859-1"; 362 363 static char * 364 Style(int32_t s) 365 { 366 switch (s) { 367 case java_awt_Font_ITALIC: 368 return "medium-i"; 369 case java_awt_Font_BOLD: 370 return "bold-r"; 371 case java_awt_Font_BOLD + java_awt_Font_ITALIC: 372 return "bold-i"; 373 case java_awt_Font_PLAIN: 374 default: 375 return "medium-r"; 376 } 377 } 378 379 static int32_t 380 awtJNI_FontName(JNIEnv * env, jstring name, char **foundry, char **facename, char **encoding) 381 { 382 char *cname = NULL; 383 384 if (JNU_IsNull(env, name)) { 385 return 0; 386 } 387 cname = (char *) JNU_GetStringPlatformChars(env, name, NULL); 388 389 /* additional default font names */ 390 if (strcmp(cname, "serif") == 0) { 391 *foundry = "adobe"; 392 *facename = "times"; 393 *encoding = isolatin1; 394 } else if (strcmp(cname, "sansserif") == 0) { 395 *foundry = "adobe"; 396 *facename = "helvetica"; 397 *encoding = isolatin1; 398 } else if (strcmp(cname, "monospaced") == 0) { 399 *foundry = "adobe"; 400 *facename = "courier"; 401 *encoding = isolatin1; 402 } else if (strcmp(cname, "helvetica") == 0) { 403 *foundry = "adobe"; 404 *facename = "helvetica"; 405 *encoding = isolatin1; 406 } else if (strcmp(cname, "timesroman") == 0) { 407 *foundry = "adobe"; 408 *facename = "times"; 409 *encoding = isolatin1; 410 } else if (strcmp(cname, "courier") == 0) { 411 *foundry = "adobe"; 412 *facename = "courier"; 413 *encoding = isolatin1; 414 } else if (strcmp(cname, "dialog") == 0) { 415 *foundry = "b&h"; 416 *facename = "lucida"; 417 *encoding = isolatin1; 418 } else if (strcmp(cname, "dialoginput") == 0) { 419 *foundry = "b&h"; 420 *facename = "lucidatypewriter"; 421 *encoding = isolatin1; 422 } else if (strcmp(cname, "zapfdingbats") == 0) { 423 *foundry = "itc"; 424 *facename = "zapfdingbats"; 425 *encoding = "*-*"; 426 } else { 427 #ifdef DEBUG 428 jio_fprintf(stderr, "Unknown font: %s\n", cname); 429 #endif 430 *foundry = defaultfoundry; 431 *facename = defaultfontname; 432 *encoding = isolatin1; 433 } 434 435 if (cname != NULL) 436 JNU_ReleaseStringPlatformChars(env, name, (const char *) cname); 437 438 return 1; 439 } 440 441 struct FontData * 442 awtJNI_GetFontData(JNIEnv * env, jobject font, char **errmsg) 443 { 444 /* We are going to create at most 4 outstanding local refs in this 445 * function. */ 446 if ((*env)->EnsureLocalCapacity(env, 4) < 0) { 447 return NULL; 448 } 449 450 if (!JNU_IsNull(env, font) && awtJNI_IsMultiFont(env, font)) { 451 struct FontData *fdata = NULL; 452 int32_t i, size; 453 char *fontsetname = NULL; 454 char *nativename = NULL; 455 jobjectArray componentFonts = NULL; 456 jobject peer = NULL; 457 jobject fontDescriptor = NULL; 458 jstring fontDescriptorName = NULL; 459 jstring charsetName = NULL; 460 461 fdata = (struct FontData *) JNU_GetLongFieldAsPtr(env,font, 462 fontIDs.pData); 463 464 if (fdata != NULL && fdata->flist != NULL) { 465 return fdata; 466 } 467 size = (*env)->GetIntField(env, font, fontIDs.size); 468 fdata = (struct FontData *) malloc(sizeof(struct FontData)); 469 470 peer = (*env)->CallObjectMethod(env, font, fontIDs.getPeer); 471 472 componentFonts = 473 (*env)->GetObjectField(env, peer, platformFontIDs.componentFonts); 474 /* We no longer need peer */ 475 (*env)->DeleteLocalRef(env, peer); 476 477 fdata->charset_num = (*env)->GetArrayLength(env, componentFonts); 478 479 fdata->flist = (awtFontList *) malloc(sizeof(awtFontList) 480 * fdata->charset_num); 481 fdata->xfont = NULL; 482 for (i = 0; i < fdata->charset_num; i++) { 483 /* 484 * set xlfd name 485 */ 486 487 fontDescriptor = (*env)->GetObjectArrayElement(env, componentFonts, i); 488 fontDescriptorName = 489 (*env)->GetObjectField(env, fontDescriptor, 490 fontDescriptorIDs.nativeName); 491 492 if (!JNU_IsNull(env, fontDescriptorName)) { 493 nativename = (char *) JNU_GetStringPlatformChars(env, fontDescriptorName, NULL); 494 } else { 495 nativename = ""; 496 } 497 498 fdata->flist[i].xlfd = malloc(strlen(nativename) 499 + strlen(defaultXLFD)); 500 jio_snprintf(fdata->flist[i].xlfd, strlen(nativename) + 10, 501 nativename, size * 10); 502 503 if (nativename != NULL && nativename != "") 504 JNU_ReleaseStringPlatformChars(env, fontDescriptorName, (const char *) nativename); 505 506 /* 507 * set charset_name 508 */ 509 510 charsetName = 511 (*env)->GetObjectField(env, fontDescriptor, 512 fontDescriptorIDs.charsetName); 513 514 fdata->flist[i].charset_name = (char *) 515 JNU_GetStringPlatformChars(env, charsetName, NULL); 516 517 /* We are done with the objects. */ 518 (*env)->DeleteLocalRef(env, fontDescriptor); 519 (*env)->DeleteLocalRef(env, fontDescriptorName); 520 (*env)->DeleteLocalRef(env, charsetName); 521 522 /* 523 * set load & XFontStruct 524 */ 525 fdata->flist[i].load = 0; 526 527 /* 528 * This appears to be a bogus check. The actual intent appears 529 * to be to find out whether this is the "base" font in a set, 530 * rather than iso8859_1 explicitly. Note that iso8859_15 will 531 * and must also pass this test. 532 */ 533 534 if (fdata->xfont == NULL && 535 strstr(fdata->flist[i].charset_name, "8859_1")) { 536 fdata->flist[i].xfont = 537 loadFont(awt_display, fdata->flist[i].xlfd, size * 10); 538 if (fdata->flist[i].xfont != NULL) { 539 fdata->flist[i].load = 1; 540 fdata->xfont = fdata->flist[i].xfont; 541 fdata->flist[i].index_length = 1; 542 } else { 543 /* Free any already allocated storage and fonts */ 544 int j = i; 545 for (j = 0; j <= i; j++) { 546 free((void *)fdata->flist[j].xlfd); 547 JNU_ReleaseStringPlatformChars(env, NULL, 548 fdata->flist[j].charset_name); 549 if (fdata->flist[j].load) { 550 XFreeFont(awt_display, fdata->flist[j].xfont); 551 } 552 } 553 free((void *)fdata->flist); 554 free((void *)fdata); 555 556 if (errmsg != NULL) { 557 *errmsg = "java/lang" "NullPointerException"; 558 } 559 (*env)->DeleteLocalRef(env, componentFonts); 560 return NULL; 561 } 562 } 563 } 564 (*env)->DeleteLocalRef(env, componentFonts); 565 /* 566 * XFontSet will create if the peer of TextField/TextArea 567 * are used. 568 */ 569 fdata->xfs = NULL; 570 571 JNU_SetLongFieldFromPtr(env,font,fontIDs.pData,fdata); 572 Disposer_AddRecord(env, font, pDataDisposeMethod, ptr_to_jlong(fdata)); 573 return fdata; 574 } else { 575 Display *display = NULL; 576 struct FontData *fdata = NULL; 577 char fontSpec[1024]; 578 int32_t height; 579 int32_t oheight; 580 int32_t above = 0; /* tries above height */ 581 int32_t below = 0; /* tries below height */ 582 char *foundry = NULL; 583 char *name = NULL; 584 char *encoding = NULL; 585 char *style = NULL; 586 XFontStruct *xfont = NULL; 587 jstring family = NULL; 588 589 if (JNU_IsNull(env, font)) { 590 if (errmsg != NULL) { 591 *errmsg = "java/lang" "NullPointerException"; 592 } 593 return (struct FontData *) NULL; 594 } 595 display = XDISPLAY; 596 597 fdata = (struct FontData *) JNU_GetLongFieldAsPtr(env,font,fontIDs.pData); 598 if (fdata != NULL && fdata->xfont != NULL) { 599 return fdata; 600 } 601 602 family = (*env)->CallObjectMethod(env, font, fontIDs.getFamily); 603 604 if (!awtJNI_FontName(env, family, &foundry, &name, &encoding)) { 605 if (errmsg != NULL) { 606 *errmsg = "java/lang" "NullPointerException"; 607 } 608 (*env)->DeleteLocalRef(env, family); 609 return (struct FontData *) NULL; 610 } 611 style = Style((*env)->GetIntField(env, font, fontIDs.style)); 612 oheight = height = (*env)->GetIntField(env, font, fontIDs.size); 613 614 while (1) { 615 jio_snprintf(fontSpec, sizeof(fontSpec), "-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 616 foundry, 617 name, 618 style, 619 height, 620 encoding); 621 622 /*fprintf(stderr,"LoadFont: %s\n", fontSpec); */ 623 xfont = XLoadQueryFont(display, fontSpec); 624 625 /* XXX: sometimes XLoadQueryFont returns a bogus font structure */ 626 /* with negative ascent. */ 627 if (xfont == (Font) NULL || xfont->ascent < 0) { 628 if (xfont != NULL) { 629 XFreeFont(display, xfont); 630 } 631 if (foundry != anyfoundry) { /* Use ptr comparison here, not strcmp */ 632 /* Try any other foundry before messing with the sizes */ 633 foundry = anyfoundry; 634 continue; 635 } 636 /* We couldn't find the font. We'll try to find an */ 637 /* alternate by searching for heights above and below our */ 638 /* preferred height. We try for 4 heights above and below. */ 639 /* If we still can't find a font we repeat the algorithm */ 640 /* using misc-fixed as the font. If we then fail, then we */ 641 /* give up and signal an error. */ 642 if (above == below) { 643 above++; 644 height = oheight + above; 645 } else { 646 below++; 647 if (below > 4) { 648 if (name != defaultfontname || style != anystyle) { 649 name = defaultfontname; 650 foundry = defaultfoundry; 651 height = oheight; 652 style = anystyle; 653 encoding = isolatin1; 654 above = below = 0; 655 continue; 656 } else { 657 if (errmsg != NULL) { 658 *errmsg = "java/io/" "FileNotFoundException"; 659 } 660 (*env)->DeleteLocalRef(env, family); 661 return (struct FontData *) NULL; 662 } 663 } 664 height = oheight - below; 665 } 666 continue; 667 } else { 668 fdata = ZALLOC(FontData); 669 670 if (fdata == NULL) { 671 if (errmsg != NULL) { 672 *errmsg = "java/lang" "OutOfMemoryError"; 673 } 674 } else { 675 fdata->xfont = xfont; 676 JNU_SetLongFieldFromPtr(env,font,fontIDs.pData,fdata); 677 Disposer_AddRecord(env, font, pDataDisposeMethod, 678 ptr_to_jlong(fdata)); 679 } 680 (*env)->DeleteLocalRef(env, family); 681 return fdata; 682 } 683 } 684 /* not reached */ 685 } 686 } 687 688 /* 689 * Registered with the 2D disposer to be called after the Font is GC'd. 690 */ 691 static void pDataDisposeMethod(JNIEnv *env, jlong pData) 692 { 693 struct FontData *fdata = NULL; 694 int32_t i = 0; 695 Display *display = XDISPLAY; 696 697 AWT_LOCK(); 698 fdata = (struct FontData *)pData; 699 700 if (fdata == NULL) { 701 AWT_UNLOCK(); 702 return; 703 } 704 705 if (fdata->xfs != NULL) { 706 XFreeFontSet(display, fdata->xfs); 707 } 708 709 /* AWT fonts are always "multifonts" and probably have been in 710 * all post 1.0 releases, so this test test for multi fonts is 711 * probably not needed, and the singleton xfont is probably never used. 712 */ 713 if (fdata->charset_num > 0) { 714 for (i = 0; i < fdata->charset_num; i++) { 715 free((void *)fdata->flist[i].xlfd); 716 JNU_ReleaseStringPlatformChars(env, NULL, 717 fdata->flist[i].charset_name); 718 if (fdata->flist[i].load) { 719 XFreeFont(display, fdata->flist[i].xfont); 720 } 721 } 722 723 free((void *)fdata->flist); 724 725 /* Don't free fdata->xfont because it is equal to fdata->flist[i].xfont 726 for some 'i' */ 727 } else { 728 if (fdata->xfont != NULL) { 729 XFreeFont(display, fdata->xfont); 730 } 731 } 732 733 free((void *)fdata); 734 735 AWT_UNLOCK(); 736 } 737 #endif /* !HEADLESS */