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