git repos / blockattack-game

blame: source/code/Libs/SDL_FontCache.c

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