Mercurial > hg > release > icedtea6-1.3
changeset 63:e6e4d2549813
merge changelog
author | Lillian Angel <langel@redhat.com> |
---|---|
date | Wed, 27 Jun 2007 13:31:22 -0400 |
parents | 4d2a546e1a10 (current diff) bc010bfa0374 (diff) |
children | ab6ec85956fb |
files | ChangeLog |
diffstat | 2 files changed, 2204 insertions(+), 12 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed Jun 27 13:06:55 2007 -0400 +++ b/ChangeLog Wed Jun 27 13:31:22 2007 -0400 @@ -141,6 +141,10 @@ rt/javax/security/sasl/SaslServerFactory.java: Removed from repo. They are being copied from the openjdk src anyways. +2007-06-27 Francis Kung <fkung@redhat.com> + + * patches/icedtea-graphics.patch: Stub out libt2k. + 2007-06-26 Lillian Angel <langel@redhat.com> * AUTHORS: Added aph.
--- a/patches/icedtea-graphics.patch Wed Jun 27 13:06:55 2007 -0400 +++ b/patches/icedtea-graphics.patch Wed Jun 27 13:31:22 2007 -0400 @@ -1,15 +1,3 @@ -diff -urN openjdk.orig/j2se/src/share/native/sun/font/sunFont.c openjdk/j2se/src/share/native/sun/font/sunFont.c ---- openjdk.orig/j2se/src/share/native/sun/font/sunFont.c 2007-05-24 03:43:59.000000000 -0400 -+++ openjdk/j2se/src/share/native/sun/font/sunFont.c 2007-06-18 13:55:32.000000000 -0400 -@@ -164,7 +164,7 @@ - tmpClass = (*env)->FindClass(env, "sun/font/FileFont"); - sunFontIDs.pScaler = (*env)->GetFieldID(env, tmpClass, "pScaler", "J"); - -- setSunFontIDs(sunFontIDs); -+/* setSunFontIDs(sunFontIDs); */ - initLCDGammaTables(); - } - diff -urN openjdk.orig/j2se/src/share/native/sun/java2d/cmm/lcms/LCMS.c openjdk/j2se/src/share/native/sun/java2d/cmm/lcms/LCMS.c --- openjdk.orig/j2se/src/share/native/sun/java2d/cmm/lcms/LCMS.c 2007-05-24 03:44:01.000000000 -0400 +++ openjdk/j2se/src/share/native/sun/java2d/cmm/lcms/LCMS.c 2007-06-18 15:45:29.000000000 -0400 @@ -138,3 +126,2203 @@ .PHONY: copy-closed-src-classes +diff -urN openjdk.orig/j2se/src/share/native/sun/font/GeneralPath.cpp openjdk/j2se/src/share/native/sun/font/GeneralPath.cpp +--- openjdk.orig/j2se/src/share/native/sun/font/GeneralPath.cpp 2007-06-21 03:47:50.000000000 -0400 ++++ openjdk/j2se/src/share/native/sun/font/GeneralPath.cpp 2007-06-26 13:40:38.000000000 -0400 +@@ -174,7 +174,7 @@ + + class Walker { + public: +- const GlyphClass& glyph; ++ void* glyph; + int contourIndex; + int start; + int limit; +@@ -185,7 +185,7 @@ + bool closed; + bool done; + +- Walker(const GlyphClass& _glyph, jfloat _x, jfloat _y, bool _closed) ++ Walker(void* _glyph, jfloat _x, jfloat _y, bool _closed) + : glyph(_glyph) + , contourIndex(0) + , start(0) +@@ -200,6 +200,7 @@ + } + + bool nextContour() { ++/* + while (contourIndex < glyph.contourCount) { + start = glyph.sp[contourIndex]; + limit = glyph.ep[contourIndex] + 1; +@@ -211,6 +212,7 @@ + return true; + } + } ++*/ + return false; + } + +@@ -232,11 +234,13 @@ + } + + inline bool currentOnCurve() const { +- return glyph.onCurve[index0]; ++ /*return glyph.onCurve[index0];*/ ++ return false; + } + + inline bool nextOnCurve() const { +- return glyph.onCurve[index1]; ++ /*return glyph.onCurve[index1];*/ ++ return false; + } + + inline void setCurrent(JPoint& pt) const { +@@ -250,28 +254,36 @@ + // fprintf(stderr, "ftf: 0x%lx ", (jint)F26Dot6ToJFloat(p)); + // fprintf(stderr, "val: %g\n", F26Dot6ToJFloat(p)); + ++ /* + pt.x = x + F26Dot6ToScalar(glyph.x[index0]); + pt.y = y - F26Dot6ToScalar(glyph.y[index0]); ++ */ + } + + inline void setNext(JPoint& pt) const { ++ /* + pt.x = x + F26Dot6ToScalar(glyph.x[index1]); + pt.y = y - F26Dot6ToScalar(glyph.y[index1]); ++ */ + } + + inline void setAverage(JPoint& pt) const { ++ /* + t2kScalar p0 = F26Dot6ToScalar(glyph.x[index0]); + t2kScalar p1 = F26Dot6ToScalar(glyph.x[index1]); ++ + pt.x = x + t2kScalarAverage(p0, p1); + + p0 = F26Dot6ToScalar(glyph.y[index0]); + p1 = F26Dot6ToScalar(glyph.y[index1]); + pt.y = y - t2kScalarAverage(p0, p1); ++ */ + } + }; + +-void addGlyphToGeneralPath(const GlyphClass& glyph, GeneralPath& path, ++void addGlyphToGeneralPath(void* glyph, GeneralPath& path, + jfloat x, jfloat y, bool quadratic) { ++ /* + bool debug = false; + + Walker walker(glyph, x, y, quadratic); // quadratics are always 'closed' +@@ -282,7 +294,7 @@ + /* "firstTime" is necessary because we can't just moveto the first + * point as its not necessarily on the curve. This is known to be + * true of Solaris JA fonts, and probably many others +- */ ++ * + bool firstTime = true; + do { + if (quadratic) { +@@ -328,7 +340,7 @@ + } else { // cubic + /* REMIND: this looks like an infinite loop if there's + * never a point on the curve. +- */ ++ * + while (!walker.currentOnCurve()) { + walker.next(); + } +@@ -356,4 +368,5 @@ + path.closePath(); + // fflush(stderr); + } ++ */ + } +diff -urN openjdk.orig/j2se/src/share/native/sun/font/GeneralPath.h openjdk/j2se/src/share/native/sun/font/GeneralPath.h +--- openjdk.orig/j2se/src/share/native/sun/font/GeneralPath.h 2007-06-21 03:47:50.000000000 -0400 ++++ openjdk/j2se/src/share/native/sun/font/GeneralPath.h 2007-06-26 13:38:34.000000000 -0400 +@@ -100,7 +100,7 @@ + jobject getShape(JNIEnv* env); + }; + +-void addGlyphToGeneralPath(const GlyphClass& glyph, GeneralPath& path, ++void addGlyphToGeneralPath(void* glyph, GeneralPath& path, + jfloat x, jfloat y, bool quadratic); + + // __GeneralPath_header +diff -urN openjdk.orig/j2se/src/share/native/sun/font/scalerMethods.c openjdk/j2se/src/share/native/sun/font/scalerMethods.c +--- openjdk.orig/j2se/src/share/native/sun/font/scalerMethods.c 2007-06-21 03:47:50.000000000 -0400 ++++ openjdk/j2se/src/share/native/sun/font/scalerMethods.c 2007-06-26 15:29:03.000000000 -0400 +@@ -22,7 +22,7 @@ + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +-#include "t2k.h" ++//#include "t2k.h" + #include "sunfontids.h" + #include "sunt2kscaler.h" + #include "gdefs.h" +@@ -30,140 +30,29 @@ + #include "sun_font_FileFontStrike.h" + #include "sun_font_TrueTypeFont.h" + #include "sun_font_Type1Font.h" ++#include "fontscalerdefs.h" + +-// !!! temp +-#include "math.h" +- +-/* This copy of sunFontIDs doesn't really belong here, +- * and should move once this code is properly refactored +- */ +-FontManagerNativeIDs sunFontIDs; +-JNIEXPORT void setSunFontIDs(FontManagerNativeIDs ids) { +- sunFontIDs = ids; +-} +- +-Int32 t2kMagnitude(Int32 x, Int32 y) { +- int bits = 32; +- UInt32 root = 0; +- UInt32 currH = 0; +- UInt32 currL = 0; +- UInt32 guessH, guessL; +- +- Int32 hi, hi1, hi2; +- UInt32 lo, lo1, lo2; +- +- // !!! fails when x or y is negative, so force >= 0 +- if (x < 0) x = -x; +- if (y < 0) y = -y; +- +- WIDE_MUL(hi1, lo1, x, x); +- WIDE_MUL(hi2, lo2, y, y); +- +- lo = lo1+lo2; +- hi = hi1+hi2; +- if (lo < (lo1|lo2)) { +- hi++; +- } +- +- do { +- WIDE_SHIFTLEFT(currH, currL, currH, currL, 2); +- currL |= (UInt32)hi >> 30; +- WIDE_SHIFTLEFT(hi, lo, hi, lo, 2); +- +- WIDE_SHIFTLEFT(guessH, guessL, 0, root, 2); +- root <<= 1; +- if (WIDE_LESSTHAN(guessH, guessL, currH, currL)) { +- WIDE_ADDPOS(guessH, guessL, 1); +- WIDE_SUBWIDE(currH, currL, guessH, guessL); +- root |= 1; +- } +- } while (--bits); +- +- return (Int32)root; +-} +- +-hsFract t2kFracMul(hsFract src1, hsFract src2) { +- UInt32 lo; +- Int32 hi; +- +- WIDE_MUL(hi, lo, src1, src2); +- WIDE_ADDPOS(hi, lo, 1L << 29); +- lo = (lo >> 30) | (hi << 2); +- hi = hi >> 30; +- +- return lo; +-} +- +-Int32 t2kFracDiv(hsFract numerator, hsFract denom) { +- Int32 hi = 0; +- UInt32 lo = numerator; +- int shiftBits = 30; +- +- /* Set the wide numerator */ +- if (numerator < 0) { +- hi = -1L; +- } +- +- /* Multiply by 2^30 */ +- hi = (hi << shiftBits) | (lo >> (32 - shiftBits)); +- lo = lo << shiftBits; +- +- /* Divide by the denominator */ +- if (denom == 0) { +- if (hi < 0) { +- hi = kNegInfinity32; +- lo = 0; +- } else { +- hi = kPosInfinity32; +- lo = 0; +- } +- } else { +- UInt32 curr; +- int i, neg = 0; +- Int32 resH = 0; +- UInt32 resL = 0; +- Int32 numerH = hi; +- UInt32 numerL = lo; +- +- if (denom < 0) { +- denom = -denom; +- neg = ~0; +- } +- if ((Int32)numerH < 0) { +- WIDE_NEGATE(numerH, numerL); +- neg = ~neg; +- } +- +- /* add denom/2 to get a round result */ +- WIDE_ADDPOS(numerH, numerL, denom >> 1); +- +- curr = (UInt32)numerH >> 31; +- +- for (i = 0; i < 64; i++) { +- WIDE_SHIFTLEFT(resH, resL, resH, resL, 1); +- if ((UInt32)denom <= curr) { +- resL |= 1; +- curr -= denom; +- } +- WIDE_SHIFTLEFT(numerH, numerL, numerH, numerL, 1); +- curr = (curr << 1) | ((UInt32)numerH >> 31); +- } +- +- if (neg) { +- WIDE_NEGATE(resH, resL); +- } +- +- hi = resH; +- lo = resL; +- } ++JNIEXPORT jlong JNICALL ++ Java_sun_font_Type1Font_createScaler ++ (JNIEnv *env, jobject font2D, jint fileSize) { + +- return (Int32)lo; ++ T2KScalerInfo *scalerInfo = ++ (T2KScalerInfo*)calloc(1, sizeof(T2KScalerInfo)); ++ scalerInfo->env = env; ++ scalerInfo->font2D = font2D; ++ scalerInfo->pathType = CUBICPATHTYPE; /* for Type1 */ ++ scalerInfo->supportsCJK = JNI_FALSE; /* used only by TrueType */ ++ scalerInfo->fontData = malloc(fileSize); ++ scalerInfo->fontDataLength = 0; ++ scalerInfo->fontDataOffset = 0; ++ scalerInfo->fileSize = fileSize; ++ scalerInfo->directBuffer = NULL; ++ scalerInfo->layoutTables = NULL; ++ scalerInfo->bwGlyphCnt = 0; ++ scalerInfo->bwGlyphs = NULL; ++ return (jlong)(uintptr_t)scalerInfo; + } + +- +-/* LCD text options */ +-static int lcdscale = 6; // required to be a multiple of 3 +- + /* A singleton null (empty) scaler object. + * Null fields (ie a NULL t2k) can be used to identify the null scaler. + * C/C++ Methods which take a pScaler need to check its not the null +@@ -173,8 +62,8 @@ + + static T2KScalerInfo* getNullScaler() { + if (theNullScaler == NULL) { +- theNullScaler = (T2KScalerInfo*)malloc(sizeof(T2KScalerInfo)); +- memset(theNullScaler, 0, sizeof(T2KScalerInfo)); ++ theNullScaler = (T2KScalerInfo*)malloc(sizeof(T2KScalerInfo)); ++ memset(theNullScaler, 0, sizeof(T2KScalerInfo)); + } + return theNullScaler; + } +@@ -185,7 +74,6 @@ + int isNullScaler(T2KScalerInfo *scaler) { + return + scaler == NULL || +- scaler->memHandler == NULL || + scaler == getNullScaler(); + } + +@@ -196,97 +84,12 @@ + return (jlong)(uintptr_t)getNullScaler(); + } + +-JNIEXPORT jlong JNICALL +- Java_sun_font_Type1Font_createScaler +- (JNIEnv *env, jobject font2D, jint fileSize) { +- +- int errCode = 0; +- tsiMemObject* memHandler; +- InputStream *stream; +- sfntClass *fontClass; +- T2KScalerInfo *scalerInfo = +- (T2KScalerInfo*)calloc(1, sizeof(T2KScalerInfo)); +- tt_uint32 destLength = (tt_uint32)fileSize; +- unsigned char *destBuffer; +- jobject bBuffer; +- +- if (scalerInfo == NULL) { +- return 0L; +- } +- scalerInfo->env = env; +- scalerInfo->font2D = font2D; +- scalerInfo->pathType = CUBICPATHTYPE; /* for Type1 */ +- scalerInfo->supportsCJK = JNI_FALSE; /* used only by TrueType */ +- scalerInfo->fontData = malloc(fileSize); +- scalerInfo->fontDataLength = 0; +- scalerInfo->fontDataOffset = 0; +- scalerInfo->fileSize = fileSize; +- scalerInfo->directBuffer = NULL; +- scalerInfo->layoutTables = NULL; +- scalerInfo->bwGlyphCnt = 0; +- scalerInfo->bwGlyphs = NULL; +- +- memHandler = tsi_NewMemhandler(&errCode); +- +- /* T2K claims to destroys all its internal objects on hitting an error +- * so we don't (must not) free T2K objects on hitting an error code. +- */ +- if (errCode) { +- t2kIfDebugMessage(errCode, "tsi_NewMemhandler failed", errCode); +- free(scalerInfo); +- return 0L; +- } +- scalerInfo->memHandler = memHandler; +- +- destBuffer = (unsigned char*)scalerInfo->fontData; +- +- bBuffer = (*env)->NewDirectByteBuffer(env, destBuffer, fileSize); +- (*env)->CallObjectMethod(env, font2D, sunFontIDs.t1ReadBlockMID, +- bBuffer/*, 0, fileSize*/); +- +- if (*destBuffer == 0x80) { /* PFB file, remove the headers */ +- destBuffer = ExtractPureT1FromPCType1(destBuffer, &destLength); +- if (destBuffer == NULL) { +- /* Free handler explicitly in this case because we detected +- * the error (not T2K) so T2K needs to be instructed to free +- * its resources. +- */ +- tsi_DeleteMemhandler(memHandler); +- if (scalerInfo->fontData != NULL) { +- free(scalerInfo->fontData); +- } +- free(scalerInfo); +- return 0L; +- } +- } +- +- stream = New_InputStream3(memHandler, destBuffer, destLength, &errCode); +- +- if (errCode) { +- t2kIfDebugMessage(errCode, "New_NonRamInputStream failed", errCode); +- free(scalerInfo); +- return 0L; +- } +- +- fontClass = New_sfntClassLogical(memHandler, FONT_TYPE_1, +- 0, stream, NULL, &errCode); +- +- if (errCode) { +- t2kIfDebugMessage(errCode, "New_sfntClass failed", errCode); +- free(scalerInfo); +- return 0L; +- } +- +- scalerInfo->t2k = NewT2K(memHandler, fontClass, &errCode); +- return (jlong)(uintptr_t)scalerInfo; +-} +- + T2KScalerContext *theNullScalerContext = NULL; + /* This method should be called with theNullScaler */ + JNIEXPORT jlong JNICALL + Java_sun_font_FileFontStrike_getNullScalerContext + (JNIEnv *env, jclass strikeClass, jlong pScaler) { +- ++ + if (theNullScalerContext == NULL) { + theNullScalerContext = + (T2KScalerContext*)malloc(sizeof(T2KScalerContext)); +@@ -308,289 +111,39 @@ + jboolean ttFont, jint aa, jint fm, + jboolean algoStyle, jfloat boldness, jfloat italic) { + +- double dmat[4]; + T2KScalerContext *context = + (T2KScalerContext*)malloc(sizeof(T2KScalerContext)); +- context->scalerInfo = (T2KScalerInfo*)pScaler; +- +- if (context->scalerInfo == NULL || +- context->scalerInfo->t2k == NULL) { /* bad/null scaler */ +- free((void*)context); +- return (jlong)0; +- } +- + context->doAlgoStyle = algoStyle; +- if (algoStyle) { ++/* if (algoStyle) { + context->styling.StyleMetricsFunc = tsi_SHAPET_BOLD_METRICS; + context->styling.StyleFuncPost = tsi_SHAPET_BoldItalic_GLYPH_Hinted; + context->styling.params[0] = t2kFloatToFixed(boldness); + context->styling.params[1] = t2kFloatToFixed(italic); + context->styling.params[2] = 0; + context->styling.params[3] = 0; +- } ++ }*/ + +- (*env)->GetDoubleArrayRegion(env, matrix, 0, 4, dmat); ++/* (*env)->GetDoubleArrayRegion(env, matrix, 0, 4, dmat); + context->t2kMatrix.t00 = t2kFloatToFixed((float)dmat[0]); + context->t2kMatrix.t10 = -t2kFloatToFixed((float)dmat[1]); + context->t2kMatrix.t01 = -t2kFloatToFixed((float)dmat[2]); +- context->t2kMatrix.t11 = t2kFloatToFixed((float)dmat[3]); ++ context->t2kMatrix.t11 = t2kFloatToFixed((float)dmat[3]);*/ + + context->doAA = aa != TEXT_AA_OFF; + context->doFM = fm != TEXT_FM_OFF; + context->aaType = aa; + context->fmType = fm; + +- /* Below, if FM is "ON" then we disable (do not request) sbits. +- * sbits retrieves embedded bitmaps from a TrueType font. These are +- * rare except for CJK fonts in which case they help quality a great deal. +- * This means that in order to get the linearly scaled metrics from +- * we want from the htx table, we also end up adversely affecting the +- * image quality when really it should not change at all. +- * This is very noticeable for CJK glyphs. +- * This needs to be fixed to be able to get linear metrics along with +- * embedded bitmaps. +- */ +- context->sbits = !(algoStyle && italic != 0) && +- !context->doFM && (context->aaType != TEXT_AA_ON); +- +- context->greyLevel = BLACK_AND_WHITE_BITMAP; +- if (context->aaType == TEXT_AA_ON) { +- context->greyLevel = GREY_SCALE_BITMAP_HIGH_QUALITY; +- } +- +- context->t2kFlags = T2K_GRID_FIT | T2K_CODE_IS_GINDEX; +- +- if (context->aaType >= TEXT_AA_LCD_HRGB) { +- /* Prefer LCD glyphs to embedded bitmaps except for CJK fonts */ +- if (context->sbits) { +- context->sbits = context->scalerInfo->supportsCJK; +- } +- /* This only affects bitmaps from T2K. Outlines are not scaled */ +- if (context->aaType == TEXT_AA_LCD_HRGB) { +- context->t2kFlags |= T2K_LCD_MODE; +- } else { +- context->t2kFlags |= T2K_LCD_MODE_V; +- } +- context->t2kFlags |= (lcdscale << 24); // oversample scale. +- } +- +- if (ttFont) { + context->pathType = QUADPATHTYPE; +- } else { +- context->pathType = CUBICPATHTYPE; +- } +- + return (jlong)(uintptr_t)context; + } + +-/* +- * We need to make an up-call to Java to read the file contents, as +- * the file is managed via the font and read via NIO APIs. +- * However since T2K supplies a buffer to fill, for larger reads +- * we can wrap it with a direct buffer and then make the up-call. +- * This avoids any copying of the data. +- * As soon as the call returns we can and do drop the reference. +- * I have verified with the NIO spec lead that the pointer to the data +- * buffer will be left well alone, and that the buffer will be rapidly +- * freed since direct buffers allocated through JNI have no finalization. +- * +- * T2K tends to read the first few hundred bytes of a file in a zillion +- * little upcalls. +- * Also I have seen cases where thousands of calls are made each reading +- * the next 2 bytes. So for smaller reads (<=1024 bytes) we fill a cache +- * and attempt to read from that. Re-using a DirectByteBuffer for this +- * purpose means that many cache hits reduce calling this function to +- * a memcpy whereas it was a system call in previous releases. +- * Also note that in t2kstrm.h I have increased the amount +- * of data to pre-cache to reduce the number of upcalls made. +- */ + #define FILEDATACACHESIZE 1024 + +-static void ReadTTFontFileFunc(void *id, tt_uint8 *destBuffer, +- tt_int32 offset, tt_int32 numBytes) { +- +- T2KScalerInfo *scalerInfo = (T2KScalerInfo *) id; +- JNIEnv* env = scalerInfo->env; +- jobject bBuffer; +- int bread = 0; +- +- /* If the read is to a negative offset, something is badly wrong, +- * and if the offset is past the end of file, we can't return valid +- * data, so the read will fail. Perhaps we should assert immediately, +- * but we need to let such cases proceed to call up into Java so +- * that it can invalidate the font. +- */ +- +- if (numBytes <= 0) { +- return; /* some bad fonts have zero-length tables */ +- } +- /* Large reads will bypass the cache and data copying */ +- if (numBytes > FILEDATACACHESIZE) { +- bBuffer = (*env)->NewDirectByteBuffer(env, destBuffer, numBytes); +- if (bBuffer != NULL) { +- /* Loop until the read succeeds (or EOF). +- * Just returning without reading the data will cause a crash. +- * If no font data can be read, tsi_Assert jumps out of T2K. +- */ +- while (bread == 0) { +- bread = (*env)->CallIntMethod(env, scalerInfo->font2D, +- sunFontIDs.ttReadBlockMID, +- bBuffer, offset, numBytes); +- } +- /* If no font data can be read, we need to jump out of T2K */ +- tsi_Assert(scalerInfo->memHandler, (bread > 0), T2K_ERR_BAD_READ); +- return; +- } else { +- /* We probably hit bug bug 4845371. For reasons that +- * are currently unclear, the call stacks after the initial +- * createScaler call that read large amounts of data seem to +- * be OK and can create the byte buffer above, but this code +- * is here just in case. +- * 4845371 is fixed now so I don't expect this code path to +- * ever get called but its harmless to leave it here on the +- * small chance its needed. +- * One scenario in which it is entered is OutOfMemoryError in +- * which case this last gasp try is also likely to fail. +- */ +- jbyteArray byteArray = (jbyteArray) +- (*env)->CallObjectMethod(env, scalerInfo->font2D, +- sunFontIDs.ttReadBytesMID, +- offset, numBytes); +- /* If there's an OutofMemoryError then byteArray will be null */ +- if (byteArray != NULL) { +- (*env)->GetByteArrayRegion(env, byteArray, +- 0, numBytes, (jbyte*)destBuffer); +- } +- return; +- } +- } /* Do we have a cache hit? */ +- else if (scalerInfo->fontDataOffset <= offset && +- scalerInfo->fontDataOffset+scalerInfo->fontDataLength >= +- offset+numBytes) { +- int cacheOffset = offset - scalerInfo->fontDataOffset; +- +- memcpy(destBuffer, scalerInfo->fontData+(size_t)cacheOffset, numBytes); +- } else { +- /* Must fill the cache */ +- scalerInfo->fontDataOffset = offset; +- scalerInfo->fontDataLength = +- (offset + FILEDATACACHESIZE > scalerInfo->fileSize) ? +- scalerInfo->fileSize - offset : FILEDATACACHESIZE; +- bBuffer = scalerInfo->directBuffer; +- /* Loop until all the read succeeds (or EOF). +- * This should improve robustness in the event of a problem in +- * the I/O system. If we find that we ever end up spinning here +- * we are going to have to do some serious work to recover. +- * Just returning without reading the data will cause a crash. +- */ +- while (bread == 0) { +- bread = (*env)->CallIntMethod(env, scalerInfo->font2D, +- sunFontIDs.ttReadBlockMID, +- bBuffer, offset, +- scalerInfo->fontDataLength); +- } +- tsi_Assert(scalerInfo->memHandler, (bread > 0), T2K_ERR_BAD_READ); +- memcpy(destBuffer, scalerInfo->fontData, numBytes); +- } +-} +- +- +-static void freeScalerInfo(JNIEnv *env, T2KScalerInfo *scalerInfo) { +- if (scalerInfo->fontData != NULL) { +- free(scalerInfo->fontData); +- } +- if (scalerInfo->directBuffer != NULL) { +- (*env)->DeleteGlobalRef(env, scalerInfo->directBuffer); +- scalerInfo->directBuffer = NULL; +- } +- freeLayoutTableCache(scalerInfo->layoutTables); +- if (scalerInfo->bwGlyphs != NULL) { +- free(scalerInfo->bwGlyphs); +- } +- /* clear memory for 'fast-fail' in event we still try to use it. +- * Also 'freeScaler' needs t2k NULLed out so it doesn' try to re-free +- * Need to leave freeing the memory for the struct to that code. +- */ +- memset(scalerInfo, 0, sizeof(T2KScalerInfo)); +-} +- +-/* This is called when T2K has returned an error code and +- * T2K functions cannot be called. The T2K struct it references and +- * its memHandler will already have been freed. However we still need to +- * free scalerInfo and ensure the reference points to the null scaler. +- * So it has a subset of the operations in the JNI freeScaler(); +- */ +-void freeScalerInfoAfterError(JNIEnv *env, T2KScalerContext *context) { +- T2KScalerInfo *scalerInfo = context->scalerInfo; +- if (isNullScaler(scalerInfo)) { +- return; +- } +- freeScalerInfo(env, scalerInfo); +- context->scalerInfo = getNullScaler(); +-} +- + JNIEXPORT void JNICALL + Java_sun_font_FileFont_freeScaler + (JNIEnv *env, jclass fileFontClass, jlong pScaler) { +- +- int errCode = 0; +- tsiMemObject *mem; +- sfntClass *fontClass; +- InputStream *stream; +- T2KScalerInfo *scalerInfo = (T2KScalerInfo*)pScaler; +- +- if (isNullScaler(scalerInfo)) { +- return; // nothing to do. +- } +- if (scalerInfo->memHandler == NULL || scalerInfo->t2k == NULL) { +- free(scalerInfo); //just free the memory. +- return; +- } +- +- mem = scalerInfo->memHandler; +- fontClass = scalerInfo->t2k->font; +- stream = fontClass->in; +- scalerInfo->env = env; +- scalerInfo->font2D = NULL; /* can't be needed as the font is gc'd */ +- DeleteT2K(scalerInfo->t2k, &errCode); +- t2kIfDebugMessage(errCode, "DeleteT2K failed", errCode); +- Delete_sfntClass(fontClass, &errCode); +- t2kIfDebugMessage(errCode, "Delete_sfntClass failed", errCode); +- Delete_InputStream(stream, &errCode); +- t2kIfDebugMessage(errCode, "Delete_InputStream failed", errCode); +- tsi_DeleteMemhandler(mem); +- freeScalerInfo(env, scalerInfo); +- free(scalerInfo); +-} +- +-TTLayoutTableCache* newLayoutTableCache() { +- TTLayoutTableCache* ltc = malloc(sizeof(TTLayoutTableCache)); +- if (ltc) { +- ltc->gsub = 0; +- ltc->gpos = 0; +- ltc->gdef = 0; +- ltc->mort = 0; +- ltc->kern = 0; +- ltc->kernPairs = 0; +- ltc->gsub_len = -1; +- ltc->gpos_len = -1; +- ltc->gdef_len = -1; +- ltc->mort_len = -1; +- ltc->kern_len = -1; +- } +- return ltc; +-} +- +-void freeLayoutTableCache(TTLayoutTableCache* ltc) { +- if (ltc) { +- if (ltc->gsub) free(ltc->gsub); +- if (ltc->gpos) free(ltc->gpos); +- if (ltc->gdef) free(ltc->gdef); +- if (ltc->mort) free(ltc->mort); +- if (ltc->kern) free(ltc->kern); +- if (ltc->kernPairs) free(ltc->kernPairs); +- free(ltc); +- } ++ ; + } + + JNIEXPORT jlong JNICALL +@@ -598,17 +151,8 @@ + (JNIEnv *env, jobject font2D, jint fileSize, jint fontNumber, + jboolean supportsCJK, jintArray bwGlyphArray) { + +- int errCode = 0; +- tsiMemObject* memHandler; +- InputStream *stream; +- sfntClass *fontClass; +- + T2KScalerInfo *scalerInfo = + (T2KScalerInfo*)calloc(1, sizeof(T2KScalerInfo)); +- +- if (scalerInfo == NULL) { +- return 0L; +- } + scalerInfo->env = env; + scalerInfo->font2D = font2D; + scalerInfo->pathType = QUADPATHTYPE; /* for TrueType */ +@@ -642,562 +186,12 @@ + } + } + +- memHandler = tsi_NewMemhandler(&errCode); +- +- /* T2K claims to destroys all its internal objects on hitting an error +- * so we don't (must not) free T2K objects on hitting an error code. +- */ +- if (errCode) { +- t2kIfDebugMessage(errCode, "tsi_NewMemhandler failed", errCode); +- // nothing to dispose in layout tables +- (*env)->DeleteGlobalRef(env, scalerInfo->directBuffer); +- free(scalerInfo->fontData); +- free(scalerInfo); +- return 0L; +- } +- scalerInfo->memHandler = memHandler; +- +- stream = New_NonRamInputStream(memHandler, (void *)scalerInfo, +- ReadTTFontFileFunc, fileSize, +- &errCode); +- +- if (errCode) { +- t2kIfDebugMessage(errCode, "New_NonRamInputStream failed", errCode); +- (*env)->DeleteGlobalRef(env, scalerInfo->directBuffer); +- free(scalerInfo->fontData); +- free(scalerInfo); +- return 0L; +- } +- +- /* T2K supports algorithmic styling of TrueType fonts. +- * Unfortunately T2K doesn't come with a public call to set up styling +- * except at scaler instance creation time. +- * Since we want to share a single T2K scaler per font resource (which +- * usually means a file) we have exposed an internal T2K API to set that +- * up as part of the context along with the transform. So what is passed +- * in here is always NULL (the final arg before errCode). +- */ +- fontClass = New_sfntClassLogical(memHandler, FONT_TYPE_TT_OR_T2K, +- fontNumber, stream, +- NULL, &errCode); +- +- if (errCode) { +- t2kIfDebugMessage(errCode, "New_sfntClass failed", errCode); +- (*env)->DeleteGlobalRef(env, scalerInfo->directBuffer); +- free(scalerInfo->fontData); +- free(scalerInfo); +- return 0L; +- } +- +- scalerInfo->t2k = NewT2K(memHandler, fontClass, &errCode); +- +- if (errCode) { +- t2kIfDebugMessage(errCode, "NewT2K failed", errCode); +- (*env)->DeleteGlobalRef(env, scalerInfo->directBuffer); +- free(scalerInfo->fontData); +- free(scalerInfo); +- return 0L; +- } + return (jlong)(uintptr_t)scalerInfo; + } + +-#define T2KByteToAlpha255(value) (((value) << 4) + (value) >> 3) +- +-static void CopyBW2Grey8(const void* srcImage, int srcRowBytes, +- void* dstImage, int dstRowBytes, +- int width, int height) +-{ +- const UInt8* srcRow = (UInt8*)srcImage; +- UInt8* dstRow = (UInt8*)dstImage; +- int wholeByteCount = width >> 3; +- int remainingBitsCount = width & 7; +- int i, j; +- +- while (height--) { +- const UInt8* src8 = srcRow; +- UInt8* dstByte = dstRow; +- unsigned srcValue; +- +- srcRow += srcRowBytes; +- dstRow += dstRowBytes; +- +- for (i = 0; i < wholeByteCount; i++) { +- srcValue = *src8++; +- for (j = 0; j < 8; j++) { +- *dstByte++ = (srcValue & 0x80) ? 0xFF : 0; +- srcValue <<= 1; +- } +- } +- if (remainingBitsCount) { +- srcValue = *src8; +- for (j = 0; j < remainingBitsCount; j++) { +- *dstByte++ = (srcValue & 0x80) ? 0xFF : 0; +- srcValue <<= 1; +- } +- } +- } +-} +- +-/* +- * - input image is T2K's 1 bit per sample format with +- * "scale" samples per destination pixel +- * +- * - output image is 3 byte samples per destination pixel +- * thus, 1 byte sample per RGB component in the destination +- * +- * - default scale of 6 means that 2 bits in the input must be +- * combined into a single output byte. +- * This provides for a better approximation to coverage +- * intensity so combining the benefits of over-sampling with +- * the benefits of coverage on transition edges, which can help +- * reduce the transitions which contribute to colour fringing (see +- * filtering in the next paragraph) +- * +- * - furthermore, the code that uses these LCD glyphs +- * will apply a filter that is 3 samples wide so that +- * energy from any given sample can spread to adjacent +- * samples, thus we need at least one byte on both sides +- * of the image to absorb this extra energy. (The +- * code actually pads by more than that for other +- * reasons - see the sub-pixel positioning note below). +- * +- * - T2K produced a glyph image assuming that each bit was a +- * discrete output pixel, but our real addressability +- * can be either one destination component (with lcd +- * subpixel positioning turned on) or one destination +- * pixel (with lcd subpixel pos turned off). For simplicity +- * we will modify the glyph origin and the output image +- * so that the image is ready to be applied to a whole +- * pixel boundary. If lcd sub-pixel positioning is +- * turned on, then further adjustments may be necessary +- * at the rendering stage. The sub-pixel positioning implementation +- * requires that we further pad by an additional two bytes each +- * side of the image. +- * +- * - To adjust the image position we first round the left edge of +- * the T2K glyph image to the nearest destination pixel +- * and then produce a bitmap relative to that destination +- * pixel location. This may involve a virtual shift of +- * the samples left or right depending on whether the +- * nearest destination pixel location was to the left or +- * right of the actual left edge of the T2K bit samples. +- * +- * - Note this function relies on its caller to call it only if width>0. +- * +- * - Earlier we had defined PADRIGHT to be 2 as that was sufficient +- * for the software loops, but this resulted in non-integral +- * row lengths, which is something that the OpenGL pipeline +- * cannot handle. Therefore, we now require that PADLEFT and PADRIGHT +- * each be a multiple of 3. It is unfortunate that this will "waste" +- * one byte per row in the glyph image (compared to before), but that +- * seems to be the price we pay to get hardware acceleration of +- * LCD-optimized text. +- */ +-#define PADLEFT 3 +-#define PADRIGHT 3 +-static void CopyBW2LCDH(T2K *t2k, int xscale, void **dstImage, +- int *dstBytesWidth, float *rndTopLeftX) +-{ +- const UInt8* srcRow = t2k->baseAddr; +- int srcRowBytes = t2k->rowBytes; +- int width = t2k->width; +- int height = t2k->height; +- int wholeByteCount = width >> 3; +- int remainingBitsCount = width & 7; +- UInt8* dstRow; +- float topLeftX; +- int dstRowBytes, bitsWidth, rndbits, padleft; +- int shiftMajor=0, shiftMinor=0, subpixelShift; +- int average = xscale/3; /* scale will and must be a multiple of 3. */ +- int round_average = average/2; /* used for rounding */ +- +- /* Round the top left x to the nearest whole pixel position and +- * calculate the subpixelShift. +- * subpixelShift is the difference in glyph image position between +- * the rounded (whole pixel) position and the scaled (sub pixel) position. +- * For example, suppose scale is 6 and the scaled topLeftX is 26.0. +- * Trying to be compatible with the unscaled glyph position this is +- * rounded up to 29 before scaling down : floor((26.0 + (6/2))/6) = 4; +- * So "4" is our computed whole pixel left edge position, which +- * corresponds to "24" in the scaled T2K coordinate system. +- * Since T2K had returned that value as "26" we want to adjust the +- * sub-pixel image by (26-24)==2 to compensate for this rounding +- * a +ve value for (topLeftX-rndTopLeftX) means we have rounded down +- * so will need to shift the image to the right. +- * The range of the shift for a scale of 6 is -3 <= shift <= +2 +- * or more generally from -scale/2 -> scale/2-1 which amounts to half a +- * pixel at most, so padding of one full RGB pixel is always sufficient. +- * +- * shiftMajor is the number of RGB subpixels to shift +- * shiftMinor is the position within an RGB subpixel to shift - ie in +- * the range 0 .. average-1 +- * Perhaps it would have been possible to make T2K return the image +- * already shifted and with an already adjusted topLeftX but right now +- * this seems easier. +- */ +- topLeftX = t2kFixedToFloat(F26Dot6ToFixed(t2k->fLeft26Dot6)); +- *rndTopLeftX = (int)floor((topLeftX + (xscale/2.0)) / (float)xscale); +- subpixelShift = (topLeftX-*rndTopLeftX*xscale); +- shiftMajor = (int)floor(subpixelShift/(float)average); +- if ((subpixelShift % average) != 0) { +- shiftMinor = subpixelShift-(shiftMajor*average); +- } +- +- /* bitsWidth is the width we need, including padding on the right +- * average is the number of scaled bits corresponding to one subpixel +- * component, so is the needed amount of padding on the right for +- * the filter. +- * bitsWidth then needs to be rounded up to a whole number of pixels +- * Then we can calculate how many whole bytes are needed per row. +- */ +- bitsWidth = width + subpixelShift + average; +- rndbits = bitsWidth % xscale; +- if (rndbits != 0) { +- bitsWidth+= xscale - rndbits; +- } +- +- /* The width is adjusted with 3 or 6 bytes padding on the left (padleft, +- * which is either PADLEFT or PADLEFT*2) and 3 bytes padding on the +- * right (PADRIGHT). padleft is 3 when shiftMajor >=0 and 6 when it is <=0 +- * We copy the down-sampled source into the destination row at a byte +- * offset determined by this padding and shiftMajor. +- * If shiftMajor is >=0 (which empirically is the usual case) then +- * the offset skips past the "padleft bytes and past the "shiftMajor" +- * bytes. +- * If shiftMajor is < 0 we copy into the padding bytes, so will need +- * 3 additional padding bytes for subpixel positioning, in which case +- * padleft is 6. In this scenario we have 6 bytes per row which is +- * used only with fractional metrics/subpixel positioning. This is +- * somewhat wasteful but seems rare. +- * In both cases we draw the image to the left of its previously +- * calculated position so that the original glyph image ends up at +- * the same position it would have done. Its drawn 1 pixel to the left +- * if padleft==3 and 2 pixels to the left if padleft==6 +- * +- * To recap, the padding is needed for two reasons : +- * filtering needs a byte to the left and right to diffuse coverage. +- * This padding byte needs to be contained in a whole pixel (ie 3 bytes). +- * The left pading is added here, but the right padding is added above +- * in the calculation for bitsWidth +- * Subpixel positioning needs 2 bytes at the left of the image so it +- * can safely index past at rendering time and a matching 2 bytes +- * at the right of the image of the image. +- * The rendering loops need to make only a minor adjustment to use +- * these bytes for subpixel positioning by offsetting into the image row. +- */ +- if (shiftMajor >= 0) { +- padleft = PADLEFT; +- *rndTopLeftX-=1.0; +- } else { +- padleft = PADLEFT*2; +- *rndTopLeftX-=2.0; +- } +- *dstBytesWidth = dstRowBytes = padleft + (bitsWidth/average) + PADRIGHT; +- *dstImage = malloc(dstRowBytes*height); +- memset(*dstImage, 0, dstRowBytes*height); +- dstRow = (UInt8*)*dstImage; +- +- while (height--) { +- int i,j; +- jint srcValue; /* 32 bits signed */ +- int count = shiftMinor; +- /* Initialise "sum" to average/2 so that the calculation +- * "sum/average" rounds to the nearest. In practice this will mean +- * round up if sum is odd. Note that this will never cause us to +- * end up with 256 (==0 in a byte) since the maximum inputs will +- * be 255 + 255 + (2/1) = 511, and 511/2 = 255. +- */ +- int sum = round_average; +- +- const UInt8* src8 = srcRow; +- UInt8 *dstByte = dstRow + padleft + shiftMajor; +- +- srcRow += srcRowBytes; +- dstRow += dstRowBytes; +- +- for (i = 0; i < wholeByteCount; i++) { +- srcValue = (*src8++) << 24; +- for (j = 0; j < 8; j++) { +- sum += (srcValue >> 31) & 0xff; +- count++; +- if (count == average) { +- *dstByte++ = (sum/average); +- sum = round_average; +- count = 0; +- } +- srcValue <<= 1; +- } +- } +- if (remainingBitsCount) { +- srcValue = (*src8) << 24; +- for (j = 0; j < remainingBitsCount; j++) { +- sum += (srcValue >> 31) & 0xFF; +- count++; +- if (count == average) { +- *dstByte++ = (sum/average); +- sum = round_average; +- count = 0; +- } +- srcValue <<= 1; +- } +- } +- if (count > 0) { +- *dstByte = sum/average; +- } +- } +-} +- +-static void getTBFromBW2(T2K *t2k, int *topmost, int *bottommost) { +- const UInt8* srcRow = t2k->baseAddr; +- int height = t2k->height; +- int srcRowBytes = t2k->rowBytes; +- +- int tmsp=0x7fffffff, bmsp=0; +- int i, y; +- +- for (y=0;y<height;y++) { +- const UInt8* src8 = srcRow; +- +- srcRow += srcRowBytes; +- +- for (i = 0; i < srcRowBytes; i++) { +- if (*src8++) { +- if (y<tmsp) tmsp = y; +- if (y>bmsp) bmsp = y; +- break; +- } +- } +- } +- /* just in case we somehow have an image that's all zeroes, +- * set top == bottom == 0. +- */ +- if (tmsp > bmsp) tmsp = bmsp; +- *topmost = tmsp; +- *bottommost = bmsp; +- return; +-} +- +-/* +- * The source image is in T2K packed output format. +- * The output image is 3 bytes per pixel - ie 1 byte per subpixel +- * The subpixels here increase the VERTICAL resolution +- */ +-static void CopyBW2LCDV(T2K *t2k, int scale, void **dstImage, +- int *dstBytesWidth, int *dstHeight, float *rndTopLeftY) +-{ +- const UInt8* srcImage = t2k->baseAddr; +- int srcRowBytes = t2k->rowBytes; +- int width = t2k->width; +- int height = t2k->height; +- UInt8 *dstRow, *image; +- int dstRowBytes, paddedHeight; +- int shiftMajor=0, shiftMinor=0; +- int padtop=0, x, y; +- int miny, maxy, sminy, smaxy, subpixelShift; +- int average = scale/3; +- int round_average = average/2; /* used for rounding. SeeCopyBW2LCDH */ +- +- /* t2k->fTop26Dot6 is relative to the origin of the glyph +- * Since the glyph origin is at the baseline (for latin text) this +- * this means a greater value is in the "up the page" direction. +- * round top left y up to next integral (pixel) position, but adjust +- * the image downwards to compensate. This is just the image position +- * relative to the glyph position. It doesn't affect anything else. +- * subpixelShift is a measure of how much shift is introduced +- * by the above calculation at the scale of the image. +- * Break this down as follows : +- * shiftMajor is the number of RGB subpixels to shift +- * shiftMinor is the position within an RGB subpixel to shift. +- */ +- float topLeftY = t2kFixedToFloat(F26Dot6ToFixed(t2k->fTop26Dot6)); +- *rndTopLeftY = (float)ceil(topLeftY / (float)scale); +- subpixelShift = (int)(*rndTopLeftY*scale-topLeftY); +- shiftMajor = subpixelShift/average; +- shiftMinor = subpixelShift % average; +- +- /* +- * Find the top-most and bottom-most "on" source image pixels. +- * Add subpixelshift to these to reflect where we will place these in +- * the output image. +- * Rows are added to the bottom sufficient to accommodate this. +- * The image needs to be filtered to reduce colour fringing, therefore +- * it must be padded to absorb energy distributed by this filter to +- * adjacent subpixels. +- * The test sminy<average implicitly hard codes a requirement that the +- * filter be 3 RGB subpixels wide - ie energy is not distributed beyond +- * the adjacent subpixels. +- * So average tells us how many of the source image bits to consider +- * and hence the number of bits of padding needed. +- */ +- getTBFromBW2(t2k, &miny, &maxy); +- sminy = miny+subpixelShift; +- smaxy = maxy+subpixelShift; +- if (sminy<average) { +- padtop = 1; // will need to allocate an extra row at the top. +- *rndTopLeftY+=1.0; +- } +- +- /* The height required including padding on the bottom is paddedHeight +- * In the scaled space we see how much padding is needed on the bottom +- * and then we calculate the final height in rows by dividing by scale +- * and adding on any top padding. +- */ +- paddedHeight = smaxy+average+1; +- if (paddedHeight % scale != 0) { +- paddedHeight+= (scale-(paddedHeight % scale)); +- } +- paddedHeight = (paddedHeight / scale) + padtop; +- dstRowBytes = width*3; +- image = malloc(dstRowBytes*paddedHeight); +- /* Copy the above values to the return addresses */ +- *dstHeight = paddedHeight; +- *dstBytesWidth = dstRowBytes; +- *dstImage = image; +- +- memset(image, 0, dstRowBytes*paddedHeight); +- dstRow = image + padtop*dstRowBytes; +- +- /* Process a column at a time as we need to average within a column. +- * Although this could be optimised, its preferred to keep the code +- * more straightforward and maintainable. +- */ +- for (x=0; x < width ; x++) { +- /* set the x offset into the source and destination images. +- * The start row of the destination may skip past a top row +- * of padding used to absorb filter energy. +- * The source is 1 bit pp, the dest is 3 bytes pp +- * These will be updated to point to the right row. +- */ +- UInt8* srcBytePtr = (UInt8*)srcImage+(x>>3); +- UInt8* dstBytePtr = dstRow+(x*3); +- int bitmask = 0x80 >> (x & 7); +- int subpixelCount = shiftMajor; +- int count = shiftMinor; +- int sum = round_average; +- for (y=0; y <= maxy; y++) { +- sum += (*srcBytePtr & bitmask) ? 0xFF : 0; +- srcBytePtr += srcRowBytes; +- count++; +- if (count == average) { +- dstBytePtr[subpixelCount++] = (sum/average); +- sum = round_average; +- count = 0; +- if (subpixelCount == 3) { +- subpixelCount = 0; +- dstBytePtr += dstRowBytes; +- } +- } +- } +- if (count > 0) { +- dstBytePtr[subpixelCount] = sum/average; +- } +- } +-} +- +- +-/* +- * Simple filter centred on a sub-pixel. The filter will span pixel +- * boundaries. +- * Approx 1/3 of each of the 3 adjacent sub-pixels contributes to the +- * output subpixel. We approximate 1/3 as (21931*SUBPIX/65536) +- * We arrive at 21931 from ((1<<24) - 1) / (255*3) +- * This gives a good statistical distribion of the values into the 256 +- * possible value "buckets". +- */ +-#define DIV3(x) (((x) * 21931) >> 16) +-static void filterPixelsH(const UInt8* srcImage, const UInt8* dstImage, +- int width, int height) { +- int x, y; +- const UInt8 *srcRow=srcImage; +- UInt8 *dstRow=(UInt8*)dstImage; +- +- for (y=0;y<height;y++) { +- dstRow[0] = (UInt8)(DIV3(srcRow[0] + srcRow[1])); +- for (x = 1; x < width-1; x++) { +- dstRow[x] = (UInt8)(DIV3(srcRow[x-1] + srcRow[x] + srcRow[x+1])); +- } +- dstRow[width-1] = (UInt8)(DIV3(srcRow[width-2] + srcRow[width-1])); +- +- srcRow+=width; +- dstRow+=width; +- } +-} +-/* +- * Simple filter centred on a sub-pixel. The filter will span pixel +- * boundaries. The in-memory organisation is what complicates this filter +- * Vertically adjacent subpixels may be stored a scanrow apart. +- */ +-static void filterPixelsV(const UInt8* srcImage, const UInt8* dstImage, +- int width, int height) { +- int x, y; +- const UInt8 *src=srcImage; +- UInt8 *dst=(UInt8*)dstImage; +- +- for (x=0;x<width;x+=3) { +- dst[x] = (UInt8)(DIV3(src[x] + src[x+1])); +- dst[x+1] = (UInt8)(DIV3(src[x] + src[x+1] + src[x+2])); +- if (height == 1) { +- dst[x+2] = (UInt8)(DIV3(src[x+1] + src[x+2])); +- } else { +- dst[x+2] = (UInt8)(DIV3(src[x+1] + src[x+2] + src[x+width])); +- } +- } +- +- for (x=0;x<width;x+=3) { +- for (y=1;y<height-1;y++) { +- src = srcImage+(y*width); +- dst = (UInt8*)dstImage+(y*width); +- /* filter centred on Red (top subpixel) - row spanned */ +- dst[x] = (UInt8)(DIV3(src[x-width+2] + src[x] + src[x+1])); +- /* filter centred on Green (centre subpixel) - all in same row */ +- dst[x+1] = (UInt8)(DIV3(src[x]+src[x+1]+src[x+2])); +- /* filter centred on Blue (bottom subpixel) - row spanned */ +- dst[x+2] = (UInt8)(DIV3(src[x+1] + src[x+2] + src[x+width])); +- } +- } +- +- if (height > 1) { +- src = srcImage+((height-1)*width); +- dst = (UInt8*)dstImage+((height-1)*width); +- for (x=0;x<width;x+=3) { +- dst[x] = (UInt8)(DIV3(src[x-width+2] + src[x] + src[x+1])); +- dst[x+1] = (UInt8)(DIV3(src[x] + src[x+1] + src[x+2])); +- dst[x+2] = (UInt8)(DIV3(src[x+1] + src[x+2])); +- } +- } +-} +- +-int setupT2KContext(JNIEnv *env, jobject font2D, +- T2KScalerInfo *scalerInfo, T2KScalerContext *context, +- jboolean sbits) { +- int errCode = 0; +- T2K_TRANS_MATRIX t2kMatrix; +- T2K *t2k = scalerInfo->t2k; +- +- scalerInfo->env = env; +- scalerInfo->font2D = font2D; +- +- if (context->doAlgoStyle) { +- t2k_SetStyling(t2k->font, &context->styling); +- } else { +- t2k_SetStyling(t2k->font, NULL); +- } +- +- /* T2K_NewTransformation updates the matrix parameter(!) so pass in a copy +- */ +- t2kMatrix.t00 = context->t2kMatrix.t00; +- t2kMatrix.t01 = context->t2kMatrix.t01; +- t2kMatrix.t10 = context->t2kMatrix.t10; +- t2kMatrix.t11 = context->t2kMatrix.t11; +- T2K_NewTransformation(t2k, true, 72, 72, &t2kMatrix, sbits, &errCode); +- +- return errCode; +-} +- + JNIEXPORT void JNICALL + Java_sun_font_FileFont_setNullScaler + (JNIEnv *env, jobject font2D, jlong pScalerContext) { +- + T2KScalerContext *context = (T2KScalerContext*)pScalerContext; + context->scalerInfo = getNullScaler(); + } +@@ -1205,76 +199,12 @@ + JNIEXPORT jfloat JNICALL + Java_sun_font_FileFont_getGlyphAdvance + (JNIEnv *env, jobject font2D, jlong pScalerContext, jint glyphCode) { +- +- int errCode = 0; ++ /* + T2KScalerContext *context = (T2KScalerContext*)pScalerContext; + T2KScalerInfo *scalerInfo = context->scalerInfo; +- T2K *t2k = scalerInfo->t2k; +- UInt32 renderFlags = context->t2kFlags |T2K_SCAN_CONVERT |T2K_SKIP_SCAN_BM; +- int fAdvanceX; +- +- if (isNullScaler(scalerInfo) || context == theNullScalerContext) { +- return (jfloat)0; +- } +- +- if (glyphCode >= INVISIBLE_GLYPHS) { +- return (jfloat)0; +- } +- errCode= setupT2KContext(env, font2D, scalerInfo, context, context->sbits); +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- return (jfloat)0; +- } +- +- T2K_RenderGlyph(t2k, glyphCode, 0, 0, context->greyLevel, +- renderFlags, &errCode); +- +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- return (jfloat)0; +- } +- +- if (context->doFM) { +- /* Fractional metrics requested. +- * Use the linearly scaled advance which is from the precomputed +- * hmtx table in a truetype font. xAdvanceWidth16Dot16 is derived +- * from the points after hinting which snaps those points to the +- * pixel grid. The linearly scaled advance is what the advance would +- * be if hinting effects weren't present. This assumes that hinting +- * doesn't also have some "linear" consequence that isn't accounted +- * for in the precomputed metrics. +- * So since xAdvanceWidth16Dot16 is always integral values, then +- * xLinearAdvanceWidth16Dot16 is what we need to use here, unless +- * there is some way to request the rasteriser +- */ +- fAdvanceX = t2k->xLinearAdvanceWidth16Dot16; +- } else { +- /* rounding advances in both x and y causes falloff from the baseline +- * so in this case we don't round. Rounding the magnitude of the +- * advance vector really has no point to it -- caller can round +- * resulting positions if desired. +- */ +- if (!t2k->yAdvanceWidth16Dot16) { +- fAdvanceX = (t2kFixedRound ( t2k->xAdvanceWidth16Dot16 )) << 16; +- +- } else if (!t2k->xAdvanceWidth16Dot16) { +- fAdvanceX = 0; +- +- } else { +- fAdvanceX = t2k->xAdvanceWidth16Dot16; +- } +- } +- +- T2K_PurgeMemory(t2k, 1, &errCode); // to relase the bitmap/outline +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_PurgeMemory failed", errCode); +- freeScalerInfoAfterError(env, context); +- } +- +- /* Note this value is in device space. The caller needs to convert +- * it into user space +- */ + return (jfloat)t2kFixedToFloat(fAdvanceX); ++ */ ++ return (jfloat)0; + } + + JNIEXPORT void JNICALL +@@ -1282,74 +212,16 @@ + (JNIEnv *env, jobject font2D, jlong pScalerContext, + jint glyphCode, jobject metricsPt) { + +- int errCode = 0; +- T2KScalerContext *context = (T2KScalerContext*)pScalerContext; +- T2KScalerInfo *scalerInfo = context->scalerInfo; +- T2K *t2k = scalerInfo->t2k; +- +- UInt32 renderFlags = context->t2kFlags |T2K_SCAN_CONVERT |T2K_SKIP_SCAN_BM; +- int fAdvanceX, fAdvanceY; +- +- if (metricsPt == NULL) { +- return; +- } +- +- if (isNullScaler(scalerInfo) || context == theNullScalerContext || +- glyphCode >= INVISIBLE_GLYPHS || +- setupT2KContext(env, font2D, scalerInfo, context, context->sbits)!=0) { +- (*env)->SetFloatField(env, metricsPt, sunFontIDs.xFID, (jfloat)0); +- (*env)->SetFloatField(env, metricsPt, sunFontIDs.yFID, (jfloat)0); +- return; +- } +- +- +- T2K_RenderGlyph(t2k, glyphCode, 0, 0, context->greyLevel, +- renderFlags, &errCode); +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- (*env)->SetFloatField(env, metricsPt, sunFontIDs.xFID, (jfloat)0); +- (*env)->SetFloatField(env, metricsPt, sunFontIDs.yFID, (jfloat)0); +- return; +- } +- +- if (context->doFM) { +- fAdvanceX = t2k->xLinearAdvanceWidth16Dot16; +- fAdvanceY = -t2k->yLinearAdvanceWidth16Dot16; +- } else { +- /* rounding advances in both x and y causes falloff from the baseline +- * so in this case we don't round. Rounding the magnitude of the +- * advance vector really has no point to it -- caller can round +- * resulting positions if desired. +- */ +- if (!t2k->yAdvanceWidth16Dot16) { +- fAdvanceX = (t2kFixedRound(t2k->xAdvanceWidth16Dot16)) << 16; +- fAdvanceY = 0; +- } else if (!t2k->xAdvanceWidth16Dot16) { +- fAdvanceX = 0; +- fAdvanceY = -(t2kFixedRound(t2k->yAdvanceWidth16Dot16)) << 16; +- } else { +- fAdvanceX = t2k->xAdvanceWidth16Dot16; +- fAdvanceY = -t2k->yAdvanceWidth16Dot16; +- } +- +- } +- +- T2K_PurgeMemory(t2k, 1, &errCode); // to relase the bitmap/outline +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_PurgeMemory failed", errCode); +- freeScalerInfoAfterError(env, context); +- } +- ++ /* + (*env)->SetFloatField(env, metricsPt, sunFontIDs.xFID, + (jfloat)t2kFixedToFloat(fAdvanceX)); + (*env)->SetFloatField(env, metricsPt, sunFontIDs.yFID, + (jfloat)t2kFixedToFloat(fAdvanceY)); +-} +- +-static jlong getNullGlyphImage() { +- GlyphInfo *glyphInfo = (GlyphInfo*)malloc(sizeof(GlyphInfo)); +- memset(glyphInfo, 0, sizeof(GlyphInfo)); +- return (jlong)(uintptr_t)glyphInfo; ++ */ ++ (*env)->SetFloatField(env, metricsPt, sunFontIDs.xFID, ++ (jfloat)t2kFixedToFloat(0)); ++ (*env)->SetFloatField(env, metricsPt, sunFontIDs.yFID, ++ (jfloat)t2kFixedToFloat(0)); + } + + /* +@@ -1366,194 +238,28 @@ + GlyphInfo *glyphInfo; + T2KScalerContext *context = (T2KScalerContext*)pScalerContext; + T2KScalerInfo *scalerInfo = context->scalerInfo; +- T2K *t2k = scalerInfo->t2k; +- int aaType = context->aaType; +- int greyLevel = context->greyLevel; +- UInt32 renderFlags = context->t2kFlags | T2K_SCAN_CONVERT; +- short width, height; +- int imageRowBytes, imageHeight, imageSize; +- float rndTopLeftX, rndTopLeftY; +- int errCode; +- void* paddedImage = NULL; +- +- if (isNullScaler(scalerInfo) || context == theNullScalerContext) { +- return getNullGlyphImage(); +- } +- +- errCode= setupT2KContext(env, font2D, scalerInfo, context, context->sbits); +- +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- return getNullGlyphImage(); +- } +- +- /* For some glyphs override requested behaviour to force a B&W glyph */ +- if (scalerInfo->bwGlyphs != NULL && aaType == TEXT_AA_LCD_HRGB && +- context->t2kMatrix.t00 < t2kFloatToFixed(14.0) && +- context->t2kMatrix.t00 == context->t2kMatrix.t11 && +- context->t2kMatrix.t01 == 0 && context->t2kMatrix.t10 == 0) { +- int matched = 0, i; +- for (i=0; i<scalerInfo->bwGlyphCnt;i++) { +- if (scalerInfo->bwGlyphs[i] == glyphCode) { +- matched = 1; +- break; +- } +- } +- if (matched) { +- aaType = TEXT_AA_OFF; +- greyLevel = BLACK_AND_WHITE_BITMAP; +- renderFlags = T2K_GRID_FIT | T2K_CODE_IS_GINDEX | T2K_SCAN_CONVERT; +- } +- } +- +- T2K_RenderGlyph(t2k, glyphCode, 0, 0, greyLevel, +- renderFlags, &errCode); +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- return getNullGlyphImage(); +- } +- +- /* LCD text isn't used if an embedded bitmap is requested and available. +- * When "sbits" is true, then T2K will return embedded bitmaps if present. +- * This happens before even entering the internal T2K code that handles +- * the LCD case. Thus the returned bitmaps are not scaled. They are the +- * same as in the B&W case. We must therefore check the T2k flag +- * "embeddedBitmapWasUsed" on return to know how to handle the glyph. +- * If algorithmic bolding (but not obliquing) is specified then the +- * bitmaps may also be used (ie the bitmap is obtained and widened) +- * so the same applies in that case too. +- * Since that case also sets the embeddedBitmapWasUsed flag then that +- * flag is sufficient for us to know how to handle both these cases. +- * +- * However if there is no embedded bitmap then "widening" would still +- * happen. The widening will be applied to the 3X wide bitmap but it +- * will not sufficiently widen or bolden it because the code assumes +- * that the glyph bitmap is at pixel (1X) resolution. Eg it will add an +- * extra column of subpixels rather than the 3 extra columns needed. +- * That is the principal problem as it will affect metrics. Also probably +- * noticeable is that it will allow "gaps" of 1 subpixel rather than +- * 1 whole pixel. Until such time as we can resolve these issues we +- * need to disable bitmap bolding except when embedded bitmaps are +- * retrieved. But the increased horizontal resolution mitigates this +- * substantially +- */ +- if (t2k->embeddedBitmapWasUsed && +- (aaType == TEXT_AA_LCD_HRGB || aaType == TEXT_AA_LCD_VRGB)) { +- aaType = TEXT_AA_OFF; +- } +- width = (UInt16)t2k->width; +- height = (UInt16)t2k->height; +- +- imageRowBytes = width; +- imageHeight = height; +- if (aaType >= TEXT_AA_LCD_HRGB && width > 0) { +- if (aaType == TEXT_AA_LCD_HRGB) { +- CopyBW2LCDH(t2k, lcdscale, +- &paddedImage, &imageRowBytes, &rndTopLeftX); +- } else { +- CopyBW2LCDV(t2k, lcdscale, +- &paddedImage, &imageRowBytes, &imageHeight, +- &rndTopLeftY); +- } +- } +- +- imageSize = imageRowBytes*imageHeight; ++ /* T2K_RenderGlyph(t2k, glyphCode, 0, 0, greyLevel, ++ renderFlags, &errCode); + glyphInfo = (GlyphInfo*)malloc(sizeof(GlyphInfo)+imageSize); + glyphInfo->cellInfo = NULL; +- glyphInfo->rowBytes = imageRowBytes; +- +- if (aaType == TEXT_AA_LCD_HRGB) { +- /* width adjusted by 2 because of FM subpixel padding */ +- glyphInfo->width = (imageRowBytes-PADRIGHT)/3; +- } else if (aaType == TEXT_AA_LCD_VRGB) { +- /* NB no subpixel positioning for VRGB/VBGR */ +- glyphInfo->width = (imageRowBytes/3); +- } else { +- glyphInfo->width = imageRowBytes; +- } +- glyphInfo->height = imageHeight; +- +- +- /* The T2K rasteriser always reports an integer value for topLeftX even +- * though we store it in a float. Perhaps it makes sense to store these +- * values in 16 bit integers as that will save 4 bytes per glyph +- * at the cost of being marginally slower to process at rendering time. +- */ +- if (aaType == TEXT_AA_LCD_HRGB && width != 0) { +- glyphInfo->topLeftX = rndTopLeftX; +- } else { +- glyphInfo->topLeftX= t2kFixedToFloat(F26Dot6ToFixed(t2k->fLeft26Dot6)); +- } +- +- if (aaType == TEXT_AA_LCD_VRGB && width != 0) { +- /* NB no subpixel positioning for VRGB/VBGR. */ +- glyphInfo->topLeftY = -rndTopLeftY; +- } else { +- glyphInfo->topLeftY= -t2kFixedToFloat(F26Dot6ToFixed(t2k->fTop26Dot6)); +- } +- +- if (context->doFM) { +- glyphInfo->advanceX = t2kFixedToFloat(t2k->xLinearAdvanceWidth16Dot16); +- glyphInfo->advanceY =-t2kFixedToFloat(t2k->yLinearAdvanceWidth16Dot16); +- } else { +- /* rounding advances in both x and y causes falloff from the baseline +- * so in this case we don't round. Rounding the magnitude of the +- * advance vector really has no point to it -- caller can round +- * resulting positions if desired. +- */ +- if (!t2k->yAdvanceWidth16Dot16) { +- glyphInfo->advanceX = t2kFixedToFloat +- ((t2kFixedRound(t2k->xAdvanceWidth16Dot16 )) << 16); +- glyphInfo->advanceY = 0; +- } else if (!t2k->xAdvanceWidth16Dot16) { +- glyphInfo->advanceX = 0; +- glyphInfo->advanceY = -t2kFixedToFloat +- ((t2kFixedRound ( t2k->yAdvanceWidth16Dot16 )) << 16); +- } else { +- glyphInfo->advanceX = t2kFixedToFloat(t2k->xAdvanceWidth16Dot16); +- glyphInfo->advanceY = -t2kFixedToFloat(t2k->yAdvanceWidth16Dot16); +- } +- } ++ glyphInfo->rowBytes = imageRowBytes; */ ++ glyphInfo = (GlyphInfo*)malloc(sizeof(GlyphInfo)+0); ++ glyphInfo->cellInfo = NULL; ++ glyphInfo->rowBytes = 0; + + /* Now need to retrieve the glyph so can store the image data. + * The image data is stored contiguously with the info structure as its + * memory is allocated in the same block +- */ +- if (imageSize == 0) { ++ * ++ if (imageSize == 0) { */ + glyphInfo->image = NULL; +- } else { ++ /*} else { + glyphInfo->image = (unsigned char*)glyphInfo+sizeof(GlyphInfo); + memset(glyphInfo->image, 0, imageSize); + if (aaType == TEXT_AA_OFF) { + CopyBW2Grey8(t2k->baseAddr, t2k->rowBytes, + (void *)glyphInfo->image, width, width, height); +- } else if (aaType == TEXT_AA_LCD_HRGB) { +- filterPixelsH(paddedImage, (UInt8*)glyphInfo->image, +- imageRowBytes, glyphInfo->height); +- free(paddedImage); +- } else if (aaType == TEXT_AA_LCD_VRGB) { +- filterPixelsV(paddedImage, (UInt8*)glyphInfo->image, +- imageRowBytes, glyphInfo->height); +- free(paddedImage); +- } else /* must be (aaType == TEXT_AA_ON) */ { +- int x,y; +- const UInt8* srcRow = (UInt8*)t2k->baseAddr; +- UInt8* dstRow = (UInt8*)glyphInfo->image; +- for (y = 0; y < glyphInfo->height; y++) { +- for (x = 0; x < width; x++) { +- dstRow[x] = T2KByteToAlpha255(srcRow[x]); +- } +- dstRow += imageRowBytes; +- srcRow += t2k->rowBytes; +- } +- } +- } +- +- T2K_PurgeMemory(t2k, 1, &errCode); // to release the bitmap/outline +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_PurgeMemory failed", errCode); +- freeScalerInfoAfterError(env, context); +- } ++ } */ + return (jlong)(uintptr_t)glyphInfo; + } + +@@ -1564,115 +270,34 @@ + Java_sun_font_TrueTypeFont_getGlyphPoint + (JNIEnv *env, jobject font2D, jlong pScalerContext, + jint glyphCode, jint pointNumber) { +- +- jobject point = NULL; +- T2KScalerContext *context = (T2KScalerContext*)pScalerContext; +- T2KScalerInfo *scalerInfo = context->scalerInfo; +- T2K *t2k = scalerInfo->t2k; +- UInt32 renderFlags = context->t2kFlags | +- T2K_SCAN_CONVERT | T2K_RETURN_OUTLINES; +- int errCode; +- +- if (isNullScaler(scalerInfo) || context == theNullScalerContext) { +- return NULL; +- } +- +- errCode = setupT2KContext(env, font2D, scalerInfo, context, false); +- +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- return (*env)->NewObject(env, sunFontIDs.pt2DFloatClass, +- sunFontIDs.pt2DFloatCtr, 0, 0); +- } +- ++/* + T2K_RenderGlyph(t2k, glyphCode, 0, 0, context->greyLevel, renderFlags, + &errCode); +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_RenderGlyph failed", errCode); +- freeScalerInfoAfterError(env, context); +- return NULL; // seems to be allowed. +- } + + if (!t2k->embeddedBitmapWasUsed) { + if (pointNumber < t2k->glyph->pointCount) { +- /* Convert from T2K's 26.6 format (64 == 2^6) */ ++ /* Convert from T2K's 26.6 format (64 == 2^6) * + float x = (float)(t2k->glyph->x[pointNumber] / 64.0 ); +- /* convert to java's "+y is down" coordinate system */ ++ /* convert to java's "+y is down" coordinate system * + float y = -(float)(t2k->glyph->y[pointNumber] / 64.0 ); + + point = (*env)->NewObject(env, sunFontIDs.pt2DFloatClass, + sunFontIDs.pt2DFloatCtr, x, y); + } + } +- T2K_PurgeMemory(t2k, 1, &errCode); // to release the bitmap/outline +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_PurgeMemory failed", errCode); +- freeScalerInfoAfterError(env, context); +- } + return point; +-} +- +-/* This function is called by the OpenType layout engine. +- */ +-JNIEXPORT +-int getUnitsPerEmForLayout(JNIEnv* env, jobject font2D) { +- +- int upem = 2048; +- T2K *t2k; +- +- T2KScalerInfo* scalerInfo = NULL; +- if ((*env)->IsInstanceOf(env, font2D, sunFontIDs.ttFontClass)) { +- scalerInfo = (T2KScalerInfo*) +- (*env)->GetLongField(env, font2D, sunFontIDs.pScaler); +- } +- +- if (!isNullScaler(scalerInfo)) { +- t2k = scalerInfo->t2k; +- if (t2k->font && t2k->font->head) { +- upem = t2k->font->head->unitsPerEm; +- } +- } +- return upem; +-} +- +-JNIEXPORT +-TTLayoutTableCache* getLayoutTables(JNIEnv* env, jobject font2D) { +- // we're assuming the font is a file font, otherwise we shouldn't be +- // able to get here... but if we get here with a NativeFont it +- // doesn't have a T2KScalerInfo, so don't initialise layout tables. +- // will be NULL, so don't initialise layout tables. In fact we will +- // do this properly and check its a TrueTypeFont. +- // QUADPATHTYPE stands in for test for t1 font. +- if ((*env)->IsInstanceOf(env, font2D, sunFontIDs.ttFontClass)) { +- T2KScalerInfo *pScaler = (T2KScalerInfo*) +- (*env)->GetLongField(env, font2D, sunFontIDs.pScaler); +- if (pScaler != NULL && pScaler->pathType == QUADPATHTYPE) { +- if (pScaler->layoutTables == NULL) { +- pScaler->layoutTables = newLayoutTableCache(); +- } +- return pScaler->layoutTables; +- } +- } +- return NULL; +-} +- +-static void ProjectUnitVector(hsFixed projX, hsFixed projY, +- hsFract dirX, hsFract dirY, +- hsFract baseX, hsFract baseY, +- hsFixed *fX, hsFixed *fY) +-{ +- hsFixed dist = t2kFracMul(projX, baseY) - t2kFracMul(projY, baseX); +- hsFixed scale = t2kFracDiv(dist, +- t2kFracMul(dirX, baseY) - +- t2kFracMul(dirY, baseX)); +- *fX = t2kFracMul(dirX, scale); +- *fY = t2kFracMul(dirY, scale); ++ */ ++ jobject point; ++ point = (*env)->NewObject(env, sunFontIDs.pt2DFloatClass, ++ sunFontIDs.pt2DFloatCtr, 0, 0); ++ return point; + } + + JNIEXPORT jobject JNICALL + Java_sun_font_FileFont_getFontMetrics + (JNIEnv *env, jobject font2D, jlong pScalerContext) { + ++ /* + T2KScalerContext *context = (T2KScalerContext*)pScalerContext; + T2KScalerInfo *scalerInfo = context->scalerInfo; + T2K *t2k = scalerInfo->t2k; +@@ -1682,114 +307,114 @@ + jfloat ax, ay, dx, dy, bx, by, lx, ly, mx, my; + jfloat f0 = 0.0; + +- int errCode; +- +- if (isNullScaler(scalerInfo) || context == theNullScalerContext) { +- return (*env)->NewObject(env, sunFontIDs.strikeMetricsClass, +- sunFontIDs.strikeMetricsCtr, +- f0,f0,f0,f0,f0,f0,f0,f0,f0,f0); +- } +- +- errCode= setupT2KContext(env, font2D, scalerInfo, context, context->sbits); +- +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- return (*env)->NewObject(env, sunFontIDs.strikeMetricsClass, +- sunFontIDs.strikeMetricsCtr, +- f0,f0,f0,f0,f0,f0,f0,f0,f0,f0); +- } +- +- mag = t2kMagnitude(t2k->caretDx, t2k->caretDy); +- +- caretX = t2kFracDiv(t2k->caretDx, mag); +- caretY = t2kFracDiv(t2k->caretDy, mag); +- +- mag = t2kMagnitude(t2k->xMaxLinearAdvanceWidth, +- t2k->yMaxLinearAdvanceWidth); +- +- baseX = t2kFracDiv(t2k->xMaxLinearAdvanceWidth, mag); +- baseY = t2kFracDiv(t2k->yMaxLinearAdvanceWidth, mag); +- +- /* ascent */ +- ProjectUnitVector(t2k->xAscender + (t2k->xLineGap >> 1), +- - t2k->yAscender - (t2k->yLineGap >> 1), +- caretX, - caretY, baseX, - baseY, &fX, &fY); +- ax = (jfloat)t2kFixedToFloat(fX); +- ay = (jfloat)t2kFixedToFloat(fY); +- +- /* descent */ +- ProjectUnitVector(t2k->xDescender + (t2k->xLineGap >> 1), +- - t2k->yDescender - (t2k->yLineGap >> 1), +- - caretX, caretY, baseX, - baseY, &fX, &fY); +- dx = (jfloat)t2kFixedToFloat(fX); +- dy = (jfloat)t2kFixedToFloat(fY); +- +- /* baseline */ +- bx = (jfloat)t2kFixedToFloat(baseX >> 16); +- by = (jfloat)t2kFixedToFloat(baseY >> 16); +- +- /* leading */ +- ProjectUnitVector(t2k->xLineGap, +- - t2k->yLineGap, +- - caretX, caretY, baseX, - baseY, &fX, &fY); +- lx = (jfloat)-t2kFixedToFloat(fX); +- ly = (jfloat)-t2kFixedToFloat(fY); +- +- /* max advance */ +- mx = (jfloat)t2kFixedToFloat(t2k->xMaxLinearAdvanceWidth); +- my = (jfloat)t2kFixedToFloat(t2k->yMaxLinearAdvanceWidth); +- + metrics = (*env)->NewObject(env, sunFontIDs.strikeMetricsClass, + sunFontIDs.strikeMetricsCtr, + ax, ay, dx, dy, bx, by, lx, ly, mx, my); +-/* printf("ax=%f ay=%f dx=%f dy=%f lx=%f ly=%f\n",ax,ay,dx,dy,lx,ly); */ +-/* printf("mx=%f my=%f\n", mx, my); */ ++/* printf("ax=%f ay=%f dx=%f dy=%f lx=%f ly=%f\n",ax,ay,dx,dy,lx,ly); * ++/* printf("mx=%f my=%f\n", mx, my); * + + return metrics; ++ */ ++ jobject metrics = (*env)->NewObject(env, sunFontIDs.strikeMetricsClass, ++ sunFontIDs.strikeMetricsCtr, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); ++ return metrics; + } + + JNIEXPORT jint JNICALL + Java_sun_font_Type1Font_getNumGlyphs + (JNIEnv *env, jobject t1font, jlong pScaler) { + ++/* + T2KScalerInfo *scalerInfo = (T2KScalerInfo*)pScaler; + T2K *t2k = scalerInfo->t2k; + +- if (t2k == NULL) { /* bad/null scaler */ ++ if (t2k == NULL) { /* bad/null scaler * + /* null scaler can render 1 glyph - "missing glyph" with code 0 + (all glyph codes requested by user are mapped to code 0 at +- validation step) */ ++ validation step) * + return (jint) 1; + } + + return (jint)GetNumGlyphs_sfntClass(t2k->font); ++ */ ++ return (jint) 1; + } + + + JNIEXPORT jint JNICALL + Java_sun_font_Type1Font_getMissingGlyphCode + (JNIEnv *env, jobject t1font, jlong pScaler) { +- ++/* + T2KScalerInfo *scalerInfo = (T2KScalerInfo*)pScaler; + T2K *t2k = scalerInfo->t2k; + +- if (t2k == NULL) { /* bad/null scaler */ ++ if (t2k == NULL) { /* bad/null scaler * + return (jint)0; + } + + return (jint)t2k->font->T1->notdefGlyphIndex; ++ */ ++ return (jint)0; + } + + JNIEXPORT jint JNICALL + Java_sun_font_Type1Font_getGlyphCode + (JNIEnv *env, jobject t1font, jlong pScaler, jchar charCode) { +- ++/* + T2KScalerInfo *scalerInfo = (T2KScalerInfo*)pScaler; + T2K *t2k = scalerInfo->t2k; + +- if (t2k == NULL) { /* bad/null scaler */ ++ if (t2k == NULL) { /* bad/null scaler * + return (jint)0; + } + + return (jint)T2K_GetGlyphIndex(t2k, charCode); ++ */ ++ return (jint)0; + } ++ ++JNIEXPORT ++int getUnitsPerEmForLayout(JNIEnv* env, jobject font2D) { ++ ++ int upem = 2048; ++ /* ++ T2K *t2k; ++ ++ T2KScalerInfo* scalerInfo = NULL; ++ if ((*env)->IsInstanceOf(env, font2D, sunFontIDs.ttFontClass)) { ++ scalerInfo = (T2KScalerInfo*) ++ (*env)->GetLongField(env, font2D, sunFontIDs.pScaler); ++ } ++ ++ if (!isNullScaler(scalerInfo)) { ++ t2k = scalerInfo->t2k; ++ if (t2k->font && t2k->font->head) { ++ upem = t2k->font->head->unitsPerEm; ++ } ++ } ++ */ ++ return upem; ++} ++ ++JNIEXPORT ++TTLayoutTableCache* getLayoutTables(JNIEnv* env, jobject font2D) { ++ // we're assuming the font is a file font, otherwise we shouldn't be ++ // able to get here... but if we get here with a NativeFont it ++ // doesn't have a T2KScalerInfo, so don't initialise layout tables. ++ // will be NULL, so don't initialise layout tables. In fact we will ++ // do this properly and check its a TrueTypeFont. ++ // QUADPATHTYPE stands in for test for t1 font. ++ if ((*env)->IsInstanceOf(env, font2D, sunFontIDs.ttFontClass)) { ++ T2KScalerInfo *pScaler = (T2KScalerInfo*) ++ (*env)->GetLongField(env, font2D, sunFontIDs.pScaler); ++ if (pScaler != NULL && pScaler->pathType == QUADPATHTYPE) { ++ if (pScaler->layoutTables == NULL) { ++ pScaler->layoutTables = newLayoutTableCache(); ++ } ++ return pScaler->layoutTables; ++ } ++ } ++ return NULL; ++} ++ +diff -urN openjdk.orig/j2se/src/share/native/sun/font/sunFont.c openjdk/j2se/src/share/native/sun/font/sunFont.c +--- openjdk.orig/j2se/src/share/native/sun/font/sunFont.c 2007-06-21 03:47:50.000000000 -0400 ++++ openjdk/j2se/src/share/native/sun/font/sunFont.c 2007-06-26 10:38:03.000000000 -0400 +@@ -164,7 +164,7 @@ + tmpClass = (*env)->FindClass(env, "sun/font/FileFont"); + sunFontIDs.pScaler = (*env)->GetFieldID(env, tmpClass, "pScaler", "J"); + +- setSunFontIDs(sunFontIDs); ++/* setSunFontIDs(sunFontIDs); */ + initLCDGammaTables(); + } + +diff -urN openjdk.orig/j2se/src/share/native/sun/font/sunt2kscaler.h openjdk/j2se/src/share/native/sun/font/sunt2kscaler.h +--- openjdk.orig/j2se/src/share/native/sun/font/sunt2kscaler.h 2007-06-21 03:47:50.000000000 -0400 ++++ openjdk/j2se/src/share/native/sun/font/sunt2kscaler.h 2007-06-26 11:38:22.000000000 -0400 +@@ -29,7 +29,7 @@ + + #include "jni.h" + #include <math.h> +-#include "t2k.h" ++//#include "t2k.h" + #include "glyphblitting.h" + #include "fontscalerdefs.h" + +@@ -126,6 +126,8 @@ + TTLayoutTableCache* newLayoutTableCache(); + void freeLayoutTableCache(TTLayoutTableCache* ltc); + ++typedef unsigned char tt_uint8; ++ + typedef struct T2KScalerInfo { + /* Every call down must copy its "env" and "font2D" variable into the + * appropriate members of this struct. +@@ -134,8 +136,8 @@ + * T2K instance is not yet initialised. + */ + JNIEnv* env; +- tsiMemObject* memHandler; +- T2K* t2k; ++/* tsiMemObject* memHandler; ++ T2K* t2k; */ + tt_uint8* fontData; + jobject font2D; + jobject directBuffer; +@@ -169,8 +171,8 @@ + */ + typedef struct T2KScalerContext { + T2KScalerInfo* scalerInfo; +- T2K_TRANS_MATRIX t2kMatrix; /* glyph TX - includes dev TX */ +- T2K_AlgStyleDescriptor styling; ++/* T2K_TRANS_MATRIX t2kMatrix; /* glyph TX - includes dev TX * ++ T2K_AlgStyleDescriptor styling; */ + jboolean sbits; + jboolean doAA; + jint aaType; +diff -urN openjdk.orig/j2se/src/share/native/sun/font/t2kScalerMethods.cpp openjdk/j2se/src/share/native/sun/font/t2kScalerMethods.cpp +--- openjdk.orig/j2se/src/share/native/sun/font/t2kScalerMethods.cpp 2007-06-21 03:47:50.000000000 -0400 ++++ openjdk/j2se/src/share/native/sun/font/t2kScalerMethods.cpp 2007-06-26 13:41:40.000000000 -0400 +@@ -30,46 +30,11 @@ + + extern "C" { + +-static void getGlyphGeneralPath(JNIEnv* env, jobject font2D, jlong pScalerContext, ++static void getGlyphGeneralPath(JNIEnv* env, jobject font2D, jlong pScalerContext, + jint glyphCode, jfloat xpos, jfloat ypos, + GeneralPath* gp) { + +- if (glyphCode >= INVISIBLE_GLYPHS) { +- return; +- } +- +- T2KScalerContext *context = (T2KScalerContext*)pScalerContext; +- T2KScalerInfo *scalerInfo = context->scalerInfo; +- T2K *t2k = scalerInfo->t2k; +- UInt32 renderFlags = ((context->t2kFlags | T2K_RETURN_OUTLINES) +- & ~T2K_GRID_FIT); +- jboolean isQuadPath = scalerInfo->pathType == QUADPATHTYPE; +- +- int errCode; +- +- if (isNullScaler(scalerInfo) || context == theNullScalerContext) { +- return; +- } +- errCode = setupT2KContext(env, font2D, scalerInfo, context, false); +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- return; +- } +- +- T2K_RenderGlyph(t2k, glyphCode, 0, 0, context->greyLevel, renderFlags, +- &errCode); +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_RenderGlyph failed", errCode); +- freeScalerInfoAfterError(env, context); +- } +- +- addGlyphToGeneralPath(*t2k->glyph, *gp, xpos, ypos, isQuadPath); +- +- T2K_PurgeMemory(t2k, 1, &errCode); +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_PurgeMemory failed", errCode); +- freeScalerInfoAfterError(env, context); +- } ++ /*addGlyphToGeneralPath(*t2k->glyph, *gp, xpos, ypos, isQuadPath);*/ + } + + JNIEXPORT jobject JNICALL +@@ -78,7 +43,7 @@ + jint glyphCode, jfloat xpos, jfloat ypos) { + + GeneralPath gp; +- getGlyphGeneralPath(env, font2D, pScalerContext, glyphCode, xpos, ypos, &gp); ++/* getGlyphGeneralPath(env, font2D, pScalerContext, glyphCode, xpos, ypos, &gp); */ + return gp.getShape(env); + } + +@@ -87,7 +52,7 @@ + (JNIEnv *env, jobject font2D, jlong pScalerContext, int glyphCode) { + + GeneralPath gp; +- getGlyphGeneralPath(env, font2D, pScalerContext, glyphCode, 0.0f, 0.0f, &gp); ++/* getGlyphGeneralPath(env, font2D, pScalerContext, glyphCode, 0.0f, 0.0f, &gp);*/ + return gp.getBounds(env); + } + +@@ -96,56 +61,17 @@ + (JNIEnv *env, jobject font2D, jintArray glyphArray, int numGlyphs, + jlong pScalerContext, jfloat xpos, jfloat ypos) { + +- int i; +- T2KScalerContext *context = (T2KScalerContext*)pScalerContext; +- T2KScalerInfo *scalerInfo = context->scalerInfo; +- T2K *t2k = scalerInfo->t2k; + GeneralPath generalPath; + ++/* + if (isNullScaler(scalerInfo) || context == theNullScalerContext) { + return generalPath.getShape(env); + } + +- UInt32 renderFlags = ((context->t2kFlags | T2K_RETURN_OUTLINES) +- & ~T2K_GRID_FIT); +- jint *glyphs = (jint*)malloc(sizeof(jint)*numGlyphs); +- jboolean isQuadPath = scalerInfo->pathType == QUADPATHTYPE; +- +- int errCode; +- +- errCode = setupT2KContext(env, font2D, scalerInfo, context, false); +- if (errCode) { +- freeScalerInfoAfterError(env, context); +- return generalPath.getShape(env); +- } +- +- env->GetIntArrayRegion(glyphArray, 0, numGlyphs, glyphs); +- for (i=0; i<numGlyphs;i++) { +- if (glyphs[i] >= INVISIBLE_GLYPHS) { +- continue; +- } +- /* NB LCD modes have a T2K context which requests scaled bitmaps. +- * Here we rely on T2K to interpret that to mean to scale only +- * the returned bitmap image, not the returned outline. +- */ +- T2K_RenderGlyph(t2k, glyphs[i], 0, 0, context->greyLevel, renderFlags, +- &errCode); +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_RenderGlyph failed", errCode); +- freeScalerInfoAfterError(env, context); +- } +- + addGlyphToGeneralPath(*t2k->glyph, generalPath, + xpos, ypos, isQuadPath); +- +- T2K_PurgeMemory(t2k, 1, &errCode); +- if (errCode) { +- t2kIfDebugMessage(errCode, "T2K_PurgeMemory failed", errCode); +- freeScalerInfoAfterError(env, context); +- } +- } +- + free(glyphs); ++ */ + return generalPath.getShape(env); + } + + +diff -urN openjdk.orig/j2se/make/sun/font/FILES_c.gmk openjdk/j2se/make/sun/font/FILES_c.gmk +--- openjdk.orig/j2se/make/sun/font/FILES_c.gmk 2007-06-21 03:33:28.000000000 -0400 ++++ openjdk/j2se/make/sun/font/FILES_c.gmk 2007-06-26 10:40:56.000000000 -0400 +@@ -29,7 +29,8 @@ + $(TARGDIR)ubidiln.c \ + $(TARGDIR)uchardir.c \ + $(TARGDIR)DrawGlyphList.c \ +- $(TARGDIR)sunFont.c ++ $(TARGDIR)sunFont.c \ ++ $(TARGDIR)scalerMethods.c + + FILES_cpp_shared = \ + $(TARGDIR)CursiveAttachmentSubtables.cpp \ +@@ -105,7 +106,9 @@ + $(TARGDIR)OpenTypeLayoutEngine.cpp \ + $(TARGDIR)ThaiLayoutEngine.cpp \ + $(TARGDIR)ScriptAndLanguageTags.cpp \ +- $(TARGDIR)FontInstanceAdapter.cpp ++ $(TARGDIR)FontInstanceAdapter.cpp \ ++ $(TARGDIR)GeneralPath.cpp \ ++ $(TARGDIR)t2kScalerMethods.cpp + + + ifeq ($(PLATFORM),windows) +diff -urN openjdk.orig/j2se/make/sun/font/mapfile-vers openjdk/j2se/make/sun/font/mapfile-vers +--- openjdk.orig/j2se/make/sun/font/mapfile-vers 2007-06-21 03:33:28.000000000 -0400 ++++ openjdk/j2se/make/sun/font/mapfile-vers 2007-06-26 14:43:41.000000000 -0400 +@@ -57,6 +57,23 @@ + Java_sun_java2d_loops_DrawGlyphListAA_DrawGlyphListAA; + Java_sun_java2d_loops_DrawGlyphListLCD_DrawGlyphListLCD; + Java_sun_java2d_loops_DrawGlyphList_DrawGlyphList; ++ Java_sun_font_Type1Font_createScaler; ++ Java_sun_font_FileFont_getNullScaler; ++ Java_sun_font_FileFontStrike_getNullScalerContext; ++ Java_sun_font_FileFontStrike_createScalerContext; ++ Java_sun_font_FileFont_freeScaler; ++ Java_sun_font_TrueTypeFont_createScaler; ++ Java_sun_font_FileFont_setNullScaler; ++ Java_sun_font_FileFont_getGlyphMetrics; ++ Java_sun_font_FileFont_getGlyphImage; ++ Java_sun_font_TrueTypeFont_getGlyphPoint; ++ Java_sun_font_FileFont_getFontMetrics; ++ Java_sun_font_Type1Font_getNumGlyphs; ++ Java_sun_font_Type1Font_getMissingGlyphCode; ++ Java_sun_font_Type1Font_getGlyphCode; ++ Java_sun_font_FileFont_getGlyphOutline; ++ Java_sun_font_FileFont_getGlyphOutlineBounds; ++ Java_sun_font_FileFont_getGlyphVectorOutline; + + local: + *;