git repos / blockattack-game

blame: source/code/Libs/SDL_FontCache.cpp

normal view · raw

078900fe sago007 2015-12-05 15:31 1
/*
078900fe sago007 2015-12-05 15:31 2
SDL_FontCache v0.0.1: A font cache for SDL and SDL_ttf
078900fe sago007 2015-12-05 15:31 3
by Jonathan Dearborn
078900fe sago007 2015-12-05 15:31 4
Dedicated to the memory of Florian Hufsky
078900fe sago007 2015-12-05 15:31 5
078900fe sago007 2015-12-05 15:31 6
License:
078900fe sago007 2015-12-05 15:31 7
    The short:
1d2e2129 sago007 2015-12-23 15:41 8
    Use it however you'd like, but keep the copyright and license notice
078900fe sago007 2015-12-05 15:31 9
    whenever these files or parts of them are distributed in uncompiled form.
1d2e2129 sago007 2015-12-23 15:41 10
078900fe sago007 2015-12-05 15:31 11
    The long:
078900fe sago007 2015-12-05 15:31 12
Copyright (c) 2015 Jonathan Dearborn
078900fe sago007 2015-12-05 15:31 13
078900fe sago007 2015-12-05 15:31 14
Permission is hereby granted, free of charge, to any person obtaining a copy
078900fe sago007 2015-12-05 15:31 15
of this software and associated documentation files (the "Software"), to deal
078900fe sago007 2015-12-05 15:31 16
in the Software without restriction, including without limitation the rights
078900fe sago007 2015-12-05 15:31 17
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
078900fe sago007 2015-12-05 15:31 18
copies of the Software, and to permit persons to whom the Software is
078900fe sago007 2015-12-05 15:31 19
furnished to do so, subject to the following conditions:
078900fe sago007 2015-12-05 15:31 20
078900fe sago007 2015-12-05 15:31 21
The above copyright notice and this permission notice shall be included in
078900fe sago007 2015-12-05 15:31 22
all copies or substantial portions of the Software.
078900fe sago007 2015-12-05 15:31 23
078900fe sago007 2015-12-05 15:31 24
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
078900fe sago007 2015-12-05 15:31 25
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
078900fe sago007 2015-12-05 15:31 26
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
078900fe sago007 2015-12-05 15:31 27
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
078900fe sago007 2015-12-05 15:31 28
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
078900fe sago007 2015-12-05 15:31 29
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
078900fe sago007 2015-12-05 15:31 30
THE SOFTWARE.
078900fe sago007 2015-12-05 15:31 31
*/
078900fe sago007 2015-12-05 15:31 32
078900fe sago007 2015-12-05 15:31 33
#include "SDL_FontCache.h"
078900fe sago007 2015-12-05 15:31 34
078900fe sago007 2015-12-05 15:31 35
#include <stdio.h>
078900fe sago007 2015-12-05 15:31 36
#include <stdlib.h>
078900fe sago007 2015-12-05 15:31 37
#include <string.h>
078900fe sago007 2015-12-05 15:31 38
078900fe sago007 2015-12-05 15:31 39
// Visual C does not support static inline
078900fe sago007 2015-12-05 15:31 40
#ifndef static_inline
1d2e2129 sago007 2015-12-23 15:41 41
#ifdef _MSC_VER
1d2e2129 sago007 2015-12-23 15:41 42
#define static_inline static
1d2e2129 sago007 2015-12-23 15:41 43
#else
1d2e2129 sago007 2015-12-23 15:41 44
#define static_inline static inline
1d2e2129 sago007 2015-12-23 15:41 45
#endif
078900fe sago007 2015-12-05 15:31 46
#endif
078900fe sago007 2015-12-05 15:31 47
078900fe sago007 2015-12-05 15:31 48
#if SDL_VERSION_ATLEAST(2,0,0)
1d2e2129 sago007 2015-12-23 15:41 49
#define FC_GET_ALPHA(sdl_color) ((sdl_color).a)
078900fe sago007 2015-12-05 15:31 50
#else
1d2e2129 sago007 2015-12-23 15:41 51
#define FC_GET_ALPHA(sdl_color) ((sdl_color).unused)
078900fe sago007 2015-12-05 15:31 52
#endif
078900fe sago007 2015-12-05 15:31 53
078900fe sago007 2015-12-05 15:31 54
// Need SDL_RenderIsClipEnabled() for proper clipping support
078900fe sago007 2015-12-05 15:31 55
#if SDL_VERSION_ATLEAST(2,0,4)
1d2e2129 sago007 2015-12-23 15:41 56
#define ENABLE_SDL_CLIPPING
078900fe sago007 2015-12-05 15:31 57
#endif
078900fe sago007 2015-12-05 15:31 58
078900fe sago007 2015-12-05 15:31 59
#define FC_MIN(a,b) ((a) < (b)? (a) : (b))
078900fe sago007 2015-12-05 15:31 60
#define FC_MAX(a,b) ((a) > (b)? (a) : (b))
078900fe sago007 2015-12-05 15:31 61
078900fe sago007 2015-12-05 15:31 62
078900fe sago007 2015-12-05 15:31 63
#define FC_EXTRACT_VARARGS(buffer, start_args) \
078900fe sago007 2015-12-05 15:31 64
{ \
078900fe sago007 2015-12-05 15:31 65
    va_list lst; \
078900fe sago007 2015-12-05 15:31 66
    va_start(lst, start_args); \
078900fe sago007 2015-12-05 15:31 67
    vsprintf(buffer, start_args, lst); \
078900fe sago007 2015-12-05 15:31 68
    va_end(lst); \
078900fe sago007 2015-12-05 15:31 69
}
078900fe sago007 2015-12-05 15:31 70
078900fe sago007 2015-12-05 15:31 71
// Extra pixels of padding around each glyph to avoid linear filtering artifacts
078900fe sago007 2015-12-05 15:31 72
#define FC_CACHE_PADDING 1
078900fe sago007 2015-12-05 15:31 73
078900fe sago007 2015-12-05 15:31 74
078900fe sago007 2015-12-05 15:31 75
1d2e2129 sago007 2015-12-23 15:41 76
static Uint8 has_clip(FC_Target* dest) {
1d2e2129 sago007 2015-12-23 15:41 77
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 78
	return dest->use_clip_rect;
1d2e2129 sago007 2015-12-23 15:41 79
#elif defined(ENABLE_SDL_CLIPPING)
1d2e2129 sago007 2015-12-23 15:41 80
	return SDL_RenderIsClipEnabled(dest);
1d2e2129 sago007 2015-12-23 15:41 81
#else
1d2e2129 sago007 2015-12-23 15:41 82
	return 0;
1d2e2129 sago007 2015-12-23 15:41 83
#endif
078900fe sago007 2015-12-05 15:31 84
}
078900fe sago007 2015-12-05 15:31 85
1d2e2129 sago007 2015-12-23 15:41 86
static FC_Rect get_clip(FC_Target* dest) {
1d2e2129 sago007 2015-12-23 15:41 87
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 88
	return dest->clip_rect;
1d2e2129 sago007 2015-12-23 15:41 89
#elif defined(ENABLE_SDL_CLIPPING)
1d2e2129 sago007 2015-12-23 15:41 90
	SDL_Rect r;
1d2e2129 sago007 2015-12-23 15:41 91
	SDL_RenderGetClipRect(dest, &r);
1d2e2129 sago007 2015-12-23 15:41 92
	return r;
1d2e2129 sago007 2015-12-23 15:41 93
#else
1d2e2129 sago007 2015-12-23 15:41 94
	SDL_Rect r = {0, 0, 0, 0};
1d2e2129 sago007 2015-12-23 15:41 95
	return r;
1d2e2129 sago007 2015-12-23 15:41 96
#endif
078900fe sago007 2015-12-05 15:31 97
}
078900fe sago007 2015-12-05 15:31 98
1d2e2129 sago007 2015-12-23 15:41 99
static void set_clip(FC_Target* dest, FC_Rect* rect) {
1d2e2129 sago007 2015-12-23 15:41 100
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 101
	if (rect != NULL) {
1d2e2129 sago007 2015-12-23 15:41 102
		GPU_SetClipRect(dest, *rect);
1d2e2129 sago007 2015-12-23 15:41 103
	}
1d2e2129 sago007 2015-12-23 15:41 104
	else {
1d2e2129 sago007 2015-12-23 15:41 105
		GPU_UnsetClip(dest);
1d2e2129 sago007 2015-12-23 15:41 106
	}
1d2e2129 sago007 2015-12-23 15:41 107
#elif defined(ENABLE_SDL_CLIPPING)
1d2e2129 sago007 2015-12-23 15:41 108
	SDL_RenderSetClipRect(dest, rect);
1d2e2129 sago007 2015-12-23 15:41 109
#endif
078900fe sago007 2015-12-05 15:31 110
}
078900fe sago007 2015-12-05 15:31 111
1d2e2129 sago007 2015-12-23 15:41 112
static void set_color(FC_Image* src, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
1d2e2129 sago007 2015-12-23 15:41 113
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 114
	GPU_SetRGBA(src, r, g, b, a);
1d2e2129 sago007 2015-12-23 15:41 115
#else
1d2e2129 sago007 2015-12-23 15:41 116
	SDL_SetTextureColorMod(src, r, g, b);
1d2e2129 sago007 2015-12-23 15:41 117
	SDL_SetTextureAlphaMod(src, a);
1d2e2129 sago007 2015-12-23 15:41 118
#endif
078900fe sago007 2015-12-05 15:31 119
}
078900fe sago007 2015-12-05 15:31 120
078900fe sago007 2015-12-05 15:31 121
078900fe sago007 2015-12-05 15:31 122
1d2e2129 sago007 2015-12-23 15:41 123
static char* new_concat(const char* a, const char* b) {
1d2e2129 sago007 2015-12-23 15:41 124
	// Create new buffer
1d2e2129 sago007 2015-12-23 15:41 125
	unsigned int size = strlen(a) + strlen(b);
1d2e2129 sago007 2015-12-23 15:41 126
	char* new_string = (char*)malloc(size+1);
078900fe sago007 2015-12-05 15:31 127
1d2e2129 sago007 2015-12-23 15:41 128
	// Concatenate strings in the new buffer
1d2e2129 sago007 2015-12-23 15:41 129
	strcpy(new_string, a);
1d2e2129 sago007 2015-12-23 15:41 130
	strcat(new_string, b);
078900fe sago007 2015-12-05 15:31 131
1d2e2129 sago007 2015-12-23 15:41 132
	return new_string;
078900fe sago007 2015-12-05 15:31 133
}
078900fe sago007 2015-12-05 15:31 134
1d2e2129 sago007 2015-12-23 15:41 135
static char* replace_concat(char** a, const char* b) {
1d2e2129 sago007 2015-12-23 15:41 136
	char* new_string = new_concat(*a, b);
1d2e2129 sago007 2015-12-23 15:41 137
	free(*a);
1d2e2129 sago007 2015-12-23 15:41 138
	*a = new_string;
1d2e2129 sago007 2015-12-23 15:41 139
	return *a;
078900fe sago007 2015-12-05 15:31 140
}
078900fe sago007 2015-12-05 15:31 141
078900fe sago007 2015-12-05 15:31 142
078900fe sago007 2015-12-05 15:31 143
078900fe sago007 2015-12-05 15:31 144
078900fe sago007 2015-12-05 15:31 145
1d2e2129 sago007 2015-12-23 15:41 146
// Shared buffer for variadic text
1d2e2129 sago007 2015-12-23 15:41 147
static char* fc_buffer = NULL;
078900fe sago007 2015-12-05 15:31 148
1d2e2129 sago007 2015-12-23 15:41 149
static Uint8 fc_has_render_target_support = 0;
1d2e2129 sago007 2015-12-23 15:41 150
1d2e2129 sago007 2015-12-23 15:41 151
const char* FC_GetStringASCII(void) {
1d2e2129 sago007 2015-12-23 15:41 152
	static char* buffer = NULL;
1d2e2129 sago007 2015-12-23 15:41 153
	if (buffer == NULL) {
1d2e2129 sago007 2015-12-23 15:41 154
		int i;
1d2e2129 sago007 2015-12-23 15:41 155
		char c;
1d2e2129 sago007 2015-12-23 15:41 156
		buffer = (char*)malloc(512);
1d2e2129 sago007 2015-12-23 15:41 157
		memset(buffer, 0, 512);
1d2e2129 sago007 2015-12-23 15:41 158
		i = 0;
1d2e2129 sago007 2015-12-23 15:41 159
		c = 32;
1d2e2129 sago007 2015-12-23 15:41 160
		while (1) {
1d2e2129 sago007 2015-12-23 15:41 161
			buffer[i] = c;
1d2e2129 sago007 2015-12-23 15:41 162
			if (c == 126) {
1d2e2129 sago007 2015-12-23 15:41 163
				break;
1d2e2129 sago007 2015-12-23 15:41 164
			}
1d2e2129 sago007 2015-12-23 15:41 165
			++i;
1d2e2129 sago007 2015-12-23 15:41 166
			++c;
1d2e2129 sago007 2015-12-23 15:41 167
		}
1d2e2129 sago007 2015-12-23 15:41 168
	}
1d2e2129 sago007 2015-12-23 15:41 169
	return buffer;
1d2e2129 sago007 2015-12-23 15:41 170
}
1d2e2129 sago007 2015-12-23 15:41 171
1d2e2129 sago007 2015-12-23 15:41 172
const char* FC_GetStringLatin1(void) {
1d2e2129 sago007 2015-12-23 15:41 173
	static char* buffer = NULL;
1d2e2129 sago007 2015-12-23 15:41 174
	if (buffer == NULL) {
1d2e2129 sago007 2015-12-23 15:41 175
		int i;
1d2e2129 sago007 2015-12-23 15:41 176
		unsigned char c;
1d2e2129 sago007 2015-12-23 15:41 177
		buffer = (char*)malloc(512);
1d2e2129 sago007 2015-12-23 15:41 178
		memset(buffer, 0, 512);
1d2e2129 sago007 2015-12-23 15:41 179
		i = 0;
1d2e2129 sago007 2015-12-23 15:41 180
		c = 0xA0;
1d2e2129 sago007 2015-12-23 15:41 181
		while (1) {
1d2e2129 sago007 2015-12-23 15:41 182
			buffer[i] = 0xC2;
1d2e2129 sago007 2015-12-23 15:41 183
			buffer[i+1] = c;
1d2e2129 sago007 2015-12-23 15:41 184
			if (c == 0xBF) {
1d2e2129 sago007 2015-12-23 15:41 185
				break;
1d2e2129 sago007 2015-12-23 15:41 186
			}
1d2e2129 sago007 2015-12-23 15:41 187
			i += 2;
1d2e2129 sago007 2015-12-23 15:41 188
			++c;
1d2e2129 sago007 2015-12-23 15:41 189
		}
1d2e2129 sago007 2015-12-23 15:41 190
		i += 2;
1d2e2129 sago007 2015-12-23 15:41 191
		c = 0x80;
1d2e2129 sago007 2015-12-23 15:41 192
		while (1) {
1d2e2129 sago007 2015-12-23 15:41 193
			buffer[i] = 0xC3;
1d2e2129 sago007 2015-12-23 15:41 194
			buffer[i+1] = c;
1d2e2129 sago007 2015-12-23 15:41 195
			if (c == 0xBF) {
1d2e2129 sago007 2015-12-23 15:41 196
				break;
1d2e2129 sago007 2015-12-23 15:41 197
			}
1d2e2129 sago007 2015-12-23 15:41 198
			i += 2;
1d2e2129 sago007 2015-12-23 15:41 199
			++c;
1d2e2129 sago007 2015-12-23 15:41 200
		}
1d2e2129 sago007 2015-12-23 15:41 201
	}
1d2e2129 sago007 2015-12-23 15:41 202
	return buffer;
1d2e2129 sago007 2015-12-23 15:41 203
}
1d2e2129 sago007 2015-12-23 15:41 204
1d2e2129 sago007 2015-12-23 15:41 205
const char* FC_GetStringASCII_Latin1(void) {
1d2e2129 sago007 2015-12-23 15:41 206
	static char* buffer = NULL;
1d2e2129 sago007 2015-12-23 15:41 207
	if (buffer == NULL) {
1d2e2129 sago007 2015-12-23 15:41 208
		buffer = new_concat(FC_GetStringASCII(), FC_GetStringLatin1());
1d2e2129 sago007 2015-12-23 15:41 209
	}
1d2e2129 sago007 2015-12-23 15:41 210
1d2e2129 sago007 2015-12-23 15:41 211
	return buffer;
1d2e2129 sago007 2015-12-23 15:41 212
}
1d2e2129 sago007 2015-12-23 15:41 213
1d2e2129 sago007 2015-12-23 15:41 214
FC_Rect FC_MakeRect(float x, float y, float w, float h) {
1d2e2129 sago007 2015-12-23 15:41 215
	FC_Rect r = {x, y, w, h};
1d2e2129 sago007 2015-12-23 15:41 216
	return r;
1d2e2129 sago007 2015-12-23 15:41 217
}
1d2e2129 sago007 2015-12-23 15:41 218
1d2e2129 sago007 2015-12-23 15:41 219
FC_Scale FC_MakeScale(float x, float y) {
1d2e2129 sago007 2015-12-23 15:41 220
	FC_Scale s = {x, y};
1d2e2129 sago007 2015-12-23 15:41 221
1d2e2129 sago007 2015-12-23 15:41 222
	return s;
1d2e2129 sago007 2015-12-23 15:41 223
}
1d2e2129 sago007 2015-12-23 15:41 224
1d2e2129 sago007 2015-12-23 15:41 225
SDL_Color FC_MakeColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
1d2e2129 sago007 2015-12-23 15:41 226
	SDL_Color c = {r, g, b, a};
1d2e2129 sago007 2015-12-23 15:41 227
1d2e2129 sago007 2015-12-23 15:41 228
	return c;
