Draw unicode(khmer script) using Graphics.DrawString()

M

mann

I'm trying to send khmer script(unicode) string to printer using
PrintDocument provided by the .NET framework.

Unfortunately it seems to me that the Graphics.DrawString() does not
render khmer script correctly.

Platform: Windows 7 Ultimate
IDE: VS 2010 Ultimate + .NET Framework 4

Here is the sample code:

<iframe src="http://pastebin.com/embed_iframe.php?i=TYyaBQgf"
style="border:none;width:100%"></iframe>

Expected: "សួស្ážáž¸"
But display: "សួស្​ážáž¸"
 
M

mann

Are you sure that you are using the correct characters in your .NET
string?  Are you using a font that includes glyphs for the Khmer
characters you want rendered?

.NET uses Unicode for its strings.  Assuming the string has the correct
characters, then the only other reason the character won't be rendered
correctly is that they simply aren't supported by the font (in many
cases, the printer won't be able to directly support the font, but
usually in that case the printer driver will just use the PC-installed
font and draw a bitmap for the printer…unless, of course, you've got a
driver that allows you to disable that behavior and it's disabled).

Pete

Thanks Pete,
What I need to do in order to see if the font includes glyphs?
The font "Khmer UI" is included by default in Windows 7, also I could
print Khmer character with MS Word 2007 and Notepad++.

Here is the full sample code:
http://paste.ideaslabs.com/show/3yyS0Jmm54

Very appreciate for your active response.
 
K

kndg

Generally, I'd look using the Character Map program.

That said, it appears to me that either .NET or Windows is handling the
Khmer character code points specially (and I suppose it probably does
this for similar scripts). In particular, even when I'm using a font
that Character Map doesn't show to include the specific characters
you're showing in your code, I still get actual characters displayed on
the screen when I use the text in a Forms program.

About now, I'd insert a rant about how screwed up text handling is in
the various APIs (on Windows and otherwise). But that's just a
distraction at this point. :)

For what it's worth, I can see the script characters almost just fine in
my own test app when I use the PrintPreviewDialog. I say "almost",
because while the text shows up as two characters in the form on the
screen, when I draw the same text using the same font during printing,
it shows up as three characters, the middle one with a "+" symbol under
what looks like a normal Khmer script character (in fact, the character
looks just like the first character, except with the "+" symbol instead
of the sort of W-shaped element that appears in the first character).

So, I can verify that it doesn't quite work right on my computer either.
Unfortunately, I don't know what's going wrong, so can't suggest a
work-around.

Pete

I have no knowledge about the Cambodian language, so I'm not sure
whether my findings below is correct or not...

When I try using the supplied "Khmer UI" font, yes it does not display
correctly on the PrintPreviewDialog. However, when I using the
open-source font (link below), it shows and print correctly (at least on
my PC). So, I suspect there is a problem with the Microsoft's supplied
font. The OP may try and see if it is work on his computer.

Link: http://sourceforge.net/projects/khmer/
(I would suggest to try it on virtual system first as the installer will
replace some system file. The OP could also just download and installed
the fonts files by browsing the project files)

Regards.
 
K

kndg

I have no knowledge about the Cambodian language, so I'm not sure
whether my findings below is correct or not...

When I try using the supplied "Khmer UI" font, yes it does not display
correctly on the PrintPreviewDialog. However, when I using the
open-source font (link below), it shows and print correctly (at least on
my PC). So, I suspect there is a problem with the Microsoft's supplied
font. The OP may try and see if it is work on his computer.

Link: http://sourceforge.net/projects/khmer/
(I would suggest to try it on virtual system first as the installer will
replace some system file. The OP could also just download and installed
the fonts files by browsing the project files)

Regards.

I'm sorry, I don't know where I had done it wrong, but after a second
try, when I try to display both text (Expected: "សួស្ážáž¸" and Displayed: "សួស្
​ážáž¸"), both look very identical on my PC. (maybe I had copied it wrong
previously). So, I think there is no problem with Microsoft supplied font...
 
