Reputation: 464
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
Upvotes: 0
Views: 236
Reputation: 2769
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.
Upvotes: 1
Reputation: 11321
This is not an answer. I just want to post the code to confirm the timing from this question.
I am getting 7-8 ms for the commented out characters, and ~50 ms for that 0x25A0
.
I use Times New Roman
because this page claims that it has that UNICODE symbol.
#include <iostream>
#include <chrono>
#include <windows.h>
int main()
{
wchar_t b = 0x25A0;
//wchar_t b = 0x0416;
//wchar_t b = L'H';
LPCWSTR s = &b;
HDC hDC = ::GetWindowDC(::GetDesktopWindow());
HFONT hFont = CreateFontW(36, 20, 0, 0, FW_DONTCARE, FALSE, TRUE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, VARIABLE_PITCH, L"Times New Roman");
HGDIOBJ hOld = ::SelectObject(hDC, hFont);
auto t1 = std::chrono::steady_clock::now();
for (int i = 0; i < 1000; i++) {
TextOutW(hDC, 25, 25, s, 1);
}
auto t2 = std::chrono::steady_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count() << " msec" << std::endl;
return 0;
}
Upvotes: 1
Reputation: 308452
The problem is that you're pointing to a single character, not a string. The wcslen
is exhibiting undefined behavior and probably returning a very large number. Replace it with 1
and things should speed up greatly.
Upvotes: 6