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
44 static GC pixmapGC = 0;
45 static Pixmap pixmap = 0;
46 static Atom psAtom = 0;
47 static Atom fullNameAtom = 0;
48 static int pixmapWidth = 0;
49 static int pixmapHeight = 0;
50
51 #define FONT_AWT_LOCK() \
52 env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); \
53 AWT_LOCK();
54
CreatePixmapAndGC(int width,int height)55 int 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
dumpXImage(XImage * ximage)92 static 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
AWTCountFonts(char * xlfd)114 JNIEXPORT 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
AWTLoadFont(char * name,AWTFont * pReturn)129 JNIEXPORT 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
AWTFreeFont(AWTFont font)139 JNIEXPORT 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
AWTFontMinByte1(AWTFont font)148 JNIEXPORT unsigned JNICALL AWTFontMinByte1(AWTFont font) {
149 #ifdef HEADLESS
150 return 0;
151 #else
152 return ((XFontStruct *)font)->min_byte1;
153 #endif /* !HEADLESS */
154 }
155
AWTFontMaxByte1(AWTFont font)156 JNIEXPORT unsigned JNICALL AWTFontMaxByte1(AWTFont font) {
157 #ifdef HEADLESS
158 return 0;
159 #else
160 return ((XFontStruct *)font)->max_byte1;
161 #endif /* !HEADLESS */
162 }
163
AWTFontMinCharOrByte2(AWTFont font)164 JNIEXPORT 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
AWTFontMaxCharOrByte2(AWTFont font)172 JNIEXPORT 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
AWTFontDefaultChar(AWTFont font)180 JNIEXPORT unsigned JNICALL AWTFontDefaultChar(AWTFont font) {
181 #ifdef HEADLESS
182 return 0;
183 #else
184 return ((XFontStruct *)font)->default_char;
185 #endif /* !HEADLESS */
186 }
187
AWTFontPerChar(AWTFont font,int index)188 JNIEXPORT 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
AWTFontMaxBounds(AWTFont font)201 JNIEXPORT 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
AWTFontAscent(AWTFont font)210 JNIEXPORT int JNICALL AWTFontAscent(AWTFont font) {
211 #ifdef HEADLESS
212 return 0;
213 #else
214 return ((XFontStruct *)font)->ascent;
215 #endif /* !HEADLESS */
216 }
217
218
AWTFontDescent(AWTFont font)219 JNIEXPORT int JNICALL AWTFontDescent(AWTFont font) {
220 #ifdef HEADLESS
221 return 0;
222 #else
223 return ((XFontStruct *)font)->descent;
224 #endif /* !HEADLESS */
225 }
226
AWTFontTextExtents16(AWTFont font,AWTChar2b * xChar,AWTChar * overall)227 JNIEXPORT 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
AWTFreeChar(AWTChar xChar)255 JNIEXPORT void JNICALL AWTFreeChar(AWTChar xChar) {
256 #ifndef HEADLESS
257 free(xChar);
258 #endif /* !HEADLESS */
259 }
260
AWTFontGenerateImage(AWTFont pFont,AWTChar2b * xChar)261 JNIEXPORT 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
AWTCharAdvance(AWTChar xChar)377 JNIEXPORT short JNICALL AWTCharAdvance(AWTChar xChar) {
378 #ifdef HEADLESS
379 return 0;
380 #else
381 return ((XCharStruct *)xChar)->width;
382 #endif /* !HEADLESS */
383 }
384
AWTCharLBearing(AWTChar xChar)385 JNIEXPORT short JNICALL AWTCharLBearing(AWTChar xChar) {
386 #ifdef HEADLESS
387 return 0;
388 #else
389 return ((XCharStruct *)xChar)->lbearing;
390 #endif /* !HEADLESS */
391 }
392
AWTCharRBearing(AWTChar xChar)393 JNIEXPORT short JNICALL AWTCharRBearing(AWTChar xChar) {
394 #ifdef HEADLESS
395 return 0;
396 #else
397 return ((XCharStruct *)xChar)->rbearing;
398 #endif /* !HEADLESS */
399 }
400
AWTCharAscent(AWTChar xChar)401 JNIEXPORT short JNICALL AWTCharAscent(AWTChar xChar) {
402 #ifdef HEADLESS
403 return 0;
404 #else
405 return ((XCharStruct *)xChar)->ascent;
406 #endif /* !HEADLESS */
407 }
408
AWTCharDescent(AWTChar xChar)409 JNIEXPORT short JNICALL AWTCharDescent(AWTChar xChar) {
410 #ifdef HEADLESS
411 return 0;
412 #else
413 return ((XCharStruct *)xChar)->descent;
414 #endif /* !HEADLESS */
415 }
416