src/windows/native/sun/windows/awt_Font.cpp

Print this page




  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" */