J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 2003-2007 Sun Microsystems, Inc. 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. Sun designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 22 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 23 | * have any questions. |
| 24 | */ |
| 25 | |
| 26 | /* |
| 27 | * Important note : All AWTxxx functions are defined in font.h. |
| 28 | * These were added to remove the dependency of this file on X11. |
| 29 | * These functions are used to perform X11 operations and should |
| 30 | * be "stubbed out" in environments that do not support X11. |
| 31 | * The implementation of these functions has been moved from this file |
| 32 | * into X11FontScaler_md.c, which is compiled into another library. |
| 33 | */ |
| 34 | #include <stdio.h> |
| 35 | #include <malloc.h> |
| 36 | #include <ctype.h> |
| 37 | #include <sys/utsname.h> |
| 38 | |
| 39 | #include <jni.h> |
| 40 | #include <jni_util.h> |
| 41 | |
| 42 | #include "sun_font_NativeFont.h" |
| 43 | #include "sun_font_NativeStrike.h" |
| 44 | #include "sun_font_NativeStrikeDisposer.h" |
| 45 | #include "sunfontids.h" |
| 46 | #include "fontscalerdefs.h" |
| 47 | #include "X11FontScaler.h" |
| 48 | |
| 49 | JNIEXPORT void JNICALL |
| 50 | Java_sun_font_NativeStrikeDisposer_freeNativeScalerContext |
| 51 | (JNIEnv *env, jobject disposer, jlong pScalerContext) { |
| 52 | |
| 53 | NativeScalerContext *context = (NativeScalerContext*)pScalerContext; |
| 54 | |
| 55 | if (context != NULL) { |
| 56 | if (context->xFont != NULL) { |
| 57 | AWTFreeFont(context->xFont); |
| 58 | } |
| 59 | free(context); |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | JNIEXPORT jlong JNICALL |
| 64 | Java_sun_font_NativeStrike_createNullScalerContext |
| 65 | (JNIEnv *env, jobject strike) { |
| 66 | |
| 67 | NativeScalerContext *context = |
| 68 | (NativeScalerContext*)malloc(sizeof(NativeScalerContext)); |
| 69 | context->xFont = NULL; |
| 70 | context->minGlyph = 0; |
| 71 | context->maxGlyph = 0; |
| 72 | context->numGlyphs = 0; |
| 73 | context->defaultGlyph = 0; |
| 74 | context->ptSize = NO_POINTSIZE; |
| 75 | return (jlong)(uintptr_t)context; |
| 76 | } |
| 77 | |
| 78 | JNIEXPORT jlong JNICALL |
| 79 | Java_sun_font_NativeStrike_createScalerContext |
| 80 | (JNIEnv *env, jobject strike, jbyteArray xlfdBytes, |
| 81 | jint ptSize, jdouble scale) { |
| 82 | |
| 83 | NativeScalerContext *context; |
| 84 | int len = (*env)->GetArrayLength(env, xlfdBytes); |
| 85 | |
| 86 | char* xlfd = (char*)malloc(len+1); |
| 87 | |
| 88 | if (xlfd == NULL) { |
| 89 | return (jlong)(uintptr_t)0L; |
| 90 | } |
| 91 | |
| 92 | (*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd); |
| 93 | xlfd[len] = '\0'; |
| 94 | context = (NativeScalerContext*)malloc(sizeof(NativeScalerContext)); |
| 95 | |
| 96 | AWTLoadFont (xlfd, &(context->xFont)); |
| 97 | free(xlfd); |
| 98 | |
| 99 | if (context->xFont == NULL) { /* NULL means couldn't find the font */ |
| 100 | free(context); |
| 101 | context = NULL; |
| 102 | } else { |
| 103 | /* numGlyphs is an estimate : X11 doesn't provide a quick way to |
| 104 | * discover which glyphs are valid: just the range that contains all |
| 105 | * the valid glyphs, and this range may have holes. |
| 106 | */ |
| 107 | context->minGlyph = (AWTFontMinByte1(context->xFont) << 8) + |
| 108 | AWTFontMinCharOrByte2(context->xFont); |
| 109 | context->maxGlyph = (AWTFontMaxByte1(context->xFont) << 8) + |
| 110 | AWTFontMaxCharOrByte2(context->xFont); |
| 111 | context->numGlyphs = context->maxGlyph - context->minGlyph + 1; |
| 112 | context->defaultGlyph = AWTFontDefaultChar(context->xFont); |
| 113 | /* Sometimes the default_char field of the XFontStruct isn't |
| 114 | * initialized to anything, so it can be a large number. So, |
| 115 | * check to see if its less than the largest possible value |
| 116 | * and if so, then use it. Otherwise, just use the minGlyph. |
| 117 | */ |
| 118 | if (context->defaultGlyph < context->minGlyph || |
| 119 | context->defaultGlyph > context->maxGlyph) { |
| 120 | context->defaultGlyph = context->minGlyph; |
| 121 | } |
| 122 | context->ptSize = ptSize; |
| 123 | context->scale = scale; |
| 124 | } |
| 125 | |
| 126 | /* |
| 127 | * REMIND: freeing of native resources? XID, XFontStruct etc?? |
| 128 | */ |
| 129 | return (jlong)(uintptr_t)context; |
| 130 | } |
| 131 | |
| 132 | |
| 133 | /* JNIEXPORT jint JNICALL */ |
| 134 | /* Java_sun_font_NativeFont_getItalicAngle */ |
| 135 | /* (JNIEnv *env, jobject font) { */ |
| 136 | |
| 137 | /* UInt32 angle; */ |
| 138 | /* AWTGetFontItalicAngle(xFont, &angle); */ |
| 139 | /*X11 reports italic angle as 1/64ths of a degree, relative to 3 o'clock |
| 140 | * with anti-clockwise being the +ve rotation direction. |
| 141 | * We return |
| 142 | XGetFontProperty(xFont,XA_ITALIC_ANGLE, &angle); |
| 143 | */ |
| 144 | |
| 145 | /* return (jint)angle; */ |
| 146 | /* } */ |
| 147 | |
| 148 | JNIEXPORT jboolean JNICALL |
| 149 | Java_sun_font_NativeFont_fontExists |
| 150 | (JNIEnv *env, jclass fontClass, jbyteArray xlfdBytes) { |
| 151 | |
| 152 | int count = 0; |
| 153 | int len = (*env)->GetArrayLength(env, xlfdBytes); |
| 154 | char* xlfd = (char*)malloc(len+1); |
| 155 | |
| 156 | if (xlfd == NULL) { |
| 157 | return JNI_FALSE; |
| 158 | } |
| 159 | |
| 160 | (*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd); |
| 161 | xlfd[len] = '\0'; |
| 162 | |
| 163 | count = AWTCountFonts(xlfd); |
| 164 | free(xlfd); |
| 165 | if (count > 0) { |
| 166 | return JNI_TRUE; |
| 167 | } else { |
| 168 | return JNI_FALSE; |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | JNIEXPORT jboolean JNICALL |
| 173 | Java_sun_font_NativeFont_haveBitmapFonts |
| 174 | (JNIEnv *env, jclass fontClass, jbyteArray xlfdBytes) { |
| 175 | |
| 176 | int count = 0; |
| 177 | int len = (*env)->GetArrayLength(env, xlfdBytes); |
| 178 | char* xlfd = (char*)malloc(len+1); |
| 179 | |
| 180 | if (xlfd == NULL) { |
| 181 | return JNI_FALSE; |
| 182 | } |
| 183 | |
| 184 | (*env)->GetByteArrayRegion(env, xlfdBytes, 0, len, (jbyte*)xlfd); |
| 185 | xlfd[len] = '\0'; |
| 186 | |
| 187 | count = AWTCountFonts(xlfd); |
| 188 | free(xlfd); |
| 189 | if (count > 2) { |
| 190 | return JNI_TRUE; |
| 191 | } else { |
| 192 | return JNI_FALSE; |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | // CountGlyphs doubles as way of getting a native font reference |
| 197 | // and telling if its valid. So far as I can tell GenerateImage etc |
| 198 | // just return if this "initialisation method" hasn't been called. |
| 199 | // So clients of this class need to call CountGlyphs() right after |
| 200 | // construction to be safe. |
| 201 | JNIEXPORT jint JNICALL |
| 202 | Java_sun_font_NativeFont_countGlyphs |
| 203 | (JNIEnv *env, jobject font, jbyteArray xlfdBytes, jint ptSize) { |
| 204 | |
| 205 | NativeScalerContext *context = (NativeScalerContext*) |
| 206 | Java_sun_font_NativeStrike_createScalerContext |
| 207 | (env, NULL, xlfdBytes, ptSize, 1); |
| 208 | |
| 209 | if (context == NULL) { |
| 210 | return 0; |
| 211 | } else { |
| 212 | int numGlyphs = context->numGlyphs; |
| 213 | AWTFreeFont(context->xFont); |
| 214 | free(context); |
| 215 | return numGlyphs; |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | JNIEXPORT jint JNICALL |
| 220 | Java_sun_font_NativeStrike_getMaxGlyph |
| 221 | (JNIEnv *env, jobject strike, jlong pScalerContext) { |
| 222 | |
| 223 | NativeScalerContext *context = (NativeScalerContext*)pScalerContext; |
| 224 | if (context == NULL) { |
| 225 | return (jint)0; |
| 226 | } else { |
| 227 | return (jint)context->maxGlyph+1; |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | JNIEXPORT jfloat JNICALL |
| 232 | Java_sun_font_NativeFont_getGlyphAdvance |
| 233 | (JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) { |
| 234 | |
| 235 | NativeScalerContext *context = (NativeScalerContext*)pScalerContext; |
| 236 | AWTFont xFont = (AWTFont)context->xFont; |
| 237 | AWTChar xcs; |
| 238 | jfloat advance = 0.0f; |
| 239 | |
| 240 | if (xFont == NULL || context->ptSize == NO_POINTSIZE) { |
| 241 | return advance; |
| 242 | } |
| 243 | |
| 244 | if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) { |
| 245 | glyphCode = context->defaultGlyph; |
| 246 | } |
| 247 | |
| 248 | /* If number of glyphs is 256 or less, the metrics are |
| 249 | * stored correctly in the XFontStruct for each |
| 250 | * character. If the # characters is more (double byte |
| 251 | * case), then these metrics seem flaky and there's no |
| 252 | * way to determine if they have been set or not. |
| 253 | */ |
| 254 | if ((context->maxGlyph <= 256) && (AWTFontPerChar(xFont, 0) != NULL)) { |
| 255 | xcs = AWTFontPerChar(xFont, glyphCode - context->minGlyph); |
| 256 | advance = AWTCharAdvance(xcs); |
| 257 | } else { |
| 258 | int direction, ascent, descent; |
| 259 | AWTChar2b xChar; |
| 260 | |
| 261 | xChar.byte1 = (unsigned char) (glyphCode >> 8); |
| 262 | xChar.byte2 = (unsigned char) glyphCode; |
| 263 | AWTFontTextExtents16(xFont, &xChar, &xcs); |
| 264 | advance = AWTCharAdvance(xcs); |
| 265 | AWTFreeChar(xcs); |
| 266 | } |
| 267 | return (jfloat)(advance/context->scale); |
| 268 | } |
| 269 | |
| 270 | JNIEXPORT jlong JNICALL |
| 271 | Java_sun_font_NativeFont_getGlyphImageNoDefault |
| 272 | (JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) { |
| 273 | |
| 274 | NativeScalerContext *context = (NativeScalerContext*)pScalerContext; |
| 275 | AWTFont xFont = context->xFont; |
| 276 | AWTChar2b xChar; |
| 277 | |
| 278 | if (xFont == NULL || context->ptSize == NO_POINTSIZE) { |
| 279 | return (jlong)0; |
| 280 | } |
| 281 | |
| 282 | if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) { |
| 283 | return (jlong)0; |
| 284 | } |
| 285 | |
| 286 | xChar.byte1 = (unsigned char)(glyphCode >> 8); |
| 287 | xChar.byte2 = (unsigned char)glyphCode; |
| 288 | return AWTFontGenerateImage(xFont, &xChar); |
| 289 | } |
| 290 | |
| 291 | JNIEXPORT jlong JNICALL |
| 292 | Java_sun_font_NativeFont_getGlyphImage |
| 293 | (JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) { |
| 294 | |
| 295 | NativeScalerContext *context = (NativeScalerContext*)pScalerContext; |
| 296 | AWTFont xFont = context->xFont; |
| 297 | AWTChar2b xChar; |
| 298 | |
| 299 | if (xFont == NULL || context->ptSize == NO_POINTSIZE) { |
| 300 | return (jlong)0; |
| 301 | } |
| 302 | |
| 303 | if (glyphCode < context->minGlyph || glyphCode > context->maxGlyph) { |
| 304 | glyphCode = context->defaultGlyph; |
| 305 | } |
| 306 | |
| 307 | xChar.byte1 = (unsigned char)(glyphCode >> 8); |
| 308 | xChar.byte2 = (unsigned char)glyphCode; |
| 309 | return AWTFontGenerateImage(xFont, &xChar); |
| 310 | } |
| 311 | |
| 312 | JNIEXPORT jobject JNICALL |
| 313 | Java_sun_font_NativeFont_getFontMetrics |
| 314 | (JNIEnv *env, jobject font2D, jlong pScalerContext) { |
| 315 | |
| 316 | NativeScalerContext *context = (NativeScalerContext*)pScalerContext; |
| 317 | AWTFont xFont = (AWTFont)context->xFont; |
| 318 | jfloat j0=0, j1=1, ay=j0, dy=j0, mx=j0; |
| 319 | jobject metrics; |
| 320 | |
| 321 | if (xFont == NULL) { |
| 322 | return NULL; |
| 323 | } |
| 324 | |
| 325 | /* the commented out lines are the old 1.4.x behaviour which used max |
| 326 | * bounds instead of the font's designed ascent/descent */ |
| 327 | /* ay = (jfloat)-AWTCharAscent(AWTFontMaxBounds(xFont)); */ |
| 328 | /* dy = (jfloat)AWTCharDescent(AWTFontMaxBounds(xFont)); */ |
| 329 | |
| 330 | ay = (jfloat)-AWTFontAscent(xFont); |
| 331 | dy = (jfloat)AWTFontDescent(xFont); |
| 332 | mx = (jfloat)AWTCharAdvance(AWTFontMaxBounds(xFont)); |
| 333 | |
| 334 | /* ascent : no need to set ascentX - it will be zero |
| 335 | * descent : no need to set descentX - it will be zero |
| 336 | * baseline : old releases "made up" a number and also seemed to |
| 337 | * make it up for "X" and set "Y" to 0. |
| 338 | * leadingX : no need to set leadingX - it will be zero. |
| 339 | * leadingY : made-up number, but being compatible with what 1.4.x did |
| 340 | * advance : no need to set yMaxLinearAdvanceWidth - it will be zero. |
| 341 | */ |
| 342 | metrics = (*env)->NewObject(env, sunFontIDs.strikeMetricsClass, |
| 343 | sunFontIDs.strikeMetricsCtr, |
| 344 | j0, ay, j0, dy, j1, j0, j0, j1, mx, j0); |
| 345 | /* printf("X11 asc=%f dsc=%f adv=%f scale=%f\n", */ |
| 346 | /* ay, dy, mx, (float)context->scale); */ |
| 347 | return metrics; |
| 348 | } |