git repos / blockattack-game

blame: source/code/Libs/SDL_FontCache.c

normal view · raw

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