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