mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-19 04:29:09 +00:00
Compare commits
2 Commits
605dff4920
...
f220ed179d
Author | SHA1 | Date | |
---|---|---|---|
f220ed179d | |||
3d4b98845a |
@@ -35,7 +35,7 @@ static int ScaleFontTrad(int value)
|
||||
* Create a new sprite font cache.
|
||||
* @param fs The font size to create the cache for.
|
||||
*/
|
||||
SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs), glyph_to_spriteid_map(nullptr)
|
||||
SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs)
|
||||
{
|
||||
this->InitializeUnicodeGlyphMap();
|
||||
this->height = ScaleGUITrad(FontCache::GetDefaultFontHeight(this->fs));
|
||||
@@ -43,30 +43,26 @@ SpriteFontCache::SpriteFontCache(FontSize fs) : FontCache(fs), glyph_to_spriteid
|
||||
}
|
||||
|
||||
/**
|
||||
* Free everything we allocated.
|
||||
* Get SpriteID associated with a GlyphID.
|
||||
* @param key Glyph to find.
|
||||
* @return SpriteID of glyph, or 0 if not present.
|
||||
*/
|
||||
SpriteFontCache::~SpriteFontCache()
|
||||
SpriteID SpriteFontCache::GetUnicodeGlyph(GlyphID key)
|
||||
{
|
||||
this->ClearGlyphToSpriteMap();
|
||||
}
|
||||
|
||||
SpriteID SpriteFontCache::GetUnicodeGlyph(char32_t key)
|
||||
{
|
||||
if (this->glyph_to_spriteid_map[GB(key, 8, 8)] == nullptr) return 0;
|
||||
return this->glyph_to_spriteid_map[GB(key, 8, 8)][GB(key, 0, 8)];
|
||||
const auto found = this->glyph_to_spriteid_map.find(key & ~SPRITE_GLYPH);
|
||||
if (found == std::end(this->glyph_to_spriteid_map)) return 0;
|
||||
return found->second;
|
||||
}
|
||||
|
||||
void SpriteFontCache::SetUnicodeGlyph(char32_t key, SpriteID sprite)
|
||||
{
|
||||
if (this->glyph_to_spriteid_map == nullptr) this->glyph_to_spriteid_map = CallocT<SpriteID*>(256);
|
||||
if (this->glyph_to_spriteid_map[GB(key, 8, 8)] == nullptr) this->glyph_to_spriteid_map[GB(key, 8, 8)] = CallocT<SpriteID>(256);
|
||||
this->glyph_to_spriteid_map[GB(key, 8, 8)][GB(key, 0, 8)] = sprite;
|
||||
this->glyph_to_spriteid_map[key] = sprite;
|
||||
}
|
||||
|
||||
void SpriteFontCache::InitializeUnicodeGlyphMap()
|
||||
{
|
||||
/* Clear out existing glyph map if it exists */
|
||||
this->ClearGlyphToSpriteMap();
|
||||
this->glyph_to_spriteid_map.clear();
|
||||
|
||||
SpriteID base;
|
||||
switch (this->fs) {
|
||||
@@ -98,20 +94,6 @@ void SpriteFontCache::InitializeUnicodeGlyphMap()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the glyph to sprite mapping.
|
||||
*/
|
||||
void SpriteFontCache::ClearGlyphToSpriteMap()
|
||||
{
|
||||
if (this->glyph_to_spriteid_map == nullptr) return;
|
||||
|
||||
for (uint i = 0; i < 256; i++) {
|
||||
free(this->glyph_to_spriteid_map[i]);
|
||||
}
|
||||
free(this->glyph_to_spriteid_map);
|
||||
this->glyph_to_spriteid_map = nullptr;
|
||||
}
|
||||
|
||||
void SpriteFontCache::ClearFontCache()
|
||||
{
|
||||
Layouter::ResetFontCache(this->fs);
|
||||
@@ -121,14 +103,14 @@ void SpriteFontCache::ClearFontCache()
|
||||
|
||||
const Sprite *SpriteFontCache::GetGlyph(GlyphID key)
|
||||
{
|
||||
SpriteID sprite = this->GetUnicodeGlyph(key);
|
||||
SpriteID sprite = this->GetUnicodeGlyph(static_cast<char32_t>(key & ~SPRITE_GLYPH));
|
||||
if (sprite == 0) sprite = this->GetUnicodeGlyph('?');
|
||||
return GetSprite(sprite, SpriteType::Font);
|
||||
}
|
||||
|
||||
uint SpriteFontCache::GetGlyphWidth(GlyphID key)
|
||||
{
|
||||
SpriteID sprite = this->GetUnicodeGlyph(key);
|
||||
SpriteID sprite = this->GetUnicodeGlyph(static_cast<char32_t>(key & ~SPRITE_GLYPH));
|
||||
if (sprite == 0) sprite = this->GetUnicodeGlyph('?');
|
||||
return SpriteExists(sprite) ? GetSprite(sprite, SpriteType::Font)->width + ScaleFontTrad(this->fs != FS_NORMAL ? 1 : 0) : 0;
|
||||
}
|
||||
|
@@ -15,14 +15,8 @@
|
||||
|
||||
/** Font cache for fonts that are based on a freetype font. */
|
||||
class SpriteFontCache : public FontCache {
|
||||
private:
|
||||
SpriteID **glyph_to_spriteid_map; ///< Mapping of glyphs to sprite IDs.
|
||||
SpriteID GetUnicodeGlyph(char32_t key);
|
||||
|
||||
void ClearGlyphToSpriteMap();
|
||||
public:
|
||||
SpriteFontCache(FontSize fs);
|
||||
~SpriteFontCache();
|
||||
void SetUnicodeGlyph(char32_t key, SpriteID sprite) override;
|
||||
void InitializeUnicodeGlyphMap() override;
|
||||
void ClearFontCache() override;
|
||||
@@ -32,6 +26,10 @@ public:
|
||||
GlyphID MapCharToGlyph(char32_t key, [[maybe_unused]] bool allow_fallback = true) override { assert(IsPrintable(key)); return SPRITE_GLYPH | key; }
|
||||
std::string GetFontName() override { return "sprite"; }
|
||||
bool IsBuiltInFont() override { return true; }
|
||||
|
||||
private:
|
||||
std::unordered_map<GlyphID, SpriteID> glyph_to_spriteid_map{}; ///< Mapping of glyphs to sprite IDs.
|
||||
SpriteID GetUnicodeGlyph(GlyphID key);
|
||||
};
|
||||
|
||||
#endif /* SPRITEFONTCACHE_H */
|
||||
|
20
src/gfx.cpp
20
src/gfx.cpp
@@ -491,11 +491,12 @@ static void SetColourRemap(TextColour colour)
|
||||
* will be drawn in the right direction.
|
||||
* @param underline Whether to underline what has been drawn or not.
|
||||
* @param truncation Whether to perform string truncation or not.
|
||||
* @param default_colour Colour of text if not specified within string.
|
||||
*
|
||||
* @return In case of left or center alignment the right most pixel we have drawn to.
|
||||
* In case of right alignment the left most pixel we have drawn to.
|
||||
*/
|
||||
static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, int right, StringAlignment align, bool underline, bool truncation)
|
||||
static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, int right, StringAlignment align, bool underline, bool truncation, TextColour default_colour)
|
||||
{
|
||||
if (line.CountRuns() == 0) return 0;
|
||||
|
||||
@@ -589,6 +590,7 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
|
||||
|
||||
FontCache *fc = f->fc;
|
||||
TextColour colour = f->colour;
|
||||
if (colour == TC_INVALID) colour = default_colour;
|
||||
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;
|
||||
@@ -665,10 +667,10 @@ int DrawString(int left, int right, int top, std::string_view str, TextColour co
|
||||
return 0;
|
||||
}
|
||||
|
||||
Layouter layout(str, INT32_MAX, colour, fontsize);
|
||||
Layouter layout(str, INT32_MAX, fontsize);
|
||||
if (layout.empty()) return 0;
|
||||
|
||||
return DrawLayoutLine(*layout.front(), top, left, right, align, underline, true);
|
||||
return DrawLayoutLine(*layout.front(), top, left, right, align, underline, true, colour);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -702,7 +704,7 @@ int DrawString(int left, int right, int top, StringID str, TextColour colour, St
|
||||
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
|
||||
{
|
||||
assert(maxw > 0);
|
||||
Layouter layout(str, maxw, TC_FROMSTRING, fontsize);
|
||||
Layouter layout(str, maxw, fontsize);
|
||||
return layout.GetBounds().height;
|
||||
}
|
||||
|
||||
@@ -778,7 +780,7 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_vi
|
||||
* do we really want to support fonts of 0 or less pixels high? */
|
||||
if (maxh <= 0) return top;
|
||||
|
||||
Layouter layout(str, maxw, colour, fontsize);
|
||||
Layouter layout(str, maxw, fontsize);
|
||||
int total_height = layout.GetBounds().height;
|
||||
int y;
|
||||
switch (align & SA_VERT_MASK) {
|
||||
@@ -807,7 +809,7 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_vi
|
||||
last_line = y + line_height;
|
||||
if (first_line > y) first_line = y;
|
||||
|
||||
DrawLayoutLine(*line, y, left, right, align, underline, false);
|
||||
DrawLayoutLine(*line, y, left, right, align, underline, false, colour);
|
||||
}
|
||||
y += line_height;
|
||||
}
|
||||
@@ -848,7 +850,7 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str,
|
||||
*/
|
||||
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
|
||||
{
|
||||
Layouter layout(str, INT32_MAX, TC_FROMSTRING, start_fontsize);
|
||||
Layouter layout(str, INT32_MAX, start_fontsize);
|
||||
return layout.GetBounds();
|
||||
}
|
||||
|
||||
@@ -907,7 +909,7 @@ Point GetCharPosInString(std::string_view str, const char *ch, FontSize start_fo
|
||||
assert(ch >= str.data() && (ch - str.data()) <= static_cast<ptrdiff_t>(str.size()));
|
||||
auto it_ch = str.begin() + (ch - str.data());
|
||||
|
||||
Layouter layout(str, INT32_MAX, TC_FROMSTRING, start_fontsize);
|
||||
Layouter layout(str, INT32_MAX, start_fontsize);
|
||||
return layout.GetCharPosition(it_ch);
|
||||
}
|
||||
|
||||
@@ -922,7 +924,7 @@ ptrdiff_t GetCharAtPosition(std::string_view str, int x, FontSize start_fontsize
|
||||
{
|
||||
if (x < 0) return -1;
|
||||
|
||||
Layouter layout(str, INT32_MAX, TC_FROMSTRING, start_fontsize);
|
||||
Layouter layout(str, INT32_MAX, start_fontsize);
|
||||
return layout.GetCharAtPosition(x, 0);
|
||||
}
|
||||
|
||||
|
@@ -125,12 +125,11 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, std::string_view s
|
||||
* Create a new layouter.
|
||||
* @param str The string to create the layout for.
|
||||
* @param maxw The maximum width.
|
||||
* @param colour The colour of the font.
|
||||
* @param fontsize The size of font to use.
|
||||
*/
|
||||
Layouter::Layouter(std::string_view str, int maxw, TextColour colour, FontSize fontsize) : string(str)
|
||||
Layouter::Layouter(std::string_view str, int maxw, FontSize fontsize) : string(str)
|
||||
{
|
||||
FontState state(colour, fontsize);
|
||||
FontState state(TC_INVALID, fontsize);
|
||||
|
||||
while (true) {
|
||||
auto line_length = str.find_first_of('\n');
|
||||
|
@@ -36,7 +36,7 @@ struct FontState {
|
||||
*/
|
||||
inline void SetColour(TextColour c)
|
||||
{
|
||||
assert((c & TC_COLOUR_MASK) >= TC_BLUE && (c & TC_COLOUR_MASK) <= TC_BLACK);
|
||||
assert(((c & TC_COLOUR_MASK) >= TC_BLUE && (c & TC_COLOUR_MASK) <= TC_BLACK) || (c & TC_COLOUR_MASK) == TC_INVALID);
|
||||
assert((c & (TC_COLOUR_MASK | TC_FLAGS_MASK)) == c);
|
||||
if ((this->cur_colour & TC_FORCED) == 0) this->cur_colour = c;
|
||||
}
|
||||
@@ -174,7 +174,7 @@ private:
|
||||
public:
|
||||
static Font *GetFont(FontSize size, TextColour colour);
|
||||
|
||||
Layouter(std::string_view str, int maxw = INT32_MAX, TextColour colour = TC_FROMSTRING, FontSize fontsize = FS_NORMAL);
|
||||
Layouter(std::string_view str, int maxw = INT32_MAX, FontSize fontsize = FS_NORMAL);
|
||||
Dimension GetBounds();
|
||||
Point GetCharPosition(std::string_view::const_iterator ch) const;
|
||||
ptrdiff_t GetCharAtPosition(int x, size_t line_index) const;
|
||||
|
@@ -331,7 +331,7 @@ void TextfileWindow::CheckHyperlinkClick(Point pt)
|
||||
|
||||
/* Build line layout to figure out character position that was clicked. */
|
||||
uint window_width = IsWidgetLowered(WID_TF_WRAPTEXT) ? this->GetWidget<NWidgetCore>(WID_TF_BACKGROUND)->current_x - WidgetDimensions::scaled.frametext.Horizontal() : INT_MAX;
|
||||
Layouter layout(this->lines[line_index].text, window_width, this->lines[line_index].colour, FS_MONO);
|
||||
Layouter layout(this->lines[line_index].text, window_width, FS_MONO);
|
||||
assert(subline < layout.size());
|
||||
ptrdiff_t char_index = layout.GetCharAtPosition(pt.x - WidgetDimensions::scaled.frametext.left, subline);
|
||||
if (char_index < 0) return;
|
||||
|
Reference in New Issue
Block a user