1d2e2129 sago007 2015-12-23 15:41 229
}
1d2e2129 sago007 2015-12-23 15:41 230
1d2e2129 sago007 2015-12-23 15:41 231
FC_Effect FC_MakeEffect(FC_AlignEnum alignment, FC_Scale scale, SDL_Color color) {
1d2e2129 sago007 2015-12-23 15:41 232
	FC_Effect e;
1d2e2129 sago007 2015-12-23 15:41 233
1d2e2129 sago007 2015-12-23 15:41 234
	e.alignment = alignment;
1d2e2129 sago007 2015-12-23 15:41 235
	e.scale = scale;
1d2e2129 sago007 2015-12-23 15:41 236
	e.color = color;
1d2e2129 sago007 2015-12-23 15:41 237
1d2e2129 sago007 2015-12-23 15:41 238
	return e;
1d2e2129 sago007 2015-12-23 15:41 239
}
1d2e2129 sago007 2015-12-23 15:41 240
1d2e2129 sago007 2015-12-23 15:41 241
FC_GlyphData FC_MakeGlyphData(int cache_level, Sint16 x, Sint16 y, Uint16 w, Uint16 h) {
1d2e2129 sago007 2015-12-23 15:41 242
	FC_GlyphData gd;
1d2e2129 sago007 2015-12-23 15:41 243
1d2e2129 sago007 2015-12-23 15:41 244
	gd.rect.x = x;
1d2e2129 sago007 2015-12-23 15:41 245
	gd.rect.y = y;
1d2e2129 sago007 2015-12-23 15:41 246
	gd.rect.w = w;
1d2e2129 sago007 2015-12-23 15:41 247
	gd.rect.h = h;
1d2e2129 sago007 2015-12-23 15:41 248
	gd.cache_level = cache_level;
1d2e2129 sago007 2015-12-23 15:41 249
1d2e2129 sago007 2015-12-23 15:41 250
	return gd;
078900fe sago007 2015-12-05 15:31 251
}
078900fe sago007 2015-12-05 15:31 252
078900fe sago007 2015-12-05 15:31 253
// Enough to hold all of the ascii characters and some.
078900fe sago007 2015-12-05 15:31 254
#define FC_DEFAULT_NUM_BUCKETS 300
078900fe sago007 2015-12-05 15:31 255
1d2e2129 sago007 2015-12-23 15:41 256
typedef struct FC_MapNode {
1d2e2129 sago007 2015-12-23 15:41 257
	Uint32 key;
1d2e2129 sago007 2015-12-23 15:41 258
	FC_GlyphData value;
1d2e2129 sago007 2015-12-23 15:41 259
	struct FC_MapNode* next;
1d2e2129 sago007 2015-12-23 15:41 260
078900fe sago007 2015-12-05 15:31 261
} FC_MapNode;
078900fe sago007 2015-12-05 15:31 262
1d2e2129 sago007 2015-12-23 15:41 263
typedef struct FC_Map {
1d2e2129 sago007 2015-12-23 15:41 264
	int num_buckets;
1d2e2129 sago007 2015-12-23 15:41 265
	FC_MapNode** buckets;
078900fe sago007 2015-12-05 15:31 266
} FC_Map;
078900fe sago007 2015-12-05 15:31 267
078900fe sago007 2015-12-05 15:31 268
078900fe sago007 2015-12-05 15:31 269
1d2e2129 sago007 2015-12-23 15:41 270
static FC_Map* FC_MapCreate(int num_buckets) {
1d2e2129 sago007 2015-12-23 15:41 271
	int i;
1d2e2129 sago007 2015-12-23 15:41 272
	FC_Map* map = (FC_Map*)malloc(sizeof(FC_Map));
1d2e2129 sago007 2015-12-23 15:41 273
1d2e2129 sago007 2015-12-23 15:41 274
	map->num_buckets = num_buckets;
1d2e2129 sago007 2015-12-23 15:41 275
	map->buckets = (FC_MapNode**)malloc(num_buckets * sizeof(FC_MapNode*));
1d2e2129 sago007 2015-12-23 15:41 276
1d2e2129 sago007 2015-12-23 15:41 277
	for (i = 0; i < num_buckets; ++i) {
1d2e2129 sago007 2015-12-23 15:41 278
		map->buckets[i] = NULL;
1d2e2129 sago007 2015-12-23 15:41 279
	}
1d2e2129 sago007 2015-12-23 15:41 280
1d2e2129 sago007 2015-12-23 15:41 281
	return map;
078900fe sago007 2015-12-05 15:31 282
}
078900fe sago007 2015-12-05 15:31 283
078900fe sago007 2015-12-05 15:31 284
/*static void FC_MapClear(FC_Map* map)
078900fe sago007 2015-12-05 15:31 285
{
078900fe sago007 2015-12-05 15:31 286
    int i;
078900fe sago007 2015-12-05 15:31 287
    if(map == NULL)
078900fe sago007 2015-12-05 15:31 288
        return;
1d2e2129 sago007 2015-12-23 15:41 289
078900fe sago007 2015-12-05 15:31 290
    // Go through each bucket
078900fe sago007 2015-12-05 15:31 291
    for(i = 0; i < map->num_buckets; ++i)
078900fe sago007 2015-12-05 15:31 292
    {
078900fe sago007 2015-12-05 15:31 293
        // Delete the nodes in order
078900fe sago007 2015-12-05 15:31 294
        FC_MapNode* node = map->buckets[i];
078900fe sago007 2015-12-05 15:31 295
        while(node != NULL)
078900fe sago007 2015-12-05 15:31 296
        {
078900fe sago007 2015-12-05 15:31 297
            FC_MapNode* last = node;
078900fe sago007 2015-12-05 15:31 298
            node = node->next;
078900fe sago007 2015-12-05 15:31 299
            free(last);
078900fe sago007 2015-12-05 15:31 300
        }
078900fe sago007 2015-12-05 15:31 301
        // Set the bucket to empty
078900fe sago007 2015-12-05 15:31 302
        map->buckets[i] = NULL;
078900fe sago007 2015-12-05 15:31 303
    }
078900fe sago007 2015-12-05 15:31 304
}*/
078900fe sago007 2015-12-05 15:31 305
1d2e2129 sago007 2015-12-23 15:41 306
static void FC_MapFree(FC_Map* map) {
1d2e2129 sago007 2015-12-23 15:41 307
	int i;
1d2e2129 sago007 2015-12-23 15:41 308
	if (map == NULL) {
1d2e2129 sago007 2015-12-23 15:41 309
		return;
1d2e2129 sago007 2015-12-23 15:41 310
	}
1d2e2129 sago007 2015-12-23 15:41 311
1d2e2129 sago007 2015-12-23 15:41 312
	// Go through each bucket
1d2e2129 sago007 2015-12-23 15:41 313
	for (i = 0; i < map->num_buckets; ++i) {
1d2e2129 sago007 2015-12-23 15:41 314
		// Delete the nodes in order
1d2e2129 sago007 2015-12-23 15:41 315
		FC_MapNode* node = map->buckets[i];
1d2e2129 sago007 2015-12-23 15:41 316
		while (node != NULL) {
1d2e2129 sago007 2015-12-23 15:41 317
			FC_MapNode* last = node;
1d2e2129 sago007 2015-12-23 15:41 318
			node = node->next;
1d2e2129 sago007 2015-12-23 15:41 319
			free(last);
1d2e2129 sago007 2015-12-23 15:41 320
		}
1d2e2129 sago007 2015-12-23 15:41 321
	}
1d2e2129 sago007 2015-12-23 15:41 322
1d2e2129 sago007 2015-12-23 15:41 323
	free(map->buckets);
1d2e2129 sago007 2015-12-23 15:41 324
	free(map);
078900fe sago007 2015-12-05 15:31 325
}
078900fe sago007 2015-12-05 15:31 326
078900fe sago007 2015-12-05 15:31 327
// Note: Does not handle duplicates in any special way.
1d2e2129 sago007 2015-12-23 15:41 328
static FC_GlyphData* FC_MapInsert(FC_Map* map, Uint32 codepoint, FC_GlyphData glyph) {
1d2e2129 sago007 2015-12-23 15:41 329
	Uint32 index;
1d2e2129 sago007 2015-12-23 15:41 330
	FC_MapNode* node;
1d2e2129 sago007 2015-12-23 15:41 331
	if (map == NULL) {
1d2e2129 sago007 2015-12-23 15:41 332
		return NULL;
1d2e2129 sago007 2015-12-23 15:41 333
	}
1d2e2129 sago007 2015-12-23 15:41 334
1d2e2129 sago007 2015-12-23 15:41 335
	// Get index for bucket
1d2e2129 sago007 2015-12-23 15:41 336
	index = codepoint % map->num_buckets;
1d2e2129 sago007 2015-12-23 15:41 337
1d2e2129 sago007 2015-12-23 15:41 338
	// If this bucket is empty, create a node and return its value
1d2e2129 sago007 2015-12-23 15:41 339
	if (map->buckets[index] == NULL) {
1d2e2129 sago007 2015-12-23 15:41 340
		node = map->buckets[index] = (FC_MapNode*)malloc(sizeof(FC_MapNode));
1d2e2129 sago007 2015-12-23 15:41 341
		node->key = codepoint;
1d2e2129 sago007 2015-12-23 15:41 342
		node->value = glyph;
1d2e2129 sago007 2015-12-23 15:41 343
		node->next = NULL;
1d2e2129 sago007 2015-12-23 15:41 344
		return &node->value;
1d2e2129 sago007 2015-12-23 15:41 345
	}
1d2e2129 sago007 2015-12-23 15:41 346
1d2e2129 sago007 2015-12-23 15:41 347
	for (node = map->buckets[index]; node != NULL; node = node->next) {
1d2e2129 sago007 2015-12-23 15:41 348
		// Find empty node and add a new one on.
1d2e2129 sago007 2015-12-23 15:41 349
		if (node->next == NULL) {
1d2e2129 sago007 2015-12-23 15:41 350
			node->next = (FC_MapNode*)malloc(sizeof(FC_MapNode));
1d2e2129 sago007 2015-12-23 15:41 351
			node = node->next;
1d2e2129 sago007 2015-12-23 15:41 352
1d2e2129 sago007 2015-12-23 15:41 353
			node->key = codepoint;
1d2e2129 sago007 2015-12-23 15:41 354
			node->value = glyph;
1d2e2129 sago007 2015-12-23 15:41 355
			node->next = NULL;
1d2e2129 sago007 2015-12-23 15:41 356
			return &node->value;
1d2e2129 sago007 2015-12-23 15:41 357
		}
1d2e2129 sago007 2015-12-23 15:41 358
	}
1d2e2129 sago007 2015-12-23 15:41 359
1d2e2129 sago007 2015-12-23 15:41 360
	return NULL;
1d2e2129 sago007 2015-12-23 15:41 361
}
1d2e2129 sago007 2015-12-23 15:41 362
1d2e2129 sago007 2015-12-23 15:41 363
static FC_GlyphData* FC_MapFind(FC_Map* map, Uint32 codepoint) {
1d2e2129 sago007 2015-12-23 15:41 364
	Uint32 index;
1d2e2129 sago007 2015-12-23 15:41 365
	FC_MapNode* node;
1d2e2129 sago007 2015-12-23 15:41 366
	if (map == NULL) {
1d2e2129 sago007 2015-12-23 15:41 367
		return NULL;
1d2e2129 sago007 2015-12-23 15:41 368
	}
1d2e2129 sago007 2015-12-23 15:41 369
1d2e2129 sago007 2015-12-23 15:41 370
	// Get index for bucket
1d2e2129 sago007 2015-12-23 15:41 371
	index = codepoint % map->num_buckets;
1d2e2129 sago007 2015-12-23 15:41 372
1d2e2129 sago007 2015-12-23 15:41 373
	// Go through list until we find a match
1d2e2129 sago007 2015-12-23 15:41 374
	for (node = map->buckets[index]; node != NULL; node = node->next) {
1d2e2129 sago007 2015-12-23 15:41 375
		if (node->key == codepoint) {
1d2e2129 sago007 2015-12-23 15:41 376
			return &node->value;
1d2e2129 sago007 2015-12-23 15:41 377
		}
1d2e2129 sago007 2015-12-23 15:41 378
	}
1d2e2129 sago007 2015-12-23 15:41 379
1d2e2129 sago007 2015-12-23 15:41 380
	return NULL;
1d2e2129 sago007 2015-12-23 15:41 381
}
1d2e2129 sago007 2015-12-23 15:41 382
1d2e2129 sago007 2015-12-23 15:41 383
1d2e2129 sago007 2015-12-23 15:41 384
1d2e2129 sago007 2015-12-23 15:41 385
struct FC_Font {
1d2e2129 sago007 2015-12-23 15:41 386
#ifndef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 387
	SDL_Renderer* renderer;
1d2e2129 sago007 2015-12-23 15:41 388
#endif
078900fe sago007 2015-12-05 15:31 389
1d2e2129 sago007 2015-12-23 15:41 390
	TTF_Font* ttf_source;  // TTF_Font source of characters
1d2e2129 sago007 2015-12-23 15:41 391
	Uint8 owns_ttf_source;  // Can we delete the TTF_Font ourselves?
078900fe sago007 2015-12-05 15:31 392
1d2e2129 sago007 2015-12-23 15:41 393
	FC_FilterEnum filter;
078900fe sago007 2015-12-05 15:31 394
1d2e2129 sago007 2015-12-23 15:41 395
	SDL_Color default_color;
1d2e2129 sago007 2015-12-23 15:41 396
	Uint16 height;
1d2e2129 sago007 2015-12-23 15:41 397
1d2e2129 sago007 2015-12-23 15:41 398
	Uint16 maxWidth;
1d2e2129 sago007 2015-12-23 15:41 399
	Uint16 baseline;
1d2e2129 sago007 2015-12-23 15:41 400
	int ascent;
1d2e2129 sago007 2015-12-23 15:41 401
	int descent;
1d2e2129 sago007 2015-12-23 15:41 402
1d2e2129 sago007 2015-12-23 15:41 403
	int lineSpacing;
1d2e2129 sago007 2015-12-23 15:41 404
	int letterSpacing;
1d2e2129 sago007 2015-12-23 15:41 405
1d2e2129 sago007 2015-12-23 15:41 406
	// Uses 32-bit (4-byte) Unicode codepoints to refer to each glyph
1d2e2129 sago007 2015-12-23 15:41 407
	// Codepoints are little endian (reversed from UTF-8) so that something like 0x00000005 is ASCII 5 and the map can be indexed by ASCII values
1d2e2129 sago007 2015-12-23 15:41 408
	FC_Map* glyphs;
1d2e2129 sago007 2015-12-23 15:41 409
1d2e2129 sago007 2015-12-23 15:41 410
	FC_GlyphData last_glyph;  // Texture packing cursor
1d2e2129 sago007 2015-12-23 15:41 411
	int glyph_cache_size;
1d2e2129 sago007 2015-12-23 15:41 412
	int glyph_cache_count;
1d2e2129 sago007 2015-12-23 15:41 413
	FC_Image** glyph_cache;
1d2e2129 sago007 2015-12-23 15:41 414
1d2e2129 sago007 2015-12-23 15:41 415
	char* loading_string;
078900fe sago007 2015-12-05 15:31 416
078900fe sago007 2015-12-05 15:31 417
};
078900fe sago007 2015-12-05 15:31 418
078900fe sago007 2015-12-05 15:31 419
// Private
078900fe sago007 2015-12-05 15:31 420
static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight);
078900fe sago007 2015-12-05 15:31 421
078900fe sago007 2015-12-05 15:31 422
078900fe sago007 2015-12-05 15:31 423
static FC_Rect FC_RenderLeft(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text);
078900fe sago007 2015-12-05 15:31 424
static FC_Rect FC_RenderCenter(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text);
078900fe sago007 2015-12-05 15:31 425
static FC_Rect FC_RenderRight(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text);
078900fe sago007 2015-12-05 15:31 426
078900fe sago007 2015-12-05 15:31 427
1d2e2129 sago007 2015-12-23 15:41 428
static_inline SDL_Surface* FC_CreateSurface32(Uint32 width, Uint32 height) {
1d2e2129 sago007 2015-12-23 15:41 429
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
1d2e2129 sago007 2015-12-23 15:41 430
	return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
1d2e2129 sago007 2015-12-23 15:41 431
#else
1d2e2129 sago007 2015-12-23 15:41 432
	return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
1d2e2129 sago007 2015-12-23 15:41 433
#endif
078900fe sago007 2015-12-05 15:31 434
}
078900fe sago007 2015-12-05 15:31 435
078900fe sago007 2015-12-05 15:31 436
1d2e2129 sago007 2015-12-23 15:41 437
char* U8_alloc(unsigned int size) {
1d2e2129 sago007 2015-12-23 15:41 438
	char* result;
1d2e2129 sago007 2015-12-23 15:41 439
	if (size == 0) {
1d2e2129 sago007 2015-12-23 15:41 440
		return NULL;
1d2e2129 sago007 2015-12-23 15:41 441
	}
078900fe sago007 2015-12-05 15:31 442
1d2e2129 sago007 2015-12-23 15:41 443
	result = (char*)malloc(size);
1d2e2129 sago007 2015-12-23 15:41 444
	result[0] = '\0';
1d2e2129 sago007 2015-12-23 15:41 445
1d2e2129 sago007 2015-12-23 15:41 446
	return result;
078900fe sago007 2015-12-05 15:31 447
}
078900fe sago007 2015-12-05 15:31 448
1d2e2129 sago007 2015-12-23 15:41 449
void U8_free(char* string) {
1d2e2129 sago007 2015-12-23 15:41 450
	free(string);
078900fe sago007 2015-12-05 15:31 451
}
078900fe sago007 2015-12-05 15:31 452
1d2e2129 sago007 2015-12-23 15:41 453
char* U8_strdup(const char* string) {
1d2e2129 sago007 2015-12-23 15:41 454
	char* result;
1d2e2129 sago007 2015-12-23 15:41 455
	if (string == NULL) {
1d2e2129 sago007 2015-12-23 15:41 456
		return NULL;
1d2e2129 sago007 2015-12-23 15:41 457
	}
078900fe sago007 2015-12-05 15:31 458
1d2e2129 sago007 2015-12-23 15:41 459
	result = (char*)malloc(strlen(string)+1);
1d2e2129 sago007 2015-12-23 15:41 460
	strcpy(result, string);
078900fe sago007 2015-12-05 15:31 461
1d2e2129 sago007 2015-12-23 15:41 462
	return result;
078900fe sago007 2015-12-05 15:31 463
}
078900fe sago007 2015-12-05 15:31 464
1d2e2129 sago007 2015-12-23 15:41 465
int U8_strlen(const char* string) {
1d2e2129 sago007 2015-12-23 15:41 466
	int length = 0;
1d2e2129 sago007 2015-12-23 15:41 467
	if (string == NULL) {
1d2e2129 sago007 2015-12-23 15:41 468
		return 0;
1d2e2129 sago007 2015-12-23 15:41 469
	}
1d2e2129 sago007 2015-12-23 15:41 470
1d2e2129 sago007 2015-12-23 15:41 471
	while (*string != '\0') {
1d2e2129 sago007 2015-12-23 15:41 472
		string = U8_next(string);
1d2e2129 sago007 2015-12-23 15:41 473
		++length;
1d2e2129 sago007 2015-12-23 15:41 474
	}
1d2e2129 sago007 2015-12-23 15:41 475
1d2e2129 sago007 2015-12-23 15:41 476
	return length;
078900fe sago007 2015-12-05 15:31 477
}
078900fe sago007 2015-12-05 15:31 478
1d2e2129 sago007 2015-12-23 15:41 479
int U8_charsize(const char* character) {
1d2e2129 sago007 2015-12-23 15:41 480
	if (character == NULL) {
1d2e2129 sago007 2015-12-23 15:41 481
		return 0;
1d2e2129 sago007 2015-12-23 15:41 482
	}
1d2e2129 sago007 2015-12-23 15:41 483
1d2e2129 sago007 2015-12-23 15:41 484
	if ((unsigned char)*character <= 0x7F) {
1d2e2129 sago007 2015-12-23 15:41 485
		return 1;
1d2e2129 sago007 2015-12-23 15:41 486
	}
1d2e2129 sago007 2015-12-23 15:41 487
	else if ((unsigned char)*character < 0xE0) {
1d2e2129 sago007 2015-12-23 15:41 488
		return 2;
1d2e2129 sago007 2015-12-23 15:41 489
	}
1d2e2129 sago007 2015-12-23 15:41 490
	else if ((unsigned char)*character < 0xF0) {
1d2e2129 sago007 2015-12-23 15:41 491
		return 3;
1d2e2129 sago007 2015-12-23 15:41 492
	}
1d2e2129 sago007 2015-12-23 15:41 493
	else {
1d2e2129 sago007 2015-12-23 15:41 494
		return 4;
1d2e2129 sago007 2015-12-23 15:41 495
	}
1d2e2129 sago007 2015-12-23 15:41 496
	return 1;
078900fe sago007 2015-12-05 15:31 497
}
078900fe sago007 2015-12-05 15:31 498
1d2e2129 sago007 2015-12-23 15:41 499
int U8_charcpy(char* buffer, const char* source, int buffer_size) {
1d2e2129 sago007 2015-12-23 15:41 500
	int charsize;
1d2e2129 sago007 2015-12-23 15:41 501
	if (buffer == NULL || source == NULL || buffer_size < 1) {
1d2e2129 sago007 2015-12-23 15:41 502
		return 0;
1d2e2129 sago007 2015-12-23 15:41 503
	}
1d2e2129 sago007 2015-12-23 15:41 504
1d2e2129 sago007 2015-12-23 15:41 505
	charsize = U8_charsize(source);
1d2e2129 sago007 2015-12-23 15:41 506
	if (charsize > buffer_size) {
1d2e2129 sago007 2015-12-23 15:41 507
		return 0;
1d2e2129 sago007 2015-12-23 15:41 508
	}
1d2e2129 sago007 2015-12-23 15:41 509
1d2e2129 sago007 2015-12-23 15:41 510
	memcpy(buffer, source, charsize);
1d2e2129 sago007 2015-12-23 15:41 511
	return charsize;
078900fe sago007 2015-12-05 15:31 512
}
078900fe sago007 2015-12-05 15:31 513
1d2e2129 sago007 2015-12-23 15:41 514
const char* U8_next(const char* string) {
1d2e2129 sago007 2015-12-23 15:41 515
	return string + U8_charsize(string);
078900fe sago007 2015-12-05 15:31 516
}
078900fe sago007 2015-12-05 15:31 517
1d2e2129 sago007 2015-12-23 15:41 518
int U8_strinsert(char* string, int position, const char* source, int max_bytes) {
1d2e2129 sago007 2015-12-23 15:41 519
	int pos_bytes;
1d2e2129 sago007 2015-12-23 15:41 520
	int len = strlen(string);
1d2e2129 sago007 2015-12-23 15:41 521
	int add_len = strlen(source);
1d2e2129 sago007 2015-12-23 15:41 522
	int ulen = U8_strlen(string);
078900fe sago007 2015-12-05 15:31 523
1d2e2129 sago007 2015-12-23 15:41 524
	if (position == -1) {
1d2e2129 sago007 2015-12-23 15:41 525
		position = ulen;
1d2e2129 sago007 2015-12-23 15:41 526
	}
078900fe sago007 2015-12-05 15:31 527
1d2e2129 sago007 2015-12-23 15:41 528
	if (string == NULL || source == NULL || position < 0 || position > ulen || len + add_len + 1 > max_bytes) {
1d2e2129 sago007 2015-12-23 15:41 529
		return 0;
1d2e2129 sago007 2015-12-23 15:41 530
	}
078900fe sago007 2015-12-05 15:31 531
1d2e2129 sago007 2015-12-23 15:41 532
	// Move string pointer to the proper position
1d2e2129 sago007 2015-12-23 15:41 533
	pos_bytes = 0;
1d2e2129 sago007 2015-12-23 15:41 534
	while (*string != '\0' && pos_bytes < position) {
1d2e2129 sago007 2015-12-23 15:41 535
		string = (char*)U8_next(string);
1d2e2129 sago007 2015-12-23 15:41 536
		++pos_bytes;
1d2e2129 sago007 2015-12-23 15:41 537
	}
078900fe sago007 2015-12-05 15:31 538
1d2e2129 sago007 2015-12-23 15:41 539
	// Move the rest of the string out of the way
1d2e2129 sago007 2015-12-23 15:41 540
	memmove(string + add_len, string, len - pos_bytes + 1);
1d2e2129 sago007 2015-12-23 15:41 541
1d2e2129 sago007 2015-12-23 15:41 542
	// Copy in the new characters
1d2e2129 sago007 2015-12-23 15:41 543
	memcpy(string, source, add_len);
1d2e2129 sago007 2015-12-23 15:41 544
1d2e2129 sago007 2015-12-23 15:41 545
	return 1;
1d2e2129 sago007 2015-12-23 15:41 546
}
1d2e2129 sago007 2015-12-23 15:41 547
1d2e2129 sago007 2015-12-23 15:41 548
void U8_strdel(char* string, int position) {
1d2e2129 sago007 2015-12-23 15:41 549
	if (string == NULL || position < 0) {
1d2e2129 sago007 2015-12-23 15:41 550
		return;
1d2e2129 sago007 2015-12-23 15:41 551
	}
1d2e2129 sago007 2015-12-23 15:41 552
1d2e2129 sago007 2015-12-23 15:41 553
	while (*string != '\0') {
1d2e2129 sago007 2015-12-23 15:41 554
		if (position == 0) {
1d2e2129 sago007 2015-12-23 15:41 555
			int chars_to_erase = U8_charsize(string);
1d2e2129 sago007 2015-12-23 15:41 556
			int remaining_bytes = strlen(string) + 1;
1d2e2129 sago007 2015-12-23 15:41 557
			memmove(string, string + chars_to_erase, remaining_bytes);
1d2e2129 sago007 2015-12-23 15:41 558
			break;
1d2e2129 sago007 2015-12-23 15:41 559
		}
1d2e2129 sago007 2015-12-23 15:41 560
1d2e2129 sago007 2015-12-23 15:41 561
		string = (char*)U8_next(string);
1d2e2129 sago007 2015-12-23 15:41 562
		--position;
1d2e2129 sago007 2015-12-23 15:41 563
	}
1d2e2129 sago007 2015-12-23 15:41 564
}
1d2e2129 sago007 2015-12-23 15:41 565
1d2e2129 sago007 2015-12-23 15:41 566
1d2e2129 sago007 2015-12-23 15:41 567
1d2e2129 sago007 2015-12-23 15:41 568
1d2e2129 sago007 2015-12-23 15:41 569
1d2e2129 sago007 2015-12-23 15:41 570
static_inline FC_Rect FC_RectUnion(FC_Rect A, FC_Rect B) {
1d2e2129 sago007 2015-12-23 15:41 571
	float x,x2,y,y2;
1d2e2129 sago007 2015-12-23 15:41 572
	x = FC_MIN(A.x, B.x);
1d2e2129 sago007 2015-12-23 15:41 573
	y = FC_MIN(A.y, B.y);
1d2e2129 sago007 2015-12-23 15:41 574
	x2 = FC_MAX(A.x+A.w, B.x+B.w);
1d2e2129 sago007 2015-12-23 15:41 575
	y2 = FC_MAX(A.y+A.h, B.y+B.h);
1d2e2129 sago007 2015-12-23 15:41 576
	{
1d2e2129 sago007 2015-12-23 15:41 577
		FC_Rect result = {x, y, FC_MAX(0, x2 - x), FC_MAX(0, y2 - y)};
1d2e2129 sago007 2015-12-23 15:41 578
		return result;
1d2e2129 sago007 2015-12-23 15:41 579
	}
078900fe sago007 2015-12-05 15:31 580
}
078900fe sago007 2015-12-05 15:31 581
078900fe sago007 2015-12-05 15:31 582
// Adapted from SDL_IntersectRect
1d2e2129 sago007 2015-12-23 15:41 583
static_inline FC_Rect FC_RectIntersect(FC_Rect A, FC_Rect B) {
1d2e2129 sago007 2015-12-23 15:41 584
	FC_Rect result;
078900fe sago007 2015-12-05 15:31 585
	float Amin, Amax, Bmin, Bmax;
078900fe sago007 2015-12-05 15:31 586
078900fe sago007 2015-12-05 15:31 587
	// Horizontal intersection
078900fe sago007 2015-12-05 15:31 588
	Amin = A.x;
078900fe sago007 2015-12-05 15:31 589
	Amax = Amin + A.w;
078900fe sago007 2015-12-05 15:31 590
	Bmin = B.x;
078900fe sago007 2015-12-05 15:31 591
	Bmax = Bmin + B.w;
1d2e2129 sago007 2015-12-23 15:41 592
	if (Bmin > Amin) {
1d2e2129 sago007 2015-12-23 15:41 593
		Amin = Bmin;
1d2e2129 sago007 2015-12-23 15:41 594
	}
078900fe sago007 2015-12-05 15:31 595
	result.x = Amin;
1d2e2129 sago007 2015-12-23 15:41 596
	if (Bmax < Amax) {
1d2e2129 sago007 2015-12-23 15:41 597
		Amax = Bmax;
1d2e2129 sago007 2015-12-23 15:41 598
	}
078900fe sago007 2015-12-05 15:31 599
	result.w = Amax - Amin > 0 ? Amax - Amin : 0;
078900fe sago007 2015-12-05 15:31 600
078900fe sago007 2015-12-05 15:31 601
	// Vertical intersection
078900fe sago007 2015-12-05 15:31 602
	Amin = A.y;
078900fe sago007 2015-12-05 15:31 603
	Amax = Amin + A.h;
078900fe sago007 2015-12-05 15:31 604
	Bmin = B.y;
078900fe sago007 2015-12-05 15:31 605
	Bmax = Bmin + B.h;
1d2e2129 sago007 2015-12-23 15:41 606
	if (Bmin > Amin) {
1d2e2129 sago007 2015-12-23 15:41 607
		Amin = Bmin;
1d2e2129 sago007 2015-12-23 15:41 608
	}
078900fe sago007 2015-12-05 15:31 609
	result.y = Amin;
1d2e2129 sago007 2015-12-23 15:41 610
	if (Bmax < Amax) {
1d2e2129 sago007 2015-12-23 15:41 611
		Amax = Bmax;
1d2e2129 sago007 2015-12-23 15:41 612
	}
078900fe sago007 2015-12-05 15:31 613
	result.h = Amax - Amin > 0 ? Amax - Amin : 0;
078900fe sago007 2015-12-05 15:31 614
078900fe sago007 2015-12-05 15:31 615
	return result;
078900fe sago007 2015-12-05 15:31 616
}
078900fe sago007 2015-12-05 15:31 617
078900fe sago007 2015-12-05 15:31 618
078900fe sago007 2015-12-05 15:31 619
078900fe sago007 2015-12-05 15:31 620
078900fe sago007 2015-12-05 15:31 621
078900fe sago007 2015-12-05 15:31 622
078900fe sago007 2015-12-05 15:31 623
078900fe sago007 2015-12-05 15:31 624
078900fe sago007 2015-12-05 15:31 625
078900fe sago007 2015-12-05 15:31 626
078900fe sago007 2015-12-05 15:31 627
078900fe sago007 2015-12-05 15:31 628
078900fe sago007 2015-12-05 15:31 629
078900fe sago007 2015-12-05 15:31 630
1d2e2129 sago007 2015-12-23 15:41 631
FC_Rect FC_DefaultRenderCallback(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale) {
1d2e2129 sago007 2015-12-23 15:41 632
	float w = srcrect->w * xscale;
1d2e2129 sago007 2015-12-23 15:41 633
	float h = srcrect->h * yscale;
1d2e2129 sago007 2015-12-23 15:41 634
	FC_Rect result;
078900fe sago007 2015-12-05 15:31 635
1d2e2129 sago007 2015-12-23 15:41 636
	// FIXME: Why does the scaled offset look so wrong?
1d2e2129 sago007 2015-12-23 15:41 637
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 638
	{
1d2e2129 sago007 2015-12-23 15:41 639
		GPU_Rect r = *srcrect;
1d2e2129 sago007 2015-12-23 15:41 640
		GPU_BlitScale(src, &r, dest, x + xscale*r.w/2.0f, y + r.h/2.0f, xscale, yscale);
1d2e2129 sago007 2015-12-23 15:41 641
	}
1d2e2129 sago007 2015-12-23 15:41 642
#else
1d2e2129 sago007 2015-12-23 15:41 643
	{
1d2e2129 sago007 2015-12-23 15:41 644
		int flip = SDL_FLIP_NONE;
1d2e2129 sago007 2015-12-23 15:41 645
		if (xscale < 0) {
1d2e2129 sago007 2015-12-23 15:41 646
			xscale = -xscale;
1d2e2129 sago007 2015-12-23 15:41 647
			flip |= SDL_FLIP_HORIZONTAL;
1d2e2129 sago007 2015-12-23 15:41 648
		}
1d2e2129 sago007 2015-12-23 15:41 649
		if (yscale < 0) {
1d2e2129 sago007 2015-12-23 15:41 650
			yscale = -yscale;
1d2e2129 sago007 2015-12-23 15:41 651
			flip |= SDL_FLIP_VERTICAL;
1d2e2129 sago007 2015-12-23 15:41 652
		}
1d2e2129 sago007 2015-12-23 15:41 653
1d2e2129 sago007 2015-12-23 15:41 654
		SDL_Rect r = *srcrect;
1d2e2129 sago007 2015-12-23 15:41 655
		SDL_Rect dr = {(int)x, (int)y, (int)(xscale*r.w), (int)(yscale*r.h)};
1d2e2129 sago007 2015-12-23 15:41 656
		SDL_RenderCopyEx(dest, src, &r, &dr, 0, NULL, (SDL_RendererFlip)flip);
1d2e2129 sago007 2015-12-23 15:41 657
	}
1d2e2129 sago007 2015-12-23 15:41 658
#endif
1d2e2129 sago007 2015-12-23 15:41 659
1d2e2129 sago007 2015-12-23 15:41 660
	result.x = x;
1d2e2129 sago007 2015-12-23 15:41 661
	result.y = y;
1d2e2129 sago007 2015-12-23 15:41 662
	result.w = w;
1d2e2129 sago007 2015-12-23 15:41 663
	result.h = h;
1d2e2129 sago007 2015-12-23 15:41 664
	return result;
078900fe sago007 2015-12-05 15:31 665
}
078900fe sago007 2015-12-05 15:31 666
078900fe sago007 2015-12-05 15:31 667
static FC_Rect (*fc_render_callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale) = &FC_DefaultRenderCallback;
078900fe sago007 2015-12-05 15:31 668
1d2e2129 sago007 2015-12-23 15:41 669
void FC_SetRenderCallback(FC_Rect (*callback)(FC_Image* src, FC_Rect* srcrect, FC_Target* dest, float x, float y, float xscale, float yscale)) {
1d2e2129 sago007 2015-12-23 15:41 670
	if (callback == NULL) {
1d2e2129 sago007 2015-12-23 15:41 671
		fc_render_callback = &FC_DefaultRenderCallback;
1d2e2129 sago007 2015-12-23 15:41 672
	}
1d2e2129 sago007 2015-12-23 15:41 673
	else {
1d2e2129 sago007 2015-12-23 15:41 674
		fc_render_callback = callback;
1d2e2129 sago007 2015-12-23 15:41 675
	}
1d2e2129 sago007 2015-12-23 15:41 676
}
1d2e2129 sago007 2015-12-23 15:41 677
1d2e2129 sago007 2015-12-23 15:41 678
void FC_GetUTF8FromCodepoint(char* result, Uint32 codepoint) {
1d2e2129 sago007 2015-12-23 15:41 679
	char a, b, c, d;
1d2e2129 sago007 2015-12-23 15:41 680
1d2e2129 sago007 2015-12-23 15:41 681
	if (result == NULL) {
1d2e2129 sago007 2015-12-23 15:41 682
		return;
1d2e2129 sago007 2015-12-23 15:41 683
	}
1d2e2129 sago007 2015-12-23 15:41 684
1d2e2129 sago007 2015-12-23 15:41 685
	a = (codepoint >> 24) & 0xFF;
1d2e2129 sago007 2015-12-23 15:41 686
	b = (codepoint >> 16) & 0xFF;
1d2e2129 sago007 2015-12-23 15:41 687
	c = (codepoint >> 8) & 0xFF;
1d2e2129 sago007 2015-12-23 15:41 688
	d = codepoint & 0xFF;
1d2e2129 sago007 2015-12-23 15:41 689
1d2e2129 sago007 2015-12-23 15:41 690
	if (a == 0) {
1d2e2129 sago007 2015-12-23 15:41 691
		if (b == 0) {
1d2e2129 sago007 2015-12-23 15:41 692
			if (c == 0) {
1d2e2129 sago007 2015-12-23 15:41 693
				result[0] = d;
1d2e2129 sago007 2015-12-23 15:41 694
				result[1] = '\0';
1d2e2129 sago007 2015-12-23 15:41 695
			}
1d2e2129 sago007 2015-12-23 15:41 696
			else {
1d2e2129 sago007 2015-12-23 15:41 697
				result[0] = c;
1d2e2129 sago007 2015-12-23 15:41 698
				result[1] = d;
1d2e2129 sago007 2015-12-23 15:41 699
				result[2] = '\0';
1d2e2129 sago007 2015-12-23 15:41 700
			}
1d2e2129 sago007 2015-12-23 15:41 701
		}
1d2e2129 sago007 2015-12-23 15:41 702
		else {
1d2e2129 sago007 2015-12-23 15:41 703
			result[0] = b;
1d2e2129 sago007 2015-12-23 15:41 704
			result[1] = c;
1d2e2129 sago007 2015-12-23 15:41 705
			result[2] = d;
1d2e2129 sago007 2015-12-23 15:41 706
			result[3] = '\0';
1d2e2129 sago007 2015-12-23 15:41 707
		}
1d2e2129 sago007 2015-12-23 15:41 708
	}
1d2e2129 sago007 2015-12-23 15:41 709
	else {
1d2e2129 sago007 2015-12-23 15:41 710
		result[0] = a;
1d2e2129 sago007 2015-12-23 15:41 711
		result[1] = b;
1d2e2129 sago007 2015-12-23 15:41 712
		result[2] = c;
1d2e2129 sago007 2015-12-23 15:41 713
		result[3] = d;
1d2e2129 sago007 2015-12-23 15:41 714
		result[4] = '\0';
1d2e2129 sago007 2015-12-23 15:41 715
	}
1d2e2129 sago007 2015-12-23 15:41 716
}
1d2e2129 sago007 2015-12-23 15:41 717
1d2e2129 sago007 2015-12-23 15:41 718
Uint32 FC_GetCodepointFromUTF8(const char** c, Uint8 advance_pointer) {
1d2e2129 sago007 2015-12-23 15:41 719
	Uint32 result = 0;
1d2e2129 sago007 2015-12-23 15:41 720
	const char* str;
1d2e2129 sago007 2015-12-23 15:41 721
	if (c == NULL || *c == NULL) {
1d2e2129 sago007 2015-12-23 15:41 722
		return 0;
1d2e2129 sago007 2015-12-23 15:41 723
	}
1d2e2129 sago007 2015-12-23 15:41 724
1d2e2129 sago007 2015-12-23 15:41 725
	str = *c;
1d2e2129 sago007 2015-12-23 15:41 726
	if ((unsigned char)*str <= 0x7F) {
1d2e2129 sago007 2015-12-23 15:41 727
		result = *str;
1d2e2129 sago007 2015-12-23 15:41 728
	}
1d2e2129 sago007 2015-12-23 15:41 729
	else if ((unsigned char)*str < 0xE0) {
1d2e2129 sago007 2015-12-23 15:41 730
		result |= (unsigned char)(*str) << 8;
1d2e2129 sago007 2015-12-23 15:41 731
		result |= (unsigned char)(*(str+1));
1d2e2129 sago007 2015-12-23 15:41 732
		if (advance_pointer) {
1d2e2129 sago007 2015-12-23 15:41 733
			*c += 1;
1d2e2129 sago007 2015-12-23 15:41 734
		}
1d2e2129 sago007 2015-12-23 15:41 735
	}
1d2e2129 sago007 2015-12-23 15:41 736
	else if ((unsigned char)*str < 0xF0) {
1d2e2129 sago007 2015-12-23 15:41 737
		result |= (unsigned char)(*str) << 16;
1d2e2129 sago007 2015-12-23 15:41 738
		result |= (unsigned char)(*(str+1)) << 8;
1d2e2129 sago007 2015-12-23 15:41 739
		result |= (unsigned char)(*(str+2));
1d2e2129 sago007 2015-12-23 15:41 740
		if (advance_pointer) {
1d2e2129 sago007 2015-12-23 15:41 741
			*c += 2;
1d2e2129 sago007 2015-12-23 15:41 742
		}
1d2e2129 sago007 2015-12-23 15:41 743
	}
1d2e2129 sago007 2015-12-23 15:41 744
	else {
1d2e2129 sago007 2015-12-23 15:41 745
		result |= (unsigned char)(*str) << 24;
1d2e2129 sago007 2015-12-23 15:41 746
		result |= (unsigned char)(*(str+1)) << 16;
1d2e2129 sago007 2015-12-23 15:41 747
		result |= (unsigned char)(*(str+2)) << 8;
1d2e2129 sago007 2015-12-23 15:41 748
		result |= (unsigned char)(*(str+3));
1d2e2129 sago007 2015-12-23 15:41 749
		if (advance_pointer) {
1d2e2129 sago007 2015-12-23 15:41 750
			*c += 3;
1d2e2129 sago007 2015-12-23 15:41 751
		}
1d2e2129 sago007 2015-12-23 15:41 752
	}
1d2e2129 sago007 2015-12-23 15:41 753
	return result;
078900fe sago007 2015-12-05 15:31 754
}
078900fe sago007 2015-12-05 15:31 755
078900fe sago007 2015-12-05 15:31 756
1d2e2129 sago007 2015-12-23 15:41 757
void FC_SetLoadingString(FC_Font* font, const char* string) {
1d2e2129 sago007 2015-12-23 15:41 758
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 759
		return;
1d2e2129 sago007 2015-12-23 15:41 760
	}
