29 #include "table/strings.h" 
   52 #define MK(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false} 
   55 #define MC(col_break)  {0, STR_TINY_BLACK_HEIGHT, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, col_break} 
   58 #define MO(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, false} 
   61 #define MOEND() {0, 0, INVALID_INDUSTRYTYPE, 0, OWNER_NONE, true, true, false} 
   64 #define MKEND() {0, STR_NULL, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, true, false} 
   70 #define MS(a, b) {a, b, INVALID_INDUSTRYTYPE, 0, INVALID_COMPANY, true, false, true} 
   75   MK(
PC_GREY,            STR_SMALLMAP_LEGENDA_RAILROADS),
 
   99   MK(
PC_RED,             STR_SMALLMAP_LEGENDA_TRAINS),
 
  104   MS(
PC_BLACK,           STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
 
  111   MK(
PC_GREY,            STR_SMALLMAP_LEGENDA_RAILROADS),
 
  115   MK(
PC_ORANGE,          STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY),
 
  117   MK(
PC_RED,             STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT),
 
  133   MK(
PC_BLACK,           STR_SMALLMAP_LEGENDA_TRANSPORT_ROUTES),
 
  140   MO(0x00,               STR_SMALLMAP_LEGENDA_NO_OWNER), 
 
  184       _legend_from_industries[j].
legend = indsp->
name;
 
  186       _legend_from_industries[j].
type = ind;
 
  188       _legend_from_industries[j].
col_break = 
false;
 
  189       _legend_from_industries[j].
end = 
false;
 
  197   _legend_from_industries[j].
end = 
true;
 
  209   memset(_legend_linkstats, 0, 
sizeof(_legend_linkstats));
 
  216     _legend_linkstats[i].
colour = cs->legend_colour;
 
  225     _legend_linkstats[i].
legend = STR_EMPTY;
 
  231   _legend_linkstats[i - 1].
legend = STR_LINKGRAPH_LEGEND_OVERLOADED;
 
  233   _legend_linkstats[i].
end = 
true;
 
  246 #define MKCOLOUR(x)         TO_LE32X(x) 
  248 #define MKCOLOUR_XXXX(x)    (MKCOLOUR(0x01010101) * (uint)(x)) 
  249 #define MKCOLOUR_X0X0(x)    (MKCOLOUR(0x01000100) * (uint)(x)) 
  250 #define MKCOLOUR_0X0X(x)    (MKCOLOUR(0x00010001) * (uint)(x)) 
  251 #define MKCOLOUR_0XX0(x)    (MKCOLOUR(0x00010100) * (uint)(x)) 
  252 #define MKCOLOUR_X00X(x)    (MKCOLOUR(0x01000001) * (uint)(x)) 
  254 #define MKCOLOUR_XYXY(x, y) (MKCOLOUR_X0X0(x) | MKCOLOUR_0X0X(y)) 
  255 #define MKCOLOUR_XYYX(x, y) (MKCOLOUR_X00X(x) | MKCOLOUR_0XX0(y)) 
  257 #define MKCOLOUR_0000       MKCOLOUR_XXXX(0x00) 
  258 #define MKCOLOUR_0FF0       MKCOLOUR_0XX0(0xFF) 
  259 #define MKCOLOUR_F00F       MKCOLOUR_X00X(0xFF) 
  260 #define MKCOLOUR_FFFF       MKCOLOUR_XXXX(0xFF) 
  285   if (_heightmap_schemes[0].height_colours == NULL) 
return;
 
  307   uint deltas[][2] = { { 24, 2 }, { 48, 4 }, { 72, 6 }, { 120, 10 }, { 180, 15 }, { 240, 20 }, { 
MAX_TILE_HEIGHT + 1, 25 }};
 
  312   uint delta = deltas[i][1];
 
  315   int rows = 
CeilDiv(total_entries, 2);
 
  318   for (i = 0; i < 
lengthof(_legend_land_contours) - 1 && j < total_entries; i++) {
 
  319     if (_legend_land_contours[i].legend != STR_TINY_BLACK_HEIGHT) 
continue;
 
  321     _legend_land_contours[i].
col_break = j % rows == 0;
 
  322     _legend_land_contours[i].
end = 
false;
 
  323     _legend_land_contours[i].
height = j * delta;
 
  327   _legend_land_contours[i].
end = 
true;
 
  339   FOR_ALL_COMPANIES(c) {
 
  343     _legend_land_owners[i].
col_break = 
false;
 
  344     _legend_land_owners[i].
end = 
false;
 
  350   _legend_land_owners[i].
end = 
true;
 
  361 static inline uint32 ApplyMask(uint32 colour, 
const AndOr *mask)
 
  363   return (colour & mask->mand) | mask->mor;
 
  369   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, 
 
  370   {MKCOLOUR_0XX0(
PC_GREY      ), MKCOLOUR_F00F}, 
 
  371   {MKCOLOUR_0XX0(
PC_BLACK     ), MKCOLOUR_F00F}, 
 
  373   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, 
 
  375   {MKCOLOUR_XXXX(
PC_WATER     ), MKCOLOUR_0000}, 
 
  376   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, 
 
  378   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, 
 
  380   {MKCOLOUR_0XX0(
PC_GREY      ), MKCOLOUR_F00F},
 
  385   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, 
 
  386   {MKCOLOUR_0XX0(
PC_BLACK     ), MKCOLOUR_F00F}, 
 
  387   {MKCOLOUR_0XX0(
PC_BLACK     ), MKCOLOUR_F00F}, 
 
  389   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, 
 
  390   {MKCOLOUR_0XX0(
PC_BLACK     ), MKCOLOUR_F00F}, 
 
  391   {MKCOLOUR_XXXX(
PC_WATER     ), MKCOLOUR_0000}, 
 
  392   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, 
 
  394   {MKCOLOUR_0000               , MKCOLOUR_FFFF}, 
 
  396   {MKCOLOUR_0XX0(
PC_BLACK     ), MKCOLOUR_F00F},
 
  438   return ApplyMask(cs->
default_colour, &_smallmap_vehicles_andor[t]);
 
  466       case STATION_AIRPORT: 
return MKCOLOUR_XXXX(
PC_RED);
 
  467       case STATION_TRUCK:   
return MKCOLOUR_XXXX(
PC_ORANGE);
 
  468       case STATION_BUS:     
return MKCOLOUR_XXXX(
PC_YELLOW);
 
  470       default:              
return MKCOLOUR_FFFF;
 
  475       _smallmap_contours_andor[t].mand
 
  484   return ApplyMask(cs->
default_colour, &_smallmap_contours_andor[t]);
 
  499 static const uint32 _vegetation_clear_bits[] = {
 
  533       return ApplyMask(MKCOLOUR_XXXX(
PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
 
  575 inline Point SmallMapWindow::SmallmapRemapCoords(
int x, 
int y)
 const 
  594   if (this->
zoom == 1) 
return SmallmapRemapCoords(x_offset, y_offset);
 
  597   if (x_offset < 0) x_offset -= this->
zoom - 1;
 
  598   if (y_offset < 0) y_offset -= this->
zoom - 1;
 
  600   return SmallmapRemapCoords(x_offset / this->
zoom, y_offset / this->
zoom);
 
  619   Point pt = {((py >> 1) - (px >> 2)) * this->
zoom, ((py >> 1) + (px >> 2)) * this->
zoom};
 
  647   assert(x >= 0 && y >= 0);
 
  675   static const int zoomlevels[] = {1, 2, 4, 6, 8}; 
 
  676   static const int MIN_ZOOM_INDEX = 0;
 
  677   static const int MAX_ZOOM_INDEX = 
lengthof(zoomlevels) - 1;
 
  679   int new_index, cur_index, sub;
 
  684       new_index = MIN_ZOOM_INDEX;
 
  690       for (cur_index = MIN_ZOOM_INDEX; cur_index <= MAX_ZOOM_INDEX; cur_index++) {
 
  691         if (this->
zoom == zoomlevels[cur_index]) 
break;
 
  693       assert(cur_index <= MAX_ZOOM_INDEX);
 
  695       tile = this->
PixelToTile(zoom_pt->x, zoom_pt->y, &sub);
 
  696       new_index = 
Clamp(cur_index + ((change == 
ZLC_ZOOM_IN) ? -1 : 1), MIN_ZOOM_INDEX, MAX_ZOOM_INDEX);
 
  699     default: NOT_REACHED();
 
  702   if (new_index != cur_index) {
 
  703     this->
zoom = zoomlevels[new_index];
 
  704     if (cur_index >= 0) {
 
  707           this->scroll_y + (tile.y - new_tile.y) * 
TILE_SIZE, sub);
 
  708     } 
else if (this->
map_type == SMT_LINKSTATS) {
 
  745         if (this->
map_type == SMT_INDUSTRY) {
 
  765     if (_tiletype_importance[ttype] > importance) {
 
  766       importance = _tiletype_importance[ttype];
 
  794     default: NOT_REACHED();
 
  813   void *dst_ptr_abs_end = blitter->
MoveTo(_screen.dst_ptr, 0, _screen.height);
 
  821     if (dst < _screen.dst_ptr) 
continue;
 
  822     if (dst >= dst_ptr_abs_end) 
continue;
 
  826     if (min_xy == 1 && (xc == 0 || yc == 0)) {
 
  827       if (this->
zoom == 1) 
continue; 
 
  836     uint8 *val8 = (uint8 *)&val;
 
  837     int idx = 
max(0, -start_pos);
 
  838     for (
int pos = 
max(0, start_pos); pos < end_pos; pos++) {
 
  839       blitter->
SetPixel(dst, idx, 0, val8[idx]);
 
  843   } 
while (xc += this->
zoom, yc += this->
zoom, dst = blitter->
MoveTo(dst, pitch, 0), --reps != 0);
 
  861     int y = pt.y - dpi->top;
 
  865     int x = pt.x - this->
subscroll - 3 - dpi->left; 
 
  869       if (++x != 0) 
continue;
 
  871     } 
else if (x >= dpi->width - 1) {
 
  873       if (x != dpi->width - 1) 
continue;
 
  881     blitter->
SetPixel(dpi->dst_ptr, x, y, colour);
 
  882     if (!skip) blitter->
SetPixel(dpi->dst_ptr, x + 1, y, colour);
 
  901         x < dpi->
left + dpi->width &&
 
  903         y < dpi->
top + dpi->height) {
 
  922   Point upper_left = this->
RemapTile(upper_left_smallmap_coord.x / (
int)
TILE_SIZE, upper_left_smallmap_coord.y / (
int)TILE_SIZE);
 
  925   Point lower_right = this->
RemapTile(lower_right_smallmap_coord.x / (
int)TILE_SIZE, lower_right_smallmap_coord.y / (
int)TILE_SIZE);
 
  955   GfxFillRect(dpi->left, dpi->top, dpi->left + dpi->width - 1, dpi->top + dpi->height - 1, 
PC_BLACK);
 
  961   int tile_y = this->scroll_y / (
int)
TILE_SIZE + tile.y;
 
  963   void *ptr = blitter->
MoveTo(dpi->dst_ptr, -dx - 4, 0);
 
  970       if (x >= dpi->width) 
break; 
 
  972       int end_pos = 
min(dpi->width, x + 4);
 
  973       int reps = (dpi->height - y + 1) / 2; 
 
  975         this->
DrawSmallMapColumn(ptr, tile_x, tile_y, dpi->pitch * 2, reps, x, end_pos, blitter);
 
  980       tile_y += this->
zoom;
 
  982       ptr = blitter->
MoveTo(ptr, 0, 1);
 
  984       tile_x -= this->
zoom;
 
  986       ptr = blitter->
MoveTo(ptr, 0, -1);
 
  988     ptr = blitter->
MoveTo(ptr, 2, 0);
 
  996   if (this->
map_type == SMT_LINKSTATS) this->overlay->
Draw(dpi);
 
 1018       legend_tooltip = STR_SMALLMAP_TOOLTIP_INDUSTRY_SELECTION;
 
 1019       enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_INDUSTRIES;
 
 1020       disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_INDUSTRIES;
 
 1025       legend_tooltip = STR_SMALLMAP_TOOLTIP_COMPANY_SELECTION;
 
 1026       enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_COMPANIES;
 
 1027       disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_COMPANIES;
 
 1032       legend_tooltip = STR_SMALLMAP_TOOLTIP_CARGO_SELECTION;
 
 1033       enable_all_tooltip = STR_SMALLMAP_TOOLTIP_ENABLE_ALL_CARGOS;
 
 1034       disable_all_tooltip = STR_SMALLMAP_TOOLTIP_DISABLE_ALL_CARGOS;
 
 1039       legend_tooltip = STR_NULL;
 
 1040       enable_all_tooltip = STR_NULL;
 
 1041       disable_all_tooltip = STR_NULL;
 
 1052 SmallMapWindow::SmallMapWindow(
WindowDesc *desc, 
int window_number) : 
Window(desc), refresh(FORCE_REFRESH_PERIOD)
 
 1080   for (uint n = 0; n < 
lengthof(_heightmap_schemes); n++) {
 
 1085     for (
int z = 0; z < heights; z++) {
 
 1086       size_t access_index = (_heightmap_schemes[n].
colour_count * z) / heights;
 
 1111   for (uint i = 0; i < 
lengthof(_legend_table); i++) {
 
 1113     uint num_columns = 1;
 
 1116       if (i == SMT_INDUSTRY) {
 
 1119         str = STR_SMALLMAP_INDUSTRY;
 
 1120       } 
else if (i == SMT_LINKSTATS) {
 
 1122         str = STR_SMALLMAP_LINKSTATS;
 
 1123       } 
else if (i == SMT_OWNER) {
 
 1133           str = STR_SMALLMAP_COMPANY;
 
 1138         if (tbl->col_break) {
 
 1177       if (!
FillDrawPixelInfo(&new_dpi, r.left + 1, r.top + 1, r.right - r.left - 1, r.bottom - r.top - 1)) 
return;
 
 1200           string = STR_SMALLMAP_INDUSTRY;
 
 1203           string = STR_SMALLMAP_LINKSTATS;
 
 1206           string = STR_SMALLMAP_COMPANY;
 
 1213         if (tbl->col_break || ((this->map_type == SMT_INDUSTRY || this->map_type == SMT_OWNER || this->map_type == SMT_LINKSTATS) && i++ >= number_of_rows)) {
 
 1221         uint8 legend_colour = tbl->colour;
 
 1239               if (!tbl->show_on_map) {
 
 1242                 DrawString(x + text_left, x + text_right, y, 
string, TC_GREY);
 
 1244                 DrawString(x + text_left, x + text_right, y, 
string, TC_BLACK);
 
 1254             DrawString(x + text_left, x + text_right, y, tbl->legend);
 
 1257         GfxFillRect(x + blob_left + 1, y + 2, x + blob_right - 1, y + row_height - 2, legend_colour); 
 
 1277   if (map_type == SMT_LINKSTATS) this->overlay->
RebuildCache();
 
 1312     bool changes = 
false;
 
 1313     for (
int i = begin_legend_item; i != end_legend_item; i++) {
 
 1314       bool new_state = (i == click_pos);
 
 1315       if (legend[i].show_on_map != new_state) {
 
 1322       for (
int i = begin_legend_item; i != end_legend_item; i++) {
 
 1336   uint32 cargo_mask = 0;
 
 1338     if (_legend_linkstats[i].show_on_map) 
SetBit(cargo_mask, _legend_linkstats[i].type);
 
 1354   if (line >= number_of_rows) 
return -1;
 
 1357   int x = pt.x - wi->
pos_x;
 
 1361   return (column * number_of_rows) + line;
 
 1370       new_highlight = _legend_from_industries[industry_pos].
type;
 
 1445         if (click_pos < 0) 
break;
 
 1448         if (this->
map_type == SMT_INDUSTRY) {
 
 1453         } 
else if (this->
map_type == SMT_LINKSTATS) {
 
 1458         } 
else if (this->
map_type == SMT_OWNER) {
 
 1484       for (;!tbl->
end && tbl->
legend != STR_LINKGRAPH_LEGEND_UNUSED; ++tbl) {
 
 1510   if (!gui_scope) 
return;
 
 1523         _legend_from_industries[i].
show_on_map = _displayed_industries.test(_legend_from_industries[i].type);
 
 1532     default: NOT_REACHED();
 
 1549     int cursor_x = _cursor.
pos.x - this->
left - wid->
pos_x;
 
 1550     int cursor_y = _cursor.
pos.y - this->
top  - wid->
pos_y;
 
 1552       Point pt = {cursor_x, cursor_y};
 
 1561   if (--this->
refresh != 0) 
return;
 
 1563   if (this->
map_type == SMT_LINKSTATS) {
 
 1649   int x = (st->
rect.right + st->
rect.left + 1) / 2;
 
 1650   int y = (st->
rect.bottom + st->
rect.top + 1) / 2;
 
 1716     uint bar_height = 
max(bar->
smallest_y, this->smallmap_window->GetLegendHeight(this->smallmap_window->GetNumberColumnsLegend(given_width - bar->
smallest_x)));
 
 1717     uint display_height = given_height - bar_height;
 
 1725     for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) {
 
 1727       if (widget != NULL) 
return widget;
 
 1734     for (
NWidgetBase *child_wid = this->
head; child_wid != NULL; child_wid = child_wid->
next) child_wid->Draw(w);
 
 1741     NWidget(
WWT_INSET, COLOUR_BROWN, 
WID_SM_MAP), 
SetMinimalSize(346, 140), 
SetResize(1, 1), 
SetPadding(2, 2, 2, 2), 
EndContainer(),
 
 1754               SetDataTip(SPR_IMG_ZOOMIN, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN), 
SetFill(1, 1),
 
 1760               SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), 
SetFill(1, 1),
 
 1762               SetDataTip(SPR_IMG_SHOW_VEHICLES, STR_SMALLMAP_TOOLTIP_SHOW_VEHICLES_ON_MAP), 
SetFill(1, 1),
 
 1764               SetDataTip(SPR_IMG_INDUSTRY, STR_SMALLMAP_TOOLTIP_SHOW_INDUSTRIES_ON_MAP), 
SetFill(1, 1),
 
 1769               SetDataTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), 
SetFill(1, 1),
 
 1771               SetDataTip(SPR_IMG_TOWN, STR_SMALLMAP_TOOLTIP_TOGGLE_TOWN_NAMES_ON_OFF), 
SetFill(1, 1),
 
 1773               SetDataTip(SPR_IMG_CARGOFLOW, STR_SMALLMAP_TOOLTIP_SHOW_LINK_STATS_ON_MAP), 
SetFill(1, 1),
 
 1775               SetDataTip(SPR_IMG_SHOW_ROUTES, STR_SMALLMAP_TOOLTIP_SHOW_TRANSPORT_ROUTES_ON), 
SetFill(1, 1),
 
 1777               SetDataTip(SPR_IMG_PLANTTREES, STR_SMALLMAP_TOOLTIP_SHOW_VEGETATION_ON_MAP), 
SetFill(1, 1),
 
 1779               SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_SMALLMAP_TOOLTIP_SHOW_LAND_OWNERS_ON_MAP), 
SetFill(1, 1),
 
 1787 static NWidgetBase *SmallMapDisplay(
int *biggest_index)
 
 1791   MakeNWidgets(_nested_smallmap_display, 
lengthof(_nested_smallmap_display), biggest_index, map_display);
 
 1792   MakeNWidgets(_nested_smallmap_bar, 
lengthof(_nested_smallmap_bar), biggest_index, map_display);
 
 1797 static const NWidgetPart _nested_smallmap_widgets[] = {
 
 1827   _nested_smallmap_widgets, 
lengthof(_nested_smallmap_widgets)
 
 1835   AllocateWindowDescFront<SmallMapWindow>(&_smallmap_desc, 0);
 
 1854   if (res) 
return res;