git repos / blockattack-game

blame: source/code/Libs/SDL_FontCache.c

normal view · raw

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