078900fe sago007 2015-12-05 15:31 761
1d2e2129 sago007 2015-12-23 15:41 762
	free(font->loading_string);
1d2e2129 sago007 2015-12-23 15:41 763
	font->loading_string = U8_strdup(string);
078900fe sago007 2015-12-05 15:31 764
}
078900fe sago007 2015-12-05 15:31 765
078900fe sago007 2015-12-05 15:31 766
1d2e2129 sago007 2015-12-23 15:41 767
void FC_SetBufferSize(unsigned int size) {
1d2e2129 sago007 2015-12-23 15:41 768
	free(fc_buffer);
1d2e2129 sago007 2015-12-23 15:41 769
	if (size > 0) {
1d2e2129 sago007 2015-12-23 15:41 770
		fc_buffer = (char*)malloc(size);
1d2e2129 sago007 2015-12-23 15:41 771
	}
1d2e2129 sago007 2015-12-23 15:41 772
	else {
1d2e2129 sago007 2015-12-23 15:41 773
		fc_buffer = (char*)malloc(1024);
1d2e2129 sago007 2015-12-23 15:41 774
	}
078900fe sago007 2015-12-05 15:31 775
}
078900fe sago007 2015-12-05 15:31 776
078900fe sago007 2015-12-05 15:31 777
078900fe sago007 2015-12-05 15:31 778
078900fe sago007 2015-12-05 15:31 779
078900fe sago007 2015-12-05 15:31 780
078900fe sago007 2015-12-05 15:31 781
// Constructors
078900fe sago007 2015-12-05 15:31 782
1d2e2129 sago007 2015-12-23 15:41 783
static void FC_Init(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 784
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 785
		return;
1d2e2129 sago007 2015-12-23 15:41 786
	}
078900fe sago007 2015-12-05 15:31 787
1d2e2129 sago007 2015-12-23 15:41 788
#ifndef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 789
	font->renderer = NULL;
1d2e2129 sago007 2015-12-23 15:41 790
#endif
078900fe sago007 2015-12-05 15:31 791
1d2e2129 sago007 2015-12-23 15:41 792
	font->ttf_source = NULL;
1d2e2129 sago007 2015-12-23 15:41 793
	font->owns_ttf_source = 0;
078900fe sago007 2015-12-05 15:31 794
1d2e2129 sago007 2015-12-23 15:41 795
	font->filter = FC_FILTER_NEAREST;
078900fe sago007 2015-12-05 15:31 796
1d2e2129 sago007 2015-12-23 15:41 797
	font->default_color.r = 0;
1d2e2129 sago007 2015-12-23 15:41 798
	font->default_color.g = 0;
1d2e2129 sago007 2015-12-23 15:41 799
	font->default_color.b = 0;
1d2e2129 sago007 2015-12-23 15:41 800
	FC_GET_ALPHA(font->default_color) = 255;
078900fe sago007 2015-12-05 15:31 801
1d2e2129 sago007 2015-12-23 15:41 802
	font->height = 0; // ascent+descent
078900fe sago007 2015-12-05 15:31 803
1d2e2129 sago007 2015-12-23 15:41 804
	font->maxWidth = 0;
1d2e2129 sago007 2015-12-23 15:41 805
	font->baseline = 0;
1d2e2129 sago007 2015-12-23 15:41 806
	font->ascent = 0;
1d2e2129 sago007 2015-12-23 15:41 807
	font->descent = 0;
078900fe sago007 2015-12-05 15:31 808
1d2e2129 sago007 2015-12-23 15:41 809
	font->lineSpacing = 0;
1d2e2129 sago007 2015-12-23 15:41 810
	font->letterSpacing = 0;
078900fe sago007 2015-12-05 15:31 811
1d2e2129 sago007 2015-12-23 15:41 812
	// Give a little offset for when filtering/mipmaps are used.  Depending on mipmap level, this will still not be enough.
1d2e2129 sago007 2015-12-23 15:41 813
	font->last_glyph.rect.x = FC_CACHE_PADDING;
1d2e2129 sago007 2015-12-23 15:41 814
	font->last_glyph.rect.y = FC_CACHE_PADDING;
1d2e2129 sago007 2015-12-23 15:41 815
	font->last_glyph.rect.w = 0;
1d2e2129 sago007 2015-12-23 15:41 816
	font->last_glyph.rect.h = 0;
1d2e2129 sago007 2015-12-23 15:41 817
	font->last_glyph.cache_level = 0;
078900fe sago007 2015-12-05 15:31 818
1d2e2129 sago007 2015-12-23 15:41 819
	if (font->glyphs != NULL) {
1d2e2129 sago007 2015-12-23 15:41 820
		FC_MapFree(font->glyphs);
1d2e2129 sago007 2015-12-23 15:41 821
	}
1d2e2129 sago007 2015-12-23 15:41 822
1d2e2129 sago007 2015-12-23 15:41 823
	font->glyphs = FC_MapCreate(FC_DEFAULT_NUM_BUCKETS);
1d2e2129 sago007 2015-12-23 15:41 824
1d2e2129 sago007 2015-12-23 15:41 825
	font->glyph_cache_size = 3;
1d2e2129 sago007 2015-12-23 15:41 826
	font->glyph_cache_count = 0;
1d2e2129 sago007 2015-12-23 15:41 827
1d2e2129 sago007 2015-12-23 15:41 828
1d2e2129 sago007 2015-12-23 15:41 829
	font->glyph_cache = (FC_Image**)malloc(font->glyph_cache_size * sizeof(FC_Image*));
1d2e2129 sago007 2015-12-23 15:41 830
1d2e2129 sago007 2015-12-23 15:41 831
	if (font->loading_string == NULL) {
1d2e2129 sago007 2015-12-23 15:41 832
		font->loading_string = U8_strdup(FC_GetStringASCII());
1d2e2129 sago007 2015-12-23 15:41 833
	}
1d2e2129 sago007 2015-12-23 15:41 834
1d2e2129 sago007 2015-12-23 15:41 835
	if (fc_buffer == NULL) {
1d2e2129 sago007 2015-12-23 15:41 836
		fc_buffer = (char*)malloc(1024);
1d2e2129 sago007 2015-12-23 15:41 837
	}
1d2e2129 sago007 2015-12-23 15:41 838
}
078900fe sago007 2015-12-05 15:31 839
1d2e2129 sago007 2015-12-23 15:41 840
static Uint8 FC_GrowGlyphCache(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 841
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 842
		return 0;
1d2e2129 sago007 2015-12-23 15:41 843
	}
078900fe sago007 2015-12-05 15:31 844
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 845
	GPU_Image* new_level = GPU_CreateImage(font->height * 12, font->height * 12, GPU_FORMAT_RGBA);
078900fe sago007 2015-12-05 15:31 846
#else
1d2e2129 sago007 2015-12-23 15:41 847
	SDL_Texture* new_level = SDL_CreateTexture(font->renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, font->height * 12, font->height * 12);
078900fe sago007 2015-12-05 15:31 848
#endif
1d2e2129 sago007 2015-12-23 15:41 849
	if (new_level == NULL || !FC_SetGlyphCacheLevel(font, font->glyph_cache_count, new_level)) {
1d2e2129 sago007 2015-12-23 15:41 850
		FC_Log("Error: SDL_FontCache ran out of packing space and could not add another cache level.\n");
078900fe sago007 2015-12-05 15:31 851
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 852
		GPU_FreeImage(new_level);
078900fe sago007 2015-12-05 15:31 853
#else
1d2e2129 sago007 2015-12-23 15:41 854
		SDL_DestroyTexture(new_level);
078900fe sago007 2015-12-05 15:31 855
#endif
1d2e2129 sago007 2015-12-23 15:41 856
		return 0;
1d2e2129 sago007 2015-12-23 15:41 857
	}
1d2e2129 sago007 2015-12-23 15:41 858
	return 1;
078900fe sago007 2015-12-05 15:31 859
}
078900fe sago007 2015-12-05 15:31 860
1d2e2129 sago007 2015-12-23 15:41 861
static Uint8 FC_UploadGlyphCache(FC_Font* font, int cache_level, SDL_Surface* data_surface) {
1d2e2129 sago007 2015-12-23 15:41 862
	if (font == NULL || data_surface == NULL) {
1d2e2129 sago007 2015-12-23 15:41 863
		return 0;
1d2e2129 sago007 2015-12-23 15:41 864
	}
078900fe sago007 2015-12-05 15:31 865
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 866
	GPU_Image* new_level = GPU_CopyImageFromSurface(data_surface);
1d2e2129 sago007 2015-12-23 15:41 867
	if (FC_GetFilterMode(font) == FC_FILTER_LINEAR) {
1d2e2129 sago007 2015-12-23 15:41 868
		GPU_SetImageFilter(new_level, GPU_FILTER_LINEAR);
1d2e2129 sago007 2015-12-23 15:41 869
	}
1d2e2129 sago007 2015-12-23 15:41 870
	else {
1d2e2129 sago007 2015-12-23 15:41 871
		GPU_SetImageFilter(new_level, GPU_FILTER_NEAREST);
1d2e2129 sago007 2015-12-23 15:41 872
	}
078900fe sago007 2015-12-05 15:31 873
#else
1d2e2129 sago007 2015-12-23 15:41 874
	SDL_Texture* new_level;
1d2e2129 sago007 2015-12-23 15:41 875
	if (!fc_has_render_target_support) {
1d2e2129 sago007 2015-12-23 15:41 876
		new_level = SDL_CreateTextureFromSurface(font->renderer, data_surface);
1d2e2129 sago007 2015-12-23 15:41 877
	}
1d2e2129 sago007 2015-12-23 15:41 878
	else {
1d2e2129 sago007 2015-12-23 15:41 879
		// Must upload with render target enabled so we can put more glyphs on later
1d2e2129 sago007 2015-12-23 15:41 880
		SDL_Renderer* renderer = font->renderer;
1d2e2129 sago007 2015-12-23 15:41 881
1d2e2129 sago007 2015-12-23 15:41 882
		// Set filter mode for new texture
1d2e2129 sago007 2015-12-23 15:41 883
		const char* old_filter_mode = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
1d2e2129 sago007 2015-12-23 15:41 884
		if (FC_GetFilterMode(font) == FC_FILTER_LINEAR) {
1d2e2129 sago007 2015-12-23 15:41 885
			SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
1d2e2129 sago007 2015-12-23 15:41 886
		}
1d2e2129 sago007 2015-12-23 15:41 887
		else {
1d2e2129 sago007 2015-12-23 15:41 888
			SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
1d2e2129 sago007 2015-12-23 15:41 889
		}
1d2e2129 sago007 2015-12-23 15:41 890
1d2e2129 sago007 2015-12-23 15:41 891
		new_level = SDL_CreateTexture(renderer, data_surface->format->format, SDL_TEXTUREACCESS_TARGET, data_surface->w, data_surface->h);
1d2e2129 sago007 2015-12-23 15:41 892
		SDL_SetTextureBlendMode(new_level, SDL_BLENDMODE_BLEND);
1d2e2129 sago007 2015-12-23 15:41 893
1d2e2129 sago007 2015-12-23 15:41 894
		// Reset filter mode for the temp texture
1d2e2129 sago007 2015-12-23 15:41 895
		SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
1d2e2129 sago007 2015-12-23 15:41 896
1d2e2129 sago007 2015-12-23 15:41 897
		{
1d2e2129 sago007 2015-12-23 15:41 898
			Uint8 r, g, b, a;
1d2e2129 sago007 2015-12-23 15:41 899
			SDL_Texture* temp = SDL_CreateTextureFromSurface(renderer, data_surface);
1d2e2129 sago007 2015-12-23 15:41 900
			SDL_SetTextureBlendMode(temp, SDL_BLENDMODE_NONE);
1d2e2129 sago007 2015-12-23 15:41 901
			SDL_SetRenderTarget(renderer, new_level);
1d2e2129 sago007 2015-12-23 15:41 902
1d2e2129 sago007 2015-12-23 15:41 903
			SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);
1d2e2129 sago007 2015-12-23 15:41 904
			SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 905
			SDL_RenderClear(renderer);
1d2e2129 sago007 2015-12-23 15:41 906
			SDL_SetRenderDrawColor(renderer, r, g, b, a);
1d2e2129 sago007 2015-12-23 15:41 907
1d2e2129 sago007 2015-12-23 15:41 908
			SDL_RenderCopy(renderer, temp, NULL, NULL);
1d2e2129 sago007 2015-12-23 15:41 909
			SDL_SetRenderTarget(renderer, NULL);
1d2e2129 sago007 2015-12-23 15:41 910
1d2e2129 sago007 2015-12-23 15:41 911
			SDL_DestroyTexture(temp);
1d2e2129 sago007 2015-12-23 15:41 912
		}
1d2e2129 sago007 2015-12-23 15:41 913
1d2e2129 sago007 2015-12-23 15:41 914
		// Reset to the old filter value
1d2e2129 sago007 2015-12-23 15:41 915
		SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, old_filter_mode);
1d2e2129 sago007 2015-12-23 15:41 916
1d2e2129 sago007 2015-12-23 15:41 917
	}
078900fe sago007 2015-12-05 15:31 918
#endif
1d2e2129 sago007 2015-12-23 15:41 919
	if (new_level == NULL || !FC_SetGlyphCacheLevel(font, cache_level, new_level)) {
1d2e2129 sago007 2015-12-23 15:41 920
		FC_Log("Error: SDL_FontCache ran out of packing space and could not add another cache level.\n");
1d2e2129 sago007 2015-12-23 15:41 921
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 922
		GPU_FreeImage(new_level);
1d2e2129 sago007 2015-12-23 15:41 923
#else
1d2e2129 sago007 2015-12-23 15:41 924
		SDL_DestroyTexture(new_level);
1d2e2129 sago007 2015-12-23 15:41 925
#endif
1d2e2129 sago007 2015-12-23 15:41 926
		return 0;
1d2e2129 sago007 2015-12-23 15:41 927
	}
