Groups | Blog | Home
all groups > dotnet sdk > august 2007 >

dotnet sdk : CultureInfo.NativeName - can it be rendered?


David Thielen
8/29/2007 2:52:09 PM
Hi;

How can I determine for a given CultureInfo.NativeName if the fonts are
installed on a system to render it?

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com

Cubicle Wars - http://www.windwardreports.com/film.htm

wawang NO[at]SPAM online.microsoft.com (
8/30/2007 12:00:00 AM
Hi Dave,

This is a quick note to let you know that I am performing research on this
issue and will get back to you as soon as possible. I appreciate your
patience.


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
wawang NO[at]SPAM online.microsoft.com (
9/3/2007 3:25:25 AM
Hi Dave,

Sorry the delayed reply.

If your objective here is to show all cultures' NativeName in one
control(font), then this is not possible since currently no Unicode font
could display all Unicode characters.

If your objective is to show one culture's NativeName at a time (for
example, in a Label), then you should simply use the default font and it
will choose the best suitable font installed on the system to show the
content.

In .NET WinForm, SystemFonts.DefaultFont is used to return the default font
that applications can use for dialog boxes and forms.

For more information on this, please refer to following document:

http://www.microsoft.com/globaldev/getwr/steps/wrg_font.mspx

To summarize the info in above document: hardcoding a physical font name is
not recommended for showing text which is not in the system default locale.
Using the virtual font "MS Shell Dlg" is recommended.

Since .NET WinForm's designer now uses only physical fonts, the "MS Shell
Dlg" font is not listed. However, simply don't set a control's Font or uses
SystemFonts.DefaultFont should do the equivalent.

For an example on this, please refer to CultureExplorer:

http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=B778F
F2C-9142-4769-839A-094F51A6F9F4

This is correctly showing each culture's NativeName on it.

Hope this helps.


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen
9/3/2007 8:38:07 AM
I use it in a dropdown control to let them pick their locale. If the Asian
and bi-di fonts are installed on a computer it works great - each locale is
displayed in it's native language.

But if those fonts are not installed, then I get the box characters for the
Asian and bi-di locale names.

So I need some way to find out if the font used in the control can display
the characters in the string.

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com

Cubicle Wars - http://www.windwardreports.com/film.htm




[quoted text, click to view]
wawang NO[at]SPAM online.microsoft.com (
9/4/2007 12:00:00 AM
Hi Dave,

Thanks. Now I understand your question is actually to detect if the
CultureInfo.NativeName can be correctly displayed on current system and if
not, fallback to show English name for it, right?

I'll do some more consulting and researching for you.


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen
9/4/2007 7:40:03 AM
Yes.

THis way if someone in China is using it I want it to display in Han
characters instead of English.

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com

Cubicle Wars - http://www.windwardreports.com/film.htm




[quoted text, click to view]
wawang NO[at]SPAM online.microsoft.com (
9/6/2007 12:00:00 AM
Hi Dave,

Please refer to following blog:

#Sorting It All Out : WYSIWYG font dropdowns
http://blogs.msdn.com/michkap/archive/2006/06/28/649791.aspx
<quote>
So, the real question here is even simpler: "How can one determine if a
font supports the characters in a string?"

The easiest way is via the GetGlyphIndices function, which has in the
initial description:

The GetGlyphIndices function translates a string into an array of glyph
indices. The function can be used to determine whether a glyph exists in a
font.

So you can pass the name you were going to use to the function (making sure
to pass the GGI_MARK_NONEXISTING_GLYPHS flag), and then look at the glyph
indices for the 0xffff marker.

If it shows up for any of the characters, then you know you should use some
other font.
</quote>


In summary, you use the default font for the ComboBox, then iterate all
NativeName to see if the text could be displayed. If not, then you use
english name to display the CultureInfo.

Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen
9/6/2007 10:00:00 AM
perfect - thanks

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com

Cubicle Wars - http://www.windwardreports.com/film.htm




[quoted text, click to view]
David Thielen
9/9/2007 3:36:06 PM
Hi;

I'm hitting 2 problems with this.

1) It returns all 0's for all Asian languages (it does return correctly for
Hebrew & Arabic). I have the Far-East fonts installed and they display fine -
but I get all 0's for them.

2) The code "CultureInfo.CreateSpecificCulture(ci.IetfLanguageTag)" throws
an exception for Chinese - both traditional & simplified. For every other
language it returns a CultureInfo. I assume this is because of the PRC/Taiwan
issue? Is there a good way to handle this other than hard-coding for those 2
cases?

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com

Cubicle Wars - http://www.windwardreports.com/film.htm




