Search code examples
c++winapigdi

How To Speed Up Printing Unicode?


I'm using windows.h "TextOutW" function to print text to a bitmap. Printing regular ascii is really fast, but the printing in the unicode range seems to cause a huge slowdown. Here's my code to print a unicode square & test the duration:

wchar_t b = 0x25A0;
LPCWSTR s = &b;
TextOutW(hMyDC, x, y, s, wcslen(s));

Are there any ways of speeding this up?

EDIT: I ran my loop with a timer to test speed:

    using std::chrono::high_resolution_clock;
    using std::chrono::duration_cast;
    using std::chrono::duration;
    using std::chrono::milliseconds;



auto t1 = high_resolution_clock::now();

for(int i = 0; i<1000; i++){
    TextOutW(hMyDC, 25, 25, s, 1);
}
  
auto t2 = high_resolution_clock::now();

  //  auto ms_int = duration_cast<milliseconds>(t2 - t1);
duration<double, std::milli> ms_double = t2 - t1;
    cout << ms_double.count() << "ms\n";

Printing 'H' a 1000 times took around 5ms and printing 0x25A0 1000 times took around 50ms


Solution

  • You are hitting Uniscribe. ExtTextOutW and TextOutW check if text should be threaded through Uniscribe or passed directly to GDI.

    To avoid Uniscribe overhead (NOT RECOMMENDED) you can pass ETO_IGNORELANGUAGE to ExtTextOutW, but you will miss some more advanced scripts (CJK aka Chinese+Japan+Korean, right to left writing, characters changing shape depending on where they are placed etc.) or get no text at all.

    For 0x25A0 character I get slowdown about 8×

    For 0x6F22 slowdown increases to 17×

    On my system, when ETO_IGNORELANGUAGE is specified there is no slowdown. 0x25A0 displays correctly, 0x6F22 is replaced by default box.