1d2e2129 sago007 2015-12-23 15:41 928
	return 1;
078900fe sago007 2015-12-05 15:31 929
}
078900fe sago007 2015-12-05 15:31 930
1d2e2129 sago007 2015-12-23 15:41 931
static FC_GlyphData* FC_PackGlyphData(FC_Font* font, Uint32 codepoint, Uint16 width, Uint16 maxWidth, Uint16 maxHeight) {
1d2e2129 sago007 2015-12-23 15:41 932
	FC_Map* glyphs = font->glyphs;
1d2e2129 sago007 2015-12-23 15:41 933
	FC_GlyphData* last_glyph = &font->last_glyph;
1d2e2129 sago007 2015-12-23 15:41 934
	Uint16 height = font->height + FC_CACHE_PADDING;
078900fe sago007 2015-12-05 15:31 935
1d2e2129 sago007 2015-12-23 15:41 936
	if (last_glyph->rect.x + last_glyph->rect.w + width >= maxWidth - FC_CACHE_PADDING) {
1d2e2129 sago007 2015-12-23 15:41 937
		if (last_glyph->rect.y + height + height >= maxHeight - FC_CACHE_PADDING) {
1d2e2129 sago007 2015-12-23 15:41 938
			// Get ready to pack on the next cache level when it is ready
1d2e2129 sago007 2015-12-23 15:41 939
			last_glyph->cache_level = font->glyph_cache_count;
1d2e2129 sago007 2015-12-23 15:41 940
			last_glyph->rect.x = FC_CACHE_PADDING;
1d2e2129 sago007 2015-12-23 15:41 941
			last_glyph->rect.y = FC_CACHE_PADDING;
1d2e2129 sago007 2015-12-23 15:41 942
			last_glyph->rect.w = 0;
1d2e2129 sago007 2015-12-23 15:41 943
			return NULL;
1d2e2129 sago007 2015-12-23 15:41 944
		}
1d2e2129 sago007 2015-12-23 15:41 945
		else {
1d2e2129 sago007 2015-12-23 15:41 946
			// Go to next row
1d2e2129 sago007 2015-12-23 15:41 947
			last_glyph->rect.x = FC_CACHE_PADDING;
1d2e2129 sago007 2015-12-23 15:41 948
			last_glyph->rect.y += height;
1d2e2129 sago007 2015-12-23 15:41 949
			last_glyph->rect.w = 0;
1d2e2129 sago007 2015-12-23 15:41 950
		}
1d2e2129 sago007 2015-12-23 15:41 951
	}
1d2e2129 sago007 2015-12-23 15:41 952
1d2e2129 sago007 2015-12-23 15:41 953
	// Move to next space
1d2e2129 sago007 2015-12-23 15:41 954
	last_glyph->rect.x += last_glyph->rect.w + 1 + FC_CACHE_PADDING;
1d2e2129 sago007 2015-12-23 15:41 955
	last_glyph->rect.w = width;
1d2e2129 sago007 2015-12-23 15:41 956
1d2e2129 sago007 2015-12-23 15:41 957
	return FC_MapInsert(glyphs, codepoint, FC_MakeGlyphData(last_glyph->cache_level, last_glyph->rect.x, last_glyph->rect.y, last_glyph->rect.w, last_glyph->rect.h));
078900fe sago007 2015-12-05 15:31 958
}
078900fe sago007 2015-12-05 15:31 959
078900fe sago007 2015-12-05 15:31 960
1d2e2129 sago007 2015-12-23 15:41 961
FC_Image* FC_GetGlyphCacheLevel(FC_Font* font, int cache_level) {
1d2e2129 sago007 2015-12-23 15:41 962
	if (font == NULL || cache_level < 0 || cache_level > font->glyph_cache_count) {
1d2e2129 sago007 2015-12-23 15:41 963
		return NULL;
1d2e2129 sago007 2015-12-23 15:41 964
	}
1d2e2129 sago007 2015-12-23 15:41 965
1d2e2129 sago007 2015-12-23 15:41 966
	return font->glyph_cache[cache_level];
1d2e2129 sago007 2015-12-23 15:41 967
}
1d2e2129 sago007 2015-12-23 15:41 968
1d2e2129 sago007 2015-12-23 15:41 969
Uint8 FC_SetGlyphCacheLevel(FC_Font* font, int cache_level, FC_Image* cache_texture) {
1d2e2129 sago007 2015-12-23 15:41 970
	if (font == NULL || cache_level < 0) {
1d2e2129 sago007 2015-12-23 15:41 971
		return 0;
1d2e2129 sago007 2015-12-23 15:41 972
	}
1d2e2129 sago007 2015-12-23 15:41 973
1d2e2129 sago007 2015-12-23 15:41 974
	// Must be sequentially added
1d2e2129 sago007 2015-12-23 15:41 975
	if (cache_level > font->glyph_cache_count + 1) {
1d2e2129 sago007 2015-12-23 15:41 976
		return 0;
1d2e2129 sago007 2015-12-23 15:41 977
	}
1d2e2129 sago007 2015-12-23 15:41 978
1d2e2129 sago007 2015-12-23 15:41 979
	if (cache_level == font->glyph_cache_count) {
1d2e2129 sago007 2015-12-23 15:41 980
		font->glyph_cache_count++;
1d2e2129 sago007 2015-12-23 15:41 981
1d2e2129 sago007 2015-12-23 15:41 982
		// Grow cache?
1d2e2129 sago007 2015-12-23 15:41 983
		if (font->glyph_cache_count > font->glyph_cache_size) {
1d2e2129 sago007 2015-12-23 15:41 984
			// Copy old cache to new one
1d2e2129 sago007 2015-12-23 15:41 985
			int i;
1d2e2129 sago007 2015-12-23 15:41 986
			FC_Image** new_cache;
1d2e2129 sago007 2015-12-23 15:41 987
			new_cache = (FC_Image**)malloc(font->glyph_cache_count * sizeof(FC_Image*));
1d2e2129 sago007 2015-12-23 15:41 988
			for (i = 0; i < font->glyph_cache_size; ++i) {
1d2e2129 sago007 2015-12-23 15:41 989
				new_cache[i] = font->glyph_cache[i];
1d2e2129 sago007 2015-12-23 15:41 990
			}
1d2e2129 sago007 2015-12-23 15:41 991
1d2e2129 sago007 2015-12-23 15:41 992
			// Save new cache
1d2e2129 sago007 2015-12-23 15:41 993
			free(font->glyph_cache);
1d2e2129 sago007 2015-12-23 15:41 994
			font->glyph_cache_size = font->glyph_cache_count;
1d2e2129 sago007 2015-12-23 15:41 995
			font->glyph_cache = new_cache;
1d2e2129 sago007 2015-12-23 15:41 996
		}
1d2e2129 sago007 2015-12-23 15:41 997
	}
1d2e2129 sago007 2015-12-23 15:41 998
1d2e2129 sago007 2015-12-23 15:41 999
	font->glyph_cache[cache_level] = cache_texture;
1d2e2129 sago007 2015-12-23 15:41 1000
	return 1;
078900fe sago007 2015-12-05 15:31 1001
}
078900fe sago007 2015-12-05 15:31 1002
1d2e2129 sago007 2015-12-23 15:41 1003
1d2e2129 sago007 2015-12-23 15:41 1004
FC_Font* FC_CreateFont(void) {
1d2e2129 sago007 2015-12-23 15:41 1005
	FC_Font* font;
1d2e2129 sago007 2015-12-23 15:41 1006
1d2e2129 sago007 2015-12-23 15:41 1007
	font = (FC_Font*)malloc(sizeof(FC_Font));
1d2e2129 sago007 2015-12-23 15:41 1008
	memset(font, 0, sizeof(FC_Font));
1d2e2129 sago007 2015-12-23 15:41 1009
1d2e2129 sago007 2015-12-23 15:41 1010
	FC_Init(font);
1d2e2129 sago007 2015-12-23 15:41 1011
1d2e2129 sago007 2015-12-23 15:41 1012
	return font;
1d2e2129 sago007 2015-12-23 15:41 1013
}
1d2e2129 sago007 2015-12-23 15:41 1014
1d2e2129 sago007 2015-12-23 15:41 1015
1d2e2129 sago007 2015-12-23 15:41 1016
// Assume this many will be enough...
1d2e2129 sago007 2015-12-23 15:41 1017
#define FC_LOAD_MAX_SURFACES 10
1d2e2129 sago007 2015-12-23 15:41 1018
1d2e2129 sago007 2015-12-23 15:41 1019
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1020
Uint8 FC_LoadFontFromTTF(FC_Font* font, TTF_Font* ttf, SDL_Color color)
1d2e2129 sago007 2015-12-23 15:41 1021
#else
1d2e2129 sago007 2015-12-23 15:41 1022
Uint8 FC_LoadFontFromTTF(FC_Font* font, SDL_Renderer* renderer, TTF_Font* ttf, SDL_Color color)
1d2e2129 sago007 2015-12-23 15:41 1023
#endif
078900fe sago007 2015-12-05 15:31 1024
{
1d2e2129 sago007 2015-12-23 15:41 1025
	if (font == NULL || ttf == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1026
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1027
	}
1d2e2129 sago007 2015-12-23 15:41 1028
#ifndef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1029
	if (renderer == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1030
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1031
	}
1d2e2129 sago007 2015-12-23 15:41 1032
#endif
1d2e2129 sago007 2015-12-23 15:41 1033
1d2e2129 sago007 2015-12-23 15:41 1034
	FC_ClearFont(font);
1d2e2129 sago007 2015-12-23 15:41 1035
1d2e2129 sago007 2015-12-23 15:41 1036
1d2e2129 sago007 2015-12-23 15:41 1037
	// Might as well check render target support here
1d2e2129 sago007 2015-12-23 15:41 1038
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1039
	fc_has_render_target_support = GPU_IsFeatureEnabled(GPU_FEATURE_RENDER_TARGETS);
1d2e2129 sago007 2015-12-23 15:41 1040
#else
1d2e2129 sago007 2015-12-23 15:41 1041
	SDL_RendererInfo info;
1d2e2129 sago007 2015-12-23 15:41 1042
	SDL_GetRendererInfo(renderer, &info);
1d2e2129 sago007 2015-12-23 15:41 1043
	fc_has_render_target_support = (info.flags & SDL_RENDERER_TARGETTEXTURE);
1d2e2129 sago007 2015-12-23 15:41 1044
1d2e2129 sago007 2015-12-23 15:41 1045
	font->renderer = renderer;
1d2e2129 sago007 2015-12-23 15:41 1046
#endif
1d2e2129 sago007 2015-12-23 15:41 1047
1d2e2129 sago007 2015-12-23 15:41 1048
	font->ttf_source = ttf;
1d2e2129 sago007 2015-12-23 15:41 1049
1d2e2129 sago007 2015-12-23 15:41 1050
	//font->line_height = TTF_FontLineSkip(ttf);
1d2e2129 sago007 2015-12-23 15:41 1051
	font->height = TTF_FontHeight(ttf);
1d2e2129 sago007 2015-12-23 15:41 1052
	font->ascent = TTF_FontAscent(ttf);
1d2e2129 sago007 2015-12-23 15:41 1053
	font->descent = -TTF_FontDescent(ttf);
1d2e2129 sago007 2015-12-23 15:41 1054
1d2e2129 sago007 2015-12-23 15:41 1055
	font->baseline = font->height - font->descent;
1d2e2129 sago007 2015-12-23 15:41 1056
1d2e2129 sago007 2015-12-23 15:41 1057
	font->default_color = color;
1d2e2129 sago007 2015-12-23 15:41 1058
1d2e2129 sago007 2015-12-23 15:41 1059
	{
1d2e2129 sago007 2015-12-23 15:41 1060
		SDL_Color white = {255, 255, 255, 255};
1d2e2129 sago007 2015-12-23 15:41 1061
		SDL_Surface* glyph_surf;
1d2e2129 sago007 2015-12-23 15:41 1062
		char buff[5];
1d2e2129 sago007 2015-12-23 15:41 1063
		const char* buff_ptr = buff;
1d2e2129 sago007 2015-12-23 15:41 1064
		const char* source_string;
1d2e2129 sago007 2015-12-23 15:41 1065
		Uint8 packed = 0;
1d2e2129 sago007 2015-12-23 15:41 1066
1d2e2129 sago007 2015-12-23 15:41 1067
		// Copy glyphs from the surface to the font texture and store the position data
1d2e2129 sago007 2015-12-23 15:41 1068
		// Pack row by row into a square texture
1d2e2129 sago007 2015-12-23 15:41 1069
		// Try figuring out dimensions that make sense for the font size.
1d2e2129 sago007 2015-12-23 15:41 1070
		unsigned int w = font->height*12;
1d2e2129 sago007 2015-12-23 15:41 1071
		unsigned int h = font->height*12;
1d2e2129 sago007 2015-12-23 15:41 1072
		SDL_Surface* surfaces[FC_LOAD_MAX_SURFACES];
1d2e2129 sago007 2015-12-23 15:41 1073
		int num_surfaces = 1;
1d2e2129 sago007 2015-12-23 15:41 1074
		surfaces[0] = FC_CreateSurface32(w, h);
1d2e2129 sago007 2015-12-23 15:41 1075
		font->last_glyph.rect.x = FC_CACHE_PADDING;
1d2e2129 sago007 2015-12-23 15:41 1076
		font->last_glyph.rect.y = FC_CACHE_PADDING;
1d2e2129 sago007 2015-12-23 15:41 1077
		font->last_glyph.rect.w = 0;
1d2e2129 sago007 2015-12-23 15:41 1078
		font->last_glyph.rect.h = font->height;
1d2e2129 sago007 2015-12-23 15:41 1079
1d2e2129 sago007 2015-12-23 15:41 1080
		memset(buff, 0, 5);
1d2e2129 sago007 2015-12-23 15:41 1081
		source_string = font->loading_string;
1d2e2129 sago007 2015-12-23 15:41 1082
		for (; *source_string != '\0'; source_string = U8_next(source_string)) {
1d2e2129 sago007 2015-12-23 15:41 1083
			if (!U8_charcpy(buff, source_string, 5)) {
1d2e2129 sago007 2015-12-23 15:41 1084
				continue;
1d2e2129 sago007 2015-12-23 15:41 1085
			}
1d2e2129 sago007 2015-12-23 15:41 1086
			glyph_surf = TTF_RenderUTF8_Blended(ttf, buff, white);
1d2e2129 sago007 2015-12-23 15:41 1087
			if (glyph_surf == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1088
				continue;
1d2e2129 sago007 2015-12-23 15:41 1089
			}
1d2e2129 sago007 2015-12-23 15:41 1090
1d2e2129 sago007 2015-12-23 15:41 1091
			// Try packing.  If it fails, create a new surface for the next cache level.
1d2e2129 sago007 2015-12-23 15:41 1092
			packed = (FC_PackGlyphData(font, FC_GetCodepointFromUTF8(&buff_ptr, 0), glyph_surf->w, surfaces[num_surfaces-1]->w, surfaces[num_surfaces-1]->h) != NULL);
1d2e2129 sago007 2015-12-23 15:41 1093
			if (!packed) {
1d2e2129 sago007 2015-12-23 15:41 1094
				int i = num_surfaces-1;
1d2e2129 sago007 2015-12-23 15:41 1095
				if (num_surfaces >= FC_LOAD_MAX_SURFACES) {
1d2e2129 sago007 2015-12-23 15:41 1096
					// Can't do any more!
1d2e2129 sago007 2015-12-23 15:41 1097
					FC_Log("SDL_FontCache error: Could not create enough cache surfaces to fit all of the loading string!\n");
1d2e2129 sago007 2015-12-23 15:41 1098
					SDL_FreeSurface(glyph_surf);
1d2e2129 sago007 2015-12-23 15:41 1099
					break;
1d2e2129 sago007 2015-12-23 15:41 1100
				}
1d2e2129 sago007 2015-12-23 15:41 1101
1d2e2129 sago007 2015-12-23 15:41 1102
				// Upload the current surface to the glyph cache now so we can keep the cache level packing cursor up to date as we go.
1d2e2129 sago007 2015-12-23 15:41 1103
				FC_UploadGlyphCache(font, i, surfaces[i]);
1d2e2129 sago007 2015-12-23 15:41 1104
				SDL_FreeSurface(surfaces[i]);
1d2e2129 sago007 2015-12-23 15:41 1105
#ifndef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1106
				SDL_SetTextureBlendMode(font->glyph_cache[i], SDL_BLENDMODE_BLEND);
1d2e2129 sago007 2015-12-23 15:41 1107
#endif
1d2e2129 sago007 2015-12-23 15:41 1108
				// Update the glyph cursor to the new cache level.  We need to do this here because the actual cache lags behind our use of the packing above.
1d2e2129 sago007 2015-12-23 15:41 1109
				font->last_glyph.cache_level = num_surfaces;
1d2e2129 sago007 2015-12-23 15:41 1110
1d2e2129 sago007 2015-12-23 15:41 1111
1d2e2129 sago007 2015-12-23 15:41 1112
				surfaces[num_surfaces] = FC_CreateSurface32(w, h);
1d2e2129 sago007 2015-12-23 15:41 1113
				num_surfaces++;
1d2e2129 sago007 2015-12-23 15:41 1114
			}
1d2e2129 sago007 2015-12-23 15:41 1115
1d2e2129 sago007 2015-12-23 15:41 1116
			// Try packing for the new surface, then blit onto it.
1d2e2129 sago007 2015-12-23 15:41 1117
			if (packed || FC_PackGlyphData(font, FC_GetCodepointFromUTF8(&buff_ptr, 0), glyph_surf->w, surfaces[num_surfaces-1]->w, surfaces[num_surfaces-1]->h) != NULL) {
1d2e2129 sago007 2015-12-23 15:41 1118
				SDL_SetSurfaceBlendMode(glyph_surf, SDL_BLENDMODE_NONE);
1d2e2129 sago007 2015-12-23 15:41 1119
				SDL_Rect srcRect = {0, 0, glyph_surf->w, glyph_surf->h};
1d2e2129 sago007 2015-12-23 15:41 1120
				SDL_Rect destrect = font->last_glyph.rect;
1d2e2129 sago007 2015-12-23 15:41 1121
				SDL_BlitSurface(glyph_surf, &srcRect, surfaces[num_surfaces-1], &destrect);
1d2e2129 sago007 2015-12-23 15:41 1122
			}
1d2e2129 sago007 2015-12-23 15:41 1123
1d2e2129 sago007 2015-12-23 15:41 1124
			SDL_FreeSurface(glyph_surf);
1d2e2129 sago007 2015-12-23 15:41 1125
		}
1d2e2129 sago007 2015-12-23 15:41 1126
1d2e2129 sago007 2015-12-23 15:41 1127
		{
1d2e2129 sago007 2015-12-23 15:41 1128
			int i = num_surfaces-1;
1d2e2129 sago007 2015-12-23 15:41 1129
			FC_UploadGlyphCache(font, i, surfaces[i]);
1d2e2129 sago007 2015-12-23 15:41 1130
			SDL_FreeSurface(surfaces[i]);
1d2e2129 sago007 2015-12-23 15:41 1131
#ifndef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1132
			SDL_SetTextureBlendMode(font->glyph_cache[i], SDL_BLENDMODE_BLEND);
1d2e2129 sago007 2015-12-23 15:41 1133
#endif
1d2e2129 sago007 2015-12-23 15:41 1134
		}
1d2e2129 sago007 2015-12-23 15:41 1135
	}
1d2e2129 sago007 2015-12-23 15:41 1136
1d2e2129 sago007 2015-12-23 15:41 1137
	return 1;
078900fe sago007 2015-12-05 15:31 1138
}
078900fe sago007 2015-12-05 15:31 1139
1d2e2129 sago007 2015-12-23 15:41 1140
1d2e2129 sago007 2015-12-23 15:41 1141
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1142
Uint8 FC_LoadFont(FC_Font* font, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style)
1d2e2129 sago007 2015-12-23 15:41 1143
#else
1d2e2129 sago007 2015-12-23 15:41 1144
Uint8 FC_LoadFont(FC_Font* font, FC_Target* renderer, const char* filename_ttf, Uint32 pointSize, SDL_Color color, int style)
1d2e2129 sago007 2015-12-23 15:41 1145
#endif
078900fe sago007 2015-12-05 15:31 1146
{
1d2e2129 sago007 2015-12-23 15:41 1147
	SDL_RWops* rwops;
1d2e2129 sago007 2015-12-23 15:41 1148
1d2e2129 sago007 2015-12-23 15:41 1149
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1150
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1151
	}
1d2e2129 sago007 2015-12-23 15:41 1152
1d2e2129 sago007 2015-12-23 15:41 1153
	rwops = SDL_RWFromFile(filename_ttf, "rb");
1d2e2129 sago007 2015-12-23 15:41 1154
1d2e2129 sago007 2015-12-23 15:41 1155
	if (rwops == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1156
		FC_Log("Unable to open file for reading: %s \n", SDL_GetError());
1d2e2129 sago007 2015-12-23 15:41 1157
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1158
	}
1d2e2129 sago007 2015-12-23 15:41 1159
1d2e2129 sago007 2015-12-23 15:41 1160
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1161
	return FC_LoadFont_RW(font, rwops, 1, pointSize, color, style);
1d2e2129 sago007 2015-12-23 15:41 1162
#else
1d2e2129 sago007 2015-12-23 15:41 1163
	return FC_LoadFont_RW(font, renderer, rwops, 1, pointSize, color, style);
1d2e2129 sago007 2015-12-23 15:41 1164
#endif
078900fe sago007 2015-12-05 15:31 1165
}
078900fe sago007 2015-12-05 15:31 1166
1d2e2129 sago007 2015-12-23 15:41 1167
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1168
Uint8 FC_LoadFont_RW(FC_Font* font, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style)
1d2e2129 sago007 2015-12-23 15:41 1169
#else
1d2e2129 sago007 2015-12-23 15:41 1170
Uint8 FC_LoadFont_RW(FC_Font* font, FC_Target* renderer, SDL_RWops* file_rwops_ttf, Uint8 own_rwops, Uint32 pointSize, SDL_Color color, int style)
1d2e2129 sago007 2015-12-23 15:41 1171
#endif
078900fe sago007 2015-12-05 15:31 1172
{
1d2e2129 sago007 2015-12-23 15:41 1173
	Uint8 result;
1d2e2129 sago007 2015-12-23 15:41 1174
	TTF_Font* ttf;
1d2e2129 sago007 2015-12-23 15:41 1175
	Uint8 outline;
1d2e2129 sago007 2015-12-23 15:41 1176
1d2e2129 sago007 2015-12-23 15:41 1177
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1178
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1179
	}
1d2e2129 sago007 2015-12-23 15:41 1180
1d2e2129 sago007 2015-12-23 15:41 1181
	if (!TTF_WasInit() && TTF_Init() < 0) {
1d2e2129 sago007 2015-12-23 15:41 1182
		FC_Log("Unable to initialize SDL_ttf: %s \n", TTF_GetError());
1d2e2129 sago007 2015-12-23 15:41 1183
		if (own_rwops) {
1d2e2129 sago007 2015-12-23 15:41 1184
			SDL_RWclose(file_rwops_ttf);
1d2e2129 sago007 2015-12-23 15:41 1185
		}
1d2e2129 sago007 2015-12-23 15:41 1186
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1187
	}
1d2e2129 sago007 2015-12-23 15:41 1188
1d2e2129 sago007 2015-12-23 15:41 1189
	ttf = TTF_OpenFontRW(file_rwops_ttf, own_rwops, pointSize);
1d2e2129 sago007 2015-12-23 15:41 1190
1d2e2129 sago007 2015-12-23 15:41 1191
	if (ttf == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1192
		FC_Log("Unable to load TrueType font: %s \n", TTF_GetError());
1d2e2129 sago007 2015-12-23 15:41 1193
		if (own_rwops) {
1d2e2129 sago007 2015-12-23 15:41 1194
			SDL_RWclose(file_rwops_ttf);
1d2e2129 sago007 2015-12-23 15:41 1195
		}
1d2e2129 sago007 2015-12-23 15:41 1196
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1197
	}
1d2e2129 sago007 2015-12-23 15:41 1198
1d2e2129 sago007 2015-12-23 15:41 1199
	outline = (style & TTF_STYLE_OUTLINE);
1d2e2129 sago007 2015-12-23 15:41 1200
	if (outline) {
1d2e2129 sago007 2015-12-23 15:41 1201
		style &= ~TTF_STYLE_OUTLINE;
1d2e2129 sago007 2015-12-23 15:41 1202
		TTF_SetFontOutline(ttf, 1);
1d2e2129 sago007 2015-12-23 15:41 1203
	}
