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