32 #include "java_awt_Font.h"
33 #include "java_awt_FontMetrics.h"
34 #include "java_awt_Dimension.h"
35
36 #include "sun_awt_FontDescriptor.h"
37 #include "sun_awt_windows_WDefaultFontCharset.h"
38 #include "sun_awt_windows_WFontPeer.h"
39 #include "awt_Component.h"
40 #include "Disposer.h"
41
42 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
43 */
44
45 AwtFontCache fontCache;
46
47 extern jboolean IsMultiFont(JNIEnv *env, jobject obj)
48 {
49 if (obj == NULL) {
50 return JNI_FALSE;
51 }
52 if (env->EnsureLocalCapacity(2))
53 return JNI_FALSE;
54 jobject peer = env->CallObjectMethod(obj, AwtFont::peerMID);
55 if (peer == NULL) {
56 return JNI_FALSE;
57 }
58 jobject fontConfig = env->GetObjectField(peer, AwtFont::fontConfigID);
59 jboolean result = fontConfig != NULL;
60 env->DeleteLocalRef(peer);
61 env->DeleteLocalRef(fontConfig);
62 return result;
63 }
64
65 extern jstring GetTextComponentFontName(JNIEnv *env, jobject font)
66 {
67 DASSERT(font != NULL);
68 if (env->EnsureLocalCapacity(2)) {
69 return NULL;
70 }
71 jobject peer = env->CallObjectMethod(font, AwtFont::peerMID);
72 DASSERT(peer != NULL);
73 jstring textComponentFontName =
74 (jstring) env->GetObjectField(peer, AwtFont::textComponentFontNameID);
75 env->DeleteLocalRef(peer);
76 return textComponentFontName;
77 }
78
79 /************************************************************************
80 * AwtFont fields
81 */
82
83 /* sun.awt.windows.WFontMetrics fields */
84 jfieldID AwtFont::widthsID;
85 jfieldID AwtFont::ascentID;
86 jfieldID AwtFont::descentID;
87 jfieldID AwtFont::leadingID;
88 jfieldID AwtFont::heightID;
89 jfieldID AwtFont::maxAscentID;
90 jfieldID AwtFont::maxDescentID;
91 jfieldID AwtFont::maxHeightID;
92 jfieldID AwtFont::maxAdvanceID;
174 static void pDataDisposeMethod(JNIEnv *env, jlong pData)
175 {
176 TRY_NO_VERIFY;
177
178 AwtObject::_Dispose((PDATA)pData);
179
180 CATCH_BAD_ALLOC;
181 }
182
183 AwtFont* AwtFont::GetFont(JNIEnv *env, jobject font,
184 jint angle, jfloat awScale)
185 {
186 jlong pData = env->GetLongField(font, AwtFont::pDataID);
187 AwtFont* awtFont = (AwtFont*)jlong_to_ptr(pData);
188
189 if (awtFont != NULL) {
190 return awtFont;
191 }
192
193 awtFont = Create(env, font, angle, awScale);
194
195 env->SetLongField(font, AwtFont::pDataID,
196 reinterpret_cast<jlong>(awtFont));
197 return awtFont;
198 }
199
200 // Get suitable CHARSET from charset string provided by font configuration.
201 static int GetNativeCharset(LPCWSTR name)
202 {
203 if (wcsstr(name, L"ANSI_CHARSET"))
204 return ANSI_CHARSET;
205 if (wcsstr(name, L"DEFAULT_CHARSET"))
206 return DEFAULT_CHARSET;
207 if (wcsstr(name, L"SYMBOL_CHARSET") || wcsstr(name, L"WingDings"))
208 return SYMBOL_CHARSET;
209 if (wcsstr(name, L"SHIFTJIS_CHARSET"))
210 return SHIFTJIS_CHARSET;
211 if (wcsstr(name, L"GB2312_CHARSET"))
212 return GB2312_CHARSET;
213 if (wcsstr(name, L"HANGEUL_CHARSET"))
255 return 0;
256
257 if (IsMultiFont(env, font)) {
258 compFont = GetComponentFonts(env, font);
259 cfnum = env->GetArrayLength(compFont);
260 } else {
261 compFont = NULL;
262 cfnum = 0;
263 }
264
265 LPCWSTR wName;
266
267 awtFont = new AwtFont(cfnum, env, font);
268
269 awtFont->textAngle = angle;
270 awtFont->awScale = awScale;
271
272 if (cfnum > 0) {
273 // Ask peer class for the text component font name
274 jstring jTextComponentFontName = GetTextComponentFontName(env, font);
275 LPCWSTR textComponentFontName = JNU_GetStringPlatformChars(env, jTextComponentFontName, NULL);
276
277 awtFont->m_textInput = -1;
278 for (int i = 0; i < cfnum; i++) {
279 // nativeName is a pair of platform fontname and its charset
280 // tied with a comma; "Times New Roman,ANSI_CHARSET".
281 jobject fontDescriptor = env->GetObjectArrayElement(compFont,
282 i);
283 jstring nativeName =
284 (jstring)env->GetObjectField(fontDescriptor,
285 AwtFont::nativeNameID);
286 wName = JNU_GetStringPlatformChars(env, nativeName, NULL);
287 DASSERT(wName);
288
289 //On NT platforms, if the font is not Symbol or Dingbats
290 //use "W" version of Win32 APIs directly, info the FontDescription
291 //no need to convert characters from Unicode to locale encodings.
292 if (GetNativeCharset(wName) != SYMBOL_CHARSET) {
293 env->SetBooleanField(fontDescriptor, AwtFont::useUnicodeID, TRUE);
294 }
295
296 // Check to see if this font is suitable for input
297 // on AWT TextComponent
298 if ((awtFont->m_textInput == -1) &&
299 (textComponentFontName != NULL) &&
300 (wcscmp(wName, textComponentFontName) == 0)) {
301 awtFont->m_textInput = i;
302 }
303 HFONT hfonttmp = CreateHFont(const_cast<LPWSTR>(wName), fontStyle, fontSize,
304 angle, awScale);
305 awtFont->m_hFont[i] = hfonttmp;
306
307 JNU_ReleaseStringPlatformChars(env, nativeName, wName);
308
309 env->DeleteLocalRef(fontDescriptor);
310 env->DeleteLocalRef(nativeName);
311 }
312 if (awtFont->m_textInput == -1) {
313 // no text component font was identified, so default
314 // to first component
315 awtFont->m_textInput = 0;
316 }
317
318 JNU_ReleaseStringPlatformChars(env, jTextComponentFontName, textComponentFontName);
319 env->DeleteLocalRef(jTextComponentFontName);
320 } else {
321 // Instantiation for English version.
322 jstring fontName = (jstring)env->GetObjectField(font,
323 AwtFont::nameID);
324 wName = JNU_GetStringPlatformChars(env, fontName, NULL);
325
326 WCHAR* wEName;
327 if (!wcscmp(wName, L"Helvetica") || !wcscmp(wName, L"SansSerif")) {
328 wEName = L"Arial";
329 } else if (!wcscmp(wName, L"TimesRoman") ||
330 !wcscmp(wName, L"Serif")) {
331 wEName = L"Times New Roman";
332 } else if (!wcscmp(wName, L"Courier") ||
333 !wcscmp(wName, L"Monospaced")) {
334 wEName = L"Courier New";
335 } else if (!wcscmp(wName, L"Dialog")) {
336 wEName = L"MS Sans Serif";
337 } else if (!wcscmp(wName, L"DialogInput")) {
338 wEName = L"MS Sans Serif";
339 } else if (!wcscmp(wName, L"ZapfDingbats")) {
340 wEName = L"WingDings";
341 } else
342 wEName = L"Arial";
343
344 awtFont->m_textInput = 0;
630 if (str == NULL) {
631 return size;
632 }
633
634 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
635 if (env->EnsureLocalCapacity(3) < 0)
636 return size;
637 jobjectArray array = 0;
638
639 int arrayLength = 0;
640
641 if (env->GetStringLength(str) == 0) {
642 return size;
643 }
644
645 //Init AwtFont object, which will "create" a AwtFont object if necessry,
646 //before calling makeconvertedMultiFontString(), otherwise, the FontDescriptor's
647 //"useUnicode" field might not be initialized correctly (font in Menu Component,
648 //for example").
649 AwtFont* awtFont = AwtFont::GetFont(env, font);
650
651 if (IsMultiFont(env, font)) {
652 jobject peer = env->CallObjectMethod(font, AwtFont::peerMID);
653 array = (jobjectArray)(env->CallObjectMethod(
654 peer, AwtFont::makeConvertedMultiFontStringMID, str));
655 DASSERT(!safe_ExceptionOccurred(env));
656
657 if (array != NULL) {
658 arrayLength = env->GetArrayLength(array);
659 }
660 env->DeleteLocalRef(peer);
661 } else {
662 array = NULL;
663 arrayLength = 0;
664 }
665
666 HFONT oldFont = (HFONT)::SelectObject(hDC, awtFont->GetHFont());
667
668 if (arrayLength == 0) {
669 int length = env->GetStringLength(str);
670 LPCWSTR strW = JNU_GetStringPlatformChars(env, str, NULL);
671 VERIFY(::SelectObject(hDC, awtFont->GetHFont()));
672 if (AwtComponent::GetRTLReadingOrder()){
673 VERIFY(!draw || ::ExtTextOut(hDC, x, y, ETO_RTLREADING, NULL,
674 strW, length, NULL));
675 } else {
676 VERIFY(!draw || ::TextOut(hDC, x, y, strW, length));
677 }
678 VERIFY(::GetTextExtentPoint32(hDC, strW, length, &size));
679 JNU_ReleaseStringPlatformChars(env, str, strW);
680 } else {
681 for (int i = 0; i < arrayLength; i = i + 2) {
682 jobject fontDescriptor = env->GetObjectArrayElement(array, i);
683 if (fontDescriptor == NULL) {
684 break;
685 }
686
687 jbyteArray convertedBytes =
688 (jbyteArray)env->GetObjectArrayElement(array, i + 1);
689 if (convertedBytes == NULL) {
690 env->DeleteLocalRef(fontDescriptor);
691 break;
692 }
693
694 int fdIndex = getFontDescriptorNumber(env, font, fontDescriptor);
695 VERIFY(::SelectObject(hDC, awtFont->GetHFont(fdIndex)));
696
697 /*
698 * The strange-looking code that follows this comment is
699 * the result of upstream optimizations. In the array of
700 * alternating font descriptor and buffers, the buffers
701 * contain their length in the first four bytes, a la
702 * Pascal arrays.
703 *
704 * Note: the buffer MUST be unsigned, or VC++ will sign
705 * extend buflen and bad things will happen.
706 */
707 unsigned char* buffer = NULL;
708 jboolean unicodeUsed = env->GetBooleanField(fontDescriptor, AwtFont::useUnicodeID);
709 try {
710 buffer = (unsigned char *)
711 env->GetPrimitiveArrayCritical(convertedBytes, 0);
712 int buflen = (buffer[0] << 24) | (buffer[1] << 16) |
713 (buffer[2] << 8) | buffer[3];
714
715 DASSERT(buflen >= 0);
716
717 /*
718 * the offsetBuffer, on the other hand, must be signed because
719 * TextOutA and GetTextExtentPoint32A expect it.
720 */
721 char* offsetBuffer = (char *)(buffer + 4);
722
723 if (unicodeUsed) {
724 VERIFY(!draw || ::TextOutW(hDC, x, y, (LPCWSTR)offsetBuffer, buflen / 2));
725 VERIFY(::GetTextExtentPoint32W(hDC, (LPCWSTR)offsetBuffer, buflen / 2, &temp));
726 }
727 else {
728 VERIFY(!draw || ::TextOutA(hDC, x, y, offsetBuffer, buflen));
729 VERIFY(::GetTextExtentPoint32A(hDC, offsetBuffer, buflen, &temp));
730 }
731 } catch (...) {
799 */
800 JNIEXPORT jint JNICALL
801 Java_sun_awt_windows_WFontMetrics_charsWidth(JNIEnv *env, jobject self,
802 jcharArray str,
803 jint off, jint len)
804 {
805 TRY;
806
807 if (str == NULL) {
808 JNU_ThrowNullPointerException(env, "str argument");
809 return NULL;
810 }
811 if ((len < 0) || (off < 0) || (len + off > (env->GetArrayLength(str)))) {
812 JNU_ThrowArrayIndexOutOfBoundsException(env, "off/len argument");
813 return NULL;
814 }
815
816 jchar *strp = new jchar[len];
817 env->GetCharArrayRegion(str, off, len, strp);
818 jstring jstr = env->NewString(strp, len);
819 jint result = Java_sun_awt_windows_WFontMetrics_stringWidth(env, self,
820 jstr);
821 delete [] strp;
822 return result;
823
824 CATCH_BAD_ALLOC_RET(0);
825 }
826
827
828 /*
829 * Class: sun_awt_windows_WFontMetrics
830 * Method: bytesWidth
831 * Signature: ([BII)I
832 */
833 JNIEXPORT jint JNICALL
834 Java_sun_awt_windows_WFontMetrics_bytesWidth(JNIEnv *env, jobject self,
835 jbyteArray str,
836 jint off, jint len)
837 {
838 TRY;
839
840 if (str == NULL) {
841 JNU_ThrowNullPointerException(env, "bytes argument");
842 return NULL;
843 }
844 if ((len < 0) || (off < 0) || (len + off > (env->GetArrayLength(str)))) {
845 JNU_ThrowArrayIndexOutOfBoundsException(env, "off or len argument");
846 return NULL;
847 }
848 char *pStrBody = NULL;
849 jint result = 0;
850 try {
851 jintArray array = (jintArray)env->GetObjectField(self,
852 AwtFont::widthsID);
853 pStrBody = (char *)env->GetPrimitiveArrayCritical(str, 0);
854 char *pStr = pStrBody + off;
855
856 jint *widths = NULL;
857 try {
858 widths = (jint *)env->GetPrimitiveArrayCritical(array, 0);
859
860 for (; len; len--) {
861 result += widths[*pStr++];
862 }
863 } catch (...) {
864 if (widths != NULL) {
865 env->ReleasePrimitiveArrayCritical(array, widths, 0);
866 }
867 throw;
868 }
869
870 env->ReleasePrimitiveArrayCritical(array, widths, 0);
871
872 } catch (...) {
873 if (pStrBody != NULL) {
874 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
875 }
876 throw;
877 }
878
879 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
898 JNU_ThrowNullPointerException(env, "fontMetrics' font");
899 return;
900 }
901 // This local variable is unused. Is there some subtle side-effect here?
902 jlong pData = env->GetLongField(font, AwtFont::pDataID);
903
904 AwtFont::LoadMetrics(env, self);
905
906 CATCH_BAD_ALLOC;
907 }
908
909
910 /*
911 * Class: sun_awt_windows_WFontMetrics
912 * Method: initIDs
913 * Signature: ()V
914 */
915 JNIEXPORT void JNICALL
916 Java_sun_awt_windows_WFontMetrics_initIDs(JNIEnv *env, jclass cls)
917 {
918 TRY;
919
920 AwtFont::widthsID = env->GetFieldID(cls, "widths", "[I");
921 AwtFont::ascentID = env->GetFieldID(cls, "ascent", "I");
922 AwtFont::descentID = env->GetFieldID(cls, "descent", "I");
923 AwtFont::leadingID = env->GetFieldID(cls, "leading", "I");
924 AwtFont::heightID = env->GetFieldID(cls, "height", "I");
925 AwtFont::maxAscentID = env->GetFieldID(cls, "maxAscent", "I");
926 AwtFont::maxDescentID = env->GetFieldID(cls, "maxDescent", "I");
927 AwtFont::maxHeightID = env->GetFieldID(cls, "maxHeight", "I");
928 AwtFont::maxAdvanceID = env->GetFieldID(cls, "maxAdvance", "I");
929
930 DASSERT(AwtFont::widthsID != NULL);
931 DASSERT(AwtFont::ascentID != NULL);
932 DASSERT(AwtFont::descentID != NULL);
933 DASSERT(AwtFont::leadingID != NULL);
934 DASSERT(AwtFont::heightID != NULL);
935 DASSERT(AwtFont::maxAscentID != NULL);
936 DASSERT(AwtFont::maxDescentID != NULL);
937 DASSERT(AwtFont::maxHeightID != NULL);
938 DASSERT(AwtFont::maxAdvanceID != NULL);
939
940 CATCH_BAD_ALLOC;
941 }
942
943 } /* extern "C" */
944
945
946 /************************************************************************
947 * java.awt.Font native methods
948 */
949
950 extern "C" {
951
952 JNIEXPORT void JNICALL
953 Java_java_awt_Font_initIDs(JNIEnv *env, jclass cls)
954 {
955 TRY;
956
957 AwtFont::peerMID = env->GetMethodID(cls, "getPeer",
958 "()Ljava/awt/peer/FontPeer;");
959 AwtFont::pDataID = env->GetFieldID(cls, "pData", "J");
960 AwtFont::nameID = env->GetFieldID(cls, "name", "Ljava/lang/String;");
961 AwtFont::sizeID = env->GetFieldID(cls, "size", "I");
962 AwtFont::styleID = env->GetFieldID(cls, "style", "I");
963
964 AwtFont::getFontMID =
965 env->GetStaticMethodID(cls, "getFont",
966 "(Ljava/lang/String;)Ljava/awt/Font;");
967
968 DASSERT(AwtFont::peerMID != NULL);
969 DASSERT(AwtFont::pDataID != NULL);
970 DASSERT(AwtFont::nameID != NULL);
971 DASSERT(AwtFont::sizeID != NULL);
972 DASSERT(AwtFont::styleID != NULL);
973
974 DASSERT(AwtFont::getFontMID != NULL);
975
976 CATCH_BAD_ALLOC;
977 }
978
979 } /* extern "C" */
980
981
982 /************************************************************************
983 * java.awt.FontMetric native methods
984 */
985
986 extern "C" {
987
988 JNIEXPORT void JNICALL
989 Java_java_awt_FontMetrics_initIDs(JNIEnv *env, jclass cls)
990 {
991 TRY;
992
993 AwtFont::fontID = env->GetFieldID(cls, "font", "Ljava/awt/Font;");
994 AwtFont::getHeightMID = env->GetMethodID(cls, "getHeight", "()I");
995
996 DASSERT(AwtFont::fontID);
997 DASSERT(AwtFont::getHeightMID);
998
999 CATCH_BAD_ALLOC;
1000 }
1001
1002 } /* extern "C" */
1003
1004 /************************************************************************
1005 * sun.awt.FontDescriptor native methods
1006 */
1007
1008 extern "C" {
1009
1010 JNIEXPORT void JNICALL
1011 Java_sun_awt_FontDescriptor_initIDs(JNIEnv *env, jclass cls)
1012 {
1013 TRY;
1014
1015 AwtFont::nativeNameID = env->GetFieldID(cls, "nativeName",
1016 "Ljava/lang/String;");
1017 AwtFont::useUnicodeID = env->GetFieldID(cls, "useUnicode", "Z");
1018
1019 DASSERT(AwtFont::nativeNameID != NULL);
1020 DASSERT(AwtFont::useUnicodeID != NULL);
1021
1022 CATCH_BAD_ALLOC;
1023 }
1024
1025 } /* extern "C" */
1026
1027
1028 /************************************************************************
1029 * sun.awt.PlatformFont native methods
1030 */
1031
1032 extern "C" {
1033
1034 JNIEXPORT void JNICALL
1035 Java_sun_awt_PlatformFont_initIDs(JNIEnv *env, jclass cls)
1036 {
1037 TRY;
1038
1039 AwtFont::fontConfigID = env->GetFieldID(cls, "fontConfig", "Lsun/awt/FontConfiguration;");
1040 AwtFont::componentFontsID =
1041 env->GetFieldID(cls, "componentFonts", "[Lsun/awt/FontDescriptor;");
1042 AwtFont::makeConvertedMultiFontStringMID =
1043 env->GetMethodID(cls, "makeConvertedMultiFontString",
1044 "(Ljava/lang/String;)[Ljava/lang/Object;");
1045
1046 DASSERT(AwtFont::makeConvertedMultiFontStringMID != NULL);
1047 DASSERT(AwtFont::componentFontsID != NULL);
1048 DASSERT(AwtFont::fontConfigID != NULL);
1049
1050 CATCH_BAD_ALLOC;
1051 }
1052
1053 } /* extern "C" */
1054
1055
1056 /************************************************************************
1057 * sun.awt.windows.WFontPeer native methods
1058 */
1059
1060 extern "C" {
1061
1062 JNIEXPORT void JNICALL
1063 Java_sun_awt_windows_WFontPeer_initIDs(JNIEnv *env, jclass cls)
1064 {
1065 TRY;
1066
1067 AwtFont::textComponentFontNameID = env->GetFieldID(cls, "textComponentFontName", "Ljava/lang/String;");
1068
1069 DASSERT(AwtFont::textComponentFontNameID != NULL);
1070
1845
1846 /*
1847 * !!!!!!!!!!!!!!!!!!!! this does not work. I am not sure why, but
1848 * when active, this will reliably crash HJ, with no hope of debugging
1849 * for java. It doesn't seem to crash the _g version.
1850 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!
1851 *
1852 * I suspect may be running out of C stack: see alloca in
1853 * JNI_GET_STRING, the alloca in it.
1854 *
1855 * (the method is prefixed with XXX so that the linker won't find it) */
1856 JNIEXPORT jboolean JNICALL
1857 Java_sun_awt_windows_WDefaultFontCharset_canConvert(JNIEnv *env, jobject self,
1858 jchar ch)
1859 {
1860 TRY;
1861
1862 static CCombinedSegTableManager tableManager;
1863
1864 jstring fontName = (jstring)env->GetObjectField(self, AwtFont::fontNameID);
1865 DASSERT(fontName != NULL);
1866 LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL);
1867 CCombinedSegTable* pTable = tableManager.GetTable(fontNameW);
1868 JNU_ReleaseStringPlatformChars(env, fontName, fontNameW);
1869 return (pTable->In((USHORT) ch) ? JNI_TRUE : JNI_FALSE);
1870
1871 CATCH_BAD_ALLOC_RET(FALSE);
1872 }
1873
1874 } /* extern "C" */
|
32 #include "java_awt_Font.h"
33 #include "java_awt_FontMetrics.h"
34 #include "java_awt_Dimension.h"
35
36 #include "sun_awt_FontDescriptor.h"
37 #include "sun_awt_windows_WDefaultFontCharset.h"
38 #include "sun_awt_windows_WFontPeer.h"
39 #include "awt_Component.h"
40 #include "Disposer.h"
41
42 /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code.
43 */
44
45 AwtFontCache fontCache;
46
47 extern jboolean IsMultiFont(JNIEnv *env, jobject obj)
48 {
49 if (obj == NULL) {
50 return JNI_FALSE;
51 }
52 if (env->EnsureLocalCapacity(2)) {
53 env->ExceptionClear();
54 return JNI_FALSE;
55 }
56 jobject peer = env->CallObjectMethod(obj, AwtFont::peerMID);
57 env->ExceptionClear();
58 if (peer == NULL) {
59 return JNI_FALSE;
60 }
61 jobject fontConfig = env->GetObjectField(peer, AwtFont::fontConfigID);
62 jboolean result = fontConfig != NULL;
63 env->DeleteLocalRef(peer);
64 env->DeleteLocalRef(fontConfig);
65 return result;
66 }
67
68 extern jstring GetTextComponentFontName(JNIEnv *env, jobject font)
69 {
70 DASSERT(font != NULL);
71 if (env->EnsureLocalCapacity(2)) {
72 env->ExceptionClear();
73 return NULL;
74 }
75 jobject peer = env->CallObjectMethod(font, AwtFont::peerMID);
76 DASSERT(peer != NULL);
77 if (peer == NULL) return NULL;
78 jstring textComponentFontName =
79 (jstring) env->GetObjectField(peer, AwtFont::textComponentFontNameID);
80 env->DeleteLocalRef(peer);
81 return textComponentFontName;
82 }
83
84 /************************************************************************
85 * AwtFont fields
86 */
87
88 /* sun.awt.windows.WFontMetrics fields */
89 jfieldID AwtFont::widthsID;
90 jfieldID AwtFont::ascentID;
91 jfieldID AwtFont::descentID;
92 jfieldID AwtFont::leadingID;
93 jfieldID AwtFont::heightID;
94 jfieldID AwtFont::maxAscentID;
95 jfieldID AwtFont::maxDescentID;
96 jfieldID AwtFont::maxHeightID;
97 jfieldID AwtFont::maxAdvanceID;
179 static void pDataDisposeMethod(JNIEnv *env, jlong pData)
180 {
181 TRY_NO_VERIFY;
182
183 AwtObject::_Dispose((PDATA)pData);
184
185 CATCH_BAD_ALLOC;
186 }
187
188 AwtFont* AwtFont::GetFont(JNIEnv *env, jobject font,
189 jint angle, jfloat awScale)
190 {
191 jlong pData = env->GetLongField(font, AwtFont::pDataID);
192 AwtFont* awtFont = (AwtFont*)jlong_to_ptr(pData);
193
194 if (awtFont != NULL) {
195 return awtFont;
196 }
197
198 awtFont = Create(env, font, angle, awScale);
199 if (awtFont == NULL) {
200 return NULL;
201 }
202
203 env->SetLongField(font, AwtFont::pDataID,
204 reinterpret_cast<jlong>(awtFont));
205 return awtFont;
206 }
207
208 // Get suitable CHARSET from charset string provided by font configuration.
209 static int GetNativeCharset(LPCWSTR name)
210 {
211 if (wcsstr(name, L"ANSI_CHARSET"))
212 return ANSI_CHARSET;
213 if (wcsstr(name, L"DEFAULT_CHARSET"))
214 return DEFAULT_CHARSET;
215 if (wcsstr(name, L"SYMBOL_CHARSET") || wcsstr(name, L"WingDings"))
216 return SYMBOL_CHARSET;
217 if (wcsstr(name, L"SHIFTJIS_CHARSET"))
218 return SHIFTJIS_CHARSET;
219 if (wcsstr(name, L"GB2312_CHARSET"))
220 return GB2312_CHARSET;
221 if (wcsstr(name, L"HANGEUL_CHARSET"))
263 return 0;
264
265 if (IsMultiFont(env, font)) {
266 compFont = GetComponentFonts(env, font);
267 cfnum = env->GetArrayLength(compFont);
268 } else {
269 compFont = NULL;
270 cfnum = 0;
271 }
272
273 LPCWSTR wName;
274
275 awtFont = new AwtFont(cfnum, env, font);
276
277 awtFont->textAngle = angle;
278 awtFont->awScale = awScale;
279
280 if (cfnum > 0) {
281 // Ask peer class for the text component font name
282 jstring jTextComponentFontName = GetTextComponentFontName(env, font);
283 if (jTextComponentFontName == NULL) {
284 return NULL;
285 }
286 LPCWSTR textComponentFontName = JNU_GetStringPlatformChars(env, jTextComponentFontName, NULL);
287
288 awtFont->m_textInput = -1;
289 for (int i = 0; i < cfnum; i++) {
290 // nativeName is a pair of platform fontname and its charset
291 // tied with a comma; "Times New Roman,ANSI_CHARSET".
292 jobject fontDescriptor = env->GetObjectArrayElement(compFont,
293 i);
294 jstring nativeName =
295 (jstring)env->GetObjectField(fontDescriptor,
296 AwtFont::nativeNameID);
297 wName = JNU_GetStringPlatformChars(env, nativeName, NULL);
298 DASSERT(wName);
299 if (wName == NULL) {
300 wName = L"Arial";
301 }
302
303 //On NT platforms, if the font is not Symbol or Dingbats
304 //use "W" version of Win32 APIs directly, info the FontDescription
305 //no need to convert characters from Unicode to locale encodings.
306 if (GetNativeCharset(wName) != SYMBOL_CHARSET) {
307 env->SetBooleanField(fontDescriptor, AwtFont::useUnicodeID, TRUE);
308 }
309
310 // Check to see if this font is suitable for input
311 // on AWT TextComponent
312 if ((awtFont->m_textInput == -1) &&
313 (textComponentFontName != NULL) &&
314 (wcscmp(wName, textComponentFontName) == 0)) {
315 awtFont->m_textInput = i;
316 }
317 HFONT hfonttmp = CreateHFont(const_cast<LPWSTR>(wName), fontStyle, fontSize,
318 angle, awScale);
319 awtFont->m_hFont[i] = hfonttmp;
320
321 JNU_ReleaseStringPlatformChars(env, nativeName, wName);
322
323 env->DeleteLocalRef(fontDescriptor);
324 env->DeleteLocalRef(nativeName);
325 }
326 if (awtFont->m_textInput == -1) {
327 // no text component font was identified, so default
328 // to first component
329 awtFont->m_textInput = 0;
330 }
331
332 JNU_ReleaseStringPlatformChars(env, jTextComponentFontName, textComponentFontName);
333 env->DeleteLocalRef(jTextComponentFontName);
334 } else {
335 // Instantiation for English version.
336 jstring fontName = (jstring)env->GetObjectField(font,
337 AwtFont::nameID);
338 if (fontName != NULL) {
339 wName = JNU_GetStringPlatformChars(env, fontName, NULL);
340 }
341 if (wName == NULL) {
342 wName = L"Arial";
343 }
344
345 WCHAR* wEName;
346 if (!wcscmp(wName, L"Helvetica") || !wcscmp(wName, L"SansSerif")) {
347 wEName = L"Arial";
348 } else if (!wcscmp(wName, L"TimesRoman") ||
349 !wcscmp(wName, L"Serif")) {
350 wEName = L"Times New Roman";
351 } else if (!wcscmp(wName, L"Courier") ||
352 !wcscmp(wName, L"Monospaced")) {
353 wEName = L"Courier New";
354 } else if (!wcscmp(wName, L"Dialog")) {
355 wEName = L"MS Sans Serif";
356 } else if (!wcscmp(wName, L"DialogInput")) {
357 wEName = L"MS Sans Serif";
358 } else if (!wcscmp(wName, L"ZapfDingbats")) {
359 wEName = L"WingDings";
360 } else
361 wEName = L"Arial";
362
363 awtFont->m_textInput = 0;
649 if (str == NULL) {
650 return size;
651 }
652
653 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
654 if (env->EnsureLocalCapacity(3) < 0)
655 return size;
656 jobjectArray array = 0;
657
658 int arrayLength = 0;
659
660 if (env->GetStringLength(str) == 0) {
661 return size;
662 }
663
664 //Init AwtFont object, which will "create" a AwtFont object if necessry,
665 //before calling makeconvertedMultiFontString(), otherwise, the FontDescriptor's
666 //"useUnicode" field might not be initialized correctly (font in Menu Component,
667 //for example").
668 AwtFont* awtFont = AwtFont::GetFont(env, font);
669 if (awtFont == NULL) {
670 return size;
671 }
672
673 if (IsMultiFont(env, font)) {
674 jobject peer = env->CallObjectMethod(font, AwtFont::peerMID);
675 array = (jobjectArray)(env->CallObjectMethod(
676 peer, AwtFont::makeConvertedMultiFontStringMID, str));
677 DASSERT(!safe_ExceptionOccurred(env));
678
679 if (array != NULL) {
680 arrayLength = env->GetArrayLength(array);
681 }
682 env->DeleteLocalRef(peer);
683 } else {
684 array = NULL;
685 arrayLength = 0;
686 }
687
688 HFONT oldFont = (HFONT)::SelectObject(hDC, awtFont->GetHFont());
689
690 if (arrayLength == 0) {
691 int length = env->GetStringLength(str);
692 LPCWSTR strW = JNU_GetStringPlatformChars(env, str, NULL);
693 if (strW == NULL) {
694 return size;
695 }
696 VERIFY(::SelectObject(hDC, awtFont->GetHFont()));
697 if (AwtComponent::GetRTLReadingOrder()){
698 VERIFY(!draw || ::ExtTextOut(hDC, x, y, ETO_RTLREADING, NULL,
699 strW, length, NULL));
700 } else {
701 VERIFY(!draw || ::TextOut(hDC, x, y, strW, length));
702 }
703 VERIFY(::GetTextExtentPoint32(hDC, strW, length, &size));
704 JNU_ReleaseStringPlatformChars(env, str, strW);
705 } else {
706 for (int i = 0; i < arrayLength; i = i + 2) {
707 jobject fontDescriptor = env->GetObjectArrayElement(array, i);
708 if (fontDescriptor == NULL) {
709 break;
710 }
711
712 jbyteArray convertedBytes =
713 (jbyteArray)env->GetObjectArrayElement(array, i + 1);
714 if (convertedBytes == NULL) {
715 env->DeleteLocalRef(fontDescriptor);
716 break;
717 }
718
719 int fdIndex = getFontDescriptorNumber(env, font, fontDescriptor);
720 if (env->ExceptionCheck()) {
721 return size; //fdIndex==0 return could be exception or not.
722 }
723 VERIFY(::SelectObject(hDC, awtFont->GetHFont(fdIndex)));
724
725 /*
726 * The strange-looking code that follows this comment is
727 * the result of upstream optimizations. In the array of
728 * alternating font descriptor and buffers, the buffers
729 * contain their length in the first four bytes, a la
730 * Pascal arrays.
731 *
732 * Note: the buffer MUST be unsigned, or VC++ will sign
733 * extend buflen and bad things will happen.
734 */
735 unsigned char* buffer = NULL;
736 jboolean unicodeUsed =
737 env->GetBooleanField(fontDescriptor, AwtFont::useUnicodeID);
738 try {
739 buffer = (unsigned char *)
740 env->GetPrimitiveArrayCritical(convertedBytes, 0);
741 if (buffer == NULL) {
742 return size;
743 }
744 int buflen = (buffer[0] << 24) | (buffer[1] << 16) |
745 (buffer[2] << 8) | buffer[3];
746
747 DASSERT(buflen >= 0);
748
749 /*
750 * the offsetBuffer, on the other hand, must be signed because
751 * TextOutA and GetTextExtentPoint32A expect it.
752 */
753 char* offsetBuffer = (char *)(buffer + 4);
754
755 if (unicodeUsed) {
756 VERIFY(!draw || ::TextOutW(hDC, x, y, (LPCWSTR)offsetBuffer, buflen / 2));
757 VERIFY(::GetTextExtentPoint32W(hDC, (LPCWSTR)offsetBuffer, buflen / 2, &temp));
758 }
759 else {
760 VERIFY(!draw || ::TextOutA(hDC, x, y, offsetBuffer, buflen));
761 VERIFY(::GetTextExtentPoint32A(hDC, offsetBuffer, buflen, &temp));
762 }
763 } catch (...) {
831 */
832 JNIEXPORT jint JNICALL
833 Java_sun_awt_windows_WFontMetrics_charsWidth(JNIEnv *env, jobject self,
834 jcharArray str,
835 jint off, jint len)
836 {
837 TRY;
838
839 if (str == NULL) {
840 JNU_ThrowNullPointerException(env, "str argument");
841 return NULL;
842 }
843 if ((len < 0) || (off < 0) || (len + off > (env->GetArrayLength(str)))) {
844 JNU_ThrowArrayIndexOutOfBoundsException(env, "off/len argument");
845 return NULL;
846 }
847
848 jchar *strp = new jchar[len];
849 env->GetCharArrayRegion(str, off, len, strp);
850 jstring jstr = env->NewString(strp, len);
851 jint result = 0;
852 if (jstr != NULL) {
853 result = Java_sun_awt_windows_WFontMetrics_stringWidth(env, self,
854 jstr);
855 }
856 delete [] strp;
857 return result;
858
859 CATCH_BAD_ALLOC_RET(0);
860 }
861
862
863 /*
864 * Class: sun_awt_windows_WFontMetrics
865 * Method: bytesWidth
866 * Signature: ([BII)I
867 */
868 JNIEXPORT jint JNICALL
869 Java_sun_awt_windows_WFontMetrics_bytesWidth(JNIEnv *env, jobject self,
870 jbyteArray str,
871 jint off, jint len)
872 {
873 TRY;
874
875 if (str == NULL) {
876 JNU_ThrowNullPointerException(env, "bytes argument");
877 return NULL;
878 }
879 if ((len < 0) || (off < 0) || (len + off > (env->GetArrayLength(str)))) {
880 JNU_ThrowArrayIndexOutOfBoundsException(env, "off or len argument");
881 return NULL;
882 }
883 char *pStrBody = NULL;
884 jint result = 0;
885 try {
886 jintArray array = (jintArray)env->GetObjectField(self,
887 AwtFont::widthsID);
888 if (array == NULL) {
889 JNU_ThrowNullPointerException(env, "Can't access widths array.");
890 return NULL;
891 }
892 pStrBody = (char *)env->GetPrimitiveArrayCritical(str, 0);
893 if (pStrBody == NULL) {
894 JNU_ThrowNullPointerException(env, "Can't access str bytes.");
895 return NULL;
896 }
897 char *pStr = pStrBody + off;
898
899 jint *widths = NULL;
900 try {
901 widths = (jint *)env->GetPrimitiveArrayCritical(array, 0);
902 if (widths == NULL) {
903 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
904 JNU_ThrowNullPointerException(env, "Can't access widths.");
905 return NULL;
906 }
907 for (; len; len--) {
908 result += widths[*pStr++];
909 }
910 } catch (...) {
911 if (widths != NULL) {
912 env->ReleasePrimitiveArrayCritical(array, widths, 0);
913 }
914 throw;
915 }
916
917 env->ReleasePrimitiveArrayCritical(array, widths, 0);
918
919 } catch (...) {
920 if (pStrBody != NULL) {
921 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
922 }
923 throw;
924 }
925
926 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
945 JNU_ThrowNullPointerException(env, "fontMetrics' font");
946 return;
947 }
948 // This local variable is unused. Is there some subtle side-effect here?
949 jlong pData = env->GetLongField(font, AwtFont::pDataID);
950
951 AwtFont::LoadMetrics(env, self);
952
953 CATCH_BAD_ALLOC;
954 }
955
956
957 /*
958 * Class: sun_awt_windows_WFontMetrics
959 * Method: initIDs
960 * Signature: ()V
961 */
962 JNIEXPORT void JNICALL
963 Java_sun_awt_windows_WFontMetrics_initIDs(JNIEnv *env, jclass cls)
964 {
965 CHECK_NULL(AwtFont::widthsID = env->GetFieldID(cls, "widths", "[I"));
966 CHECK_NULL(AwtFont::ascentID = env->GetFieldID(cls, "ascent", "I"));
967 CHECK_NULL(AwtFont::descentID = env->GetFieldID(cls, "descent", "I"));
968 CHECK_NULL(AwtFont::leadingID = env->GetFieldID(cls, "leading", "I"));
969 CHECK_NULL(AwtFont::heightID = env->GetFieldID(cls, "height", "I"));
970 CHECK_NULL(AwtFont::maxAscentID = env->GetFieldID(cls, "maxAscent", "I"));
971 CHECK_NULL(AwtFont::maxDescentID = env->GetFieldID(cls, "maxDescent", "I"));
972 CHECK_NULL(AwtFont::maxHeightID = env->GetFieldID(cls, "maxHeight", "I"));
973 AwtFont::maxAdvanceID = env->GetFieldID(cls, "maxAdvance", "I");
974 }
975
976 } /* extern "C" */
977
978
979 /************************************************************************
980 * java.awt.Font native methods
981 */
982
983 extern "C" {
984
985 JNIEXPORT void JNICALL
986 Java_java_awt_Font_initIDs(JNIEnv *env, jclass cls)
987 {
988 CHECK_NULL(AwtFont::peerMID = env->GetMethodID(cls, "getPeer",
989 "()Ljava/awt/peer/FontPeer;"));
990 CHECK_NULL(AwtFont::pDataID = env->GetFieldID(cls, "pData", "J"));
991 CHECK_NULL(AwtFont::nameID =
992 env->GetFieldID(cls, "name", "Ljava/lang/String;"));
993 CHECK_NULL(AwtFont::sizeID = env->GetFieldID(cls, "size", "I"));
994 CHECK_NULL(AwtFont::styleID = env->GetFieldID(cls, "style", "I"));
995 AwtFont::getFontMID =
996 env->GetStaticMethodID(cls, "getFont",
997 "(Ljava/lang/String;)Ljava/awt/Font;");
998 }
999
1000 } /* extern "C" */
1001
1002
1003 /************************************************************************
1004 * java.awt.FontMetric native methods
1005 */
1006
1007 extern "C" {
1008
1009 JNIEXPORT void JNICALL
1010 Java_java_awt_FontMetrics_initIDs(JNIEnv *env, jclass cls)
1011 {
1012 CHECK_NULL(AwtFont::fontID =
1013 env->GetFieldID(cls, "font", "Ljava/awt/Font;"));
1014 AwtFont::getHeightMID = env->GetMethodID(cls, "getHeight", "()I");
1015 }
1016
1017 } /* extern "C" */
1018
1019 /************************************************************************
1020 * sun.awt.FontDescriptor native methods
1021 */
1022
1023 extern "C" {
1024
1025 JNIEXPORT void JNICALL
1026 Java_sun_awt_FontDescriptor_initIDs(JNIEnv *env, jclass cls)
1027 {
1028 CHECK_NULL(AwtFont::nativeNameID =
1029 env->GetFieldID(cls, "nativeName", "Ljava/lang/String;"));
1030 AwtFont::useUnicodeID = env->GetFieldID(cls, "useUnicode", "Z");
1031
1032 }
1033
1034 } /* extern "C" */
1035
1036
1037 /************************************************************************
1038 * sun.awt.PlatformFont native methods
1039 */
1040
1041 extern "C" {
1042
1043 JNIEXPORT void JNICALL
1044 Java_sun_awt_PlatformFont_initIDs(JNIEnv *env, jclass cls)
1045 {
1046 CHECK_NULL(AwtFont::fontConfigID =
1047 env->GetFieldID(cls, "fontConfig", "Lsun/awt/FontConfiguration;"));
1048 CHECK_NULL(AwtFont::componentFontsID =
1049 env->GetFieldID(cls, "componentFonts", "[Lsun/awt/FontDescriptor;"));
1050 AwtFont::makeConvertedMultiFontStringMID =
1051 env->GetMethodID(cls, "makeConvertedMultiFontString",
1052 "(Ljava/lang/String;)[Ljava/lang/Object;");
1053 }
1054
1055 } /* extern "C" */
1056
1057
1058 /************************************************************************
1059 * sun.awt.windows.WFontPeer native methods
1060 */
1061
1062 extern "C" {
1063
1064 JNIEXPORT void JNICALL
1065 Java_sun_awt_windows_WFontPeer_initIDs(JNIEnv *env, jclass cls)
1066 {
1067 TRY;
1068
1069 AwtFont::textComponentFontNameID = env->GetFieldID(cls, "textComponentFontName", "Ljava/lang/String;");
1070
1071 DASSERT(AwtFont::textComponentFontNameID != NULL);
1072
1847
1848 /*
1849 * !!!!!!!!!!!!!!!!!!!! this does not work. I am not sure why, but
1850 * when active, this will reliably crash HJ, with no hope of debugging
1851 * for java. It doesn't seem to crash the _g version.
1852 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!
1853 *
1854 * I suspect may be running out of C stack: see alloca in
1855 * JNI_GET_STRING, the alloca in it.
1856 *
1857 * (the method is prefixed with XXX so that the linker won't find it) */
1858 JNIEXPORT jboolean JNICALL
1859 Java_sun_awt_windows_WDefaultFontCharset_canConvert(JNIEnv *env, jobject self,
1860 jchar ch)
1861 {
1862 TRY;
1863
1864 static CCombinedSegTableManager tableManager;
1865
1866 jstring fontName = (jstring)env->GetObjectField(self, AwtFont::fontNameID);
1867 DASSERT(fontName != NULL); // leave in for debug mode.
1868 CHECK_NULL_RETURN(fontName, FALSE); // in production, just return
1869 LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL);
1870 CHECK_NULL_RETURN(fontNameW, FALSE);
1871 CCombinedSegTable* pTable = tableManager.GetTable(fontNameW);
1872 JNU_ReleaseStringPlatformChars(env, fontName, fontNameW);
1873 return (pTable->In((USHORT) ch) ? JNI_TRUE : JNI_FALSE);
1874
1875 CATCH_BAD_ALLOC_RET(FALSE);
1876 }
1877
1878 } /* extern "C" */
|