1d2e2129 sago007 2015-12-23 15:41 1204
	TTF_SetFontStyle(ttf, style);
1d2e2129 sago007 2015-12-23 15:41 1205
1d2e2129 sago007 2015-12-23 15:41 1206
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1207
	result = FC_LoadFontFromTTF(font, ttf, color);
1d2e2129 sago007 2015-12-23 15:41 1208
#else
1d2e2129 sago007 2015-12-23 15:41 1209
	result = FC_LoadFontFromTTF(font, renderer, ttf, color);
1d2e2129 sago007 2015-12-23 15:41 1210
#endif
1d2e2129 sago007 2015-12-23 15:41 1211
1d2e2129 sago007 2015-12-23 15:41 1212
	// Can only load new (uncached) glyphs if we can keep the SDL_RWops open.
1d2e2129 sago007 2015-12-23 15:41 1213
	font->owns_ttf_source = own_rwops;
1d2e2129 sago007 2015-12-23 15:41 1214
	if (!own_rwops) {
1d2e2129 sago007 2015-12-23 15:41 1215
		TTF_CloseFont(font->ttf_source);
1d2e2129 sago007 2015-12-23 15:41 1216
		font->ttf_source = NULL;
1d2e2129 sago007 2015-12-23 15:41 1217
	}
1d2e2129 sago007 2015-12-23 15:41 1218
1d2e2129 sago007 2015-12-23 15:41 1219
	return result;
078900fe sago007 2015-12-05 15:31 1220
}
078900fe sago007 2015-12-05 15:31 1221
078900fe sago007 2015-12-05 15:31 1222
1d2e2129 sago007 2015-12-23 15:41 1223
void FC_ClearFont(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 1224
	int i;
1d2e2129 sago007 2015-12-23 15:41 1225
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1226
		return;
1d2e2129 sago007 2015-12-23 15:41 1227
	}
1d2e2129 sago007 2015-12-23 15:41 1228
1d2e2129 sago007 2015-12-23 15:41 1229
	// Release resources
1d2e2129 sago007 2015-12-23 15:41 1230
	if (font->owns_ttf_source) {
1d2e2129 sago007 2015-12-23 15:41 1231
		TTF_CloseFont(font->ttf_source);
1d2e2129 sago007 2015-12-23 15:41 1232
	}
1d2e2129 sago007 2015-12-23 15:41 1233
1d2e2129 sago007 2015-12-23 15:41 1234
	font->owns_ttf_source = 0;
1d2e2129 sago007 2015-12-23 15:41 1235
	font->ttf_source = NULL;
1d2e2129 sago007 2015-12-23 15:41 1236
1d2e2129 sago007 2015-12-23 15:41 1237
	// Delete glyph map
1d2e2129 sago007 2015-12-23 15:41 1238
	FC_MapFree(font->glyphs);
1d2e2129 sago007 2015-12-23 15:41 1239
	font->glyphs = NULL;
1d2e2129 sago007 2015-12-23 15:41 1240
1d2e2129 sago007 2015-12-23 15:41 1241
	// Delete glyph cache
1d2e2129 sago007 2015-12-23 15:41 1242
	for (i = 0; i < font->glyph_cache_count; ++i) {
1d2e2129 sago007 2015-12-23 15:41 1243
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1244
		GPU_FreeImage(font->glyph_cache[i]);
1d2e2129 sago007 2015-12-23 15:41 1245
#else
1d2e2129 sago007 2015-12-23 15:41 1246
		SDL_DestroyTexture(font->glyph_cache[i]);
1d2e2129 sago007 2015-12-23 15:41 1247
#endif
1d2e2129 sago007 2015-12-23 15:41 1248
	}
1d2e2129 sago007 2015-12-23 15:41 1249
	free(font->glyph_cache);
1d2e2129 sago007 2015-12-23 15:41 1250
	font->glyph_cache = NULL;
1d2e2129 sago007 2015-12-23 15:41 1251
1d2e2129 sago007 2015-12-23 15:41 1252
	// Reset font
1d2e2129 sago007 2015-12-23 15:41 1253
	FC_Init(font);
1d2e2129 sago007 2015-12-23 15:41 1254
}
1d2e2129 sago007 2015-12-23 15:41 1255
1d2e2129 sago007 2015-12-23 15:41 1256
1d2e2129 sago007 2015-12-23 15:41 1257
void FC_FreeFont(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 1258
	int i;
1d2e2129 sago007 2015-12-23 15:41 1259
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1260
		return;
1d2e2129 sago007 2015-12-23 15:41 1261
	}
1d2e2129 sago007 2015-12-23 15:41 1262
1d2e2129 sago007 2015-12-23 15:41 1263
	// Release resources
1d2e2129 sago007 2015-12-23 15:41 1264
	if (font->owns_ttf_source) {
1d2e2129 sago007 2015-12-23 15:41 1265
		TTF_CloseFont(font->ttf_source);
1d2e2129 sago007 2015-12-23 15:41 1266
	}
1d2e2129 sago007 2015-12-23 15:41 1267
1d2e2129 sago007 2015-12-23 15:41 1268
	// Delete glyph map
1d2e2129 sago007 2015-12-23 15:41 1269
	FC_MapFree(font->glyphs);
1d2e2129 sago007 2015-12-23 15:41 1270
1d2e2129 sago007 2015-12-23 15:41 1271
	// Delete glyph cache
1d2e2129 sago007 2015-12-23 15:41 1272
	for (i = 0; i < font->glyph_cache_count; ++i) {
1d2e2129 sago007 2015-12-23 15:41 1273
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1274
		GPU_FreeImage(font->glyph_cache[i]);
1d2e2129 sago007 2015-12-23 15:41 1275
#else
1d2e2129 sago007 2015-12-23 15:41 1276
		SDL_DestroyTexture(font->glyph_cache[i]);
1d2e2129 sago007 2015-12-23 15:41 1277
#endif
1d2e2129 sago007 2015-12-23 15:41 1278
	}
1d2e2129 sago007 2015-12-23 15:41 1279
	free(font->glyph_cache);
1d2e2129 sago007 2015-12-23 15:41 1280
1d2e2129 sago007 2015-12-23 15:41 1281
	free(font->loading_string);
1d2e2129 sago007 2015-12-23 15:41 1282
1d2e2129 sago007 2015-12-23 15:41 1283
	free(font);
1d2e2129 sago007 2015-12-23 15:41 1284
}
1d2e2129 sago007 2015-12-23 15:41 1285
1d2e2129 sago007 2015-12-23 15:41 1286
int FC_GetNumCacheLevels(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 1287
	return font->glyph_cache_count;
1d2e2129 sago007 2015-12-23 15:41 1288
}
1d2e2129 sago007 2015-12-23 15:41 1289
1d2e2129 sago007 2015-12-23 15:41 1290
Uint8 FC_AddGlyphToCache(FC_Font* font, SDL_Surface* glyph_surface) {
1d2e2129 sago007 2015-12-23 15:41 1291
	if (font == NULL || glyph_surface == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1292
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1293
	}
1d2e2129 sago007 2015-12-23 15:41 1294
1d2e2129 sago007 2015-12-23 15:41 1295
	SDL_SetSurfaceBlendMode(glyph_surface, SDL_BLENDMODE_NONE);
1d2e2129 sago007 2015-12-23 15:41 1296
	FC_Image* dest = FC_GetGlyphCacheLevel(font, font->last_glyph.cache_level);
1d2e2129 sago007 2015-12-23 15:41 1297
	if (dest == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1298
		return 0;
1d2e2129 sago007 2015-12-23 15:41 1299
	}
1d2e2129 sago007 2015-12-23 15:41 1300
1d2e2129 sago007 2015-12-23 15:41 1301
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1302
	{
1d2e2129 sago007 2015-12-23 15:41 1303
		GPU_Target* target = GPU_LoadTarget(dest);
1d2e2129 sago007 2015-12-23 15:41 1304
		if (target == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1305
			return 0;
1d2e2129 sago007 2015-12-23 15:41 1306
		}
1d2e2129 sago007 2015-12-23 15:41 1307
		GPU_Image* img = GPU_CopyImageFromSurface(glyph_surface);
1d2e2129 sago007 2015-12-23 15:41 1308
		GPU_SetImageFilter(img, GPU_FILTER_NEAREST);
1d2e2129 sago007 2015-12-23 15:41 1309
		GPU_SetBlendMode(img, GPU_BLEND_SET);
1d2e2129 sago007 2015-12-23 15:41 1310
1d2e2129 sago007 2015-12-23 15:41 1311
		SDL_Rect destrect = font->last_glyph.rect;
1d2e2129 sago007 2015-12-23 15:41 1312
		GPU_Blit(img, NULL, target, destrect.x + destrect.w/2, destrect.y + destrect.h/2);
1d2e2129 sago007 2015-12-23 15:41 1313
1d2e2129 sago007 2015-12-23 15:41 1314
		GPU_FreeImage(img);
1d2e2129 sago007 2015-12-23 15:41 1315
		GPU_FreeTarget(target);
1d2e2129 sago007 2015-12-23 15:41 1316
	}
1d2e2129 sago007 2015-12-23 15:41 1317
#else
1d2e2129 sago007 2015-12-23 15:41 1318
	{
1d2e2129 sago007 2015-12-23 15:41 1319
		SDL_Texture* img = SDL_CreateTextureFromSurface(font->renderer, glyph_surface);
1d2e2129 sago007 2015-12-23 15:41 1320
1d2e2129 sago007 2015-12-23 15:41 1321
		SDL_Rect destrect = font->last_glyph.rect;
1d2e2129 sago007 2015-12-23 15:41 1322
		SDL_SetRenderTarget(font->renderer, dest);
1d2e2129 sago007 2015-12-23 15:41 1323
		SDL_RenderCopy(font->renderer, img, NULL, &destrect);
1d2e2129 sago007 2015-12-23 15:41 1324
		SDL_SetRenderTarget(font->renderer, NULL);
1d2e2129 sago007 2015-12-23 15:41 1325
		SDL_DestroyTexture(img);
1d2e2129 sago007 2015-12-23 15:41 1326
	}
1d2e2129 sago007 2015-12-23 15:41 1327
#endif
1d2e2129 sago007 2015-12-23 15:41 1328
1d2e2129 sago007 2015-12-23 15:41 1329
	return 1;
1d2e2129 sago007 2015-12-23 15:41 1330
}
1d2e2129 sago007 2015-12-23 15:41 1331
1d2e2129 sago007 2015-12-23 15:41 1332
Uint8 FC_GetGlyphData(FC_Font* font, FC_GlyphData* result, Uint32 codepoint) {
1d2e2129 sago007 2015-12-23 15:41 1333
	FC_GlyphData* e = FC_MapFind(font->glyphs, codepoint);
1d2e2129 sago007 2015-12-23 15:41 1334
	if (e == NULL || result == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1335
		char buff[5];
1d2e2129 sago007 2015-12-23 15:41 1336
		int w, h;
1d2e2129 sago007 2015-12-23 15:41 1337
		SDL_Color white = {255, 255, 255, 255};
1d2e2129 sago007 2015-12-23 15:41 1338
		SDL_Surface* surf;
1d2e2129 sago007 2015-12-23 15:41 1339
		FC_Image* cache_image;
1d2e2129 sago007 2015-12-23 15:41 1340
1d2e2129 sago007 2015-12-23 15:41 1341
		if (font->ttf_source == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1342
			return 0;
1d2e2129 sago007 2015-12-23 15:41 1343
		}
1d2e2129 sago007 2015-12-23 15:41 1344
1d2e2129 sago007 2015-12-23 15:41 1345
		FC_GetUTF8FromCodepoint(buff, codepoint);
1d2e2129 sago007 2015-12-23 15:41 1346
1d2e2129 sago007 2015-12-23 15:41 1347
		cache_image = FC_GetGlyphCacheLevel(font, font->last_glyph.cache_level);
1d2e2129 sago007 2015-12-23 15:41 1348
		if (cache_image == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1349
			FC_Log("SDL_FontCache: Failed to load cache image, so cannot add new glyphs!\n");
1d2e2129 sago007 2015-12-23 15:41 1350
			return 0;
1d2e2129 sago007 2015-12-23 15:41 1351
		}
1d2e2129 sago007 2015-12-23 15:41 1352
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1353
		w = cache_image->w;
1d2e2129 sago007 2015-12-23 15:41 1354
		h = cache_image->h;
1d2e2129 sago007 2015-12-23 15:41 1355
#else
1d2e2129 sago007 2015-12-23 15:41 1356
		SDL_QueryTexture(cache_image, NULL, NULL, &w, &h);
1d2e2129 sago007 2015-12-23 15:41 1357
#endif
1d2e2129 sago007 2015-12-23 15:41 1358
1d2e2129 sago007 2015-12-23 15:41 1359
		surf = TTF_RenderUTF8_Blended(font->ttf_source, buff, white);
1d2e2129 sago007 2015-12-23 15:41 1360
		if (surf == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1361
			return 0;
1d2e2129 sago007 2015-12-23 15:41 1362
		}
1d2e2129 sago007 2015-12-23 15:41 1363
1d2e2129 sago007 2015-12-23 15:41 1364
		e = FC_PackGlyphData(font, codepoint, surf->w, w, h);
1d2e2129 sago007 2015-12-23 15:41 1365
		if (e == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1366
			// Grow the cache
1d2e2129 sago007 2015-12-23 15:41 1367
			FC_GrowGlyphCache(font);
1d2e2129 sago007 2015-12-23 15:41 1368
1d2e2129 sago007 2015-12-23 15:41 1369
			// Try packing again
1d2e2129 sago007 2015-12-23 15:41 1370
			e = FC_PackGlyphData(font, codepoint, surf->w, w, h);
1d2e2129 sago007 2015-12-23 15:41 1371
			if (e == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1372
				SDL_FreeSurface(surf);
1d2e2129 sago007 2015-12-23 15:41 1373
				return 0;
1d2e2129 sago007 2015-12-23 15:41 1374
			}
1d2e2129 sago007 2015-12-23 15:41 1375
		}
1d2e2129 sago007 2015-12-23 15:41 1376
1d2e2129 sago007 2015-12-23 15:41 1377
		// Render onto the cache texture
1d2e2129 sago007 2015-12-23 15:41 1378
		FC_AddGlyphToCache(font, surf);
1d2e2129 sago007 2015-12-23 15:41 1379
1d2e2129 sago007 2015-12-23 15:41 1380
		SDL_FreeSurface(surf);
1d2e2129 sago007 2015-12-23 15:41 1381
	}
1d2e2129 sago007 2015-12-23 15:41 1382
1d2e2129 sago007 2015-12-23 15:41 1383
	if (result != NULL && e != NULL) {
1d2e2129 sago007 2015-12-23 15:41 1384
		*result = *e;
1d2e2129 sago007 2015-12-23 15:41 1385
	}
1d2e2129 sago007 2015-12-23 15:41 1386
1d2e2129 sago007 2015-12-23 15:41 1387
	return 1;
1d2e2129 sago007 2015-12-23 15:41 1388
}
1d2e2129 sago007 2015-12-23 15:41 1389
1d2e2129 sago007 2015-12-23 15:41 1390
1d2e2129 sago007 2015-12-23 15:41 1391
FC_GlyphData* FC_SetGlyphData(FC_Font* font, Uint32 codepoint, FC_GlyphData glyph_data) {
1d2e2129 sago007 2015-12-23 15:41 1392
	return FC_MapInsert(font->glyphs, codepoint, glyph_data);
078900fe sago007 2015-12-05 15:31 1393
}
078900fe sago007 2015-12-05 15:31 1394
078900fe sago007 2015-12-05 15:31 1395
078900fe sago007 2015-12-05 15:31 1396
// Drawing
1d2e2129 sago007 2015-12-23 15:41 1397
static FC_Rect FC_RenderLeft(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) {
1d2e2129 sago007 2015-12-23 15:41 1398
	const char* c = text;
1d2e2129 sago007 2015-12-23 15:41 1399
	FC_Rect srcRect;
1d2e2129 sago007 2015-12-23 15:41 1400
	FC_Rect dstRect;
1d2e2129 sago007 2015-12-23 15:41 1401
	FC_Rect dirtyRect = FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1402
1d2e2129 sago007 2015-12-23 15:41 1403
	FC_GlyphData glyph;
1d2e2129 sago007 2015-12-23 15:41 1404
	Uint32 codepoint;
1d2e2129 sago007 2015-12-23 15:41 1405
1d2e2129 sago007 2015-12-23 15:41 1406
	float destX = x;
1d2e2129 sago007 2015-12-23 15:41 1407
	float destY = y;
1d2e2129 sago007 2015-12-23 15:41 1408
	float destH;
1d2e2129 sago007 2015-12-23 15:41 1409
	float destLineSpacing;
1d2e2129 sago007 2015-12-23 15:41 1410
	float destLetterSpacing;
1d2e2129 sago007 2015-12-23 15:41 1411
1d2e2129 sago007 2015-12-23 15:41 1412
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1413
		return dirtyRect;
1d2e2129 sago007 2015-12-23 15:41 1414
	}
1d2e2129 sago007 2015-12-23 15:41 1415
1d2e2129 sago007 2015-12-23 15:41 1416
	destH = font->height * scale.y;
1d2e2129 sago007 2015-12-23 15:41 1417
	destLineSpacing = font->lineSpacing*scale.y;
1d2e2129 sago007 2015-12-23 15:41 1418
	destLetterSpacing = font->letterSpacing*scale.x;
1d2e2129 sago007 2015-12-23 15:41 1419
1d2e2129 sago007 2015-12-23 15:41 1420
	if (c == NULL || font->glyph_cache_count == 0 || dest == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1421
		return dirtyRect;
1d2e2129 sago007 2015-12-23 15:41 1422
	}
1d2e2129 sago007 2015-12-23 15:41 1423
1d2e2129 sago007 2015-12-23 15:41 1424
	int newlineX = x;
1d2e2129 sago007 2015-12-23 15:41 1425
1d2e2129 sago007 2015-12-23 15:41 1426
	for (; *c != '\0'; c++) {
1d2e2129 sago007 2015-12-23 15:41 1427
		if (*c == '\n') {
1d2e2129 sago007 2015-12-23 15:41 1428
			destX = newlineX;
1d2e2129 sago007 2015-12-23 15:41 1429
			destY += destH + destLineSpacing;
1d2e2129 sago007 2015-12-23 15:41 1430
			continue;
1d2e2129 sago007 2015-12-23 15:41 1431
		}
1d2e2129 sago007 2015-12-23 15:41 1432
1d2e2129 sago007 2015-12-23 15:41 1433
		codepoint = FC_GetCodepointFromUTF8(&c, 1);  // Increments 'c' to skip the extra UTF-8 bytes
1d2e2129 sago007 2015-12-23 15:41 1434
		if (!FC_GetGlyphData(font, &glyph, codepoint)) {
1d2e2129 sago007 2015-12-23 15:41 1435
			codepoint = ' ';
1d2e2129 sago007 2015-12-23 15:41 1436
			if (!FC_GetGlyphData(font, &glyph, codepoint)) {
1d2e2129 sago007 2015-12-23 15:41 1437
				continue;    // Skip bad characters
1d2e2129 sago007 2015-12-23 15:41 1438
			}
1d2e2129 sago007 2015-12-23 15:41 1439
		}
1d2e2129 sago007 2015-12-23 15:41 1440
1d2e2129 sago007 2015-12-23 15:41 1441
		if (codepoint == ' ') {
1d2e2129 sago007 2015-12-23 15:41 1442
			destX += glyph.rect.w*scale.x + destLetterSpacing;
1d2e2129 sago007 2015-12-23 15:41 1443
			continue;
1d2e2129 sago007 2015-12-23 15:41 1444
		}
1d2e2129 sago007 2015-12-23 15:41 1445
		/*if(destX >= dest->w)
1d2e2129 sago007 2015-12-23 15:41 1446
		    continue;
1d2e2129 sago007 2015-12-23 15:41 1447
		if(destY >= dest->h)
1d2e2129 sago007 2015-12-23 15:41 1448
		    continue;*/
078900fe sago007 2015-12-05 15:31 1449
1d2e2129 sago007 2015-12-23 15:41 1450
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 1451
		srcRect.x = glyph.rect.x;
1d2e2129 sago007 2015-12-23 15:41 1452
		srcRect.y = glyph.rect.y;
1d2e2129 sago007 2015-12-23 15:41 1453
		srcRect.w = glyph.rect.w;
1d2e2129 sago007 2015-12-23 15:41 1454
		srcRect.h = glyph.rect.h;
1d2e2129 sago007 2015-12-23 15:41 1455
#else
1d2e2129 sago007 2015-12-23 15:41 1456
		srcRect = glyph.rect;
1d2e2129 sago007 2015-12-23 15:41 1457
#endif
1d2e2129 sago007 2015-12-23 15:41 1458
		dstRect = fc_render_callback(FC_GetGlyphCacheLevel(font, glyph.cache_level), &srcRect, dest, destX, destY, scale.x, scale.y);
1d2e2129 sago007 2015-12-23 15:41 1459
		if (dirtyRect.w == 0 || dirtyRect.h == 0) {
1d2e2129 sago007 2015-12-23 15:41 1460
			dirtyRect = dstRect;
1d2e2129 sago007 2015-12-23 15:41 1461
		}
1d2e2129 sago007 2015-12-23 15:41 1462
		else {
1d2e2129 sago007 2015-12-23 15:41 1463
			dirtyRect = FC_RectUnion(dirtyRect, dstRect);
1d2e2129 sago007 2015-12-23 15:41 1464
		}
1d2e2129 sago007 2015-12-23 15:41 1465
1d2e2129 sago007 2015-12-23 15:41 1466
		destX += glyph.rect.w*scale.x + destLetterSpacing;
1d2e2129 sago007 2015-12-23 15:41 1467
	}
078900fe sago007 2015-12-05 15:31 1468
1d2e2129 sago007 2015-12-23 15:41 1469
	return dirtyRect;
078900fe sago007 2015-12-05 15:31 1470
}
078900fe sago007 2015-12-05 15:31 1471
1d2e2129 sago007 2015-12-23 15:41 1472
static void set_color_for_all_caches(FC_Font* font, SDL_Color color) {
1d2e2129 sago007 2015-12-23 15:41 1473
	// TODO: How can I predict which glyph caches are to be used?
1d2e2129 sago007 2015-12-23 15:41 1474
	FC_Image* img;
1d2e2129 sago007 2015-12-23 15:41 1475
	int i;
1d2e2129 sago007 2015-12-23 15:41 1476
	int num_levels = FC_GetNumCacheLevels(font);
1d2e2129 sago007 2015-12-23 15:41 1477
	for (i = 0; i < num_levels; ++i) {
1d2e2129 sago007 2015-12-23 15:41 1478
		img = FC_GetGlyphCacheLevel(font, i);
1d2e2129 sago007 2015-12-23 15:41 1479
		set_color(img, color.r, color.g, color.b, FC_GET_ALPHA(color));
1d2e2129 sago007 2015-12-23 15:41 1480
	}
078900fe sago007 2015-12-05 15:31 1481
}
078900fe sago007 2015-12-05 15:31 1482
1d2e2129 sago007 2015-12-23 15:41 1483
FC_Rect FC_Draw(FC_Font* font, FC_Target* dest, float x, float y, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1484
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1485
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1486
	}
1d2e2129 sago007 2015-12-23 15:41 1487
1d2e2129 sago007 2015-12-23 15:41 1488
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 1489
1d2e2129 sago007 2015-12-23 15:41 1490
	set_color_for_all_caches(font, font->default_color);
1d2e2129 sago007 2015-12-23 15:41 1491
1d2e2129 sago007 2015-12-23 15:41 1492
	return FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer);
