fe008ae27a
Reviewed-by: darcy, weijun
349 lines
11 KiB
C
349 lines
11 KiB
C
/*
|
|
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* 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.
|
|
*/
|
|
|
|
/*
|
|
* Important note : All AWTxxx functions are defined in font.h.
|
|
* These were added to remove the dependency of this file on X11.
|
|
* These functions are used to perform X11 operations and should
|
|
* be "stubbed out" in environments that do not support X11.
|
|
* The implementation of these functions has been moved from this file
|
|
* into X11FontScaler_md.c, which is compiled into another library.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <malloc.h>
|
|
#include <ctype.h>
|
|
#include <sys/utsname.h>
|
|
|
|
#include <jni.h>
|
|
#include <jni_util.h>
|
|
|
|
#include "sun_font_NativeFont.h"
|
|
#include "sun_font_NativeStrike.h"
|
|
#include "sun_font_NativeStrikeDisposer.h"
|
|
#include "sunfontids.h"
|
|
#include "fontscalerdefs.h"
|
|
#include "X11FontScaler.h"
|
|
|
|
JNIEXPORT void JNICALL
|
|
Java_sun_font_NativeStrikeDisposer_freeNativeScalerContext
|
|
(JNIEnv *env, jobject disposer, jlong pScalerContext) {
|
|
|
|
NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
|
|
|
|
if (context != NULL) {
|
|
if (context->xFont != NULL) {
|
|
AWTFreeFont(context->xFont);
|
|
}
|
|
free(context);
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL
|
|
Java_sun_font_NativeStrike_createNullScalerContext
|
|
(JNIEnv *env, jobject strike) {
|
|
|
|
NativeScalerContext *context =
|
|
(NativeScalerContext*)malloc(sizeof(NativeScalerContext));
|
|
context->xFont = NULL;
|
|
context->minGlyph = 0;
|
|
context->maxGlyph = 0;
|
|
context->numGlyphs = 0;
|
|
context->defaultGlyph = 0;
|
|
context->ptSize = NO_POINTSIZE;
|
|
return (jlong)(uintptr_t)context;
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL
|
|
Java_sun_font_NativeStrike_createScalerContext
|
|
(JNIEnv *env, jobject strike, jbyteArray xlfdBytes,
|
|
jint ptSize, jdouble scale) {
|
|
|
|
NativeScalerContext *context;
|
|
int len = (*env)->GetArrayLength(env, xlfdBytes);
|
|
|
|
char* xlfd = (char*)malloc(len+1);
|
|
|
|
if (xlfd == NULL) {
|
|
return (jlong)(uintptr_t)0L;
|
|
}
|
|
|
|
(*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd);
|
|
xlfd[len] = '\0';
|
|
context = (NativeScalerContext*)malloc(sizeof(NativeScalerContext));
|
|
|
|
AWTLoadFont (xlfd, &(context->xFont));
|
|
free(xlfd);
|
|
|
|
if (context->xFont == NULL) { /* NULL means couldn't find the font */
|
|
free(context);
|
|
context = NULL;
|
|
} else {
|
|
/* numGlyphs is an estimate : X11 doesn't provide a quick way to
|
|
* discover which glyphs are valid: just the range that contains all
|
|
* the valid glyphs, and this range may have holes.
|
|
*/
|
|
context->minGlyph = (AWTFontMinByte1(context->xFont) << 8) +
|
|
AWTFontMinCharOrByte2(context->xFont);
|
|
context->maxGlyph = (AWTFontMaxByte1(context->xFont) << 8) +
|
|
AWTFontMaxCharOrByte2(context->xFont);
|
|
context->numGlyphs = context->maxGlyph - context->minGlyph + 1;
|
|
context->defaultGlyph = AWTFontDefaultChar(context->xFont);
|
|
/* Sometimes the default_char field of the XFontStruct isn't
|
|
* initialized to anything, so it can be a large number. So,
|
|
* check to see if its less than the largest possible value
|
|
* and if so, then use it. Otherwise, just use the minGlyph.
|
|
*/
|
|
if (context->defaultGlyph < context->minGlyph ||
|
|
context->defaultGlyph > context->maxGlyph) {
|
|
context->defaultGlyph = context->minGlyph;
|
|
}
|
|
context->ptSize = ptSize;
|
|
context->scale = scale;
|
|
}
|
|
|
|
/*
|
|
* REMIND: freeing of native resources? XID, XFontStruct etc??
|
|
*/
|
|
return (jlong)(uintptr_t)context;
|
|
}
|
|
|
|
|
|
/* JNIEXPORT jint JNICALL */
|
|
/* Java_sun_font_NativeFont_getItalicAngle */
|
|
/* (JNIEnv *env, jobject font) { */
|
|
|
|
/* UInt32 angle; */
|
|
/* AWTGetFontItalicAngle(xFont, &angle); */
|
|
/*X11 reports italic angle as 1/64ths of a degree, relative to 3 o'clock
|
|
* with anti-clockwise being the +ve rotation direction.
|
|
* We return
|
|
XGetFontProperty(xFont,XA_ITALIC_ANGLE, &angle);
|
|
*/
|
|
|
|
/* return (jint)angle; */
|
|
/* } */
|
|
|
|
JNIEXPORT jboolean JNICALL
|
|
Java_sun_font_NativeFont_fontExists
|
|
(JNIEnv *env, jclass fontClass, jbyteArray xlfdBytes) {
|
|
|
|
int count = 0;
|
|
int len = (*env)->GetArrayLength(env, xlfdBytes);
|
|
char* xlfd = (char*)malloc(len+1);
|
|
|
|
if (xlfd == NULL) {
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
(*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd);
|
|
xlfd[len] = '\0';
|
|
|
|
count = AWTCountFonts(xlfd);
|
|
free(xlfd);
|
|
if (count > 0) {
|
|
return JNI_TRUE;
|
|
} else {
|
|
return JNI_FALSE;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jboolean JNICALL
|
|
Java_sun_font_NativeFont_haveBitmapFonts
|
|
(JNIEnv *env, jclass fontClass, jbyteArray xlfdBytes) {
|
|
|
|
int count = 0;
|
|
int len = (*env)->GetArrayLength(env, xlfdBytes);
|
|
char* xlfd = (char*)malloc(len+1);
|
|
|
|
if (xlfd == NULL) {
|
|
return JNI_FALSE;
|
|
}
|
|
|
|
(*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd);
|
|
xlfd[len] = '\0';
|
|
|
|
count = AWTCountFonts(xlfd);
|
|
free(xlfd);
|
|
if (count > 2) {
|
|
return JNI_TRUE;
|
|
} else {
|
|
return JNI_FALSE;
|
|
}
|
|
}
|
|
|
|
// CountGlyphs doubles as way of getting a native font reference
|
|
// and telling if its valid. So far as I can tell GenerateImage etc
|
|
// just return if this "initialisation method" hasn't been called.
|
|
// So clients of this class need to call CountGlyphs() right after
|
|
// construction to be safe.
|
|
JNIEXPORT jint JNICALL
|
|
Java_sun_font_NativeFont_countGlyphs
|
|
(JNIEnv *env, jobject font, jbyteArray xlfdBytes, jint ptSize) {
|
|
|
|
NativeScalerContext *context = (NativeScalerContext*)
|
|
Java_sun_font_NativeStrike_createScalerContext
|
|
(env, NULL, xlfdBytes, ptSize, 1);
|
|
|
|
if (context == NULL) {
|
|
return 0;
|
|
} else {
|
|
int numGlyphs = context->numGlyphs;
|
|
AWTFreeFont(context->xFont);
|
|
free(context);
|
|
return numGlyphs;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jint JNICALL
|
|
Java_sun_font_NativeStrike_getMaxGlyph
|
|
(JNIEnv *env, jobject strike, jlong pScalerContext) {
|
|
|
|
NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
|
|
if (context == NULL) {
|
|
return (jint)0;
|
|
} else {
|
|
return (jint)context->maxGlyph+1;
|
|
}
|
|
}
|
|
|
|
JNIEXPORT jfloat JNICALL
|
|
Java_sun_font_NativeFont_getGlyphAdvance
|
|
(JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) {
|
|
|
|
NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
|
|
AWTFont xFont = (AWTFont)context->xFont;
|
|
AWTChar xcs;
|
|
jfloat advance = 0.0f;
|
|
|
|
if (xFont == NULL || context->ptSize == NO_POINTSIZE) {
|
|
return advance;
|
|
}
|
|
|
|
if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) {
|
|
glyphCode = context->defaultGlyph;
|
|
}
|
|
|
|
/* If number of glyphs is 256 or less, the metrics are
|
|
* stored correctly in the XFontStruct for each
|
|
* character. If the # characters is more (double byte
|
|
* case), then these metrics seem flaky and there's no
|
|
* way to determine if they have been set or not.
|
|
*/
|
|
if ((context->maxGlyph <= 256) && (AWTFontPerChar(xFont, 0) != NULL)) {
|
|
xcs = AWTFontPerChar(xFont, glyphCode - context->minGlyph);
|
|
advance = AWTCharAdvance(xcs);
|
|
} else {
|
|
int direction, ascent, descent;
|
|
AWTChar2b xChar;
|
|
|
|
xChar.byte1 = (unsigned char) (glyphCode >> 8);
|
|
xChar.byte2 = (unsigned char) glyphCode;
|
|
AWTFontTextExtents16(xFont, &xChar, &xcs);
|
|
advance = AWTCharAdvance(xcs);
|
|
AWTFreeChar(xcs);
|
|
}
|
|
return (jfloat)(advance/context->scale);
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL
|
|
Java_sun_font_NativeFont_getGlyphImageNoDefault
|
|
(JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) {
|
|
|
|
NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
|
|
AWTFont xFont = context->xFont;
|
|
AWTChar2b xChar;
|
|
|
|
if (xFont == NULL || context->ptSize == NO_POINTSIZE) {
|
|
return (jlong)0;
|
|
}
|
|
|
|
if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) {
|
|
return (jlong)0;
|
|
}
|
|
|
|
xChar.byte1 = (unsigned char)(glyphCode >> 8);
|
|
xChar.byte2 = (unsigned char)glyphCode;
|
|
return AWTFontGenerateImage(xFont, &xChar);
|
|
}
|
|
|
|
JNIEXPORT jlong JNICALL
|
|
Java_sun_font_NativeFont_getGlyphImage
|
|
(JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) {
|
|
|
|
NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
|
|
AWTFont xFont = context->xFont;
|
|
AWTChar2b xChar;
|
|
|
|
if (xFont == NULL || context->ptSize == NO_POINTSIZE) {
|
|
return (jlong)0;
|
|
}
|
|
|
|
if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) {
|
|
glyphCode = context->defaultGlyph;
|
|
}
|
|
|
|
xChar.byte1 = (unsigned char)(glyphCode >> 8);
|
|
xChar.byte2 = (unsigned char)glyphCode;
|
|
return AWTFontGenerateImage(xFont, &xChar);
|
|
}
|
|
|
|
JNIEXPORT jobject JNICALL
|
|
Java_sun_font_NativeFont_getFontMetrics
|
|
(JNIEnv *env, jobject font2D, jlong pScalerContext) {
|
|
|
|
NativeScalerContext *context = (NativeScalerContext*)pScalerContext;
|
|
AWTFont xFont = (AWTFont)context->xFont;
|
|
jfloat j0=0, j1=1, ay=j0, dy=j0, mx=j0;
|
|
jobject metrics;
|
|
|
|
if (xFont == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* the commented out lines are the old 1.4.x behaviour which used max
|
|
* bounds instead of the font's designed ascent/descent */
|
|
/* ay = (jfloat)-AWTCharAscent(AWTFontMaxBounds(xFont)); */
|
|
/* dy = (jfloat)AWTCharDescent(AWTFontMaxBounds(xFont)); */
|
|
|
|
ay = (jfloat)-AWTFontAscent(xFont);
|
|
dy = (jfloat)AWTFontDescent(xFont);
|
|
mx = (jfloat)AWTCharAdvance(AWTFontMaxBounds(xFont));
|
|
|
|
/* ascent : no need to set ascentX - it will be zero
|
|
* descent : no need to set descentX - it will be zero
|
|
* baseline : old releases "made up" a number and also seemed to
|
|
* make it up for "X" and set "Y" to 0.
|
|
* leadingX : no need to set leadingX - it will be zero.
|
|
* leadingY : made-up number, but being compatible with what 1.4.x did
|
|
* advance : no need to set yMaxLinearAdvanceWidth - it will be zero.
|
|
*/
|
|
metrics = (*env)->NewObject(env, sunFontIDs.strikeMetricsClass,
|
|
sunFontIDs.strikeMetricsCtr,
|
|
j0, ay, j0, dy, j1, j0, j0, j1, mx, j0);
|
|
/* printf("X11 asc=%f dsc=%f adv=%f scale=%f\n", */
|
|
/* ay, dy, mx, (float)context->scale); */
|
|
return metrics;
|
|
}
|