1 /* Font.h
2 Copyright (c) 2014-2020 by Michael Zahniser
3 
4 Endless Sky is free software: you can redistribute it and/or modify it under the
5 terms of the GNU General Public License as published by the Free Software
6 Foundation, either version 3 of the License, or (at your option) any later version.
7 
8 Endless Sky is distributed in the hope that it will be useful, but WITHOUT ANY
9 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10 PARTICULAR PURPOSE.  See the GNU General Public License for more details.
11 */
12 
13 #ifndef ES_TEXT_FONT_H_
14 #define ES_TEXT_FONT_H_
15 
16 #include "../Shader.h"
17 
18 #include "../gl_header.h"
19 
20 #include <string>
21 
22 class Color;
23 class DisplayText;
24 class ImageBuffer;
25 class Point;
26 
27 
28 
29 // Class for drawing text in OpenGL. Each font is based on a single image with
30 // glyphs for each character in ASCII order (not counting control characters).
31 // The kerning between characters is automatically adjusted to look good. At the
32 // moment only plain ASCII characters are supported, not Unicode.
33 class Font {
34 public:
35 	Font() noexcept = default;
36 	explicit Font(const std::string &imagePath);
37 
38 	void Load(const std::string &imagePath);
39 
40 	// Draw a text string, subject to the given layout and truncation strategy.
41 	void Draw(const DisplayText &text, const Point &point, const Color &color) const;
42 	void DrawAliased(const DisplayText &text, double x, double y, const Color &color) const;
43 	// Draw the given text string, e.g. post-formatting (or without regard to formatting).
44 	void Draw(const std::string &str, const Point &point, const Color &color) const;
45 	void DrawAliased(const std::string &str, double x, double y, const Color &color) const;
46 
47 	// Determine the string's width, without considering formatting.
48 	int Width(const std::string &str, char after = ' ') const;
49 	// Get the width of the text while accounting for the desired layout and truncation strategy.
50 	int FormattedWidth(const DisplayText &text, char after = ' ') const;
51 
52 	int Height() const noexcept;
53 
54 	int Space() const noexcept;
55 
56 	static void ShowUnderlines(bool show) noexcept;
57 
58 
59 private:
60 	static int Glyph(char c, bool isAfterSpace) noexcept;
61 	void LoadTexture(ImageBuffer &image);
62 	void CalculateAdvances(ImageBuffer &image);
63 	void SetUpShader(float glyphW, float glyphH);
64 
65 	int WidthRawString(const char *str, char after = ' ') const noexcept;
66 
67 	std::string TruncateText(const DisplayText &text, int &width) const;
68 	std::string TruncateBack(const std::string &str, int &width) const;
69 	std::string TruncateFront(const std::string &str, int &width) const;
70 	std::string TruncateMiddle(const std::string &str, int &width) const;
71 
72 
73 private:
74 	Shader shader;
75 	GLuint texture = 0;
76 	GLuint vao = 0;
77 	GLuint vbo = 0;
78 
79 	GLint colorI = 0;
80 	GLint scaleI = 0;
81 	GLint glyphI = 0;
82 	GLint aspectI = 0;
83 	GLint positionI = 0;
84 
85 	int height = 0;
86 	int space = 0;
87 	mutable int screenWidth = 0;
88 	mutable int screenHeight = 0;
89 
90 	static const int GLYPHS = 98;
91 	int advance[GLYPHS * GLYPHS] = {};
92 	int widthEllipses = 0;
93 };
94 
95 
96 
97 #endif
98