078900fe sago007 2015-12-05 15:31 1493
}
078900fe sago007 2015-12-05 15:31 1494
078900fe sago007 2015-12-05 15:31 1495
078900fe sago007 2015-12-05 15:31 1496
1d2e2129 sago007 2015-12-23 15:41 1497
typedef struct FC_StringList {
1d2e2129 sago007 2015-12-23 15:41 1498
	char* value;
1d2e2129 sago007 2015-12-23 15:41 1499
	struct FC_StringList* next;
078900fe sago007 2015-12-05 15:31 1500
} FC_StringList;
078900fe sago007 2015-12-05 15:31 1501
1d2e2129 sago007 2015-12-23 15:41 1502
void FC_StringListFree(FC_StringList* node) {
1d2e2129 sago007 2015-12-23 15:41 1503
	// Delete the nodes in order
1d2e2129 sago007 2015-12-23 15:41 1504
	while (node != NULL) {
1d2e2129 sago007 2015-12-23 15:41 1505
		FC_StringList* last = node;
1d2e2129 sago007 2015-12-23 15:41 1506
		node = node->next;
1d2e2129 sago007 2015-12-23 15:41 1507
1d2e2129 sago007 2015-12-23 15:41 1508
		free(last->value);
1d2e2129 sago007 2015-12-23 15:41 1509
		free(last);
1d2e2129 sago007 2015-12-23 15:41 1510
	}
1d2e2129 sago007 2015-12-23 15:41 1511
}
1d2e2129 sago007 2015-12-23 15:41 1512
1d2e2129 sago007 2015-12-23 15:41 1513
FC_StringList** FC_StringListPushBack(FC_StringList** node, char* value, Uint8 copy) {
1d2e2129 sago007 2015-12-23 15:41 1514
	// Get to the last node
1d2e2129 sago007 2015-12-23 15:41 1515
	while (node != NULL && *node != NULL) {
1d2e2129 sago007 2015-12-23 15:41 1516
		node = &(*node)->next;
1d2e2129 sago007 2015-12-23 15:41 1517
	}
1d2e2129 sago007 2015-12-23 15:41 1518
1d2e2129 sago007 2015-12-23 15:41 1519
	*node = (FC_StringList*)malloc(sizeof(FC_StringList));
1d2e2129 sago007 2015-12-23 15:41 1520
1d2e2129 sago007 2015-12-23 15:41 1521
	(*node)->value = (copy? U8_strdup(value) : value);
1d2e2129 sago007 2015-12-23 15:41 1522
	(*node)->next = NULL;
1d2e2129 sago007 2015-12-23 15:41 1523
1d2e2129 sago007 2015-12-23 15:41 1524
	return node;
1d2e2129 sago007 2015-12-23 15:41 1525
}
1d2e2129 sago007 2015-12-23 15:41 1526
1d2e2129 sago007 2015-12-23 15:41 1527
static FC_StringList* FC_Explode(const char* text, char delimiter) {
1d2e2129 sago007 2015-12-23 15:41 1528
	FC_StringList* head;
1d2e2129 sago007 2015-12-23 15:41 1529
	FC_StringList* new_node;
1d2e2129 sago007 2015-12-23 15:41 1530
	FC_StringList** node;
1d2e2129 sago007 2015-12-23 15:41 1531
	const char* start;
1d2e2129 sago007 2015-12-23 15:41 1532
	const char* end;
1d2e2129 sago007 2015-12-23 15:41 1533
	unsigned int size;
1d2e2129 sago007 2015-12-23 15:41 1534
	if (text == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1535
		return NULL;
1d2e2129 sago007 2015-12-23 15:41 1536
	}
1d2e2129 sago007 2015-12-23 15:41 1537
1d2e2129 sago007 2015-12-23 15:41 1538
	head = NULL;
1d2e2129 sago007 2015-12-23 15:41 1539
	node = &head;
1d2e2129 sago007 2015-12-23 15:41 1540
1d2e2129 sago007 2015-12-23 15:41 1541
	// Doesn't technically support UTF-8, but it's probably fine, right?
1d2e2129 sago007 2015-12-23 15:41 1542
	size = 0;
1d2e2129 sago007 2015-12-23 15:41 1543
	start = end = text;
1d2e2129 sago007 2015-12-23 15:41 1544
	while (1) {
1d2e2129 sago007 2015-12-23 15:41 1545
		if (*end == delimiter || *end == '\0') {
1d2e2129 sago007 2015-12-23 15:41 1546
			*node = (FC_StringList*)malloc(sizeof(FC_StringList));
1d2e2129 sago007 2015-12-23 15:41 1547
			new_node = *node;
1d2e2129 sago007 2015-12-23 15:41 1548
1d2e2129 sago007 2015-12-23 15:41 1549
			new_node->value = (char*)malloc(size + 1);
1d2e2129 sago007 2015-12-23 15:41 1550
			memcpy(new_node->value, start, size);
1d2e2129 sago007 2015-12-23 15:41 1551
			new_node->value[size] = '\0';
1d2e2129 sago007 2015-12-23 15:41 1552
1d2e2129 sago007 2015-12-23 15:41 1553
			new_node->next = NULL;
1d2e2129 sago007 2015-12-23 15:41 1554
1d2e2129 sago007 2015-12-23 15:41 1555
			if (*end == '\0') {
1d2e2129 sago007 2015-12-23 15:41 1556
				break;
1d2e2129 sago007 2015-12-23 15:41 1557
			}
1d2e2129 sago007 2015-12-23 15:41 1558
1d2e2129 sago007 2015-12-23 15:41 1559
			node = &((*node)->next);
1d2e2129 sago007 2015-12-23 15:41 1560
			start = end+1;
1d2e2129 sago007 2015-12-23 15:41 1561
			size = 0;
1d2e2129 sago007 2015-12-23 15:41 1562
		}
1d2e2129 sago007 2015-12-23 15:41 1563
		else {
1d2e2129 sago007 2015-12-23 15:41 1564
			++size;
1d2e2129 sago007 2015-12-23 15:41 1565
		}
1d2e2129 sago007 2015-12-23 15:41 1566
1d2e2129 sago007 2015-12-23 15:41 1567
		++end;
1d2e2129 sago007 2015-12-23 15:41 1568
	}
1d2e2129 sago007 2015-12-23 15:41 1569
1d2e2129 sago007 2015-12-23 15:41 1570
	return head;
1d2e2129 sago007 2015-12-23 15:41 1571
}
1d2e2129 sago007 2015-12-23 15:41 1572
1d2e2129 sago007 2015-12-23 15:41 1573
static FC_StringList* FC_ExplodeAndKeep(const char* text, char delimiter) {
1d2e2129 sago007 2015-12-23 15:41 1574
	FC_StringList* head;
1d2e2129 sago007 2015-12-23 15:41 1575
	FC_StringList* new_node;
1d2e2129 sago007 2015-12-23 15:41 1576
	FC_StringList** node;
1d2e2129 sago007 2015-12-23 15:41 1577
	const char* start;
1d2e2129 sago007 2015-12-23 15:41 1578
	const char* end;
1d2e2129 sago007 2015-12-23 15:41 1579
	unsigned int size;
1d2e2129 sago007 2015-12-23 15:41 1580
	if (text == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1581
		return NULL;
1d2e2129 sago007 2015-12-23 15:41 1582
	}
1d2e2129 sago007 2015-12-23 15:41 1583
1d2e2129 sago007 2015-12-23 15:41 1584
	head = NULL;
1d2e2129 sago007 2015-12-23 15:41 1585
	node = &head;
1d2e2129 sago007 2015-12-23 15:41 1586
1d2e2129 sago007 2015-12-23 15:41 1587
	// Doesn't technically support UTF-8, but it's probably fine, right?
1d2e2129 sago007 2015-12-23 15:41 1588
	size = 0;
1d2e2129 sago007 2015-12-23 15:41 1589
	start = end = text;
1d2e2129 sago007 2015-12-23 15:41 1590
	while (1) {
1d2e2129 sago007 2015-12-23 15:41 1591
		if (*end == delimiter || *end == '\0') {
1d2e2129 sago007 2015-12-23 15:41 1592
			*node = (FC_StringList*)malloc(sizeof(FC_StringList));
1d2e2129 sago007 2015-12-23 15:41 1593
			new_node = *node;
1d2e2129 sago007 2015-12-23 15:41 1594
1d2e2129 sago007 2015-12-23 15:41 1595
			new_node->value = (char*)malloc(size + 1);
1d2e2129 sago007 2015-12-23 15:41 1596
			memcpy(new_node->value, start, size);
1d2e2129 sago007 2015-12-23 15:41 1597
			new_node->value[size] = '\0';
1d2e2129 sago007 2015-12-23 15:41 1598
1d2e2129 sago007 2015-12-23 15:41 1599
			new_node->next = NULL;
1d2e2129 sago007 2015-12-23 15:41 1600
1d2e2129 sago007 2015-12-23 15:41 1601
			if (*end == '\0') {
1d2e2129 sago007 2015-12-23 15:41 1602
				break;
1d2e2129 sago007 2015-12-23 15:41 1603
			}
1d2e2129 sago007 2015-12-23 15:41 1604
1d2e2129 sago007 2015-12-23 15:41 1605
			node = &((*node)->next);
1d2e2129 sago007 2015-12-23 15:41 1606
			start = end;
1d2e2129 sago007 2015-12-23 15:41 1607
			size = 1;
1d2e2129 sago007 2015-12-23 15:41 1608
		}
1d2e2129 sago007 2015-12-23 15:41 1609
		else {
1d2e2129 sago007 2015-12-23 15:41 1610
			++size;
1d2e2129 sago007 2015-12-23 15:41 1611
		}
1d2e2129 sago007 2015-12-23 15:41 1612
1d2e2129 sago007 2015-12-23 15:41 1613
		++end;
1d2e2129 sago007 2015-12-23 15:41 1614
	}
1d2e2129 sago007 2015-12-23 15:41 1615
1d2e2129 sago007 2015-12-23 15:41 1616
	return head;
1d2e2129 sago007 2015-12-23 15:41 1617
}
1d2e2129 sago007 2015-12-23 15:41 1618
1d2e2129 sago007 2015-12-23 15:41 1619
static void FC_RenderAlign(FC_Font* font, FC_Target* dest, float x, float y, int width, FC_Scale scale, FC_AlignEnum align, const char* text) {
1d2e2129 sago007 2015-12-23 15:41 1620
	switch (align) {
1d2e2129 sago007 2015-12-23 15:41 1621
	case FC_ALIGN_LEFT:
1d2e2129 sago007 2015-12-23 15:41 1622
		FC_RenderLeft(font, dest, x, y, scale, text);
1d2e2129 sago007 2015-12-23 15:41 1623
		break;
1d2e2129 sago007 2015-12-23 15:41 1624
	case FC_ALIGN_CENTER:
1d2e2129 sago007 2015-12-23 15:41 1625
		FC_RenderCenter(font, dest, x + width/2, y, scale, text);
1d2e2129 sago007 2015-12-23 15:41 1626
		break;
1d2e2129 sago007 2015-12-23 15:41 1627
	case FC_ALIGN_RIGHT:
1d2e2129 sago007 2015-12-23 15:41 1628
		FC_RenderRight(font, dest, x + width, y, scale, text);
1d2e2129 sago007 2015-12-23 15:41 1629
		break;
1d2e2129 sago007 2015-12-23 15:41 1630
	}
1d2e2129 sago007 2015-12-23 15:41 1631
}
1d2e2129 sago007 2015-12-23 15:41 1632
1d2e2129 sago007 2015-12-23 15:41 1633
static FC_StringList* FC_GetBufferFitToColumn(FC_Font* font, int width, FC_Scale scale, Uint8 keep_newlines) {
1d2e2129 sago007 2015-12-23 15:41 1634
	FC_StringList* result = NULL;
1d2e2129 sago007 2015-12-23 15:41 1635
	FC_StringList** current = &result;
1d2e2129 sago007 2015-12-23 15:41 1636
1d2e2129 sago007 2015-12-23 15:41 1637
	FC_StringList* ls, *iter;
1d2e2129 sago007 2015-12-23 15:41 1638
1d2e2129 sago007 2015-12-23 15:41 1639
	ls = (keep_newlines? FC_ExplodeAndKeep(fc_buffer, '\n') : FC_Explode(fc_buffer, '\n'));
1d2e2129 sago007 2015-12-23 15:41 1640
	for (iter = ls; iter != NULL; iter = iter->next) {
1d2e2129 sago007 2015-12-23 15:41 1641
		char* line = iter->value;
1d2e2129 sago007 2015-12-23 15:41 1642
1d2e2129 sago007 2015-12-23 15:41 1643
		// If line is too long, then add words one at a time until we go over.
1d2e2129 sago007 2015-12-23 15:41 1644
		if (width > 0 && FC_GetWidth(font, "%s", line) > width) {
1d2e2129 sago007 2015-12-23 15:41 1645
			FC_StringList* words, *word_iter;
1d2e2129 sago007 2015-12-23 15:41 1646
1d2e2129 sago007 2015-12-23 15:41 1647
			words = FC_Explode(line, ' ');
1d2e2129 sago007 2015-12-23 15:41 1648
			// Skip the first word for the iterator, so there will always be at least one word per line
1d2e2129 sago007 2015-12-23 15:41 1649
			line = new_concat(words->value, " ");
1d2e2129 sago007 2015-12-23 15:41 1650
			for (word_iter = words->next; word_iter != NULL; word_iter = word_iter->next) {
1d2e2129 sago007 2015-12-23 15:41 1651
				char* line_plus_word = new_concat(line, word_iter->value);
1d2e2129 sago007 2015-12-23 15:41 1652
				char* word_plus_space = new_concat(word_iter->value, " ");
1d2e2129 sago007 2015-12-23 15:41 1653
				if (FC_GetWidth(font, line_plus_word) > width) {
1d2e2129 sago007 2015-12-23 15:41 1654
					current = FC_StringListPushBack(current, line, 0);
1d2e2129 sago007 2015-12-23 15:41 1655
1d2e2129 sago007 2015-12-23 15:41 1656
					line = word_plus_space;
1d2e2129 sago007 2015-12-23 15:41 1657
				}
1d2e2129 sago007 2015-12-23 15:41 1658
				else {
1d2e2129 sago007 2015-12-23 15:41 1659
					replace_concat(&line, word_plus_space);
1d2e2129 sago007 2015-12-23 15:41 1660
					free(word_plus_space);
1d2e2129 sago007 2015-12-23 15:41 1661
				}
1d2e2129 sago007 2015-12-23 15:41 1662
				free(line_plus_word);
1d2e2129 sago007 2015-12-23 15:41 1663
			}
1d2e2129 sago007 2015-12-23 15:41 1664
			current = FC_StringListPushBack(current, line, 0);
1d2e2129 sago007 2015-12-23 15:41 1665
			FC_StringListFree(words);
1d2e2129 sago007 2015-12-23 15:41 1666
		}
1d2e2129 sago007 2015-12-23 15:41 1667
		else {
1d2e2129 sago007 2015-12-23 15:41 1668
			current = FC_StringListPushBack(current, line, 0);
1d2e2129 sago007 2015-12-23 15:41 1669
			iter->value = NULL;
1d2e2129 sago007 2015-12-23 15:41 1670
		}
1d2e2129 sago007 2015-12-23 15:41 1671
	}
1d2e2129 sago007 2015-12-23 15:41 1672
	FC_StringListFree(ls);
1d2e2129 sago007 2015-12-23 15:41 1673
1d2e2129 sago007 2015-12-23 15:41 1674
	return result;
078900fe sago007 2015-12-05 15:31 1675
}
078900fe sago007 2015-12-05 15:31 1676
1d2e2129 sago007 2015-12-23 15:41 1677
static void FC_DrawColumnFromBuffer(FC_Font* font, FC_Target* dest, FC_Rect box, int* total_height, FC_Scale scale, FC_AlignEnum align) {
1d2e2129 sago007 2015-12-23 15:41 1678
	int y = box.y;
1d2e2129 sago007 2015-12-23 15:41 1679
	FC_StringList* ls, *iter;
1d2e2129 sago007 2015-12-23 15:41 1680
1d2e2129 sago007 2015-12-23 15:41 1681
	ls = FC_GetBufferFitToColumn(font, box.w, scale, 0);
1d2e2129 sago007 2015-12-23 15:41 1682
	for (iter = ls; iter != NULL; iter = iter->next) {
1d2e2129 sago007 2015-12-23 15:41 1683
		FC_RenderAlign(font, dest, box.x, y, box.w, scale, align, iter->value);
1d2e2129 sago007 2015-12-23 15:41 1684
		y += FC_GetLineHeight(font);
1d2e2129 sago007 2015-12-23 15:41 1685
	}
1d2e2129 sago007 2015-12-23 15:41 1686
	FC_StringListFree(ls);
1d2e2129 sago007 2015-12-23 15:41 1687
1d2e2129 sago007 2015-12-23 15:41 1688
	if (total_height != NULL) {
1d2e2129 sago007 2015-12-23 15:41 1689
		*total_height = y - box.y;
1d2e2129 sago007 2015-12-23 15:41 1690
	}
078900fe sago007 2015-12-05 15:31 1691
}
078900fe sago007 2015-12-05 15:31 1692
1d2e2129 sago007 2015-12-23 15:41 1693
FC_Rect FC_DrawBox(FC_Font* font, FC_Target* dest, FC_Rect box, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1694
	Uint8 useClip;
1d2e2129 sago007 2015-12-23 15:41 1695
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1696
		return FC_MakeRect(box.x, box.y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1697
	}
1d2e2129 sago007 2015-12-23 15:41 1698
1d2e2129 sago007 2015-12-23 15:41 1699
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 1700
1d2e2129 sago007 2015-12-23 15:41 1701
	useClip = has_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1702
	FC_Rect oldclip, newclip;
1d2e2129 sago007 2015-12-23 15:41 1703
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1704
		oldclip = get_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1705
		newclip = FC_RectIntersect(oldclip, box);
1d2e2129 sago007 2015-12-23 15:41 1706
	}
1d2e2129 sago007 2015-12-23 15:41 1707
	else {
1d2e2129 sago007 2015-12-23 15:41 1708
		newclip = box;
1d2e2129 sago007 2015-12-23 15:41 1709
	}
1d2e2129 sago007 2015-12-23 15:41 1710
	set_clip(dest, &newclip);
1d2e2129 sago007 2015-12-23 15:41 1711
1d2e2129 sago007 2015-12-23 15:41 1712
	set_color_for_all_caches(font, font->default_color);
1d2e2129 sago007 2015-12-23 15:41 1713
1d2e2129 sago007 2015-12-23 15:41 1714
	FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), FC_ALIGN_LEFT);
1d2e2129 sago007 2015-12-23 15:41 1715
1d2e2129 sago007 2015-12-23 15:41 1716
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1717
		set_clip(dest, &oldclip);
1d2e2129 sago007 2015-12-23 15:41 1718
	}
1d2e2129 sago007 2015-12-23 15:41 1719
	else {
1d2e2129 sago007 2015-12-23 15:41 1720
		set_clip(dest, NULL);
1d2e2129 sago007 2015-12-23 15:41 1721
	}
1d2e2129 sago007 2015-12-23 15:41 1722
1d2e2129 sago007 2015-12-23 15:41 1723
	return box;
078900fe sago007 2015-12-05 15:31 1724
}
078900fe sago007 2015-12-05 15:31 1725
1d2e2129 sago007 2015-12-23 15:41 1726
FC_Rect FC_DrawBoxAlign(FC_Font* font, FC_Target* dest, FC_Rect box, FC_AlignEnum align, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1727
	Uint8 useClip;
1d2e2129 sago007 2015-12-23 15:41 1728
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1729
		return FC_MakeRect(box.x, box.y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1730
	}
1d2e2129 sago007 2015-12-23 15:41 1731
1d2e2129 sago007 2015-12-23 15:41 1732
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 1733
1d2e2129 sago007 2015-12-23 15:41 1734
	useClip = has_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1735
	FC_Rect oldclip, newclip;
1d2e2129 sago007 2015-12-23 15:41 1736
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1737
		oldclip = get_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1738
		newclip = FC_RectIntersect(oldclip, box);
1d2e2129 sago007 2015-12-23 15:41 1739
	}
1d2e2129 sago007 2015-12-23 15:41 1740
	else {
1d2e2129 sago007 2015-12-23 15:41 1741
		newclip = box;
1d2e2129 sago007 2015-12-23 15:41 1742
	}
1d2e2129 sago007 2015-12-23 15:41 1743
	set_clip(dest, &newclip);
1d2e2129 sago007 2015-12-23 15:41 1744
1d2e2129 sago007 2015-12-23 15:41 1745
	set_color_for_all_caches(font, font->default_color);
1d2e2129 sago007 2015-12-23 15:41 1746
1d2e2129 sago007 2015-12-23 15:41 1747
	FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), align);
1d2e2129 sago007 2015-12-23 15:41 1748
1d2e2129 sago007 2015-12-23 15:41 1749
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1750
		set_clip(dest, &oldclip);
1d2e2129 sago007 2015-12-23 15:41 1751
	}
1d2e2129 sago007 2015-12-23 15:41 1752
	else {
1d2e2129 sago007 2015-12-23 15:41 1753
		set_clip(dest, NULL);
1d2e2129 sago007 2015-12-23 15:41 1754
	}
1d2e2129 sago007 2015-12-23 15:41 1755
1d2e2129 sago007 2015-12-23 15:41 1756
	return box;
078900fe sago007 2015-12-05 15:31 1757
}
078900fe sago007 2015-12-05 15:31 1758
1d2e2129 sago007 2015-12-23 15:41 1759
FC_Rect FC_DrawBoxScale(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Scale scale, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1760
	Uint8 useClip;
1d2e2129 sago007 2015-12-23 15:41 1761
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1762
		return FC_MakeRect(box.x, box.y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1763
	}
1d2e2129 sago007 2015-12-23 15:41 1764
1d2e2129 sago007 2015-12-23 15:41 1765
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 1766
1d2e2129 sago007 2015-12-23 15:41 1767
	useClip = has_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1768
	FC_Rect oldclip, newclip;
1d2e2129 sago007 2015-12-23 15:41 1769
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1770
		oldclip = get_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1771
		newclip = FC_RectIntersect(oldclip, box);
1d2e2129 sago007 2015-12-23 15:41 1772
	}
1d2e2129 sago007 2015-12-23 15:41 1773
	else {
1d2e2129 sago007 2015-12-23 15:41 1774
		newclip = box;
1d2e2129 sago007 2015-12-23 15:41 1775
	}
1d2e2129 sago007 2015-12-23 15:41 1776
	set_clip(dest, &newclip);
1d2e2129 sago007 2015-12-23 15:41 1777
1d2e2129 sago007 2015-12-23 15:41 1778
	set_color_for_all_caches(font, font->default_color);
1d2e2129 sago007 2015-12-23 15:41 1779
1d2e2129 sago007 2015-12-23 15:41 1780
	FC_DrawColumnFromBuffer(font, dest, box, NULL, scale, FC_ALIGN_LEFT);
1d2e2129 sago007 2015-12-23 15:41 1781
1d2e2129 sago007 2015-12-23 15:41 1782
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1783
		set_clip(dest, &oldclip);
1d2e2129 sago007 2015-12-23 15:41 1784
	}
1d2e2129 sago007 2015-12-23 15:41 1785
	else {
1d2e2129 sago007 2015-12-23 15:41 1786
		set_clip(dest, NULL);
1d2e2129 sago007 2015-12-23 15:41 1787
	}
1d2e2129 sago007 2015-12-23 15:41 1788
1d2e2129 sago007 2015-12-23 15:41 1789
	return box;
078900fe sago007 2015-12-05 15:31 1790
}
078900fe sago007 2015-12-05 15:31 1791
1d2e2129 sago007 2015-12-23 15:41 1792
FC_Rect FC_DrawBoxColor(FC_Font* font, FC_Target* dest, FC_Rect box, SDL_Color color, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1793
	Uint8 useClip;
1d2e2129 sago007 2015-12-23 15:41 1794
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1795
		return FC_MakeRect(box.x, box.y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1796
	}
078900fe sago007 2015-12-05 15:31 1797
1d2e2129 sago007 2015-12-23 15:41 1798
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
078900fe sago007 2015-12-05 15:31 1799
1d2e2129 sago007 2015-12-23 15:41 1800
	useClip = has_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1801
	FC_Rect oldclip, newclip;
1d2e2129 sago007 2015-12-23 15:41 1802
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1803
		oldclip = get_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1804
		newclip = FC_RectIntersect(oldclip, box);
1d2e2129 sago007 2015-12-23 15:41 1805
	}
1d2e2129 sago007 2015-12-23 15:41 1806
	else {
1d2e2129 sago007 2015-12-23 15:41 1807
		newclip = box;
1d2e2129 sago007 2015-12-23 15:41 1808
	}
1d2e2129 sago007 2015-12-23 15:41 1809
	set_clip(dest, &newclip);
1d2e2129 sago007 2015-12-23 15:41 1810
1d2e2129 sago007 2015-12-23 15:41 1811
	set_color_for_all_caches(font, color);
1d2e2129 sago007 2015-12-23 15:41 1812
1d2e2129 sago007 2015-12-23 15:41 1813
	FC_DrawColumnFromBuffer(font, dest, box, NULL, FC_MakeScale(1,1), FC_ALIGN_LEFT);
1d2e2129 sago007 2015-12-23 15:41 1814
1d2e2129 sago007 2015-12-23 15:41 1815
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1816
		set_clip(dest, &oldclip);
