/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <string.h>
#endif /* __linux__ */
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef __solaris__
#include <sys/systeminfo.h>
#endif
#include <jni.h>
#include <jni_util.h>
#include <jvm_md.h>
#include <sizecalc.h>
#include <sun_font_FontManager.h>
#ifndef HEADLESS
#include <awt.h>
#else
/* locks ought to be included from awt.h */
#define AWT_LOCK()
#define AWT_UNLOCK()
#endif /* !HEADLESS */
#if defined(__linux__) && !defined(MAP_FAILED)
#endif
#ifndef HEADLESS
extern Display *awt_display;
#endif /* !HEADLESS */
#ifdef MACOSX
//
// XXXDARWIN: Hard-code the path to Apple's fontconfig, as it is
// not included in the dyld search path by default, and 10.4
// does not support -rpath.
//
// This ignores the build time setting of ALT_FREETYPE_LIB_PATH,
// and should be replaced with -rpath/@rpath support on 10.5 or later,
// or via support for a the FREETYPE_LIB_PATH define.
#else
#endif
/*
*/
#ifndef OPENWINHOMELIB
#endif
/* This is all known Solaris X11 directories on Solaris 8, 9 and 10.
* It is ordered to give precedence to TrueType directories.
* It is needed if fontconfig is not installed or configured properly.
*/
static char *fullSolarisFontPath[] = {
NULL, /* terminates the list */
};
static char *full_MACOSX_X11FontPath[] = {
PACKAGE_PATH "/share/fonts/tt",
PACKAGE_PATH "/share/fonts/TTF",
PACKAGE_PATH "/share/fonts/OTF",
PACKAGE_PATH "/share/fonts/Type1",
NULL, /* terminates the list */
};
#else /* __linux */
/* All the known interesting locations we have discovered on
* various flavors of Linux
*/
static char *fullLinuxFontPath[] = {
NULL, /* terminates the list */
};
#endif
static char **getFontConfigLocations();
typedef struct {
int num;
#ifndef HEADLESS
/*
* Returns True if display is local, False of it's remote.
*/
if (! isLocalSet) {
"getLocalGraphicsEnvironment",
"()Ljava/awt/GraphicsEnvironment;");
"isDisplayLocal",
"()Z");
} else {
}
isLocalSet = True;
}
return isLocal;
}
{
char *onePath;
int origIndex;
int totalDirCount;
char **origFontPath;
char **tempFontPath;
int doNotAppend;
int *appendDirList;
char **newFontPath;
int dirFile;
doNotAppend = 0;
if ( appendDirList == NULL ) {
return; /* if it fails we cannot do much */
}
doNotAppend = 0;
onePath = *tempFontPath;
/* there is a slash at the end of every solaris X11 font path name */
doNotAppend = 1;
break;
}
tempFontPath++;
}
appendDirList[index] = 0;
if ( doNotAppend == 0 ) {
if ( dirFile == -1 ) {
doNotAppend = 1;
} else {
}
}
}
/* if no changes are required do not bother to do a setfontpath */
if ( totalDirCount == nPaths ) {
free ( ( void *) appendDirList );
return;
}
/* if it fails free things and get out */
if ( newFontPath == NULL ) {
free ( ( void *) appendDirList );
return;
}
}
/* now add the other font paths */
/* printf ( "Appending %s\n", fDirP->name[index] ); */
free ( ( void *) appendDirList );
return;
}
/* printf ( "The path to be appended is %s\n", onePath ); */
}
}
/* printf ( "The dir count = %d\n", totalDirCount ); */
free ( ( void *) appendDirList );
}
free ( (void *) newFontPath );
return;
}
#endif /* !HEADLESS */
#ifndef HEADLESS
static char **getX11FontPath ()
{
/* This isn't ever going to be perfect: the font path may contain
* much we aren't interested in, but the cost should be moderate
* Exclude all directories that contain the strings "Speedo","/F3/",
* "75dpi", "100dpi", "misc" or "bitmap", or don't begin with a "/",
* the last of which should exclude font servers.
* Also exclude the user specific ".gnome*" directories which
* aren't going to contain the system fonts we need.
* Hopefully we are left only with Type1 and TrueType directories.
* It doesn't matter much if there are extraneous directories, it'll just
* cost us a little wasted effort upstream.
*/
pos = 0;
for (i=0; i < nPaths; i++) {
if (x11Path[i][0] != '/') {
continue;
}
continue;
}
continue;
}
continue;
}
continue;
}
continue;
}
#ifdef __solaris__
continue;
}
continue;
}
#endif
}
pos++;
}
if (pos == 0) {
}
return fontdirs;
}
#endif /* !HEADLESS */
/* from awt_LoadLibrary.c */
#endif
/* This eliminates duplicates, at a non-linear but acceptable cost
* since the lists are expected to be reasonably short, and then
* deletes references to non-existent directories, and returns
* a single path consisting of unique font directories.
*/
}
}
}
for (i=0; i < len1; i++) {
continue;
}
}
for (i=0; i < len2; i++) {
continue;
}
found = 0;
for (j=0; j < currLen; j++) {
found = 1;
break;
}
}
if (!found) {
}
}
for (i=0; i < len3; i++) {
continue;
}
found = 0;
for (j=0; j < currLen; j++) {
found = 1;
break;
}
}
if (!found) {
}
}
/* Now fontdirs contains unique dirs and numDirs records how many.
* What we don't know is if they all exist. On reflection I think
* this isn't an issue, so for now I will return all these locations,
* converted to one string */
for (i=0; i<numDirs; i++) {
}
*fontPath = '\0';
for (i = 0; i<numDirs; i++) {
if (i != 0) {
}
}
}
return fontPath;
}
/*
* The goal of this function is to find all "system" fonts which
* are needed by the JRE to display text in supported locales etc, and
* to support APIs which allow users to enumerate all system fonts and use
* them from their Java applications.
* The preferred mechanism is now using the new "fontconfig" library
* This exists on newer versions of Linux and Solaris (S10 and above)
* The library is dynamically located. The results are merged with
* a set of "known" locations and with the X11 font path, if running in
* a local X11 environment.
* The hardwired paths are built into the JDK binary so as new font locations
* are created on a host plaform for them to be located by the JRE they will
* need to be added ito the host's font configuration database, typically
* /etc/fonts/local.conf, and to ensure that directory contains a fonts.dir
* NB: Fontconfig also depends heavily for performance on the host O/S
* maintaining up to date caches.
* This is consistent with the requirements of the desktop environments
* on these OSes.
* This also frees us from X11 APIs as JRE is required to function in
* a "headless" mode where there is no Xserver.
*/
/* As of 1.5 we try to use fontconfig on both Solaris and Linux.
* If its not available NULL is returned.
*/
#if defined(__linux__)
#else /* IF SOLARIS */
#endif
/* REMIND: this code requires to be executed when the GraphicsEnvironment
* is already initialised. That is always true, but if it were not so,
* this code could throw an exception and the fontpath would fail to
* be initialised.
*/
#ifndef HEADLESS
/* There's no headless build on linux ... */
if (!AWTIsHeadless()) { /* .. so need to call a function to check */
#endif
/* Using the X11 font path to locate font files is now a fallback
* useful only if fontconfig failed, or is incomplete. So we could
* remove this code completely and the consequences should be rare
* and non-fatal. If this happens, then the calling Java code can
* be modified to no longer require that the AWT lock (the X11GE)
* be initialised prior to calling this code.
*/
AWT_LOCK();
if (isDisplayLocal(env)) {
x11dirs = getX11FontPath();
}
AWT_UNLOCK();
}
#endif
#endif /* !HEADLESS */
char **p = fcdirs;
}
char **p = x11dirs;
}
return path;
}
}
return ret;
}
#include <dlfcn.h>
#include "fontconfig.h"
static void* openFontConfig() {
char *homeEnv;
#ifdef __solaris__
#endif
/* Private workaround to not use fontconfig library.
*/
return NULL;
}
#ifdef __solaris__
* although allow user to override this behaviour with an env. variable
* ie if USE_J2D_FONTCONFIG=yes then we skip this test.
* NB "4" is the length of a string which matches our patterns.
*/
return NULL;
}
}
}
#endif
/* 64 bit sparc should pick up the right version from the lib path.
* New features may be added to libfontconfig, this is expected to
* be compatible with old features, but we may need to start
* distinguishing the library version, to know whether to expect
* certain symbols - and functionality - to be available.
* Also add explicit search for .so.1 in case .so symlink doesn't exist.
*/
if (libfontconfig == NULL) {
if (libfontconfig == NULL) {
return NULL;
}
}
/* Version 1.0 of libfontconfig crashes if HOME isn't defined in
* the environment. This should generally never happen, but we can't
* control it, and can't control the version of fontconfig, so iff
* its not defined we set it to an empty value which is sufficient
* to prevent a crash. I considered unsetting it before exit, but
* it doesn't appear to work on Solaris, so I will leave it set.
*/
}
return libfontconfig;
}
typedef void* (FcFiniFuncType)();
/* NB FcFini is not in (eg) the Solaris 10 version of fontconfig. Its not
* clear if this means we are really leaking resources in those cases
* but it seems we should call this function when its available.
* But since the Swing GTK code may be still accessing the lib, its probably
* safest for now to just let this "leak" rather than potentially
* concurrently free global data still in use by other code.
*/
#if 0
if (fcFini) { /* release resources */
(*FcFini)();
}
}
#endif
}
FcPattern *p,
FcObjectSet *os);
const char *object,
int n,
FcBool *b);
const char *object,
int n,
int *i);
const char *object,
int n,
FcChar8 ** s);
const char *object,
const FcChar8 *s);
FcPattern *p,
FcPattern *p,
const char *object,
int n,
FcCharSet **c);
FcPattern *p,
const FcCharSet *b);
const FcCharSet *b);
typedef int (*FcGetVersionFuncType)();
static char **getFontConfigLocations() {
char **fontdirs;
int numdirs = 0;
char **fontPath;
if (libfontconfig == NULL) {
return NULL;
}
if (FcPatternBuild == NULL ||
FcObjectSetBuild == NULL ||
FcPatternGetString == NULL ||
FcFontList == NULL ||
FcStrDirname == NULL ||
FcPatternDestroy == NULL ||
return NULL;
}
/* Make calls into the fontconfig library to build a search for
* outline fonts, and to get the set of full file paths from the matches.
* This set is returned from the call to FcFontList(..)
* We allocate an array of char* pointers sufficient to hold all
* the matches + 1 extra which ensures there will be a NULL after all
* valid entries.
* We call FcStrDirname strip the file name from the path, and
* check if we have yet seen this directory. If not we add a pointer to
* it into our array of char*. Note that FcStrDirname returns newly
* allocated storage so we can use this in the return char** value.
* Finally we clean up, freeing allocated resources, and return the
* array of unique directories.
*/
found = 0;
for (i=0;i<numdirs; i++) {
found = 1;
break;
}
}
if (!found) {
} else {
}
}
}
/* Free memory and close the ".so" */
(*FcFontSetDestroy)(fontSet);
(*FcPatternDestroy)(pattern);
return fontdirs;
}
/* These are copied from sun.awt.SunHints.
* Consider initialising them as ints using JNI for more robustness.
*/
int rgba = 0;
void* libfontconfig;
return -1;
}
return -1;
}
if (locale) {
}
return -1;
}
if (FcNameParse == NULL ||
FcPatternAddString == NULL ||
FcConfigSubstitute == NULL ||
FcDefaultSubstitute == NULL ||
FcFontMatch == NULL ||
FcPatternGetBool == NULL ||
FcPatternGetInteger == NULL ||
if (locale) {
}
return -1;
}
}
/* Perhaps should call FcFontRenderPrepare() here as some pattern
* elements might change as a result of that call, but I'm not seeing
* any difference in testing.
*/
if (matchPattern) {
}
(*FcPatternDestroy)(pattern);
if (locale) {
}
return TEXT_AA_OFF;
return TEXT_AA_ON;
} else {
switch (rgba) {
case FC_RGBA_RGB : return TEXT_AA_LCD_HRGB;
case FC_RGBA_BGR : return TEXT_AA_LCD_HBGR;
case FC_RGBA_VRGB : return TEXT_AA_LCD_VRGB;
case FC_RGBA_VBGR : return TEXT_AA_LCD_VBGR;
default : return TEXT_AA_LCD_HRGB; // should not get here.
}
}
}
void* libfontconfig;
int version = 0;
return 0;
}
if (FcGetVersion == NULL) {
return 0;
}
version = (*FcGetVersion)();
return version;
}
int i, arrlen;
void* libfontconfig;
return;
}
"Lsun/font/FontConfigManager$FontConfigFont;");
"[Lsun/font/FontConfigManager$FontConfigFont;");
fontFileID == NULL) {
return;
}
return;
}
"FcPatternGetCharSet");
"FcCharSetSubtractCount");
if (FcNameParse == NULL ||
FcPatternAddString == NULL ||
FcConfigSubstitute == NULL ||
FcDefaultSubstitute == NULL ||
FcFontMatch == NULL ||
FcPatternGetString == NULL ||
FcPatternDestroy == NULL ||
FcPatternGetCharSet == NULL ||
FcFontSetDestroy == NULL ||
FcCharSetUnion == NULL ||
FcGetVersion == NULL ||
return;
}
/* Optionally get the cache dir locations. This isn't
* available until v 2.4.x, but this is OK since on those later versions
* we can check the time stamps on the cache dirs to see if we
* are out of date. There are a couple of assumptions here. First
* that the time stamp on the directory changes when the contents are
* updated. Secondly that the locations don't change. The latter is
* most likely if a new version of fontconfig is installed, but we also
* invalidate the cache if we detect that. Arguably even that is "rare",
* and most likely is tied to an OS upgrade which gets a new file anyway.
*/
"FcConfigGetCacheDirs");
FcConfigGetCacheDirs != NULL) {
int cnt = 0;
}
(*FcStrListDone)(cacheDirs);
}
}
for (i=0; i<arrlen; i++) {
unsigned int minGlyphs;
continue;
}
return;
}
/* locale may not usually be necessary as fontconfig appears to apply
* this anyway based on the user's environment. However we want
* to use the value of the JDK startup locale so this should take
* care of it.
*/
}
(*FcPatternDestroy)(pattern);
return;
}
/* fontconfig returned us "nfonts". If we are just getting the
* first font, we set nfont to zero. Otherwise we use "nfonts".
* Next create separate C arrrays of length nfonts for family file etc.
* Inspect the returned fonts and the ones we like (adds enough glyphs)
* are added to the arrays and we increment 'fontCount'.
*/
}
}
}
}
(*FcPatternDestroy)(pattern);
(*FcFontSetDestroy)(fontset);
return;
}
fontCount = 0;
minGlyphs = 20;
if (debugMinGlyphsStr != NULL) {
}
}
for (j=0; j<nfonts; j++) {
fontformat = NULL;
/* We only want TrueType fonts but some Linuxes still depend
* on Type 1 fonts for some Locale support, so we'll allow
* them there.
*/
if (fontformat != NULL
#ifdef __linux__
#endif
) {
continue;
}
FC_CHARSET, 0, &charset);
if (result != FcResultMatch) {
(*FcPatternDestroy)(pattern);
(*FcFontSetDestroy)(fontset);
return;
}
/* We don't want 20 or 30 fonts, so once we hit 10 fonts,
* then require that they really be adding value. Too many
* adversely affects load time for minimal value-add.
* This is still likely far more than we've had in the past.
*/
if (j==10) {
minGlyphs = 50;
}
if (unionCharset == NULL) {
} else {
> minGlyphs) {
} else {
continue;
}
}
fontCount++; // found a font we will use.
if (!includeFallbacks) {
break;
}
}
/* Once we get here 'fontCount' is the number of returned fonts
* we actually want to use, so we create 'fcFontArr' of that length.
* The non-null entries of "family[]" etc are those fonts.
* Then loop again over all nfonts adding just those non-null ones
* to 'fcFontArr'. If its null (we didn't want the font)
* then we don't enter the main body.
* So we should never get more than 'fontCount' entries.
*/
if (includeFallbacks) {
}
fn=0;
for (j=0;j<nfonts;j++) {
}
}
}
if (fn==0) {
}
if (includeFallbacks) {
} else {
break;
}
}
}
(*FcFontSetDestroy)(fontset);
(*FcPatternDestroy)(pattern);
}
/* release resources and close the ".so" */
if (locale) {
}
}