diff options
Diffstat (limited to 'win32/PlatWin.cxx')
| -rw-r--r-- | win32/PlatWin.cxx | 142 | 
1 files changed, 93 insertions, 49 deletions
| diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 63dd56648..7ce9930e4 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -323,20 +323,49 @@ void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {  		surfaceSource.hdc, from.x, from.y, SRCCOPY);  } -#define ASCII_ONLY 1 +int UCS2FromUTF8(const char *s, int len, wchar_t *tbuf, int tlen) { +#ifdef USE_API +	return ::MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, tlen); +#else  +	int ui=0; +	const unsigned char *us = reinterpret_cast<const unsigned char *>(s); +	int i=0; +	while (i<len) { +		unsigned char ch = us[i++]; +		if (ch < 0x80) { +			tbuf[ui] = ch; +		} else if (ch < 0x80 + 0x40 + 0x20) { +			tbuf[ui] = (ch & 0x1F) << 6; +			ch = us[i++]; +			tbuf[ui] += ch & 0x7F; +		} else { +			tbuf[ui] = (ch & 0xF) << 12; +			ch = us[i++]; +			tbuf[ui] += (ch & 0x7F) << 6; +			ch = us[i++]; +			tbuf[ui] += ch & 0x7F; +		} +		ui++; +	} +	return ui; +#endif +} + +#define MAX_US_LEN 5000  void Surface::DrawText(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back) {  	SetFont(font_);  	::SetTextColor(hdc, fore.AsLong());  	::SetBkColor(hdc, back.AsLong());  	RECT rcw = RectFromPRectangle(rc); -#ifdef ASCII_ONLY -	::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, s, len, NULL); -#else -	wchar_t tbuf[20000]; -	int tlen = MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, sizeof(tbuf)); -	::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, tbuf, tlen, NULL); -#endif +	if (unicodeMode) { +		wchar_t tbuf[MAX_US_LEN]; +		int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)); +		tbuf[tlen] = L'\0'; +		::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, tbuf, tlen, NULL); +	} else { +		::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, s, len, NULL); +	}  }  void Surface::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back) { @@ -344,60 +373,75 @@ void Surface::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char  	::SetTextColor(hdc, fore.AsLong());  	::SetBkColor(hdc, back.AsLong());  	RECT rcw = RectFromPRectangle(rc); -#ifdef ASCII_ONLY -	::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, s, len, NULL); -#else -	wchar_t tbuf[20000]; -	int tlen = MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, sizeof(tbuf)); -	::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, tbuf, tlen, NULL); -#endif +	if (unicodeMode) { +		wchar_t tbuf[MAX_US_LEN]; +		int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)); +		tbuf[tlen] = L'\0'; +		::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, tbuf, tlen, NULL); +	} else { +		::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, s, len, NULL); +	}  }  int Surface::WidthText(Font &font_, const char *s, int len) {  	SetFont(font_); -	SIZE sz; -#ifdef ASCII_ONLY -	::GetTextExtentPoint32(hdc, s, len, &sz); -#else -	wchar_t tbuf[20000]; -	int tlen = MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, sizeof(tbuf)); -	::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz); -#endif +	SIZE sz={0,0}; +	if (unicodeMode) { +		int fit = 0; +		wchar_t tbuf[MAX_US_LEN]; +		int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)); +		tbuf[tlen] = L'\0'; +		fit = tlen; +		//::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz); +		if (!::GetTextExtentExPointW(hdc, tbuf, tlen, 30000, &fit, NULL, &sz)) { +			DWORD dw = GetLastError(); +			Platform::DebugPrintf("Error for 1 GTEEPW %d\n", dw); +		} else { +			//Platform::DebugPrintf("OK 1 GTEEPW %d\n", len); +		} +	} else { +		::GetTextExtentPoint32(hdc, s, len, &sz); +	}  	return sz.cx;  }  void Surface::MeasureWidths(Font &font_, const char *s, int len, int *positions) {  	SetFont(font_); -	SIZE sz; +	SIZE sz={0,0};  	int fit = 0; -#ifdef ASCII_ONLY -	::GetTextExtentExPoint(hdc, s, len, 30000, &fit, positions, &sz); -#else -	wchar_t tbuf[20000]; -	int poses[20000]; -	int tlen = MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, sizeof(tbuf)); -	::GetTextExtentExPointW(hdc, tbuf, tlen, 30000, &fit, poses, &sz); -	int ui=0; -	const unsigned char *us = reinterpret_cast<const unsigned char *>(s); -	int i=0; -	while (i<len) { -		positions[i] = poses[ui]; -		if (us[i] < 128) { -			ui++; -		} else if (us[i] < (128 + 64 + 32)) { -			positions[i+1] = poses[ui]; -			ui++; -			i++; +	if (unicodeMode) { +		wchar_t tbuf[MAX_US_LEN]; +		int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)); +		tbuf[tlen] = L'\0'; +		int poses[MAX_US_LEN]; +		fit = tlen; +		SetLastError(0); +		if (!::GetTextExtentExPointW(hdc, tbuf, tlen, 30000, &fit, poses, &sz)) { +			DWORD dw = GetLastError(); +			Platform::DebugPrintf("Error for GTEEPW %d\n", dw);  		} else { -			positions[i+1] = poses[ui]; -			positions[i+2] = poses[ui]; +			//Platform::DebugPrintf("OK GTEEPW %d\n", len); +		} +		int ui=0; +		const unsigned char *us = reinterpret_cast<const unsigned char *>(s); +		int i=0; +		while (i<len) { +			unsigned char uch = us[i]; +			positions[i++] = poses[ui]; +			if (uch >= 0x80) { +				if (uch < (0x80 + 0x40 + 0x20)) { +					positions[i++] = poses[ui]; +				} else { +					positions[i++] = poses[ui]; +					positions[i++] = poses[ui]; +				} +			}  			ui++; -			i++; -			i++;  		} -		i++; +		positions[i] = sz.cx; +	} else { +		::GetTextExtentExPoint(hdc, s, len, 30000, &fit, positions, &sz);  	} -#endif  }  int Surface::WidthChar(Font &font_, char ch) { @@ -704,7 +748,7 @@ int Platform::Maximum(int a, int b) {  		return b;  } -//#define TRACE +#define TRACE  void Platform::DebugPrintf(const char *format, ...) {  #ifdef TRACE | 
