Changeset - r28812:d6d9465e39a0
[Not reviewed]
master
0 23 0
Peter Nelson - 5 months ago 2023-12-24 22:51:55
peter1138@openttd.org
Codechange: Remove direct access to _colour_gradient.

Access is now through GetColourGradient, which ensures parameters are in range.
23 files changed with 98 insertions and 65 deletions:
0 comments (0 inline, 0 general)
src/bootstrap_gui.cpp
Show inline comments
 
@@ -376,27 +376,27 @@ bool HandleBootstrap()
 
#if defined(__EMSCRIPTEN__)
 
	new BootstrapEmscripten();
 
#else
 
	/* Initialise the font cache. */
 
	InitializeUnicodeGlyphMap();
 
	/* Next "force" finding a suitable non-sprite font as the local font is missing. */
 
	CheckForMissingGlyphs(false);
 

	
 
	/* Initialise the palette. The biggest step is 'faking' some recolour sprites.
 
	 * This way the mauve and gray colours work and we can show the user interface. */
 
	GfxInitPalettes();
 
	static const int offsets[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0x04, 0x08 };
 
	for (uint i = 0; i != 16; i++) {
 
	for (Colours i = COLOUR_BEGIN; i != COLOUR_END; i++) {
 
		for (int j = 0; j < 8; j++) {
 
			_colour_gradient[i][j] = offsets[i] + j;
 
			SetColourGradient(i, j, offsets[i] + j);
 
		}
 
	}
 

	
 
	/* Finally ask the question. */
 
	new BootstrapBackground();
 
	new BootstrapAskForDownloadWindow();
 
#endif /* __EMSCRIPTEN__ */
 

	
 
	/* Process the user events. */
 
	VideoDriver::GetInstance()->MainLoop();
 

	
 
	/* _exit_game is used to get out of the video driver's main loop.
src/build_vehicle_gui.cpp
Show inline comments
 
@@ -1008,25 +1008,25 @@ void DrawEngineList(VehicleType type, co
 
{
 
	static const int sprite_y_offsets[] = { -1, -1, -2, -2 };
 

	
 
	/* Obligatory sanity checks! */
 
	assert(max <= eng_list.size());
 

	
 
	bool rtl = _current_text_dir == TD_RTL;
 
	int step_size = GetEngineListHeight(type);
 
	int sprite_left  = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_left;
 
	int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right;
 
	int sprite_width = sprite_left + sprite_right;
 
	int circle_width = std::max(GetScaledSpriteSize(SPR_CIRCLE_FOLDED).width, GetScaledSpriteSize(SPR_CIRCLE_UNFOLDED).width);
 
	int linecolour = _colour_gradient[COLOUR_ORANGE][4];
 
	int linecolour = GetColourGradient(COLOUR_ORANGE, 4);
 

	
 
	Rect ir      = r.WithHeight(step_size).Shrink(WidgetDimensions::scaled.matrix);
 
	int sprite_y_offset = ScaleSpriteTrad(sprite_y_offsets[type]) + ir.Height() / 2;
 

	
 
	Dimension replace_icon = {0, 0};
 
	int count_width = 0;
 
	if (show_count) {
 
		replace_icon = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE);
 

	
 
		uint biggest_num_engines = 0;
 
		for (auto i = min; i < max; i++) {
 
			const auto &item = eng_list[i];
src/company_cmd.cpp
Show inline comments
 
@@ -137,26 +137,26 @@ void SetLocalCompany(CompanyID new_compa
 
	MarkWholeScreenDirty();
 
	InvalidateWindowClassesData(WC_SIGN_LIST, -1);
 
	InvalidateWindowClassesData(WC_GOALS_LIST);
 
}
 

	
 
/**
 
 * Get the colour for DrawString-subroutines which matches the colour of the company.
 
 * @param company Company to get the colour of.
 
 * @return Colour of \a company.
 
 */
 
TextColour GetDrawStringCompanyColour(CompanyID company)
 
{
 
	if (!Company::IsValidID(company)) return (TextColour)_colour_gradient[COLOUR_WHITE][4] | TC_IS_PALETTE_COLOUR;
 
	return (TextColour)_colour_gradient[_company_colours[company]][4] | TC_IS_PALETTE_COLOUR;
 
	if (!Company::IsValidID(company)) return (TextColour)GetColourGradient(COLOUR_WHITE, 4) | TC_IS_PALETTE_COLOUR;
 
	return (TextColour)GetColourGradient(_company_colours[company], 4) | TC_IS_PALETTE_COLOUR;
 
}
 

	
 
/**
 
 * Draw the icon of a company.
 
 * @param c Company that needs its icon drawn.
 
 * @param x Horizontal coordinate of the icon.
 
 * @param y Vertical coordinate of the icon.
 
 */
 
void DrawCompanyIcon(CompanyID c, int x, int y)
 
{
 
	DrawSprite(SPR_COMPANY_ICON, COMPANY_SPRITE_COLOUR(c), x, y);
 
}
 
@@ -468,25 +468,25 @@ static const Colours _similar_colour[COL
 
	{ COLOUR_GREY,       INVALID_COLOUR    }, // COLOUR_WHITE
 
};
 

	
 
/**
 
 * Generate a company colour.
 
 * @return Generated company colour.
 
 */
 
static Colours GenerateCompanyColour()
 
{
 
	Colours colours[COLOUR_END];
 

	
 
	/* Initialize array */
 
	for (uint i = 0; i < COLOUR_END; i++) colours[i] = (Colours)i;
 
	for (uint i = 0; i < COLOUR_END; i++) colours[i] = static_cast<Colours>(i);
 

	
 
	/* And randomize it */
 
	for (uint i = 0; i < 100; i++) {
 
		uint r = Random();
 
		Swap(colours[GB(r, 0, 4)], colours[GB(r, 4, 4)]);
 
	}
 

	
 
	/* Bubble sort it according to the values in table 1 */
 
	for (uint i = 0; i < COLOUR_END; i++) {
 
		for (uint j = 1; j < COLOUR_END; j++) {
 
			if (_colour_sort[colours[j - 1]] < _colour_sort[colours[j]]) {
 
				Swap(colours[j - 1], colours[j]);
src/console_gui.cpp
Show inline comments
 
@@ -484,18 +484,18 @@ static bool TruncateBuffer()
 
 * Check whether the given TextColour is valid for console usage.
 
 * @param c The text colour to compare to.
 
 * @return true iff the TextColour is valid for console usage.
 
 */
 
bool IsValidConsoleColour(TextColour c)
 
{
 
	/* A normal text colour is used. */
 
	if (!(c & TC_IS_PALETTE_COLOUR)) return TC_BEGIN <= c && c < TC_END;
 

	
 
	/* A text colour from the palette is used; must be the company
 
	 * colour gradient, so it must be one of those. */
 
	c &= ~TC_IS_PALETTE_COLOUR;
 
	for (uint i = COLOUR_BEGIN; i < COLOUR_END; i++) {
 
		if (_colour_gradient[i][4] == c) return true;
 
	for (Colours i = COLOUR_BEGIN; i < COLOUR_END; i++) {
 
		if (GetColourGradient(i, 4) == c) return true;
 
	}
 

	
 
	return false;
 
}
src/depot_gui.cpp
Show inline comments
 
@@ -375,25 +375,25 @@ struct DepotWindow : Window {
 
		/* Set up rect for each cell */
 
		Rect ir = r.WithHeight(this->resize.step_height);
 
		if (this->num_columns != 1) ir = ir.WithWidth(this->resize.step_width, rtl);
 
		ir = ir.Shrink(WidgetDimensions::scaled.framerect, RectPadding::zero);
 

	
 
		/* Draw vertical separators at whole tiles.
 
		 * This only works in two cases:
 
		 *  - All vehicles use VEHICLEINFO_FULL_VEHICLE_WIDTH as reference width.
 
		 *  - All vehicles are 8/8. This cannot be checked for NewGRF, so instead we check for "all vehicles are original vehicles".
 
		 */
 
		if (this->type == VEH_TRAIN && _consistent_train_width != 0) {
 
			int w = ScaleSpriteTrad(2 * _consistent_train_width);
 
			int col = _colour_gradient[wid->colour][4];
 
			int col = GetColourGradient(wid->colour, 4);
 
			Rect image = ir.Indent(this->header_width, rtl).Indent(this->count_width, !rtl);
 
			int first_line = w + (-this->hscroll->GetPosition()) % w;
 
			if (rtl) {
 
				for (int x = image.right - first_line; x >= image.left; x -= w) {
 
					GfxDrawLine(x, r.top, x, r.bottom, col, ScaleGUITrad(1), ScaleGUITrad(3));
 
				}
 
			} else {
 
				for (int x = image.left + first_line; x <= image.right; x += w) {
 
					GfxDrawLine(x, r.top, x, r.bottom, col, ScaleGUITrad(1), ScaleGUITrad(3));
 
				}
 
			}
 
		}
src/gfx_type.h
Show inline comments
 
@@ -2,24 +2,25 @@
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
/** @file gfx_type.h Types related to the graphics and/or input devices. */
 

	
 
#ifndef GFX_TYPE_H
 
#define GFX_TYPE_H
 

	
 
#include "core/endian_type.hpp"
 
#include "core/enum_type.hpp"
 
#include "core/geometry_type.hpp"
 
#include "zoom_type.h"
 

	
 
typedef uint32_t SpriteID;  ///< The number of a sprite, without mapping bits and colourtables
 
typedef uint32_t PaletteID; ///< The number of the palette
 
typedef uint32_t CursorID;  ///< The number of the cursor (sprite)
 

	
 
/** Combination of a palette sprite and a 'real' sprite */
 
struct PalSpriteID {
 
	SpriteID sprite;  ///< The 'real' sprite
 
	PaletteID pal;    ///< The palette (use \c PAL_NONE) if not needed)
 
};
 
@@ -238,24 +239,25 @@ enum Colours : byte {
 
	COLOUR_DARK_GREEN,
 
	COLOUR_BLUE,
 
	COLOUR_CREAM,
 
	COLOUR_MAUVE,
 
	COLOUR_PURPLE,
 
	COLOUR_ORANGE,
 
	COLOUR_BROWN,
 
	COLOUR_GREY,
 
	COLOUR_WHITE,
 
	COLOUR_END,
 
	INVALID_COLOUR = 0xFF,
 
};
 
DECLARE_POSTFIX_INCREMENT(Colours)
 
DECLARE_ENUM_AS_ADDABLE(Colours)
 

	
 
/** Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palette.png */
 
enum TextColour {
 
	TC_BEGIN       = 0x00,
 
	TC_FROMSTRING  = 0x00,
 
	TC_BLUE        = 0x00,
 
	TC_SILVER      = 0x01,
 
	TC_GOLD        = 0x02,
 
	TC_RED         = 0x03,
 
	TC_PURPLE      = 0x04,
 
	TC_LIGHT_BROWN = 0x05,
src/graph_gui.cpp
Show inline comments
 
@@ -618,25 +618,25 @@ public:
 
			return;
 
		}
 

	
 
		this->excluded_data = excluded_companies;
 
		this->num_on_x_axis = nums;
 
		this->year = yr;
 
		this->month = mo;
 

	
 
		int numd = 0;
 
		for (CompanyID k = COMPANY_FIRST; k < MAX_COMPANIES; k++) {
 
			const Company *c = Company::GetIfValid(k);
 
			if (c != nullptr) {
 
				this->colours[numd] = _colour_gradient[c->colour][6];
 
				this->colours[numd] = GetColourGradient(c->colour, 6);
 
				for (int j = this->num_on_x_axis, i = 0; --j >= 0;) {
 
					if (j >= c->num_valid_stat_ent) {
 
						this->cost[numd][i] = INVALID_DATAPOINT;
 
					} else {
 
						/* Ensure we never assign INVALID_DATAPOINT, as that has another meaning.
 
						 * Instead, use the value just under it. Hopefully nobody will notice. */
 
						this->cost[numd][i] = std::min(GetGraphData(c, j), INVALID_DATAPOINT - 1);
 
					}
 
					i++;
 
				}
 
			}
 
			numd++;
 
@@ -1285,26 +1285,26 @@ struct PerformanceRatingDetailWindow : W
 
			if (this->IsWidgetDisabled(widget)) return;
 
			CompanyID cid = (CompanyID)(widget - WID_PRD_COMPANY_FIRST);
 
			Dimension sprite_size = GetSpriteSize(SPR_COMPANY_ICON);
 
			DrawCompanyIcon(cid, CenterBounds(r.left, r.right, sprite_size.width), CenterBounds(r.top, r.bottom, sprite_size.height));
 
			return;
 
		}
 

	
 
		if (!IsInsideMM(widget, WID_PRD_SCORE_FIRST, WID_PRD_SCORE_LAST + 1)) return;
 

	
 
		ScoreID score_type = (ScoreID)(widget - WID_PRD_SCORE_FIRST);
 

	
 
		/* The colours used to show how the progress is going */
 
		int colour_done = _colour_gradient[COLOUR_GREEN][4];
 
		int colour_notdone = _colour_gradient[COLOUR_RED][4];
 
		int colour_done = GetColourGradient(COLOUR_GREEN, 4);
 
		int colour_notdone = GetColourGradient(COLOUR_RED, 4);
 

	
 
		/* Draw all the score parts */
 
		int64_t val    = _score_part[company][score_type];
 
		int64_t needed = _score_info[score_type].needed;
 
		int   score  = _score_info[score_type].score;
 

	
 
		/* SCORE_TOTAL has its own rules ;) */
 
		if (score_type == SCORE_TOTAL) {
 
			for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) score += _score_info[i].score;
 
			needed = SCORE_MAX;
 
		}
 

	
src/group_gui.cpp
Show inline comments
 
@@ -253,25 +253,25 @@ private:
 
	 * @param y Top of the row.
 
	 * @param left Left of the row.
 
	 * @param right Right of the row.
 
	 * @param g_id Group to list.
 
	 * @param indent Indentation level.
 
	 * @param protection Whether autoreplace protection is set.
 
	 * @param has_children Whether the group has children and should have a fold / unfold button.
 
	 */
 
	void DrawGroupInfo(int y, int left, int right, GroupID g_id, int indent = 0, bool protection = false, bool has_children = false) const
 
	{
 
		/* Highlight the group if a vehicle is dragged over it */
 
		if (g_id == this->group_over) {
 
			GfxFillRect(left + WidgetDimensions::scaled.bevel.left, y + WidgetDimensions::scaled.framerect.top, right - WidgetDimensions::scaled.bevel.right, y + this->tiny_step_height - 1 - WidgetDimensions::scaled.framerect.bottom, _colour_gradient[COLOUR_GREY][7]);
 
			GfxFillRect(left + WidgetDimensions::scaled.bevel.left, y + WidgetDimensions::scaled.framerect.top, right - WidgetDimensions::scaled.bevel.right, y + this->tiny_step_height - 1 - WidgetDimensions::scaled.framerect.bottom, GetColourGradient(COLOUR_GREY, 7));
 
		}
 

	
 
		if (g_id == NEW_GROUP) return;
 

	
 
		/* draw the selected group in white, else we draw it in black */
 
		TextColour colour = g_id == this->vli.index ? TC_WHITE : TC_BLACK;
 
		const GroupStatistics &stats = GroupStatistics::Get(this->vli.company, g_id, this->vli.vtype);
 
		bool rtl = _current_text_dir == TD_RTL;
 

	
 
		/* draw fold / unfold button */
 
		int x = rtl ? right - WidgetDimensions::scaled.framerect.right - this->column_size[VGC_FOLD].width + 1 : left + WidgetDimensions::scaled.framerect.left;
 
		if (has_children) {
 
@@ -621,25 +621,25 @@ public:
 
			case WID_GL_SORT_BY_ORDER:
 
				this->DrawSortButtonState(WID_GL_SORT_BY_ORDER, this->vehgroups.IsDescSortOrder() ? SBS_DOWN : SBS_UP);
 
				break;
 

	
 
			case WID_GL_LIST_VEHICLE:
 
				if (this->vli.index != ALL_GROUP && this->grouping == GB_NONE) {
 
					/* Mark vehicles which are in sub-groups (only if we are not using shared order coalescing) */
 
					Rect mr = r.WithHeight(this->resize.step_height);
 
					size_t max = std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->vehgroups.size());
 
					for (size_t i = this->vscroll->GetPosition(); i < max; ++i) {
 
						const Vehicle *v = this->vehgroups[i].GetSingleVehicle();
 
						if (v->group_id != this->vli.index) {
 
							GfxFillRect(mr.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[COLOUR_GREY][3], FILLRECT_CHECKER);
 
							GfxFillRect(mr.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(COLOUR_GREY, 3), FILLRECT_CHECKER);
 
						}
 
						mr = mr.Translate(0, this->resize.step_height);
 
					}
 
				}
 

	
 
				this->DrawVehicleListItems(this->vehicle_sel, this->resize.step_height, r);
 
				break;
 
		}
 
	}
 

	
 
	static void DeleteGroupCallback(Window *win, bool confirmed)
 
	{
src/linkgraph/linkgraph_gui.cpp
Show inline comments
 
@@ -303,46 +303,46 @@ void LinkGraphOverlay::DrawContent(Point
 

	
 
	/* Move line a bit 90° against its dominant direction to prevent it from
 
	 * being hidden below the grey line. */
 
	int side = _settings_game.vehicle.road_side ? 1 : -1;
 
	if (abs(pta.x - ptb.x) < abs(pta.y - ptb.y)) {
 
		int offset_x = (pta.y > ptb.y ? 1 : -1) * side * width;
 
		GfxDrawLine(pta.x + offset_x, pta.y, ptb.x + offset_x, ptb.y, colour, width, dash);
 
	} else {
 
		int offset_y = (pta.x < ptb.x ? 1 : -1) * side * width;
 
		GfxDrawLine(pta.x, pta.y + offset_y, ptb.x, ptb.y + offset_y, colour, width, dash);
 
	}
 

	
 
	GfxDrawLine(pta.x, pta.y, ptb.x, ptb.y, _colour_gradient[COLOUR_GREY][1], width);
 
	GfxDrawLine(pta.x, pta.y, ptb.x, ptb.y, GetColourGradient(COLOUR_GREY, 1), width);
 
}
 

	
 
/**
 
 * Draw dots for stations into the smallmap. The dots' sizes are determined by the amount of
 
 * cargo produced there, their colours by the type of cargo produced.
 
 */
 
void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
 
{
 
	int width = ScaleGUITrad(this->scale);
 
	for (const auto &i : this->cached_stations) {
 
		const Station *st = Station::GetIfValid(i.first);
 
		if (st == nullptr) continue;
 
		Point pt = this->GetStationMiddle(st);
 
		if (!this->IsPointVisible(pt, dpi, 3 * width)) continue;
 

	
 
		uint r = width * 2 + width * 2 * std::min(200U, i.second) / 200;
 

	
 
		LinkGraphOverlay::DrawVertex(pt.x, pt.y, r,
 
				_colour_gradient[st->owner != OWNER_NONE ?
 
						Company::Get(st->owner)->colour : COLOUR_GREY][5],
 
				_colour_gradient[COLOUR_GREY][1]);
 
				GetColourGradient(st->owner != OWNER_NONE ?
 
						Company::Get(st->owner)->colour : COLOUR_GREY, 5),
 
				GetColourGradient(COLOUR_GREY, 1));
 
	}
 
}
 

	
 
/**
 
 * Draw a square symbolizing a producer of cargo.
 
 * @param x X coordinate of the middle of the vertex.
 
 * @param y Y coordinate of the middle of the vertex.
 
 * @param size x and y extent of the vertex.
 
 * @param colour Colour with which the vertex will be filled.
 
 * @param border_colour Colour for the border of the vertex.
 
 */
 
/* static */ void LinkGraphOverlay::DrawVertex(int x, int y, int size, int colour, int border_colour)
src/main_gui.cpp
Show inline comments
 
@@ -531,29 +531,30 @@ bool IsQuitKey(uint16_t keycode)
 
	int num = MainWindow::hotkeys.CheckMatch(keycode);
 
	return num == GHK_QUIT;
 
}
 

	
 

	
 
void ShowSelectGameWindow();
 

	
 
/**
 
 * Initialise the default colours (remaps and the likes), and load the main windows.
 
 */
 
void SetupColoursAndInitialWindow()
 
{
 
	for (uint i = 0; i != 16; i++) {
 
	for (Colours i = COLOUR_BEGIN; i != COLOUR_END; i++) {
 
		const byte *b = GetNonSprite(GENERAL_SPRITE_COLOUR(i), SpriteType::Recolour);
 

	
 
		assert(b);
 
		memcpy(_colour_gradient[i], b + 0xC6, sizeof(_colour_gradient[i]));
 
		assert(b != nullptr);
 
		for (uint j = 0; j < 8; j++) {
 
			SetColourGradient(i, j, b[0xC6 + j]);
 
		}
 
	}
 

	
 
	new MainWindow(&_main_window_desc);
 

	
 
	/* XXX: these are not done */
 
	switch (_game_mode) {
 
		default: NOT_REACHED();
 
		case GM_MENU:
 
			ShowSelectGameWindow();
 
			break;
 

	
 
		case GM_NORMAL:
src/misc_gui.cpp
Show inline comments
 
@@ -785,25 +785,25 @@ void QueryString::DrawEditBox(const Wind
 
	assert((wi->type & WWT_MASK) == WWT_EDITBOX);
 

	
 
	bool rtl = _current_text_dir == TD_RTL;
 
	Dimension sprite_size = GetScaledSpriteSize(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT);
 
	int clearbtn_width = sprite_size.width + WidgetDimensions::scaled.imgbtn.Horizontal();
 

	
 
	Rect r = wi->GetCurrentRect();
 
	Rect cr = r.WithWidth(clearbtn_width, !rtl);
 
	Rect fr = r.Indent(clearbtn_width, !rtl);
 

	
 
	DrawFrameRect(cr, wi->colour, wi->IsLowered() ? FR_LOWERED : FR_NONE);
 
	DrawSpriteIgnorePadding(rtl ? SPR_IMG_DELETE_RIGHT : SPR_IMG_DELETE_LEFT, PAL_NONE, cr, SA_CENTER);
 
	if (this->text.bytes == 1) GfxFillRect(cr.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[wi->colour & 0xF][2], FILLRECT_CHECKER);
 
	if (this->text.bytes == 1) GfxFillRect(cr.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(wi->colour, 2), FILLRECT_CHECKER);
 

	
 
	DrawFrameRect(fr, wi->colour, FR_LOWERED | FR_DARKENED);
 
	GfxFillRect(fr.Shrink(WidgetDimensions::scaled.bevel), PC_BLACK);
 

	
 
	fr = fr.Shrink(WidgetDimensions::scaled.framerect);
 
	/* Limit the drawing of the string inside the widget boundaries */
 
	DrawPixelInfo dpi;
 
	if (!FillDrawPixelInfo(&dpi, fr)) return;
 

	
 
	AutoRestoreBackup dpi_backup(_cur_dpi, &dpi);
 

	
 
	/* We will take the current widget length as maximum width, with a small
src/network/network_gui.cpp
Show inline comments
 
@@ -1937,25 +1937,25 @@ public:
 
		for (auto &button : buttons) {
 
			bool rtl = _current_text_dir == TD_RTL;
 

	
 
			int offset = (this->line_height - button->height) / 2;
 
			r.left = rtl ? x : x - button->width + 1;
 
			r.right = rtl ? x + button->width - 1 : x;
 
			r.top = y + offset;
 
			r.bottom = r.top + button->height - 1;
 

	
 
			DrawFrameRect(r, button->colour, FR_NONE);
 
			DrawSprite(button->sprite, PAL_NONE, r.left + WidgetDimensions::scaled.framerect.left, r.top + WidgetDimensions::scaled.framerect.top);
 
			if (button->disabled) {
 
				GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[button->colour & 0xF][2], FILLRECT_CHECKER);
 
				GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(button->colour, 2), FILLRECT_CHECKER);
 
			}
 

	
 
			int width = button->width + WidgetDimensions::scaled.hsep_normal;
 
			x += rtl ? width : -width;
 
		}
 
	}
 

	
 
	/**
 
	 * Draw a company and its clients on the matrix.
 
	 * @param company_id The company to draw.
 
	 * @param r The rect to draw within.
 
	 * @param line The Nth line we are drawing. Updated during this function.
src/order_gui.cpp
Show inline comments
 
@@ -1115,25 +1115,25 @@ public:
 
		const Order *order = this->vehicle->GetOrder(i);
 
		/* First draw the highlighting underground if it exists. */
 
		if (this->order_over != INVALID_VEH_ORDER_ID) {
 
			while (order != nullptr) {
 
				/* Don't draw anything if it extends past the end of the window. */
 
				if (!this->vscroll->IsVisible(i)) break;
 

	
 
				if (i != this->selected_order && i == this->order_over) {
 
					/* Highlight dragged order destination. */
 
					int top = (this->order_over < this->selected_order ? y : y + line_height) - WidgetDimensions::scaled.framerect.top;
 
					int bottom = std::min(top + 2, ir.bottom);
 
					top = std::max(top - 3, ir.top);
 
					GfxFillRect(ir.left, top, ir.right, bottom, _colour_gradient[COLOUR_GREY][7]);
 
					GfxFillRect(ir.left, top, ir.right, bottom, GetColourGradient(COLOUR_GREY, 7));
 
					break;
 
				}
 
				y += line_height;
 

	
 
				i++;
 
				order = order->next;
 
			}
 

	
 
			/* Reset counters for drawing the orders. */
 
			y = ir.top;
 
			i = this->vscroll->GetPosition();
 
			order = this->vehicle->GetOrder(i);
src/palette.cpp
Show inline comments
 
@@ -14,26 +14,24 @@
 
#include "gfx_type.h"
 
#include "landscape_type.h"
 
#include "palette_func.h"
 
#include "settings_type.h"
 
#include "thread.h"
 

	
 
#include "table/palettes.h"
 

	
 
#include "safeguards.h"
 

	
 
Palette _cur_palette;
 

	
 
byte _colour_gradient[COLOUR_END][8];
 

	
 
static std::recursive_mutex _palette_mutex; ///< To coordinate access to _cur_palette.
 

	
 
/**
 
 * PALETTE_BITS reduces the bits-per-channel of 32bpp graphics data to allow faster palette lookups from
 
 * a smaller lookup table.
 
 *
 
 * 6 bpc is chosen as this results in a palette lookup table of 256KiB with adequate fidelty.
 
 * In constract, a 5 bpc lookup table would be 32KiB, and 7 bpc would be 2MiB.
 
 *
 
 * Values in the table are filled as they are first encountered -- larger lookup table means more colour
 
 * distance calculations, and is therefore slower.
 
 */
 
@@ -286,12 +284,47 @@ void DoPaletteAnimations()
 
 * @param threshold Background colour brightness threshold below which the background is considered dark and TC_WHITE is returned, range: 0 - 255, default 128.
 
 * @return TC_BLACK or TC_WHITE depending on what gives a better contrast.
 
 */
 
TextColour GetContrastColour(uint8_t background, uint8_t threshold)
 
{
 
	Colour c = _cur_palette.palette[background];
 
	/* Compute brightness according to http://www.w3.org/TR/AERT#color-contrast.
 
	 * The following formula computes 1000 * brightness^2, with brightness being in range 0 to 255. */
 
	uint sq1000_brightness = c.r * c.r * 299 + c.g * c.g * 587 + c.b * c.b * 114;
 
	/* Compare with threshold brightness which defaults to 128 (50%) */
 
	return sq1000_brightness < ((uint) threshold) * ((uint) threshold) * 1000 ? TC_WHITE : TC_BLACK;
 
}
 

	
 
/**
 
 * Lookup table of colour shades for all 16 colour gradients.
 
 * 8 colours per gradient from darkest (0) to lightest (7)
 
 */
 
struct ColourGradients
 
{
 
	using ColourGradient = std::array<byte, 8>;
 

	
 
	static inline std::array<ColourGradient, COLOUR_END> gradient{};
 
};
 

	
 
/**
 
 * Get colour gradient palette index.
 
 * @param colour Colour.
 
 * @param shade Shade level from 1 to 7.
 
 * @returns palette index of colour.
 
 */
 
byte GetColourGradient(Colours colour, uint8_t shade)
 
{
 
	return ColourGradients::gradient[colour % COLOUR_END][shade % 8];
 
}
 

	
 
/**
 
 * Set colour gradient palette index.
 
 * @param colour Colour.
 
 * @param shade Shade level from 1 to 7.
 
 * @param palette_index Palette index to set.
 
 */
 
void SetColourGradient(Colours colour, uint8_t shade, byte palette_index)
 
{
 
	assert(colour < COLOUR_END);
 
	assert(shade < 8);
 
	ColourGradients::gradient[colour % COLOUR_END][shade % 8] = palette_index;
 
}
src/palette_func.h
Show inline comments
 
@@ -30,29 +30,26 @@ inline uint8_t GetNearestColourIndex(con
 
 * Checks if a Colours value is valid.
 
 *
 
 * @param colours The value to check
 
 * @return true if the given value is a valid Colours.
 
 */
 
inline bool IsValidColours(Colours colours)
 
{
 
	return colours < COLOUR_END;
 
}
 

	
 
TextColour GetContrastColour(uint8_t background, uint8_t threshold = 128);
 

	
 
/**
 
 * All 16 colour gradients
 
 * 8 colours per gradient from darkest (0) to lightest (7)
 
 */
 
extern byte _colour_gradient[COLOUR_END][8];
 
byte GetColourGradient(Colours colour, uint8_t shade);
 
void SetColourGradient(Colours colour, uint8_t shade, byte palette_colour);
 

	
 
/**
 
 * Return the colour for a particular greyscale level.
 
 * @param level Intensity, 0 = black, 15 = white
 
 * @return colour
 
 */
 
#define GREY_SCALE(level) (level)
 

	
 
static const uint8_t PC_BLACK              = GREY_SCALE(1);  ///< Black palette colour.
 
static const uint8_t PC_DARK_GREY          = GREY_SCALE(6);  ///< Dark grey palette colour.
 
static const uint8_t PC_GREY               = GREY_SCALE(10); ///< Grey palette colour.
 
static const uint8_t PC_WHITE              = GREY_SCALE(15); ///< White palette colour.
src/settings_gui.cpp
Show inline comments
 
@@ -1405,25 +1405,25 @@ BaseSettingEntry *BaseSettingEntry::Find
 
 */
 
uint BaseSettingEntry::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
 
{
 
	if (this->IsFiltered()) return cur_row;
 
	if (cur_row >= max_row) return cur_row;
 

	
 
	bool rtl = _current_text_dir == TD_RTL;
 
	int offset = (rtl ? -(int)_circle_size.width : (int)_circle_size.width) / 2;
 
	int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent;
 

	
 
	int x = rtl ? right : left;
 
	if (cur_row >= first_row) {
 
		int colour = _colour_gradient[COLOUR_ORANGE][4];
 
		int colour = GetColourGradient(COLOUR_ORANGE, 4);
 
		y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
 

	
 
		/* Draw vertical for parent nesting levels */
 
		for (uint lvl = 0; lvl < this->level; lvl++) {
 
			if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
 
			x += level_width;
 
		}
 
		/* draw own |- prefix */
 
		int halfway_y = y + SETTING_HEIGHT / 2;
 
		int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
 
		GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
 
		/* Small horizontal line from the last vertical line */
 
@@ -2900,25 +2900,25 @@ void ShowGameSettings()
 

	
 
/**
 
 * Draw [<][>] boxes.
 
 * @param x the x position to draw
 
 * @param y the y position to draw
 
 * @param button_colour the colour of the button
 
 * @param state 0 = none clicked, 1 = first clicked, 2 = second clicked
 
 * @param clickable_left is the left button clickable?
 
 * @param clickable_right is the right button clickable?
 
 */
 
void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
 
{
 
	int colour = _colour_gradient[button_colour][2];
 
	int colour = GetColourGradient(button_colour, 2);
 
	Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
 

	
 
	Rect lr = {x,                  y, x + (int)dim.width     - 1, y + (int)dim.height - 1};
 
	Rect rr = {x + (int)dim.width, y, x + (int)dim.width * 2 - 1, y + (int)dim.height - 1};
 

	
 
	DrawFrameRect(lr, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
 
	DrawFrameRect(rr, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
 
	DrawSpriteIgnorePadding(SPR_ARROW_LEFT,  PAL_NONE, lr, SA_CENTER);
 
	DrawSpriteIgnorePadding(SPR_ARROW_RIGHT, PAL_NONE, rr, SA_CENTER);
 

	
 
	/* Grey out the buttons that aren't clickable */
 
	bool rtl = _current_text_dir == TD_RTL;
 
@@ -2931,25 +2931,25 @@ void DrawArrowButtons(int x, int y, Colo
 
}
 

	
 
/**
 
 * Draw a dropdown button.
 
 * @param x the x position to draw
 
 * @param y the y position to draw
 
 * @param button_colour the colour of the button
 
 * @param state true = lowered
 
 * @param clickable is the button clickable?
 
 */
 
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
 
{
 
	int colour = _colour_gradient[button_colour][2];
 
	int colour = GetColourGradient(button_colour, 2);
 

	
 
	Rect r = {x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1};
 

	
 
	DrawFrameRect(r, button_colour, state ? FR_LOWERED : FR_NONE);
 
	DrawSpriteIgnorePadding(SPR_ARROW_DOWN, PAL_NONE, r, SA_CENTER);
 

	
 
	if (!clickable) {
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), colour, FILLRECT_CHECKER);
 
	}
 
}
 

	
 
/**
src/smallmap_gui.cpp
Show inline comments
 
@@ -337,25 +337,25 @@ void BuildLandLegend()
 
	_legend_land_contours[i].end = true;
 
}
 

	
 
/**
 
 * Completes the array for the owned property legend.
 
 */
 
void BuildOwnerLegend()
 
{
 
	_legend_land_owners[1].colour = _heightmap_schemes[_settings_client.gui.smallmap_land_colour].default_colour;
 

	
 
	int i = NUM_NO_COMPANY_ENTRIES;
 
	for (const Company *c : Company::Iterate()) {
 
		_legend_land_owners[i].colour = _colour_gradient[c->colour][5];
 
		_legend_land_owners[i].colour = GetColourGradient(c->colour, 5);
 
		_legend_land_owners[i].company = c->index;
 
		_legend_land_owners[i].show_on_map = true;
 
		_legend_land_owners[i].col_break = false;
 
		_legend_land_owners[i].end = false;
 
		_company_to_list_pos[c->index] = i;
 
		i++;
 
	}
 

	
 
	/* Terminate the list */
 
	_legend_land_owners[i].end = true;
 

	
 
	/* Store maximum amount of owner legend entries. */
src/train_gui.cpp
Show inline comments
 
@@ -67,25 +67,25 @@ static int HighlightDragPosition(int px,
 
		dragged_width += t->GetDisplayImageWidth(nullptr);
 
	}
 

	
 
	int drag_hlight_left = rtl ? std::max(px - dragged_width + 1, 0) : px;
 
	int drag_hlight_right = rtl ? px : std::min(px + dragged_width, max_width) - 1;
 
	int drag_hlight_width = std::max(drag_hlight_right - drag_hlight_left + 1, 0);
 

	
 
	if (drag_hlight_width > 0) {
 
		int height = ScaleSpriteTrad(12);
 
		int top = y - height / 2;
 
		Rect r = {drag_hlight_left, top, drag_hlight_right, top + height - 1};
 
		/* Sprite-scaling is used here as the area is from sprite size */
 
		GfxFillRect(r.Shrink(ScaleSpriteTrad(1)), _colour_gradient[COLOUR_GREY][7]);
 
		GfxFillRect(r.Shrink(ScaleSpriteTrad(1)), GetColourGradient(COLOUR_GREY, 7));
 
	}
 

	
 
	return drag_hlight_width;
 
}
 

	
 
/**
 
 * Draws an image of a whole train
 
 * @param v         Front vehicle
 
 * @param r         Rect to draw at
 
 * @param selection Selected vehicle to draw a frame around
 
 * @param skip      Number of pixels to skip at the front (for scrolling)
 
 * @param drag_dest The vehicle another one is dragged over, \c INVALID_VEHICLE if none.
 
@@ -390,25 +390,25 @@ void DrawTrainDetails(const Train *v, co
 
			if (separate_sprite_row) {
 
				vscroll_pos--;
 
				dx = 0;
 
			}
 

	
 
			int sprite_width = std::max<int>(dx, ScaleSpriteTrad(TRAIN_DETAILS_MIN_INDENT)) + WidgetDimensions::scaled.hsep_normal;
 
			Rect dr = r.Indent(sprite_width, rtl);
 
			uint num_lines = std::max(1u, (unsigned)_cargo_summary.size());
 
			for (uint i = 0; i < num_lines; i++) {
 
				if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
 
					int py = r.top - line_height * vscroll_pos + text_y_offset;
 
					if (i > 0 || separate_sprite_row) {
 
						if (vscroll_pos != 0) GfxFillRect(r.left, py - WidgetDimensions::scaled.matrix.top - 1, r.right, py - WidgetDimensions::scaled.matrix.top, _colour_gradient[COLOUR_GREY][5]);
 
						if (vscroll_pos != 0) GfxFillRect(r.left, py - WidgetDimensions::scaled.matrix.top - 1, r.right, py - WidgetDimensions::scaled.matrix.top, GetColourGradient(COLOUR_GREY, 5));
 
					}
 
					switch (det_tab) {
 
						case TDW_TAB_CARGO:
 
							if (i < _cargo_summary.size()) {
 
								TrainDetailsCargoTab(&_cargo_summary[i], dr.left, dr.right, py);
 
							} else {
 
								DrawString(dr.left, dr.right, py, STR_QUANTITY_N_A, TC_LIGHT_BLUE);
 
							}
 
							break;
 

	
 
						case TDW_TAB_INFO:
 
							if (i == 0) TrainDetailsInfoTab(v, dr.left, dr.right, py);
src/vehicle_gui.cpp
Show inline comments
 
@@ -615,25 +615,25 @@ using RefitOptions = std::map<CargoID, s
 
 * @param rows  Number of rows(capacity) in caller window
 
 * @param delta Step height in caller window
 
 * @param r     Rectangle of the matrix widget.
 
 */
 
static void DrawVehicleRefitWindow(const RefitOptions &refits, const RefitOption *sel, uint pos, uint rows, uint delta, const Rect &r)
 
{
 
	Rect ir = r.Shrink(WidgetDimensions::scaled.matrix);
 
	uint current = 0;
 

	
 
	bool rtl = _current_text_dir == TD_RTL;
 
	uint iconwidth = std::max(GetSpriteSize(SPR_CIRCLE_FOLDED).width, GetSpriteSize(SPR_CIRCLE_UNFOLDED).width);
 
	uint iconheight = GetSpriteSize(SPR_CIRCLE_FOLDED).height;
 
	int linecolour = _colour_gradient[COLOUR_ORANGE][4];
 
	int linecolour = GetColourGradient(COLOUR_ORANGE, 4);
 

	
 
	int iconleft   = rtl ? ir.right - iconwidth     : ir.left;
 
	int iconcenter = rtl ? ir.right - iconwidth / 2 : ir.left + iconwidth / 2;
 
	int iconinner  = rtl ? ir.right - iconwidth     : ir.left + iconwidth;
 

	
 
	Rect tr = ir.Indent(iconwidth + WidgetDimensions::scaled.hsep_wide, rtl);
 

	
 
	/* Draw the list of subtypes for each cargo, and find the selected refit option (by its position). */
 
	for (const auto &pair : refits) {
 
		bool has_subtypes = pair.second.size() > 1;
 
		for (const RefitOption &refit : pair.second) {
 
			if (current >= pos + rows) break;
src/viewport.cpp
Show inline comments
 
@@ -1707,25 +1707,25 @@ static void ViewportDrawStrings(ZoomLeve
 
		TextColour colour = TC_BLACK;
 
		bool small = HasBit(ss.width, 15);
 
		int w = GB(ss.width, 0, 15);
 
		int x = UnScaleByZoom(ss.x, zoom);
 
		int y = UnScaleByZoom(ss.y, zoom);
 
		int h = WidgetDimensions::scaled.fullbevel.top + (small ? GetCharacterHeight(FS_SMALL) : GetCharacterHeight(FS_NORMAL)) + WidgetDimensions::scaled.fullbevel.bottom;
 

	
 
		if (ss.colour != INVALID_COLOUR) {
 
			if (IsTransparencySet(TO_SIGNS) && ss.string_id != STR_WHITE_SIGN) {
 
				/* Don't draw the rectangle.
 
				 * Real colours need the TC_IS_PALETTE_COLOUR flag.
 
				 * Otherwise colours from _string_colourmap are assumed. */
 
				colour = (TextColour)_colour_gradient[ss.colour][6] | TC_IS_PALETTE_COLOUR;
 
				colour = (TextColour)GetColourGradient(ss.colour, 6) | TC_IS_PALETTE_COLOUR;
 
			} else {
 
				/* Draw the rectangle if 'transparent station signs' is off,
 
				 * or if we are drawing a general text sign (STR_WHITE_SIGN). */
 
				DrawFrameRect(
 
					x, y, x + w - 1, y + h - 1, ss.colour,
 
					IsTransparencySet(TO_SIGNS) ? FR_TRANSPARENT : FR_NONE
 
				);
 
			}
 
		}
 

	
 
		DrawString(x + WidgetDimensions::scaled.fullbevel.left, x + w - 1 - WidgetDimensions::scaled.fullbevel.right, y + WidgetDimensions::scaled.fullbevel.top, ss.string, colour, SA_HOR_CENTER, false, small ? FS_SMALL : FS_NORMAL);
 
	}
src/widget.cpp
Show inline comments
 
@@ -266,35 +266,35 @@ void ScrollbarClickHandler(Window *w, NW
 
WidgetID GetWidgetFromPos(const Window *w, int x, int y)
 
{
 
	NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y);
 
	return (nw != nullptr) ? nw->index : -1;
 
}
 

	
 
/**
 
 * Draw frame rectangle.
 
 * @param left   Left edge of the frame
 
 * @param top    Top edge of the frame
 
 * @param right  Right edge of the frame
 
 * @param bottom Bottom edge of the frame
 
 * @param colour Colour table to use. @see _colour_gradient
 
 * @param colour Colour table to use. @see Colours
 
 * @param flags  Flags controlling how to draw the frame. @see FrameFlags
 
 */
 
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
 
{
 
	assert(colour < COLOUR_END);
 

	
 
	uint dark         = _colour_gradient[colour][3];
 
	uint medium_dark  = _colour_gradient[colour][5];
 
	uint medium_light = _colour_gradient[colour][6];
 
	uint light        = _colour_gradient[colour][7];
 
	uint dark         = GetColourGradient(colour, 3);
 
	uint medium_dark  = GetColourGradient(colour, 5);
 
	uint medium_light = GetColourGradient(colour, 6);
 
	uint light        = GetColourGradient(colour, 7);
 

	
 
	if (flags & FR_TRANSPARENT) {
 
		GfxFillRect(left, top, right, bottom, PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR);
 
	} else {
 
		uint interior;
 

	
 
		Rect outer = {left, top, right, bottom};                   // Outside rectangle
 
		Rect inner = outer.Shrink(WidgetDimensions::scaled.bevel); // Inside rectangle
 

	
 
		if (flags & FR_LOWERED) {
 
			GfxFillRect(outer.left,      outer.top,        inner.left - 1,  outer.bottom, dark);   // Left
 
			GfxFillRect(inner.left,      outer.top,        outer.right,     inner.top - 1, dark);  // Top
 
@@ -414,39 +414,39 @@ static inline void DrawMatrix(const Rect
 
		column_width = r.Width() / num_columns;
 
	}
 

	
 
	int num_rows = GB(data, MAT_ROW_START, MAT_ROW_BITS); // Upper 8 bits of the widget data: Number of rows in the matrix.
 
	int row_height; // Height of a single row in the matrix.
 
	if (num_rows == 0) {
 
		row_height = resize_y;
 
		num_rows = r.Height() / row_height;
 
	} else {
 
		row_height = r.Height() / num_rows;
 
	}
 

	
 
	int col = _colour_gradient[colour & 0xF][6];
 
	int col = GetColourGradient(colour, 6);
 

	
 
	int x = r.left;
 
	for (int ctr = num_columns; ctr > 1; ctr--) {
 
		x += column_width;
 
		GfxFillRect(x, r.top + WidgetDimensions::scaled.bevel.top, x + WidgetDimensions::scaled.bevel.left - 1, r.bottom - WidgetDimensions::scaled.bevel.bottom, col);
 
	}
 

	
 
	x = r.top;
 
	for (int ctr = num_rows; ctr > 1; ctr--) {
 
		x += row_height;
 
		GfxFillRect(r.left + WidgetDimensions::scaled.bevel.left, x, r.right - WidgetDimensions::scaled.bevel.right, x + WidgetDimensions::scaled.bevel.top - 1, col);
 
	}
 

	
 
	col = _colour_gradient[colour & 0xF][4];
 
	col = GetColourGradient(colour, 4);
 

	
 
	x = r.left - 1;
 
	for (int ctr = num_columns; ctr > 1; ctr--) {
 
		x += column_width;
 
		GfxFillRect(x - WidgetDimensions::scaled.bevel.right + 1, r.top + WidgetDimensions::scaled.bevel.top, x, r.bottom - WidgetDimensions::scaled.bevel.bottom, col);
 
	}
 

	
 
	x = r.top - 1;
 
	for (int ctr = num_rows; ctr > 1; ctr--) {
 
		x += row_height;
 
		GfxFillRect(r.left + WidgetDimensions::scaled.bevel.left, x - WidgetDimensions::scaled.bevel.bottom + 1, r.right - WidgetDimensions::scaled.bevel.right, x, col);
 
	}
 
@@ -460,26 +460,26 @@ static inline void DrawMatrix(const Rect
 
 * @param bar_dragged  Bar is dragged.
 
 * @param down_clicked Down-arrow is clicked.
 
 * @param scrollbar    Scrollbar size, offset, and capacity information.
 
 */
 
static inline void DrawVerticalScrollbar(const Rect &r, Colours colour, bool up_clicked, bool bar_dragged, bool down_clicked, const Scrollbar *scrollbar)
 
{
 
	int height = NWidgetScrollbar::GetVerticalDimension().height;
 

	
 
	/* draw up/down buttons */
 
	DrawImageButtons(r.WithHeight(height, false),  NWID_VSCROLLBAR, colour, up_clicked,   SPR_ARROW_UP,   SA_CENTER);
 
	DrawImageButtons(r.WithHeight(height, true),   NWID_VSCROLLBAR, colour, down_clicked, SPR_ARROW_DOWN, SA_CENTER);
 

	
 
	int c1 = _colour_gradient[colour & 0xF][3];
 
	int c2 = _colour_gradient[colour & 0xF][7];
 
	int c1 = GetColourGradient(colour, 3);
 
	int c2 = GetColourGradient(colour, 7);
 

	
 
	/* draw "shaded" background */
 
	GfxFillRect(r.left, r.top + height, r.right, r.bottom - height, c2);
 
	GfxFillRect(r.left, r.top + height, r.right, r.bottom - height, c1, FILLRECT_CHECKER);
 

	
 
	/* track positions. These fractions are based on original 1x dimensions, but scale better. */
 
	int left  = r.left + r.Width() * 3 / 11; /*  left track is positioned 3/11ths from the left */
 
	int right = r.left + r.Width() * 8 / 11; /* right track is positioned 8/11ths from the left */
 
	const uint8_t bl = WidgetDimensions::scaled.bevel.left;
 
	const uint8_t br = WidgetDimensions::scaled.bevel.right;
 

	
 
	/* draw shaded lines */
 
@@ -499,26 +499,26 @@ static inline void DrawVerticalScrollbar
 
 * @param left_clicked  Left-arrow is clicked.
 
 * @param bar_dragged   Bar is dragged.
 
 * @param right_clicked Right-arrow is clicked.
 
 * @param scrollbar     Scrollbar size, offset, and capacity information.
 
 */
 
static inline void DrawHorizontalScrollbar(const Rect &r, Colours colour, bool left_clicked, bool bar_dragged, bool right_clicked, const Scrollbar *scrollbar)
 
{
 
	int width = NWidgetScrollbar::GetHorizontalDimension().width;
 

	
 
	DrawImageButtons(r.WithWidth(width, false), NWID_HSCROLLBAR, colour, left_clicked,  SPR_ARROW_LEFT,  SA_CENTER);
 
	DrawImageButtons(r.WithWidth(width, true),  NWID_HSCROLLBAR, colour, right_clicked, SPR_ARROW_RIGHT, SA_CENTER);
 

	
 
	int c1 = _colour_gradient[colour & 0xF][3];
 
	int c2 = _colour_gradient[colour & 0xF][7];
 
	int c1 = GetColourGradient(colour, 3);
 
	int c2 = GetColourGradient(colour, 7);
 

	
 
	/* draw "shaded" background */
 
	GfxFillRect(r.left + width, r.top, r.right - width, r.bottom, c2);
 
	GfxFillRect(r.left + width, r.top, r.right - width, r.bottom, c1, FILLRECT_CHECKER);
 

	
 
	/* track positions. These fractions are based on original 1x dimensions, but scale better. */
 
	int top    = r.top + r.Height() * 3 / 11; /*    top track is positioned 3/11ths from the top */
 
	int bottom = r.top + r.Height() * 8 / 11; /* bottom track is positioned 8/11ths from the top */
 
	const uint8_t bt = WidgetDimensions::scaled.bevel.top;
 
	const uint8_t bb = WidgetDimensions::scaled.bevel.bottom;
 

	
 
	/* draw shaded lines */
 
@@ -538,26 +538,26 @@ static inline void DrawHorizontalScrollb
 
 * @param colour      Colour of the frame.
 
 * @param text_colour Colour of the text.
 
 * @param str         Text of the frame.
 
 * @param align       Alignment of the text in the frame.
 
 * @param fs          Font size of the text.
 
 */
 
static inline void DrawFrame(const Rect &r, Colours colour, TextColour text_colour, StringID str, StringAlignment align, FontSize fs)
 
{
 
	int x2 = r.left; // by default the left side is the left side of the widget
 

	
 
	if (str != STR_NULL) x2 = DrawString(r.left + WidgetDimensions::scaled.frametext.left, r.right - WidgetDimensions::scaled.frametext.right, r.top, str, text_colour, align, false, fs);
 

	
 
	int c1 = _colour_gradient[colour][3];
 
	int c2 = _colour_gradient[colour][7];
 
	int c1 = GetColourGradient(colour, 3);
 
	int c2 = GetColourGradient(colour, 7);
 

	
 
	/* If the frame has text, adjust the top bar to fit half-way through */
 
	Rect inner = r.Shrink(ScaleGUITrad(1));
 
	if (str != STR_NULL) inner.top = r.top + GetCharacterHeight(FS_NORMAL) / 2;
 

	
 
	Rect outer  = inner.Expand(WidgetDimensions::scaled.bevel);
 
	Rect inside = inner.Shrink(WidgetDimensions::scaled.bevel);
 

	
 
	if (_current_text_dir == TD_LTR) {
 
		/* Line from upper left corner to start of text */
 
		GfxFillRect(outer.left, outer.top, r.left + WidgetDimensions::scaled.frametext.left - WidgetDimensions::scaled.bevel.left - 1, inner.top  - 1, c1);
 
		GfxFillRect(inner.left, inner.top, r.left + WidgetDimensions::scaled.frametext.left - WidgetDimensions::scaled.bevel.left - 1, inside.top - 1, c2);
 
@@ -636,25 +636,25 @@ static inline void DrawDebugBox(const Re
 
 * Draw a resize box.
 
 * @param r       Rectangle of the box.
 
 * @param colour  Colour of the resize box.
 
 * @param at_left Resize box is at left-side of the window,
 
 * @param clicked Box is lowered.
 
 * @param bevel   Draw bevel iff set.
 
 */
 
static inline void DrawResizeBox(const Rect &r, Colours colour, bool at_left, bool clicked, bool bevel)
 
{
 
	if (bevel) {
 
		DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FR_LOWERED : FR_NONE);
 
	} else if (clicked) {
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[colour][6]);
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(colour, 6));
 
	}
 
	DrawSpriteIgnorePadding(at_left ? SPR_WINDOW_RESIZE_LEFT : SPR_WINDOW_RESIZE_RIGHT, PAL_NONE, r.Shrink(ScaleGUITrad(2)), at_left ? (SA_LEFT | SA_BOTTOM | SA_FORCE) : (SA_RIGHT | SA_BOTTOM | SA_FORCE));
 
}
 

	
 
/**
 
 * Draw a close box.
 
 * @param r      Rectangle of the box.`
 
 * @param colour Colour of the close box.
 
 */
 
static inline void DrawCloseBox(const Rect &r, Colours colour)
 
{
 
	if (colour != COLOUR_WHITE) DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, FR_NONE);
 
@@ -676,25 +676,25 @@ static inline void DrawCloseBox(const Re
 
 * @param align       Alignment of the text.
 
 * @param fs          Font size of the text.
 
 */
 
void DrawCaption(const Rect &r, Colours colour, Owner owner, TextColour text_colour, StringID str, StringAlignment align, FontSize fs)
 
{
 
	bool company_owned = owner < MAX_COMPANIES;
 

	
 
	DrawFrameRect(r, colour, FR_BORDERONLY);
 
	Rect ir = r.Shrink(WidgetDimensions::scaled.bevel);
 
	DrawFrameRect(ir, colour, company_owned ? FR_LOWERED | FR_DARKENED | FR_BORDERONLY : FR_LOWERED | FR_DARKENED);
 

	
 
	if (company_owned) {
 
		GfxFillRect(ir.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[_company_colours[owner]][4]);
 
		GfxFillRect(ir.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(_company_colours[owner], 4));
 
	}
 

	
 
	if (str != STR_NULL) {
 
		Dimension d = GetStringBoundingBox(str);
 
		Point p = GetAlignedPosition(r, d, align);
 
		DrawString(r.left + WidgetDimensions::scaled.captiontext.left, r.right - WidgetDimensions::scaled.captiontext.left, p.y, str, text_colour, align, false, fs);
 
	}
 
}
 

	
 
/**
 
 * Draw a button with a dropdown (#WWT_DROPDOWN and #NWID_BUTTON_DROPDOWN).
 
 * @param r                Rectangle containing the widget.
 
@@ -1897,25 +1897,25 @@ NWidgetCore *NWidgetMatrix::GetWidgetFro
 
	assert(child != nullptr);
 
	child->AssignSizePosition(ST_RESIZE,
 
			this->pos_x + (rtl ? this->pip_post - widget_col * this->widget_w : this->pip_pre + widget_col * this->widget_w) + base_offs_x,
 
			this->pos_y + this->pip_pre + widget_row * this->widget_h + base_offs_y,
 
			child->smallest_x, child->smallest_y, rtl);
 

	
 
	return child->GetWidgetFromPos(x, y);
 
}
 

	
 
/* virtual */ void NWidgetMatrix::Draw(const Window *w)
 
{
 
	/* Fill the background. */
 
	GfxFillRect(this->GetCurrentRect(), _colour_gradient[this->colour & 0xF][5]);
 
	GfxFillRect(this->GetCurrentRect(), GetColourGradient(this->colour, 5));
 

	
 
	/* Set up a clipping area for the previews. */
 
	bool rtl = _current_text_dir == TD_RTL;
 
	DrawPixelInfo tmp_dpi;
 
	if (!FillDrawPixelInfo(&tmp_dpi, this->pos_x + (rtl ? this->pip_post : this->pip_pre), this->pos_y + this->pip_pre, this->current_x - this->pip_pre - this->pip_post, this->current_y - this->pip_pre - this->pip_post)) return;
 

	
 
	{
 
		AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
 

	
 
		/* Get the appropriate offsets so we can draw the right widgets. */
 
		NWidgetCore *child = dynamic_cast<NWidgetCore *>(this->children.front().get());
 
		assert(child != nullptr);
 
@@ -2162,25 +2162,25 @@ void NWidgetBackground::Draw(const Windo
 
			if (this->index >= 0) w->SetStringParameters(this->index);
 
			DrawInset(r, this->colour, this->text_colour, this->widget_data, this->align, this->text_size);
 
			break;
 

	
 
		default:
 
			NOT_REACHED();
 
	}
 

	
 
	if (this->index >= 0) w->DrawWidget(r, this->index);
 
	if (this->child != nullptr) this->child->Draw(w);
 

	
 
	if (this->IsDisabled()) {
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[this->colour & 0xF][2], FILLRECT_CHECKER);
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(this->colour, 2), FILLRECT_CHECKER);
 
	}
 

	
 
	DrawOutline(w, this);
 
}
 

	
 
NWidgetCore *NWidgetBackground::GetWidgetFromPos(int x, int y)
 
{
 
	NWidgetCore *nwid = nullptr;
 
	if (IsInsideBS(x, this->pos_x, this->current_x) && IsInsideBS(y, this->pos_y, this->current_y)) {
 
		if (this->child != nullptr) nwid = this->child->GetWidgetFromPos(x, y);
 
		if (nwid == nullptr) nwid = this;
 
	}
 
@@ -2407,25 +2407,25 @@ void NWidgetScrollbar::Draw(const Window
 

	
 
	bool up_lowered = HasBit(this->disp_flags, NDB_SCROLLBAR_UP);
 
	bool down_lowered = HasBit(this->disp_flags, NDB_SCROLLBAR_DOWN);
 
	bool middle_lowered = !(this->disp_flags & ND_SCROLLBAR_BTN) && w->mouse_capture_widget == this->index;
 

	
 
	if (this->type == NWID_HSCROLLBAR) {
 
		DrawHorizontalScrollbar(r, this->colour, up_lowered, middle_lowered, down_lowered, this);
 
	} else {
 
		DrawVerticalScrollbar(r, this->colour, up_lowered, middle_lowered, down_lowered, this);
 
	}
 

	
 
	if (this->IsDisabled()) {
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[this->colour & 0xF][2], FILLRECT_CHECKER);
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(this->colour, 2), FILLRECT_CHECKER);
 
	}
 

	
 
	DrawOutline(w, this);
 
}
 

	
 
/* static */ void NWidgetScrollbar::InvalidateDimensionCache()
 
{
 
	vertical_dimension.width   = vertical_dimension.height   = 0;
 
	horizontal_dimension.width = horizontal_dimension.height = 0;
 
}
 

	
 
/* static */ Dimension NWidgetScrollbar::GetVerticalDimension()
 
@@ -2858,25 +2858,25 @@ void NWidgetLeaf::Draw(const Window *w)
 
		case NWID_BUTTON_DROPDOWN:
 
		case NWID_PUSHBUTTON_DROPDOWN:
 
			if (this->index >= 0) w->SetStringParameters(this->index);
 
			DrawButtonDropdown(r, this->colour, clicked, (this->disp_flags & ND_DROPDOWN_ACTIVE) != 0, this->widget_data, this->align);
 
			break;
 

	
 
		default:
 
			NOT_REACHED();
 
	}
 
	if (this->index >= 0) w->DrawWidget(r, this->index);
 

	
 
	if (this->IsDisabled()) {
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), _colour_gradient[this->colour & 0xF][2], FILLRECT_CHECKER);
 
		GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(this->colour, 2), FILLRECT_CHECKER);
 
	}
 

	
 
	DrawOutline(w, this);
 
}
 

	
 
/**
 
 * For a #NWID_BUTTON_DROPDOWN, test whether \a pt refers to the button or to the drop-down.
 
 * @param pt Point in the widget.
 
 * @return The point refers to the button.
 
 *
 
 * @note The magic constants are also used at #DrawButtonDropdown.
 
 */
src/widgets/dropdown_type.h
Show inline comments
 
@@ -28,25 +28,25 @@ public:
 
	bool masked; ///< Masked and unselectable item.
 
	bool shaded; ///< Shaded item, affects text colour.
 

	
 
	explicit DropDownListItem(int result, bool masked = false, bool shaded = false) : result(result), masked(masked), shaded(shaded) {}
 
	virtual ~DropDownListItem() = default;
 

	
 
	virtual bool Selectable() const { return true; }
 
	virtual uint Height() const { return 0; }
 
	virtual uint Width() const { return 0; }
 

	
 
	virtual void Draw(const Rect &full, const Rect &, bool, Colours bg_colour) const
 
	{
 
		if (this->masked) GfxFillRect(full, _colour_gradient[bg_colour][5], FILLRECT_CHECKER);
 
		if (this->masked) GfxFillRect(full, GetColourGradient(bg_colour, 5), FILLRECT_CHECKER);
 
	}
 

	
 
	TextColour GetColour(bool sel) const
 
	{
 
		if (this->shaded) return (sel ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
 
		return sel ? TC_WHITE : TC_BLACK;
 
	}
 
};
 

	
 
/**
 
 * Drop down divider component.
 
 * @tparam TBase Base component.
 
@@ -54,26 +54,26 @@ public:
 
 */
 
template<class TBase, FontSize TFs = FS_NORMAL>
 
class DropDownDivider : public TBase {
 
public:
 
	template <typename... Args>
 
	explicit DropDownDivider(Args&&... args) : TBase(std::forward<Args>(args)...) {}
 

	
 
	bool Selectable() const override { return false; }
 
	uint Height() const override { return std::max<uint>(GetCharacterHeight(TFs), this->TBase::Height()); }
 

	
 
	void Draw(const Rect &full, const Rect &, bool, Colours bg_colour) const override
 
	{
 
		uint8_t c1 = _colour_gradient[bg_colour][3];
 
		uint8_t c2 = _colour_gradient[bg_colour][7];
 
		uint8_t c1 = GetColourGradient(bg_colour, 3);
 
		uint8_t c2 = GetColourGradient(bg_colour, 7);
 

	
 
		int mid = CenterBounds(full.top, full.bottom, 0);
 
		GfxFillRect(full.left, mid - WidgetDimensions::scaled.bevel.bottom, full.right, mid - 1, c1);
 
		GfxFillRect(full.left, mid, full.right, mid + WidgetDimensions::scaled.bevel.top - 1, c2);
 
	}
 
};
 

	
 
/**
 
 * Drop down string component.
 
 * @tparam TBase Base component.
 
 * @tparam TFs Font size.
 
 * @tparam TEnd Position string at end if true, or start if false.
src/widgets/slider.cpp
Show inline comments
 
@@ -32,27 +32,27 @@ void DrawSliderWidget(Rect r, int min_va
 
	/* Allow space for labels. We assume they are in the small font. */
 
	if (!labels.empty()) r.bottom -= GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.hsep_normal;
 

	
 
	max_value -= min_value;
 

	
 
	/* Draw a wedge indicating low to high value. */
 
	const int ha = (r.bottom - r.top) / 5;
 
	const int sw = ScaleGUITrad(SLIDER_WIDTH);
 
	const int t = WidgetDimensions::scaled.bevel.top; /* Thickness of lines */
 
	int wx1 = r.left  + sw / 2;
 
	int wx2 = r.right - sw / 2;
 
	if (_current_text_dir == TD_RTL) std::swap(wx1, wx2);
 
	const uint shadow = _colour_gradient[COLOUR_GREY][3];
 
	const uint fill = _colour_gradient[COLOUR_GREY][6];
 
	const uint light = _colour_gradient[COLOUR_GREY][7];
 
	const uint shadow = GetColourGradient(COLOUR_GREY, 3);
 
	const uint fill = GetColourGradient(COLOUR_GREY, 6);
 
	const uint light = GetColourGradient(COLOUR_GREY, 7);
 
	const std::vector<Point> wedge{ Point{wx1, r.bottom - ha}, Point{wx2, r.top + ha}, Point{wx2, r.bottom - ha} };
 
	GfxFillPolygon(wedge, fill);
 
	GfxDrawLine(wedge[0].x, wedge[0].y, wedge[2].x, wedge[2].y, light, t);
 
	GfxDrawLine(wedge[1].x, wedge[1].y, wedge[2].x, wedge[2].y, _current_text_dir == TD_RTL ? shadow : light, t);
 
	GfxDrawLine(wedge[0].x, wedge[0].y, wedge[1].x, wedge[1].y, shadow, t);
 

	
 
	int x;
 
	for (auto label : labels) {
 
		x = label.first - min_value;
 
		if (_current_text_dir == TD_RTL) x = max_value - x;
 
		x = r.left + (x * (r.right - r.left - sw) / max_value) + sw / 2;
 
		GfxDrawLine(x, r.bottom - ha + 1, x, r.bottom + (label.second == STR_NULL ? 0 : WidgetDimensions::scaled.hsep_normal), shadow, t);
0 comments (0 inline, 0 general)