K

kndg

Actually, I should have mentioned this before, but…I think the
"expected" and "display" bit in the OP's message is a red herring.

Both strings use almost identical Unicode characters. The second string
in the post (the "display" one) has an extra character that doesn't
print - '\u200b', which is "zero width space" - in the fifth character
position, but it's otherwise the same string.

Given that the problem description involves print-preview, which has no
copy/paste, it's not clear at all where the "display" string would even
have come from in the first place. But the presence of a zero width
space doesn't to me suggest any actual real difference in the handling
of the display of the string, especially not as it relates to the font
per se.

Pete

Actually, I didn't notice it until I restarted my computer where my news
reader (thunderbird) actually show what the "expected" and "display"
looked like (previously it just displayed as boxed characters). Hmm, it
seems to me that there is a bug in gdi+ that incorrectly show certain
script ('khmer' in this case) to a different wording. (I actually
haven't verify it by creating a native win32 program that directly call
a gdi+ function, but since the Graphics.DrawString() method in .Net just
call the native method in gdi+ library, the possibility is quite high).
I had tried with the WPF version of DrawingContext.DrawText() method,
and it didn't suffer the same problem (which is not a surprise as the
rendering in WPF is through DirectX).
 
M

mann

Actually, I should have mentioned this before, but…I think the
"expected" and "display" bit in the OP's message is a red herring.

Both strings use almost identical Unicode characters.  The second string
in the post (the "display" one) has an extra character that doesn't
print - '\u200b', which is "zero width space" - in the fifth character
position, but it's otherwise the same string.

Given that the problem description involves print-preview, which has no
copy/paste, it's not clear at all where the "display" string would even
have come from in the first place.  But the presence of a zero width
space doesn't to me suggest any actual real difference in the handling
of the display of the string, especially not as it relates to the font
per se.

Pete

Yes Pete, the zero-length space in the fifth character in the OP was
intentionally added to be able to display the difference in the
browser.
The code in

http://paste.ideaslabs.com/show/3yyS0Jmm54

is trying to print "សួស្ážáž¸", the one without zero-length space. But it
doesn't print as expected.
 
K

kndg

Actually, I didn't notice it until I restarted my computer where my news
reader (thunderbird) actually show what the "expected" and "display"
looked like (previously it just displayed as boxed characters). Hmm, it
seems to me that there is a bug in gdi+ that incorrectly show certain
script ('khmer' in this case) to a different wording. (I actually
haven't verify it by creating a native win32 program that directly call
a gdi+ function, but since the Graphics.DrawString() method in .Net just
call the native method in gdi+ library, the possibility is quite high).
I had tried with the WPF version of DrawingContext.DrawText() method,
and it didn't suffer the same problem (which is not a surprise as the
rendering in WPF is through DirectX).

Okay, I actually did a test with a native win32 application (code below)
and yes - there is a problem with gdi+ of DrawString method. At the
moment, I don't know any workaround yet (maybe the OP can post a bug
report to MS Connect) and probably this is a good time for the OP to
migrate to WPF...

#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>

using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

VOID OnPaint(HDC hdc)
{
Graphics graphics(hdc);
SolidBrush brush(Color(255, 0, 0, 255));
FontFamily fontFamily(L"Khmer UI");
Font font(&fontFamily, 64, FontStyleRegular, UnitPixel);
PointF pointF(10.0f, 20.0f);

graphics.DrawString(L"សួស្ážáž¸", -1, &font, pointF, &brush);
}

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;

// Initialize GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = TEXT("Test");

RegisterClass(&wndClass);

hWnd = CreateWindow(
TEXT("Test"), // window class name
TEXT("Test"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters

ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);

while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

GdiplusShutdown(gdiplusToken);
return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
HDC hdc;
PAINTSTRUCT ps;

switch(message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
OnPaint(hdc);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top