1 /**
2  * Copyright (c) 2006-2016 LOVE Development Team
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty.  In no event will the authors be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  *    claim that you wrote the original software. If you use this software
14  *    in a product, an acknowledgment in the product documentation would be
15  *    appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  *    misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  **/
20 
21 #ifndef LOVE_GRAPHICS_OPENGL_FONT_H
22 #define LOVE_GRAPHICS_OPENGL_FONT_H
23 
24 // STD
25 #include <unordered_map>
26 #include <string>
27 #include <vector>
28 
29 // LOVE
30 #include "common/config.h"
31 #include "common/Object.h"
32 #include "common/Matrix.h"
33 #include "common/Vector.h"
34 
35 #include "font/Rasterizer.h"
36 #include "graphics/Texture.h"
37 #include "graphics/Volatile.h"
38 #include "GLBuffer.h"
39 
40 #include "OpenGL.h"
41 
42 namespace love
43 {
44 namespace graphics
45 {
46 namespace opengl
47 {
48 
49 class Font : public Object, public Volatile
50 {
51 public:
52 
53 	typedef std::vector<uint32> Codepoints;
54 
55 	enum AlignMode
56 	{
57 		ALIGN_LEFT,
58 		ALIGN_CENTER,
59 		ALIGN_RIGHT,
60 		ALIGN_JUSTIFY,
61 		ALIGN_MAX_ENUM
62 	};
63 
64 	struct ColoredString
65 	{
66 		std::string str;
67 		Color color;
68 	};
69 
70 	struct IndexedColor
71 	{
72 		Color color;
73 		int index;
74 	};
75 
76 	struct ColoredCodepoints
77 	{
78 		std::vector<uint32> cps;
79 		std::vector<IndexedColor> colors;
80 	};
81 
82 	struct GlyphVertex
83 	{
84 		float  x, y;
85 		uint16 s, t;
86 		Color  color;
87 	};
88 
89 	struct TextInfo
90 	{
91 		int width;
92 		int height;
93 	};
94 
95 	// Used to determine when to change textures in the generated vertex array.
96 	struct DrawCommand
97 	{
98 		GLuint texture;
99 		int startvertex;
100 		int vertexcount;
101 	};
102 
103 	Font(love::font::Rasterizer *r, const Texture::Filter &filter = Texture::getDefaultFilter());
104 
105 	virtual ~Font();
106 
107 	std::vector<DrawCommand> generateVertices(const ColoredCodepoints &codepoints, std::vector<GlyphVertex> &vertices, float extra_spacing = 0.0f, Vector offset = {}, TextInfo *info = nullptr);
108 	std::vector<DrawCommand> generateVertices(const std::string &text, std::vector<GlyphVertex> &vertices, float extra_spacing = 0.0f, Vector offset = Vector(), TextInfo *info = nullptr);
109 
110 	std::vector<DrawCommand> generateVerticesFormatted(const ColoredCodepoints &text, float wrap, AlignMode align, std::vector<GlyphVertex> &vertices, TextInfo *info = nullptr);
111 
112 	void drawVertices(const std::vector<DrawCommand> &drawcommands, bool bufferedvertices);
113 
114 	static void getCodepointsFromString(const std::string &str, Codepoints &codepoints);
115 	static void getCodepointsFromString(const std::vector<ColoredString> &strs, ColoredCodepoints &codepoints);
116 
117 	/**
118 	 * Prints the text at the designated position with rotation and scaling.
119 	 *
120 	 * @param text A string.
121 	 * @param x The x-coordinate.
122 	 * @param y The y-coordinate.
123 	 * @param angle The amount of rotation.
124 	 * @param sx Scale along the x axis.
125 	 * @param sy Scale along the y axis.
126 	 * @param ox The origin offset along the x-axis.
127 	 * @param oy The origin offset along the y-axis.
128 	 * @param kx Shear along the x axis.
129 	 * @param ky Shear along the y axis.
130 	 **/
131 	void print(const std::vector<ColoredString> &text, float x, float y, float angle = 0.0f, float sx = 1.0f, float sy = 1.0f, float ox = 0.0f, float oy = 0.0f, float kx = 0.0f, float ky = 0.0f);
132 
133 	void printf(const std::vector<ColoredString> &text, float x, float y, float wrap, AlignMode align, float angle = 0.0f, float sx = 1.0f, float sy = 1.0f, float ox = 0.0f, float oy = 0.0f, float kx = 0.0f, float ky = 0.0f);
134 
135 	/**
136 	 * Returns the height of the font.
137 	 **/
138 	float getHeight() const;
139 
140 	/**
141 	 * Returns the width of the passed string.
142 	 *
143 	 * @param str A string of text.
144 	 **/
145 	int getWidth(const std::string &str);
146 
147 	/**
148 	 * Returns the width of the passed character.
149 	 *
150 	 * @param character A character.
151 	 **/
152 	int getWidth(char character);
153 
154 	/**
155 	 * Returns the maximal width of a wrapped string
156 	 * and optionally the number of lines
157 	 *
158 	 * @param text The input text
159 	 * @param wraplimit The number of pixels to wrap at
160 	 * @param max_width Optional output of the maximum width
161 	 * Returns a vector with the lines.
162 	 **/
163 	void getWrap(const std::vector<ColoredString> &text, float wraplimit, std::vector<std::string> &lines, std::vector<int> *line_widths = nullptr);
164 	void getWrap(const ColoredCodepoints &codepoints, float wraplimit, std::vector<ColoredCodepoints> &lines, std::vector<int> *line_widths = nullptr);
165 
166 	/**
167 	 * Sets the line height (which should be a number to multiply the font size by,
168 	 * example: line height = 1.2 and size = 12 means that rendered line height = 12*1.2)
169 	 * @param height The new line height.
170 	 **/
171 	void setLineHeight(float height);
172 
173 	/**
174 	 * Returns the line height.
175 	 **/
176 	float getLineHeight() const;
177 
178 	void setFilter(const Texture::Filter &f);
179 	const Texture::Filter &getFilter();
180 
181 	// Implements Volatile.
182 	bool loadVolatile();
183 	void unloadVolatile();
184 
185 	// Extra font metrics
186 	int getAscent() const;
187 	int getDescent() const;
188 	float getBaseline() const;
189 
190 	bool hasGlyph(uint32 glyph) const;
191 	bool hasGlyphs(const std::string &text) const;
192 
193 	void setFallbacks(const std::vector<Font *> &fallbacks);
194 
195 	uint32 getTextureCacheID() const;
196 
197 	static bool getConstant(const char *in, AlignMode &out);
198 	static bool getConstant(AlignMode in, const char *&out);
199 
200 	static int fontCount;
201 
202 private:
203 
204 	enum FontType
205 	{
206 		FONT_TRUETYPE,
207 		FONT_IMAGE,
208 		FONT_UNKNOWN
209 	};
210 
211 	struct Glyph
212 	{
213 		GLuint texture;
214 		int spacing;
215 		GlyphVertex vertices[4];
216 	};
217 
218 	struct TextureSize
219 	{
220 		int width;
221 		int height;
222 	};
223 
224 	TextureSize getNextTextureSize() const;
225 	GLenum getTextureFormat(FontType fontType, GLenum *internalformat = nullptr) const;
226 	void createTexture();
227 	love::font::GlyphData *getRasterizerGlyphData(uint32 glyph);
228 	const Glyph &addGlyph(uint32 glyph);
229 	const Glyph &findGlyph(uint32 glyph);
230 	float getKerning(uint32 leftglyph, uint32 rightglyph);
231 	void printv(const Matrix4 &t, const std::vector<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices);
232 
233 	std::vector<StrongRef<love::font::Rasterizer>> rasterizers;
234 
235 	int height;
236 	float lineHeight;
237 
238 	int textureWidth;
239 	int textureHeight;
240 
241 	// vector of packed textures
242 	std::vector<GLuint> textures;
243 
244 	// maps glyphs to glyph texture information
245 	std::unordered_map<uint32, Glyph> glyphs;
246 
247 	// map of left/right glyph pairs to horizontal kerning.
248 	std::unordered_map<uint64, float> kerning;
249 
250 	FontType type;
251 	Texture::Filter filter;
252 
253 	int textureX, textureY;
254 	int rowHeight;
255 
256 	bool useSpacesAsTab;
257 
258 	// Index buffer used for drawing quads with GL_TRIANGLES.
259 	QuadIndices quadIndices;
260 
261 	// ID which is incremented when the texture cache is invalidated.
262 	uint32 textureCacheID;
263 
264 	size_t textureMemorySize;
265 
266 	static const int TEXTURE_PADDING = 1;
267 
268 	// This will be used if the Rasterizer doesn't have a tab character itself.
269 	static const int SPACES_PER_TAB = 4;
270 
271 	static StringMap<AlignMode, ALIGN_MAX_ENUM>::Entry alignModeEntries[];
272 	static StringMap<AlignMode, ALIGN_MAX_ENUM> alignModes;
273 
274 }; // Font
275 
276 } // opengl
277 } // graphics
278 } // love
279 
280 #endif // LOVE_GRAPHICS_OPENGL_FONT_H
281