/* font-glyphkeeper.m,
 *
 * TTF support using Glyph Keeper.
 */

#include <assert.h>
#include "font-glyphkeeper.h"
#include "seborrhea-debug.h"


@implementation SebFontGlyphKeeper
- free
{
    if (face) {
	gk_unload_face(face);
	face = NULL;
    }

    if (rend) {
	gk_done_renderer(rend);
	rend = NULL;
    }

    if (keep) {
	gk_done_keeper(keep);
	keep = NULL;
    }

    if (font_data) {
	free(font_data);
	font_data = NULL;
    }

    return [super free];
}

- (BOOL) createKeeper
{
    assert(not keep);

    /* 256*1024 = 256K, which is plenty. */
    keep = gk_create_keeper(0, 256*1024);
    if (keep) {
	return YES;
    }
    else {
	fprintf(stderr, "[SebFontGlyphKeeper] Error creating keeper.\n");
	return NO;
    }    
}

- (BOOL) createRenderer
{
    assert(not rend);

    rend = gk_create_renderer(face, keep);
    if (rend) {
	return YES;
    }
    else {
	fprintf(stderr, "[SebFontGlyphKeeper] Error creating renderer.\n");
	return NO;
    }
}

- (BOOL) loadFromFile:(const char *)filename
{
    assert(filename);
    assert(not face);

    face = gk_load_face_from_file(filename, 0);
    if (not face) {
	fprintf(stderr, "[SebFontGlyphKeeper] Error loading face from file (%s).\n", filename);
	return NO;
    }

    if (not [self createKeeper] ||
	not [self createRenderer])
	return NO;

    SEBORRHEA_MESSAGE(stdout, "[SebFontGlyphKeeper] %s has %d glyphs, %d characters\n", [self name],
		      gk_face_number_of_glyphs(face), gk_face_number_of_characters(face));

    return YES;
}

- (BOOL) loadFromMemory:(void *)buffer :(int)buffer_size
{
    assert(buffer);
    assert(not face);

    face = gk_load_face_from_memory(buffer, buffer_size, 0);
    if (not face) {
	fprintf(stderr, "[SebFontGlyphKeeper] Error loading face from memory.\n");
	return NO;
    }

    if (not [self createKeeper] ||
	not [self createRenderer])
	return NO;

    SEBORRHEA_MESSAGE(stdout, "[SebFontGlyphKeeper] %s has %d glyphs, %d characters\n", [self name],
		      gk_face_number_of_glyphs(face), gk_face_number_of_characters(face));

    font_data = buffer;

    return YES;
}

- (BOOL) setFontSize:(int)size
{
    assert(rend);
    assert(allow_resize);

    if (gk_rend_set_size_pixels(rend, size, size))
	return YES;
    else
	return NO;
}

	/* Dimensions. */
- (unsigned int) textHeight
{
    assert(rend);
    return gk_rend_height_pixels(rend);
}

- (unsigned int) textLength:(const char *)str
{
    assert(rend);
    return gk_text_width_utf8(rend, str);
}

	/* Simple output routines. */
- (void) putChar:(unsigned int)ch To:(void *)dest X:(int)x Y:(int)y Colour:(int)r :(int)g :(int)b
{
    GLYPH_TARGET_SURFACE *bmp = dest;
    assert(bmp && rend);

    y += gk_rend_height_pixels(rend) - gk_rend_ascender_pixels(rend);
    gk_rend_set_text_color_rgb(rend, r, g, b);
    gk_put_char(bmp, rend, ch, x, y);
}

- (void) putString:(const char *)str To:(void *)dest X:(int)x Y:(int) y Colour:(int)r :(int)g :(int)b
{
    GLYPH_TARGET_SURFACE *bmp = dest;
    assert(bmp && rend);

    /* Glyph Keeper aligns things from the bottom, which I don't like,
       so there. */
    y += gk_rend_ascender_pixels(rend);

    gk_rend_set_text_color_rgb(rend, r, g, b);
    gk_render_line_utf8(bmp, rend, str, x, y);

    /* printf("[%s:%s] %d\n", [[self class] name], [self name], keeper_byte_count(keep)); */
}
@end

/*--------------------------------------------------------------*/

BOOL sebfont_glyphkeeper_init(void)
{
    return seborrhea_font_init([SebFontGlyphKeeper class]);
}

void sebfont_glyphkeeper_shutdown(void)
{
    seborrhea_font_shutdown();
}
