diff options
| author | Neil <nyamatongwe@gmail.com> | 2015-06-24 16:05:51 +1000 | 
|---|---|---|
| committer | Neil <nyamatongwe@gmail.com> | 2015-06-24 16:05:51 +1000 | 
| commit | 1152a104c7e40c584a5b83bfb211f3d227dc36c7 (patch) | |
| tree | 93e89c87db077fd589957a3642602347e8635858 /win32 | |
| parent | 499682c7b1c9f7ab6f57ecdf7dc7b49460781e21 (diff) | |
| download | scintilla-mirror-1152a104c7e40c584a5b83bfb211f3d227dc36c7.tar.gz | |
Simplify text measurement and drawing by removing segmentation and failure
handling that was needed to support Windows 95.
Diffstat (limited to 'win32')
| -rw-r--r-- | win32/PlatWin.cxx | 113 | 
1 files changed, 25 insertions, 88 deletions
| diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 3bcc183a6..035ea60b9 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -893,46 +893,15 @@ typedef VarBuffer<int, stackBufferLength> TextPositionsI;  void SurfaceGDI::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, UINT fuOptions) {  	SetFont(font_); -	RECT rcw = RectFromPRectangle(rc); -	SIZE sz={0,0}; -	int pos = 0; -	int x = static_cast<int>(rc.left); +	const RECT rcw = RectFromPRectangle(rc); +	const int x = static_cast<int>(rc.left);  	const int yBaseInt = static_cast<int>(ybase); -	// Text drawing may fail if the text is too big. -	// If it does fail, slice up into segments and draw each segment. -	const int maxSegmentLength = 0x200; - -	if (!unicodeMode) { -		// Use ANSI calls -		int lenDraw = Platform::Minimum(len, maxLenText); -		if (!::ExtTextOutA(hdc, x, yBaseInt, fuOptions, &rcw, s, lenDraw, NULL)) { -			while (lenDraw > pos) { -				int seglen = Platform::Minimum(maxSegmentLength, lenDraw - pos); -				if (!::ExtTextOutA(hdc, x, yBaseInt, fuOptions, &rcw, s + pos, seglen, NULL)) { -					PLATFORM_ASSERT(false); -					return; -				} -				::GetTextExtentPoint32A(hdc, s+pos, seglen, &sz); -				x += sz.cx; -				pos += seglen; -			} -		} -	} else { -		// Use Unicode calls +	if (unicodeMode) {  		const TextWide tbuf(s, len, unicodeMode, codePage); -		if (!::ExtTextOutW(hdc, x, yBaseInt, fuOptions, &rcw, tbuf.buffer, tbuf.tlen, NULL)) { -			while (tbuf.tlen > pos) { -				int seglen = Platform::Minimum(maxSegmentLength, tbuf.tlen - pos); -				if (!::ExtTextOutW(hdc, x, yBaseInt, fuOptions, &rcw, tbuf.buffer + pos, seglen, NULL)) { -					PLATFORM_ASSERT(false); -					return; -				} -				::GetTextExtentPoint32W(hdc, tbuf.buffer+pos, seglen, &sz); -				x += sz.cx; -				pos += seglen; -			} -		} +		::ExtTextOutW(hdc, x, yBaseInt, fuOptions, &rcw, tbuf.buffer, tbuf.tlen, NULL); +	} else { +		::ExtTextOutA(hdc, x, yBaseInt, fuOptions, &rcw, s, len, NULL);  	}  } @@ -977,75 +946,43 @@ XYPOSITION SurfaceGDI::WidthText(Font &font_, const char *s, int len) {  }  void SurfaceGDI::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) { +	// Zero positions to avoid random behaviour on failure. +	std::fill(positions, positions + len, 0.0f);  	SetFont(font_);  	SIZE sz={0,0};  	int fit = 0; +	int i = 0;  	if (unicodeMode) {  		const TextWide tbuf(s, len, unicodeMode, codePage);  		TextPositionsI poses(tbuf.tlen); -		fit = tbuf.tlen;  		if (!::GetTextExtentExPointW(hdc, tbuf.buffer, tbuf.tlen, maxWidthMeasure, &fit, poses.buffer, &sz)) { -			// Likely to have failed because on Windows 9x where function not available -			// So measure the character widths by measuring each initial substring -			// Turns a linear operation into a quadratic but seems fast enough on test files -			for (int widthSS=0; widthSS < tbuf.tlen; widthSS++) { -				::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz); -				poses.buffer[widthSS] = sz.cx; -			} +			// Failure +			return;  		}  		// Map the widths given for UTF-16 characters back onto the UTF-8 input string -		int ui=0; -		const unsigned char *us = reinterpret_cast<const unsigned char *>(s); -		int i=0; -		while (ui<fit) { -			unsigned char uch = us[i]; -			unsigned int lenChar = 1; -			if (uch >= (0x80 + 0x40 + 0x20 + 0x10)) { -				lenChar = 4; +		for (int ui = 0; ui < fit; ui++) { +			unsigned int lenChar = UTF8BytesOfLead[static_cast<unsigned char>(s[i])]; +			if (lenChar == 4) {	// Non-BMP  				ui++; -			} else if (uch >= (0x80 + 0x40 + 0x20)) { -				lenChar = 3; -			} else if (uch >= (0x80)) { -				lenChar = 2;  			}  			for (unsigned int bytePos=0; (bytePos<lenChar) && (i<len); bytePos++) {  				positions[i++] = static_cast<XYPOSITION>(poses.buffer[ui]);  			} -			ui++; -		} -		XYPOSITION lastPos = 0.0f; -		if (i > 0) -			lastPos = positions[i-1]; -		while (i<len) { -			positions[i++] = lastPos;  		}  	} else { -		// Zero positions to avoid random behaviour on failure. -		std::fill(positions, positions + len, 0.0f); -		// len may be larger than platform supports so loop over segments small enough for platform -		int startOffset = 0; -		while (len > 0) { -			int lenBlock = Platform::Minimum(len, maxLenText); -			TextPositionsI poses(len); -			if (!::GetTextExtentExPointA(hdc, s, lenBlock, maxWidthMeasure, &fit, poses.buffer, &sz)) { -				// Eeek - a NULL DC or other foolishness could cause this. -				return; -			} else if (fit < lenBlock) { -				// For some reason, such as an incomplete DBCS character -				// Not all the positions are filled in so make them equal to end. -				if (fit == 0) -					poses.buffer[fit++] = 0; -				for (int i = fit; i<lenBlock; i++) -					poses.buffer[i] = poses.buffer[fit-1]; -			} -			for (int i=0; i<lenBlock; i++) -				positions[i] = static_cast<XYPOSITION>(poses.buffer[i] + startOffset); -			startOffset = poses.buffer[lenBlock-1]; -			len -= lenBlock; -			positions += lenBlock; -			s += lenBlock; +		TextPositionsI poses(len); +		if (!::GetTextExtentExPointA(hdc, s, len, maxWidthMeasure, &fit, poses.buffer, &sz)) { +			// Eeek - a NULL DC or other foolishness could cause this. +			return; +		} +		while (i<fit) { +			positions[i] = static_cast<XYPOSITION>(poses.buffer[i]); +			i++;  		}  	} +	// If any positions not filled in then use the last position for them +	const XYPOSITION lastPos = (fit > 0) ? positions[fit - 1] : 0.0f; +	std::fill(positions+i, positions + len, lastPos);  }  XYPOSITION SurfaceGDI::WidthChar(Font &font_, char ch) { | 
