Loading

Paste #pkx703zlv

  1. diff --git a/src/dropdown.cpp b/src/dropdown.cpp
  2. index 8298f2d..c23a66c 100644
  3. --- a/src/dropdown.cpp
  4. +++ b/src/dropdown.cpp
  5. @@ -108,7 +108,7 @@ void DropdownMenuWindow::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid)
  6.     for (auto const &item : this->items) {
  7.         if (it == this->selected_index) {
  8.             Rectangle32 r = {this->rect.base.x, y, static_cast<uint>(wid->pos.width - 1), static_cast<uint>(GetTextHeight())};
  9. -           _video.FillSurface(_palette[GetColourRangeBase(COL_RANGE_GREY) + 7], r);
  10. +           _video.FillSurface(r, _palette[GetColourRangeBase(COL_RANGE_GREY) + 7]);
  11.         }
  12.         _video.BlitText(item.str, MakeRGBA(255, 255, 255, OPAQUE), this->rect.base.x, y, wid->pos.width);
  13.  
  14. diff --git a/src/fence_gui.cpp b/src/fence_gui.cpp
  15. index 7532717..fbc9718 100644
  16. --- a/src/fence_gui.cpp
  17. +++ b/src/fence_gui.cpp
  18. @@ -115,7 +115,7 @@ void FenceGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) const
  19.                 lines--;
  20.  
  21.                 Recolouring recolouring;
  22. -               _video.BlitImage(rect.x, rect.y - sprite->yoffset, sprite, recolouring, GS_NORMAL);
  23. +               _video.BlitImage({rect.x, rect.y - sprite->yoffset}, sprite, recolouring);
  24.                 rect.y += sprite->height;
  25.             }
  26.             break;
  27. diff --git a/src/gui_graphics.cpp b/src/gui_graphics.cpp
  28. index c0528dc..a583266 100644
  29. --- a/src/gui_graphics.cpp
  30. +++ b/src/gui_graphics.cpp
  31. @@ -30,12 +30,12 @@ void DrawBorderSprites(const BorderSpriteData &bsd, bool pressed, const Rectangl
  32.     rc.Set(0, RecolourEntry(COL_RANGE_BROWN, colour));
  33.  
  34.     Point32 pt = rect.base;
  35. -   _video.BlitImage(pt, spr_base[WBS_TOP_LEFT], rc, GS_NORMAL);
  36. +   _video.BlitImage(pt, spr_base[WBS_TOP_LEFT], rc);
  37.     int xleft = pt.x + spr_base[WBS_TOP_LEFT]->xoffset + spr_base[WBS_TOP_LEFT]->width;
  38.     int ytop = pt.y + spr_base[WBS_TOP_LEFT]->yoffset + spr_base[WBS_TOP_LEFT]->height;
  39.  
  40.     pt.x = rect.base.x + rect.width - 1;
  41. -   _video.BlitImage(pt, spr_base[WBS_TOP_RIGHT], rc, GS_NORMAL);
  42. +   _video.BlitImage(pt, spr_base[WBS_TOP_RIGHT], rc);
  43.     int xright = pt.x + spr_base[WBS_TOP_RIGHT]->xoffset;
  44.  
  45.     uint16 numx = (xright - xleft) / spr_base[WBS_TOP_MIDDLE]->width;
  46. @@ -43,7 +43,7 @@ void DrawBorderSprites(const BorderSpriteData &bsd, bool pressed, const Rectangl
  47.  
  48.     pt.x = rect.base.x;
  49.     pt.y = rect.base.y + rect.height - 1;
  50. -   _video.BlitImage(pt, spr_base[WBS_BOTTOM_LEFT], rc, GS_NORMAL);
  51. +   _video.BlitImage(pt, spr_base[WBS_BOTTOM_LEFT], rc);
  52.     int ybot = pt.y + spr_base[WBS_BOTTOM_LEFT]->yoffset;
  53.  
  54.     uint16 numy = (ybot - ytop) / spr_base[WBS_MIDDLE_LEFT]->height;
  55. @@ -51,14 +51,15 @@ void DrawBorderSprites(const BorderSpriteData &bsd, bool pressed, const Rectangl
  56.  
  57.     pt.x = rect.base.x + rect.width - 1;
  58.     pt.y = rect.base.y + rect.height - 1;
  59. -   _video.BlitImage(pt, spr_base[WBS_BOTTOM_RIGHT], rc, GS_NORMAL);
  60. +   _video.BlitImage(pt, spr_base[WBS_BOTTOM_RIGHT], rc);
  61.  
  62.     _video.BlitHorizontal(xleft, numx, pt.y, spr_base[WBS_BOTTOM_MIDDLE], rc);
  63.  
  64.     pt.x = rect.base.x + rect.width - 1;
  65.     _video.BlitVertical(ytop, numy, pt.x, spr_base[WBS_MIDDLE_RIGHT], rc);
  66.  
  67. -   _video.BlitImages(xleft, ytop, spr_base[WBS_MIDDLE_MIDDLE], numx, numy, rc);
  68. +   Rectangle32 inner_rect(xleft, ytop, numx, numy);
  69. +   _video.FillSurface(inner_rect, rc.GetPalette(GS_NORMAL)[7]);
  70.  }
  71.  
  72.  /**
  73. @@ -75,21 +76,14 @@ void OverlayShaded(const Rectangle32 &rect)
  74.     r.RestrictTo(0, 0, _video.GetXSize(), _video.GetYSize());
  75.     if (r.width == 0 || r.height == 0) return;
  76.  
  77. -   /* Set clipped area to the rectangle. */
  78. -   ClippedRectangle cr(_video.GetClippedRectangle());
  79. -   ClippedRectangle new_cr(cr, r.base.x, r.base.y, r.width, r.height);
  80. -   _video.SetClippedRectangle(new_cr);
  81. -
  82.     /* Align the disabled sprite so it becomes a continuous pattern. */
  83. -   int32 base_x = -(r.base.x % img->width);
  84. -   int32 base_y = -(r.base.y % img->height);
  85. +   int32 base_x = r.base.x - (r.base.x % img->width);
  86. +   int32 base_y = r.base.y - (r.base.y % img->height);
  87.     uint16 numx = (r.width + img->width - 1) / img->width;
  88.     uint16 numy = (r.height + img->height - 1) / img->height;
  89.  
  90.     static const Recolouring recolour; // Fixed recolouring mapping.
  91. -   _video.BlitImages(base_x, base_y, img, numx, numy, recolour);
  92. -
  93. -   _video.SetClippedRectangle(cr); // Restore clipped area.
  94. +   _video.BlitImages({base_x, base_y}, img, numx, numy, recolour);
  95.  }
  96.  
  97.  /**
  98. @@ -109,10 +103,11 @@ void DrawString(StringID strid, uint8 colour, int x, int y, int width, Alignment
  99.     DrawText(strid, buffer, lengthof(buffer));
  100.     /** \todo Reduce the naiviness of this. */
  101.     if (outline) {
  102. -       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x + 1, y, width, align);
  103. -       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x, y + 1, width, align);
  104. -       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x - 1, y, width, align);
  105. -       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x, y - 1, width, align);
  106. +//     _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x + 1, y, width, align);
  107. +//     _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x, y + 1, width, align);
  108. +//     _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x - 1, y, width, align);
  109. +//     _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x, y - 1, width, align);
  110. +       _video.BlitText(buffer, MakeRGBA(0, 0, 0, OPAQUE), x + 1, y + 1, width, align);
  111.     }
  112.     _video.BlitText(buffer, _palette[colour], x, y, width, align);
  113.  }
  114. diff --git a/src/palette.h b/src/palette.h
  115. index 1e98317..fdc5122 100644
  116. --- a/src/palette.h
  117. +++ b/src/palette.h
  118. @@ -86,6 +86,8 @@ static inline uint32 SetA(uint32 rgba, uint8 opacity)
  119.     return rgba | opacity;
  120.  }
  121.  
  122. +#define SPLIT_RGBA(rgba) GetR(rgba), GetG(rgba), GetB(rgba), GetA(rgba)
  123. +
  124.  /** Names of colour ranges. */
  125.  enum ColourRange {
  126.     COL_RANGE_GREY,
  127. diff --git a/src/path_gui.cpp b/src/path_gui.cpp
  128. index cd808b0..d5beca9 100644
  129. --- a/src/path_gui.cpp
  130. +++ b/src/path_gui.cpp
  131. @@ -225,7 +225,8 @@ void PathBuildGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) const
  132.                 if (img != nullptr) {
  133.                     int dx = (wid->pos.width - path_type_button_size.width) / 2;
  134.                     int dy = (wid->pos.height - path_type_button_size.height) / 2;
  135. -                   _video.BlitImage(GetWidgetScreenX(wid) + dx - path_type_button_size.base.x, GetWidgetScreenY(wid) + dy - path_type_button_size.base.y, img, recolour, GS_NORMAL);
  136. +                   Point32 pt(GetWidgetScreenX(wid) + dx - path_type_button_size.base.x, GetWidgetScreenY(wid) + dy - path_type_button_size.base.y);
  137. +                   _video.BlitImage(pt, img, recolour);
  138.                 }
  139.             }
  140.             break;
  141. @@ -239,7 +240,8 @@ void PathBuildGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) const
  142.                 if (img != nullptr) {
  143.                     int dx = (wid->pos.width - path_type_button_size.width) / 2;
  144.                     int dy = (wid->pos.height - path_type_button_size.height) / 2;
  145. -                   _video.BlitImage(GetWidgetScreenX(wid) + dx - path_type_button_size.base.x, GetWidgetScreenY(wid) + dy - path_type_button_size.base.y, img, recolour, GS_NORMAL);
  146. +                   Point32 pt(GetWidgetScreenX(wid) + dx - path_type_button_size.base.x, GetWidgetScreenY(wid) + dy - path_type_button_size.base.y);
  147. +                   _video.BlitImage(pt, img, recolour);
  148.                 }
  149.             }
  150.             break;
  151. diff --git a/src/ride_gui.cpp b/src/ride_gui.cpp
  152. index cfa2795..0ea21b1 100644
  153. --- a/src/ride_gui.cpp
  154. +++ b/src/ride_gui.cpp
  155. @@ -221,9 +221,8 @@ void RideSelectGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) cons
  156.                 /* Display the selected shop in the ride select window. */
  157.                 if (ride_type != nullptr && ride_type->kind == RTK_SHOP) {
  158.                     static const Recolouring recolour; // Never modified, display 'original' image in the GUI.
  159. -                   _video.BlitImage(this->GetWidgetScreenX(wid) + wid->pos.width / 2,
  160. -                           this->GetWidgetScreenY(wid) + 40, ride_type->GetView(_shop_placer.orientation),
  161. -                           recolour, GS_NORMAL);
  162. +                   Point32 pt(this->GetWidgetScreenX(wid) + wid->pos.width / 2, this->GetWidgetScreenY(wid) + 40);
  163. +                   _video.BlitImage(pt, ride_type->GetView(_shop_placer.orientation), recolour);
  164.                 }
  165.             }
  166.             break;
  167. diff --git a/src/sprite_data.cpp b/src/sprite_data.cpp
  168. index 28b3ce0..5fd4389 100644
  169. --- a/src/sprite_data.cpp
  170. +++ b/src/sprite_data.cpp
  171. @@ -27,6 +27,7 @@ ImageData::ImageData()
  172.     this->height = 0;
  173.     this->table = nullptr;
  174.     this->data = nullptr;
  175. +   this->image = nullptr;
  176.  }
  177.  
  178.  ImageData::~ImageData()
  179. diff --git a/src/sprite_data.h b/src/sprite_data.h
  180. index 049990c..5987aa2 100644
  181. --- a/src/sprite_data.h
  182. +++ b/src/sprite_data.h
  183. @@ -12,6 +12,8 @@
  184.  #ifndef SPRITE_DATA_H
  185.  #define SPRITE_DATA_H
  186.  
  187. +#include <SDL.h>
  188. +
  189.  static const uint32 INVALID_JUMP = UINT32_MAX; ///< Invalid jump destination in image data.
  190.  
  191.  class RcdFileReader;
  192. @@ -42,6 +44,8 @@ public:
  193.     int16 yoffset; ///< Vertical offset of the image.
  194.     uint32 *table; ///< The jump table. For missing entries, #INVALID_JUMP is used.
  195.     uint8 *data;   ///< The image data itself.
  196. +
  197. +   mutable SDL_Texture *image;
  198.  };
  199.  
  200.  ImageData *LoadImage(RcdFileReader *rcd_file);
  201. diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp
  202. index dbf13a5..5cd5eaf 100644
  203. --- a/src/terraform_gui.cpp
  204. +++ b/src/terraform_gui.cpp
  205. @@ -103,7 +103,7 @@ void TerraformGui::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid) const
  206.  
  207.         base.x = this->GetWidgetScreenX(wid) + (wid->pos.width - dot->width) / 2;
  208.         base.y = this->GetWidgetScreenY(wid) + (wid->pos.height - dot->height) / 2;
  209. -       _video.BlitImage(base, dot, recolour, GS_NORMAL);
  210. +       _video.BlitImage(base, dot, recolour);
  211.         return;
  212.     }
  213.  
  214. diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp
  215. index 590e9f8..51f49ae 100644
  216. --- a/src/toolbar_gui.cpp
  217. +++ b/src/toolbar_gui.cpp
  218. @@ -368,14 +368,14 @@ void BottomToolbarWindow::DrawWidget(WidgetNumber wid_num, const BaseWidget *wid
  219.             Viewport *vp = GetViewport();
  220.             int dir = (vp == nullptr) ? 0 : vp->orientation;
  221.             const ImageData *img = _sprite_manager.GetTableSprite(SPR_GUI_COMPASS_START + dir);
  222. -           if (img != nullptr) _video.BlitImage(GetWidgetScreenX(wid), GetWidgetScreenY(wid), img, recolour, GS_NORMAL);
  223. +           if (img != nullptr) _video.BlitImage({GetWidgetScreenX(wid), GetWidgetScreenY(wid)}, img, recolour);
  224.             break;
  225.         }
  226.  
  227.         case BTB_WEATHER: {
  228.             int spr = SPR_GUI_WEATHER_START + _weather.GetWeatherType();
  229.             const ImageData *img = _sprite_manager.GetTableSprite(spr);
  230. -           if (img != nullptr) _video.BlitImage(GetWidgetScreenX(wid), GetWidgetScreenY(wid), img, recolour, GS_NORMAL);
  231. +           if (img != nullptr) _video.BlitImage({GetWidgetScreenX(wid), GetWidgetScreenY(wid)}, img, recolour);
  232.             break;
  233.         }
  234.     }
  235. diff --git a/src/video.cpp b/src/video.cpp
  236. index 748e120..204ef44 100644
  237. --- a/src/video.cpp
  238. +++ b/src/video.cpp
  239. @@ -31,100 +31,6 @@ void QuitProgram()
  240.     _finish = true;
  241.  }
  242.  
  243. -/** Default constructor of a clipped rectangle. */
  244. -ClippedRectangle::ClippedRectangle()
  245. -{
  246. -   this->absx = 0;
  247. -   this->absy = 0;
  248. -   this->width = 0;
  249. -   this->height = 0;
  250. -   this->address = nullptr; this->pitch = 0;
  251. -}
  252. -
  253. -/**
  254. - * Construct a clipped rectangle from coordinates.
  255. - * @param x Top-left x position.
  256. - * @param y Top-left y position.
  257. - * @param w Width.
  258. - * @param h Height.
  259. - */
  260. -ClippedRectangle::ClippedRectangle(uint16 x, uint16 y, uint16 w, uint16 h)
  261. -{
  262. -   this->absx = x;
  263. -   this->absy = y;
  264. -   this->width = w;
  265. -   this->height = h;
  266. -   this->address = nullptr; this->pitch = 0;
  267. -}
  268. -
  269. -/**
  270. - * Construct a clipped rectangle inside an existing one.
  271. - * @param cr Existing rectangle.
  272. - * @param x Top-left x position.
  273. - * @param y Top-left y position.
  274. - * @param w Width.
  275. - * @param h Height.
  276. - * @note %Rectangle is clipped to the old one.
  277. - */
  278. -ClippedRectangle::ClippedRectangle(const ClippedRectangle &cr, uint16 x, uint16 y, uint16 w, uint16 h)
  279. -{
  280. -   if (x >= cr.width || y >= cr.height) {
  281. -       this->absx = 0;
  282. -       this->absy = 0;
  283. -       this->width = 0;
  284. -       this->height = 0;
  285. -       this->address = nullptr; this->pitch = 0;
  286. -       return;
  287. -   }
  288. -   if (x + w > cr.width)  w = cr.width - x;
  289. -   if (y + h > cr.height) h = cr.height - y;
  290. -
  291. -   this->absx = cr.absx + x;
  292. -   this->absy = cr.absy + y;
  293. -   this->width = w;
  294. -   this->height = h;
  295. -   this->address = nullptr; this->pitch = 0;
  296. -}
  297. -
  298. -/**
  299. - * Copy constructor.
  300. - * @param cr Existing clipped rectangle.
  301. - */
  302. -ClippedRectangle::ClippedRectangle(const ClippedRectangle &cr)
  303. -{
  304. -   this->absx = cr.absx;
  305. -   this->absy = cr.absy;
  306. -   this->width = cr.width;
  307. -   this->height = cr.height;
  308. -   this->address = cr.address; this->pitch = cr.pitch;
  309. -}
  310. -
  311. -/**
  312. - * Assignment operator override.
  313. - * @param cr Existing clipped rectangle.
  314. - * @return The assigned value.
  315. - */
  316. -ClippedRectangle &ClippedRectangle::operator=(const ClippedRectangle &cr)
  317. -{
  318. -   if (this != &cr) {
  319. -       this->absx = cr.absx;
  320. -       this->absy = cr.absy;
  321. -       this->width = cr.width;
  322. -       this->height = cr.height;
  323. -       this->address = cr.address; this->pitch = cr.pitch;
  324. -   }
  325. -   return *this;
  326. -}
  327. -
  328. -/** Initialize the #address if not done already. */
  329. -void ClippedRectangle::ValidateAddress()
  330. -{
  331. -   if (this->address == nullptr) {
  332. -       this->pitch = _video.GetXSize();
  333. -       this->address = _video.mem + this->absx + this->absy * this->pitch;
  334. -   }
  335. -}
  336. -
  337.  /**
  338.   * Default constructor, does nothing, never goes wrong.
  339.   * Call #Initialize to initialize the system.
  340. @@ -165,9 +71,18 @@ std::string VideoSystem::Initialize(const char *font_name, int font_size)
  341.         return err;
  342.     }
  343.  
  344. +   this->renderer = SDL_CreateRenderer(this->window, -1, 0);
  345. +   if (this->renderer == nullptr) {
  346. +       std::string err = "Could not create renderer: ";
  347. +       err += SDL_GetError();
  348. +       SDL_Quit();
  349. +       return err;
  350. +   }
  351. +   SDL_SetRenderDrawBlendMode(this->renderer, SDL_BLENDMODE_BLEND);
  352. +
  353.     this->GetResolutions();
  354.  
  355. -   this->SetResolution({800, 600}); // Allocates this->mem, return value is ignored.
  356. +   this->SetResolution({800, 600}); // return value is ignored.
  357.  
  358.     /* SDL_CreateRGBSurfaceFrom() pretends to use a void* for the data,
  359.      * but it's really treated as endian-specific uint32*.
  360. @@ -183,12 +98,11 @@ std::string VideoSystem::Initialize(const char *font_name, int font_size)
  361.         SDL_SetWindowIcon(this->window, icon);
  362.         SDL_FreeSurface(icon);
  363.     } else {
  364. -       printf("Could not set window icon (%s)\n", SDL_GetError());
  365. +       fprintf(stderr, "Could not set window icon (%s)\n", SDL_GetError());
  366.     }
  367.  
  368.     if (TTF_Init() != 0) {
  369.         SDL_Quit();
  370. -       delete[] this->mem;
  371.         std::string err = "TTF font initialization failed: ";
  372.         err += TTF_GetError();
  373.         return err;
  374. @@ -204,7 +118,6 @@ std::string VideoSystem::Initialize(const char *font_name, int font_size)
  375.         err += TTF_GetError();
  376.         TTF_Quit();
  377.         SDL_Quit();
  378. -       delete[] this->mem;
  379.         return err;
  380.     }
  381.  
  382. @@ -230,43 +143,12 @@ bool VideoSystem::SetResolution(const Point32 &res)
  383.  {
  384.     if (this->initialized && this->GetXSize() == res.x && this->GetYSize() == res.y) return true;
  385.  
  386. -   /* Destroy old window, if it exists. */
  387. -   if (this->initialized) {
  388. -       delete[] mem;
  389. -       this->mem = nullptr;
  390. -       SDL_DestroyTexture(this->texture);
  391. -       this->texture = nullptr;
  392. -       SDL_DestroyRenderer(this->renderer);
  393. -       this->renderer = nullptr;
  394. -   }
  395. -
  396.     this->vid_width = res.x;
  397.     this->vid_height = res.y;
  398.     SDL_SetWindowSize(this->window, this->vid_width, this->vid_height);
  399.  
  400. -   this->renderer = SDL_CreateRenderer(this->window, -1, 0);
  401. -   if (this->renderer == nullptr) {
  402. -       SDL_Quit();
  403. -       fprintf(stderr, "Could not create renderer (%s)\n", SDL_GetError());
  404. -       return false;
  405. -   }
  406. -
  407. -   this->texture = SDL_CreateTexture(this->renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, this->vid_width, this->vid_height);
  408. -   if (this->texture == nullptr) {
  409. -       SDL_Quit();
  410. -       fprintf(stderr, "Could not create texture (%s)\n", SDL_GetError());
  411. -       return false;
  412. -   }
  413. -
  414. -   this->mem = new uint32[this->vid_width * this->vid_height];
  415. -   if (this->mem == nullptr) {
  416. -       SDL_Quit();
  417. -       fprintf(stderr, "Failed to obtain window display storage.\n");
  418. -       return false;
  419. -   }
  420. -
  421.     /* Update internal screen size data structures. */
  422. -   this->blit_rect = ClippedRectangle(0, 0, this->vid_width, this->vid_height);
  423. +   this->blit_rect = Rectangle32(0, 0, this->vid_width, this->vid_height);
  424.     Viewport *vp = GetViewport();
  425.     if (vp != nullptr) vp->SetSize(this->vid_width, this->vid_height);
  426.     _manager.RepositionAllWindows();
  427. @@ -314,18 +196,17 @@ void VideoSystem::MarkDisplayClean()
  428.   * Set the clipped area.
  429.   * @param cr New clipped blitting area.
  430.   */
  431. -void VideoSystem::SetClippedRectangle(const ClippedRectangle &cr)
  432. +void VideoSystem::SetClippedRectangle(const Rectangle32 &rect)
  433.  {
  434. -   this->blit_rect = cr;
  435. +   this->blit_rect = rect;
  436.  }
  437.  
  438.  /**
  439.   * Get the current clipped blitting area.
  440.   * @return Current clipped area.
  441.   */
  442. -ClippedRectangle VideoSystem::GetClippedRectangle()
  443. +Rectangle32 VideoSystem::GetClippedRectangle()
  444.  {
  445. -   this->blit_rect.ValidateAddress();
  446.     return this->blit_rect;
  447.  }
  448.  
  449. @@ -439,6 +320,9 @@ void VideoSystem::MainLoop()
  450.         if (_finish) break;
  451.  
  452.         uint32 now = SDL_GetTicks();
  453. +
  454. +       printf("%dms\n", now - start);
  455. +
  456.         if (now >= start) { // No wrap around.
  457.             now -= start;
  458.             if (now < FRAME_DELAY) SDL_Delay(FRAME_DELAY - now); // Too early, wait until next frame.
  459. @@ -458,7 +342,6 @@ void VideoSystem::Shutdown()
  460.         TTF_CloseFont(this->font);
  461.         TTF_Quit();
  462.         SDL_Quit();
  463. -       delete[] this->mem;
  464.         this->initialized = false;
  465.         this->dirty = false;
  466.     }
  467. @@ -470,11 +353,12 @@ void VideoSystem::Shutdown()
  468.   */
  469.  void VideoSystem::FinishRepaint()
  470.  {
  471. -   SDL_UpdateTexture(this->texture, nullptr, this->mem, this->GetXSize() * sizeof(uint32)); // Upload memory to the GPU.
  472. -   SDL_RenderClear(this->renderer);
  473. -   SDL_RenderCopy(this->renderer, this->texture, nullptr, nullptr);
  474.     SDL_RenderPresent(this->renderer);
  475.  
  476. +   /* Reset the renderer */
  477. +   SDL_SetRenderDrawColor(this->renderer, 0, 0, 0, 0);
  478. +   SDL_RenderClear(this->renderer);
  479. +
  480.     MarkDisplayClean();
  481.  }
  482.  
  483. @@ -483,333 +367,96 @@ void VideoSystem::FinishRepaint()
  484.   * @param colour Colour to fill with.
  485.   * @param rect %Rectangle to fill.
  486.   */
  487. -void VideoSystem::FillSurface(uint32 colour, const Rectangle32 &rect)
  488. -{
  489. -   ClippedRectangle cr = this->GetClippedRectangle();
  490. -
  491. -   int x = Clamp((int)rect.base.x, 0, (int)cr.width);
  492. -   int w = Clamp((int)(rect.base.x + rect.width), 0, (int)cr.width);
  493. -   int y = Clamp((int)rect.base.y, 0, (int)cr.height);
  494. -   int h = Clamp((int)(rect.base.y + rect.height), 0, (int)cr.height);
  495. -
  496. -   w -= x;
  497. -   h -= y;
  498. -   if (w == 0 || h == 0) return;
  499. -
  500. -   uint32 *pixels_base = cr.address + x + y * cr.pitch;
  501. -   while (h > 0) {
  502. -       uint32 *pixels = pixels_base;
  503. -       for (int i = 0; i < w; i++) *pixels++ = colour;
  504. -       pixels_base += cr.pitch;
  505. -       h--;
  506. -   }
  507. -}
  508. -
  509. -/**
  510. - * Blit pixels from the \a spr relative to #blit_rect into the area.
  511. - * @param img_base Coordinate of the sprite data.
  512. - * @param spr The sprite to blit.
  513. - * @param recolour Sprite recolouring definition.
  514. - * @param shift Gradient shift.
  515. - */
  516. -void VideoSystem::BlitImage(const Point32 &img_base, const ImageData *spr, const Recolouring &recolour, GradientShift shift)
  517. +void VideoSystem::FillSurface(const Rectangle32 &rect, uint32 colour)
  518.  {
  519. -   this->BlitImage(img_base.x, img_base.y, spr, recolour, shift);
  520. -}
  521. -
  522. -static const int STEP_SIZE = 18; ///< Amount of colour shift for each gradient step.
  523. -typedef uint8 (*ShiftFunc)(uint8); ///< Type of the gradient shift function.
  524. -
  525. -/**
  526. - * Gradient shift function for #GS_NIGHT.
  527. - * @param col Input colour.
  528. - * @return Shifted result colour.
  529. - */
  530. -static uint8 ShiftGradientNight(uint8 col)
  531. -{
  532. -   return (col <= 4 * STEP_SIZE) ? 0 : col - 4 * STEP_SIZE;
  533. -}
  534. -
  535. -/**
  536. - * Gradient shift function for #GS_VERY_DARK.
  537. - * @param col Input colour.
  538. - * @return Shifted result colour.
  539. - */
  540. -static uint8 ShiftGradientVeryDark(uint8 col)
  541. -{
  542. -   return (col <= 3 * STEP_SIZE) ? 0 : col - 3 * STEP_SIZE;
  543. -}
  544. -
  545. -/**
  546. - * Gradient shift function for #GS_DARK
  547. - * @param col Input colour.
  548. - * @return Shifted result colour.
  549. - */
  550. -static uint8 ShiftGradientDark(uint8 col)
  551. -{
  552. -   return (col <= 2 * STEP_SIZE) ? 0 : col - 2 * STEP_SIZE;
  553. -}
  554. -
  555. -/**
  556. - * Gradient shift function for #GS_SLIGHTLY_DARK.
  557. - * @param col Input colour.
  558. - * @return Shifted result colour.
  559. - */
  560. -static uint8 ShiftGradientSlightlyDark(uint8 col)
  561. -{
  562. -   return (col <= STEP_SIZE) ? 0 : col - STEP_SIZE;
  563. -}
  564. -
  565. -/**
  566. - * Gradient shift function for #GS_NORMAL.
  567. - * @param col Input colour.
  568. - * @return Shifted result colour.
  569. - */
  570. -static uint8 ShiftGradientNormal(uint8 col)
  571. -{
  572. -   return col;
  573. -}
  574. -
  575. -/**
  576. - * Gradient shift function for #GS_SLIGHTLY_LIGHT.
  577. - * @param col Input colour.
  578. - * @return Shifted result colour.
  579. - */
  580. -static uint8 ShiftGradientSlightlyLight(uint8 col)
  581. -{
  582. -   return (col >= 255 - STEP_SIZE) ? 255: col + STEP_SIZE;
  583. -}
  584. -
  585. -/**
  586. - * Gradient shift function for #GS_LIGHT.
  587. - * @param col Input colour.
  588. - * @return Shifted result colour.
  589. - */
  590. -static uint8 ShiftGradientLight(uint8 col)
  591. -{
  592. -   return (col >= 255 - 2 * STEP_SIZE) ? 255: col + 2 * STEP_SIZE;
  593. -}
  594. -
  595. -/**
  596. - * Gradient shift function for #GS_VERY_LIGHT.
  597. - * @param col Input colour.
  598. - * @return Shifted result colour.
  599. - */
  600. -static uint8 ShiftGradientVeryLight(uint8 col)
  601. -{
  602. -   return (col >= 255 - 3 * STEP_SIZE) ? 255: col + 3 * STEP_SIZE;
  603. -}
  604. -
  605. -/**
  606. - * Gradient shift function for #GS_DAY.
  607. - * @param col Input colour.
  608. - * @return Shifted result colour.
  609. - */
  610. -static uint8 ShiftGradientDay(uint8 col)
  611. -{
  612. -   return (col >= 255 - 4 * STEP_SIZE) ? 255: col + 4 * STEP_SIZE;
  613. -}
  614. -
  615. -/**
  616. - * Select gradient shift function based on the \a shift.
  617. - * @param shift Desired amount of gradient shift.
  618. - * @return Recolour function implementing the shift.
  619. - */
  620. -static ShiftFunc GetGradientShiftFunc(GradientShift shift)
  621. -{
  622. -   switch (shift) {
  623. -       case GS_NIGHT:          return ShiftGradientNight;
  624. -       case GS_VERY_DARK:      return ShiftGradientVeryDark;
  625. -       case GS_DARK:           return ShiftGradientDark;
  626. -       case GS_SLIGHTLY_DARK:  return ShiftGradientSlightlyDark;
  627. -       case GS_NORMAL:         return ShiftGradientNormal;
  628. -       case GS_SLIGHTLY_LIGHT: return ShiftGradientSlightlyLight;
  629. -       case GS_LIGHT:          return ShiftGradientLight;
  630. -       case GS_VERY_LIGHT:     return ShiftGradientVeryLight;
  631. -       case GS_DAY:            return ShiftGradientDay;
  632. -       default: NOT_REACHED();
  633. -   }
  634. -}
  635. -
  636. -/**
  637. - * Blit an image at the specified position (top-left position) relative to #blit_rect.
  638. - * @param x Horizontal position.
  639. - * @param y Vertical position.
  640. - * @param img The sprite image data to blit.
  641. - * @param recolour Sprite recolouring definition.
  642. - * @param shift Gradient shift.
  643. - */
  644. -void VideoSystem::BlitImage(int x, int y, const ImageData *img, const Recolouring &recolour, GradientShift shift)
  645. -{
  646. -   this->BlitImages(x, y, img, 1, 1, recolour, shift);
  647. -}
  648. -
  649. -/**
  650. - * Blit a pixel to an area of \a numx times \a numy sprites.
  651. - * @param cr Clipped rectangle.
  652. - * @param scr_base Base address of the screen array.
  653. - * @param xmin Minimal x position.
  654. - * @param ymin Minimal y position.
  655. - * @param numx Number of horizontal count.
  656. - * @param numy Number of vertical count.
  657. - * @param width Width of an image.
  658. - * @param height Height of an image.
  659. - * @param colour Pixel value to blit.
  660. - * @note Function does not handle alpha blending of the new pixel with the background.
  661. - */
  662. -static void BlitPixel(const ClippedRectangle &cr, uint32 *scr_base,
  663. -       int32 xmin, int32 ymin, uint16 numx, uint16 numy, uint16 width, uint16 height, uint32 colour)
  664. -{
  665. -   const int32 xend = xmin + numx * width;
  666. -   const int32 yend = ymin + numy * height;
  667. -   while (ymin < yend) {
  668. -       if (ymin >= cr.height) return;
  669. -
  670. -       if (ymin >= 0) {
  671. -           uint32 *scr = scr_base;
  672. -           int32 x = xmin;
  673. -           while (x < xend) {
  674. -               if (x >= cr.width) break;
  675. -               if (x >= 0) *scr = colour;
  676. -
  677. -               x += width;
  678. -               scr += width;
  679. -           }
  680. -       }
  681. -       ymin += height;
  682. -       scr_base += height * cr.pitch;
  683. -   }
  684. +   SDL_Rect sdl_rect = RectToSDLRect(rect);
  685. +   SDL_SetRenderDrawColor(this->renderer, SPLIT_RGBA(colour));
  686. +   SDL_RenderFillRect(this->renderer, &sdl_rect);
  687.  }
  688.  
  689.  /**
  690.   * Blit 8bpp images to the screen.
  691. - * @param cr Clipped rectangle to draw to.
  692. - * @param x_base Base X coordinate of the sprite data.
  693. - * @param y_base Base Y coordinate of the sprite data.
  694.   * @param spr The sprite to blit.
  695. - * @param numx Number of sprites to draw in horizontal direction.
  696. - * @param numy Number of sprites to draw in vertical direction.
  697.   * @param recoloured Shifted palette to use.
  698.   */
  699. -static void Blit8bppImages(const ClippedRectangle &cr, int32 x_base, int32 y_base, const ImageData *spr, uint16 numx, uint16 numy, const uint8 *recoloured)
  700. +static std::vector<uint32> Blit8bppImage(const ImageData *spr, const uint8 *recoloured)
  701.  {
  702. -   uint32 *line_base = cr.address + x_base + cr.pitch * y_base;
  703. -   int32 ypos = y_base;
  704. -   for (int yoff = 0; yoff < spr->height; yoff++) {
  705. -       uint32 offset = spr->table[yoff];
  706. +   std::vector<uint32> mem(spr->height * spr->width);
  707. +   for (int ypos = 0; ypos < spr->height; ypos++) {
  708. +       uint32 offset = spr->table[ypos];
  709.         if (offset != INVALID_JUMP) {
  710. -           int32 xpos = x_base;
  711. -           uint32 *src_base = line_base;
  712. -           for (;;) {
  713. +           for (int xpos = 0;;) {
  714.                 uint8 rel_off = spr->data[offset];
  715.                 uint8 count   = spr->data[offset + 1];
  716.                 uint8 *pixels = &spr->data[offset + 2];
  717.                 offset += 2 + count;
  718.  
  719. -               xpos += rel_off & 127;
  720. -               src_base += rel_off & 127;
  721. -               while (count > 0) {
  722. -                   uint32 colour = _palette[recoloured[*pixels]];
  723. -                   BlitPixel(cr, src_base, xpos, ypos, numx, numy, spr->width, spr->height, colour);
  724. +               xpos += rel_off & 0x7F;
  725. +               for (; count > 0; count--) {
  726. +                   mem.at(ypos * spr->width + xpos) = _palette[recoloured[*pixels]];
  727.                     pixels++;
  728.                     xpos++;
  729. -                   src_base++;
  730. -                   count--;
  731.                 }
  732. -               if ((rel_off & 128) != 0) break;
  733. +               if ((rel_off & 0x80) != 0) break;
  734.             }
  735.         }
  736. -       line_base += cr.pitch;
  737. -       ypos++;
  738.     }
  739. +   return mem;
  740.  }
  741.  
  742.  /**
  743.   * Blit 32bpp images to the screen.
  744. - * @param cr Clipped rectangle to draw to.
  745. - * @param x_base Base X coordinate of the sprite data.
  746. - * @param y_base Base Y coordinate of the sprite data.
  747.   * @param spr The sprite to blit.
  748. - * @param numx Number of sprites to draw in horizontal direction.
  749. - * @param numy Number of sprites to draw in vertical direction.
  750.   * @param recolour Sprite recolouring definition.
  751.   * @param shift Gradient shift.
  752.   */
  753. -static void Blit32bppImages(const ClippedRectangle &cr, int32 x_base, int32 y_base, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour, GradientShift shift)
  754. +static std::vector<uint32> Blit32bppImage(const ImageData *spr, const Recolouring &recolour)
  755.  {
  756. -   uint32 *line_base = cr.address + x_base + cr.pitch * y_base;
  757. -   ShiftFunc sf = GetGradientShiftFunc(shift);
  758. -   int32 ypos = y_base;
  759. +   std::vector<uint32> mem(spr->height * spr->width);
  760.     const uint8 *src = spr->data + 2; // Skip the length word.
  761. -   for (int yoff = 0; yoff < spr->height; yoff++) {
  762. -       int32 xpos = x_base;
  763. -       uint32 *src_base = line_base;
  764. -       for (;;) {
  765. +   for (int ypos = 0; ypos < spr->height; ypos++) {
  766. +       for (int xpos = 0;;) {
  767.             uint8 mode = *src++;
  768.             if (mode == 0) break;
  769. +           int len = mode & 0x3F;
  770.             switch (mode >> 6) {
  771.                 case 0: // Fully opaque pixels.
  772. -                   mode &= 0x3F;
  773. -                   for (; mode > 0; mode--) {
  774. -                       uint32 colour = MakeRGBA(sf(src[0]), sf(src[1]), sf(src[2]), OPAQUE);
  775. -                       BlitPixel(cr, src_base, xpos, ypos, numx, numy, spr->width, spr->height, colour);
  776. +                   for (; len > 0; len--) {
  777. +                       mem.at(ypos * spr->width + xpos) = MakeRGBA(src[0], src[1], src[2], OPAQUE);
  778.                         xpos++;
  779. -                       src_base++;
  780.                         src += 3;
  781.                     }
  782.                     break;
  783.  
  784.                 case 1: { // Partial opaque pixels.
  785.                     uint8 opacity = *src++;
  786. -                   mode &= 0x3F;
  787. -                   for (; mode > 0; mode--) {
  788. -                       /* Cheat transparency a bit by just recolouring the previously drawn pixel */
  789. -                       uint32 old_pixel = *src_base;
  790. -
  791. -                       uint r = sf(src[0]) * opacity + GetR(old_pixel) * (256 - opacity);
  792. -                       uint g = sf(src[1]) * opacity + GetG(old_pixel) * (256 - opacity);
  793. -                       uint b = sf(src[2]) * opacity + GetB(old_pixel) * (256 - opacity);
  794. -
  795. -                       /* Opaque, but colour adjusted depending on the old pixel. */
  796. -                       uint32 ndest = MakeRGBA(r >> 8, g >> 8, b >> 8, OPAQUE);
  797. -                       BlitPixel(cr, src_base, xpos, ypos, numx, numy, spr->width, spr->height, ndest);
  798. +                   for (; len > 0; len--) {
  799. +                       mem.at(ypos * spr->width + xpos) = MakeRGBA(src[0], src[1], src[2], opacity);
  800.                         xpos++;
  801. -                       src_base++;
  802.                         src += 3;
  803.                     }
  804.                     break;
  805.                 }
  806.                 case 2: // Fully transparent pixels.
  807. -                   xpos += mode & 0x3F;
  808. -                   src_base += mode & 0x3F;
  809. +                   xpos += len;
  810.                     break;
  811.  
  812.                 case 3: { // Recoloured pixels.
  813.                     uint8 layer = *src++;
  814.                     const uint32 *table = recolour.GetRecolourTable(layer - 1);
  815.                     uint8 opacity = *src++;
  816. -                   mode &= 0x3F;
  817. -                   for (; mode > 0; mode--) {
  818. -                       uint32 old_pixel = *src_base;
  819. +                   for (; len > 0; len--) {
  820.                         uint32 recoloured = table[*src++];
  821. -
  822. -                       uint r = sf(GetR(recoloured)) * opacity + GetR(old_pixel) * (256 - opacity);
  823. -                       uint g = sf(GetG(recoloured)) * opacity + GetG(old_pixel) * (256 - opacity);
  824. -                       uint b = sf(GetB(recoloured)) * opacity + GetB(old_pixel) * (256 - opacity);
  825. -
  826. -                       uint32 colour = MakeRGBA(r >> 8, g >> 8, b >> 8, OPAQUE);
  827. -                       BlitPixel(cr, src_base, xpos, ypos, numx, numy, spr->width, spr->height, colour);
  828. +                       mem.at(ypos * spr->width + xpos) = SetA(recoloured, opacity);
  829.                         xpos++;
  830. -                       src_base++;
  831.                     }
  832.                     break;
  833.                 }
  834.             }
  835.         }
  836. -       line_base += cr.pitch;
  837. -       ypos++;
  838.         src += 2; // Skip the length word.
  839.     }
  840. +   return mem;
  841.  }
  842.  
  843.  /**
  844. @@ -822,30 +469,33 @@ static void Blit32bppImages(const ClippedRectangle &cr, int32 x_base, int32 y_ba
  845.   * @param recolour Sprite recolouring definition.
  846.   * @param shift Gradient shift.
  847.   */
  848. -void VideoSystem::BlitImages(int32 x_base, int32 y_base, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour, GradientShift shift)
  849. +void VideoSystem::BlitImages(const Point32 &img_base, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour)
  850.  {
  851. -   this->blit_rect.ValidateAddress();
  852. +   int x_base = img_base.x + spr->xoffset;
  853. +   int y_base = img_base.y + spr->yoffset;
  854.  
  855. -   x_base += spr->xoffset;
  856. -   y_base += spr->yoffset;
  857. +   if (numx == 0 || numy == 0) return;
  858.  
  859. -   /* Don't draw wildly outside the screen. */
  860. -   while (numx > 0 && x_base + spr->width < 0) {
  861. -       x_base += spr->width; numx--;
  862. -   }
  863. -   while (numx > 0 && x_base + (numx - 1) * spr->width >= this->blit_rect.width) numx--;
  864. -   if (numx == 0) return;
  865. +   if (spr->image == nullptr) {
  866. +       std::vector<uint32> img;
  867. +       if (GB(spr->flags, IFG_IS_8BPP, 1) != 0) {
  868. +           img = Blit8bppImage(spr, recolour.GetPalette(GS_NORMAL));
  869. +       } else {
  870. +           img = Blit32bppImage(spr, recolour);
  871. +       }
  872.  
  873. -   while (numy > 0 && y_base + spr->height < 0) {
  874. -       y_base += spr->height; numy--;
  875. +       spr->image = SDL_CreateTexture(this->renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, spr->width, spr->height);
  876. +       SDL_UpdateTexture(spr->image, nullptr, img.data(), spr->width * sizeof(uint32));
  877. +       SDL_SetTextureBlendMode(spr->image, SDL_BLENDMODE_BLEND);
  878.     }
  879. -   while (numy > 0 && y_base + (numy - 1) * spr->height >= this->blit_rect.height) numy--;
  880. -   if (numy == 0) return;
  881.  
  882. -   if (GB(spr->flags, IFG_IS_8BPP, 1) != 0) {
  883. -       Blit8bppImages(this->blit_rect, x_base, y_base, spr, numx, numy, recolour.GetPalette(shift));
  884. -   } else {
  885. -       Blit32bppImages(this->blit_rect, x_base, y_base, spr, numx, numy, recolour, shift);
  886. +   assert(spr->image != nullptr);
  887. +
  888. +   for (int x = 0; x < numx; x++) {
  889. +       for (int y = 0; y < numy; y++) {
  890. +           SDL_Rect sdl_rect = {x_base + x * spr->width, y_base + y * spr->height, spr->width, spr->height};
  891. +           SDL_RenderCopy(this->renderer, spr->image, nullptr, &sdl_rect);
  892. +       }
  893.     }
  894.  }
  895.  
  896. @@ -912,7 +562,7 @@ void VideoSystem::GetNumberRangeSize(int64 smallest, int64 biggest, int *width,
  897.   */
  898.  void VideoSystem::BlitText(const uint8 *text, uint32 colour, int xpos, int ypos, int width, Alignment align)
  899.  {
  900. -   SDL_Color col = {0, 0, 0}; // Font colour does not matter as only the bitmap is used.
  901. +   SDL_Color col = {SPLIT_RGBA(colour)};
  902.     SDL_Surface *surf = TTF_RenderUTF8_Solid(this->font, (const char *)text, col);
  903.     if (surf == nullptr) {
  904.         fprintf(stderr, "Rendering text failed (%s)\n", TTF_GetError());
  905. @@ -924,7 +574,10 @@ void VideoSystem::BlitText(const uint8 *text, uint32 colour, int xpos, int ypos,
  906.         return;
  907.     }
  908.  
  909. +   SDL_Texture *tex = SDL_CreateTextureFromSurface(this->renderer, surf);
  910. +
  911.     int real_w = std::min(surf->w, width);
  912. +
  913.     switch (align) {
  914.         case ALG_LEFT:
  915.             break;
  916. @@ -940,44 +593,10 @@ void VideoSystem::BlitText(const uint8 *text, uint32 colour, int xpos, int ypos,
  917.         default: NOT_REACHED();
  918.     }
  919.  
  920. -   this->blit_rect.ValidateAddress();
  921. -
  922. -   uint8 *src = ((uint8 *)surf->pixels);
  923. -   uint32 *dest = this->blit_rect.address + xpos + ypos * this->blit_rect.pitch;
  924. -   int h = surf->h;
  925. -   if (ypos < 0) {
  926. -       h += ypos;
  927. -       src  -= ypos * surf->pitch;
  928. -       dest -= ypos * this->blit_rect.pitch;
  929. -       ypos = 0;
  930. -   }
  931. -   while (h > 0) {
  932. -       if (ypos >= this->blit_rect.height) break;
  933. -       uint8 *src2 = src;
  934. -       uint32 *dest2 = dest;
  935. -       int w = real_w;
  936. -       int x = xpos;
  937. -       if (x < 0) {
  938. -           w += x;
  939. -           if (w <= 0) break;
  940. -           dest2 -= x;
  941. -           src2 -= x;
  942. -           x = 0;
  943. -       }
  944. -       while (w > 0) {
  945. -           if (x >= this->blit_rect.width) break;
  946. -           if (*src2 != 0) *dest2 = colour;
  947. -           src2++;
  948. -           dest2++;
  949. -           x++;
  950. -           w--;
  951. -       }
  952. -       ypos++;
  953. -       src  += surf->pitch;
  954. -       dest += this->blit_rect.pitch;
  955. -       h--;
  956. -   }
  957. +   SDL_Rect sdl_rect = {xpos, ypos, real_w, surf->h};
  958. +   SDL_RenderCopy(this->renderer, tex, nullptr, &sdl_rect);
  959.  
  960. +   SDL_DestroyTexture(tex);
  961.     SDL_FreeSurface(surf);
  962.  }
  963.  
  964. @@ -989,51 +608,8 @@ void VideoSystem::BlitText(const uint8 *text, uint32 colour, int xpos, int ypos,
  965.   */
  966.  void VideoSystem::DrawLine(const Point16 &start, const Point16 &end, uint32 colour)
  967.  {
  968. -   int16 dx, inc_x, dy, inc_y;
  969. -   if (start.x > end.x) {
  970. -       dx = start.x - end.x;
  971. -       inc_x = -1;
  972. -   } else {
  973. -       dx = end.x - start.x;
  974. -       inc_x = 1;
  975. -   }
  976. -   if (start.y > end.y) {
  977. -       dy = start.y - end.y;
  978. -       inc_y = -1;
  979. -   } else {
  980. -       dy = end.y - start.y;
  981. -       inc_y = 1;
  982. -   }
  983. -
  984. -   int16 step = std::min(dx, dy);
  985. -   int16 pos_x = start.x;
  986. -   int16 pos_y = start.y;
  987. -   int16 sum_x = 0;
  988. -   int16 sum_y = 0;
  989. -
  990. -   this->blit_rect.ValidateAddress();
  991. -   uint32 *dest = this->blit_rect.address + pos_x + pos_y * this->blit_rect.pitch;
  992. -
  993. -   for (;;) {
  994. -       /* Blit pixel. */
  995. -       if (pos_x >= 0 && pos_x < this->blit_rect.width && pos_y >= 0 && pos_y < this->blit_rect.height) {
  996. -           *dest = colour;
  997. -       }
  998. -       if (pos_x == end.x && pos_y == end.y) break;
  999. -
  1000. -       sum_x += step;
  1001. -       sum_y += step;
  1002. -       if (sum_x >= dy) {
  1003. -           pos_x += inc_x;
  1004. -           dest += inc_x;
  1005. -           sum_x -= dy;
  1006. -       }
  1007. -       if (sum_y >= dx) {
  1008. -           pos_y += inc_y;
  1009. -           dest += inc_y * this->blit_rect.pitch;
  1010. -           sum_y -= dx;
  1011. -       }
  1012. -   }
  1013. +   SDL_SetRenderDrawColor(this->renderer, SPLIT_RGBA(colour));
  1014. +   SDL_RenderDrawLine(this->renderer, start.x, start.y, end.x, end.y);
  1015.  }
  1016.  
  1017.  /**
  1018. @@ -1043,12 +619,7 @@ void VideoSystem::DrawLine(const Point16 &start, const Point16 &end, uint32 colo
  1019.   */
  1020.  void VideoSystem::DrawRectangle(const Rectangle32 &rect, uint32 colour)
  1021.  {
  1022. -   Point16 top_left    (static_cast<int16>(rect.base.x),                  static_cast<int16>(rect.base.y));
  1023. -   Point16 top_right   (static_cast<int16>(rect.base.x + rect.width - 1), static_cast<int16>(rect.base.y));
  1024. -   Point16 bottom_left (static_cast<int16>(rect.base.x),                  static_cast<int16>(rect.base.y + rect.height - 1));
  1025. -   Point16 bottom_right(static_cast<int16>(rect.base.x + rect.width - 1), static_cast<int16>(rect.base.y + rect.height - 1));
  1026. -   this->DrawLine(top_left, top_right, colour);
  1027. -   this->DrawLine(top_left, bottom_left, colour);
  1028. -   this->DrawLine(top_right, bottom_right, colour);
  1029. -   this->DrawLine(bottom_left, bottom_right, colour);
  1030. +   SDL_Rect sdl_rect = RectToSDLRect(rect);
  1031. +   SDL_SetRenderDrawColor(this->renderer, SPLIT_RGBA(colour));
  1032. +   SDL_RenderDrawRect(this->renderer, &sdl_rect);
  1033.  }
  1034. diff --git a/src/video.h b/src/video.h
  1035. index 6f435a9..2d6f81e 100644
  1036. --- a/src/video.h
  1037. +++ b/src/video.h
  1038. @@ -22,27 +22,6 @@ void QuitProgram();
  1039.  
  1040.  class ImageData;
  1041.  
  1042. -/** Clipped rectangle. */
  1043. -class ClippedRectangle {
  1044. -public:
  1045. -   ClippedRectangle();
  1046. -   ClippedRectangle(uint16 x, uint16 y, uint16 w, uint16 h);
  1047. -   ClippedRectangle(const ClippedRectangle &cr, uint16 x, uint16 y, uint16 w, uint16 h);
  1048. -
  1049. -   ClippedRectangle(const ClippedRectangle &cr);
  1050. -   ClippedRectangle &operator=(const ClippedRectangle &cr);
  1051. -
  1052. -   void ValidateAddress();
  1053. -
  1054. -   uint16 absx;     ///< Absolute X position in the screen of the top-left.
  1055. -   uint16 absy;     ///< Absolute Y position in the screen of the top-left.
  1056. -   uint16 width;    ///< Number of columns.
  1057. -   uint16 height;   ///< Number of rows.
  1058. -
  1059. -   uint32 *address; ///< Base address. @note Call #ValidateAddress prior to use.
  1060. -   int32 pitch;     ///< Pitch of a row in bytes. @note Call #ValidateAddress prior to use.
  1061. -};
  1062. -
  1063.  /** How to align text during drawing. */
  1064.  enum Alignment {
  1065.     ALG_LEFT,   ///< Align to the left edge.
  1066. @@ -54,15 +33,12 @@ enum Alignment {
  1067.   * Class representing the video system.
  1068.   */
  1069.  class VideoSystem {
  1070. -   friend class ClippedRectangle;
  1071. -
  1072.  public:
  1073.     VideoSystem();
  1074.     ~VideoSystem();
  1075.  
  1076.     std::string Initialize(const char *font_name, int font_size);
  1077.     bool SetResolution(const Point32 &res);
  1078. -   void GetResolutions();
  1079.     void MainLoop();
  1080.     void Shutdown();
  1081.  
  1082. @@ -98,12 +74,18 @@ public:
  1083.     void MarkDisplayDirty();
  1084.     void MarkDisplayDirty(const Rectangle32 &rect);
  1085.  
  1086. -   void SetClippedRectangle(const ClippedRectangle &cr);
  1087. -   ClippedRectangle GetClippedRectangle();
  1088. +   void FillSurface(const Rectangle32 &rect, uint32 colour);
  1089.  
  1090. -   void FillSurface(uint32 colour, const Rectangle32 &rect);
  1091. -   void BlitImage(const Point32 &img_base, const ImageData *spr, const Recolouring &recolour, GradientShift shift);
  1092. -   void BlitImage(int x, int y, const ImageData *img, const Recolouring &recolour, GradientShift shift);
  1093. +   /**
  1094. +    * Blit a single sprite.
  1095. +    * @param img_base Coordinates of the sprite data (relative to window).
  1096. +    * @param spr The sprite to blit.
  1097. +    * @param recolour Sprite recolouring definition.
  1098. +    */
  1099. +   void BlitImage(const Point32 &img_base, const ImageData *spr, const Recolouring &recolour)
  1100. +   {
  1101. +       this->BlitImages(img_base, spr, 1, 1, recolour);
  1102. +   }
  1103.  
  1104.     /**
  1105.      * Blit a row of sprites.
  1106. @@ -115,7 +97,7 @@ public:
  1107.      */
  1108.     inline void BlitHorizontal(int32 xmin, uint16 numx, int32 y, const ImageData *spr, const Recolouring &recolour)
  1109.     {
  1110. -       this->BlitImages(xmin, y, spr, numx, 1, recolour);
  1111. +       this->BlitImages({xmin, y}, spr, numx, 1, recolour);
  1112.     }
  1113.  
  1114.     /**
  1115. @@ -128,10 +110,10 @@ public:
  1116.      */
  1117.     inline void BlitVertical(int32 ymin, uint16 numy, int32 x, const ImageData *spr, const Recolouring &recolour)
  1118.     {
  1119. -       this->BlitImages(x, ymin, spr, 1, numy, recolour);
  1120. +       this->BlitImages({x, ymin}, spr, 1, numy, recolour);
  1121.     }
  1122.  
  1123. -   void BlitImages(int32 x_base, int32 y_base, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour, GradientShift shift = GS_NORMAL);
  1124. +   void BlitImages(const Point32 &img_base, const ImageData *spr, uint16 numx, uint16 numy, const Recolouring &recolour);
  1125.  
  1126.     void FinishRepaint();
  1127.  
  1128. @@ -144,6 +126,9 @@ public:
  1129.         return this->font_height;
  1130.     }
  1131.  
  1132. +   void SetClippedRectangle(const Rectangle32 &rect);
  1133. +   Rectangle32 GetClippedRectangle();
  1134. +
  1135.     void GetTextSize(const uint8 *text, int *width, int *height);
  1136.     void GetNumberRangeSize(int64 smallest, int64 biggest, int *width, int *height);
  1137.     void BlitText(const uint8 *text, uint32 colour, int xpos, int ypos, int width = 0x7FFF, Alignment align = ALG_LEFT);
  1138. @@ -164,12 +149,20 @@ private:
  1139.     SDL_Window *window;         ///< %Window of the application.
  1140.     SDL_Renderer *renderer;     ///< GPU renderer to the application window.
  1141.     SDL_Texture *texture;       ///< GPU Texture storage of the application window.
  1142. -   uint32 *mem;                ///< Memory used for blitting the application display.
  1143. -   ClippedRectangle blit_rect; ///< %Rectangle to blit in.
  1144. +   Rectangle32 blit_rect;
  1145.     Point16 digit_size;         ///< Size of largest digit (initially a zero-size).
  1146.  
  1147. +   void GetResolutions();
  1148.     bool HandleEvent();
  1149.     void MarkDisplayClean();
  1150. +
  1151. +   template<class PZ, class SZ>
  1152. +   SDL_Rect RectToSDLRect(const Rectangle<PZ, SZ> &rect)
  1153. +   {
  1154. +       SDL_Rect sdl_rect = {static_cast<int>(rect.base.x), static_cast<int>(rect.base.y),
  1155. +                            static_cast<int>(rect.width),  static_cast<int>(rect.height)};
  1156. +       return sdl_rect;
  1157. +   }
  1158.  };
  1159.  
  1160.  extern VideoSystem _video;
  1161. diff --git a/src/viewport.cpp b/src/viewport.cpp
  1162. index eae8aa3..bfead68 100644
  1163. --- a/src/viewport.cpp
  1164. +++ b/src/viewport.cpp
  1165. @@ -1022,7 +1022,7 @@ void SpriteCollector::CollectVoxel(const Voxel *voxel, int xpos, int ypos, int z
  1166.  
  1167.         gslope = voxel->GetGroundSlope();
  1168.     }
  1169. -  
  1170. +
  1171.     /* Fences */
  1172.     for (TileEdge edge = EDGE_BEGIN; edge < EDGE_COUNT; edge++) {
  1173.         FenceType fence_type = voxel->GetFenceType(edge);
  1174. @@ -1404,21 +1404,14 @@ void Viewport::OnDraw()
  1175.     collector.Collect(this->additions_enabled && this->additions_displayed);
  1176.     static const Recolouring recolour;
  1177.  
  1178. -   _video.FillSurface(MakeRGBA(0, 0, 0, OPAQUE), this->rect); // Black background.
  1179. -
  1180. -   ClippedRectangle cr = _video.GetClippedRectangle();
  1181. -   assert(this->rect.base.x >= 0 && this->rect.base.y >= 0);
  1182. -   ClippedRectangle draw_rect(cr, this->rect.base.x, this->rect.base.y, this->rect.width, this->rect.height);
  1183. -   _video.SetClippedRectangle(draw_rect);
  1184. -
  1185. -   GradientShift gs = static_cast<GradientShift>(GS_LIGHT - _weather.GetWeatherType());
  1186.     for (const auto &iter : collector.draw_images) {
  1187.         const DrawData &dd = iter;
  1188.         const Recolouring &rec = (dd.recolour == nullptr) ? recolour : *dd.recolour;
  1189. -       _video.BlitImage(dd.base, dd.sprite, rec, gs);
  1190. +       _video.BlitImage(dd.base, dd.sprite, rec);
  1191.     }
  1192.  
  1193. -   _video.SetClippedRectangle(cr);
  1194. +   /// \todo Actually change brightness/darkness overlay depending on weather
  1195. +   _video.FillSurface(this->rect, MakeRGBA(0, 0, 0, 0));
  1196.  }
  1197.  
  1198.  /**
  1199. diff --git a/src/widget.cpp b/src/widget.cpp
  1200. index 6139ada..a96c9e2 100644
  1201. --- a/src/widget.cpp
  1202. +++ b/src/widget.cpp
  1203. @@ -285,7 +285,7 @@ void LeafWidget::Draw(const GuiWindow *w)
  1204.         } else if ((this->flags & LWF_PRESSED) != 0) {
  1205.             spr_num += WCS_EMPTY_PRESSED;
  1206.         }
  1207. -       _video.BlitImage(left, top, _gui_sprites.radio_button.sprites[spr_num], rc, GS_NORMAL);
  1208. +       _video.BlitImage({left, top}, _gui_sprites.radio_button.sprites[spr_num], rc);
  1209.         return;
  1210.     }
  1211.     assert(this->wtype == WT_CLOSEBOX);
  1212. @@ -305,7 +305,7 @@ void LeafWidget::Draw(const GuiWindow *w)
  1213.     int yoffset = top + (bottom - 1 - top - _gui_sprites.close_sprite->height) / 2;
  1214.  
  1215.     const ImageData *imgdata = _gui_sprites.close_sprite;
  1216. -   if (imgdata != nullptr) _video.BlitImage(xoffset + 1, yoffset + 1, imgdata, rc, GS_NORMAL);
  1217. +   if (imgdata != nullptr) _video.BlitImage({xoffset + 1, yoffset + 1}, imgdata, rc);
  1218.     /* Closebox is never shaded. */
  1219.  }
  1220.  
  1221. @@ -464,7 +464,7 @@ void DataWidget::Draw(const GuiWindow *w)
  1222.             int xoffset = left + (right + 1 - left - this->value_width) / 2 - rect.base.x;
  1223.             yoffset -= rect.base.y;
  1224.             const ImageData *imgdata = _sprite_manager.GetTableSprite(this->value);
  1225. -           if (imgdata != nullptr) _video.BlitImage(xoffset + pressed, yoffset + pressed, imgdata, rc, GS_NORMAL);
  1226. +           if (imgdata != nullptr) _video.BlitImage({xoffset + pressed, yoffset + pressed}, imgdata, rc);
  1227.             break;
  1228.         }
  1229.  
  1230. @@ -477,7 +477,7 @@ void DataWidget::Draw(const GuiWindow *w)
  1231.  
  1232.             if (imgdata != nullptr) {
  1233.                 int triangle_yoff = top + (bottom + 1 - top - imgrect.height) / 2 + pressed;
  1234. -               _video.BlitImage(right - imgrect.width + pressed, triangle_yoff, imgdata, rc, GS_NORMAL);
  1235. +               _video.BlitImage({right - imgrect.width + pressed, triangle_yoff}, imgdata, rc);
  1236.             }
  1237.             /* Note: Reusing the same string parameters from above */
  1238.             if (this->value != STR_NULL) DrawString(w->TranslateStringNumber(this->value), TEXT_WHITE, left + pressed, yoffset + pressed, right - left - imgrect.width, align);
  1239. @@ -553,12 +553,12 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1240.     Point32 pos(w->GetWidgetScreenX(this), w->GetWidgetScreenY(this));
  1241.  
  1242.     /* Draw left/up button. */
  1243. -   _video.BlitImage(pos, imd[WLS_LEFT_BUTTON], rc, GS_NORMAL);
  1244. +   _video.BlitImage(pos, imd[WLS_LEFT_BUTTON], rc);
  1245.     if (this->wtype == WT_HOR_SCROLLBAR) pos.x += imd[WLS_LEFT_BUTTON]->width;
  1246.     if (this->wtype != WT_HOR_SCROLLBAR) pos.y += imd[WLS_LEFT_BUTTON]->height;
  1247.  
  1248.     /* Draw top/left underground. */
  1249. -   _video.BlitImage(pos, imd[WLS_LEFT_BED], rc, GS_NORMAL);
  1250. +   _video.BlitImage(pos, imd[WLS_LEFT_BED], rc);
  1251.     if (this->wtype == WT_HOR_SCROLLBAR) pos.x += imd[WLS_LEFT_BED]->width;
  1252.     if (this->wtype != WT_HOR_SCROLLBAR) pos.y += imd[WLS_LEFT_BED]->height;
  1253.  
  1254. @@ -578,7 +578,7 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1255.     }
  1256.  
  1257.     /* Draw bottom/right underground. */
  1258. -   _video.BlitImage(pos, imd[WLS_RIGHT_BED], rc, GS_NORMAL);
  1259. +   _video.BlitImage(pos, imd[WLS_RIGHT_BED], rc);
  1260.     if (this->wtype == WT_HOR_SCROLLBAR) {
  1261.         pos.x += imd[WLS_RIGHT_BED]->width;
  1262.     } else {
  1263. @@ -586,7 +586,7 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1264.     }
  1265.  
  1266.     /* Draw right/bottom button. */
  1267. -   _video.BlitImage(pos, imd[WLS_RIGHT_BUTTON], rc, GS_NORMAL);
  1268. +   _video.BlitImage(pos, imd[WLS_RIGHT_BUTTON], rc);
  1269.  
  1270.     int start_edge, slider_length;
  1271.     this->CalculateSliderPosition(&start_edge, &slider_length);
  1272. @@ -598,7 +598,7 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1273.     }
  1274.  
  1275.     /* Draw top/left slider. */
  1276. -   _video.BlitImage(pos, imd[WLS_LEFT_SLIDER], rc, GS_NORMAL);
  1277. +   _video.BlitImage(pos, imd[WLS_LEFT_SLIDER], rc);
  1278.     if (this->wtype == WT_HOR_SCROLLBAR) {
  1279.         pos.x += imd[WLS_LEFT_SLIDER]->width;
  1280.     } else {
  1281. @@ -617,7 +617,7 @@ void ScrollbarWidget::Draw(const GuiWindow *w)
  1282.     }
  1283.  
  1284.     /* Draw bottom/right slider. */
  1285. -   _video.BlitImage(pos, imd[WLS_RIGHT_SLIDER], rc, GS_NORMAL);
  1286. +   _video.BlitImage(pos, imd[WLS_RIGHT_SLIDER], rc);
  1287.  }
  1288.  
  1289.  /**
  1290. diff --git a/src/window.cpp b/src/window.cpp
  1291. index 5fc0127..1eb9181 100644
  1292. --- a/src/window.cpp
  1293. +++ b/src/window.cpp
  1294. @@ -986,12 +986,6 @@ void UpdateWindows()
  1295.  {
  1296.     if (!_video.DisplayNeedsRepaint()) return;
  1297.  
  1298. -   /* Until the entire background is covered by the main display, clean the entire display to ensure deleted
  1299. -    * windows truly disappear (even if there is no other window behind it).
  1300. -    */
  1301. -   Rectangle32 rect(0, 0, _video.GetXSize(), _video.GetYSize());
  1302. -   _video.FillSurface(MakeRGBA(0, 0, 0, OPAQUE), rect);
  1303. -
  1304.     Window *w = _manager.bottom;
  1305.     while (w != nullptr) {
  1306.         w->OnDraw();
  1307.  

Comments