diff --git a/src/gfx.cpp b/src/gfx.cpp index 95c53e6b13..1add357877 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -523,10 +523,9 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, int max_x = right; // The maximum x position to draw normal glyphs on. truncation &= max_w < w; // Whether we need to do truncation. - int dot_width = 0; // Cache for the width of the dot. - const Sprite *dot_sprite = nullptr; // Cache for the sprite of the dot. - bool dot_has_shadow = false; // Whether the dot's font requires shadows. + int truncation_width = 0; // Width of the ellipsis string. + std::optional truncation_layout; ///< Layout for truncation ellipsis. if (truncation) { /* * Assumption may be made that all fonts of a run are of the same size. @@ -534,20 +533,17 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, * another size would be chosen it won't have truncated too little for * the truncation dots. */ - FontCache *fc = line.GetVisualRun(0).GetFont()->fc; - dot_has_shadow = fc->GetDrawGlyphShadow(); - GlyphID dot_glyph = fc->MapCharToGlyph('.'); - dot_width = fc->GetGlyphWidth(dot_glyph); - dot_sprite = fc->GetGlyph(dot_glyph); + truncation_layout.emplace(GetEllipsis(), INT32_MAX, line.GetVisualRun(0).GetFont()->fc->GetSize()); + truncation_width = truncation_layout->GetBounds().width; /* Is there enough space even for an ellipsis? */ - if (max_w < dot_width * 3) return (_current_text_dir == TD_RTL) ? left : right; + if (max_w < truncation_width) return (_current_text_dir == TD_RTL) ? left : right; if (_current_text_dir == TD_RTL) { - min_x += 3 * dot_width; + min_x += truncation_width; offset_x = w - max_w; } else { - max_x -= 3 * dot_width; + max_x -= truncation_width; } w = max_w; @@ -583,9 +579,11 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, const uint shadow_offset = ScaleGUITrad(1); - /* Draw shadow, then foreground */ - for (bool do_shadow : { true, false }) { - bool colour_has_shadow = false; + auto draw_line = [&](const ParagraphLayouter::Line &line, bool do_shadow, int left, int min_x, int max_x, bool truncation) { + const DrawPixelInfo *dpi = _cur_dpi; + int dpi_left = dpi->left; + int dpi_right = dpi->left + dpi->width - 1; + for (int run_index = 0; run_index < line.CountRuns(); run_index++) { const ParagraphLayouter::VisualRun &run = line.GetVisualRun(run_index); const auto &glyphs = run.GetGlyphs(); @@ -595,22 +593,18 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, FontCache *fc = f->fc; TextColour colour = f->colour; if (colour == TC_INVALID || HasFlag(default_colour, TC_FORCED)) colour = default_colour; - colour_has_shadow = (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK; + bool colour_has_shadow = (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK; SetColourRemap(do_shadow ? TC_BLACK : colour); // the last run also sets the colour for the truncation dots if (do_shadow && (!fc->GetDrawGlyphShadow() || !colour_has_shadow)) continue; - DrawPixelInfo *dpi = _cur_dpi; - int dpi_left = dpi->left; - int dpi_right = dpi->left + dpi->width - 1; - for (int i = 0; i < run.GetGlyphCount(); i++) { GlyphID glyph = glyphs[i]; /* Not a valid glyph (empty) */ if (glyph == 0xFFFF) continue; - int begin_x = positions[i].left + left - offset_x; - int end_x = positions[i].right + left - offset_x; + int begin_x = positions[i].left + left; + int end_x = positions[i].right + left; int top = positions[i].top + y; /* Truncated away. */ @@ -625,12 +619,15 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, GfxMainBlitter(sprite, begin_x + (do_shadow ? shadow_offset : 0), top + (do_shadow ? shadow_offset : 0), BlitterMode::ColourRemap); } } + }; - if (truncation && (!do_shadow || (dot_has_shadow && colour_has_shadow))) { - int x = (_current_text_dir == TD_RTL) ? left : (right - 3 * dot_width); - for (int i = 0; i < 3; i++, x += dot_width) { - GfxMainBlitter(dot_sprite, x + (do_shadow ? shadow_offset : 0), y + (do_shadow ? shadow_offset : 0), BlitterMode::ColourRemap); - } + /* Draw shadow, then foreground */ + for (bool do_shadow : {true, false}) { + draw_line(line, do_shadow, left - offset_x, min_x, max_x, truncation); + + if (truncation) { + int x = (_current_text_dir == TD_RTL) ? left : (right - truncation_width); + draw_line(*truncation_layout->front(), do_shadow, x, INT32_MIN, INT32_MAX, false); } } diff --git a/src/lang/english.txt b/src/lang/english.txt index 5560d34b80..fd36e64c90 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -267,6 +267,7 @@ STR_UNITS_YEARS :{NUM}{NBSP}year STR_UNITS_PERIODS :{NUM}{NBSP}period{P "" s} STR_LIST_SEPARATOR :,{SPACE} +STR_TRUNCATION_ELLIPSIS :... # Common window strings STR_LIST_FILTER_TITLE :{BLACK}Filter: diff --git a/src/strings.cpp b/src/strings.cpp index c327615485..d33535ba92 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -286,6 +286,7 @@ struct LoadedLanguagePack { std::array langtab_start; ///< Offset into langpack offs std::string list_separator; ///< Current list separator string. + std::string ellipsis; ///< Current ellipsis string. }; static LoadedLanguagePack _langpack; @@ -301,6 +302,15 @@ std::string_view GetListSeparator() return _langpack.list_separator; } +/** + * Get the ellipsis string for the current language. + * @returns string containing ellipsis to use. + */ +std::string_view GetEllipsis() +{ + return _langpack.ellipsis; +} + std::string_view GetStringPtr(StringID string) { switch (GetStringTab(string)) { @@ -2063,6 +2073,7 @@ bool ReadLanguagePack(const LanguageMetadata *lang) _config_language_file = FS2OTTD(_current_language->file.filename().native()); SetCurrentGrfLangID(_current_language->newgrflangid); _langpack.list_separator = GetString(STR_LIST_SEPARATOR); + _langpack.ellipsis = GetString(STR_TRUNCATION_ELLIPSIS); #ifdef _WIN32 extern void Win32SetCurrentLocaleName(std::string iso_code); diff --git a/src/strings_func.h b/src/strings_func.h index f813dc0fb5..7bb9ae99ff 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -98,6 +98,7 @@ extern TextDirection _current_text_dir; ///< Text direction of the currently sel void InitializeLanguagePacks(); std::string_view GetCurrentLanguageIsoCode(); std::string_view GetListSeparator(); +std::string_view GetEllipsis(); /** * Helper to create the StringParameters with its own buffer with the given