Changeset - r11471:14b30a910394
[Not reviewed]
master
0 2 0
rubidium - 15 years ago 2009-03-24 21:23:56
rubidium@openttd.org
(svn r15837) -Codechange: support SETX(Y) with RTL text, swap alignment for RTL text.
2 files changed with 101 insertions and 29 deletions:
0 comments (0 inline, 0 general)
src/gfx.cpp
Show inline comments
 
@@ -18,6 +18,7 @@
 
#include "core/sort_func.hpp"
 
#include "landscape_type.h"
 
#include "network/network_func.h"
 
#include "core/smallvec_type.hpp"
 

	
 
#include "table/palettes.h"
 
#include "table/sprites.h"
 
@@ -394,42 +395,113 @@ static int TruncateString(char *str, int
 
 */
 
static int DrawString(int left, int right, int top, char *str, const char *last, TextColour colour, StringAlignment align, bool underline = false, bool truncate = true)
 
{
 
	/* We need the outer limits of both left/right */
 
	int min_left = INT32_MAX;
 
	int max_right = INT32_MIN;
 

	
 
	int initial_left = left;
 
	int initial_right = right;
 
	int initial_top = top;
 

	
 
	if (truncate) TruncateString(str, right - left);
 
	HandleBiDiAndArabicShapes(str, last);
 

	
 
	int w = GetStringBoundingBox(str).width;
 

	
 
	/* right is the right most position to draw on. In this case we want to do
 
	 * calculations with the width of the string. In comparison right can be
 
	 * seen as lastof(todraw) and width as lengthof(todraw). They differ by 1.
 
	 * So most +1/-1 additions are to move from lengthof to 'indices'.
 
	/*
 
	 * To support SETX and SETXY properly with RTL languages we have to
 
	 * calculate the offsets from the right. To do this we need to split
 
	 * the string and draw the parts separated by SETX(Y).
 
	 * So here we split
 
	 */
 
	switch (align) {
 
		case SA_LEFT:
 
			/* right + 1 = left + w */
 
			right = left + w - 1;
 
			break;
 
	static SmallVector<char *, 4> setx_offsets;
 
	setx_offsets.Clear();
 
	*setx_offsets.Append() = str;
 

	
 
		case SA_CENTER:
 
			/* The second + 1 is to round to the closest number */
 
			left  = (right + 1 + left - w + 1) / 2;
 
			/* right + 1 = left + w */
 
			right = left + w - 1;
 
			break;
 
	char *loc = str;
 
	for (;;) {
 
		WChar c;
 
		/* We cannot use Utf8Consume as we need the location of the SETX(Y) */
 
		size_t len = Utf8Decode(&c, loc);
 
		if (c == '\0') break;
 
		if (c != SCC_SETX && c != SCC_SETXY) {
 
			loc += len;
 
			continue;
 
		}
 

	
 
		case SA_RIGHT:
 
			left = right + 1 - w;
 
			break;
 
		if (align != SA_LEFT) {
 
			DEBUG(grf, 1, "Using SETX and/or SETXY when not aligned to the left. Fixing alignment...");
 
			align = SA_LEFT;
 
		}
 

	
 
		default:
 
			NOT_REACHED();
 
	}
 
	ReallyDoDrawString(str, left, top, colour, !truncate);
 
	if (underline) {
 
		GfxFillRect(left, top + 10, right, top + 10, _string_colourremap[1]);
 
		/* We add the begin of the string, but don't add it twice */
 
		if (loc != str) *setx_offsets.Append() = loc;
 

	
 
		/* Skip the SCC_SETX(Y) ... */
 
		loc += len;
 
		/* ... skip the x coordinate ... */
 
		loc++;
 
		/* ... and finally the y coordinate if it exists */
 
		if (c == SCC_SETXY) loc++;
 
	}
 

	
 
	return align == SA_RIGHT ? left : right;
 
	/* In case we have a RTL language we swap the alignment. */
 
	if (_dynlang.text_dir == TD_RTL && align != SA_CENTER) align = (StringAlignment)(align ^ 2);
 

	
 
	/* Now draw the parts. This is done in the reverse order so we can give the
 
	 * BiDi algorithm the room to replace characters. It also simplifies
 
	 * 'ending' the strings. */
 
	for (char **iter = setx_offsets.End(); iter-- != setx_offsets.Begin(); ) {
 
		char *to_draw = *iter;
 
		WChar c;
 
		size_t len = Utf8Decode(&c, to_draw);
 
		int offset = 0;
 

	
 
		/* Skip the SETX(Y) and set the appropriate offsets. */
 
		if (c == SCC_SETX || c == SCC_SETXY) {
 
			*to_draw = '\0';
 
			to_draw += len;
 
			offset = *to_draw++;
 
			if (c == SCC_SETXY) top = initial_top + *to_draw++;
 
		}
 

	
 
		HandleBiDiAndArabicShapes(to_draw, last);
 
		int w = GetStringBoundingBox(to_draw).width;
 

	
 
		/* right is the right most position to draw on. In this case we want to do
 
		 * calculations with the width of the string. In comparison right can be
 
		 * seen as lastof(todraw) and width as lengthof(todraw). They differ by 1.
 
		 * So most +1/-1 additions are to move from lengthof to 'indices'.
 
		 */
 
		switch (align) {
 
			case SA_LEFT:
 
				/* right + 1 = left + w */
 
				left = initial_left + offset;
 
				right = left + w - 1;
 
				break;
 

	
 
			case SA_CENTER:
 
				/* The second + 1 is to round to the closest number */
 
				left  = (initial_right + 1 + initial_left - w + 1) / 2;
 
				/* right + 1 = left + w */
 
				right = left + w - 1;
 
				break;
 

	
 
			case SA_RIGHT:
 
				left = initial_right + 1 - w - offset;
 
				break;
 

	
 
			default:
 
				NOT_REACHED();
 
		}
 

	
 
		min_left  = min(left, min_left);
 
		max_right = max(right, max_right);
 

	
 
		ReallyDoDrawString(to_draw, left, top, colour, !truncate);
 
		if (underline) {
 
			GfxFillRect(left, top + 10, right, top + 10, _string_colourremap[1]);
 
		}
 
	}
 

	
 
	return align == SA_RIGHT ? min_left : max_right;
 
}
 

	
 
/**
src/station_gui.cpp
Show inline comments
 
@@ -864,7 +864,7 @@ struct StationViewWindow : public Window
 
			assert(b < endof(string));
 

	
 
			SetDParamStr(0, string);
 
			DrawStringMultiLine(this->widget[SVW_ACCEPTLIST].left + 2, this->widget[SVW_ACCEPTLIST].right - 2, this->widget[SVW_ACCEPTLIST].top + 1,this->widget[SVW_ACCEPTLIST].bottom - 1,  STR_JUST_RAW_STRING);
 
			DrawStringMultiLine(this->widget[SVW_ACCEPTLIST].left + 2, this->widget[SVW_ACCEPTLIST].right - 2, this->widget[SVW_ACCEPTLIST].top + 1, this->widget[SVW_ACCEPTLIST].bottom - 1, STR_JUST_RAW_STRING);
 
		} else { // extended window with list of cargo ratings
 
			y = this->widget[SVW_RATINGLIST].top + 1;
 

	
0 comments (0 inline, 0 general)