1/* 2 * Copyright (c) 2001, 2003, 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#include <stdio.h> 27#include <string.h> 28#include <stdlib.h> 29 30#include <ctype.h> 31#include <sys/utsname.h> 32 33#include <jni.h> 34#include <jni_util.h> 35#include "fontscalerdefs.h" 36#include "X11FontScaler.h" 37 38#ifndef HEADLESS 39 40#include <X11/Xlib.h> 41#include <X11/Xutil.h> 42#include <awt.h> 43 44static GC pixmapGC = 0; 45static Pixmap pixmap = 0; 46static Atom psAtom = 0; 47static Atom fullNameAtom = 0; 48static int pixmapWidth = 0; 49static int pixmapHeight = 0; 50 51#define FONT_AWT_LOCK() \ 52env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); \ 53AWT_LOCK(); 54 55int CreatePixmapAndGC (int width, int height) 56{ 57 /* REMIND: use the actual screen, not the default screen */ 58 Window awt_defaultRoot = 59 RootWindow(awt_display, DefaultScreen(awt_display)); 60 61 if (width < 100) { 62 width = 100; 63 } 64 if (height < 100) { 65 height = 100; 66 } 67 pixmapHeight = height; 68 pixmapWidth = width; 69 if (pixmap != 0) { 70 XFreePixmap (awt_display, pixmap); 71 } 72 if (pixmapGC != NULL) { 73 XFreeGC (awt_display, pixmapGC); 74 } 75 pixmap = XCreatePixmap (awt_display, awt_defaultRoot, pixmapWidth, 76 pixmapHeight, 1); 77 if (pixmap == 0) { 78 return BadAlloc; 79 } 80 pixmapGC = XCreateGC (awt_display, pixmap, 0, 0); 81 if (pixmapGC == NULL) { 82 return BadAlloc; 83 } 84 XFillRectangle (awt_display, pixmap, pixmapGC, 0, 0, pixmapWidth, 85 pixmapHeight); 86 XSetForeground (awt_display, pixmapGC, 1); 87 return Success; 88} 89 90#ifdef DUMP_IMAGES 91 92static void dumpXImage(XImage *ximage) 93{ 94 int height = ximage->height; 95 int width = ximage->width; 96 int row; 97 int column; 98 99 fprintf(stderr, "-------------------------------------------\n"); 100 for (row = 0; row < height; ++row) { 101 for (column = 0; column < width; ++column) { 102 int pixel = ximage->f.get_pixel(ximage, column, row); 103 fprintf(stderr, (pixel == 0) ? " " : "XX"); 104 } 105 fprintf(stderr, "\n"); 106 } 107 fprintf(stderr, "-------------------------------------------\n"); 108} 109 110#endif 111 112#endif /* !HEADLESS */ 113 114JNIEXPORT int JNICALL AWTCountFonts(char* xlfd) { 115#ifdef HEADLESS 116 return 0; 117#else 118 char **names; 119 int count; 120 JNIEnv *env; 121 FONT_AWT_LOCK(); 122 names = XListFonts(awt_display, xlfd, 3, &count); 123 XFreeFontNames(names); 124 AWT_UNLOCK(); 125 return count; 126#endif /* !HEADLESS */ 127} 128 129JNIEXPORT void JNICALL AWTLoadFont(char* name, AWTFont *pReturn) { 130 JNIEnv *env; 131 *pReturn = NULL; 132#ifndef HEADLESS 133 FONT_AWT_LOCK(); 134 *pReturn = (AWTFont)XLoadQueryFont(awt_display, name); 135 AWT_UNLOCK(); 136#endif /* !HEADLESS */ 137} 138 139JNIEXPORT void JNICALL AWTFreeFont(AWTFont font) { 140#ifndef HEADLESS 141 JNIEnv *env; 142 FONT_AWT_LOCK(); 143 XFreeFont(awt_display, (XFontStruct *)font); 144 AWT_UNLOCK(); 145#endif /* !HEADLESS */ 146} 147 148JNIEXPORT unsigned JNICALL AWTFontMinByte1(AWTFont font) { 149#ifdef HEADLESS 150 return 0; 151#else 152 return ((XFontStruct *)font)->min_byte1; 153#endif /* !HEADLESS */ 154} 155 156JNIEXPORT unsigned JNICALL AWTFontMaxByte1(AWTFont font) { 157#ifdef HEADLESS 158 return 0; 159#else 160 return ((XFontStruct *)font)->max_byte1; 161#endif /* !HEADLESS */ 162} 163 164JNIEXPORT unsigned JNICALL AWTFontMinCharOrByte2(AWTFont font) { 165#ifdef HEADLESS 166 return 0; 167#else 168 return ((XFontStruct *)font)->min_char_or_byte2; 169#endif /* !HEADLESS */ 170} 171 172JNIEXPORT unsigned JNICALL AWTFontMaxCharOrByte2(AWTFont font) { 173#ifdef HEADLESS 174 return 0; 175#else 176 return ((XFontStruct *)font)->max_char_or_byte2; 177#endif /* !HEADLESS */ 178} 179 180JNIEXPORT unsigned JNICALL AWTFontDefaultChar(AWTFont font) { 181#ifdef HEADLESS 182 return 0; 183#else 184 return ((XFontStruct *)font)->default_char; 185#endif /* !HEADLESS */ 186} 187 188JNIEXPORT AWTChar JNICALL AWTFontPerChar(AWTFont font, int index) { 189#ifdef HEADLESS 190 return NULL; 191#else 192 XFontStruct *fXFont = (XFontStruct *)font; 193 XCharStruct *perChar = fXFont->per_char; 194 if (perChar == NULL) { 195 return NULL; 196 } 197 return (AWTChar)&(perChar[index]); 198#endif /* !HEADLESS */ 199} 200 201JNIEXPORT AWTChar JNICALL AWTFontMaxBounds(AWTFont font) { 202#ifdef HEADLESS 203 return 0; 204#else 205 return (AWTChar)&((XFontStruct *)font)->max_bounds; 206#endif /* !HEADLESS */ 207} 208 209 210JNIEXPORT int JNICALL AWTFontAscent(AWTFont font) { 211#ifdef HEADLESS 212 return 0; 213#else 214 return ((XFontStruct *)font)->ascent; 215#endif /* !HEADLESS */ 216} 217 218 219JNIEXPORT int JNICALL AWTFontDescent(AWTFont font) { 220#ifdef HEADLESS 221 return 0; 222#else 223 return ((XFontStruct *)font)->descent; 224#endif /* !HEADLESS */ 225} 226 227JNIEXPORT void JNICALL AWTFontTextExtents16(AWTFont font, 228 AWTChar2b* xChar, 229 AWTChar* overall) { 230#ifndef HEADLESS 231 JNIEnv *env; 232 int ascent, descent, direction; 233 XFontStruct* xFont = (XFontStruct*)font; 234 XCharStruct* newChar = (XCharStruct*)malloc(sizeof(XCharStruct)); 235 *overall = (AWTChar)newChar; 236 /* There is a claim from the pre 1.5 source base that the info in the 237 * XFontStruct is flaky for 16 byte chars. This seems plausible as 238 * for info to be valid, that struct would need a large number of 239 * XCharStructs. But there's nothing in the X APIs which warns you of 240 * this. If it really is flaky you must question why there's an 241 * XTextExtents16 API call. Try XTextExtents16 for now and if it fails 242 * go back to XQueryTextExtents16 in this function. 243 * Indeed the metrics from the Solaris 9 JA font 244 * -ricoh-gothic-medium-r-normal--*-140-72-72-m-*-jisx0208.1983-0 245 * do appear different so revert to the query api 246 */ 247 FONT_AWT_LOCK(); 248 XQueryTextExtents16(awt_display,xFont->fid, xChar, 1, 249 &direction, &ascent, &descent, newChar); 250/* XTextExtents16(xFont, xChar, 1, &direction, &ascent, &descent, newChar); */ 251 AWT_UNLOCK(); 252#endif /* !HEADLESS */ 253} 254 255JNIEXPORT void JNICALL AWTFreeChar(AWTChar xChar) { 256#ifndef HEADLESS 257 free(xChar); 258#endif /* !HEADLESS */ 259} 260 261JNIEXPORT jlong JNICALL AWTFontGenerateImage(AWTFont pFont, AWTChar2b* xChar) { 262 263#ifndef HEADLESS 264 265 int width, height, direction, ascent, descent; 266 GlyphInfo *glyphInfo; 267 XFontStruct* xFont = (XFontStruct*)pFont; 268 XCharStruct xcs; 269 XImage *ximage; 270 int h, i, j, nbytes; 271 unsigned char *srcRow, *dstRow, *dstByte; 272 int wholeByteCount, remainingBitsCount; 273 unsigned int imageSize; 274 JNIEnv *env; 275 276 FONT_AWT_LOCK(); 277/* XTextExtents16(xFont, xChar, 1, &direction, &ascent, &descent, &xcs); */ 278 XQueryTextExtents16(awt_display,xFont->fid, xChar, 1, 279 &direction, &ascent, &descent, &xcs); 280 width = xcs.rbearing - xcs.lbearing; 281 height = xcs.ascent+xcs.descent; 282 imageSize = width*height; 283 284 glyphInfo = (GlyphInfo*)malloc(sizeof(GlyphInfo)+imageSize); 285 glyphInfo->cellInfo = NULL; 286 glyphInfo->width = width; 287 glyphInfo->height = height; 288 glyphInfo->topLeftX = xcs.lbearing; 289 glyphInfo->topLeftY = -xcs.ascent; 290 glyphInfo->advanceX = xcs.width; 291 glyphInfo->advanceY = 0; 292 293 if (imageSize == 0) { 294 glyphInfo->image = NULL; 295 AWT_UNLOCK(); 296 return (jlong)(uintptr_t)glyphInfo; 297 } else { 298 glyphInfo->image = (unsigned char*)glyphInfo+sizeof(GlyphInfo); 299 } 300 301 if ((pixmap == 0) || (width > pixmapWidth) || (height > pixmapHeight)) { 302 if (CreatePixmapAndGC(width, height) != Success) { 303 glyphInfo->image = NULL; 304 AWT_UNLOCK(); 305 return (jlong)(uintptr_t)glyphInfo; 306 } 307 } 308 309 XSetFont(awt_display, pixmapGC, xFont->fid); 310 XSetForeground(awt_display, pixmapGC, 0); 311 XFillRectangle(awt_display, pixmap, pixmapGC, 0, 0, 312 pixmapWidth, pixmapHeight); 313 XSetForeground(awt_display, pixmapGC, 1); 314 XDrawString16(awt_display, pixmap, pixmapGC, 315 -xcs.lbearing, xcs.ascent, xChar, 1); 316 ximage = XGetImage(awt_display, pixmap, 0, 0, width, height, 317 AllPlanes, XYPixmap); 318 319 if (ximage == NULL) { 320 glyphInfo->image = NULL; 321 AWT_UNLOCK(); 322 return (jlong)(uintptr_t)glyphInfo; 323 } 324 325#ifdef DUMP_IMAGES 326 dumpXImage(ximage); 327#endif 328 329 nbytes = ximage->bytes_per_line; 330 srcRow = (unsigned char*)ximage->data; 331 dstRow = (unsigned char*)glyphInfo->image; 332 wholeByteCount = width >> 3; 333 remainingBitsCount = width & 7; 334 335 for (h=0; h<height; h++) { 336 const UInt8* src8 = srcRow; 337 UInt8 *dstByte = dstRow; 338 UInt32 srcValue; 339 340 srcRow += nbytes; 341 dstRow += width; 342 343 for (i = 0; i < wholeByteCount; i++) { 344 srcValue = *src8++; 345 for (j = 0; j < 8; j++) { 346 if (ximage->bitmap_bit_order == LSBFirst) { 347 *dstByte++ = (srcValue & 0x01) ? 0xFF : 0; 348 srcValue >>= 1; 349 } else { /* MSBFirst */ 350 *dstByte++ = (srcValue & 0x80) ? 0xFF : 0; 351 srcValue <<= 1; 352 } 353 } 354 } 355 if (remainingBitsCount) { 356 srcValue = *src8; 357 for (j = 0; j < remainingBitsCount; j++) { 358 if (ximage->bitmap_bit_order == LSBFirst) { 359 *dstByte++ = (srcValue & 0x01) ? 0xFF : 0; 360 srcValue >>= 1; 361 } else { /* MSBFirst */ 362 *dstByte++ = (srcValue & 0x80) ? 0xFF : 0; 363 srcValue <<= 1; 364 } 365 } 366 } 367 } 368 369 XDestroyImage (ximage); 370 AWT_UNLOCK(); 371 return (jlong)(uintptr_t)glyphInfo; 372#else 373 return (jlong)0; 374#endif /* !HEADLESS */ 375} 376 377JNIEXPORT short JNICALL AWTCharAdvance(AWTChar xChar) { 378#ifdef HEADLESS 379 return 0; 380#else 381 return ((XCharStruct *)xChar)->width; 382#endif /* !HEADLESS */ 383} 384 385JNIEXPORT short JNICALL AWTCharLBearing(AWTChar xChar) { 386#ifdef HEADLESS 387 return 0; 388#else 389 return ((XCharStruct *)xChar)->lbearing; 390#endif /* !HEADLESS */ 391} 392 393JNIEXPORT short JNICALL AWTCharRBearing(AWTChar xChar) { 394#ifdef HEADLESS 395 return 0; 396#else 397 return ((XCharStruct *)xChar)->rbearing; 398#endif /* !HEADLESS */ 399} 400 401JNIEXPORT short JNICALL AWTCharAscent(AWTChar xChar) { 402#ifdef HEADLESS 403 return 0; 404#else 405 return ((XCharStruct *)xChar)->ascent; 406#endif /* !HEADLESS */ 407} 408 409JNIEXPORT short JNICALL AWTCharDescent(AWTChar xChar) { 410#ifdef HEADLESS 411 return 0; 412#else 413 return ((XCharStruct *)xChar)->descent; 414#endif /* !HEADLESS */ 415} 416