1 /*
2 * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 #include "awt.h"
27 #include <math.h>
28 #include "jlong.h"
29 #include "awt_Font.h"
30 #include "awt_Toolkit.h"
31
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
IsMultiFont(JNIEnv * env,jobject obj)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
GetTextComponentFontName(JNIEnv * env,jobject font)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;
98
99 /* java.awt.FontDescriptor fields */
100 jfieldID AwtFont::nativeNameID;
101 jfieldID AwtFont::useUnicodeID;
102
103 /* java.awt.Font fields */
104 jfieldID AwtFont::pDataID;
105 jfieldID AwtFont::nameID;
106 jfieldID AwtFont::sizeID;
107 jfieldID AwtFont::styleID;
108
109 /* java.awt.FontMetrics fields */
110 jfieldID AwtFont::fontID;
111
112 /* sun.awt.PlatformFont fields */
113 jfieldID AwtFont::fontConfigID;
114 jfieldID AwtFont::componentFontsID;
115
116 /* sun.awt.windows.WFontPeer fields */
117 jfieldID AwtFont::textComponentFontNameID;
118
119 /* sun.awt.windows.WDefaultFontCharset fields */
120 jfieldID AwtFont::fontNameID;
121
122 /* java.awt.Font methods */
123 jmethodID AwtFont::peerMID;
124
125 /* sun.awt.PlatformFont methods */
126 jmethodID AwtFont::makeConvertedMultiFontStringMID;
127
128 /* sun.awt.PlatformFont methods */
129 jmethodID AwtFont::getFontMID;
130
131 /* java.awt.FontMetrics methods */
132 jmethodID AwtFont::getHeightMID;
133
134
135 /************************************************************************
136 * AwtFont methods
137 */
AwtFont(int num,JNIEnv * env,jobject javaFont)138 AwtFont::AwtFont(int num, JNIEnv *env, jobject javaFont)
139 {
140 if (num == 0) { // not multi-font
141 num = 1;
142 }
143
144 m_hFontNum = num;
145 m_hFont = new HFONT[num];
146
147 for (int i = 0; i < num; i++) {
148 m_hFont[i] = NULL;
149 }
150
151 m_textInput = -1;
152 m_ascent = -1;
153 m_overhang = 0;
154 }
155
~AwtFont()156 AwtFont::~AwtFont()
157 {
158 delete[] m_hFont;
159 }
160
Dispose()161 void AwtFont::Dispose() {
162 for (int i = 0; i < m_hFontNum; i++) {
163 HFONT font = m_hFont[i];
164 if (font != NULL && fontCache.Search(font)) {
165 fontCache.Remove(font);
166 /* NOTE: delete of windows HFONT happens in FontCache::Remove
167 only when the final reference to the font is disposed */
168 } else if (font != NULL) {
169 // if font was not in cache, its not shared and we delete it now
170 DASSERT(::GetObjectType(font) == OBJ_FONT);
171 VERIFY(::DeleteObject(font));
172 }
173 m_hFont[i] = NULL;
174 }
175
176 AwtObject::Dispose();
177 }
178
pDataDisposeMethod(JNIEnv * env,jlong pData)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
GetFont(JNIEnv * env,jobject font,jint angle,jfloat awScale)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.
GetNativeCharset(LPCWSTR name)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"))
222 return HANGEUL_CHARSET;
223 if (wcsstr(name, L"CHINESEBIG5_CHARSET"))
224 return CHINESEBIG5_CHARSET;
225 if (wcsstr(name, L"OEM_CHARSET"))
226 return OEM_CHARSET;
227 if (wcsstr(name, L"JOHAB_CHARSET"))
228 return JOHAB_CHARSET;
229 if (wcsstr(name, L"HEBREW_CHARSET"))
230 return HEBREW_CHARSET;
231 if (wcsstr(name, L"ARABIC_CHARSET"))
232 return ARABIC_CHARSET;
233 if (wcsstr(name, L"GREEK_CHARSET"))
234 return GREEK_CHARSET;
235 if (wcsstr(name, L"TURKISH_CHARSET"))
236 return TURKISH_CHARSET;
237 if (wcsstr(name, L"VIETNAMESE_CHARSET"))
238 return VIETNAMESE_CHARSET;
239 if (wcsstr(name, L"THAI_CHARSET"))
240 return THAI_CHARSET;
241 if (wcsstr(name, L"EASTEUROPE_CHARSET"))
242 return EASTEUROPE_CHARSET;
243 if (wcsstr(name, L"RUSSIAN_CHARSET"))
244 return RUSSIAN_CHARSET;
245 if (wcsstr(name, L"MAC_CHARSET"))
246 return MAC_CHARSET;
247 if (wcsstr(name, L"BALTIC_CHARSET"))
248 return BALTIC_CHARSET;
249 return ANSI_CHARSET;
250 }
251
Create(JNIEnv * env,jobject font,jint angle,jfloat awScale)252 AwtFont* AwtFont::Create(JNIEnv *env, jobject font, jint angle, jfloat awScale)
253 {
254 int fontSize = env->GetIntField(font, AwtFont::sizeID);
255 int fontStyle = env->GetIntField(font, AwtFont::styleID);
256
257 AwtFont* awtFont = NULL;
258 jobjectArray compFont = NULL;
259 int cfnum = 0;
260
261 try {
262 if (env->EnsureLocalCapacity(3) < 0)
263 return 0;
264
265 if (IsMultiFont(env, font)) {
266 compFont = GetComponentFonts(env, font);
267 if (compFont != NULL) {
268 cfnum = env->GetArrayLength(compFont);
269 }
270 } else {
271 compFont = NULL;
272 cfnum = 0;
273 }
274
275 LPCWSTR wName = NULL;
276
277 awtFont = new AwtFont(cfnum, env, font);
278
279 awtFont->textAngle = angle;
280 awtFont->awScale = awScale;
281
282 if (cfnum > 0) {
283 // Ask peer class for the text component font name
284 jstring jTextComponentFontName = GetTextComponentFontName(env, font);
285 if (jTextComponentFontName == NULL) {
286 delete awtFont;
287 return NULL;
288 }
289 LPCWSTR textComponentFontName = JNU_GetStringPlatformChars(env, jTextComponentFontName, NULL);
290
291 awtFont->m_textInput = -1;
292 for (int i = 0; i < cfnum; i++) {
293 // nativeName is a pair of platform fontname and its charset
294 // tied with a comma; "Times New Roman,ANSI_CHARSET".
295 jobject fontDescriptor = env->GetObjectArrayElement(compFont,
296 i);
297 jstring nativeName =
298 (jstring)env->GetObjectField(fontDescriptor,
299 AwtFont::nativeNameID);
300 wName = JNU_GetStringPlatformChars(env, nativeName, NULL);
301 DASSERT(wName);
302 if (wName == NULL) {
303 wName = L"Arial";
304 }
305
306 //On NT platforms, if the font is not Symbol or Dingbats
307 //use "W" version of Win32 APIs directly, info the FontDescription
308 //no need to convert characters from Unicode to locale encodings.
309 if (GetNativeCharset(wName) != SYMBOL_CHARSET) {
310 env->SetBooleanField(fontDescriptor, AwtFont::useUnicodeID, TRUE);
311 }
312
313 // Check to see if this font is suitable for input
314 // on AWT TextComponent
315 if ((awtFont->m_textInput == -1) &&
316 (textComponentFontName != NULL) &&
317 (wcscmp(wName, textComponentFontName) == 0)) {
318 awtFont->m_textInput = i;
319 }
320 HFONT hfonttmp = CreateHFont(const_cast<LPWSTR>(wName), fontStyle, fontSize,
321 angle, awScale);
322 awtFont->m_hFont[i] = hfonttmp;
323
324 JNU_ReleaseStringPlatformChars(env, nativeName, wName);
325
326 env->DeleteLocalRef(fontDescriptor);
327 env->DeleteLocalRef(nativeName);
328 }
329 if (awtFont->m_textInput == -1) {
330 // no text component font was identified, so default
331 // to first component
332 awtFont->m_textInput = 0;
333 }
334
335 JNU_ReleaseStringPlatformChars(env, jTextComponentFontName, textComponentFontName);
336 env->DeleteLocalRef(jTextComponentFontName);
337 } else {
338 // Instantiation for English version.
339 jstring fontName = (jstring)env->GetObjectField(font,
340 AwtFont::nameID);
341 if (fontName != NULL) {
342 wName = JNU_GetStringPlatformChars(env, fontName, NULL);
343 }
344 if (wName == NULL) {
345 wName = L"Arial";
346 }
347
348 WCHAR* wEName;
349 if (!wcscmp(wName, L"Helvetica") || !wcscmp(wName, L"SansSerif")) {
350 wEName = L"Arial";
351 } else if (!wcscmp(wName, L"TimesRoman") ||
352 !wcscmp(wName, L"Serif")) {
353 wEName = L"Times New Roman";
354 } else if (!wcscmp(wName, L"Courier") ||
355 !wcscmp(wName, L"Monospaced")) {
356 wEName = L"Courier New";
357 } else if (!wcscmp(wName, L"Dialog")) {
358 wEName = L"MS Sans Serif";
359 } else if (!wcscmp(wName, L"DialogInput")) {
360 wEName = L"MS Sans Serif";
361 } else if (!wcscmp(wName, L"ZapfDingbats")) {
362 wEName = L"WingDings";
363 } else
364 wEName = L"Arial";
365
366 awtFont->m_textInput = 0;
367 awtFont->m_hFont[0] = CreateHFont(wEName, fontStyle, fontSize,
368 angle, awScale);
369
370 JNU_ReleaseStringPlatformChars(env, fontName, wName);
371
372 env->DeleteLocalRef(fontName);
373 }
374 /* The several callers of this method also set the pData field.
375 * That's unnecessary but harmless duplication. However we definitely
376 * want only one disposer record.
377 */
378 env->SetLongField(font, AwtFont::pDataID,
379 reinterpret_cast<jlong>(awtFont));
380 Disposer_AddRecord(env, font, pDataDisposeMethod,
381 reinterpret_cast<jlong>(awtFont));
382 } catch (...) {
383 env->DeleteLocalRef(compFont);
384 throw;
385 }
386
387 env->DeleteLocalRef(compFont);
388 return awtFont;
389 }
390
strip_tail(wchar_t * text,wchar_t * tail)391 static void strip_tail(wchar_t* text, wchar_t* tail) { // strips tail and any possible whitespace before it from the end of text
392 if (wcslen(text)<=wcslen(tail)) {
393 return;
394 }
395 wchar_t* p = text+wcslen(text)-wcslen(tail);
396 if (!wcscmp(p, tail)) {
397 while(p>text && iswspace(*(p-1)))
398 p--;
399 *p = 0;
400 }
401
402 }
403
ScaleUpX(float x)404 static int ScaleUpX(float x) {
405 int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
406 ::GetDesktopWindow());
407 Devices::InstanceAccess devices;
408 AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
409 return device == NULL ? x : device->ScaleUpX(x);
410 }
411
ScaleUpY(int y)412 static int ScaleUpY(int y) {
413 int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
414 ::GetDesktopWindow());
415 Devices::InstanceAccess devices;
416 AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
417 return device == NULL ? y : device->ScaleUpY(y);
418 }
419
ScaleDownX(int x)420 static int ScaleDownX(int x) {
421 int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
422 ::GetDesktopWindow());
423 Devices::InstanceAccess devices;
424 AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
425 return device == NULL ? x : device->ScaleDownX(x);
426 }
427
ScaleDownY(int y)428 static int ScaleDownY(int y) {
429 int deviceIndex = AwtWin32GraphicsDevice::DeviceIndexForWindow(
430 ::GetDesktopWindow());
431 Devices::InstanceAccess devices;
432 AwtWin32GraphicsDevice *device = devices->GetDevice(deviceIndex);
433 return device == NULL ? y : device->ScaleDownY(y);
434 }
435
CreateHFont_sub(LPCWSTR name,int style,int height,int angle=0,float awScale=1.0f)436 static HFONT CreateHFont_sub(LPCWSTR name, int style, int height,
437 int angle=0, float awScale=1.0f)
438 {
439 LOGFONTW logFont;
440
441 logFont.lfWidth = 0;
442 logFont.lfEscapement = angle;
443 logFont.lfOrientation = angle;
444 logFont.lfUnderline = FALSE;
445 logFont.lfStrikeOut = FALSE;
446 logFont.lfCharSet = GetNativeCharset(name);
447 if (angle == 0 && awScale == 1.0f) {
448 logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
449 } else {
450 logFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
451 }
452 logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
453 logFont.lfQuality = DEFAULT_QUALITY;
454 logFont.lfPitchAndFamily = DEFAULT_PITCH;
455
456 // Set style
457 logFont.lfWeight = (style & java_awt_Font_BOLD) ? FW_BOLD : FW_NORMAL;
458 logFont.lfItalic = (style & java_awt_Font_ITALIC) != 0;
459 logFont.lfUnderline = 0;//(style & java_awt_Font_UNDERLINE) != 0;
460
461 // Get point size
462 logFont.lfHeight = ScaleUpY(-height);
463
464 // Set font name
465 WCHAR tmpname[80];
466 wcscpy(tmpname, name);
467 WCHAR* delimit = wcschr(tmpname, L',');
468 if (delimit != NULL)
469 *delimit = L'\0'; // terminate the string after the font name.
470 // strip "Bold" and "Italic" from the end of the name
471 strip_tail(tmpname,L""); //strip possible trailing whitespace
472 strip_tail(tmpname,L"Italic");
473 strip_tail(tmpname,L"Bold");
474 wcscpy(&(logFont.lfFaceName[0]), tmpname);
475 HFONT hFont = ::CreateFontIndirect(&logFont);
476 DASSERT(hFont != NULL);
477 // get a expanded or condensed version if its specified.
478 if (awScale != 1.0f) {
479 HDC hDC = ::GetDC(0);
480 HFONT oldFont = (HFONT)::SelectObject(hDC, hFont);
481 TEXTMETRIC tm;
482 DWORD avgWidth;
483 GetTextMetrics(hDC, &tm);
484 oldFont = (HFONT)::SelectObject(hDC, oldFont);
485 if (oldFont != NULL) { // should be the same as hFont
486 VERIFY(::DeleteObject(oldFont));
487 }
488 avgWidth = tm.tmAveCharWidth;
489 logFont.lfWidth = (LONG) ScaleUpX((fabs) (avgWidth * awScale));
490 hFont = ::CreateFontIndirect(&logFont);
491 DASSERT(hFont != NULL);
492 VERIFY(::ReleaseDC(0, hDC));
493 }
494
495 return hFont;
496 }
497
CreateHFont(WCHAR * name,int style,int height,int angle,float awScale)498 HFONT AwtFont::CreateHFont(WCHAR* name, int style, int height,
499 int angle, float awScale)
500 {
501 WCHAR longName[80];
502 // 80 > (max face name(=30) + strlen("CHINESEBIG5_CHARSET"))
503 // longName doesn't have to be printable. So, it is OK not to convert.
504
505 wsprintf(longName, L"%ls-%d-%d", name, style, height);
506
507 HFONT hFont = NULL;
508
509 // only cache & share unrotated, unexpanded/uncondensed fonts
510 if (angle == 0 && awScale == 1.0f) {
511 hFont = fontCache.Lookup(longName);
512 if (hFont != NULL) {
513 fontCache.IncRefCount(hFont);
514 return hFont;
515 }
516 }
517
518 hFont = CreateHFont_sub(name, style, height, angle, awScale);
519 if (angle == 0 && awScale == 1.0f) {
520 fontCache.Add(longName, hFont);
521 }
522 return hFont;
523 }
524
Cleanup()525 void AwtFont::Cleanup()
526 {
527 fontCache.Clear();
528 }
529
SetupAscent(AwtFont * font)530 void AwtFont::SetupAscent(AwtFont* font)
531 {
532 HDC hDC = ::GetDC(0);
533 DASSERT(hDC != NULL);
534 HGDIOBJ oldFont = ::SelectObject(hDC, font->GetHFont());
535
536 TEXTMETRIC metrics;
537 VERIFY(::GetTextMetrics(hDC, &metrics));
538 font->SetAscent(metrics.tmAscent);
539
540 ::SelectObject(hDC, oldFont);
541 VERIFY(::ReleaseDC(0, hDC));
542 }
543
LoadMetrics(JNIEnv * env,jobject fontMetrics)544 void AwtFont::LoadMetrics(JNIEnv *env, jobject fontMetrics)
545 {
546 if (env->EnsureLocalCapacity(3) < 0)
547 return;
548 jintArray widths = env->NewIntArray(256);
549 if (widths == NULL) {
550 /* no local refs to delete yet. */
551 return;
552 }
553 jobject font = env->GetObjectField(fontMetrics, AwtFont::fontID);
554 AwtFont* awtFont = AwtFont::GetFont(env, font);
555
556 if (!awtFont) {
557 /* failed to get font */
558 return;
559 }
560
561 HDC hDC = ::GetDC(0);
562 DASSERT(hDC != NULL);
563
564 HGDIOBJ oldFont = ::SelectObject(hDC, awtFont->GetHFont());
565 TEXTMETRIC metrics;
566 VERIFY(::GetTextMetrics(hDC, &metrics));
567
568 awtFont->m_ascent = metrics.tmAscent;
569
570 int ascent = metrics.tmAscent;
571 int descent = metrics.tmDescent;
572 int leading = metrics.tmExternalLeading;
573
574 env->SetIntField(fontMetrics, AwtFont::ascentID, ScaleDownY(ascent));
575 env->SetIntField(fontMetrics, AwtFont::descentID, ScaleDownY(descent));
576 env->SetIntField(fontMetrics, AwtFont::leadingID, ScaleDownX(leading));
577 env->SetIntField(fontMetrics, AwtFont::heightID,
578 ScaleDownY(metrics.tmAscent + metrics.tmDescent + leading));
579 env->SetIntField(fontMetrics, AwtFont::maxAscentID, ScaleDownY(ascent));
580 env->SetIntField(fontMetrics, AwtFont::maxDescentID, ScaleDownY(descent));
581
582 int maxHeight = ascent + descent + leading;
583 env->SetIntField(fontMetrics, AwtFont::maxHeightID, ScaleDownY(maxHeight));
584
585 int maxAdvance = metrics.tmMaxCharWidth;
586 env->SetIntField(fontMetrics, AwtFont::maxAdvanceID, ScaleDownX(maxAdvance));
587
588 awtFont->m_overhang = metrics.tmOverhang;
589
590 jint intWidths[256];
591 memset(intWidths, 0, 256 * sizeof(int));
592 VERIFY(::GetCharWidth(hDC, metrics.tmFirstChar,
593 min(metrics.tmLastChar, 255),
594 (int *)&intWidths[metrics.tmFirstChar]));
595 env->SetIntArrayRegion(widths, 0, 256, intWidths);
596 env->SetObjectField(fontMetrics, AwtFont::widthsID, widths);
597
598 // Get font metrics on remaining fonts (if multifont).
599 for (int j = 1; j < awtFont->GetHFontNum(); j++) {
600 ::SelectObject(hDC, awtFont->GetHFont(j));
601 VERIFY(::GetTextMetrics(hDC, &metrics));
602 env->SetIntField(fontMetrics, AwtFont::maxAscentID,
603 ascent = max(ascent, metrics.tmAscent));
604 env->SetIntField(fontMetrics, AwtFont::maxDescentID,
605 descent = max(descent, metrics.tmDescent));
606 env->SetIntField(fontMetrics, AwtFont::maxHeightID,
607 maxHeight = max(maxHeight,
608 metrics.tmAscent +
609 metrics.tmDescent +
610 metrics.tmExternalLeading));
611 env->SetIntField(fontMetrics, AwtFont::maxAdvanceID,
612 maxAdvance = max(maxAdvance, metrics.tmMaxCharWidth));
613 }
614
615 VERIFY(::SelectObject(hDC, oldFont));
616 VERIFY(::ReleaseDC(0, hDC));
617 env->DeleteLocalRef(font);
618 env->DeleteLocalRef(widths);
619 }
620
TextSize(AwtFont * font,int columns,int rows)621 SIZE AwtFont::TextSize(AwtFont* font, int columns, int rows)
622 {
623 HDC hDC = ::GetDC(0);
624 DASSERT(hDC != NULL);
625 HGDIOBJ oldFont = ::SelectObject(hDC, (font == NULL)
626 ? ::GetStockObject(SYSTEM_FONT)
627 : font->GetHFont());
628
629 SIZE size;
630 VERIFY(::GetTextExtentPoint(hDC,
631 TEXT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 52, &size));
632
633 VERIFY(::SelectObject(hDC, oldFont));
634 VERIFY(::ReleaseDC(0, hDC));
635
636 size.cx = size.cx * columns / 52;
637 size.cy = size.cy * rows;
638 return size;
639 }
640
getFontDescriptorNumber(JNIEnv * env,jobject font,jobject fontDescriptor)641 int AwtFont::getFontDescriptorNumber(JNIEnv *env, jobject font,
642 jobject fontDescriptor)
643 {
644 int i, num = 0;
645 jobject refFontDescriptor;
646 jobjectArray array;
647
648 if (env->EnsureLocalCapacity(2) < 0)
649 return 0;
650
651 if (IsMultiFont(env, font)) {
652 array = GetComponentFonts(env, font);
653 if (array != NULL) {
654 num = env->GetArrayLength(array);
655 }
656 } else {
657 array = NULL;
658 num = 0;
659 }
660
661 for (i = 0; i < num; i++){
662 // Trying to identify the same FontDescriptor by comparing the
663 // pointers.
664 refFontDescriptor = env->GetObjectArrayElement(array, i);
665 if (env->IsSameObject(refFontDescriptor, fontDescriptor)) {
666 env->DeleteLocalRef(refFontDescriptor);
667 env->DeleteLocalRef(array);
668 return i;
669 }
670 env->DeleteLocalRef(refFontDescriptor);
671 }
672 env->DeleteLocalRef(array);
673 return 0; // Not found. Use default.
674 }
675
676 /*
677 * This is a faster version of the same function, which does most of
678 * the work in Java.
679 */
DrawStringSize_sub(jstring str,HDC hDC,jobject font,long x,long y,BOOL draw,UINT codePage)680 SIZE AwtFont::DrawStringSize_sub(jstring str, HDC hDC,
681 jobject font, long x, long y, BOOL draw,
682 UINT codePage)
683 {
684 SIZE size, temp;
685 size.cx = size.cy = 0;
686
687 if (str == NULL) {
688 return size;
689 }
690
691 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
692 if (env->EnsureLocalCapacity(3) < 0)
693 return size;
694 jobjectArray array = 0;
695
696 int arrayLength = 0;
697
698 if (env->GetStringLength(str) == 0) {
699 return size;
700 }
701
702 //Init AwtFont object, which will "create" a AwtFont object if necessry,
703 //before calling makeconvertedMultiFontString(), otherwise, the FontDescriptor's
704 //"useUnicode" field might not be initialized correctly (font in Menu Component,
705 //for example").
706 AwtFont* awtFont = AwtFont::GetFont(env, font);
707 if (awtFont == NULL) {
708 return size;
709 }
710
711 if (IsMultiFont(env, font)) {
712 jobject peer = env->CallObjectMethod(font, AwtFont::peerMID);
713 if (peer != NULL) {
714 array = (jobjectArray)(env->CallObjectMethod(
715 peer, AwtFont::makeConvertedMultiFontStringMID, str));
716 DASSERT(!safe_ExceptionOccurred(env));
717
718 if (array != NULL) {
719 arrayLength = env->GetArrayLength(array);
720 }
721 env->DeleteLocalRef(peer);
722 }
723 } else {
724 array = NULL;
725 arrayLength = 0;
726 }
727
728 HFONT oldFont = (HFONT)::SelectObject(hDC, awtFont->GetHFont());
729
730 if (arrayLength == 0) {
731 int length = env->GetStringLength(str);
732 LPCWSTR strW = JNU_GetStringPlatformChars(env, str, NULL);
733 if (strW == NULL) {
734 return size;
735 }
736 VERIFY(::SelectObject(hDC, awtFont->GetHFont()));
737 if (AwtComponent::GetRTLReadingOrder()){
738 VERIFY(!draw || ::ExtTextOut(hDC, x, y, ETO_RTLREADING, NULL,
739 strW, length, NULL));
740 } else {
741 VERIFY(!draw || ::TextOut(hDC, x, y, strW, length));
742 }
743 VERIFY(::GetTextExtentPoint32(hDC, strW, length, &size));
744 JNU_ReleaseStringPlatformChars(env, str, strW);
745 } else {
746 for (int i = 0; i < arrayLength; i = i + 2) {
747 jobject fontDescriptor = env->GetObjectArrayElement(array, i);
748 if (fontDescriptor == NULL) {
749 break;
750 }
751
752 jbyteArray convertedBytes =
753 (jbyteArray)env->GetObjectArrayElement(array, i + 1);
754 if (convertedBytes == NULL) {
755 env->DeleteLocalRef(fontDescriptor);
756 break;
757 }
758
759 int fdIndex = getFontDescriptorNumber(env, font, fontDescriptor);
760 if (env->ExceptionCheck()) {
761 return size; //fdIndex==0 return could be exception or not.
762 }
763 VERIFY(::SelectObject(hDC, awtFont->GetHFont(fdIndex)));
764
765 /*
766 * The strange-looking code that follows this comment is
767 * the result of upstream optimizations. In the array of
768 * alternating font descriptor and buffers, the buffers
769 * contain their length in the first four bytes, a la
770 * Pascal arrays.
771 *
772 * Note: the buffer MUST be unsigned, or VC++ will sign
773 * extend buflen and bad things will happen.
774 */
775 unsigned char* buffer = NULL;
776 jboolean unicodeUsed =
777 env->GetBooleanField(fontDescriptor, AwtFont::useUnicodeID);
778 try {
779 buffer = (unsigned char *)
780 env->GetPrimitiveArrayCritical(convertedBytes, 0);
781 if (buffer == NULL) {
782 return size;
783 }
784 int buflen = (buffer[0] << 24) | (buffer[1] << 16) |
785 (buffer[2] << 8) | buffer[3];
786
787 DASSERT(buflen >= 0);
788
789 /*
790 * the offsetBuffer, on the other hand, must be signed because
791 * TextOutA and GetTextExtentPoint32A expect it.
792 */
793 char* offsetBuffer = (char *)(buffer + 4);
794
795 if (unicodeUsed) {
796 VERIFY(!draw || ::TextOutW(hDC, x, y, (LPCWSTR)offsetBuffer, buflen / 2));
797 VERIFY(::GetTextExtentPoint32W(hDC, (LPCWSTR)offsetBuffer, buflen / 2, &temp));
798 }
799 else {
800 VERIFY(!draw || ::TextOutA(hDC, x, y, offsetBuffer, buflen));
801 VERIFY(::GetTextExtentPoint32A(hDC, offsetBuffer, buflen, &temp));
802 }
803 } catch (...) {
804 if (buffer != NULL) {
805 env->ReleasePrimitiveArrayCritical(convertedBytes, buffer,
806 0);
807 }
808 throw;
809 }
810 env->ReleasePrimitiveArrayCritical(convertedBytes, buffer, 0);
811
812 if (awtFont->textAngle == 0) {
813 x += temp.cx;
814 } else {
815 // account for rotation of the text used in 2D printing.
816 double degrees = 360.0 - (awtFont->textAngle/10.0);
817 double rads = degrees/(180.0/3.1415926535);
818 double dx = temp.cx * cos(rads);
819 double dy = temp.cx * sin(rads);
820 x += (long)floor(dx+0.5);
821 y += (long)floor(dy+0.5);
822 }
823 size.cx += temp.cx;
824 size.cy = (size.cy < temp.cy) ? temp.cy : size.cy;
825 env->DeleteLocalRef(fontDescriptor);
826 env->DeleteLocalRef(convertedBytes);
827 }
828 }
829 env->DeleteLocalRef(array);
830
831 VERIFY(::SelectObject(hDC, oldFont));
832 return size;
833 }
834
835 /************************************************************************
836 * WFontMetrics native methods
837 */
838
839 extern "C" {
840
841 /*
842 * Class: sun_awt_windows_WFontMetrics
843 * Method: stringWidth
844 * Signature: (Ljava/lang/String;)I
845 */
846 JNIEXPORT jint JNICALL
Java_sun_awt_windows_WFontMetrics_stringWidth(JNIEnv * env,jobject self,jstring str)847 Java_sun_awt_windows_WFontMetrics_stringWidth(JNIEnv *env, jobject self,
848 jstring str)
849 {
850 TRY;
851
852 if (str == NULL) {
853 JNU_ThrowNullPointerException(env, "str argument");
854 return NULL;
855 }
856 HDC hDC = ::GetDC(0); DASSERT(hDC != NULL);
857
858 jobject font = env->GetObjectField(self, AwtFont::fontID);
859
860 long ret = AwtFont::getMFStringWidth(hDC, font, str);
861 ret = ScaleDownX(ret);
862 VERIFY(::ReleaseDC(0, hDC));
863 return ret;
864
865 CATCH_BAD_ALLOC_RET(0);
866 }
867
868 /*
869 * Class: sun_awt_windows_WFontMetrics
870 * Method: charsWidth
871 * Signature: ([CII)I
872 */
873 JNIEXPORT jint JNICALL
Java_sun_awt_windows_WFontMetrics_charsWidth(JNIEnv * env,jobject self,jcharArray str,jint off,jint len)874 Java_sun_awt_windows_WFontMetrics_charsWidth(JNIEnv *env, jobject self,
875 jcharArray str,
876 jint off, jint len)
877 {
878 TRY;
879
880 if (str == NULL) {
881 JNU_ThrowNullPointerException(env, "str argument");
882 return 0;
883 }
884 if ((len < 0) || (off < 0) || (len + off < 0) ||
885 (len + off > (env->GetArrayLength(str)))) {
886 JNU_ThrowArrayIndexOutOfBoundsException(env, "off/len argument");
887 return 0;
888 }
889
890 if (off == env->GetArrayLength(str)) {
891 return 0;
892 }
893
894 jchar *strp = new jchar[len];
895 env->GetCharArrayRegion(str, off, len, strp);
896 jstring jstr = env->NewString(strp, len);
897 jint result = 0;
898 if (jstr != NULL) {
899 result = Java_sun_awt_windows_WFontMetrics_stringWidth(env, self,
900 jstr);
901 }
902 delete [] strp;
903 return result;
904
905 CATCH_BAD_ALLOC_RET(0);
906 }
907
908
909 /*
910 * Class: sun_awt_windows_WFontMetrics
911 * Method: bytesWidth
912 * Signature: ([BII)I
913 */
914 JNIEXPORT jint JNICALL
Java_sun_awt_windows_WFontMetrics_bytesWidth(JNIEnv * env,jobject self,jbyteArray str,jint off,jint len)915 Java_sun_awt_windows_WFontMetrics_bytesWidth(JNIEnv *env, jobject self,
916 jbyteArray str,
917 jint off, jint len)
918 {
919 TRY;
920
921 if (str == NULL) {
922 JNU_ThrowNullPointerException(env, "bytes argument");
923 return 0;
924 }
925 if ((len < 0) || (off < 0) || (len + off < 0) ||
926 (len + off > (env->GetArrayLength(str)))) {
927 JNU_ThrowArrayIndexOutOfBoundsException(env, "off or len argument");
928 return 0;
929 }
930
931 if (off == env->GetArrayLength(str)) {
932 return 0;
933 }
934
935 char *pStrBody = NULL;
936 jint result = 0;
937 try {
938 jintArray array = (jintArray)env->GetObjectField(self,
939 AwtFont::widthsID);
940 if (array == NULL) {
941 JNU_ThrowNullPointerException(env, "Can't access widths array.");
942 return 0;
943 }
944 pStrBody = (char *)env->GetPrimitiveArrayCritical(str, 0);
945 if (pStrBody == NULL) {
946 JNU_ThrowNullPointerException(env, "Can't access str bytes.");
947 return 0;
948 }
949 char *pStr = pStrBody + off;
950
951 jint *widths = NULL;
952 try {
953 widths = (jint *)env->GetPrimitiveArrayCritical(array, 0);
954 if (widths == NULL) {
955 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
956 JNU_ThrowNullPointerException(env, "Can't access widths.");
957 return 0;
958 }
959 for (; len; len--) {
960 result += widths[*pStr++];
961 }
962 } catch (...) {
963 if (widths != NULL) {
964 env->ReleasePrimitiveArrayCritical(array, widths, 0);
965 }
966 throw;
967 }
968
969 env->ReleasePrimitiveArrayCritical(array, widths, 0);
970
971 } catch (...) {
972 if (pStrBody != NULL) {
973 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
974 }
975 throw;
976 }
977
978 env->ReleasePrimitiveArrayCritical(str, pStrBody, 0);
979 return ScaleDownX(result);
980
981 CATCH_BAD_ALLOC_RET(0);
982 }
983
984
985 /*
986 * Class: sun_awt_windows_WFontMetrics
987 * Method: init
988 * Signature: ()V
989 */
990 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFontMetrics_init(JNIEnv * env,jobject self)991 Java_sun_awt_windows_WFontMetrics_init(JNIEnv *env, jobject self)
992 {
993 TRY;
994
995 jobject font = env->GetObjectField(self, AwtFont::fontID);
996 if (font == NULL) {
997 JNU_ThrowNullPointerException(env, "fontMetrics' font");
998 return;
999 }
1000 // This local variable is unused. Is there some subtle side-effect here?
1001 jlong pData = env->GetLongField(font, AwtFont::pDataID);
1002
1003 AwtFont::LoadMetrics(env, self);
1004
1005 CATCH_BAD_ALLOC;
1006 }
1007
1008
1009 /*
1010 * Class: sun_awt_windows_WFontMetrics
1011 * Method: initIDs
1012 * Signature: ()V
1013 */
1014 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFontMetrics_initIDs(JNIEnv * env,jclass cls)1015 Java_sun_awt_windows_WFontMetrics_initIDs(JNIEnv *env, jclass cls)
1016 {
1017 CHECK_NULL(AwtFont::widthsID = env->GetFieldID(cls, "widths", "[I"));
1018 CHECK_NULL(AwtFont::ascentID = env->GetFieldID(cls, "ascent", "I"));
1019 CHECK_NULL(AwtFont::descentID = env->GetFieldID(cls, "descent", "I"));
1020 CHECK_NULL(AwtFont::leadingID = env->GetFieldID(cls, "leading", "I"));
1021 CHECK_NULL(AwtFont::heightID = env->GetFieldID(cls, "height", "I"));
1022 CHECK_NULL(AwtFont::maxAscentID = env->GetFieldID(cls, "maxAscent", "I"));
1023 CHECK_NULL(AwtFont::maxDescentID = env->GetFieldID(cls, "maxDescent", "I"));
1024 CHECK_NULL(AwtFont::maxHeightID = env->GetFieldID(cls, "maxHeight", "I"));
1025 AwtFont::maxAdvanceID = env->GetFieldID(cls, "maxAdvance", "I");
1026 }
1027
1028 } /* extern "C" */
1029
1030
1031 /************************************************************************
1032 * java.awt.Font native methods
1033 */
1034
1035 extern "C" {
1036
1037 JNIEXPORT void JNICALL
Java_java_awt_Font_initIDs(JNIEnv * env,jclass cls)1038 Java_java_awt_Font_initIDs(JNIEnv *env, jclass cls)
1039 {
1040 CHECK_NULL(AwtFont::peerMID = env->GetMethodID(cls, "getFontPeer",
1041 "()Ljava/awt/peer/FontPeer;"));
1042 CHECK_NULL(AwtFont::pDataID = env->GetFieldID(cls, "pData", "J"));
1043 CHECK_NULL(AwtFont::nameID =
1044 env->GetFieldID(cls, "name", "Ljava/lang/String;"));
1045 CHECK_NULL(AwtFont::sizeID = env->GetFieldID(cls, "size", "I"));
1046 CHECK_NULL(AwtFont::styleID = env->GetFieldID(cls, "style", "I"));
1047 AwtFont::getFontMID =
1048 env->GetStaticMethodID(cls, "getFont",
1049 "(Ljava/lang/String;)Ljava/awt/Font;");
1050 }
1051
1052 } /* extern "C" */
1053
1054
1055 /************************************************************************
1056 * java.awt.FontMetric native methods
1057 */
1058
1059 extern "C" {
1060
1061 JNIEXPORT void JNICALL
Java_java_awt_FontMetrics_initIDs(JNIEnv * env,jclass cls)1062 Java_java_awt_FontMetrics_initIDs(JNIEnv *env, jclass cls)
1063 {
1064 CHECK_NULL(AwtFont::fontID =
1065 env->GetFieldID(cls, "font", "Ljava/awt/Font;"));
1066 AwtFont::getHeightMID = env->GetMethodID(cls, "getHeight", "()I");
1067 }
1068
1069 } /* extern "C" */
1070
1071 /************************************************************************
1072 * sun.awt.FontDescriptor native methods
1073 */
1074
1075 extern "C" {
1076
1077 JNIEXPORT void JNICALL
Java_sun_awt_FontDescriptor_initIDs(JNIEnv * env,jclass cls)1078 Java_sun_awt_FontDescriptor_initIDs(JNIEnv *env, jclass cls)
1079 {
1080 CHECK_NULL(AwtFont::nativeNameID =
1081 env->GetFieldID(cls, "nativeName", "Ljava/lang/String;"));
1082 AwtFont::useUnicodeID = env->GetFieldID(cls, "useUnicode", "Z");
1083
1084 }
1085
1086 } /* extern "C" */
1087
1088
1089 /************************************************************************
1090 * sun.awt.PlatformFont native methods
1091 */
1092
1093 extern "C" {
1094
1095 JNIEXPORT void JNICALL
Java_sun_awt_PlatformFont_initIDs(JNIEnv * env,jclass cls)1096 Java_sun_awt_PlatformFont_initIDs(JNIEnv *env, jclass cls)
1097 {
1098 CHECK_NULL(AwtFont::fontConfigID =
1099 env->GetFieldID(cls, "fontConfig", "Lsun/awt/FontConfiguration;"));
1100 CHECK_NULL(AwtFont::componentFontsID =
1101 env->GetFieldID(cls, "componentFonts", "[Lsun/awt/FontDescriptor;"));
1102 AwtFont::makeConvertedMultiFontStringMID =
1103 env->GetMethodID(cls, "makeConvertedMultiFontString",
1104 "(Ljava/lang/String;)[Ljava/lang/Object;");
1105 }
1106
1107 } /* extern "C" */
1108
1109
1110 /************************************************************************
1111 * sun.awt.windows.WFontPeer native methods
1112 */
1113
1114 extern "C" {
1115
1116 JNIEXPORT void JNICALL
Java_sun_awt_windows_WFontPeer_initIDs(JNIEnv * env,jclass cls)1117 Java_sun_awt_windows_WFontPeer_initIDs(JNIEnv *env, jclass cls)
1118 {
1119 TRY;
1120
1121 AwtFont::textComponentFontNameID = env->GetFieldID(cls, "textComponentFontName", "Ljava/lang/String;");
1122
1123 DASSERT(AwtFont::textComponentFontNameID != NULL);
1124
1125 CATCH_BAD_ALLOC;
1126 }
1127
1128 } /* extern "C" */
1129
1130
1131 /************************************************************************
1132 * FontCache methods
1133 */
1134
Add(WCHAR * name,HFONT font)1135 void AwtFontCache::Add(WCHAR* name, HFONT font)
1136 {
1137 fontCache.m_head = new Item(name, font, fontCache.m_head);
1138 }
1139
Lookup(WCHAR * name)1140 HFONT AwtFontCache::Lookup(WCHAR* name)
1141 {
1142 Item* item = fontCache.m_head;
1143 Item* lastItem = NULL;
1144
1145 while (item != NULL) {
1146 if (wcscmp(item->name, name) == 0) {
1147 return item->font;
1148 }
1149 lastItem = item;
1150 item = item->next;
1151 }
1152 return NULL;
1153 }
1154
Search(HFONT font)1155 BOOL AwtFontCache::Search(HFONT font)
1156 {
1157 Item* item = fontCache.m_head;
1158
1159 while (item != NULL) {
1160 if (item->font == font) {
1161 return TRUE;
1162 }
1163 item = item->next;
1164 }
1165 return FALSE;
1166 }
1167
Remove(HFONT font)1168 void AwtFontCache::Remove(HFONT font)
1169 {
1170 Item* item = fontCache.m_head;
1171 Item* lastItem = NULL;
1172
1173 while (item != NULL) {
1174 if (item->font == font) {
1175 if (DecRefCount(item) <= 0){
1176 if (lastItem == NULL) {
1177 fontCache.m_head = item->next;
1178 } else {
1179 lastItem->next = item->next;
1180 }
1181 delete item;
1182 }
1183 return;
1184 }
1185 lastItem = item;
1186 item = item->next;
1187 }
1188 }
1189
Clear()1190 void AwtFontCache::Clear()
1191 {
1192 Item* item = m_head;
1193 Item* next;
1194
1195 while (item != NULL) {
1196 next = item->next;
1197 delete item;
1198 item = next;
1199 }
1200
1201 m_head = NULL;
1202 }
1203
1204 /* NOTE: In the interlock calls below the return value is different
1205 depending on which version of windows. However, all versions
1206 return a 0 or less than value when the count gets there. Only
1207 under NT 4.0 & 98 does the value actaully represent the new value. */
1208
IncRefCount(HFONT hFont)1209 void AwtFontCache::IncRefCount(HFONT hFont){
1210 Item* item = fontCache.m_head;
1211
1212 while (item != NULL){
1213
1214 if (item->font == hFont){
1215 IncRefCount(item);
1216 return;
1217 }
1218 item = item->next;
1219 }
1220 }
1221
IncRefCount(Item * item)1222 LONG AwtFontCache::IncRefCount(Item* item){
1223 LONG newVal = 0;
1224
1225 if(NULL != item){
1226 newVal = InterlockedIncrement((long*)&item->refCount);
1227 }
1228 return(newVal);
1229 }
1230
DecRefCount(Item * item)1231 LONG AwtFontCache::DecRefCount(Item* item){
1232 LONG newVal = 0;
1233
1234 if(NULL != item){
1235 newVal = InterlockedDecrement((long*)&item->refCount);
1236 }
1237 return(newVal);
1238 }
1239
Item(const WCHAR * s,HFONT f,AwtFontCache::Item * n)1240 AwtFontCache::Item::Item(const WCHAR* s, HFONT f, AwtFontCache::Item* n )
1241 {
1242 name = _wcsdup(s);
1243 font = f;
1244 next = n;
1245 refCount = 1;
1246 }
1247
~Item()1248 AwtFontCache::Item::~Item() {
1249 VERIFY(::DeleteObject(font));
1250 free(name);
1251 }
1252
1253 /////////////////////////////////////////////////////////////////////////////
1254 // for canConvert native method of WDefaultFontCharset
1255
1256 class CSegTableComponent
1257 {
1258 public:
1259 CSegTableComponent();
1260 virtual ~CSegTableComponent();
1261 virtual void Create(LPCWSTR name);
In(USHORT iChar)1262 virtual BOOL In(USHORT iChar) { DASSERT(FALSE); return FALSE; };
GetFontName()1263 LPWSTR GetFontName(){
1264 DASSERT(m_lpszFontName != NULL); return m_lpszFontName;
1265 };
1266
1267 private:
1268 LPWSTR m_lpszFontName;
1269 };
1270
CSegTableComponent()1271 CSegTableComponent::CSegTableComponent()
1272 {
1273 m_lpszFontName = NULL;
1274 }
1275
~CSegTableComponent()1276 CSegTableComponent::~CSegTableComponent()
1277 {
1278 if (m_lpszFontName != NULL) {
1279 free(m_lpszFontName);
1280 m_lpszFontName = NULL;
1281 }
1282 }
1283
Create(LPCWSTR name)1284 void CSegTableComponent::Create(LPCWSTR name)
1285 {
1286 if (m_lpszFontName != NULL) {
1287 free(m_lpszFontName);
1288 m_lpszFontName = NULL;
1289 }
1290 m_lpszFontName = _wcsdup(name);
1291 DASSERT(m_lpszFontName);
1292 }
1293
1294 #define CMAPHEX 0x70616d63 // = "cmap" (reversed)
1295
1296 // CSegTable: Segment table describing character coverage for a font
1297 class CSegTable : public CSegTableComponent
1298 {
1299 public:
1300 CSegTable();
1301 virtual ~CSegTable();
1302 virtual BOOL In(USHORT iChar);
1303 BOOL HasCmap();
IsEUDC()1304 virtual BOOL IsEUDC() { DASSERT(FALSE); return FALSE; };
1305
1306 protected:
GetData(DWORD dwOffset,LPVOID lpData,DWORD cbData)1307 virtual void GetData(DWORD dwOffset, LPVOID lpData, DWORD cbData) {
1308 DASSERT(FALSE); };
1309 void MakeTable();
1310 static void SwapShort(USHORT& p);
1311 static void SwapULong(ULONG& p);
1312
1313 private:
1314 USHORT m_cSegCount; // number of segments
1315 PUSHORT m_piStart; // pointer to array of starting values
1316 PUSHORT m_piEnd; // pointer to array of ending values (inclusive)
1317 USHORT m_cSeg; // current segment (cache)
1318 };
1319
CSegTable()1320 CSegTable::CSegTable()
1321 {
1322 m_cSegCount = 0;
1323 m_piStart = NULL;
1324 m_piEnd = NULL;
1325 m_cSeg = 0;
1326 }
1327
~CSegTable()1328 CSegTable::~CSegTable()
1329 {
1330 if (m_piStart != NULL)
1331 delete[] m_piStart;
1332 if (m_piEnd != NULL)
1333 delete[] m_piEnd;
1334 }
1335
1336 #define OFFSETERROR 0
1337
MakeTable()1338 void CSegTable::MakeTable()
1339 {
1340 typedef struct tagTABLE{
1341 USHORT platformID;
1342 USHORT encodingID;
1343 ULONG offset;
1344 } TABLE, *PTABLE;
1345
1346 typedef struct tagSUBTABLE{
1347 USHORT format;
1348 USHORT length;
1349 USHORT version;
1350 USHORT segCountX2;
1351 USHORT searchRange;
1352 USHORT entrySelector;
1353 USHORT rangeShift;
1354 } SUBTABLE, *PSUBTABLE;
1355
1356 USHORT aShort[2];
1357 (void) GetData(0, aShort, sizeof(aShort));
1358 USHORT nTables = aShort[1];
1359 SwapShort(nTables);
1360
1361 // allocate buffer to hold encoding tables
1362 DWORD cbData = nTables * sizeof(TABLE);
1363 PTABLE pTables = new TABLE[nTables];
1364 PTABLE pTable = pTables;
1365
1366 // get array of encoding tables.
1367 (void) GetData(4, (PBYTE) pTable, cbData);
1368
1369 ULONG offsetFormat4 = OFFSETERROR;
1370 USHORT i;
1371 for (i = 0; i < nTables; i++) {
1372 SwapShort(pTable->encodingID);
1373 SwapShort(pTable->platformID);
1374 //for a Unicode font for Windows, platformID == 3, encodingID == 1
1375 if ((pTable->platformID == 3)&&(pTable->encodingID == 1)) {
1376 offsetFormat4 = pTable->offset;
1377 SwapULong(offsetFormat4);
1378 break;
1379 }
1380 pTable++;
1381 }
1382 delete[] pTables;
1383 if (offsetFormat4 == OFFSETERROR) {
1384 return;
1385 }
1386 // DASSERT(offsetFormat4 != OFFSETERROR);
1387
1388 SUBTABLE subTable;
1389 (void) GetData(offsetFormat4, &subTable, sizeof(SUBTABLE));
1390 SwapShort(subTable.format);
1391 SwapShort(subTable.segCountX2);
1392 DASSERT(subTable.format == 4);
1393
1394 m_cSegCount = subTable.segCountX2/2;
1395
1396 // read in the array of segment end values
1397 m_piEnd = new USHORT[m_cSegCount];
1398
1399 ULONG offset = offsetFormat4
1400 + sizeof(SUBTABLE); //skip constant # bytes in subtable
1401 cbData = m_cSegCount * sizeof(USHORT);
1402 (void) GetData(offset, m_piEnd, cbData);
1403 for (i = 0; i < m_cSegCount; i++)
1404 SwapShort(m_piEnd[i]);
1405 DASSERT(m_piEnd[m_cSegCount-1] == 0xffff);
1406
1407 // read in the array of segment start values
1408 try {
1409 m_piStart = new USHORT[m_cSegCount];
1410 } catch (std::bad_alloc&) {
1411 delete [] m_piEnd;
1412 m_piEnd = NULL;
1413 throw;
1414 }
1415
1416 offset += cbData //skip SegEnd array
1417 + sizeof(USHORT); //skip reservedPad
1418 (void) GetData(offset, m_piStart, cbData);
1419 for (i = 0; i < m_cSegCount; i++)
1420 SwapShort(m_piStart[i]);
1421 DASSERT(m_piStart[m_cSegCount-1] == 0xffff);
1422 }
1423
In(USHORT iChar)1424 BOOL CSegTable::In(USHORT iChar)
1425 {
1426 if (!HasCmap()) {
1427 return FALSE;
1428 }
1429 // DASSERT(m_piStart);
1430 // DASSERT(m_piEnd);
1431
1432 if (iChar > m_piEnd[m_cSeg]) {
1433 for (; (m_cSeg < m_cSegCount)&&(iChar > m_piEnd[m_cSeg]); m_cSeg++);
1434 } else if (iChar < m_piStart[m_cSeg]) {
1435 for (; (m_cSeg > 0)&&(iChar < m_piStart[m_cSeg]); m_cSeg--);
1436 }
1437
1438 if ((iChar <= m_piEnd[m_cSeg])&&(iChar >= m_piStart[m_cSeg])&&(iChar != 0xffff))
1439 return TRUE;
1440 else
1441 return FALSE;
1442 }
1443
HasCmap()1444 inline BOOL CSegTable::HasCmap()
1445 {
1446 return (((m_piEnd)&&(m_piStart)) ? TRUE : FALSE);
1447 }
1448
SwapShort(USHORT & p)1449 inline void CSegTable::SwapShort(USHORT& p)
1450 {
1451 SHORT temp;
1452
1453 temp = (SHORT)(HIBYTE(p) + (LOBYTE(p) << 8));
1454 p = temp;
1455 }
1456
SwapULong(ULONG & p)1457 inline void CSegTable::SwapULong(ULONG& p)
1458 {
1459 ULONG temp;
1460
1461 temp = (LONG) ((BYTE) p);
1462 temp <<= 8;
1463 p >>= 8;
1464
1465 temp += (LONG) ((BYTE) p);
1466 temp <<= 8;
1467 p >>= 8;
1468
1469 temp += (LONG) ((BYTE) p);
1470 temp <<= 8;
1471 p >>= 8;
1472
1473 temp += (LONG) ((BYTE) p);
1474 p = temp;
1475 }
1476
1477 class CStdSegTable : public CSegTable
1478 {
1479 public:
1480 CStdSegTable();
1481 virtual ~CStdSegTable();
IsEUDC()1482 BOOL IsEUDC() { return FALSE; };
1483 virtual void Create(LPCWSTR name);
1484
1485 protected:
1486 void GetData(DWORD dwOffset, LPVOID lpData, DWORD cbData);
1487
1488 private:
1489 HDC m_hTmpDC;
1490 };
1491
CStdSegTable()1492 CStdSegTable::CStdSegTable()
1493 {
1494 m_hTmpDC = NULL;
1495 }
1496
~CStdSegTable()1497 CStdSegTable::~CStdSegTable()
1498 {
1499 DASSERT(m_hTmpDC == NULL);
1500 }
1501
GetData(DWORD dwOffset,LPVOID lpData,DWORD cbData)1502 inline void CStdSegTable::GetData(DWORD dwOffset,
1503 LPVOID lpData, DWORD cbData)
1504 {
1505 DASSERT(m_hTmpDC);
1506 DWORD nBytes =
1507 ::GetFontData(m_hTmpDC, CMAPHEX, dwOffset, lpData, cbData);
1508 DASSERT(nBytes != GDI_ERROR);
1509 }
1510
Create(LPCWSTR name)1511 void CStdSegTable::Create(LPCWSTR name)
1512 {
1513 CSegTableComponent::Create(name);
1514
1515 HWND hWnd = ::GetDesktopWindow();
1516 DASSERT(hWnd);
1517 m_hTmpDC = ::GetWindowDC(hWnd);
1518 DASSERT(m_hTmpDC);
1519
1520 HFONT hFont = CreateHFont_sub(name, 0, 20);
1521
1522 HFONT hOldFont = (HFONT)::SelectObject(m_hTmpDC, hFont);
1523 DASSERT(hOldFont);
1524
1525 (void) MakeTable();
1526
1527 VERIFY(::SelectObject(m_hTmpDC, hOldFont));
1528 VERIFY(::DeleteObject(hFont));
1529 VERIFY(::ReleaseDC(hWnd, m_hTmpDC) != 0);
1530 m_hTmpDC = NULL;
1531 }
1532
1533 class CEUDCSegTable : public CSegTable
1534 {
1535 public:
1536 CEUDCSegTable();
1537 virtual ~CEUDCSegTable();
IsEUDC()1538 BOOL IsEUDC() { return TRUE; };
1539 virtual void Create(LPCWSTR name);
1540
1541 protected:
1542 void GetData(DWORD dwOffset, LPVOID lpData, DWORD cbData);
1543
1544 private:
1545 HANDLE m_hTmpFile;
1546 ULONG m_hTmpCMapOffset;
1547 };
1548
CEUDCSegTable()1549 CEUDCSegTable::CEUDCSegTable()
1550 {
1551 m_hTmpFile = NULL;
1552 m_hTmpCMapOffset = 0;
1553 }
1554
~CEUDCSegTable()1555 CEUDCSegTable::~CEUDCSegTable()
1556 {
1557 DASSERT(m_hTmpFile == NULL);
1558 DASSERT(m_hTmpCMapOffset == 0);
1559 }
1560
GetData(DWORD dwOffset,LPVOID lpData,DWORD cbData)1561 inline void CEUDCSegTable::GetData(DWORD dwOffset,
1562 LPVOID lpData, DWORD cbData)
1563 {
1564 DASSERT(m_hTmpFile);
1565 DASSERT(m_hTmpCMapOffset);
1566 ::SetFilePointer(m_hTmpFile, m_hTmpCMapOffset + dwOffset,
1567 NULL, FILE_BEGIN);
1568 DWORD dwRead;
1569 VERIFY(::ReadFile(m_hTmpFile, lpData, cbData, &dwRead, NULL));
1570 DASSERT(dwRead == cbData);
1571 }
1572
Create(LPCWSTR name)1573 void CEUDCSegTable::Create(LPCWSTR name)
1574 {
1575 typedef struct tagHEAD{
1576 FIXED sfnt_version;
1577 USHORT numTables;
1578 USHORT searchRange;
1579 USHORT entrySelector;
1580 USHORT rangeShift;
1581 } HEAD, *PHEAD;
1582
1583 typedef struct tagENTRY{
1584 ULONG tag;
1585 ULONG checkSum;
1586 ULONG offset;
1587 ULONG length;
1588 } ENTRY, *PENTRY;
1589
1590 CSegTableComponent::Create(name);
1591
1592 // create EUDC font file and make EUDCSegTable
1593 // after wrapper function for CreateFileW, we use only CreateFileW
1594 m_hTmpFile = ::CreateFile(name, GENERIC_READ,
1595 FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1596 if (m_hTmpFile == INVALID_HANDLE_VALUE){
1597 m_hTmpFile = NULL;
1598 return;
1599 }
1600
1601 HEAD head;
1602 DWORD dwRead;
1603 VERIFY(::ReadFile(m_hTmpFile, &head, sizeof(head), &dwRead, NULL));
1604 DASSERT(dwRead == sizeof(HEAD));
1605 SwapShort(head.numTables);
1606 ENTRY entry;
1607 for (int i = 0; i < head.numTables; i++){
1608 VERIFY(::ReadFile(m_hTmpFile, &entry, sizeof(entry), &dwRead, NULL));
1609 DASSERT(dwRead == sizeof(ENTRY));
1610 if (entry.tag == CMAPHEX)
1611 break;
1612 }
1613 DASSERT(entry.tag == CMAPHEX);
1614 SwapULong(entry.offset);
1615 m_hTmpCMapOffset = entry.offset;
1616
1617 (void) MakeTable();
1618
1619 m_hTmpCMapOffset = 0;
1620 VERIFY(::CloseHandle(m_hTmpFile));
1621 m_hTmpFile = NULL;
1622 }
1623
1624 class CSegTableManagerComponent
1625 {
1626 public:
1627 CSegTableManagerComponent();
1628 ~CSegTableManagerComponent();
1629
1630 protected:
1631 void MakeBiggerTable();
1632 CSegTableComponent **m_tables;
1633 int m_nTable;
1634 int m_nMaxTable;
1635 };
1636
1637 #define TABLENUM 20
1638
CSegTableManagerComponent()1639 CSegTableManagerComponent::CSegTableManagerComponent()
1640 {
1641 m_nTable = 0;
1642 m_nMaxTable = TABLENUM;
1643 m_tables = new CSegTableComponent*[m_nMaxTable];
1644 }
1645
~CSegTableManagerComponent()1646 CSegTableManagerComponent::~CSegTableManagerComponent()
1647 {
1648 for (int i = 0; i < m_nTable; i++) {
1649 DASSERT(m_tables[i]);
1650 delete m_tables[i];
1651 }
1652 delete [] m_tables;
1653 m_tables = NULL;
1654 }
1655
MakeBiggerTable()1656 void CSegTableManagerComponent::MakeBiggerTable()
1657 {
1658 CSegTableComponent **tables =
1659 new CSegTableComponent*[m_nMaxTable + TABLENUM];
1660
1661 for (int i = 0; i < m_nMaxTable; i++)
1662 tables[i] = m_tables[i];
1663
1664 delete[] m_tables;
1665
1666 m_tables = tables;
1667 m_nMaxTable += TABLENUM;
1668 }
1669
1670 class CSegTableManager : public CSegTableManagerComponent
1671 {
1672 public:
1673 CSegTable* GetTable(LPCWSTR lpszFontName, BOOL fEUDC);
1674 };
1675
GetTable(LPCWSTR lpszFontName,BOOL fEUDC)1676 CSegTable* CSegTableManager::GetTable(LPCWSTR lpszFontName, BOOL fEUDC)
1677 {
1678 for (int i = 0; i < m_nTable; i++) {
1679 if ((((CSegTable*)m_tables[i])->IsEUDC() == fEUDC) &&
1680 (wcscmp(m_tables[i]->GetFontName(),lpszFontName) == 0))
1681 return (CSegTable*) m_tables[i];
1682 }
1683
1684 if (m_nTable == m_nMaxTable) {
1685 (void) MakeBiggerTable();
1686 }
1687 DASSERT(m_nTable < m_nMaxTable);
1688
1689 if (!fEUDC) {
1690 m_tables[m_nTable] = new CStdSegTable;
1691 } else {
1692 m_tables[m_nTable] = new CEUDCSegTable;
1693 }
1694 m_tables[m_nTable]->Create(lpszFontName);
1695 return (CSegTable*) m_tables[m_nTable++];
1696 }
1697
1698 CSegTableManager g_segTableManager;
1699
1700 #define KEYLEN 16
1701
1702 class CCombinedSegTable : public CSegTableComponent
1703 {
1704 public:
1705 CCombinedSegTable();
1706 void Create(LPCWSTR name);
1707 BOOL In(USHORT iChar);
1708
1709 private:
1710 LPSTR GetCodePageSubkey();
1711 void GetEUDCFileName(LPWSTR lpszFileName, int cchFileName);
1712 static char m_szCodePageSubkey[KEYLEN];
1713 static WCHAR m_szDefaultEUDCFile[_MAX_PATH];
1714 static BOOL m_fEUDCSubKeyExist;
1715 static BOOL m_fTTEUDCFileExist;
1716 CStdSegTable* m_pStdSegTable;
1717 CEUDCSegTable* m_pEUDCSegTable;
1718 };
1719
1720 char CCombinedSegTable::m_szCodePageSubkey[KEYLEN] = "";
1721
1722 WCHAR CCombinedSegTable::m_szDefaultEUDCFile[_MAX_PATH] = L"";
1723
1724 BOOL CCombinedSegTable::m_fEUDCSubKeyExist = TRUE;
1725
1726 BOOL CCombinedSegTable::m_fTTEUDCFileExist = TRUE;
1727
CCombinedSegTable()1728 CCombinedSegTable::CCombinedSegTable()
1729 {
1730 m_pStdSegTable = NULL;
1731 m_pEUDCSegTable = NULL;
1732 }
1733
1734 #include <locale.h>
GetCodePageSubkey()1735 LPSTR CCombinedSegTable::GetCodePageSubkey()
1736 {
1737 if (strlen(m_szCodePageSubkey) > 0) {
1738 return m_szCodePageSubkey;
1739 }
1740
1741 LPSTR lpszLocale = setlocale(LC_CTYPE, "");
1742 // cf lpszLocale = "Japanese_Japan.932"
1743 if (lpszLocale == NULL) {
1744 return NULL;
1745 }
1746 LPSTR lpszCP = strchr(lpszLocale, (int) '.');
1747 if (lpszCP == NULL) {
1748 return NULL;
1749 }
1750 lpszCP++; // cf lpszCP = "932"
1751
1752 char szSubKey[KEYLEN];
1753 strcpy(szSubKey, "EUDC\\");
1754 if ((strlen(szSubKey) + strlen(lpszCP)) >= KEYLEN) {
1755 return NULL;
1756 }
1757 strcpy(&(szSubKey[strlen(szSubKey)]), lpszCP);
1758 strcpy(m_szCodePageSubkey, szSubKey);
1759 return m_szCodePageSubkey;
1760 }
1761
GetEUDCFileName(LPWSTR lpszFileName,int cchFileName)1762 void CCombinedSegTable::GetEUDCFileName(LPWSTR lpszFileName, int cchFileName)
1763 {
1764 if (m_fEUDCSubKeyExist == FALSE)
1765 return;
1766
1767 // get filename of typeface-specific TureType EUDC font
1768 LPSTR lpszSubKey = GetCodePageSubkey();
1769 if (lpszSubKey == NULL) {
1770 m_fEUDCSubKeyExist = FALSE;
1771 return; // can not get codepage information
1772 }
1773 HKEY hRootKey = HKEY_CURRENT_USER;
1774 HKEY hKey;
1775 LONG lRet = ::RegOpenKeyExA(hRootKey, lpszSubKey, 0, KEY_ALL_ACCESS, &hKey);
1776 if (lRet != ERROR_SUCCESS) {
1777 m_fEUDCSubKeyExist = FALSE;
1778 return; // no EUDC font
1779 }
1780
1781 // get EUDC font file name
1782 WCHAR szFamilyName[80];
1783 wcscpy(szFamilyName, GetFontName());
1784 WCHAR* delimit = wcschr(szFamilyName, L',');
1785 if (delimit != NULL)
1786 *delimit = L'\0';
1787 DWORD dwType;
1788 UCHAR szFileName[_MAX_PATH];
1789 ::ZeroMemory(szFileName, sizeof(szFileName));
1790 DWORD dwBytes = sizeof(szFileName);
1791 // try Typeface-specific EUDC font
1792 char szTmpName[80];
1793 VERIFY(::WideCharToMultiByte(CP_ACP, 0, szFamilyName, -1,
1794 szTmpName, sizeof(szTmpName), NULL, NULL));
1795 LONG lStatus = ::RegQueryValueExA(hKey, (LPCSTR) szTmpName,
1796 NULL, &dwType, szFileName, &dwBytes);
1797 BOOL fUseDefault = FALSE;
1798 if (lStatus != ERROR_SUCCESS){ // try System default EUDC font
1799 if (m_fTTEUDCFileExist == FALSE)
1800 return;
1801 if (wcslen(m_szDefaultEUDCFile) > 0) {
1802 wcscpy(lpszFileName, m_szDefaultEUDCFile);
1803 return;
1804 }
1805 char szDefault[] = "SystemDefaultEUDCFont";
1806 lStatus = ::RegQueryValueExA(hKey, (LPCSTR) szDefault,
1807 NULL, &dwType, szFileName, &dwBytes);
1808 fUseDefault = TRUE;
1809 if (lStatus != ERROR_SUCCESS) {
1810 m_fTTEUDCFileExist = FALSE;
1811 // This font is associated with no EUDC font
1812 // and there is no system default EUDC font
1813 return;
1814 }
1815 }
1816
1817 if (strcmp((LPCSTR) szFileName, "userfont.fon") == 0) {
1818 // This font is associated with no EUDC font
1819 // and the system default EUDC font is not TrueType
1820 m_fTTEUDCFileExist = FALSE;
1821 return;
1822 }
1823
1824 DASSERT(strlen((LPCSTR)szFileName) > 0);
1825 VERIFY(::MultiByteToWideChar(CP_ACP, 0,
1826 (LPCSTR)szFileName, -1, lpszFileName, cchFileName) != 0);
1827 if (fUseDefault)
1828 wcscpy(m_szDefaultEUDCFile, lpszFileName);
1829 }
1830
Create(LPCWSTR name)1831 void CCombinedSegTable::Create(LPCWSTR name)
1832 {
1833 CSegTableComponent::Create(name);
1834
1835 m_pStdSegTable =
1836 (CStdSegTable*) g_segTableManager.GetTable(name, FALSE/*not EUDC*/);
1837 WCHAR szEUDCFileName[_MAX_PATH];
1838 ::ZeroMemory(szEUDCFileName, sizeof(szEUDCFileName));
1839 (void) GetEUDCFileName(szEUDCFileName,
1840 sizeof(szEUDCFileName)/sizeof(WCHAR));
1841 if (wcslen(szEUDCFileName) > 0) {
1842 m_pEUDCSegTable = (CEUDCSegTable*) g_segTableManager.GetTable(
1843 szEUDCFileName, TRUE/*EUDC*/);
1844 if (m_pEUDCSegTable->HasCmap() == FALSE)
1845 m_pEUDCSegTable = NULL;
1846 }
1847 }
1848
In(USHORT iChar)1849 BOOL CCombinedSegTable::In(USHORT iChar)
1850 {
1851 DASSERT(m_pStdSegTable);
1852 if (m_pStdSegTable->In(iChar))
1853 return TRUE;
1854
1855 if (m_pEUDCSegTable != NULL)
1856 return m_pEUDCSegTable->In(iChar);
1857
1858 return FALSE;
1859 }
1860
1861 class CCombinedSegTableManager : public CSegTableManagerComponent
1862 {
1863 public:
1864 CCombinedSegTable* GetTable(LPCWSTR lpszFontName);
1865 };
1866
GetTable(LPCWSTR lpszFontName)1867 CCombinedSegTable* CCombinedSegTableManager::GetTable(LPCWSTR lpszFontName)
1868 {
1869 for (int i = 0; i < m_nTable; i++) {
1870 if (wcscmp(m_tables[i]->GetFontName(),lpszFontName) == 0)
1871 return (CCombinedSegTable*) m_tables[i];
1872 }
1873
1874 if (m_nTable == m_nMaxTable) {
1875 (void) MakeBiggerTable();
1876 }
1877 DASSERT(m_nTable < m_nMaxTable);
1878
1879 m_tables[m_nTable] = new CCombinedSegTable;
1880 m_tables[m_nTable]->Create(lpszFontName);
1881
1882 return (CCombinedSegTable*) m_tables[m_nTable++];
1883 }
1884
1885
1886 /************************************************************************
1887 * WDefaultFontCharset native methos
1888 */
1889
1890 extern "C" {
1891
1892 JNIEXPORT void JNICALL
Java_sun_awt_windows_WDefaultFontCharset_initIDs(JNIEnv * env,jclass cls)1893 Java_sun_awt_windows_WDefaultFontCharset_initIDs(JNIEnv *env, jclass cls)
1894 {
1895 TRY;
1896
1897 AwtFont::fontNameID = env->GetFieldID(cls, "fontName",
1898 "Ljava/lang/String;");
1899 DASSERT(AwtFont::fontNameID != NULL);
1900
1901 CATCH_BAD_ALLOC;
1902 }
1903
1904
1905 /*
1906 * !!!!!!!!!!!!!!!!!!!! this does not work. I am not sure why, but
1907 * when active, this will reliably crash HJ, with no hope of debugging
1908 * for java. It doesn't seem to crash the _g version.
1909 * !!!!!!!!!!!!!!!!!!!!!!!!!!!!
1910 *
1911 * I suspect may be running out of C stack: see alloca in
1912 * JNI_GET_STRING, the alloca in it.
1913 *
1914 * (the method is prefixed with XXX so that the linker won't find it) */
1915 JNIEXPORT jboolean JNICALL
Java_sun_awt_windows_WDefaultFontCharset_canConvert(JNIEnv * env,jobject self,jchar ch)1916 Java_sun_awt_windows_WDefaultFontCharset_canConvert(JNIEnv *env, jobject self,
1917 jchar ch)
1918 {
1919 TRY;
1920
1921 static CCombinedSegTableManager tableManager;
1922
1923 jstring fontName = (jstring)env->GetObjectField(self, AwtFont::fontNameID);
1924 DASSERT(fontName != NULL); // leave in for debug mode.
1925 CHECK_NULL_RETURN(fontName, FALSE); // in production, just return
1926 LPCWSTR fontNameW = JNU_GetStringPlatformChars(env, fontName, NULL);
1927 CHECK_NULL_RETURN(fontNameW, FALSE);
1928 CCombinedSegTable* pTable = tableManager.GetTable(fontNameW);
1929 JNU_ReleaseStringPlatformChars(env, fontName, fontNameW);
1930 return (pTable->In((USHORT) ch) ? JNI_TRUE : JNI_FALSE);
1931
1932 CATCH_BAD_ALLOC_RET(FALSE);
1933 }
1934
1935 } /* extern "C" */
1936