Loading

Paste #pjaahlc1m

  1. diff --git a/src/fence_gui.cpp b/src/fence_gui.cpp
  2. index 1e9d178..fbc9718 100644
  3. --- a/src/fence_gui.cpp
  4. +++ b/src/fence_gui.cpp
  5. @@ -115,7 +115,7 @@ void FenceGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) const
  6.                 lines--;
  7.  
  8.                 Recolouring recolouring;
  9. -               _video.BlitImage({rect.x, rect.y - sprite->yoffset}, sprite, recolouring, GS_NORMAL);
  10. +               _video.BlitImage({rect.x, rect.y - sprite->yoffset}, sprite, recolouring);
  11.                 rect.y += sprite->height;
  12.             }
  13.             break;
  14. diff --git a/src/freerct.cpp b/src/freerct.cpp
  15. index bc093eb..89d57b9 100644
  16. --- a/src/freerct.cpp
  17. +++ b/src/freerct.cpp
  18. @@ -98,15 +98,9 @@ int freerct_main(int argc, char **argv)
  19.     /* Load RCD files. */
  20.     InitImageStorage();
  21.     _rcd_collection.ScanDirectories();
  22. -   _sprite_manager.LoadRcdFiles();
  23.  
  24.     InitLanguage();
  25.  
  26. -   if (!_gui_sprites.HasSufficientGraphics()) {
  27. -       fprintf(stderr, "Insufficient graphics loaded.\n");
  28. -       return 1;
  29. -   }
  30. -
  31.     cfg_file.Load("freerct.cfg");
  32.     const char *font_path = cfg_file.GetValue("font", "medium-path");
  33.     int font_size = cfg_file.GetNum("font", "medium-size");
  34. @@ -126,6 +120,12 @@ int freerct_main(int argc, char **argv)
  35.         return 1;
  36.     }
  37.  
  38. +   _sprite_manager.LoadRcdFiles();
  39. +   if (!_gui_sprites.HasSufficientGraphics()) {
  40. +       fprintf(stderr, "Insufficient graphics loaded.\n");
  41. +       return 1;
  42. +   }
  43. +
  44.     InitMouseModes();
  45.  
  46.     StartNewGame();
  47. diff --git a/src/gui_graphics.cpp b/src/gui_graphics.cpp
  48. index dfa6910..e974ee2 100644
  49. --- a/src/gui_graphics.cpp
  50. +++ b/src/gui_graphics.cpp
  51. @@ -55,7 +55,7 @@ void DrawBorderSprites(const BorderSpriteData &bsd, bool pressed, const Rectangl
  52.     int xleft = pt.x;
  53.     int ytop = pt.y;
  54.     if (spr_base[WBS_TOP_LEFT] != nullptr) {
  55. -       _video.BlitImage(pt, spr_base[WBS_TOP_LEFT], rc, GS_NORMAL);
  56. +       _video.BlitImage(pt, spr_base[WBS_TOP_LEFT], rc);
  57.         xleft += spr_base[WBS_TOP_LEFT]->xoffset + spr_base[WBS_TOP_LEFT]->width;
  58.         ytop += spr_base[WBS_TOP_LEFT]->yoffset + spr_base[WBS_TOP_LEFT]->height;
  59.     }
  60. @@ -63,7 +63,7 @@ void DrawBorderSprites(const BorderSpriteData &bsd, bool pressed, const Rectangl
  61.     pt.x = rect.base.x + rect.width - 1;
  62.     int xright = pt.x;
  63.     if (spr_base[WBS_TOP_RIGHT] != nullptr) {
  64. -       _video.BlitImage(pt, spr_base[WBS_TOP_RIGHT], rc, GS_NORMAL);
  65. +       _video.BlitImage(pt, spr_base[WBS_TOP_RIGHT], rc);
  66.         xright += spr_base[WBS_TOP_RIGHT]->xoffset;
  67.     }
  68.  
  69. @@ -79,7 +79,7 @@ void DrawBorderSprites(const BorderSpriteData &bsd, bool pressed, const Rectangl
  70.     pt.y = rect.base.y + rect.height - 1;
  71.     int ybot = pt.y;
  72.     if (spr_base[WBS_BOTTOM_LEFT] != nullptr) {
  73. -       _video.BlitImage(pt, spr_base[WBS_BOTTOM_LEFT], rc, GS_NORMAL);
  74. +       _video.BlitImage(pt, spr_base[WBS_BOTTOM_LEFT], rc);
  75.         ybot += spr_base[WBS_BOTTOM_LEFT]->yoffset;
  76.     }
  77.  
  78. @@ -93,7 +93,7 @@ void DrawBorderSprites(const BorderSpriteData &bsd, bool pressed, const Rectangl
  79.  
  80.     pt.x = rect.base.x + rect.width - 1;
  81.     pt.y = rect.base.y + rect.height - 1;
  82. -   if (spr_base[WBS_BOTTOM_RIGHT] != nullptr) _video.BlitImage(pt, spr_base[WBS_BOTTOM_RIGHT], rc, GS_NORMAL);
  83. +   if (spr_base[WBS_BOTTOM_RIGHT] != nullptr) _video.BlitImage(pt, spr_base[WBS_BOTTOM_RIGHT], rc);
  84.  
  85.     if (spr_base[WBS_BOTTOM_MIDDLE] != nullptr) _video.BlitHorizontal(xleft, numx, pt.y, spr_base[WBS_BOTTOM_MIDDLE], rc);
  86.  
  87. @@ -117,21 +117,14 @@ void OverlayShaded(const Rectangle32 &rect)
  88.     r.RestrictTo(0, 0, _video.GetXSize(), _video.GetYSize());
  89.     if (r.width == 0 || r.height == 0) return;
  90.  
  91. -   /* Set clipped area to the rectangle. */
  92. -   ClippedRectangle cr(_video.GetClippedRectangle());
  93. -   ClippedRectangle new_cr(cr, r.base.x, r.base.y, r.width, r.height);
  94. -   _video.SetClippedRectangle(new_cr);
  95. -
  96.     /* Align the disabled sprite so it becomes a continuous pattern. */
  97. -   int32 base_x = -(r.base.x % img->width);
  98. -   int32 base_y = -(r.base.y % img->height);
  99. +   int32 base_x = r.base.x - (r.base.x % img->width);
  100. +   int32 base_y = r.base.y - (r.base.y % img->height);
  101.     uint16 numx = (r.width + img->width - 1) / img->width;
  102.     uint16 numy = (r.height + img->height - 1) / img->height;
  103.  
  104.     static const Recolouring recolour; // Fixed recolouring mapping.
  105.     _video.BlitImages({base_x, base_y}, img, numx, numy, recolour);
  106. -
  107. -   _video.SetClippedRectangle(cr); // Restore clipped area.
  108.  }
  109.  
  110.  /**
  111. @@ -151,10 +144,11 @@ void DrawString(StringID strid, uint8 colour, int x, int y, int width, Alignment
  112.     DrawText(strid, buffer, lengthof(buffer));
  113.     /** \todo Reduce the naiviness of this. */
  114.     if (outline) {
  115. -       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x + 1, y, width, align);
  116. -       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x, y + 1, width, align);
  117. -       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x - 1, y, width, align);
  118. -       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x, y - 1, width, align);
  119. +//     _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x + 1, y, width, align);
  120. +//     _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x, y + 1, width, align);
  121. +//     _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x - 1, y, width, align);
  122. +//     _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x, y - 1, width, align);
  123. +       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x + 1, y + 1, width, align);
  124.     }
  125.     _video.BlitText(buffer, _palette[colour], x, y, width, align);
  126.  }
  127. diff --git a/src/money.h b/src/money.h
  128. index cf32ff3..a9d54f5 100644
  129. --- a/src/money.h
  130. +++ b/src/money.h
  131. @@ -77,7 +77,7 @@ public:
  132.      */
  133.     inline Money& operator+=(const Money& other)
  134.     {
  135. -       if ((INT64_MAX - abs(other.m_value)) < abs(this->m_value) &&
  136. +       if ((INT64_MAX - std::abs(other.m_value)) < std::abs(this->m_value) &&
  137.             (this->m_value < 0) == (other.m_value < 0)) {
  138.             this->m_value = (this->m_value < 0) ? INT64_MIN : INT64_MAX ;
  139.         } else {
  140. @@ -219,7 +219,7 @@ public:
  141.      */
  142.     inline Money& operator*=(const int factor)
  143.     {
  144. -       if (factor != 0 && (INT64_MAX / abs(factor)) < abs(this->m_value)) {
  145. +       if (factor != 0 && (INT64_MAX / std::abs(factor)) < std::abs(this->m_value)) {
  146.             this->m_value = ((this->m_value < 0) == (factor < 0)) ? INT64_MAX : INT64_MIN;
  147.         } else {
  148.             this->m_value *= factor;
  149. diff --git a/src/palette.h b/src/palette.h
  150. index 42041f4..9c5fd62 100644
  151. --- a/src/palette.h
  152. +++ b/src/palette.h
  153. @@ -12,6 +12,9 @@
  154.  #ifndef PALETTE_H
  155.  #define PALETTE_H
  156.  
  157. +#include <functional>
  158. +#include <map>
  159. +
  160.  class Random;
  161.  
  162.  extern const uint32 _palette[256];  ///< The 8bpp FreeRCT palette.
  163. @@ -86,6 +89,8 @@ static inline uint32 SetA(uint32 rgba, uint8 opacity)
  164.     return rgba | opacity;
  165.  }
  166.  
  167. +#define SPLIT_RGBA(rgba) GetR(rgba), GetG(rgba), GetB(rgba), GetA(rgba)
  168. +
  169.  /** Names of colour ranges. */
  170.  enum ColourRange {
  171.     COL_RANGE_GREY,
  172. @@ -129,7 +134,8 @@ enum PaletteColours {
  173.  
  174.  /** Shifting of the gradient to make the sprite lighter or darker. */
  175.  enum GradientShift {
  176. -   GS_NIGHT,          ///< Shift gradient four steps darker.
  177. +   GS_START,
  178. +   GS_NIGHT = GS_START, ///< Shift gradient four steps darker.
  179.     GS_VERY_DARK,      ///< Shift gradient three steps darker.
  180.     GS_DARK,           ///< Shift gradient two steps darker.
  181.     GS_SLIGHTLY_DARK,  ///< Shift gradient one step darker.
  182. @@ -143,119 +149,19 @@ enum GradientShift {
  183.     GS_INVALID = 0xff, ///< Invalid gradient shift.
  184.  };
  185.  
  186. -static const int STEP_SIZE = 18; ///< Amount of colour shift for each gradient step.
  187. -typedef uint8 (*ShiftFunc)(uint8); ///< Type of the gradient shift function.
  188. -
  189. -/**
  190. - * Gradient shift function for #GS_NIGHT.
  191. - * @param col Input colour.
  192. - * @return Shifted result colour.
  193. - */
  194. -static inline uint8 ShiftGradientNight(uint8 col)
  195. -{
  196. -   return (col <= 4 * STEP_SIZE) ? 0 : col - 4 * STEP_SIZE;
  197. -}
  198. -
  199. -/**
  200. - * Gradient shift function for #GS_VERY_DARK.
  201. - * @param col Input colour.
  202. - * @return Shifted result colour.
  203. - */
  204. -static inline uint8 ShiftGradientVeryDark(uint8 col)
  205. -{
  206. -   return (col <= 3 * STEP_SIZE) ? 0 : col - 3 * STEP_SIZE;
  207. -}
  208. -
  209. -/**
  210. - * Gradient shift function for #GS_DARK
  211. - * @param col Input colour.
  212. - * @return Shifted result colour.
  213. - */
  214. -static inline uint8 ShiftGradientDark(uint8 col)
  215. -{
  216. -   return (col <= 2 * STEP_SIZE) ? 0 : col - 2 * STEP_SIZE;
  217. -}
  218. -
  219. -/**
  220. - * Gradient shift function for #GS_SLIGHTLY_DARK.
  221. - * @param col Input colour.
  222. - * @return Shifted result colour.
  223. - */
  224. -static inline uint8 ShiftGradientSlightlyDark(uint8 col)
  225. -{
  226. -   return (col <= STEP_SIZE) ? 0 : col - STEP_SIZE;
  227. -}
  228. -
  229. -/**
  230. - * Gradient shift function for #GS_NORMAL.
  231. - * @param col Input colour.
  232. - * @return Shifted result colour.
  233. - */
  234. -static inline uint8 ShiftGradientNormal(uint8 col)
  235. -{
  236. -   return col;
  237. -}
  238. -
  239. -/**
  240. - * Gradient shift function for #GS_SLIGHTLY_LIGHT.
  241. - * @param col Input colour.
  242. - * @return Shifted result colour.
  243. - */
  244. -static inline uint8 ShiftGradientSlightlyLight(uint8 col)
  245. -{
  246. -   return (col >= 255 - STEP_SIZE) ? 255: col + STEP_SIZE;
  247. -}
  248. -
  249. -/**
  250. - * Gradient shift function for #GS_LIGHT.
  251. - * @param col Input colour.
  252. - * @return Shifted result colour.
  253. - */
  254. -static inline uint8 ShiftGradientLight(uint8 col)
  255. -{
  256. -   return (col >= 255 - 2 * STEP_SIZE) ? 255: col + 2 * STEP_SIZE;
  257. -}
  258. -
  259. -/**
  260. - * Gradient shift function for #GS_VERY_LIGHT.
  261. - * @param col Input colour.
  262. - * @return Shifted result colour.
  263. - */
  264. -static inline uint8 ShiftGradientVeryLight(uint8 col)
  265. -{
  266. -   return (col >= 255 - 3 * STEP_SIZE) ? 255: col + 3 * STEP_SIZE;
  267. -}
  268. -
  269. -/**
  270. - * Gradient shift function for #GS_DAY.
  271. - * @param col Input colour.
  272. - * @return Shifted result colour.
  273. - */
  274. -static inline uint8 ShiftGradientDay(uint8 col)
  275. -{
  276. -   return (col >= 255 - 4 * STEP_SIZE) ? 255: col + 4 * STEP_SIZE;
  277. -}
  278. -
  279. -/**
  280. - * Select gradient shift function based on the \a shift.
  281. - * @param shift Desired amount of gradient shift.
  282. - * @return Recolour function implementing the shift.
  283. - */
  284. -static inline ShiftFunc GetGradientShiftFunc(GradientShift shift)
  285. -{
  286. -   switch (shift) {
  287. -       case GS_NIGHT:          return ShiftGradientNight;
  288. -       case GS_VERY_DARK:      return ShiftGradientVeryDark;
  289. -       case GS_DARK:           return ShiftGradientDark;
  290. -       case GS_SLIGHTLY_DARK:  return ShiftGradientSlightlyDark;
  291. -       case GS_NORMAL:         return ShiftGradientNormal;
  292. -       case GS_SLIGHTLY_LIGHT: return ShiftGradientSlightlyLight;
  293. -       case GS_LIGHT:          return ShiftGradientLight;
  294. -       case GS_VERY_LIGHT:     return ShiftGradientVeryLight;
  295. -       case GS_DAY:            return ShiftGradientDay;
  296. -       default: NOT_REACHED();
  297. -   }
  298. -}
  299. +static const int STEP_SIZE = 18;
  300. +
  301. +static const std::map<GradientShift, std::function<uint8(uint8)>> gsmap = {
  302. +   {GS_NIGHT,          [](uint8 col){return (col <=       4 * STEP_SIZE) ?   0: col - 4 * STEP_SIZE;}},
  303. +   {GS_VERY_DARK,      [](uint8 col){return (col <=       3 * STEP_SIZE) ?   0: col - 3 * STEP_SIZE;}},
  304. +   {GS_DARK,           [](uint8 col){return (col <=       2 * STEP_SIZE) ?   0: col - 2 * STEP_SIZE;}},
  305. +   {GS_SLIGHTLY_DARK,  [](uint8 col){return (col <=       1 * STEP_SIZE) ?   0: col - 1 * STEP_SIZE;}},
  306. +   {GS_NORMAL,         [](uint8 col){return col;                                                    }},
  307. +   {GS_SLIGHTLY_LIGHT, [](uint8 col){return (col >= 255 - 1 * STEP_SIZE) ? 255: col + 1 * STEP_SIZE;}},
  308. +   {GS_LIGHT,          [](uint8 col){return (col >= 255 - 2 * STEP_SIZE) ? 255: col + 2 * STEP_SIZE;}},
  309. +   {GS_VERY_LIGHT,     [](uint8 col){return (col >= 255 - 3 * STEP_SIZE) ? 255: col + 3 * STEP_SIZE;}},
  310. +   {GS_DAY,            [](uint8 col){return (col >= 255 - 4 * STEP_SIZE) ? 255: col + 4 * STEP_SIZE;}},
  311. +};
  312.  
  313.  /**
  314.   * Get the index of the base colour of a colour range.
  315. diff --git a/src/path_gui.cpp b/src/path_gui.cpp
  316. index 4a0e0ef..d5beca9 100644
  317. --- a/src/path_gui.cpp
  318. +++ b/src/path_gui.cpp
  319. @@ -226,7 +226,7 @@ void PathBuildGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) const
  320.                     int dx = (wid->pos.width - path_type_button_size.width) / 2;
  321.                     int dy = (wid->pos.height - path_type_button_size.height) / 2;
  322.                     Point32 pt(GetWidgetScreenX(wid) + dx - path_type_button_size.base.x, GetWidgetScreenY(wid) + dy - path_type_button_size.base.y);
  323. -                   _video.BlitImage(pt, img, recolour, GS_NORMAL);
  324. +                   _video.BlitImage(pt, img, recolour);
  325.                 }
  326.             }
  327.             break;
  328. @@ -241,7 +241,7 @@ void PathBuildGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) const
  329.                     int dx = (wid->pos.width - path_type_button_size.width) / 2;
  330.                     int dy = (wid->pos.height - path_type_button_size.height) / 2;
  331.                     Point32 pt(GetWidgetScreenX(wid) + dx - path_type_button_size.base.x, GetWidgetScreenY(wid) + dy - path_type_button_size.base.y);
  332. -                   _video.BlitImage(pt, img, recolour, GS_NORMAL);
  333. +                   _video.BlitImage(pt, img, recolour);
  334.                 }
  335.             }
  336.             break;
  337. diff --git a/src/ride_gui.cpp b/src/ride_gui.cpp
  338. index f72631d..c007c69 100644
  339. --- a/src/ride_gui.cpp
  340. +++ b/src/ride_gui.cpp
  341. @@ -222,7 +222,7 @@ void RideSelectGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) cons
  342.                 if (ride_type != nullptr && ride_type->kind == RTK_SHOP) {
  343.                     static const Recolouring recolour; // Never modified, display 'original' image in the GUI.
  344.                     Point32 pt(this->GetWidgetScreenX(wid) + wid->pos.width / 2, this->GetWidgetScreenY(wid) + 40);
  345. -                   _video.BlitImage(pt, ride_type->GetView(_shop_placer.orientation), recolour, GS_NORMAL);
  346. +                   _video.BlitImage(pt, ride_type->GetView(_shop_placer.orientation), recolour);
  347.                 }
  348.             }
  349.             break;
  350. diff --git a/src/sprite_data.cpp b/src/sprite_data.cpp
  351. index d221e5c..113e760 100644
  352. --- a/src/sprite_data.cpp
  353. +++ b/src/sprite_data.cpp
  354. @@ -14,7 +14,9 @@
  355.  #include "sprite_data.h"
  356.  #include "fileio.h"
  357.  #include "bitmath.h"
  358. +#include "video.h"
  359.  
  360. +#include <map>
  361.  #include <vector>
  362.  
  363.  static const int MAX_IMAGE_COUNT = 5000; ///< Maximum number of images that can be loaded (arbitrary number).
  364. @@ -25,14 +27,19 @@ ImageData::ImageData()
  365.  {
  366.     this->width = 0;
  367.     this->height = 0;
  368. -   this->table = nullptr;
  369. -   this->data = nullptr;
  370. +   for (int gs = GS_START; gs < GS_COUNT; gs++) {
  371. +       this->images[static_cast<GradientShift>(gs)] = nullptr;
  372. +   }
  373.  }
  374.  
  375.  ImageData::~ImageData()
  376.  {
  377. -   delete[] this->table;
  378. -   delete[] this->data;
  379. +   for (auto &pair : this->images) {
  380. +       if (pair.second != nullptr) SDL_DestroyTexture(pair.second);
  381. +   }
  382. +
  383. +   for (auto &mask : this->masks) SDL_DestroyTexture(mask);
  384. +   SDL_FreeSurface(this->img);
  385.  }
  386.  
  387.  /**
  388. @@ -56,38 +63,37 @@ bool ImageData::Load8bpp(RcdFileReader *rcd_file, size_t length)
  389.     length -= 8;
  390.     if (length > 100 * 1024) return false; // Another arbitrary limit.
  391.  
  392. -   size_t jmp_table = 4 * this->height;
  393. -   if (length <= jmp_table) return false; // You need at least place for the jump table.
  394. -   length -= jmp_table;
  395. +   if (length <= this->height * sizeof(uint32)) return false; // You need at least place for the jump table.
  396. +   length -= this->height * sizeof(uint32);
  397.  
  398. -   this->table = new uint32[jmp_table / 4];
  399. -   this->data  = new uint8[length];
  400. -   if (this->table == nullptr || this->data == nullptr) return false;
  401. +   uint32 *jmp_table = new uint32[this->height];
  402. +   uint8 *data       = new uint8[length];
  403. +   if (jmp_table == nullptr || data == nullptr) return false;
  404.  
  405.     /* Load jump table, adjusting the entries while loading. */
  406.     for (uint i = 0; i < this->height; i++) {
  407.         uint32 dest = rcd_file->GetUInt32();
  408.         if (dest == 0) {
  409. -           this->table[i] = INVALID_JUMP;
  410. +           jmp_table[i] = INVALID_JUMP;
  411.             continue;
  412.         }
  413. -       dest -= jmp_table;
  414. +       dest -= this->height * sizeof(uint32);
  415.         if (dest >= length) return false;
  416. -       this->table[i] = dest;
  417. +       jmp_table[i] = dest;
  418.     }
  419.  
  420. -   rcd_file->GetBlob(this->data, length); // Load the image data.
  421. +   rcd_file->GetBlob(data, length); // Load the image data.
  422.  
  423.     /* Verify the image data. */
  424.     for (uint i = 0; i < this->height; i++) {
  425. -       uint32 offset = this->table[i];
  426. +       uint32 offset = jmp_table[i];
  427.         if (offset == INVALID_JUMP) continue;
  428.  
  429.         uint32 xpos = 0;
  430.         for (;;) {
  431.             if (offset + 2 >= length) return false;
  432. -           uint8 rel_pos = this->data[offset];
  433. -           uint8 count = this->data[offset + 1];
  434. +           uint8 rel_pos = data[offset];
  435. +           uint8 count = data[offset + 1];
  436.             xpos += (rel_pos & 127) + count;
  437.             offset += 2 + count;
  438.             if ((rel_pos & 128) == 0) {
  439. @@ -98,14 +104,14 @@ bool ImageData::Load8bpp(RcdFileReader *rcd_file, size_t length)
  440.             }
  441.         }
  442.     }
  443. -   return true;
  444. +   return this->Blit8bppSprite(jmp_table, data);
  445.  }
  446.  
  447.  /**
  448.   * Load a 32bpp image.
  449.   * @param rcd_file Input stream to read from.
  450.   * @param length Length of the 32bpp block.
  451. - * @return Exeit code, \0 means ok, every other number indicates an error.
  452. + * @return Exit code, \0 means ok, every other number indicates an error.
  453.   */
  454.  bool ImageData::Load32bpp(RcdFileReader *rcd_file, size_t length)
  455.  {
  456. @@ -122,14 +128,14 @@ bool ImageData::Load32bpp(RcdFileReader *rcd_file, size_t length)
  457.     if (length > 100 * 1024) return false; // Another arbitrary limit.
  458.  
  459.     /* Allocate and load the image data. */
  460. -   this->data = new uint8[length];
  461. -   if (this->data == nullptr) return false;
  462. -   rcd_file->GetBlob(this->data, length);
  463. +   uint8 *data = new uint8[length];
  464. +   if (data == nullptr) return false;
  465. +   rcd_file->GetBlob(data, length);
  466.  
  467.     /* Verify the data. */
  468. -   uint8 *abs_end = this->data + length;
  469. +   uint8 *abs_end = data + length;
  470.     int line_count = 0;
  471. -   const uint8 *ptr = this->data;
  472. +   const uint8 *ptr = data;
  473.     bool finished = false;
  474.     while (ptr < abs_end && !finished) {
  475.         line_count++;
  476. @@ -169,92 +175,136 @@ bool ImageData::Load32bpp(RcdFileReader *rcd_file, size_t length)
  477.     }
  478.     if (line_count != this->height) return false;
  479.     if (ptr != abs_end) return false;
  480. -   return true;
  481. +   return this->Blit32bppSprite(data);
  482.  }
  483.  
  484.  /**
  485. - * Return the pixel-value of the provided position.
  486. - * @param xoffset Horizontal offset in the sprite.
  487. - * @param yoffset Vertical offset in the sprite.
  488. - * @param recolour Recolouring to apply to the retrieved pixel. Use \c nullptr for disabling recolouring.
  489. - * @param shift Gradient shift to apply to the retrieved pixel. Use #GS_NORMAL for not shifting the colour.
  490. - * @return Pixel value at the given position, or \c 0 if transparent.
  491. + * @todo Add other gradientshifts
  492.   */
  493. -uint32 ImageData::GetPixel(uint16 xoffset, uint16 yoffset, const Recolouring *recolour, GradientShift shift) const
  494. +bool ImageData::SetupTextures(const std::vector<uint32> &mem, const std::vector<uint32> &recol)
  495.  {
  496. -   if (xoffset >= this->width) return _palette[0];
  497. -   if (yoffset >= this->height) return _palette[0];
  498. +   this->img = SDL_CreateRGBSurfaceFrom((void *)mem.data(), this->width, this->height, 32, this->width * sizeof(uint32),
  499. +                                        0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
  500. +
  501. +   this->images[GS_NORMAL] = SDL_CreateTextureFromSurface(_video.GetRenderer(), this->img);
  502. +   SDL_SetTextureBlendMode(this->images[GS_NORMAL], SDL_BLENDMODE_BLEND);
  503. +// for (auto &pair : this->images) {
  504. +//     pair.second = SDL_CreateTextureFromSurface(_video.GetRenderer(), this->img);
  505. +//     SDL_SetTextureBlendMode(pair.second, SDL_BLENDMODE_BLEND);
  506. +// }
  507. +
  508. +   return this->img != nullptr;
  509. +}
  510.  
  511. -   if (GB(this->flags, IFG_IS_8BPP, 1) != 0) {
  512. -       /* 8bpp image. */
  513. -       uint32 offset = this->table[yoffset];
  514. -       if (offset == INVALID_JUMP) return _palette[0];
  515. -
  516. -       uint16 xpos = 0;
  517. -       while (xpos <= xoffset) {
  518. -           uint8 rel_pos = this->data[offset];
  519. -           uint8 count = this->data[offset + 1];
  520. -           xpos += (rel_pos & 127);
  521. -           if (xpos > xoffset) return _palette[0];
  522. -           if (xoffset - xpos < count) {
  523. -               uint8 pixel = this->data[offset + 2 + xoffset - xpos];
  524. -               if (recolour != nullptr) {
  525. -                   const uint8 *recolour_table = recolour->GetPalette(shift);
  526. -                   pixel = recolour_table[pixel];
  527. +/**
  528. + */
  529. +bool ImageData::Blit8bppSprite(const uint32 *jmp_table, const uint8 *data)
  530. +{
  531. +   if (this->height == 0 || this->width == 0) return false;
  532. +   std::vector<uint32> mem(this->height * this->width);
  533. +   std::vector<uint32> recol(this->height * this->width);
  534. +
  535. +   for (int ypos = 0; ypos < this->height; ypos++) {
  536. +       uint32 offset = jmp_table[ypos];
  537. +       if (offset != INVALID_JUMP) {
  538. +           for (int xpos = 0;;) {
  539. +               uint8 rel_off = data[offset];
  540. +               uint8 count   = data[offset + 1];
  541. +               const uint8 *pixels = &data[offset + 2];
  542. +               offset += 2 + count;
  543. +
  544. +               xpos += rel_off & 0x7F;
  545. +               for(; count > 0; count--) {
  546. +                   // RECOLOURING
  547. +                   mem.at(ypos * this->width + xpos) = _palette[*pixels];
  548. +                   pixels++;
  549. +                   xpos++;
  550.                 }
  551. -               return _palette[pixel];
  552. +               if ((rel_off & 0x80) != 0) break;
  553.             }
  554. -           xpos += count;
  555. -           offset += 2 + count;
  556. -           if ((rel_pos & 128) != 0) break;
  557. -       }
  558. -       return _palette[0];
  559. -   } else {
  560. -       /* 32bpp image. */
  561. -       const uint8 *ptr = this->data;
  562. -       while (yoffset > 0) {
  563. -           uint16 length = ptr[0] | (ptr[1] << 8);
  564. -           ptr += length;
  565. -           yoffset--;
  566.         }
  567. -       ptr += 2;
  568. -       while (xoffset > 0) {
  569. -           uint8 mode = *ptr++;
  570. +   }
  571. +   return this->SetupTextures(mem, recol);
  572. +}
  573. +
  574. +/**
  575. + */
  576. +bool ImageData::Blit32bppSprite(const uint8 *data)
  577. +{
  578. +   if (this->height == 0 || this->width == 0) return false;
  579. +   std::vector<uint32> mem(this->height * this->width);
  580. +   std::vector<uint32> recol(this->height * this->width);
  581. +
  582. +   const uint8 *src = data + 2; // Skip the length word.
  583. +   for (int ypos = 0; ypos < this->height; ypos++) {
  584. +       for (int xpos = 0;;) {
  585. +           uint8 mode = *src++;
  586.             if (mode == 0) break;
  587. -           if ((mode & 0x3F) < xoffset) {
  588. -               xoffset -= mode & 0x3F;
  589. -               switch (mode >> 6) {
  590. -                   case 0: ptr += 3 * (mode & 0x3F); break;
  591. -                   case 1: ptr += 1 + 3 * (mode & 0x3F); break;
  592. -                   case 2: ptr++; break;
  593. -                   case 3: ptr += 1 + 1 + (mode & 0x3F); break;
  594. -               }
  595. -           } else {
  596. -               ShiftFunc sf = GetGradientShiftFunc(shift);
  597. -               switch (mode >> 6) {
  598. -                   case 0:
  599. -                       ptr += 3 * xoffset;
  600. -                       return MakeRGBA(sf(ptr[0]), sf(ptr[1]), sf(ptr[2]), OPAQUE);
  601. -                   case 1: {
  602. -                       uint8 opacity = *ptr;
  603. -                       ptr += 1 + 3 * xoffset;
  604. -                       return MakeRGBA(sf(ptr[0]), sf(ptr[1]), sf(ptr[2]), opacity);
  605. +           int len = mode & 0x3F;
  606. +           switch (mode >> 6) {
  607. +               case 0: // Fully opaque pixels.
  608. +                   for (; len > 0; len--) {
  609. +                       mem.at(ypos * this->width + xpos) = MakeRGBA(src[0], src[1], src[2], OPAQUE);
  610. +                       xpos++;
  611. +                       src += 3;
  612. +                   }
  613. +                   break;
  614. +
  615. +               case 1: { // Partial opaque pixels.
  616. +                   uint8 opacity = *src++;
  617. +                   for (; len > 0; len--) {
  618. +                       mem.at(ypos * this->width + xpos) = MakeRGBA(src[0], src[1], src[2], opacity);
  619. +                       xpos++;
  620. +                       src += 3;
  621.                     }
  622. -                   case 2:
  623. -                       return _palette[0]; // Arbitrary fully transparent.
  624. -                   case 3: {
  625. -                       uint8 opacity = ptr[1];
  626. -                       if (recolour == nullptr) return MakeRGBA(0, 0, 0, opacity); // Arbitrary colour with the correct opacity.
  627. -                       const uint32 *table = recolour->GetRecolourTable(ptr[0] - 1);
  628. -                       ptr += 2 + xoffset;
  629. -                       uint32 recoloured = table[*ptr];
  630. -                       return MakeRGBA(sf(GetR(recoloured)), sf(GetG(recoloured)), sf(GetB(recoloured)), opacity);
  631. +                   break;
  632. +               }
  633. +               case 2: // Fully transparent pixels.
  634. +                   xpos += len;
  635. +                   break;
  636. +
  637. +               case 3: { // Recoloured pixels.
  638. +                   uint8 layer = *src++;
  639. +                   //const uint32 *table = recolour.GetRecolourTable(layer - 1);
  640. +                   uint8 opacity = *src++;
  641. +                   for (; len > 0; len--) {
  642. +                       *src++;//uint32 recoloured = table[*src++];
  643. +                       //mem.at(ypos * this->width + xpos) = SetA(recoloured, opacity);
  644. +                       xpos++;
  645.                     }
  646. +                   break;
  647.                 }
  648.             }
  649.         }
  650. -       return _palette[0]; // Arbitrary fully transparent.
  651. +       src += 2; // Skip the length word.
  652.     }
  653. +
  654. +   return this->SetupTextures(mem, recol);
  655. +}
  656. +
  657. +
  658. +/**
  659. + * Return the pixel-value of the provided position.
  660. + * @param xoffset Horizontal offset in the sprite.
  661. + * @param yoffset Vertical offset in the sprite.
  662. + * @param recolour Recolouring to apply to the retrieved pixel. Use \c nullptr for disabling recolouring.
  663. + * @param shift Gradient shift to apply to the retrieved pixel. Use #GS_NORMAL for not shifting the colour.
  664. + * @return Pixel value at the given position, or \c 0 if transparent.
  665. + */
  666. +uint32 ImageData::GetPixel(uint16 xoffset, uint16 yoffset, const Recolouring *recolour) const
  667. +{
  668. +   if (xoffset >= this->width) return _palette[0];
  669. +   if (yoffset >= this->height) return _palette[0];
  670. +
  671. +   SDL_LockSurface(this->img);
  672. +
  673. +   int pitch = this->img->pitch;
  674. +   uint32 *pixels = (uint32 *)this->img->pixels;
  675. +
  676. +   uint32 col = pixels[yoffset * pitch + xoffset];
  677. +
  678. +   SDL_UnlockSurface(this->img);
  679. +   return col;
  680.  }
  681.  
  682.  /**
  683. diff --git a/src/sprite_data.h b/src/sprite_data.h
  684. index e1061b1..778f232 100644
  685. --- a/src/sprite_data.h
  686. +++ b/src/sprite_data.h
  687. @@ -12,6 +12,8 @@
  688.  #ifndef SPRITE_DATA_H
  689.  #define SPRITE_DATA_H
  690.  
  691. +#include <SDL.h>
  692. +
  693.  static const uint32 INVALID_JUMP = UINT32_MAX; ///< Invalid jump destination in image data.
  694.  
  695.  class RcdFileReader;
  696. @@ -33,7 +35,7 @@ public:
  697.     bool Load8bpp(RcdFileReader *rcd_file, size_t length);
  698.     bool Load32bpp(RcdFileReader *rcd_file, size_t length);
  699.  
  700. -   uint32 GetPixel(uint16 xoffset, uint16 yoffset, const Recolouring *recolour = nullptr, GradientShift shift = GS_NORMAL) const;
  701. +   uint32 GetPixel(uint16 xoffset, uint16 yoffset, const Recolouring *recolour = nullptr) const;
  702.  
  703.     /**
  704.      * Is the sprite just a single pixel?
  705. @@ -49,8 +51,15 @@ public:
  706.     uint16 height; ///< Height of the image.
  707.     int16 xoffset; ///< Horizontal offset of the image.
  708.     int16 yoffset; ///< Vertical offset of the image.
  709. -   uint32 *table; ///< The jump table. For missing entries, #INVALID_JUMP is used.
  710. -   uint8 *data;   ///< The image data itself.
  711. +
  712. +   std::map<GradientShift, SDL_Texture *> images;
  713. +   std::vector<SDL_Texture *> masks;
  714. +private:
  715. +   SDL_Surface *img; // Used to determine an image's opacity
  716. +
  717. +   bool Blit8bppSprite(const uint32 *jmp_table, const uint8 *data);
  718. +   bool Blit32bppSprite(const uint8 *data);
  719. +   bool SetupTextures(const std::vector<uint32> &mem, const std::vector<uint32> &recol);
  720.  };
  721.  
  722.  ImageData *LoadImage(RcdFileReader *rcd_file);
  723. diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp
  724. index dbf13a5..5cd5eaf 100644
  725. --- a/src/terraform_gui.cpp
  726. +++ b/src/terraform_gui.cpp
  727. @@ -103,7 +103,7 @@ void TerraformGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) const
  728.  
  729.         base.x = this->GetWidgetScreenX(wid) + (wid->pos.width - dot->width) / 2;
  730.         base.y = this->GetWidgetScreenY(wid) + (wid->pos.height - dot->height) / 2;
  731. -       _video.BlitImage(base, dot, recolour, GS_NORMAL);
  732. +       _video.BlitImage(base, dot, recolour);
  733.         return;
  734.     }
  735.  
  736. diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
  737. index 57ba0ae..51f49ae 100644
  738. --- a/src/toolbar_gui.cpp
  739. +++ b/src/toolbar_gui.cpp
  740. @@ -368,14 +368,14 @@ void BottomToolbarWindow::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid
  741.             Viewport *vp = GetViewport();
  742.             int dir = (vp == nullptr) ? 0 : vp->orientation;
  743.             const ImageData *img = _sprite_manager.GetTableSprite(SPR_GUI_COMPASS_START + dir);
  744. -           if (img != nullptr) _video.BlitImage({GetWidgetScreenX(wid), GetWidgetScreenY(wid)}, img, recolour, GS_NORMAL);
  745. +           if (img != nullptr) _video.BlitImage({GetWidgetScreenX(wid), GetWidgetScreenY(wid)}, img, recolour);
  746.             break;
  747.         }
  748.  
  749.         case BTB_WEATHER: {
  750.             int spr = SPR_GUI_WEATHER_START + _weather.GetWeatherType();
  751.             const ImageData *img = _sprite_manager.GetTableSprite(spr);
  752. -           if (img != nullptr) _video.BlitImage({GetWidgetScreenX(wid), GetWidgetScreenY(wid)}, img, recolour, GS_NORMAL);
  753. +           if (img != nullptr) _video.BlitImage({GetWidgetScreenX(wid), GetWidgetScreenY(wid)}, img, recolour);
  754.             break;
  755.         }
  756.     }
  757. diff --git a/src/video.cpp b/src/video.cpp
  758. index f4fbdb2..7ee8601 100644
  759. --- a/src/video.cpp
  760. +++ b/src/video.cpp
  761. @@ -20,6 +20,8 @@
  762.  #include "gamecontrol.h"
  763.  #include "window.h"
  764.  #include "viewport.h"
  765. +#include "weather.h"
  766. +
  767.  #include <string>
  768.  
  769.  VideoSystem _video;  ///< Video sub-system.
  770. @@ -31,100 +33,6 @@ void QuitProgram()
  771.     _finish = true;
  772.  }
  773.  
  774. -/** Default constructor of a clipped rectangle. */
  775. -ClippedRectangle::ClippedRectangle()
  776. -{
  777. -   this->absx = 0;
  778. -   this->absy = 0;
  779. -   this->width = 0;
  780. -   this->height = 0;
  781. -   this->address = nullptr; this->pitch = 0;
  782. -}
  783. -
  784. -/**
  785. - * Construct a clipped rectangle from coordinates.
  786. - * @param x Top-left x position.
  787. - * @param y Top-left y position.
  788. - * @param w Width.
  789. - * @param h Height.
  790. - */
  791. -ClippedRectangle::ClippedRectangle(uint16 x, uint16 y, uint16 w, uint16 h)
  792. -{
  793. -   this->absx = x;
  794. -   this->absy = y;
  795. -   this->width = w;
  796. -   this->height = h;
  797. -   this->address = nullptr; this->pitch = 0;
  798. -}
  799. -
  800. -/**
  801. - * Construct a clipped rectangle inside an existing one.
  802. - * @param cr Existing rectangle.
  803. - * @param x Top-left x position.
  804. - * @param y Top-left y position.
  805. - * @param w Width.
  806. - * @param h Height.
  807. - * @note %Rectangle is clipped to the old one.
  808. - */
  809. -ClippedRectangle::ClippedRectangle(const ClippedRectangle &cr, uint16 x, uint16 y, uint16 w, uint16 h)
  810. -{
  811. -   if (x >= cr.width || y >= cr.height) {
  812. -       this->absx = 0;
  813. -       this->absy = 0;
  814. -       this->width = 0;
  815. -       this->height = 0;
  816. -       this->address = nullptr; this->pitch = 0;
  817. -       return;
  818. -   }
  819. -   if (x + w > cr.width)  w = cr.width - x;
  820. -   if (y + h > cr.height) h = cr.height - y;
  821. -
  822. -   this->absx = cr.absx + x;
  823. -   this->absy = cr.absy + y;
  824. -   this->width = w;
  825. -   this->height = h;
  826. -   this->address = nullptr; this->pitch = 0;
  827. -}
  828. -
  829. -/**
  830. - * Copy constructor.
  831. - * @param cr Existing clipped rectangle.
  832. - */
  833. -ClippedRectangle::ClippedRectangle(const ClippedRectangle &cr)
  834. -{
  835. -   this->absx = cr.absx;
  836. -   this->absy = cr.absy;
  837. -   this->width = cr.width;
  838. -   this->height = cr.height;
  839. -   this->address = cr.address; this->pitch = cr.pitch;
  840. -}
  841. -
  842. -/**
  843. - * Assignment operator override.
  844. - * @param cr Existing clipped rectangle.
  845. - * @return The assigned value.
  846. - */
  847. -ClippedRectangle &ClippedRectangle::operator=(const ClippedRectangle &cr)
  848. -{
  849. -   if (this != &cr) {
  850. -       this->absx = cr.absx;
  851. -       this->absy = cr.absy;
  852. -       this->width = cr.width;
  853. -       this->height = cr.height;
  854. -       this->address = cr.address; this->pitch = cr.pitch;
  855. -   }
  856. -   return *this;
  857. -}
  858. -
  859. -/** Initialize the #address if not done already. */
  860. -void ClippedRectangle::ValidateAddress()
  861. -{
  862. -   if (this->address == nullptr) {
  863. -       this->pitch = _video.GetXSize();
  864. -       this->address = _video.mem + this->absx + this->absy * this->pitch;
  865. -   }
  866. -}
  867. -
  868.  /**
  869.   * Default constructor, does nothing, never goes wrong.
  870.   * Call #Initialize to initialize the system.
  871. @@ -165,9 +73,18 @@ std::string VideoSystem::Initialize(const char *font_name, int font_size)
  872.         return err;
  873.     }
  874.  
  875. +   this->renderer = SDL_CreateRenderer(this->window, -1, 0);
  876. +   if (this->renderer == nullptr) {
  877. +       std::string err = "Could not create renderer: ";
  878. +       err += SDL_GetError();
  879. +       SDL_Quit();
  880. +       return err;
  881. +   }
  882. +   SDL_SetRenderDrawBlendMode(this->renderer, SDL_BLENDMODE_BLEND);
  883. +
  884.     this->GetResolutions();
  885.  
  886. -   this->SetResolution({800, 600}); // Allocates this->mem, return value is ignored.
  887. +   this->SetResolution({800, 600}); // return value is ignored.
  888.  
  889.     /* SDL_CreateRGBSurfaceFrom() pretends to use a void* for the data,
  890.      * but it's really treated as endian-specific uint32*.
  891. @@ -183,12 +100,11 @@ std::string VideoSystem::Initialize(const char *font_name, int font_size)
  892.         SDL_SetWindowIcon(this->window, icon);
  893.         SDL_FreeSurface(icon);
  894.     } else {
  895. -       printf("Could not set window icon (%s)\n", SDL_GetError());
  896. +       fprintf(stderr, "Could not set window icon (%s)\n", SDL_GetError());
  897.     }
  898.  
  899.     if (TTF_Init() != 0) {
  900.         SDL_Quit();
  901. -       delete[] this->mem;
  902.         std::string err = "TTF font initialization failed: ";
  903.         err += TTF_GetError();
  904.         return err;
  905. @@ -204,7 +120,6 @@ std::string VideoSystem::Initialize(const char *font_name, int font_size)
  906.         err += TTF_GetError();
  907.         TTF_Quit();
  908.         SDL_Quit();
  909. -       delete[] this->mem;
  910.         return err;
  911.     }
  912.  
  913. @@ -230,43 +145,12 @@ bool VideoSystem::SetResolution(const Point32 &res)
  914.  {
  915.     if (this->initialized && this->GetXSize() == res.x && this->GetYSize() == res.y) return true;
  916.  
  917. -   /* Destroy old window, if it exists. */
  918. -   if (this->initialized) {
  919. -       delete[] mem;
  920. -       this->mem = nullptr;
  921. -       SDL_DestroyTexture(this->texture);
  922. -       this->texture = nullptr;
  923. -       SDL_DestroyRenderer(this->renderer);
  924. -       this->renderer = nullptr;
  925. -   }
  926. -
  927.     this->vid_width = res.x;
  928.     this->vid_height = res.y;
  929.     SDL_SetWindowSize(this->window, this->vid_width, this->vid_height);
  930.  
  931. -   this->renderer = SDL_CreateRenderer(this->window, -1, 0);
  932. -   if (this->renderer == nullptr) {
  933. -       SDL_Quit();
  934. -       fprintf(stderr, "Could not create renderer (%s)\n", SDL_GetError());
  935. -       return false;
  936. -   }
  937. -
  938. -   this->texture = SDL_CreateTexture(this->renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, this->vid_width, this->vid_height);
  939. -   if (this->texture == nullptr) {
  940. -       SDL_Quit();
  941. -       fprintf(stderr, "Could not create texture (%s)\n", SDL_GetError());
  942. -       return false;
  943. -   }
  944. -
  945. -   this->mem = new uint32[this->vid_width * this->vid_height];
  946. -   if (this->mem == nullptr) {
  947. -       SDL_Quit();
  948. -       fprintf(stderr, "Failed to obtain window display storage.\n");
  949. -       return false;
  950. -   }
  951. -
  952.     /* Update internal screen size data structures. */
  953. -   this->blit_rect = ClippedRectangle(0, 0, this->vid_width, this->vid_height);
  954. +   this->blit_rect = Rectangle32(0, 0, this->vid_width, this->vid_height);
  955.     Viewport *vp = GetViewport();
  956.     if (vp != nullptr) vp->SetSize(this->vid_width, this->vid_height);
  957.     _manager.RepositionAllWindows();
  958. @@ -314,18 +198,17 @@ void VideoSystem::MarkDisplayClean()
  959.   * Set the clipped area.
  960.   * @param cr New clipped blitting area.
  961.   */
  962. -void VideoSystem::SetClippedRectangle(const ClippedRectangle &cr)
  963. +void VideoSystem::SetClippedRectangle(const Rectangle32 &rect)
  964.  {
  965. -   this->blit_rect = cr;
  966. +   this->blit_rect = rect;
  967.  }
  968.  
  969.  /**
  970.   * Get the current clipped blitting area.
  971.   * @return Current clipped area.
  972.   */
  973. -ClippedRectangle VideoSystem::GetClippedRectangle()
  974. +Rectangle32 VideoSystem::GetClippedRectangle()
  975.  {
  976. -   this->blit_rect.ValidateAddress();
  977.     return this->blit_rect;
  978.  }
  979.  
  980. @@ -439,6 +322,9 @@ void VideoSystem::MainLoop()
  981.         if (_finish) break;
  982.  
  983.         uint32 now = SDL_GetTicks();
  984. +
  985. +       printf("%dms\n", now - start);
  986. +
  987.         if (now >= start) { // No wrap around.
  988.             now -= start;
  989.             if (now < FRAME_DELAY) SDL_Delay(FRAME_DELAY - now); // Too early, wait until next frame.
  990. @@ -458,7 +344,6 @@ void VideoSystem::Shutdown()
  991.         TTF_CloseFont(this->font);
  992.         TTF_Quit();
  993.         SDL_Quit();
  994. -       delete[] this->mem;
  995.         this->initialized = false;
  996.         this->dirty = false;
  997.     }
  998. @@ -470,192 +355,13 @@ void VideoSystem::Shutdown()
  999.   */
  1000.  void VideoSystem::FinishRepaint()
  1001.  {
  1002. -   SDL_UpdateTexture(this->texture, nullptr, this->mem, this->GetXSize() * sizeof(uint32)); // Upload memory to the GPU.
  1003. -   SDL_RenderClear(this->renderer);
  1004. -   SDL_RenderCopy(this->renderer, this->texture, nullptr, nullptr);
  1005.     SDL_RenderPresent(this->renderer);
  1006.  
  1007. -   MarkDisplayClean();
  1008. -}
  1009. -
  1010. -/**
  1011. - * Blit pixels from the \a spr relative to #blit_rect into the area.
  1012. - * @param img_base Coordinate of the sprite data.
  1013. - * @param spr The sprite to blit.
  1014. - * @param recolour Sprite recolouring definition.
  1015. - * @param shift Gradient shift.
  1016. - */
  1017. -void VideoSystem::BlitImage(const Point32 &img_base, const ImageData *spr, const Recolouring &recolour, GradientShift shift)
  1018. -{
  1019. -   this->BlitImage(img_base, spr, recolour, shift);
  1020. -}
  1021. -
  1022. -/**
  1023. - * Blit a pixel to an area of \a numx times \a numy sprites.
  1024. - * @param cr Clipped rectangle.
  1025. - * @param scr_base Base address of the screen array.
  1026. - * @param xmin Minimal x position.
  1027. - * @param ymin Minimal y position.
  1028. - * @param numx Number of horizontal count.
  1029. - * @param numy Number of vertical count.
  1030. - * @param width Width of an image.
  1031. - * @param height Height of an image.
  1032. - * @param colour Pixel value to blit.
  1033. - * @note Function does not handle alpha blending of the new pixel with the background.
  1034. - */
  1035. -static void BlitPixel(const ClippedRectangle &cr, uint32 *scr_base,
  1036. -       int32 xmin, int32 ymin, uint16 numx, uint16 numy, uint16 width, uint16 height, uint32 colour)
  1037. -{
  1038. -   const int32 xend = xmin + numx * width;
  1039. -   const int32 yend = ymin + numy * height;
  1040. -   while (ymin < yend) {
  1041. -       if (ymin >= cr.height) return;
  1042. -
  1043. -       if (ymin >= 0) {
  1044. -           uint32 *scr = scr_base;
  1045. -           int32 x = xmin;
  1046. -           while (x < xend) {
  1047. -               if (x >= cr.width) break;
  1048. -               if (x >= 0) *scr = colour;
  1049. -
  1050. -               x += width;
  1051. -               scr += width;
  1052. -           }
  1053. -       }
  1054. -       ymin += height;
  1055. -       scr_base += height * cr.pitch;
  1056. -   }
  1057. -}
  1058. -
  1059. -/**
  1060. - * Blit 8bpp images to the screen.
  1061. - * @param cr Clipped rectangle to draw to.
  1062. - * @param x_base Base X coordinate of the sprite data.
  1063. - * @param y_base Base Y coordinate of the sprite data.
  1064. - * @param spr The sprite to blit.
  1065. - * @param numx Number of sprites to draw in horizontal direction.
  1066. - * @param numy Number of sprites to draw in vertical direction.
  1067. - * @param recoloured Shifted palette to use.
  1068. - */
  1069. -static void Blit8bppImages(const ClippedRectangle &cr, int32 x_base, int32 y_base, const ImageData *spr, uint16 numx, uint16 numy, const uint8 *recoloured)
  1070. -{
  1071. -   uint32 *line_base = cr.address + x_base + cr.pitch * y_base;
  1072. -   int32 ypos = y_base;
  1073. -   for (int yoff = 0; yoff < spr->height; yoff++) {
  1074. -       uint32 offset = spr->table[yoff];
  1075. -       if (offset != INVALID_JUMP) {
  1076. -           int32 xpos = x_base;
  1077. -           uint32 *src_base = line_base;
  1078. -           for (;;) {
  1079. -               uint8 rel_off = spr->data[offset];
  1080. -               uint8 count   = spr->data[offset + 1];
  1081. -               uint8 *pixels = &spr->data[offset + 2];
  1082. -               offset += 2 + count;
  1083. -
  1084. -               xpos += rel_off & 127;
  1085. -               src_base += rel_off & 127;
  1086. -               while (count > 0) {
  1087. -                   uint32 colour = _palette[recoloured[*pixels]];
  1088. -                   BlitPixel(cr, src_base, xpos, ypos, numx, numy, spr->width, spr->height, colour);
  1089. -                   pixels++;
  1090. -                   xpos++;
  1091. -                   src_base++;
  1092. -                   count--;
  1093. -               }
  1094. -               if ((rel_off & 128) != 0) break;
  1095. -           }
  1096. -       }
  1097. -       line_base += cr.pitch;
  1098. -       ypos++;
  1099. -   }
  1100. -}
  1101. -
  1102. -/**
  1103. - * Blit 32bpp images to the screen.
  1104. - * @param cr Clipped rectangle to draw to.
  1105. - * @param x_base Base X coordinate of the sprite data.
  1106. - * @param y_base Base Y coordinate of the sprite data.
  1107. - * @param spr The sprite to blit.
  1108. - * @param numx Number of sprites to draw in horizontal direction.
  1109. - * @param numy Number of sprites to draw in vertical direction.
  1110. - * @param recolour Sprite recolouring definition.
  1111. - * @param shift Gradient shift.
  1112. - */
  1113. -static void Blit32bppImages(const ClippedRectangle &cr, int32 x_base, int32 y_base, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour, GradientShift shift)
  1114. -{
  1115. -   uint32 *line_base = cr.address + x_base + cr.pitch * y_base;
  1116. -   ShiftFunc sf = GetGradientShiftFunc(shift);
  1117. -   int32 ypos = y_base;
  1118. -   const uint8 *src = spr->data + 2; // Skip the length word.
  1119. -   for (int yoff = 0; yoff < spr->height; yoff++) {
  1120. -       int32 xpos = x_base;
  1121. -       uint32 *src_base = line_base;
  1122. -       for (;;) {
  1123. -           uint8 mode = *src++;
  1124. -           if (mode == 0) break;
  1125. -           switch (mode >> 6) {
  1126. -               case 0: // Fully opaque pixels.
  1127. -                   mode &= 0x3F;
  1128. -                   for (; mode > 0; mode--) {
  1129. -                       uint32 colour = MakeRGBA(sf(src[0]), sf(src[1]), sf(src[2]), OPAQUE);
  1130. -                       BlitPixel(cr, src_base, xpos, ypos, numx, numy, spr->width, spr->height, colour);
  1131. -                       xpos++;
  1132. -                       src_base++;
  1133. -                       src += 3;
  1134. -                   }
  1135. -                   break;
  1136. -
  1137. -               case 1: { // Partial opaque pixels.
  1138. -                   uint8 opacity = *src++;
  1139. -                   mode &= 0x3F;
  1140. -                   for (; mode > 0; mode--) {
  1141. -                       /* Cheat transparency a bit by just recolouring the previously drawn pixel */
  1142. -                       uint32 old_pixel = *src_base;
  1143. -
  1144. -                       uint r = sf(src[0]) * opacity + GetR(old_pixel) * (256 - opacity);
  1145. -                       uint g = sf(src[1]) * opacity + GetG(old_pixel) * (256 - opacity);
  1146. -                       uint b = sf(src[2]) * opacity + GetB(old_pixel) * (256 - opacity);
  1147. -
  1148. -                       /* Opaque, but colour adjusted depending on the old pixel. */
  1149. -                       uint32 ndest = MakeRGBA(r >> 8, g >> 8, b >> 8, OPAQUE);
  1150. -                       BlitPixel(cr, src_base, xpos, ypos, numx, numy, spr->width, spr->height, ndest);
  1151. -                       xpos++;
  1152. -                       src_base++;
  1153. -                       src += 3;
  1154. -                   }
  1155. -                   break;
  1156. -               }
  1157. -               case 2: // Fully transparent pixels.
  1158. -                   xpos += mode & 0x3F;
  1159. -                   src_base += mode & 0x3F;
  1160. -                   break;
  1161. +   /* Reset the renderer */
  1162. +   SDL_SetRenderDrawColor(this->renderer, 0, 0, 0, 0);
  1163. +   SDL_RenderClear(this->renderer);
  1164.  
  1165. -               case 3: { // Recoloured pixels.
  1166. -                   uint8 layer = *src++;
  1167. -                   const uint32 *table = recolour.GetRecolourTable(layer - 1);
  1168. -                   uint8 opacity = *src++;
  1169. -                   mode &= 0x3F;
  1170. -                   for (; mode > 0; mode--) {
  1171. -                       uint32 old_pixel = *src_base;
  1172. -                       uint32 recoloured = table[*src++];
  1173. -
  1174. -                       uint r = sf(GetR(recoloured)) * opacity + GetR(old_pixel) * (256 - opacity);
  1175. -                       uint g = sf(GetG(recoloured)) * opacity + GetG(old_pixel) * (256 - opacity);
  1176. -                       uint b = sf(GetB(recoloured)) * opacity + GetB(old_pixel) * (256 - opacity);
  1177. -
  1178. -                       uint32 colour = MakeRGBA(r >> 8, g >> 8, b >> 8, OPAQUE);
  1179. -                       BlitPixel(cr, src_base, xpos, ypos, numx, numy, spr->width, spr->height, colour);
  1180. -                       xpos++;
  1181. -                       src_base++;
  1182. -                   }
  1183. -                   break;
  1184. -               }
  1185. -           }
  1186. -       }
  1187. -       line_base += cr.pitch;
  1188. -       ypos++;
  1189. -       src += 2; // Skip the length word.
  1190. -   }
  1191. +   MarkDisplayClean();
  1192.  }
  1193.  
  1194.  /**
  1195. @@ -667,31 +373,28 @@ static void Blit32bppImages(const ClippedRectangle &cr, int32 x_base, int32 y_ba
  1196.   * @param recolour Sprite recolouring definition.
  1197.   * @param shift Gradient shift.
  1198.   */
  1199. -void VideoSystem::BlitImages(const Point32 &pt, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour, GradientShift shift)
  1200. +void VideoSystem::BlitImages(const Point32 &pt, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour)
  1201.  {
  1202. -   this->blit_rect.ValidateAddress();
  1203. -
  1204.     int x_base = pt.x + spr->xoffset;
  1205.     int y_base = pt.y + spr->yoffset;
  1206.  
  1207. -   /* Don't draw wildly outside the screen. */
  1208. -   while (numx > 0 && x_base + spr->width < 0) {
  1209. -       x_base += spr->width; numx--;
  1210. -   }
  1211. -   while (numx > 0 && x_base + (numx - 1) * spr->width >= this->blit_rect.width) numx--;
  1212. -   if (numx == 0) return;
  1213. +   // Get current gradient shift
  1214. +   GradientShift gs = static_cast<GradientShift>(GS_LIGHT - _weather.GetWeatherType());
  1215.  
  1216. -   while (numy > 0 && y_base + spr->height < 0) {
  1217. -       y_base += spr->height; numy--;
  1218. +   SDL_Texture *shifted_sprite = spr->images.find(gs)->second;
  1219. +   if (shifted_sprite == nullptr) {
  1220. +       shifted_sprite = spr->images.find(GS_NORMAL)->second;
  1221.     }
  1222. -   while (numy > 0 && y_base + (numy - 1) * spr->height >= this->blit_rect.height) numy--;
  1223. -   if (numy == 0) return;
  1224. +   assert(shifted_sprite != nullptr);
  1225.  
  1226. -   if (GB(spr->flags, IFG_IS_8BPP, 1) != 0) {
  1227. -       Blit8bppImages(this->blit_rect, x_base, y_base, spr, numx, numy, recolour.GetPalette(shift));
  1228. -   } else {
  1229. -       Blit32bppImages(this->blit_rect, x_base, y_base, spr, numx, numy, recolour, shift);
  1230. +   for (int x = 0; x < numx; x++) {
  1231. +       for (int y = 0; y < numy; y++) {
  1232. +           SDL_Rect sdl_rect = {x_base + x * spr->width, y_base + y * spr->height, spr->width, spr->height};
  1233. +           SDL_RenderCopy(this->renderer, shifted_sprite, nullptr, &sdl_rect);
  1234. +           // Also draw recolourings
  1235. +       }
  1236.     }
  1237. +
  1238.  }
  1239.  
  1240.  /**
  1241. @@ -757,7 +460,7 @@ void VideoSystem::GetNumberRangeSize(int64 smallest, int64 biggest, int *width,
  1242.   */
  1243.  void VideoSystem::BlitText(const uint8 *text, uint32 colour, int xpos, int ypos, int width, Alignment align)
  1244.  {
  1245. -   SDL_Color col = {0, 0, 0}; // Font colour does not matter as only the bitmap is used.
  1246. +   SDL_Color col = {SPLIT_RGBA(colour)};
  1247.     SDL_Surface *surf = TTF_RenderUTF8_Solid(this->font, (const char *)text, col);
  1248.     if (surf == nullptr) {
  1249.         fprintf(stderr, "Rendering text failed (%s)\n", TTF_GetError());
  1250. @@ -769,7 +472,10 @@ void VideoSystem::BlitText(const uint8 *text, uint32 colour, int xpos, int ypos,
  1251.         return;
  1252.     }
  1253.  
  1254. +   SDL_Texture *tex = SDL_CreateTextureFromSurface(this->renderer, surf);
  1255. +
  1256.     int real_w = std::min(surf->w, width);
  1257. +
  1258.     switch (align) {
  1259.         case ALG_LEFT:
  1260.             break;
  1261. @@ -785,44 +491,10 @@ void VideoSystem::BlitText(const uint8 *text, uint32 colour, int xpos, int ypos,
  1262.         default: NOT_REACHED();
  1263.     }
  1264.  
  1265. -   this->blit_rect.ValidateAddress();
  1266. -
  1267. -   uint8 *src = ((uint8 *)surf->pixels);
  1268. -   uint32 *dest = this->blit_rect.address + xpos + ypos * this->blit_rect.pitch;
  1269. -   int h = surf->h;
  1270. -   if (ypos < 0) {
  1271. -       h += ypos;
  1272. -       src  -= ypos * surf->pitch;
  1273. -       dest -= ypos * this->blit_rect.pitch;
  1274. -       ypos = 0;
  1275. -   }
  1276. -   while (h > 0) {
  1277. -       if (ypos >= this->blit_rect.height) break;
  1278. -       uint8 *src2 = src;
  1279. -       uint32 *dest2 = dest;
  1280. -       int w = real_w;
  1281. -       int x = xpos;
  1282. -       if (x < 0) {
  1283. -           w += x;
  1284. -           if (w <= 0) break;
  1285. -           dest2 -= x;
  1286. -           src2 -= x;
  1287. -           x = 0;
  1288. -       }
  1289. -       while (w > 0) {
  1290. -           if (x >= this->blit_rect.width) break;
  1291. -           if (*src2 != 0) *dest2 = colour;
  1292. -           src2++;
  1293. -           dest2++;
  1294. -           x++;
  1295. -           w--;
  1296. -       }
  1297. -       ypos++;
  1298. -       src  += surf->pitch;
  1299. -       dest += this->blit_rect.pitch;
  1300. -       h--;
  1301. -   }
  1302. +   SDL_Rect sdl_rect = {xpos, ypos, real_w, surf->h};
  1303. +   SDL_RenderCopy(this->renderer, tex, nullptr, &sdl_rect);
  1304.  
  1305. +   SDL_DestroyTexture(tex);
  1306.     SDL_FreeSurface(surf);
  1307.  }
  1308.  
  1309. @@ -834,51 +506,8 @@ void VideoSystem::BlitText(const uint8 *text, uint32 colour, int xpos, int ypos,
  1310.   */
  1311.  void VideoSystem::DrawLine(const Point16 &start, const Point16 &end, uint32 colour)
  1312.  {
  1313. -   int16 dx, inc_x, dy, inc_y;
  1314. -   if (start.x > end.x) {
  1315. -       dx = start.x - end.x;
  1316. -       inc_x = -1;
  1317. -   } else {
  1318. -       dx = end.x - start.x;
  1319. -       inc_x = 1;
  1320. -   }
  1321. -   if (start.y > end.y) {
  1322. -       dy = start.y - end.y;
  1323. -       inc_y = -1;
  1324. -   } else {
  1325. -       dy = end.y - start.y;
  1326. -       inc_y = 1;
  1327. -   }
  1328. -
  1329. -   int16 step = std::min(dx, dy);
  1330. -   int16 pos_x = start.x;
  1331. -   int16 pos_y = start.y;
  1332. -   int16 sum_x = 0;
  1333. -   int16 sum_y = 0;
  1334. -
  1335. -   this->blit_rect.ValidateAddress();
  1336. -   uint32 *dest = this->blit_rect.address + pos_x + pos_y * this->blit_rect.pitch;
  1337. -
  1338. -   for (;;) {
  1339. -       /* Blit pixel. */
  1340. -       if (pos_x >= 0 && pos_x < this->blit_rect.width && pos_y >= 0 && pos_y < this->blit_rect.height) {
  1341. -           *dest = colour;
  1342. -       }
  1343. -       if (pos_x == end.x && pos_y == end.y) break;
  1344. -
  1345. -       sum_x += step;
  1346. -       sum_y += step;
  1347. -       if (sum_x >= dy) {
  1348. -           pos_x += inc_x;
  1349. -           dest += inc_x;
  1350. -           sum_x -= dy;
  1351. -       }
  1352. -       if (sum_y >= dx) {
  1353. -           pos_y += inc_y;
  1354. -           dest += inc_y * this->blit_rect.pitch;
  1355. -           sum_y -= dx;
  1356. -       }
  1357. -   }
  1358. +   SDL_SetRenderDrawColor(this->renderer, SPLIT_RGBA(colour));
  1359. +   SDL_RenderDrawLine(this->renderer, start.x, start.y, end.x, end.y);
  1360.  }
  1361.  
  1362.  /**
  1363. @@ -888,14 +517,9 @@ void VideoSystem::DrawLine(const Point16 &start, const Point16 &end, uint32 colo
  1364.   */
  1365.  void VideoSystem::DrawRectangle(const Rectangle32 &rect, uint32 colour)
  1366.  {
  1367. -   Point16 top_left    (static_cast<int16>(rect.base.x),                  static_cast<int16>(rect.base.y));
  1368. -   Point16 top_right   (static_cast<int16>(rect.base.x + rect.width - 1), static_cast<int16>(rect.base.y));
  1369. -   Point16 bottom_left (static_cast<int16>(rect.base.x),                  static_cast<int16>(rect.base.y + rect.height - 1));
  1370. -   Point16 bottom_right(static_cast<int16>(rect.base.x + rect.width - 1), static_cast<int16>(rect.base.y + rect.height - 1));
  1371. -   this->DrawLine(top_left, top_right, colour);
  1372. -   this->DrawLine(top_left, bottom_left, colour);
  1373. -   this->DrawLine(top_right, bottom_right, colour);
  1374. -   this->DrawLine(bottom_left, bottom_right, colour);
  1375. +   SDL_Rect sdl_rect = RectToSDLRect(rect);
  1376. +   SDL_SetRenderDrawColor(this->renderer, SPLIT_RGBA(colour));
  1377. +   SDL_RenderDrawRect(this->renderer, &sdl_rect);
  1378.  }
  1379.  
  1380.  /**
  1381. @@ -905,22 +529,7 @@ void VideoSystem::DrawRectangle(const Rectangle32 &rect, uint32 colour)
  1382.   */
  1383.  void VideoSystem::FillRectangle(const Rectangle32 &rect, uint32 colour)
  1384.  {
  1385. -   ClippedRectangle cr = this->GetClippedRectangle();
  1386. -
  1387. -   int x = Clamp((int)rect.base.x, 0, (int)cr.width);
  1388. -   int w = Clamp((int)(rect.base.x + rect.width), 0, (int)cr.width);
  1389. -   int y = Clamp((int)rect.base.y, 0, (int)cr.height);
  1390. -   int h = Clamp((int)(rect.base.y + rect.height), 0, (int)cr.height);
  1391. -
  1392. -   w -= x;
  1393. -   h -= y;
  1394. -   if (w == 0 || h == 0) return;
  1395. -
  1396. -   uint32 *pixels_base = cr.address + x + y * cr.pitch;
  1397. -   while (h > 0) {
  1398. -       uint32 *pixels = pixels_base;
  1399. -       for (int i = 0; i < w; i++) *pixels++ = colour;
  1400. -       pixels_base += cr.pitch;
  1401. -       h--;
  1402. -   }
  1403. +   SDL_Rect sdl_rect = RectToSDLRect(rect);
  1404. +   SDL_SetRenderDrawColor(this->renderer, SPLIT_RGBA(colour));
  1405. +   SDL_RenderFillRect(this->renderer, &sdl_rect);
  1406.  }
  1407. diff --git a/src/video.h b/src/video.h
  1408. index 9c9c7ba..d3cfd22 100644
  1409. --- a/src/video.h
  1410. +++ b/src/video.h
  1411. @@ -22,27 +22,6 @@ void QuitProgram();
  1412.  
  1413.  class ImageData;
  1414.  
  1415. -/** Clipped rectangle. */
  1416. -class ClippedRectangle {
  1417. -public:
  1418. -   ClippedRectangle();
  1419. -   ClippedRectangle(uint16 x, uint16 y, uint16 w, uint16 h);
  1420. -   ClippedRectangle(const ClippedRectangle &cr, uint16 x, uint16 y, uint16 w, uint16 h);
  1421. -
  1422. -   ClippedRectangle(const ClippedRectangle &cr);
  1423. -   ClippedRectangle &operator=(const ClippedRectangle &cr);
  1424. -
  1425. -   void ValidateAddress();
  1426. -
  1427. -   uint16 absx;     ///< Absolute X position in the screen of the top-left.
  1428. -   uint16 absy;     ///< Absolute Y position in the screen of the top-left.
  1429. -   uint16 width;    ///< Number of columns.
  1430. -   uint16 height;   ///< Number of rows.
  1431. -
  1432. -   uint32 *address; ///< Base address. @note Call #ValidateAddress prior to use.
  1433. -   int32 pitch;     ///< Pitch of a row in bytes. @note Call #ValidateAddress prior to use.
  1434. -};
  1435. -
  1436.  /** How to align text during drawing. */
  1437.  enum Alignment {
  1438.     ALG_LEFT,   ///< Align to the left edge.
  1439. @@ -54,19 +33,26 @@ enum Alignment {
  1440.   * Class representing the video system.
  1441.   */
  1442.  class VideoSystem {
  1443. -   friend class ClippedRectangle;
  1444. -
  1445.  public:
  1446.     VideoSystem();
  1447.     ~VideoSystem();
  1448.  
  1449.     std::string Initialize(const char *font_name, int font_size);
  1450.     bool SetResolution(const Point32 &res);
  1451. -   void GetResolutions();
  1452.     void MainLoop();
  1453.     void Shutdown();
  1454.  
  1455.     /**
  1456. +    * Should only ever be used externally for creating SDL_Textures
  1457. +    * @return The renderer instance.
  1458. +    */
  1459. +   inline SDL_Renderer *GetRenderer()
  1460. +   {
  1461. +       assert(this->initialized);
  1462. +       return this->renderer;
  1463. +   }
  1464. +
  1465. +   /**
  1466.      * Get horizontal size of the screen.
  1467.      * @return Number of pixels of the screen horizontally.
  1468.      */
  1469. @@ -98,8 +84,16 @@ public:
  1470.     void MarkDisplayDirty();
  1471.     void MarkDisplayDirty(const Rectangle32 &rect);
  1472.  
  1473. -   void SetClippedRectangle(const ClippedRectangle &cr);
  1474. -   ClippedRectangle GetClippedRectangle();
  1475. +   /**
  1476. +    * Blit a single sprite.
  1477. +    * @param img_base Coordinates of the sprite data (relative to window).
  1478. +    * @param spr Sprite to blit.
  1479. +    * @param recolour Sprite recolouring definition.
  1480. +    */
  1481. +   inline void BlitImage(const Point32 &img_base, const ImageData *spr, const Recolouring &recolour)
  1482. +   {
  1483. +       this->BlitImages(img_base, spr, 1, 1, recolour);
  1484. +   }
  1485.  
  1486.     /**
  1487.      * Blit a row of sprites.
  1488. @@ -127,8 +121,7 @@ public:
  1489.         this->BlitImages({x, ymin}, spr, 1, numy, recolour);
  1490.     }
  1491.  
  1492. -   void BlitImage(const Point32 &img_base, const ImageData *spr, const Recolouring &recolour, GradientShift shift);
  1493. -   void BlitImages(const Point32 &pt, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour, GradientShift shift = GS_NORMAL);
  1494. +   void BlitImages(const Point32 &pt, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour);
  1495.  
  1496.     void FinishRepaint();
  1497.  
  1498. @@ -141,6 +134,9 @@ public:
  1499.         return this->font_height;
  1500.     }
  1501.  
  1502. +   void SetClippedRectangle(const Rectangle32 &rect);
  1503. +   Rectangle32 GetClippedRectangle();
  1504. +
  1505.     void GetTextSize(const uint8 *text, int *width, int *height);
  1506.     void GetNumberRangeSize(int64 smallest, int64 biggest, int *width, int *height);
  1507.     void BlitText(const uint8 *text, uint32 colour, int xpos, int ypos, int width = 0x7FFF, Alignment align = ALG_LEFT);
  1508. @@ -162,12 +158,20 @@ private:
  1509.     SDL_Window *window;         ///< %Window of the application.
  1510.     SDL_Renderer *renderer;     ///< GPU renderer to the application window.
  1511.     SDL_Texture *texture;       ///< GPU Texture storage of the application window.
  1512. -   uint32 *mem;                ///< Memory used for blitting the application display.
  1513. -   ClippedRectangle blit_rect; ///< %Rectangle to blit in.
  1514. +   Rectangle32 blit_rect;
  1515.     Point16 digit_size;         ///< Size of largest digit (initially a zero-size).
  1516.  
  1517. +   void GetResolutions();
  1518.     bool HandleEvent();
  1519.     void MarkDisplayClean();
  1520. +
  1521. +   template<class PZ, class SZ>
  1522. +   SDL_Rect RectToSDLRect(const Rectangle<PZ, SZ> &rect)
  1523. +   {
  1524. +       SDL_Rect sdl_rect = {static_cast<int>(rect.base.x), static_cast<int>(rect.base.y),
  1525. +                            static_cast<int>(rect.width),  static_cast<int>(rect.height)};
  1526. +       return sdl_rect;
  1527. +   }
  1528.  };
  1529.  
  1530.  extern VideoSystem _video;
  1531. diff --git a/src/viewport.cpp b/src/viewport.cpp
  1532. index 418b901..3a919a6 100644
  1533. --- a/src/viewport.cpp
  1534. +++ b/src/viewport.cpp
  1535. @@ -1404,21 +1404,15 @@ void Viewport::OnDraw()
  1536.     collector.Collect(this->additions_enabled && this->additions_displayed);
  1537.     static const Recolouring recolour;
  1538.  
  1539. -   _video.FillRectangle(this->rect, MakeRGBA(0, 0, 0, OPAQUE)); // Black background.
  1540. -
  1541. -   ClippedRectangle cr = _video.GetClippedRectangle();
  1542. -   assert(this->rect.base.x >= 0 && this->rect.base.y >= 0);
  1543. -   ClippedRectangle draw_rect(cr, this->rect.base.x, this->rect.base.y, this->rect.width, this->rect.height);
  1544. -   _video.SetClippedRectangle(draw_rect);
  1545. -
  1546. -   GradientShift gs = static_cast<GradientShift>(GS_LIGHT - _weather.GetWeatherType());
  1547.     for (const auto &iter : collector.draw_images) {
  1548.         const DrawData &dd = iter;
  1549.         const Recolouring &rec = (dd.recolour == nullptr) ? recolour : *dd.recolour;
  1550. -       _video.BlitImage(dd.base, dd.sprite, rec, gs);
  1551. +       _video.BlitImage(dd.base, dd.sprite, rec);
  1552.     }
  1553.  
  1554. -   _video.SetClippedRectangle(cr);
  1555. +   //GradientShift gs = static_cast<GradientShift>(GS_LIGHT - _weather.GetWeatherType());
  1556. +   /// \todo Actually change brightness overlay depending on weather
  1557. +   //_video.FillRectangle(this->rect, MakeRGBA(0, 0, 0, 0));
  1558.  }
  1559.  
  1560.  /**
  1561. diff --git a/src/widget.cpp b/src/widget.cpp
  1562. index 376677e..619ae9f 100644
  1563. --- a/src/widget.cpp
  1564. +++ b/src/widget.cpp
  1565. @@ -292,7 +292,7 @@ void LeafWidget::Draw(const GuiWindow *w)
  1566.         } else if ((this->flags & LWF_PRESSED) != 0) {
  1567.             spr_num += WCS_EMPTY_PRESSED;
  1568.         }
  1569. -       _video.BlitImage({left, top}, _gui_sprites.radio_button.sprites[spr_num], rc, GS_NORMAL);
  1570. +       _video.BlitImage({left, top}, _gui_sprites.radio_button.sprites[spr_num], rc);
  1571.         return;
  1572.     }
  1573.  
  1574. @@ -319,7 +319,7 @@ void LeafWidget::Draw(const GuiWindow *w)
  1575.         int yoffset = top + (bottom - 1 - top - _gui_sprites.close_sprite->height) / 2;
  1576.  
  1577.         const ImageData *imgdata = _gui_sprites.close_sprite;
  1578. -       if (imgdata != nullptr) _video.BlitImage({xoffset + 1, yoffset + 1}, imgdata, rc, GS_NORMAL);
  1579. +       if (imgdata != nullptr) _video.BlitImage({xoffset + 1, yoffset + 1}, imgdata, rc);
  1580.         /* Closebox is never shaded. */
  1581.     }
  1582.  }
  1583. @@ -500,7 +500,7 @@ void DataWidget::Draw(const GuiWindow *w)
  1584.             int xoffset = left + (right + 1 - left - this->value_width) / 2 - rect.base.x;
  1585.             yoffset -= rect.base.y;
  1586.             const ImageData *imgdata = _sprite_manager.GetTableSprite(this->value);
  1587. -           if (imgdata != nullptr) _video.BlitImage({xoffset + pressed, yoffset + pressed}, imgdata, rc, GS_NORMAL);
  1588. +           if (imgdata != nullptr) _video.BlitImage({xoffset + pressed, yoffset + pressed}, imgdata, rc);
  1589.             break;
  1590.         }
  1591.  
  1592. @@ -513,7 +513,7 @@ void DataWidget::Draw(const GuiWindow *w)
  1593.  
  1594.             if (imgdata != nullptr) {
  1595.                 int triangle_yoff = top + (bottom + 1 - top - imgrect.height) / 2 + pressed;
  1596. -               _video.BlitImage({right - imgrect.width + pressed, triangle_yoff}, imgdata, rc, GS_NORMAL);
  1597. +               _video.BlitImage({right - imgrect.width + pressed, triangle_yoff}, imgdata, rc);
  1598.             }
  1599.             /* Note: Reusing the same string parameters from above */
  1600.             if (this->value != STR_NULL) DrawString(w->TranslateStringNumber(this->value), TEXT_WHITE, left + pressed, yoffset + pressed, right - left - imgrect.width, align);
  1601. @@ -589,12 +589,12 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1602.     Point32 pos(w->GetWidgetScreenX(this), w->GetWidgetScreenY(this));
  1603.  
  1604.     /* Draw left/up button. */
  1605. -   _video.BlitImage(pos, imd[WLS_LEFT_BUTTON], rc, GS_NORMAL);
  1606. +   _video.BlitImage(pos, imd[WLS_LEFT_BUTTON], rc);
  1607.     if (this->wtype == WT_HOR_SCROLLBAR) pos.x += imd[WLS_LEFT_BUTTON]->width;
  1608.     if (this->wtype != WT_HOR_SCROLLBAR) pos.y += imd[WLS_LEFT_BUTTON]->height;
  1609.  
  1610.     /* Draw top/left underground. */
  1611. -   _video.BlitImage(pos, imd[WLS_LEFT_BED], rc, GS_NORMAL);
  1612. +   _video.BlitImage(pos, imd[WLS_LEFT_BED], rc);
  1613.     if (this->wtype == WT_HOR_SCROLLBAR) pos.x += imd[WLS_LEFT_BED]->width;
  1614.     if (this->wtype != WT_HOR_SCROLLBAR) pos.y += imd[WLS_LEFT_BED]->height;
  1615.  
  1616. @@ -614,7 +614,7 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1617.     }
  1618.  
  1619.     /* Draw bottom/right underground. */
  1620. -   _video.BlitImage(pos, imd[WLS_RIGHT_BED], rc, GS_NORMAL);
  1621. +   _video.BlitImage(pos, imd[WLS_RIGHT_BED], rc);
  1622.     if (this->wtype == WT_HOR_SCROLLBAR) {
  1623.         pos.x += imd[WLS_RIGHT_BED]->width;
  1624.     } else {
  1625. @@ -622,7 +622,7 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1626.     }
  1627.  
  1628.     /* Draw right/bottom button. */
  1629. -   _video.BlitImage(pos, imd[WLS_RIGHT_BUTTON], rc, GS_NORMAL);
  1630. +   _video.BlitImage(pos, imd[WLS_RIGHT_BUTTON], rc);
  1631.  
  1632.     int start_edge, slider_length;
  1633.     this->CalculateSliderPosition(&start_edge, &slider_length);
  1634. @@ -634,7 +634,7 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1635.     }
  1636.  
  1637.     /* Draw top/left slider. */
  1638. -   _video.BlitImage(pos, imd[WLS_LEFT_SLIDER], rc, GS_NORMAL);
  1639. +   _video.BlitImage(pos, imd[WLS_LEFT_SLIDER], rc);
  1640.     if (this->wtype == WT_HOR_SCROLLBAR) {
  1641.         pos.x += imd[WLS_LEFT_SLIDER]->width;
  1642.     } else {
  1643. @@ -653,7 +653,7 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1644.     }
  1645.  
  1646.     /* Draw bottom/right slider. */
  1647. -   _video.BlitImage(pos, imd[WLS_RIGHT_SLIDER], rc, GS_NORMAL);
  1648. +   _video.BlitImage(pos, imd[WLS_RIGHT_SLIDER], rc);
  1649.  }
  1650.  
  1651.  /**
  1652. diff --git a/src/window.cpp b/src/window.cpp
  1653. index 641e9a4..9aa534e 100644
  1654. --- a/src/window.cpp
  1655. +++ b/src/window.cpp
  1656. @@ -989,8 +989,8 @@ void UpdateWindows()
  1657.     /* Until the entire background is covered by the main display, clean the entire display to ensure deleted
  1658.      * windows truly disappear (even if there is no other window behind it).
  1659.      */
  1660. -   Rectangle32 rect(0, 0, _video.GetXSize(), _video.GetYSize());
  1661. -   _video.FillRectangle(rect, MakeRGBA(0, 0, 0, OPAQUE));
  1662. +// Rectangle32 rect(0, 0, _video.GetXSize(), _video.GetYSize());
  1663. +// _video.FillRectangle(rect, MakeRGBA(0, 0, 0, OPAQUE));
  1664.  
  1665.     Window *w = _manager.bottom;
  1666.     while (w != nullptr) {
  1667.  

Comments