JDK-4072782 : AWT components are unable to display non-Latin text
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.2.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_2.5.1
  • CPU: generic
  • Submitted: 1997-08-19
  • Updated: 1999-01-15
  • Resolved: 1999-01-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.2.0 1.2beta1Fixed
Related Reports
Relates :  
Description
JDK1.2's awt components other than TextArea and TextField are unable to display Japanese. 

-------------------------------------------------------------------------------
[ls@corp, 9/5/97]
Same problem in zh (Simplified Chinese) locale.

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.2beta1 FIXED IN: 1.2beta1 INTEGRATED IN: 1.2beta1
14-06-2004

SUGGESTED FIX sherman@japan and norbert@eng, 1997-08-21 This is a partial fix addressing items (1) and (3) in the comments. ----------------suggested fix -------- public Object[] makeConvertedMultiFontChars(char[] data, int start, int len) throws MalformedInputException,ConversionBufferFullException { Object[] result; try { int end = start + len; if (start < 0 || end > data.length) { throw new ArrayIndexOutOfBoundsException(); } FontDescriptor fontDescriptor = latestFont; if (fontDescriptor == null) { fontDescriptor = defaultFont; } CharToByteConverter converter = fontDescriptor.fontCharset; int convertedDataLen = (len * converter.getMaxBytesPerChar()) + 1; byte[] convertedData = new byte[convertedDataLen]; converter.setSubstitutionMode(false); converter.convert(data, start, end, convertedData, 0, convertedDataLen); converter.reset(); result = new Object[2]; result[0] = fontDescriptor; result[1] = convertedData; } catch (UnknownCharacterException e) { result = makeConvertedTrueMultiFontChars(data, start, len); } return result; } /** * Specialized "fast" (faster, that is) path char conversion for AWT. */ public Object[] makeConvertedTrueMultiFontChars(char[] data, int start, int length) throws MalformedInputException, ConversionBufferFullException { FontDescriptor currentFontDescriptor; char currentDefaultChar; int componentCount = componentFonts.length; int stringIndex = start; int dataEnd = start + length; if (length < 1) { return null; } if (start + length > data.length || start < 0 || length < 0) { throw new ArrayIndexOutOfBoundsException(); } if (length > data.length) length = data.length; Object[] resultArray = new Object[2]; int resultIndex = 0; while (true) { /* if we caught an exception converting... */ if (stringIndex == dataEnd) { return resultArray; } /* find a converter that can convert the current character */ currentFontDescriptor = defaultFont; currentDefaultChar = defaultChar; char ch = data[stringIndex]; for (int j = 0; j < componentCount; j++) { FontDescriptor fontDescriptor = componentFonts[j]; if (fontDescriptor.isExcluded(ch)) { continue; } if (fontDescriptor.fontCharset.canConvert(ch)) { currentFontDescriptor = fontDescriptor; /* update latest match */ latestFont = fontDescriptor; currentDefaultChar = ch; break; } } data[stringIndex] = currentDefaultChar; /* * either we found a converter, or we didn't and are using * the default one. In any, case, we try to convert the rest * of the string using it. */ CharToByteConverter converter = currentFontDescriptor.fontCharset; /* 1 is for 0-termination */ int remaining = dataEnd - stringIndex; int bufferLength = 1+(remaining * converter.getMaxBytesPerChar()); byte[] byteBuffer = new byte[bufferLength]; // Resize the resultArray if needed if (resultIndex > resultArray.length - 2) { Object[] newArray = new Object[resultArray.length * 2]; System.arraycopy(resultArray, 0, newArray, 0, resultArray.length); resultArray = newArray; } resultArray[resultIndex++] = currentFontDescriptor; resultArray[resultIndex++] = byteBuffer; /* * see how much we actually manage to convert. Since we're * not in substitution mode, we either do the whole * shebang, or get an exception. */ try { converter.setSubstitutionMode(false); converter.convert(data, stringIndex, dataEnd, byteBuffer, 0, bufferLength - 1); /* converters have state */ converter.reset(); /* we're done */ return resultArray; } catch (UnknownCharacterException e) { /* 0-terminate */ byteBuffer[converter.nextByteIndex()] = 0; stringIndex = converter.nextCharIndex(); } } } -------------------------------------------------------------------------------- [xueming.shen@Japan 1997-08-25] The implementation on Win32 may also need the following changes. For problem (6), add appropriate fontcharset name into font.properties.**, I only change the japanese locale here as an example ----------------font.properties.ja------------ fontcharset.dialog.1=sun.io.CharToByteSJIS fontcharset.dialoginput.1=sun.io.CharToByteSJIS fontcharset.serif.1=sun.io.CharToByteSJIS fontcharset.sansserif.1=sun.io.CharToByteSJIS fontcharset.monospaced.1=sun.io.CharToByteSJIS -------------------end------------------------- For problem (7), in awt_Font.cpp in AwtFont::DrawStringSize_sub() change if (IsMultiFont(env, font)) { jobject peer = env->GetObjectField(font, AwtFont::peerID); array = (jobjectArray)(env->CallObjectMethod( peer, AwtFont::makeConvertedMultiFontStringMID, str)); ASSERT(!env->ExceptionOccurred()); if (array != NULL) { int len = env->GetArrayLength(array); if (len != 0) { segment_num = len / 2; } else { segment_num = len; } } env->DeleteLocalRef(peer); } else { array = NULL; segment_num = 0; } to if (IsMultiFont(env, font)) { jobject peer = env->GetObjectField(font, AwtFont::peerID); array = (jobjectArray)(env->CallObjectMethod( peer, AwtFont::makeConvertedMultiFontStringMID, str)); ASSERT(!env->ExceptionOccurred()); if (array != NULL) { int len = env->GetArrayLength(array); segment_num = len; } env->DeleteLocalRef(peer); } else { array = NULL; segment_num = 0; }
11-06-2004

EVALUATION A number of fixes were applied for JDK 1.2 beta 1, so that non-Latin text now displays correctly in most cases. There are still problems with Dingbats on Solaris, and it's not clear whether the combination of inefficient converters and a caching scheme in PlatformFont is the right solution. It may be possible to implement a better scheme that improves the canConvert methods and thus makes the cache unnecessary, or to reduce the memory footprint of the cache, or to improve the hit ratio of the cache for locales with large character sets. ----- norbert.lindenberg@Eng 1998-01-09: The remaining problems have been reported in separate bugs 4087772 and 4102920, so I'm closing this one as fixed.
09-01-1998