381 throw;
382 }
383
384 env->DeleteLocalRef(compFont);
385 return awtFont;
386 }
387
388 static void strip_tail(wchar_t* text, wchar_t* tail) { // strips tail and any possible whitespace before it from the end of text
389 if (wcslen(text)<=wcslen(tail)) {
390 return;
391 }
392 wchar_t* p = text+wcslen(text)-wcslen(tail);
393 if (!wcscmp(p, tail)) {
394 while(p>text && iswspace(*(p-1)))
395 p--;
396 *p = 0;
397 }
398
399 }
400
401 static HFONT CreateHFont_sub(LPCWSTR name, int style, int height,
402 int angle=0, float awScale=1.0f)
403 {
404 LOGFONTW logFont;
405
406 logFont.lfWidth = 0;
407 logFont.lfEscapement = angle;
408 logFont.lfOrientation = angle;
409 logFont.lfUnderline = FALSE;
410 logFont.lfStrikeOut = FALSE;
411 logFont.lfCharSet = GetNativeCharset(name);
412 if (angle == 0 && awScale == 1.0f) {
413 logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
414 } else {
415 logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
416 }
417 logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
418 logFont.lfQuality = DEFAULT_QUALITY;
419 logFont.lfPitchAndFamily = DEFAULT_PITCH;
420
421 // Set style
422 logFont.lfWeight = (style & java_awt_Font_BOLD) ? FW_BOLD : FW_NORMAL;
423 logFont.lfItalic = (style & java_awt_Font_ITALIC) != 0;
424 logFont.lfUnderline = 0;//(style & java_awt_Font_UNDERLINE) != 0;
425
426 // Get point size
427 logFont.lfHeight = -height;
428
429 // Set font name
430 WCHAR tmpname[80];
431 wcscpy(tmpname, name);
432 WCHAR* delimit = wcschr(tmpname, L',');
433 if (delimit != NULL)
434 *delimit = L'\0'; // terminate the string after the font name.
435 // strip "Bold" and "Italic" from the end of the name
436 strip_tail(tmpname,L""); //strip possible trailing whitespace
437 strip_tail(tmpname,L"Italic");
438 strip_tail(tmpname,L"Bold");
439 wcscpy(&(logFont.lfFaceName[0]), tmpname);
440 HFONT hFont = ::CreateFontIndirect(&logFont);
441 DASSERT(hFont != NULL);
442 // get a expanded or condensed version if its specified.
443 if (awScale != 1.0f) {
444 HDC hDC = ::GetDC(0);
445 HFONT oldFont = (HFONT)::SelectObject(hDC, hFont);
446 TEXTMETRIC tm;
447 DWORD avgWidth;
448 GetTextMetrics(hDC, &tm);
449 oldFont = (HFONT)::SelectObject(hDC, oldFont);
450 if (oldFont != NULL) { // should be the same as hFont
451 VERIFY(::DeleteObject(oldFont));
452 }
453 avgWidth = tm.tmAveCharWidth;
454 logFont.lfWidth = (LONG)((fabs)(avgWidth*awScale));
455 hFont = ::CreateFontIndirect(&logFont);
456 DASSERT(hFont != NULL);
457 VERIFY(::ReleaseDC(0, hDC));
458 }
459
460 return hFont;
461 }
462
463 HFONT AwtFont::CreateHFont(WCHAR* name, int style, int height,
464 int angle, float awScale)
465 {
466 WCHAR longName[80];
467 // 80 > (max face name(=30) + strlen("CHINESEBIG5_CHARSET"))
468 // longName doesn't have to be printable. So, it is OK not to convert.
469
470 wsprintf(longName, L"%ls-%d-%d", name, style, height);
471
472 HFONT hFont = NULL;
473
474 // only cache & share unrotated, unexpanded/uncondensed fonts
518 jobject font = env->GetObjectField(fontMetrics, AwtFont::fontID);
519 AwtFont* awtFont = AwtFont::GetFont(env, font);
520
521 if (!awtFont) {
522 /* failed to get font */
523 return;
524 }
525
526 HDC hDC = ::GetDC(0);
527 DASSERT(hDC != NULL);
528
529 HGDIOBJ oldFont = ::SelectObject(hDC, awtFont->GetHFont());
530 TEXTMETRIC metrics;
531 VERIFY(::GetTextMetrics(hDC, &metrics));
532
533 awtFont->m_ascent = metrics.tmAscent;
534
535 int ascent = metrics.tmAscent;
536 int descent = metrics.tmDescent;
537 int leading = metrics.tmExternalLeading;
538 env->SetIntField(fontMetrics, AwtFont::ascentID, ascent);
539 env->SetIntField(fontMetrics, AwtFont::descentID, descent);
540 env->SetIntField(fontMetrics, AwtFont::leadingID, leading);
541 env->SetIntField(fontMetrics, AwtFont::heightID, metrics.tmAscent +
542 metrics.tmDescent + leading);
543 env->SetIntField(fontMetrics, AwtFont::maxAscentID, ascent);
544 env->SetIntField(fontMetrics, AwtFont::maxDescentID, descent);
545
546 int maxHeight = ascent + descent + leading;
547 env->SetIntField(fontMetrics, AwtFont::maxHeightID, maxHeight);
548
549 int maxAdvance = metrics.tmMaxCharWidth;
550 env->SetIntField(fontMetrics, AwtFont::maxAdvanceID, maxAdvance);
551
552 awtFont->m_overhang = metrics.tmOverhang;
553
554 jint intWidths[256];
555 memset(intWidths, 0, 256 * sizeof(int));
556 VERIFY(::GetCharWidth(hDC, metrics.tmFirstChar,
557 min(metrics.tmLastChar, 255),
558 (int *)&intWidths[metrics.tmFirstChar]));
559 env->SetIntArrayRegion(widths, 0, 256, intWidths);
560 env->SetObjectField(fontMetrics, AwtFont::widthsID, widths);
561
562 // Get font metrics on remaining fonts (if multifont).
563 for (int j = 1; j < awtFont->GetHFontNum(); j++) {
564 ::SelectObject(hDC, awtFont->GetHFont(j));
565 VERIFY(::GetTextMetrics(hDC, &metrics));
566 env->SetIntField(fontMetrics, AwtFont::maxAscentID,
567 ascent = max(ascent, metrics.tmAscent));
568 env->SetIntField(fontMetrics, AwtFont::maxDescentID,
569 descent = max(descent, metrics.tmDescent));
570 env->SetIntField(fontMetrics, AwtFont::maxHeightID,
801 /*
802 * Class: sun_awt_windows_WFontMetrics
803 * Method: stringWidth
804 * Signature: (Ljava/lang/String;)I
805 */
806 JNIEXPORT jint JNICALL
807 Java_sun_awt_windows_WFontMetrics_stringWidth(JNIEnv *env, jobject self,
808 jstring str)
809 {
810 TRY;
811
812 if (str == NULL) {
813 JNU_ThrowNullPointerException(env, "str argument");
814 return NULL;
815 }
816 HDC hDC = ::GetDC(0); DASSERT(hDC != NULL);
817
818 jobject font = env->GetObjectField(self, AwtFont::fontID);
819
820 long ret = AwtFont::getMFStringWidth(hDC, font, str);
821 VERIFY(::ReleaseDC(0, hDC));
822 return ret;
823
824 CATCH_BAD_ALLOC_RET(0);
825 }
826
827 /*
828 * Class: sun_awt_windows_WFontMetrics
829 * Method: charsWidth
830 * Signature: ([CII)I
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");
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);
927 return result;
928
929 CATCH_BAD_ALLOC_RET(0);
930 }
931
932
933 /*
934 * Class: sun_awt_windows_WFontMetrics
935 * Method: init
936 * Signature: ()V
937 */
938 JNIEXPORT void JNICALL
939 Java_sun_awt_windows_WFontMetrics_init(JNIEnv *env, jobject self)
940 {
941 TRY;
942
943 jobject font = env->GetObjectField(self, AwtFont::fontID);
944 if (font == NULL) {
945 JNU_ThrowNullPointerException(env, "fontMetrics' font");
946 return;
947 }
|
381 throw;
382 }
383
384 env->DeleteLocalRef(compFont);
385 return awtFont;
386 }
387
388 static void strip_tail(wchar_t* text, wchar_t* tail) { // strips tail and any possible whitespace before it from the end of text
389 if (wcslen(text)<=wcslen(tail)) {
390 return;
391 }
392 wchar_t* p = text+wcslen(text)-wcslen(tail);
393 if (!wcscmp(p, tail)) {
394 while(p>text && iswspace(*(p-1)))
395 p--;
396 *p = 0;
397 }
398
399 }
400
401 static int ScaleUpX(float x) {
402 int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
403 ::GetDesktopWindow());
404 Devices::InstanceAccess devices;
405 AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
406 return device == NULL ? x : device->ScaleUpX(x);
407 }
408
409 static int ScaleUpY(int y) {
410 int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
411 ::GetDesktopWindow());
412 Devices::InstanceAccess devices;
413 AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
414 return device == NULL ? y : device->ScaleUpY(y);
415 }
416
417 static int ScaleDownX(int x) {
418 int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
419 ::GetDesktopWindow());
420 Devices::InstanceAccess devices;
421 AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
422 return device == NULL ? x : device->ScaleDownX(x);
423 }
424
425 static int ScaleDownY(int y) {
426 int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
427 ::GetDesktopWindow());
428 Devices::InstanceAccess devices;
429 AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
430 return device == NULL ? y : device->ScaleDownY(y);
431 }
432
433 static HFONT CreateHFont_sub(LPCWSTR name, int style, int height,
434 int angle=0, float awScale=1.0f)
435 {
436 LOGFONTW logFont;
437
438 logFont.lfWidth = 0;
439 logFont.lfEscapement = angle;
440 logFont.lfOrientation = angle;
441 logFont.lfUnderline = FALSE;
442 logFont.lfStrikeOut = FALSE;
443 logFont.lfCharSet = GetNativeCharset(name);
444 if (angle == 0 && awScale == 1.0f) {
445 logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
446 } else {
447 logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
448 }
449 logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
450 logFont.lfQuality = DEFAULT_QUALITY;
451 logFont.lfPitchAndFamily = DEFAULT_PITCH;
452
453 // Set style
454 logFont.lfWeight = (style & java_awt_Font_BOLD) ? FW_BOLD : FW_NORMAL;
455 logFont.lfItalic = (style & java_awt_Font_ITALIC) != 0;
456 logFont.lfUnderline = 0;//(style & java_awt_Font_UNDERLINE) != 0;
457
458 // Get point size
459 logFont.lfHeight = ScaleUpY(-height);
460
461 // Set font name
462 WCHAR tmpname[80];
463 wcscpy(tmpname, name);
464 WCHAR* delimit = wcschr(tmpname, L',');
465 if (delimit != NULL)
466 *delimit = L'\0'; // terminate the string after the font name.
467 // strip "Bold" and "Italic" from the end of the name
468 strip_tail(tmpname,L""); //strip possible trailing whitespace
469 strip_tail(tmpname,L"Italic");
470 strip_tail(tmpname,L"Bold");
471 wcscpy(&(logFont.lfFaceName[0]), tmpname);
472 HFONT hFont = ::CreateFontIndirect(&logFont);
473 DASSERT(hFont != NULL);
474 // get a expanded or condensed version if its specified.
475 if (awScale != 1.0f) {
476 HDC hDC = ::GetDC(0);
477 HFONT oldFont = (HFONT)::SelectObject(hDC, hFont);
478 TEXTMETRIC tm;
479 DWORD avgWidth;
480 GetTextMetrics(hDC, &tm);
481 oldFont = (HFONT)::SelectObject(hDC, oldFont);
482 if (oldFont != NULL) { // should be the same as hFont
483 VERIFY(::DeleteObject(oldFont));
484 }
485 avgWidth = tm.tmAveCharWidth;
486 logFont.lfWidth = (LONG) ScaleUpX((fabs) (avgWidth * awScale));
487 hFont = ::CreateFontIndirect(&logFont);
488 DASSERT(hFont != NULL);
489 VERIFY(::ReleaseDC(0, hDC));
490 }
491
492 return hFont;
493 }
494
495 HFONT AwtFont::CreateHFont(WCHAR* name, int style, int height,
496 int angle, float awScale)
497 {
498 WCHAR longName[80];
499 // 80 > (max face name(=30) + strlen("CHINESEBIG5_CHARSET"))
500 // longName doesn't have to be printable. So, it is OK not to convert.
501
502 wsprintf(longName, L"%ls-%d-%d", name, style, height);
503
504 HFONT hFont = NULL;
505
506 // only cache & share unrotated, unexpanded/uncondensed fonts
550 jobject font = env->GetObjectField(fontMetrics, AwtFont::fontID);
551 AwtFont* awtFont = AwtFont::GetFont(env, font);
552
553 if (!awtFont) {
554 /* failed to get font */
555 return;
556 }
557
558 HDC hDC = ::GetDC(0);
559 DASSERT(hDC != NULL);
560
561 HGDIOBJ oldFont = ::SelectObject(hDC, awtFont->GetHFont());
562 TEXTMETRIC metrics;
563 VERIFY(::GetTextMetrics(hDC, &metrics));
564
565 awtFont->m_ascent = metrics.tmAscent;
566
567 int ascent = metrics.tmAscent;
568 int descent = metrics.tmDescent;
569 int leading = metrics.tmExternalLeading;
570
571 env->SetIntField(fontMetrics, AwtFont::ascentID, ScaleDownY(ascent));
572 env->SetIntField(fontMetrics, AwtFont::descentID, ScaleDownY(descent));
573 env->SetIntField(fontMetrics, AwtFont::leadingID, ScaleDownX(leading));
574 env->SetIntField(fontMetrics, AwtFont::heightID,
575 ScaleDownY(metrics.tmAscent + metrics.tmDescent + leading));
576 env->SetIntField(fontMetrics, AwtFont::maxAscentID, ScaleDownY(ascent));
577 env->SetIntField(fontMetrics, AwtFont::maxDescentID, ScaleDownY(descent));
578
579 int maxHeight = ascent + descent + leading;
580 env->SetIntField(fontMetrics, AwtFont::maxHeightID, ScaleDownY(maxHeight));
581
582 int maxAdvance = metrics.tmMaxCharWidth;
583 env->SetIntField(fontMetrics, AwtFont::maxAdvanceID, ScaleDownX(maxAdvance));
584
585 awtFont->m_overhang = metrics.tmOverhang;
586
587 jint intWidths[256];
588 memset(intWidths, 0, 256 * sizeof(int));
589 VERIFY(::GetCharWidth(hDC, metrics.tmFirstChar,
590 min(metrics.tmLastChar, 255),
591 (int *)&intWidths[metrics.tmFirstChar]));
592 env->SetIntArrayRegion(widths, 0, 256, intWidths);
593 env->SetObjectField(fontMetrics, AwtFont::widthsID, widths);
594
595 // Get font metrics on remaining fonts (if multifont).
596 for (int j = 1; j < awtFont->GetHFontNum(); j++) {
597 ::SelectObject(hDC, awtFont->GetHFont(j));
598 VERIFY(::GetTextMetrics(hDC, &metrics));
599 env->SetIntField(fontMetrics, AwtFont::maxAscentID,
600 ascent = max(ascent, metrics.tmAscent));
601 env->SetIntField(fontMetrics, AwtFont::maxDescentID,
602 descent = max(descent, metrics.tmDescent));
603 env->SetIntField(fontMetrics, AwtFont::maxHeightID,
834 /*
835 * Class: sun_awt_windows_WFontMetrics
836 * Method: stringWidth
837 * Signature: (Ljava/lang/String;)I
838 */
839 JNIEXPORT jint JNICALL
840 Java_sun_awt_windows_WFontMetrics_stringWidth(JNIEnv *env, jobject self,
841 jstring str)
842 {
843 TRY;
844
845 if (str == NULL) {
846 JNU_ThrowNullPointerException(env, "str argument");
847 return NULL;
848 }
849 HDC hDC = ::GetDC(0); DASSERT(hDC != NULL);
850
851 jobject font = env->GetObjectField(self, AwtFont::fontID);
852
853 long ret = AwtFont::getMFStringWidth(hDC, font, str);
854 ret = ScaleDownX(ret);
855 VERIFY(::ReleaseDC(0, hDC));
856 return ret;
857
858 CATCH_BAD_ALLOC_RET(0);
859 }
860
861 /*
862 * Class: sun_awt_windows_WFontMetrics
863 * Method: charsWidth
864 * Signature: ([CII)I
865 */
866 JNIEXPORT jint JNICALL
867 Java_sun_awt_windows_WFontMetrics_charsWidth(JNIEnv *env, jobject self,
868 jcharArray str,
869 jint off, jint len)
870 {
871 TRY;
872
873 if (str == NULL) {
874 JNU_ThrowNullPointerException(env, "str argument");
941 for (; len; len--) {
942 result += widths[*pStr++];
943 }
944 } catch (...) {
945 if (widths != NULL) {
946 env->ReleasePrimitiveArrayCritical(array, widths, 0);
947 }
948 throw;
949 }
950
951 env->ReleasePrimitiveArrayCritical(array, widths, 0);
952
953 } catch (...) {
954 if (pStrBody != NULL) {
955 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
956 }
957 throw;
958 }
959
960 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
961 return ScaleDownX(result);
962
963 CATCH_BAD_ALLOC_RET(0);
964 }
965
966
967 /*
968 * Class: sun_awt_windows_WFontMetrics
969 * Method: init
970 * Signature: ()V
971 */
972 JNIEXPORT void JNICALL
973 Java_sun_awt_windows_WFontMetrics_init(JNIEnv *env, jobject self)
974 {
975 TRY;
976
977 jobject font = env->GetObjectField(self, AwtFont::fontID);
978 if (font == NULL) {
979 JNU_ThrowNullPointerException(env, "fontMetrics' font");
980 return;
981 }
|