Fix: Viewport signs assume small font is smaller than normal font. (#12422)

If the small font is set to a larger size than the normal font for some reason, viewport signs would be drawn incorrect as the area marked dirty only considered the normal size font.
This commit is contained in:
Peter Nelson 2024-04-06 19:29:41 +01:00 committed by GitHub
parent 830c9e2de8
commit b905209421
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 15 additions and 12 deletions

View File

@ -1314,7 +1314,7 @@ void ViewportAddString(const DrawPixelInfo *dpi, ZoomLevel small_from, const Vie
int right = left + dpi->width;
int bottom = top + dpi->height;
int sign_height = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom, dpi->zoom);
int sign_height = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + GetCharacterHeight(small ? FS_SMALL : FS_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom, dpi->zoom);
int sign_half_width = ScaleByZoom((small ? sign->width_small : sign->width_normal) / 2, dpi->zoom);
if (bottom < sign->top ||
@ -1338,8 +1338,7 @@ void ViewportAddString(const DrawPixelInfo *dpi, ZoomLevel small_from, const Vie
static Rect ExpandRectWithViewportSignMargins(Rect r, ZoomLevel zoom)
{
/* Pessimistically always use normal font, but also assume small font is never larger in either dimension */
const int fh = GetCharacterHeight(FS_NORMAL);
const int fh = std::max(GetCharacterHeight(FS_NORMAL), GetCharacterHeight(FS_SMALL));
const int max_tw = _viewport_sign_maxwidth / 2 + 1;
const int expand_y = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + fh + WidgetDimensions::scaled.fullbevel.bottom, zoom);
const int expand_x = ScaleByZoom(WidgetDimensions::scaled.fullbevel.left + max_tw + WidgetDimensions::scaled.fullbevel.right, zoom);
@ -1490,12 +1489,16 @@ void ViewportSign::MarkDirty(ZoomLevel maxzoom) const
{
Rect zoomlevels[ZOOM_LVL_END];
/* We don't know which size will be drawn, so mark the largest area dirty. */
const uint half_width = std::max(this->width_normal, this->width_small) / 2 + 1;
const uint height = WidgetDimensions::scaled.fullbevel.top + std::max(GetCharacterHeight(FS_NORMAL), GetCharacterHeight(FS_SMALL)) + WidgetDimensions::scaled.fullbevel.bottom + 1;
for (ZoomLevel zoom = ZOOM_LVL_BEGIN; zoom != ZOOM_LVL_END; zoom++) {
/* FIXME: This doesn't switch to width_small when appropriate. */
zoomlevels[zoom].left = this->center - ScaleByZoom(this->width_normal / 2 + 1, zoom);
zoomlevels[zoom].left = this->center - ScaleByZoom(half_width, zoom);
zoomlevels[zoom].top = this->top - ScaleByZoom(1, zoom);
zoomlevels[zoom].right = this->center + ScaleByZoom(this->width_normal / 2 + 1, zoom);
zoomlevels[zoom].bottom = this->top + ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom + 1, zoom);
zoomlevels[zoom].right = this->center + ScaleByZoom(half_width, zoom);
zoomlevels[zoom].bottom = this->top + ScaleByZoom(height, zoom);
}
for (const Window *w : Window::Iterate()) {
@ -1709,7 +1712,7 @@ static void ViewportDrawStrings(ZoomLevel zoom, const StringSpriteToDrawVector *
int w = GB(ss.width, 0, 15);
int x = UnScaleByZoom(ss.x, zoom);
int y = UnScaleByZoom(ss.y, zoom);
int h = WidgetDimensions::scaled.fullbevel.top + (small ? GetCharacterHeight(FS_SMALL) : GetCharacterHeight(FS_NORMAL)) + WidgetDimensions::scaled.fullbevel.bottom;
int h = WidgetDimensions::scaled.fullbevel.top + GetCharacterHeight(small ? FS_SMALL : FS_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom;
if (ss.colour != INVALID_COLOUR) {
if (IsTransparencySet(TO_SIGNS) && ss.string_id != STR_WHITE_SIGN) {
@ -2194,7 +2197,7 @@ static bool CheckClickOnViewportSign(const Viewport *vp, int x, int y, const Vie
{
bool small = (vp->zoom >= ZOOM_LVL_OUT_4X);
int sign_half_width = ScaleByZoom((small ? sign->width_small : sign->width_normal) / 2, vp->zoom);
int sign_height = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + (small ? GetCharacterHeight(FS_SMALL) : GetCharacterHeight(FS_NORMAL)) + WidgetDimensions::scaled.fullbevel.bottom, vp->zoom);
int sign_height = ScaleByZoom(WidgetDimensions::scaled.fullbevel.top + GetCharacterHeight(small ? FS_SMALL : FS_NORMAL) + WidgetDimensions::scaled.fullbevel.bottom, vp->zoom);
return y >= sign->top && y < sign->top + sign_height &&
x >= sign->center - sign_half_width && x < sign->center + sign_half_width;
@ -2296,7 +2299,7 @@ ViewportSignKdtreeItem ViewportSignKdtreeItem::MakeStation(StationID id)
item.top = st->sign.top;
/* Assume the sign can be a candidate for drawing, so measure its width */
_viewport_sign_maxwidth = std::max<int>(_viewport_sign_maxwidth, st->sign.width_normal);
_viewport_sign_maxwidth = std::max<int>({_viewport_sign_maxwidth, st->sign.width_normal, st->sign.width_small});
return item;
}
@ -2313,7 +2316,7 @@ ViewportSignKdtreeItem ViewportSignKdtreeItem::MakeWaypoint(StationID id)
item.top = st->sign.top;
/* Assume the sign can be a candidate for drawing, so measure its width */
_viewport_sign_maxwidth = std::max<int>(_viewport_sign_maxwidth, st->sign.width_normal);
_viewport_sign_maxwidth = std::max<int>({_viewport_sign_maxwidth, st->sign.width_normal, st->sign.width_small});
return item;
}
@ -2330,7 +2333,7 @@ ViewportSignKdtreeItem ViewportSignKdtreeItem::MakeTown(TownID id)
item.top = town->cache.sign.top;
/* Assume the sign can be a candidate for drawing, so measure its width */
_viewport_sign_maxwidth = std::max<int>(_viewport_sign_maxwidth, town->cache.sign.width_normal);
_viewport_sign_maxwidth = std::max<int>({_viewport_sign_maxwidth, town->cache.sign.width_normal, town->cache.sign.width_small});
return item;
}
@ -2347,7 +2350,7 @@ ViewportSignKdtreeItem ViewportSignKdtreeItem::MakeSign(SignID id)
item.top = sign->sign.top;
/* Assume the sign can be a candidate for drawing, so measure its width */
_viewport_sign_maxwidth = std::max<int>(_viewport_sign_maxwidth, sign->sign.width_normal);
_viewport_sign_maxwidth = std::max<int>({_viewport_sign_maxwidth, sign->sign.width_normal, sign->sign.width_small});
return item;
}