1d2e2129 sago007 2015-12-23 15:41 1817
	}
1d2e2129 sago007 2015-12-23 15:41 1818
	else {
1d2e2129 sago007 2015-12-23 15:41 1819
		set_clip(dest, NULL);
1d2e2129 sago007 2015-12-23 15:41 1820
	}
1d2e2129 sago007 2015-12-23 15:41 1821
1d2e2129 sago007 2015-12-23 15:41 1822
	return box;
078900fe sago007 2015-12-05 15:31 1823
}
078900fe sago007 2015-12-05 15:31 1824
1d2e2129 sago007 2015-12-23 15:41 1825
FC_Rect FC_DrawBoxEffect(FC_Font* font, FC_Target* dest, FC_Rect box, FC_Effect effect, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1826
	Uint8 useClip;
1d2e2129 sago007 2015-12-23 15:41 1827
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1828
		return FC_MakeRect(box.x, box.y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1829
	}
1d2e2129 sago007 2015-12-23 15:41 1830
1d2e2129 sago007 2015-12-23 15:41 1831
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 1832
1d2e2129 sago007 2015-12-23 15:41 1833
	useClip = has_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1834
	FC_Rect oldclip, newclip;
1d2e2129 sago007 2015-12-23 15:41 1835
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1836
		oldclip = get_clip(dest);
1d2e2129 sago007 2015-12-23 15:41 1837
		newclip = FC_RectIntersect(oldclip, box);
1d2e2129 sago007 2015-12-23 15:41 1838
	}
1d2e2129 sago007 2015-12-23 15:41 1839
	else {
1d2e2129 sago007 2015-12-23 15:41 1840
		newclip = box;
1d2e2129 sago007 2015-12-23 15:41 1841
	}
1d2e2129 sago007 2015-12-23 15:41 1842
	set_clip(dest, &newclip);
1d2e2129 sago007 2015-12-23 15:41 1843
1d2e2129 sago007 2015-12-23 15:41 1844
	set_color_for_all_caches(font, effect.color);
1d2e2129 sago007 2015-12-23 15:41 1845
1d2e2129 sago007 2015-12-23 15:41 1846
	FC_DrawColumnFromBuffer(font, dest, box, NULL, effect.scale, effect.alignment);
1d2e2129 sago007 2015-12-23 15:41 1847
1d2e2129 sago007 2015-12-23 15:41 1848
	if (useClip) {
1d2e2129 sago007 2015-12-23 15:41 1849
		set_clip(dest, &oldclip);
1d2e2129 sago007 2015-12-23 15:41 1850
	}
1d2e2129 sago007 2015-12-23 15:41 1851
	else {
1d2e2129 sago007 2015-12-23 15:41 1852
		set_clip(dest, NULL);
1d2e2129 sago007 2015-12-23 15:41 1853
	}
1d2e2129 sago007 2015-12-23 15:41 1854
1d2e2129 sago007 2015-12-23 15:41 1855
	return box;
078900fe sago007 2015-12-05 15:31 1856
}
078900fe sago007 2015-12-05 15:31 1857
1d2e2129 sago007 2015-12-23 15:41 1858
FC_Rect FC_DrawColumn(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1859
	FC_Rect box = {x, y, width, 0};
1d2e2129 sago007 2015-12-23 15:41 1860
	int total_height;
1d2e2129 sago007 2015-12-23 15:41 1861
1d2e2129 sago007 2015-12-23 15:41 1862
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1863
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1864
	}
1d2e2129 sago007 2015-12-23 15:41 1865
1d2e2129 sago007 2015-12-23 15:41 1866
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 1867
1d2e2129 sago007 2015-12-23 15:41 1868
	set_color_for_all_caches(font, font->default_color);
078900fe sago007 2015-12-05 15:31 1869
1d2e2129 sago007 2015-12-23 15:41 1870
	FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), FC_ALIGN_LEFT);
078900fe sago007 2015-12-05 15:31 1871
1d2e2129 sago007 2015-12-23 15:41 1872
	return FC_MakeRect(box.x, box.y, width, total_height);
078900fe sago007 2015-12-05 15:31 1873
}
078900fe sago007 2015-12-05 15:31 1874
1d2e2129 sago007 2015-12-23 15:41 1875
FC_Rect FC_DrawColumnAlign(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_AlignEnum align, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1876
	FC_Rect box = {x, y, width, 0};
1d2e2129 sago007 2015-12-23 15:41 1877
	int total_height;
1d2e2129 sago007 2015-12-23 15:41 1878
1d2e2129 sago007 2015-12-23 15:41 1879
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1880
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1881
	}
1d2e2129 sago007 2015-12-23 15:41 1882
1d2e2129 sago007 2015-12-23 15:41 1883
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
078900fe sago007 2015-12-05 15:31 1884
1d2e2129 sago007 2015-12-23 15:41 1885
	set_color_for_all_caches(font, font->default_color);
078900fe sago007 2015-12-05 15:31 1886
1d2e2129 sago007 2015-12-23 15:41 1887
	switch (align) {
1d2e2129 sago007 2015-12-23 15:41 1888
	case FC_ALIGN_CENTER:
1d2e2129 sago007 2015-12-23 15:41 1889
		box.x -= width/2;
1d2e2129 sago007 2015-12-23 15:41 1890
		break;
1d2e2129 sago007 2015-12-23 15:41 1891
	case FC_ALIGN_RIGHT:
1d2e2129 sago007 2015-12-23 15:41 1892
		box.x -= width;
1d2e2129 sago007 2015-12-23 15:41 1893
		break;
1d2e2129 sago007 2015-12-23 15:41 1894
	default:
1d2e2129 sago007 2015-12-23 15:41 1895
		break;
1d2e2129 sago007 2015-12-23 15:41 1896
	}
1d2e2129 sago007 2015-12-23 15:41 1897
1d2e2129 sago007 2015-12-23 15:41 1898
	FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), align);
1d2e2129 sago007 2015-12-23 15:41 1899
1d2e2129 sago007 2015-12-23 15:41 1900
	return FC_MakeRect(box.x, box.y, width, total_height);
078900fe sago007 2015-12-05 15:31 1901
}
078900fe sago007 2015-12-05 15:31 1902
1d2e2129 sago007 2015-12-23 15:41 1903
FC_Rect FC_DrawColumnScale(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Scale scale, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1904
	FC_Rect box = {x, y, width, 0};
1d2e2129 sago007 2015-12-23 15:41 1905
	int total_height;
1d2e2129 sago007 2015-12-23 15:41 1906
1d2e2129 sago007 2015-12-23 15:41 1907
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1908
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1909
	}
1d2e2129 sago007 2015-12-23 15:41 1910
1d2e2129 sago007 2015-12-23 15:41 1911
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 1912
1d2e2129 sago007 2015-12-23 15:41 1913
	set_color_for_all_caches(font, font->default_color);
078900fe sago007 2015-12-05 15:31 1914
1d2e2129 sago007 2015-12-23 15:41 1915
	FC_DrawColumnFromBuffer(font, dest, box, &total_height, scale, FC_ALIGN_LEFT);
1d2e2129 sago007 2015-12-23 15:41 1916
1d2e2129 sago007 2015-12-23 15:41 1917
	return FC_MakeRect(box.x, box.y, width, total_height);
078900fe sago007 2015-12-05 15:31 1918
}
078900fe sago007 2015-12-05 15:31 1919
1d2e2129 sago007 2015-12-23 15:41 1920
FC_Rect FC_DrawColumnColor(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, SDL_Color color, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1921
	FC_Rect box = {x, y, width, 0};
1d2e2129 sago007 2015-12-23 15:41 1922
	int total_height;
078900fe sago007 2015-12-05 15:31 1923
1d2e2129 sago007 2015-12-23 15:41 1924
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1925
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1926
	}
078900fe sago007 2015-12-05 15:31 1927
1d2e2129 sago007 2015-12-23 15:41 1928
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
078900fe sago007 2015-12-05 15:31 1929
1d2e2129 sago007 2015-12-23 15:41 1930
	set_color_for_all_caches(font, color);
078900fe sago007 2015-12-05 15:31 1931
1d2e2129 sago007 2015-12-23 15:41 1932
	FC_DrawColumnFromBuffer(font, dest, box, &total_height, FC_MakeScale(1,1), FC_ALIGN_LEFT);
1d2e2129 sago007 2015-12-23 15:41 1933
1d2e2129 sago007 2015-12-23 15:41 1934
	return FC_MakeRect(box.x, box.y, width, total_height);
078900fe sago007 2015-12-05 15:31 1935
}
078900fe sago007 2015-12-05 15:31 1936
1d2e2129 sago007 2015-12-23 15:41 1937
FC_Rect FC_DrawColumnEffect(FC_Font* font, FC_Target* dest, float x, float y, Uint16 width, FC_Effect effect, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 1938
	FC_Rect box = {x, y, width, 0};
1d2e2129 sago007 2015-12-23 15:41 1939
	int total_height;
078900fe sago007 2015-12-05 15:31 1940
1d2e2129 sago007 2015-12-23 15:41 1941
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1942
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 1943
	}
078900fe sago007 2015-12-05 15:31 1944
1d2e2129 sago007 2015-12-23 15:41 1945
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
078900fe sago007 2015-12-05 15:31 1946
1d2e2129 sago007 2015-12-23 15:41 1947
	set_color_for_all_caches(font, effect.color);
078900fe sago007 2015-12-05 15:31 1948
1d2e2129 sago007 2015-12-23 15:41 1949
	switch (effect.alignment) {
1d2e2129 sago007 2015-12-23 15:41 1950
	case FC_ALIGN_CENTER:
1d2e2129 sago007 2015-12-23 15:41 1951
		box.x -= width/2;
1d2e2129 sago007 2015-12-23 15:41 1952
		break;
1d2e2129 sago007 2015-12-23 15:41 1953
	case FC_ALIGN_RIGHT:
1d2e2129 sago007 2015-12-23 15:41 1954
		box.x -= width;
1d2e2129 sago007 2015-12-23 15:41 1955
		break;
1d2e2129 sago007 2015-12-23 15:41 1956
	default:
1d2e2129 sago007 2015-12-23 15:41 1957
		break;
1d2e2129 sago007 2015-12-23 15:41 1958
	}
1d2e2129 sago007 2015-12-23 15:41 1959
1d2e2129 sago007 2015-12-23 15:41 1960
	FC_DrawColumnFromBuffer(font, dest, box, &total_height, effect.scale, effect.alignment);
1d2e2129 sago007 2015-12-23 15:41 1961
1d2e2129 sago007 2015-12-23 15:41 1962
	return FC_MakeRect(box.x, box.y, width, total_height);
078900fe sago007 2015-12-05 15:31 1963
}
078900fe sago007 2015-12-05 15:31 1964
1d2e2129 sago007 2015-12-23 15:41 1965
static FC_Rect FC_RenderCenter(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) {
1d2e2129 sago007 2015-12-23 15:41 1966
	FC_Rect result = {x, y, 0, 0};
1d2e2129 sago007 2015-12-23 15:41 1967
	if (text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 1968
		return result;
1d2e2129 sago007 2015-12-23 15:41 1969
	}
078900fe sago007 2015-12-05 15:31 1970
1d2e2129 sago007 2015-12-23 15:41 1971
	char* str = U8_strdup(text);
1d2e2129 sago007 2015-12-23 15:41 1972
	char* del = str;
1d2e2129 sago007 2015-12-23 15:41 1973
	char* c;
078900fe sago007 2015-12-05 15:31 1974
1d2e2129 sago007 2015-12-23 15:41 1975
	// Go through str, when you find a \n, replace it with \0 and print it
1d2e2129 sago007 2015-12-23 15:41 1976
	// then move down, back, and continue.
1d2e2129 sago007 2015-12-23 15:41 1977
	for (c = str; *c != '\0';) {
1d2e2129 sago007 2015-12-23 15:41 1978
		if (*c == '\n') {
1d2e2129 sago007 2015-12-23 15:41 1979
			*c = '\0';
1d2e2129 sago007 2015-12-23 15:41 1980
			result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str)/2.0f, y, scale, str), result);
1d2e2129 sago007 2015-12-23 15:41 1981
			*c = '\n';
1d2e2129 sago007 2015-12-23 15:41 1982
			c++;
1d2e2129 sago007 2015-12-23 15:41 1983
			str = c;
1d2e2129 sago007 2015-12-23 15:41 1984
			y += scale.y*font->height;
1d2e2129 sago007 2015-12-23 15:41 1985
		}
1d2e2129 sago007 2015-12-23 15:41 1986
		else {
1d2e2129 sago007 2015-12-23 15:41 1987
			c++;
1d2e2129 sago007 2015-12-23 15:41 1988
		}
1d2e2129 sago007 2015-12-23 15:41 1989
	}
078900fe sago007 2015-12-05 15:31 1990
1d2e2129 sago007 2015-12-23 15:41 1991
	result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str)/2.0f, y, scale, str), result);
1d2e2129 sago007 2015-12-23 15:41 1992
1d2e2129 sago007 2015-12-23 15:41 1993
	free(del);
1d2e2129 sago007 2015-12-23 15:41 1994
	return result;
078900fe sago007 2015-12-05 15:31 1995
}
078900fe sago007 2015-12-05 15:31 1996
1d2e2129 sago007 2015-12-23 15:41 1997
static FC_Rect FC_RenderRight(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* text) {
1d2e2129 sago007 2015-12-23 15:41 1998
	FC_Rect result = {x, y, 0, 0};
1d2e2129 sago007 2015-12-23 15:41 1999
	if (text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2000
		return result;
1d2e2129 sago007 2015-12-23 15:41 2001
	}
1d2e2129 sago007 2015-12-23 15:41 2002
1d2e2129 sago007 2015-12-23 15:41 2003
	char* str = U8_strdup(text);
1d2e2129 sago007 2015-12-23 15:41 2004
	char* del = str;
1d2e2129 sago007 2015-12-23 15:41 2005
	char* c;
1d2e2129 sago007 2015-12-23 15:41 2006
1d2e2129 sago007 2015-12-23 15:41 2007
	for (c = str; *c != '\0';) {
1d2e2129 sago007 2015-12-23 15:41 2008
		if (*c == '\n') {
1d2e2129 sago007 2015-12-23 15:41 2009
			*c = '\0';
1d2e2129 sago007 2015-12-23 15:41 2010
			result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str), y, scale, str), result);
1d2e2129 sago007 2015-12-23 15:41 2011
			*c = '\n';
1d2e2129 sago007 2015-12-23 15:41 2012
			c++;
1d2e2129 sago007 2015-12-23 15:41 2013
			str = c;
1d2e2129 sago007 2015-12-23 15:41 2014
			y += scale.y*font->height;
1d2e2129 sago007 2015-12-23 15:41 2015
		}
1d2e2129 sago007 2015-12-23 15:41 2016
		else {
1d2e2129 sago007 2015-12-23 15:41 2017
			c++;
1d2e2129 sago007 2015-12-23 15:41 2018
		}
1d2e2129 sago007 2015-12-23 15:41 2019
	}
1d2e2129 sago007 2015-12-23 15:41 2020
1d2e2129 sago007 2015-12-23 15:41 2021
	result = FC_RectUnion(FC_RenderLeft(font, dest, x - scale.x*FC_GetWidth(font, "%s", str), y, scale, str), result);
1d2e2129 sago007 2015-12-23 15:41 2022
1d2e2129 sago007 2015-12-23 15:41 2023
	free(del);
1d2e2129 sago007 2015-12-23 15:41 2024
	return result;
1d2e2129 sago007 2015-12-23 15:41 2025
}
1d2e2129 sago007 2015-12-23 15:41 2026
1d2e2129 sago007 2015-12-23 15:41 2027
1d2e2129 sago007 2015-12-23 15:41 2028
1d2e2129 sago007 2015-12-23 15:41 2029
FC_Rect FC_DrawScale(FC_Font* font, FC_Target* dest, float x, float y, FC_Scale scale, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2030
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2031
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 2032
	}
1d2e2129 sago007 2015-12-23 15:41 2033
1d2e2129 sago007 2015-12-23 15:41 2034
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2035
1d2e2129 sago007 2015-12-23 15:41 2036
	set_color_for_all_caches(font, font->default_color);
078900fe sago007 2015-12-05 15:31 2037
1d2e2129 sago007 2015-12-23 15:41 2038
	return FC_RenderLeft(font, dest, x, y, scale, fc_buffer);
078900fe sago007 2015-12-05 15:31 2039
}
078900fe sago007 2015-12-05 15:31 2040
1d2e2129 sago007 2015-12-23 15:41 2041
FC_Rect FC_DrawAlign(FC_Font* font, FC_Target* dest, float x, float y, FC_AlignEnum align, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2042
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2043
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 2044
	}
1d2e2129 sago007 2015-12-23 15:41 2045
1d2e2129 sago007 2015-12-23 15:41 2046
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2047
1d2e2129 sago007 2015-12-23 15:41 2048
	set_color_for_all_caches(font, font->default_color);
078900fe sago007 2015-12-05 15:31 2049
1d2e2129 sago007 2015-12-23 15:41 2050
	FC_Rect result;
1d2e2129 sago007 2015-12-23 15:41 2051
	switch (align) {
1d2e2129 sago007 2015-12-23 15:41 2052
	case FC_ALIGN_LEFT:
1d2e2129 sago007 2015-12-23 15:41 2053
		result = FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer);
1d2e2129 sago007 2015-12-23 15:41 2054
		break;
1d2e2129 sago007 2015-12-23 15:41 2055
	case FC_ALIGN_CENTER:
1d2e2129 sago007 2015-12-23 15:41 2056
		result = FC_RenderCenter(font, dest, x, y, FC_MakeScale(1,1), fc_buffer);
1d2e2129 sago007 2015-12-23 15:41 2057
		break;
1d2e2129 sago007 2015-12-23 15:41 2058
	case FC_ALIGN_RIGHT:
1d2e2129 sago007 2015-12-23 15:41 2059
		result = FC_RenderRight(font, dest, x, y, FC_MakeScale(1,1), fc_buffer);
1d2e2129 sago007 2015-12-23 15:41 2060
		break;
1d2e2129 sago007 2015-12-23 15:41 2061
	default:
1d2e2129 sago007 2015-12-23 15:41 2062
		result = FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 2063
		break;
1d2e2129 sago007 2015-12-23 15:41 2064
	}
1d2e2129 sago007 2015-12-23 15:41 2065
1d2e2129 sago007 2015-12-23 15:41 2066
	return result;
078900fe sago007 2015-12-05 15:31 2067
}
078900fe sago007 2015-12-05 15:31 2068
1d2e2129 sago007 2015-12-23 15:41 2069
FC_Rect FC_DrawColor(FC_Font* font, FC_Target* dest, float x, float y, SDL_Color color, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2070
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2071
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 2072
	}
078900fe sago007 2015-12-05 15:31 2073
1d2e2129 sago007 2015-12-23 15:41 2074
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2075
1d2e2129 sago007 2015-12-23 15:41 2076
	set_color_for_all_caches(font, color);
1d2e2129 sago007 2015-12-23 15:41 2077
1d2e2129 sago007 2015-12-23 15:41 2078
	return FC_RenderLeft(font, dest, x, y, FC_MakeScale(1,1), fc_buffer);
1d2e2129 sago007 2015-12-23 15:41 2079
}
1d2e2129 sago007 2015-12-23 15:41 2080
1d2e2129 sago007 2015-12-23 15:41 2081
1d2e2129 sago007 2015-12-23 15:41 2082
FC_Rect FC_DrawEffect(FC_Font* font, FC_Target* dest, float x, float y, FC_Effect effect, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2083
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2084
		return FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 2085
	}
1d2e2129 sago007 2015-12-23 15:41 2086
1d2e2129 sago007 2015-12-23 15:41 2087
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2088
1d2e2129 sago007 2015-12-23 15:41 2089
	set_color_for_all_caches(font, effect.color);
1d2e2129 sago007 2015-12-23 15:41 2090
1d2e2129 sago007 2015-12-23 15:41 2091
	FC_Rect result;
1d2e2129 sago007 2015-12-23 15:41 2092
	switch (effect.alignment) {
1d2e2129 sago007 2015-12-23 15:41 2093
	case FC_ALIGN_LEFT:
1d2e2129 sago007 2015-12-23 15:41 2094
		result = FC_RenderLeft(font, dest, x, y, effect.scale, fc_buffer);
1d2e2129 sago007 2015-12-23 15:41 2095
		break;
1d2e2129 sago007 2015-12-23 15:41 2096
	case FC_ALIGN_CENTER:
1d2e2129 sago007 2015-12-23 15:41 2097
		result = FC_RenderCenter(font, dest, x, y, effect.scale, fc_buffer);
1d2e2129 sago007 2015-12-23 15:41 2098
		break;
1d2e2129 sago007 2015-12-23 15:41 2099
	case FC_ALIGN_RIGHT:
1d2e2129 sago007 2015-12-23 15:41 2100
		result = FC_RenderRight(font, dest, x, y, effect.scale, fc_buffer);
1d2e2129 sago007 2015-12-23 15:41 2101
		break;
1d2e2129 sago007 2015-12-23 15:41 2102
	default:
1d2e2129 sago007 2015-12-23 15:41 2103
		result = FC_MakeRect(x, y, 0, 0);
1d2e2129 sago007 2015-12-23 15:41 2104
		break;
1d2e2129 sago007 2015-12-23 15:41 2105
	}
1d2e2129 sago007 2015-12-23 15:41 2106
1d2e2129 sago007 2015-12-23 15:41 2107
	return result;
078900fe sago007 2015-12-05 15:31 2108
}
078900fe sago007 2015-12-05 15:31 2109
078900fe sago007 2015-12-05 15:31 2110
078900fe sago007 2015-12-05 15:31 2111
078900fe sago007 2015-12-05 15:31 2112
078900fe sago007 2015-12-05 15:31 2113
// Getters
078900fe sago007 2015-12-05 15:31 2114
078900fe sago007 2015-12-05 15:31 2115
1d2e2129 sago007 2015-12-23 15:41 2116
FC_FilterEnum FC_GetFilterMode(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 2117
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2118
		return FC_FILTER_NEAREST;
1d2e2129 sago007 2015-12-23 15:41 2119
	}
1d2e2129 sago007 2015-12-23 15:41 2120
1d2e2129 sago007 2015-12-23 15:41 2121
	return font->filter;
078900fe sago007 2015-12-05 15:31 2122
}
078900fe sago007 2015-12-05 15:31 2123
1d2e2129 sago007 2015-12-23 15:41 2124
Uint16 FC_GetLineHeight(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 2125
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2126
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2127
	}
1d2e2129 sago007 2015-12-23 15:41 2128
1d2e2129 sago007 2015-12-23 15:41 2129
	return font->height;
078900fe sago007 2015-12-05 15:31 2130
}
078900fe sago007 2015-12-05 15:31 2131
1d2e2129 sago007 2015-12-23 15:41 2132
Uint16 FC_GetHeight(FC_Font* font, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2133
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2134
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2135
	}
078900fe sago007 2015-12-05 15:31 2136
1d2e2129 sago007 2015-12-23 15:41 2137
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
078900fe sago007 2015-12-05 15:31 2138
1d2e2129 sago007 2015-12-23 15:41 2139
	Uint16 numLines = 1;
1d2e2129 sago007 2015-12-23 15:41 2140
	const char* c;
078900fe sago007 2015-12-05 15:31 2141
1d2e2129 sago007 2015-12-23 15:41 2142
	for (c = fc_buffer; *c != '\0'; c++) {
1d2e2129 sago007 2015-12-23 15:41 2143
		if (*c == '\n') {
1d2e2129 sago007 2015-12-23 15:41 2144
			numLines++;
1d2e2129 sago007 2015-12-23 15:41 2145
		}
1d2e2129 sago007 2015-12-23 15:41 2146
	}
1d2e2129 sago007 2015-12-23 15:41 2147
1d2e2129 sago007 2015-12-23 15:41 2148
	//   Actual height of letter region + line spacing
1d2e2129 sago007 2015-12-23 15:41 2149
	return font->height*numLines + font->lineSpacing*(numLines - 1);  //height*numLines;