[quoted text, click to view]
wawang NO[at]SPAM online.microsoft.com (
9/12/2007 12:28:19 AM
Hi Dave,

According to documentation of CultureInfo.IetfLanguageTag:

------
The format of an IETF language tag is similar to the culture name returned
by the Name property, but does not identify a culture uniquely. That is,
different cultures share the same IETF language tag if those cultures have
identical linguistic characteristics.
------

Which exact value is the ci.IetfLanguageTag that you're passing to
CultureInfo.CreateSpecificCulture()?

By the way, I'm not sure if you have looked at the source code of the
sample CultureExplorer I mentioned previously: if you're using
CultureInfo.GetCultures(type), then I think you can don't need to create
individual CultureInfo again? For example, if you use
CultureTypes.InstalledWin32Cultures, this will return all CultureInfoes
that are installed locally.

What's the system default locale?

Would you please post or send me the code that you're using? Preferably a
smaller but complete project. Thanks.


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
David Thielen
9/25/2007 2:06:03 PM
Please take a look at http://www.windwardreports.com/temp/CultureInfo.zip -
on my system, which does have all the far east fonts loaded and on which
those fonts display ok, it says it cannot display them.

And for the culture neutral enum, it does not like Chinese - neither
simplified or traditional.

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com

Cubicle Wars - http://www.windwardreports.com/film.htm




[quoted text, click to view]
wawang NO[at]SPAM online.microsoft.com (
9/27/2007 12:38:06 PM
Hi Dave,

This is a quick note to let you know that I am performing research on this
issue and will get back to you as soon as possible. I appreciate your
patience.


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
wawang NO[at]SPAM online.microsoft.com (
9/28/2007 12:00:00 AM
Hi Dave,

I believe it's related to the font created in .NET code doesn't correctly
fallback to other fonts properly.

I've created a win32 DLL to do the call and it seems working correctly:

// File FontUtil.cpp
// cl /LD /D "_UNICODE" /D "UNICODE" user32.lib kernel32.lib gdi32.lib
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <tchar.h>

#define FONTUTIL_EXPORTS

#ifdef FONTUTIL_EXPORTS
#define FONTUTIL_API __declspec(dllexport)
#else
#define FONTUTIL_API __declspec(dllimport)
#endif

extern "C" {
FONTUTIL_API BOOL IsFontInstalled(LPCTSTR szFontName);
FONTUTIL_API BOOL IsCharactersAvailableInFont(LPCTSTR szFontName,
LPCTSTR characters);
}


static int CALLBACK EnumFontFamProc(CONST ENUMLOGFONT *lpelf,
CONST NEWTEXTMETRIC *lpntm,
DWORD FontType,
LPARAM lParam
)
{
*((BOOL*)lParam) = TRUE;
return 0;
}

BOOL IsFontInstalled(LPCTSTR szFontName)
{
BOOL bIsInstalled = FALSE;
HDC hDC = GetDC(NULL);
EnumFontFamilies(hDC, szFontName, (FONTENUMPROC) EnumFontFamProc, (LPARAM)
&bIsInstalled);
ReleaseDC(NULL, hDC);
return bIsInstalled;
}

BOOL IsCharactersAvailableInFont(LPCTSTR szFontName, LPCTSTR characters)
{
HDC hdc;
HFONT hFontOld;
HFONT hFontNew;
BOOL bResult = TRUE;

hFontNew = CreateFont(0, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
szFontName);
if (hFontNew == NULL) return FALSE;

hdc = GetDC(NULL);
hFontOld = (HFONT) SelectObject(hdc, hFontNew);

int count = _tcslen(characters);
WORD* indices = new WORD[count];
DWORD dwRet = GetGlyphIndices(hdc, characters, count, &indices[0],
GGI_MARK_NONEXISTING_GLYPHS);
if (dwRet == GDI_ERROR) {
bResult = FALSE;
} else {
for (int i = 0; i < count; i++) {
if (indices[i] == 0xffff) {
bResult = FALSE;
break;
}
}
}

SelectObject(hdc, hFontOld);
DeleteObject(hFontNew);
ReleaseDC(NULL, hdc);

return bResult;
}


Save above code as "FontUtil.cpp", open a VS2005 environment command
prompt, run command:

cl /LD /D "_UNICODE" /D "UNICODE" FontUtil.cpp user32.lib kernel32.lib
gdi32.lib

This will generate FontUtil.dll.


In your .NET, use following code to check if a CultureInfo.NativeName can
be displayed in Font "MS Shell Dlg", which is a virtual font name when you
use default font in WinForm:

[DllImport(@"FontUtil.dll", CharSet=CharSet.Unicode)]
static extern bool IsCharactersAvailableInFont(string fontName, string
text);

[DllImport(@"FontUtil.dll", CharSet = CharSet.Unicode)]
static extern bool IsFontInstalled(string fontName);

static void Main(string[] args)
{
Console.WriteLine(IsFontInstalled("Berlin Sans FB Demi"));
foreach (CultureInfo ci in
CultureInfo.GetCultures(CultureTypes.AllCultures))
{
if (!IsCharactersAvailableInFont("MS Shell Dlg", ci.NativeName))
{
Console.WriteLine(ci.Name);
}
}
}


Regards,
Walter Wang (wawang@online.microsoft.com, remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
wawang NO[at]SPAM online.microsoft.com (
9/28/2007 12:00:00 AM
minor fix to the CPP code:

delete indices; // add this
return bResult;
}


David Thielen
9/28/2007 9:32:01 AM
Hi;

I really really appreciate you creating this. However, we presently are 100%
managed code and this isn't important enough to add unmanaged code to our app
- so we'll have to live with it writing the far east names in English.

--
thanks - dave
david_at_windward_dot_net
http://www.windwardreports.com

Cubicle Wars - http://www.windwardreports.com/film.htm




[quoted text, click to view]
AddThis Social Bookmark Button