aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--win32/PlatWin.cxx113
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) {