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 "Disposer.h" 39 #endif /* !HEADLESS */ 40 #include <jni.h> 41 #ifndef HEADLESS 42 #include <jni_util.h> 43 44 #define defaultXLFD "-*-helvetica-*-*-*-*-12-*-*-*-*-*-iso8859-1" 45 46 struct FontIDs fontIDs; 47 struct PlatformFontIDs platformFontIDs; 48 49 static void pDataDisposeMethod(JNIEnv *env, jlong pData); 50 51 /* #define FONT_DEBUG 2 */ 52 /* 1- print failures, 2- print all, 3- terminate on failure */ 53 #if FONT_DEBUG 54 static XFontStruct *XLoadQueryFontX(Display *display, char *name) 55 { 56 XFontStruct *result = NULL; 57 result = XLoadQueryFont(display, name); 58 #if FONT_DEBUG < 2 59 if (result == NULL) 60 #endif 61 fprintf(stderr, "XLoadQueryFont(\"%s\") -> 0x%x.\n", name, result); 62 #if FONT_DEBUG >= 3 63 if (result == NULL) 64 exit(-1); 65 #endif 66 return result; 67 } 68 #define XLoadQueryFont XLoadQueryFontX 69 #endif 70 #endif /* !HEADLESS */ 71 72 /* 73 * Class: java_awt_Font 74 * Method: initIDs 75 * Signature: ()V 76 */ 77 78 /* This function gets called from the static initializer for Font.java 79 to initialize the fieldIDs for fields that may be accessed from C */ 80 81 JNIEXPORT void JNICALL 82 Java_java_awt_Font_initIDs 83 (JNIEnv *env, jclass cls) 84 { 85 #ifndef HEADLESS 86 CHECK_NULL(fontIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J")); 87 CHECK_NULL(fontIDs.style = (*env)->GetFieldID(env, cls, "style", "I")); 88 CHECK_NULL(fontIDs.size = (*env)->GetFieldID(env, cls, "size", "I")); 89 CHECK_NULL(fontIDs.getPeer = (*env)->GetMethodID(env, cls, "getFontPeer", 90 "()Ljava/awt/peer/FontPeer;")); 91 CHECK_NULL(fontIDs.getFamily = (*env)->GetMethodID(env, cls, "getFamily_NoClientCode", 92 "()Ljava/lang/String;")); 93 #endif /* !HEADLESS */ 94 } 95 96 #ifndef HEADLESS 97 /* fieldIDs for FontDescriptor fields that may be accessed from C */ 98 static struct FontDescriptorIDs { 99 jfieldID nativeName; 100 jfieldID charsetName; 101 } fontDescriptorIDs; 102 #endif /* !HEADLESS */ 103 104 /* 105 * Class: sun_awt_FontDescriptor 106 * Method: initIDs 107 * Signature: ()V 108 */ 109 110 /* This function gets called from the static initializer for 111 FontDescriptor.java to initialize the fieldIDs for fields 112 that may be accessed from C */ 113 114 JNIEXPORT void JNICALL 115 Java_sun_awt_FontDescriptor_initIDs 116 (JNIEnv *env, jclass cls) 117 { 118 #ifndef HEADLESS 119 CHECK_NULL(fontDescriptorIDs.nativeName = 120 (*env)->GetFieldID(env, cls, "nativeName", "Ljava/lang/String;")); 121 CHECK_NULL(fontDescriptorIDs.charsetName = 122 (*env)->GetFieldID(env, cls, "charsetName", "Ljava/lang/String;")); 123 #endif /* !HEADLESS */ 124 } 125 126 /* 127 * Class: sun_awt_PlatformFont 128 * Method: initIDs 129 * Signature: ()V 130 */ 131 132 /* This function gets called from the static initializer for 133 PlatformFont.java to initialize the fieldIDs for fields 134 that may be accessed from C */ 135 136 JNIEXPORT void JNICALL 137 Java_sun_awt_PlatformFont_initIDs 138 (JNIEnv *env, jclass cls) 139 { 140 #ifndef HEADLESS 141 CHECK_NULL(platformFontIDs.componentFonts = 142 (*env)->GetFieldID(env, cls, "componentFonts", 143 "[Lsun/awt/FontDescriptor;")); 144 CHECK_NULL(platformFontIDs.fontConfig = 145 (*env)->GetFieldID(env,cls, "fontConfig", 146 "Lsun/awt/FontConfiguration;")); 147 CHECK_NULL(platformFontIDs.makeConvertedMultiFontString = 148 (*env)->GetMethodID(env, cls, "makeConvertedMultiFontString", 149 "(Ljava/lang/String;)[Ljava/lang/Object;")); 150 CHECK_NULL(platformFontIDs.makeConvertedMultiFontChars = 151 (*env)->GetMethodID(env, cls, "makeConvertedMultiFontChars", 152 "([CII)[Ljava/lang/Object;")); 153 #endif /* !HEADLESS */ 154 } 155 156 #ifndef HEADLESS 157 XFontStruct * 158 loadFont(Display * display, char *name, int32_t pointSize) 159 { 160 XFontStruct *f = NULL; 161 162 /* try the exact xlfd name in font configuration file */ 163 f = XLoadQueryFont(display, name); 164 if (f != NULL) { 165 return f; 166 } 167 168 /* 169 * try nearly font 170 * 171 * 1. specify FAMILY_NAME, WEIGHT_NAME, SLANT, POINT_SIZE, 172 * CHARSET_REGISTRY and CHARSET_ENCODING. 173 * 2. change POINT_SIZE to PIXEL_SIZE 174 * 3. change FAMILY_NAME to * 175 * 4. specify only PIXEL_SIZE and CHARSET_REGISTRY/ENCODING 176 * 5. change PIXEL_SIZE +1/-1/+2/-2...+4/-4 177 * 6. default font pattern 178 */ 179 { 180 /* 181 * This code assumes the name contains exactly 14 '-' delimiter. 182 * If not use default pattern. 183 */ 184 int32_t i, length, pixelSize; 185 Boolean useDefault = FALSE; 186 187 char buffer[BUFSIZ], buffer2[BUFSIZ]; 188 char *family = NULL, *style = NULL, *slant = NULL, *encoding = NULL; 189 char *start = NULL, *end = NULL; 190 191 if (strlen(name) > BUFSIZ - 1) { 192 useDefault = TRUE; 193 } else { 194 strcpy(buffer, name); 195 } 196 197 #define NEXT_HYPHEN\ 198 start = end + 1;\ 199 end = strchr(start, '-');\ 200 if (end == NULL) {\ 201 useDefault = TRUE;\ 202 break;\ 203 }\ 204 *end = '\0' 205 206 do { 207 end = buffer; 208 209 /* skip FOUNDRY */ 210 NEXT_HYPHEN; 211 212 /* set FAMILY_NAME */ 213 NEXT_HYPHEN; 214 family = start; 215 216 /* set STYLE_NAME */ 217 NEXT_HYPHEN; 218 style = start; 219 220 /* set SLANT */ 221 NEXT_HYPHEN; 222 slant = start; 223 224 /* skip SETWIDTH_NAME, ADD_STYLE_NAME, PIXEL_SIZE 225 POINT_SIZE, RESOLUTION_X, RESOLUTION_Y, SPACING 226 and AVERAGE_WIDTH */ 227 NEXT_HYPHEN; 228 NEXT_HYPHEN; 229 NEXT_HYPHEN; 230 NEXT_HYPHEN; 231 NEXT_HYPHEN; 232 NEXT_HYPHEN; 233 NEXT_HYPHEN; 234 NEXT_HYPHEN; 235 236 /* set CHARSET_REGISTRY and CHARSET_ENCODING */ 237 encoding = end + 1; 238 } 239 while (0); 240 241 #define TRY_LOAD\ 242 f = XLoadQueryFont(display, buffer2);\ 243 if (f != NULL) {\ 244 strcpy(name, buffer2);\ 245 return f;\ 246 } 247 248 if (!useDefault) { 249 char *altstyle = NULL; 250 251 /* Regular is the style for TrueType fonts -- Type1, F3 use roman */ 252 if (strcmp(style, "regular") == 0) { 253 altstyle = "roman"; 254 } 255 #if defined(__linux__) || defined(MACOSX) 256 if (!strcmp(family, "lucidasans")) { 257 family = "lucida"; 258 } 259 #endif 260 /* try 1. */ 261 jio_snprintf(buffer2, sizeof(buffer2), 262 "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s", 263 family, style, slant, pointSize, encoding); 264 TRY_LOAD; 265 266 if (altstyle != NULL) { 267 jio_snprintf(buffer2, sizeof(buffer2), 268 "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-%s", 269 family, altstyle, slant, pointSize, encoding); 270 TRY_LOAD; 271 } 272 273 /* search bitmap font */ 274 pixelSize = pointSize / 10; 275 276 /* try 2. */ 277 jio_snprintf(buffer2, sizeof(buffer2), 278 "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 279 family, style, slant, pixelSize, encoding); 280 TRY_LOAD; 281 282 if (altstyle != NULL) { 283 jio_snprintf(buffer2, sizeof(buffer2), 284 "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 285 family, altstyle, slant, pixelSize, encoding); 286 TRY_LOAD; 287 } 288 289 /* try 3 */ 290 jio_snprintf(buffer2, sizeof(buffer2), 291 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s", 292 style, slant, pixelSize, encoding); 293 TRY_LOAD; 294 if (altstyle != NULL) { 295 jio_snprintf(buffer2, sizeof(buffer2), 296 "-*-*-%s-%s-*-*-%d-*-*-*-*-*-%s", 297 altstyle, slant, pixelSize, encoding); 298 TRY_LOAD; 299 } 300 301 /* try 4 */ 302 jio_snprintf(buffer2, sizeof(buffer2), 303 "-*-*-*-%s-*-*-%d-*-*-*-*-*-%s", 304 slant, pixelSize, encoding); 305 306 TRY_LOAD; 307 308 /* try 5. */ 309 jio_snprintf(buffer2, sizeof(buffer2), 310 "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", 311 pixelSize, encoding); 312 TRY_LOAD; 313 314 /* try 6. */ 315 for (i = 1; i < 4; i++) { 316 if (pixelSize < i) 317 break; 318 jio_snprintf(buffer2, sizeof(buffer2), 319 "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 320 family, style, slant, pixelSize + i, encoding); 321 TRY_LOAD; 322 323 jio_snprintf(buffer2, sizeof(buffer2), 324 "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-%s", 325 family, style, slant, pixelSize - i, encoding); 326 TRY_LOAD; 327 328 jio_snprintf(buffer2, sizeof(buffer2), 329 "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", 330 pixelSize + i, encoding); 331 TRY_LOAD; 332 333 jio_snprintf(buffer2, sizeof(buffer2), 334 "-*-*-*-*-*-*-%d-*-*-*-*-*-%s", 335 pixelSize - i, encoding); 336 TRY_LOAD; 337 } 338 } 339 } 340 341 strcpy(name, defaultXLFD); 342 return XLoadQueryFont(display, defaultXLFD); 343 } 344 345 /* 346 * Hardwired list of mappings for generic font names "Helvetica", 347 * "TimesRoman", "Courier", "Dialog", and "DialogInput". 348 */ 349 static char *defaultfontname = "fixed"; 350 static char *defaultfoundry = "misc"; 351 static char *anyfoundry = "*"; 352 static char *anystyle = "*-*"; 353 static char *isolatin1 = "iso8859-1"; 354 355 static char * 356 Style(int32_t s) 357 { 358 switch (s) { 359 case java_awt_Font_ITALIC: 360 return "medium-i"; 361 case java_awt_Font_BOLD: 362 return "bold-r"; 363 case java_awt_Font_BOLD + java_awt_Font_ITALIC: 364 return "bold-i"; 365 case java_awt_Font_PLAIN: 366 default: 367 return "medium-r"; 368 } 369 } 370 371 static int32_t 372 awtJNI_FontName(JNIEnv * env, jstring name, char **foundry, char **facename, char **encoding) 373 { 374 char *cname = NULL; 375 376 if (JNU_IsNull(env, name)) { 377 return 0; 378 } 379 cname = (char *) JNU_GetStringPlatformChars(env, name, NULL); 380 if (cname == NULL) { 381 (*env)->ExceptionClear(env); 382 JNU_ThrowOutOfMemoryError(env, "Could not create font name"); 383 return 0; 384 } 385 386 /* additional default font names */ 387 if (strcmp(cname, "serif") == 0) { 388 *foundry = "adobe"; 389 *facename = "times"; 390 *encoding = isolatin1; 391 } else if (strcmp(cname, "sansserif") == 0) { 392 *foundry = "adobe"; 393 *facename = "helvetica"; 394 *encoding = isolatin1; 395 } else if (strcmp(cname, "monospaced") == 0) { 396 *foundry = "adobe"; 397 *facename = "courier"; 398 *encoding = isolatin1; 399 } else if (strcmp(cname, "helvetica") == 0) { 400 *foundry = "adobe"; 401 *facename = "helvetica"; 402 *encoding = isolatin1; 403 } else if (strcmp(cname, "timesroman") == 0) { 404 *foundry = "adobe"; 405 *facename = "times"; 406 *encoding = isolatin1; 407 } else if (strcmp(cname, "courier") == 0) { 408 *foundry = "adobe"; 409 *facename = "courier"; 410 *encoding = isolatin1; 411 } else if (strcmp(cname, "dialog") == 0) { 412 *foundry = "b&h"; 413 *facename = "lucida"; 414 *encoding = isolatin1; 415 } else if (strcmp(cname, "dialoginput") == 0) { 416 *foundry = "b&h"; 417 *facename = "lucidatypewriter"; 418 *encoding = isolatin1; 419 } else if (strcmp(cname, "zapfdingbats") == 0) { 420 *foundry = "itc"; 421 *facename = "zapfdingbats"; 422 *encoding = "*-*"; 423 } else { 424 #ifdef DEBUG 425 jio_fprintf(stderr, "Unknown font: %s\n", cname); 426 #endif 427 *foundry = defaultfoundry; 428 *facename = defaultfontname; 429 *encoding = isolatin1; 430 } 431 432 if (cname != NULL) 433 JNU_ReleaseStringPlatformChars(env, name, (const char *) cname); 434 435 return 1; 436 } 437 438 /* 439 * Registered with the 2D disposer to be called after the Font is GC'd. 440 */ 441 static void pDataDisposeMethod(JNIEnv *env, jlong pData) 442 { 443 struct FontData *fdata = NULL; 444 int32_t i = 0; 445 Display *display = XDISPLAY; 446 447 AWT_LOCK(); 448 fdata = (struct FontData *)pData; 449 450 if (fdata == NULL) { 451 AWT_UNLOCK(); 452 return; 453 } 454 455 if (fdata->xfs != NULL) { 456 XFreeFontSet(display, fdata->xfs); 457 } 458 459 /* AWT fonts are always "multifonts" and probably have been in 460 * all post 1.0 releases, so this test for multi fonts is 461 * probably not needed, and the singleton xfont is probably never used. 462 */ 463 if (fdata->charset_num > 0) { 464 for (i = 0; i < fdata->charset_num; i++) { 465 free((void *)fdata->flist[i].xlfd); 466 JNU_ReleaseStringPlatformChars(env, NULL, 467 fdata->flist[i].charset_name); 468 if (fdata->flist[i].load) { 469 XFreeFont(display, fdata->flist[i].xfont); 470 } 471 } 472 473 free((void *)fdata->flist); 474 475 /* Don't free fdata->xfont because it is equal to fdata->flist[i].xfont 476 for some 'i' */ 477 } else { 478 if (fdata->xfont != NULL) { 479 XFreeFont(display, fdata->xfont); 480 } 481 } 482 483 free((void *)fdata); 484 485 AWT_UNLOCK(); 486 } 487 #endif /* !HEADLESS */