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