078900fe sago007 2015-12-05 15:31 2150
}
078900fe sago007 2015-12-05 15:31 2151
1d2e2129 sago007 2015-12-23 15:41 2152
Uint16 FC_GetWidth(FC_Font* font, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2153
	if (formatted_text == NULL || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2154
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2155
	}
078900fe sago007 2015-12-05 15:31 2156
1d2e2129 sago007 2015-12-23 15:41 2157
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
078900fe sago007 2015-12-05 15:31 2158
1d2e2129 sago007 2015-12-23 15:41 2159
	const char* c;
1d2e2129 sago007 2015-12-23 15:41 2160
	Uint16 width = 0;
1d2e2129 sago007 2015-12-23 15:41 2161
	Uint16 bigWidth = 0;  // Allows for multi-line strings
078900fe sago007 2015-12-05 15:31 2162
1d2e2129 sago007 2015-12-23 15:41 2163
	for (c = fc_buffer; *c != '\0'; c++) {
1d2e2129 sago007 2015-12-23 15:41 2164
		if (*c == '\n') {
1d2e2129 sago007 2015-12-23 15:41 2165
			bigWidth = bigWidth >= width? bigWidth : width;
1d2e2129 sago007 2015-12-23 15:41 2166
			width = 0;
1d2e2129 sago007 2015-12-23 15:41 2167
			continue;
1d2e2129 sago007 2015-12-23 15:41 2168
		}
078900fe sago007 2015-12-05 15:31 2169
1d2e2129 sago007 2015-12-23 15:41 2170
		FC_GlyphData glyph;
1d2e2129 sago007 2015-12-23 15:41 2171
		Uint32 codepoint = FC_GetCodepointFromUTF8(&c, 1);
1d2e2129 sago007 2015-12-23 15:41 2172
		if (FC_GetGlyphData(font, &glyph, codepoint) || FC_GetGlyphData(font, &glyph, ' ')) {
1d2e2129 sago007 2015-12-23 15:41 2173
			width += glyph.rect.w;
1d2e2129 sago007 2015-12-23 15:41 2174
		}
1d2e2129 sago007 2015-12-23 15:41 2175
	}
1d2e2129 sago007 2015-12-23 15:41 2176
	bigWidth = bigWidth >= width? bigWidth : width;
1d2e2129 sago007 2015-12-23 15:41 2177
1d2e2129 sago007 2015-12-23 15:41 2178
	return bigWidth;
078900fe sago007 2015-12-05 15:31 2179
}
078900fe sago007 2015-12-05 15:31 2180
078900fe sago007 2015-12-05 15:31 2181
// If width == -1, use no width limit
1d2e2129 sago007 2015-12-23 15:41 2182
FC_Rect FC_GetCharacterOffset(FC_Font* font, Uint16 position_index, int column_width, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2183
	FC_Rect result = {0, 0, 1, FC_GetLineHeight(font)};
1d2e2129 sago007 2015-12-23 15:41 2184
	FC_StringList* ls, *iter;
1d2e2129 sago007 2015-12-23 15:41 2185
	int num_lines = 0;
1d2e2129 sago007 2015-12-23 15:41 2186
	Uint8 done = 0;
1d2e2129 sago007 2015-12-23 15:41 2187
1d2e2129 sago007 2015-12-23 15:41 2188
	if (formatted_text == NULL || column_width == 0 || position_index == 0 || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2189
		return result;
1d2e2129 sago007 2015-12-23 15:41 2190
	}
1d2e2129 sago007 2015-12-23 15:41 2191
1d2e2129 sago007 2015-12-23 15:41 2192
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2193
1d2e2129 sago007 2015-12-23 15:41 2194
	ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1);
1d2e2129 sago007 2015-12-23 15:41 2195
	for (iter = ls; iter != NULL; iter = iter->next) {
1d2e2129 sago007 2015-12-23 15:41 2196
		char* line;
1d2e2129 sago007 2015-12-23 15:41 2197
		int i = 0;
1d2e2129 sago007 2015-12-23 15:41 2198
1d2e2129 sago007 2015-12-23 15:41 2199
		++num_lines;
1d2e2129 sago007 2015-12-23 15:41 2200
		for (line = iter->value; line != NULL && *line != '\0'; line = (char*)U8_next(line)) {
1d2e2129 sago007 2015-12-23 15:41 2201
			++i;
1d2e2129 sago007 2015-12-23 15:41 2202
			--position_index;
1d2e2129 sago007 2015-12-23 15:41 2203
			if (position_index == 0) {
1d2e2129 sago007 2015-12-23 15:41 2204
				// FIXME: Doesn't handle box-wrapped newlines correctly
1d2e2129 sago007 2015-12-23 15:41 2205
				line = (char*)U8_next(line);
1d2e2129 sago007 2015-12-23 15:41 2206
				line[0] = '\0';
1d2e2129 sago007 2015-12-23 15:41 2207
				result.x = FC_GetWidth(font, "%s", iter->value);
1d2e2129 sago007 2015-12-23 15:41 2208
				done = 1;
1d2e2129 sago007 2015-12-23 15:41 2209
				break;
1d2e2129 sago007 2015-12-23 15:41 2210
			}
1d2e2129 sago007 2015-12-23 15:41 2211
		}
1d2e2129 sago007 2015-12-23 15:41 2212
		if (done) {
1d2e2129 sago007 2015-12-23 15:41 2213
			break;
1d2e2129 sago007 2015-12-23 15:41 2214
		}
1d2e2129 sago007 2015-12-23 15:41 2215
	}
1d2e2129 sago007 2015-12-23 15:41 2216
	FC_StringListFree(ls);
1d2e2129 sago007 2015-12-23 15:41 2217
1d2e2129 sago007 2015-12-23 15:41 2218
	if (num_lines > 0) {
1d2e2129 sago007 2015-12-23 15:41 2219
		result.y = (num_lines - 1) * FC_GetLineHeight(font);
1d2e2129 sago007 2015-12-23 15:41 2220
	}
078900fe sago007 2015-12-05 15:31 2221
1d2e2129 sago007 2015-12-23 15:41 2222
	return result;
078900fe sago007 2015-12-05 15:31 2223
}
078900fe sago007 2015-12-05 15:31 2224
078900fe sago007 2015-12-05 15:31 2225
1d2e2129 sago007 2015-12-23 15:41 2226
Uint16 FC_GetColumnHeight(FC_Font* font, Uint16 width, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2227
	int y = 0;
078900fe sago007 2015-12-05 15:31 2228
1d2e2129 sago007 2015-12-23 15:41 2229
	FC_StringList* ls, *iter;
1d2e2129 sago007 2015-12-23 15:41 2230
1d2e2129 sago007 2015-12-23 15:41 2231
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2232
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2233
	}
1d2e2129 sago007 2015-12-23 15:41 2234
1d2e2129 sago007 2015-12-23 15:41 2235
	if (formatted_text == NULL || width == 0) {
1d2e2129 sago007 2015-12-23 15:41 2236
		return font->height;
1d2e2129 sago007 2015-12-23 15:41 2237
	}
1d2e2129 sago007 2015-12-23 15:41 2238
1d2e2129 sago007 2015-12-23 15:41 2239
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2240
1d2e2129 sago007 2015-12-23 15:41 2241
	ls = FC_GetBufferFitToColumn(font, width, FC_MakeScale(1,1), 0);
1d2e2129 sago007 2015-12-23 15:41 2242
	for (iter = ls; iter != NULL; iter = iter->next) {
1d2e2129 sago007 2015-12-23 15:41 2243
		y += FC_GetLineHeight(font);
1d2e2129 sago007 2015-12-23 15:41 2244
	}
1d2e2129 sago007 2015-12-23 15:41 2245
	FC_StringListFree(ls);
1d2e2129 sago007 2015-12-23 15:41 2246
1d2e2129 sago007 2015-12-23 15:41 2247
	return y;
078900fe sago007 2015-12-05 15:31 2248
}
078900fe sago007 2015-12-05 15:31 2249
1d2e2129 sago007 2015-12-23 15:41 2250
static int FC_GetAscentFromCodepoint(FC_Font* font, Uint32 codepoint) {
1d2e2129 sago007 2015-12-23 15:41 2251
	FC_GlyphData glyph;
1d2e2129 sago007 2015-12-23 15:41 2252
1d2e2129 sago007 2015-12-23 15:41 2253
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2254
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2255
	}
1d2e2129 sago007 2015-12-23 15:41 2256
1d2e2129 sago007 2015-12-23 15:41 2257
	// FIXME: Store ascent so we can return it here
1d2e2129 sago007 2015-12-23 15:41 2258
	FC_GetGlyphData(font, &glyph, codepoint);
1d2e2129 sago007 2015-12-23 15:41 2259
	return glyph.rect.h;
078900fe sago007 2015-12-05 15:31 2260
}
078900fe sago007 2015-12-05 15:31 2261
1d2e2129 sago007 2015-12-23 15:41 2262
static int FC_GetDescentFromCodepoint(FC_Font* font, Uint32 codepoint) {
1d2e2129 sago007 2015-12-23 15:41 2263
	FC_GlyphData glyph;
1d2e2129 sago007 2015-12-23 15:41 2264
1d2e2129 sago007 2015-12-23 15:41 2265
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2266
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2267
	}
1d2e2129 sago007 2015-12-23 15:41 2268
1d2e2129 sago007 2015-12-23 15:41 2269
	// FIXME: Store descent so we can return it here
1d2e2129 sago007 2015-12-23 15:41 2270
	FC_GetGlyphData(font, &glyph, codepoint);
1d2e2129 sago007 2015-12-23 15:41 2271
	return glyph.rect.h;
078900fe sago007 2015-12-05 15:31 2272
}
078900fe sago007 2015-12-05 15:31 2273
1d2e2129 sago007 2015-12-23 15:41 2274
int FC_GetAscent(FC_Font* font, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2275
	Uint32 codepoint;
1d2e2129 sago007 2015-12-23 15:41 2276
	int max, ascent;
1d2e2129 sago007 2015-12-23 15:41 2277
	const char* c;
1d2e2129 sago007 2015-12-23 15:41 2278
1d2e2129 sago007 2015-12-23 15:41 2279
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2280
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2281
	}
1d2e2129 sago007 2015-12-23 15:41 2282
1d2e2129 sago007 2015-12-23 15:41 2283
	if (formatted_text == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2284
		return font->ascent;
1d2e2129 sago007 2015-12-23 15:41 2285
	}
1d2e2129 sago007 2015-12-23 15:41 2286
1d2e2129 sago007 2015-12-23 15:41 2287
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2288
1d2e2129 sago007 2015-12-23 15:41 2289
	max = 0;
1d2e2129 sago007 2015-12-23 15:41 2290
	c = fc_buffer;
1d2e2129 sago007 2015-12-23 15:41 2291
1d2e2129 sago007 2015-12-23 15:41 2292
	while (*c != '\0') {
1d2e2129 sago007 2015-12-23 15:41 2293
		codepoint = FC_GetCodepointFromUTF8(&c, 1);
1d2e2129 sago007 2015-12-23 15:41 2294
		if (codepoint != 0) {
1d2e2129 sago007 2015-12-23 15:41 2295
			ascent = FC_GetAscentFromCodepoint(font, codepoint);
1d2e2129 sago007 2015-12-23 15:41 2296
			if (ascent > max) {
1d2e2129 sago007 2015-12-23 15:41 2297
				max = ascent;
1d2e2129 sago007 2015-12-23 15:41 2298
			}
1d2e2129 sago007 2015-12-23 15:41 2299
		}
1d2e2129 sago007 2015-12-23 15:41 2300
		++c;
1d2e2129 sago007 2015-12-23 15:41 2301
	}
1d2e2129 sago007 2015-12-23 15:41 2302
	return max;
078900fe sago007 2015-12-05 15:31 2303
}
078900fe sago007 2015-12-05 15:31 2304
1d2e2129 sago007 2015-12-23 15:41 2305
int FC_GetDescent(FC_Font* font, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2306
	Uint32 codepoint;
1d2e2129 sago007 2015-12-23 15:41 2307
	int max, descent;
1d2e2129 sago007 2015-12-23 15:41 2308
	const char* c;
1d2e2129 sago007 2015-12-23 15:41 2309
1d2e2129 sago007 2015-12-23 15:41 2310
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2311
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2312
	}
1d2e2129 sago007 2015-12-23 15:41 2313
1d2e2129 sago007 2015-12-23 15:41 2314
	if (formatted_text == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2315
		return font->descent;
1d2e2129 sago007 2015-12-23 15:41 2316
	}
1d2e2129 sago007 2015-12-23 15:41 2317
1d2e2129 sago007 2015-12-23 15:41 2318
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2319
1d2e2129 sago007 2015-12-23 15:41 2320
	max = 0;
1d2e2129 sago007 2015-12-23 15:41 2321
	c = fc_buffer;
1d2e2129 sago007 2015-12-23 15:41 2322
1d2e2129 sago007 2015-12-23 15:41 2323
	while (*c != '\0') {
1d2e2129 sago007 2015-12-23 15:41 2324
		codepoint = FC_GetCodepointFromUTF8(&c, 1);
1d2e2129 sago007 2015-12-23 15:41 2325
		if (codepoint != 0) {
1d2e2129 sago007 2015-12-23 15:41 2326
			descent = FC_GetDescentFromCodepoint(font, codepoint);
1d2e2129 sago007 2015-12-23 15:41 2327
			if (descent > max) {
1d2e2129 sago007 2015-12-23 15:41 2328
				max = descent;
1d2e2129 sago007 2015-12-23 15:41 2329
			}
1d2e2129 sago007 2015-12-23 15:41 2330
		}
1d2e2129 sago007 2015-12-23 15:41 2331
		++c;
1d2e2129 sago007 2015-12-23 15:41 2332
	}
1d2e2129 sago007 2015-12-23 15:41 2333
	return max;
078900fe sago007 2015-12-05 15:31 2334
}
078900fe sago007 2015-12-05 15:31 2335
1d2e2129 sago007 2015-12-23 15:41 2336
int FC_GetBaseline(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 2337
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2338
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2339
	}
1d2e2129 sago007 2015-12-23 15:41 2340
1d2e2129 sago007 2015-12-23 15:41 2341
	return font->baseline;
078900fe sago007 2015-12-05 15:31 2342
}
078900fe sago007 2015-12-05 15:31 2343
1d2e2129 sago007 2015-12-23 15:41 2344
int FC_GetSpacing(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 2345
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2346
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2347
	}
1d2e2129 sago007 2015-12-23 15:41 2348
1d2e2129 sago007 2015-12-23 15:41 2349
	return font->letterSpacing;
078900fe sago007 2015-12-05 15:31 2350
}
078900fe sago007 2015-12-05 15:31 2351
1d2e2129 sago007 2015-12-23 15:41 2352
int FC_GetLineSpacing(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 2353
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2354
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2355
	}
1d2e2129 sago007 2015-12-23 15:41 2356
1d2e2129 sago007 2015-12-23 15:41 2357
	return font->lineSpacing;
078900fe sago007 2015-12-05 15:31 2358
}
078900fe sago007 2015-12-05 15:31 2359
1d2e2129 sago007 2015-12-23 15:41 2360
Uint16 FC_GetMaxWidth(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 2361
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2362
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2363
	}
1d2e2129 sago007 2015-12-23 15:41 2364
1d2e2129 sago007 2015-12-23 15:41 2365
	return font->maxWidth;
078900fe sago007 2015-12-05 15:31 2366
}
078900fe sago007 2015-12-05 15:31 2367
1d2e2129 sago007 2015-12-23 15:41 2368
SDL_Color FC_GetDefaultColor(FC_Font* font) {
1d2e2129 sago007 2015-12-23 15:41 2369
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2370
		SDL_Color c = {0,0,0,255};
1d2e2129 sago007 2015-12-23 15:41 2371
		return c;
1d2e2129 sago007 2015-12-23 15:41 2372
	}
1d2e2129 sago007 2015-12-23 15:41 2373
1d2e2129 sago007 2015-12-23 15:41 2374
	return font->default_color;
078900fe sago007 2015-12-05 15:31 2375
}
078900fe sago007 2015-12-05 15:31 2376
078900fe sago007 2015-12-05 15:31 2377
1d2e2129 sago007 2015-12-23 15:41 2378
Uint8 FC_InRect(float x, float y, FC_Rect input_rect) {
1d2e2129 sago007 2015-12-23 15:41 2379
	return (input_rect.x <= x && x <= input_rect.x + input_rect.w && input_rect.y <= y && y <= input_rect.y + input_rect.h);
078900fe sago007 2015-12-05 15:31 2380
}
078900fe sago007 2015-12-05 15:31 2381
078900fe sago007 2015-12-05 15:31 2382
// TODO: Make it work with alignment
1d2e2129 sago007 2015-12-23 15:41 2383
Uint16 FC_GetPositionFromOffset(FC_Font* font, float x, float y, int column_width, FC_AlignEnum align, const char* formatted_text, ...) {
1d2e2129 sago007 2015-12-23 15:41 2384
	FC_StringList* ls, *iter;
1d2e2129 sago007 2015-12-23 15:41 2385
	Uint8 done = 0;
1d2e2129 sago007 2015-12-23 15:41 2386
	int height = FC_GetLineHeight(font);
1d2e2129 sago007 2015-12-23 15:41 2387
	Uint16 position = 0;
1d2e2129 sago007 2015-12-23 15:41 2388
	int current_x = 0;
1d2e2129 sago007 2015-12-23 15:41 2389
	int current_y = 0;
1d2e2129 sago007 2015-12-23 15:41 2390
	FC_GlyphData glyph_data;
1d2e2129 sago007 2015-12-23 15:41 2391
1d2e2129 sago007 2015-12-23 15:41 2392
	if (formatted_text == NULL || column_width == 0 || font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2393
		return 0;
1d2e2129 sago007 2015-12-23 15:41 2394
	}
078900fe sago007 2015-12-05 15:31 2395
1d2e2129 sago007 2015-12-23 15:41 2396
	FC_EXTRACT_VARARGS(fc_buffer, formatted_text);
1d2e2129 sago007 2015-12-23 15:41 2397
1d2e2129 sago007 2015-12-23 15:41 2398
	ls = FC_GetBufferFitToColumn(font, column_width, FC_MakeScale(1,1), 1);
1d2e2129 sago007 2015-12-23 15:41 2399
	for (iter = ls; iter != NULL; iter = iter->next) {
1d2e2129 sago007 2015-12-23 15:41 2400
		char* line;
1d2e2129 sago007 2015-12-23 15:41 2401
1d2e2129 sago007 2015-12-23 15:41 2402
		for (line = iter->value; line != NULL && *line != '\0'; line = (char*)U8_next(line)) {
1d2e2129 sago007 2015-12-23 15:41 2403
			if (FC_GetGlyphData(font, &glyph_data, FC_GetCodepointFromUTF8((const char**)&line, 0))) {
1d2e2129 sago007 2015-12-23 15:41 2404
				if (FC_InRect(x, y, FC_MakeRect(current_x, current_y, glyph_data.rect.w, glyph_data.rect.h))) {
1d2e2129 sago007 2015-12-23 15:41 2405
					done = 1;
1d2e2129 sago007 2015-12-23 15:41 2406
					break;
1d2e2129 sago007 2015-12-23 15:41 2407
				}
1d2e2129 sago007 2015-12-23 15:41 2408
1d2e2129 sago007 2015-12-23 15:41 2409
				current_x += glyph_data.rect.w;
1d2e2129 sago007 2015-12-23 15:41 2410
			}
1d2e2129 sago007 2015-12-23 15:41 2411
			position++;
1d2e2129 sago007 2015-12-23 15:41 2412
		}
1d2e2129 sago007 2015-12-23 15:41 2413
		if (done) {
1d2e2129 sago007 2015-12-23 15:41 2414
			break;
1d2e2129 sago007 2015-12-23 15:41 2415
		}
1d2e2129 sago007 2015-12-23 15:41 2416
1d2e2129 sago007 2015-12-23 15:41 2417
		current_x = 0;
1d2e2129 sago007 2015-12-23 15:41 2418
		current_y += height;
1d2e2129 sago007 2015-12-23 15:41 2419
		if (y < current_y) {
1d2e2129 sago007 2015-12-23 15:41 2420
			break;
1d2e2129 sago007 2015-12-23 15:41 2421
		}
1d2e2129 sago007 2015-12-23 15:41 2422
	}
1d2e2129 sago007 2015-12-23 15:41 2423
	FC_StringListFree(ls);
1d2e2129 sago007 2015-12-23 15:41 2424
1d2e2129 sago007 2015-12-23 15:41 2425
	return position;
078900fe sago007 2015-12-05 15:31 2426
}
078900fe sago007 2015-12-05 15:31 2427
078900fe sago007 2015-12-05 15:31 2428
078900fe sago007 2015-12-05 15:31 2429
078900fe sago007 2015-12-05 15:31 2430
078900fe sago007 2015-12-05 15:31 2431
// Setters
078900fe sago007 2015-12-05 15:31 2432
078900fe sago007 2015-12-05 15:31 2433
1d2e2129 sago007 2015-12-23 15:41 2434
void FC_SetFilterMode(FC_Font* font, FC_FilterEnum filter) {
1d2e2129 sago007 2015-12-23 15:41 2435
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2436
		return;
1d2e2129 sago007 2015-12-23 15:41 2437
	}
1d2e2129 sago007 2015-12-23 15:41 2438
1d2e2129 sago007 2015-12-23 15:41 2439
	if (font->filter != filter) {
1d2e2129 sago007 2015-12-23 15:41 2440
		font->filter = filter;
1d2e2129 sago007 2015-12-23 15:41 2441
1d2e2129 sago007 2015-12-23 15:41 2442
#ifdef FC_USE_SDL_GPU
1d2e2129 sago007 2015-12-23 15:41 2443
		// Update each texture to use this filter mode
1d2e2129 sago007 2015-12-23 15:41 2444
		{
1d2e2129 sago007 2015-12-23 15:41 2445
			int i;
1d2e2129 sago007 2015-12-23 15:41 2446
			GPU_FilterEnum gpu_filter = GPU_FILTER_NEAREST;
1d2e2129 sago007 2015-12-23 15:41 2447
			if (FC_GetFilterMode(font) == FC_FILTER_LINEAR) {
1d2e2129 sago007 2015-12-23 15:41 2448
				gpu_filter = GPU_FILTER_LINEAR;
1d2e2129 sago007 2015-12-23 15:41 2449
			}
1d2e2129 sago007 2015-12-23 15:41 2450
1d2e2129 sago007 2015-12-23 15:41 2451
			for (i = 0; i < font->glyph_cache_count; ++i) {
1d2e2129 sago007 2015-12-23 15:41 2452
				GPU_SetImageFilter(font->glyph_cache[i], gpu_filter);
1d2e2129 sago007 2015-12-23 15:41 2453
			}
1d2e2129 sago007 2015-12-23 15:41 2454
		}
1d2e2129 sago007 2015-12-23 15:41 2455
#endif
1d2e2129 sago007 2015-12-23 15:41 2456
	}
078900fe sago007 2015-12-05 15:31 2457
}
078900fe sago007 2015-12-05 15:31 2458
078900fe sago007 2015-12-05 15:31 2459
1d2e2129 sago007 2015-12-23 15:41 2460
void FC_SetSpacing(FC_Font* font, int LetterSpacing) {
1d2e2129 sago007 2015-12-23 15:41 2461
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2462
		return;
1d2e2129 sago007 2015-12-23 15:41 2463
	}
1d2e2129 sago007 2015-12-23 15:41 2464
1d2e2129 sago007 2015-12-23 15:41 2465
	font->letterSpacing = LetterSpacing;
078900fe sago007 2015-12-05 15:31 2466
}
078900fe sago007 2015-12-05 15:31 2467
1d2e2129 sago007 2015-12-23 15:41 2468
void FC_SetLineSpacing(FC_Font* font, int LineSpacing) {
1d2e2129 sago007 2015-12-23 15:41 2469
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2470
		return;
1d2e2129 sago007 2015-12-23 15:41 2471
	}
1d2e2129 sago007 2015-12-23 15:41 2472
1d2e2129 sago007 2015-12-23 15:41 2473
	font->lineSpacing = LineSpacing;
078900fe sago007 2015-12-05 15:31 2474
}
078900fe sago007 2015-12-05 15:31 2475
1d2e2129 sago007 2015-12-23 15:41 2476
void FC_SetDefaultColor(FC_Font* font, SDL_Color color) {
1d2e2129 sago007 2015-12-23 15:41 2477
	if (font == NULL) {
1d2e2129 sago007 2015-12-23 15:41 2478
		return;
1d2e2129 sago007 2015-12-23 15:41 2479
	}
1d2e2129 sago007 2015-12-23 15:41 2480
1d2e2129 sago007 2015-12-23 15:41 2481
	font->default_color = color;
078900fe sago007 2015-12-05 15:31 2482
}
078900fe sago007 2015-12-05 15:31 2483
078900fe sago007 2015-12-05 15:31 2484
078900fe sago007 2015-12-05 15:31 2485
078900fe sago007 2015-12-05 15:31 2486
078900fe sago007 2015-12-05 15:31 2487
078900fe sago007 2015-12-05 15:31 2488
1970-01-01 00:00 2489