From 8980bf2a124f647dbdece9f90b86b2f37c4f3fa5 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sun, 19 May 2024 11:21:24 -0400 Subject: Faster subway map rendering Image quality suffered a bit though. --- src/subway_map.cpp | 103 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 34 deletions(-) diff --git a/src/subway_map.cpp b/src/subway_map.cpp index b02c616..51f17c5 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp @@ -117,13 +117,77 @@ void SubwayMap::UpdateSunwarp(SubwaySunwarp from_sunwarp, void SubwayMap::OnPaint(wxPaintEvent &event) { if (GetSize() != rendered_.GetSize()) { - Redraw(); + wxSize panel_size = GetSize(); + wxSize image_size = map_image_.GetSize(); + + render_x_ = 0; + render_y_ = 0; + render_width_ = panel_size.GetWidth(); + render_height_ = panel_size.GetHeight(); + + if (image_size.GetWidth() * panel_size.GetHeight() > + panel_size.GetWidth() * image_size.GetHeight()) { + render_height_ = (panel_size.GetWidth() * image_size.GetHeight()) / + image_size.GetWidth(); + render_y_ = (panel_size.GetHeight() - render_height_) / 2; + } else { + render_width_ = (image_size.GetWidth() * panel_size.GetHeight()) / + image_size.GetHeight(); + render_x_ = (panel_size.GetWidth() - render_width_) / 2; + } + + SetZoomPos({zoom_x_, zoom_y_}); } wxBufferedPaintDC dc(this); dc.SetBackground(*wxWHITE_BRUSH); dc.Clear(); - dc.DrawBitmap(rendered_, zoom_x_, zoom_y_); + + { + wxMemoryDC rendered_dc; + rendered_dc.SelectObject(rendered_); + + int dst_x; + int dst_y; + int dst_w; + int dst_h; + int src_x; + int src_y; + int src_w; + int src_h; + + int zoomed_width = render_width_ * zoom_; + int zoomed_height = render_height_ * zoom_; + + if (zoomed_width <= GetSize().GetWidth()) { + dst_x = (GetSize().GetWidth() - zoomed_width) / 2; + dst_w = zoomed_width; + src_x = 0; + src_w = map_image_.GetWidth(); + } else { + dst_x = 0; + dst_w = GetSize().GetWidth(); + src_x = -zoom_x_ * map_image_.GetWidth() / render_width_ / zoom_; + src_w = + GetSize().GetWidth() * map_image_.GetWidth() / render_width_ / zoom_; + } + + if (zoomed_height <= GetSize().GetHeight()) { + dst_y = (GetSize().GetHeight() - zoomed_height) / 2; + dst_h = zoomed_height; + src_y = 0; + src_h = map_image_.GetHeight(); + } else { + dst_y = 0; + dst_h = GetSize().GetHeight(); + src_y = -zoom_y_ * map_image_.GetWidth() / render_width_ / zoom_; + src_h = + GetSize().GetHeight() * map_image_.GetWidth() / render_width_ / zoom_; + } + + dc.StretchBlit(dst_x, dst_y, dst_w, dst_h, &rendered_dc, src_x, src_y, + src_w, src_h); + } if (hovered_item_) { const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); @@ -320,7 +384,6 @@ void SubwayMap::OnMouseScroll(wxMouseEvent &event) { wxPoint virtual_pos = MapPosToVirtualPos(map_pos); SetZoomPos(-(virtual_pos - event.GetPosition())); - Redraw(); Refresh(); } @@ -335,29 +398,7 @@ void SubwayMap::OnTimer(wxTimerEvent &event) { } void SubwayMap::Redraw() { - wxSize panel_size = GetSize(); - wxSize image_size = map_image_.GetSize(); - - render_x_ = 0; - render_y_ = 0; - render_width_ = panel_size.GetWidth(); - render_height_ = panel_size.GetHeight(); - - if (image_size.GetWidth() * panel_size.GetHeight() > - panel_size.GetWidth() * image_size.GetHeight()) { - render_height_ = (panel_size.GetWidth() * image_size.GetHeight()) / - image_size.GetWidth(); - render_y_ = (panel_size.GetHeight() - render_height_) / 2; - } else { - render_width_ = (image_size.GetWidth() * panel_size.GetHeight()) / - image_size.GetHeight(); - render_x_ = (panel_size.GetWidth() - render_width_) / 2; - } - - rendered_ = wxBitmap(map_image_.Scale( - render_width_ * zoom_, render_height_ * zoom_, wxIMAGE_QUALITY_BILINEAR)); - - SetZoomPos({zoom_x_, zoom_y_}); + rendered_ = wxBitmap(map_image_); wxMemoryDC dc; dc.SelectObject(rendered_); @@ -413,15 +454,9 @@ void SubwayMap::Redraw() { } } - wxPoint real_area_pos = MapPosToVirtualPos({subway_item.x, subway_item.y}); + wxPoint real_area_pos = {subway_item.x, subway_item.y}; - int real_area_size = - render_width_ * zoom_ * - (draw_type == ItemDrawType::kOwl ? OWL_ACTUAL_SIZE : AREA_ACTUAL_SIZE) / - image_size.GetWidth(); - if (real_area_size == 0) { - real_area_size = 1; - } + int real_area_size = (draw_type == ItemDrawType::kOwl ? OWL_ACTUAL_SIZE : AREA_ACTUAL_SIZE); if (draw_type == ItemDrawType::kBox) { dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); -- cgit 1.4.1