OpenTTD Source 20260531-master-g0e951f3528
gfx_layout.h
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#ifndef GFX_LAYOUT_H
11#define GFX_LAYOUT_H
12
13#include "misc/lrucache.hpp"
14#include "fontcache.h"
15#include "gfx_func.h"
16#include "core/math_func.hpp"
17
18#include <string_view>
19
24struct FontState {
27 std::vector<ExtendedTextColour> colour_stack;
28
37
38 auto operator<=>(const FontState &) const = default;
39
45 {
48 if (!this->cur_colour.flags.Test(ExtendedTextColourFlag::Forced)) this->cur_colour = c;
49 }
50
54 inline void PopColour()
55 {
56 if (colour_stack.empty()) return;
57 SetColour(colour_stack.back());
58 colour_stack.pop_back();
59 }
60
64 inline void PushColour()
65 {
66 colour_stack.push_back(this->cur_colour);
67 }
68
73 inline void SetFontSize(FontSize f)
74 {
75 this->fontsize = f;
76 }
77};
78
79template <typename T> struct std::hash<std::vector<T>> {
80 size_t operator()(const std::vector<T> &vec) const
81 {
82 /* This is not an optimal hash algorithm but in most cases this is empty and therefore the same anyway. */
83 return std::transform_reduce(std::begin(vec), std::end(vec),
84 std::hash<size_t>{}(std::size(vec)),
85 [](const size_t &a, const size_t &b) -> size_t { return a ^ b; },
86 [](const T &x) -> size_t { return std::hash<T>{}(x); });
87 }
88};
89
91template <> struct std::hash<ExtendedTextColour> {
97 std::size_t operator()(const ExtendedTextColour &tc) const noexcept
98 {
99 size_t h1 = std::hash<TextColour>{}(tc.colour);
100 size_t h2 = std::hash<uint8_t>{}(tc.flags.base());
101 return h1 ^ (h2 << 1);
102 }
103};
104
105template <> struct std::hash<FontState> {
106 std::size_t operator()(const FontState &state) const noexcept
107 {
108 size_t h1 = std::hash<FontSize>{}(state.fontsize);
109 size_t h2 = std::hash<ExtendedTextColour>{}(state.cur_colour);
110 size_t h3 = std::hash<std::vector<ExtendedTextColour>>{}(state.colour_stack);
111 return h1 ^ (h2 << 1) ^ (h3 << 2);
112 }
113};
114
125
127using FontMap = std::vector<std::pair<int, Font *>>;
128
133public:
135 virtual ~ParagraphLayouter() = default;
136
138 class Position {
139 public:
140 int16_t left;
141 int16_t right;
142 int16_t top;
143
144 constexpr inline Position(int16_t left, int16_t right, int16_t top) : left(left), right(right), top(top) { }
145
150 constexpr inline Position(const Point &pt) : left(pt.x), right(pt.x), top(pt.y) { }
151 };
152
154 class VisualRun {
155 public:
157 virtual ~VisualRun() = default;
158
163 virtual const Font *GetFont() const = 0;
164
169 virtual size_t GetGlyphCount() const = 0;
170
175 virtual std::span<const GlyphID> GetGlyphs() const = 0;
176
181 virtual std::span<const Position> GetPositions() const = 0;
182
187 virtual int GetLeading() const = 0;
188
193 virtual std::span<const int> GetGlyphToCharMap() const = 0;
194 };
195
197 class Line {
198 public:
200 virtual ~Line() = default;
201
206 virtual int GetLeading() const = 0;
207
212 virtual int GetWidth() const = 0;
213
218 virtual size_t CountRuns() const = 0;
219
225 virtual const VisualRun &GetVisualRun(size_t run) const = 0;
226
233 virtual int GetInternalCharLength(char32_t c) const = 0;
234 };
235
239 virtual void Reflow() = 0;
240
246 virtual std::unique_ptr<const Line> NextLine(int max_width) = 0;
247};
248
254class Layouter : public std::vector<const ParagraphLayouter::Line *> {
255 std::string_view string;
256
260 std::string str;
261 };
262
265 std::string_view str;
266 };
267
268 friend struct std::hash<Layouter::LineCacheQuery>;
269 struct LineCacheHash;
270
272 using is_transparent = void;
273
274 template <typename Tlhs, typename Trhs>
275 bool operator()(const Tlhs &lhs, const Trhs &rhs) const
276 {
277 return lhs.state_before == rhs.state_before && lhs.str == rhs.str;
278 }
279 };
280
281public:
285 using Buffer = std::unique_ptr<void, void(*)(void *)>;
286 /* Stuff that cannot be freed until the ParagraphLayout is freed */
287 Buffer buffer{nullptr, [](void *){}};
289
291 std::unique_ptr<ParagraphLayouter> layout = nullptr;
292
293 std::vector<std::unique_ptr<const ParagraphLayouter::Line>> cached_layout{};
294 int cached_width = 0;
295 };
296private:
298 static std::unique_ptr<LineCache> linecache;
299
300 static LineCacheItem &GetCachedParagraphLayout(std::string_view str, const FontState &state);
301
302 using FontColourMap = std::map<ExtendedTextColour, std::unique_ptr<Font>>;
304public:
305 static Font *GetFont(FontSize size, ExtendedTextColour colour);
306
307 Layouter(std::string_view str, int maxw = INT32_MAX, FontSize fontsize = FontSize::Normal);
309 ParagraphLayouter::Position GetCharPosition(std::string_view::const_iterator ch) const;
310 ptrdiff_t GetCharAtPosition(int x, size_t line_index) const;
311
312 static void Initialize();
313 static void ResetFontCache(FontSize size);
314 static void ResetLineCache();
315};
316
317ParagraphLayouter::Position GetCharPosInString(std::string_view str, size_t pos, FontSize start_fontsize = FontSize::Normal);
318ptrdiff_t GetCharAtPosition(std::string_view str, int x, FontSize start_fontsize = FontSize::Normal);
319
320template <> struct std::hash<Layouter::LineCacheQuery> {
321 std::size_t operator()(const Layouter::LineCacheQuery &state) const noexcept
322 {
323 size_t h1 = std::hash<std::string_view>{}(state.str);
324 size_t h2 = std::hash<FontState>{}(state.state_before);
325 return h1 ^ (h2 << 1);
326 }
327};
328
330 using is_transparent = void;
331
332 std::size_t operator()(const Layouter::LineCacheKey &query) const { return std::hash<Layouter::LineCacheQuery>{}(LineCacheQuery{query.state_before, query.str}); }
333 std::size_t operator()(const Layouter::LineCacheQuery &query) const { return std::hash<Layouter::LineCacheQuery>{}(query); }
334};
335
336#endif /* GFX_LAYOUT_H */
@ Invalid
Invalid town production effect.
Definition cargotype.h:46
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Font cache for basic fonts.
Definition fontcache.h:23
Container with information about a font.
Definition gfx_layout.h:118
ExtendedTextColour colour
The colour this font has to be.
Definition gfx_layout.h:121
FontCache * fc
The font we are using.
Definition gfx_layout.h:120
Font(FontSize size, ExtendedTextColour colour)
Construct a new font.
Size limited cache with a least recently used eviction strategy.
Definition lrucache.hpp:23
The layouter performs all the layout work.
Definition gfx_layout.h:254
Layouter(std::string_view str, int maxw=INT32_MAX, FontSize fontsize=FontSize::Normal)
Create a new layouter.
static EnumIndexArray< FontColourMap, FontSize, FontSize::End > fonts
The colour mapping of each of the fonts.
Definition gfx_layout.h:303
static void Initialize()
Perform initialization of layout engine.
ptrdiff_t GetCharAtPosition(int x, size_t line_index) const
Get the character that is at a pixel position in the first line of the layouted text.
static void ResetFontCache(FontSize size)
Reset cached font information.
static Font * GetFont(FontSize size, ExtendedTextColour colour)
Get a static font instance.
ParagraphLayouter::Position GetCharPosition(std::string_view::const_iterator ch) const
Get the position of a character in the layout.
static std::unique_ptr< LineCache > linecache
Cache of ParagraphLayout lines.
Definition gfx_layout.h:298
std::string_view string
Pointer to the original string.
Definition gfx_layout.h:255
static void ResetLineCache()
Clear line cache.
Dimension GetBounds()
Get the boundaries of this paragraph.
static LineCacheItem & GetCachedParagraphLayout(std::string_view str, const FontState &state)
Get reference to cache item.
A single line worth of VisualRuns.
Definition gfx_layout.h:197
virtual int GetLeading() const =0
Get the font leading, or distance between the baselines of consecutive lines.
virtual int GetInternalCharLength(char32_t c) const =0
Get the number of elements the given character occupies in the underlying text buffer of the Layouter...
virtual const VisualRun & GetVisualRun(size_t run) const =0
Get a reference to the given run.
virtual ~Line()=default
Ensure the destructor of the sub classes are called as well.
virtual int GetWidth() const =0
Get the width of this line.
virtual size_t CountRuns() const =0
Get the number of runs in this line.
Position of a glyph within a VisualRun.
Definition gfx_layout.h:138
int16_t right
Right-most position of glyph.
Definition gfx_layout.h:141
constexpr Position(const Point &pt)
Conversion from a single point to a Position.
Definition gfx_layout.h:150
int16_t left
Left-most position of glyph.
Definition gfx_layout.h:140
int16_t top
Top-most position of glyph.
Definition gfx_layout.h:142
Visual run contains data about the bit of text with the same font.
Definition gfx_layout.h:154
virtual std::span< const GlyphID > GetGlyphs() const =0
Get the glyphs to draw.
virtual int GetLeading() const =0
Get the font leading, or distance between the baselines of consecutive lines.
virtual std::span< const int > GetGlyphToCharMap() const =0
The offset for each of the glyphs to the character run that was passed to the Layouter.
virtual std::span< const Position > GetPositions() const =0
Get the positions for each of the glyphs.
virtual const Font * GetFont() const =0
Get the font.
virtual size_t GetGlyphCount() const =0
Get the number of glyphs.
virtual ~VisualRun()=default
Ensure the destructor of the sub classes are called as well.
Interface to glue fallback and normal layouter into one.
Definition gfx_layout.h:132
virtual std::unique_ptr< const Line > NextLine(int max_width)=0
Construct a new line with a maximum width.
virtual void Reflow()=0
Reset the position to the start of the paragraph.
virtual ~ParagraphLayouter()=default
Ensure the destructor of the sub classes are called as well.
#define T
Climate temperate.
Definition engines.h:91
EnumClassIndexContainer< std::array< T, to_underlying(N)>, Index > EnumIndexArray
A typedef for EnumClassIndexContainer using std::array as the backing container type.
Functions to read fonts from files and cache them.
Functions related to the gfx engine.
ptrdiff_t GetCharAtPosition(std::string_view str, int x, FontSize start_fontsize=FontSize::Normal)
Get the character from a string that is drawn at a specific position.
std::vector< std::pair< int, Font * > > FontMap
Mapping from index to font.
Definition gfx_layout.h:127
ParagraphLayouter::Position GetCharPosInString(std::string_view str, size_t pos, FontSize start_fontsize=FontSize::Normal)
Get the leading corner of a character in a single-line string relative to the start of the string.
FontSize
Available font sizes.
Definition gfx_type.h:248
@ Normal
Index of the normal font in the font tables.
Definition gfx_type.h:249
@ IsPaletteColour
Colour value is already a real palette colour index, not an index of a StringColour.
Definition gfx_type.h:341
@ Forced
Ignore colour changes from strings.
Definition gfx_type.h:343
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
Definition gfx_type.h:315
@ Begin
Marker for the begin of the range.
Definition gfx_type.h:316
@ Invalid
Invalid colour.
Definition gfx_type.h:336
@ End
Marker for the end of the range.
Definition gfx_type.h:335
Size limited cache map with a least recently used eviction strategy.
#define Point
Macro that prevents name conflicts between included headers.
Integer math functions.
Dimensions (a width and height) of a rectangle in 2D.
Container for the text colour and some text colour related flags for drawing.
Definition gfx_type.h:348
ExtendedTextColourFlags flags
The flags.
Definition gfx_type.h:363
TextColour colour
The colour.
Definition gfx_type.h:362
Text drawing parameters, which can change while drawing a line, but are kept between multiple parts o...
Definition gfx_layout.h:24
std::vector< ExtendedTextColour > colour_stack
Stack of colours to assist with colour switching.
Definition gfx_layout.h:27
void PushColour()
Push the current colour on to the stack.
Definition gfx_layout.h:64
FontState()
Create the font state with an invalid state.
Definition gfx_layout.h:30
void PopColour()
Switch to and pop the last saved colour on the stack.
Definition gfx_layout.h:54
void SetColour(ExtendedTextColour c)
Switch to new colour c.
Definition gfx_layout.h:44
ExtendedTextColour cur_colour
Current text colour.
Definition gfx_layout.h:26
void SetFontSize(FontSize f)
Switch to using a new font f.
Definition gfx_layout.h:73
FontState(ExtendedTextColour colour, FontSize fontsize)
Create the font state.
Definition gfx_layout.h:36
FontSize fontsize
Current font size.
Definition gfx_layout.h:25
Item in the linecache.
Definition gfx_layout.h:283
FontMap runs
Accessed by our ParagraphLayout::nextLine.
Definition gfx_layout.h:288
Buffer buffer
Accessed by our ParagraphLayout::nextLine.
Definition gfx_layout.h:287
int cached_width
Width used for the cached layout.
Definition gfx_layout.h:294
std::vector< std::unique_ptr< const ParagraphLayouter::Line > > cached_layout
Cached results of line layouting.
Definition gfx_layout.h:293
FontState state_after
Font state after the line.
Definition gfx_layout.h:290
std::unique_ptr< void, void(*)(void *)> Buffer
Due to the type of data in the buffer differing depending on the Layouter, we need to pass our own de...
Definition gfx_layout.h:285
std::unique_ptr< ParagraphLayouter > layout
Layout of the line.
Definition gfx_layout.h:291
Key into the linecache.
Definition gfx_layout.h:258
FontState state_before
Font state at the beginning of the line.
Definition gfx_layout.h:259
std::string str
Source string of the line (including colour and font size codes).
Definition gfx_layout.h:260
const FontState & state_before
Font state at the beginning of the line.
Definition gfx_layout.h:264
std::string_view str
Source string of the line (including colour and font size codes).
Definition gfx_layout.h:265
std::size_t operator()(const ExtendedTextColour &tc) const noexcept
Hash the text colour.
Definition gfx_layout.h:97
@ End
End marker.
Definition vehicle.cpp:2829